diff --git a/.gitignore b/.gitignore index 19d3b331..252219c3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,38 @@ +# Directories to ignore +bin +Debug +Release +/NetService/src/test/testRunner +/Client/CppTest -/NetService/Debug -/NetService/bin -/vnoc/Debug -/C:/Users/tengda/Documents/GitHub/vnoc/VNOC/VNOC.sdf -/VNOC/VNOC.sdf -/netservice/Debug -/netservice/Release \ No newline at end of file +# Files to ignore +*.sdf +*.obj +*.tlog +*.user +*.log +*.res +*.pch +*.lastbuildstate +*.idb +*.ipch +*.suo +*.pdb +*.manifest +*.opensdf +*.cache +*.lib +*.o +*.aps +*.unsuccessfulbuild +tags +cpptestresults.xml + +!libmysql.lib +!mysqlclient.lib + +/NetService/libmysql.dll +/NetService/NetService.zip +/NetService/server.exe +/NetService/.project +/NetService/.cproject diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..6b6355eb --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "NetService/dependencies/libmysql"] + path = NetService/dependencies/libmysql + url = git://github.com/Tydus/libmysql diff --git a/Client/Client/Client.vcxproj b/Client/Client/Client.vcxproj new file mode 100644 index 00000000..55634362 --- /dev/null +++ b/Client/Client/Client.vcxproj @@ -0,0 +1,329 @@ + + + + + CppTest + Win32 + + + Debug + Win32 + + + Release + Win32 + + + + {8E8644B5-86CF-4286-9276-8710E6EE974C} + Win32Proj + Client + + + + Application + true + v110 + Unicode + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + + + + true + include;../../ThirdLibs;$(IncludePath); + ../../ThirdLibs;$(LibraryPath) + ../Temp/ + + + true + include;..\..\cppunit-1.12.1\include;../../ThirdLibs;$(IncludePath) + ..\..\cppunit-1.12.1\lib;../../ThirdLibs;$(LibraryPath) + ../Temp/ + + + false + include;../../ThirdLibs;$(IncludePath) + ../../ThirdLibs;$(LibraryPath) + ../Temp/ + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + + + + + + + postDispatch.bat $(Configuration) $(Platform) + + + prelink.bat $(Configuration) $(Platform) + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;CPPTEST;CONSOLE;%(PreprocessorDefinitions) + + + Console + true + cppunitd.lib;%(AdditionalDependencies) + + + + + + + postDispatch.bat $(Configuration) $(Platform) + + + prelink.bat $(Configuration) $(Platform) + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + true + true + + + + + + + postDispatch.bat $(Configuration) $(Platform) + + + prelink.bat $(Configuration) $(Platform) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Client/Client/Client.vcxproj.filters b/Client/Client/Client.vcxproj.filters new file mode 100644 index 00000000..33966720 --- /dev/null +++ b/Client/Client/Client.vcxproj.filters @@ -0,0 +1,604 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {d0789c3a-68a6-4c02-a7e6-d94306dde427} + + + {ee804ca1-3800-4eb0-9a6c-211e434327a1} + + + {9e05fbaf-f4de-42fa-80d0-60c1306a4391} + + + {aa9e61af-0ed6-4e9d-9162-c9c2905669be} + + + {1f0044bc-9b7a-4c6f-9437-72aec3e2dd27} + + + {90bc5d2c-09b6-44e9-9ee8-0cfd76455bee} + + + {42bbda5d-e16c-4491-83db-975d02aeac2a} + + + {c8315cb1-8874-40b5-8ce8-8613e0e9c98b} + + + {fc85c714-2cb6-4c08-8c01-5db94e706643} + + + {cdc4c050-f912-4fad-8f7f-630dd0450988} + + + {5c89666e-35a4-49e0-81ae-f16bcf0a90ca} + + + {61949cca-7673-4e66-b8dc-001242bd142b} + + + {902b6711-eb72-4a08-96d3-f4f28892bd9b} + + + {d5ace8d4-93aa-4c84-a4fb-0e143fb8b252} + + + {2c1f7fac-6a46-4a9a-b8a8-b847694279af} + + + {564098b2-c8f6-4da3-a462-67c4223103ca} + + + {6f0b0f68-94bf-405b-9db6-5a1b587429a4} + + + {8f1ea992-fb89-4064-ae19-55c353722fe3} + + + {77586023-2e26-4c4b-936f-e4e0ef6341c5} + + + {75a3ef47-05a4-453f-9af2-822a9b0fe9e4} + + + {419fb8d3-fb14-43bb-9e57-07ada4a5de08} + + + {6bf85c6f-0f5b-4813-a78a-f17a43f45725} + + + {45e50712-9fac-4731-a388-90a224ccdb1a} + + + {331cbf62-e92c-4964-8105-34a937d88b39} + + + + + FrameWork + + + FrameWork + + + FrameWork + + + FrameWork + + + FrameWork + + + FrameWork + + + FrameWork + + + Util\Public + + + Util\Public + + + Util\Public + + + Util\Public + + + Util\Public + + + Util\Public + + + Util\Public + + + Util\Public + + + Util\Public + + + Util\Public + + + Util\Public + + + Util\Public + + + Config + + + Config + + + Config + + + Net + + + Net + + + Net\Socket + + + Net\Socket + + + Net\Socket + + + Net\Socket + + + Net\Socket + + + Config\TinyXML + + + Config\TinyXML + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Net\Message + + + Logic\room + + + Logic\room + + + Logic\room + + + Logic\users + + + Logic\users + + + Logic\users + + + UI\BKWin\Login + + + UI\BKWin\RoomList + + + UI\BKWin\Room + + + Include + + + Include + + + Include + + + Include + + + Include + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + UI\BKWin\BKWin + + + FrameWork + + + CppTest + + + CppTest + + + Net\NMessage\Message + + + Net\NMessage\Message + + + Net\NMessage\Message + + + Net\NMessage\Message + + + Net\NMessage\Message + + + Net\NMessage\Message + + + Net\NMessage\Message + + + Net\NMessage\Message + + + Net\NMessage\MsgDataValue + + + Net\NMessage\MsgDataValue + + + Net\NMessage\MsgDataValue + + + Net\NMessage\Message + + + Net\NMessage\MsgDataValue + + + Net\NMessage\MsgDataValue + + + Net\NMessage\Message + + + Net\NMessage\Message\Produce + + + Net\NMessage\Message\Produce + + + Net\NMessage\Message\Produce + + + Net\NMessage\Message\Produce + + + Net\NMessage\Message\Produce + + + Net\NMessage\Message\Produce + + + Net\NMessage\Message\Produce + + + Net\NMessage\Message\Produce + + + Net\NMessage\Message\Produce + + + Net\NMessage\Message\Produce + + + Net\NMessage\Message\Produce + + + Net\NMessage\Message\Produce + + + Net\NMessage\Message\Produce + + + Net\NMessage\Message\Produce + + + + + FrameWork + + + FrameWork + + + FrameWork + + + FrameWork + + + Util\Public + + + Util\Public + + + Util\Public + + + Util\Public + + + Util\Public + + + Util\Public + + + Config + + + Net + + + Net\Socket + + + Net\Socket + + + Net\Socket + + + Net\Socket + + + Config\TinyXML + + + Config\TinyXML + + + Config\TinyXML + + + Config\TinyXML + + + Net\Message + + + Net\Message + + + Net\Message + + + Logic\room + + + Logic\room + + + Logic\users + + + UI\BKWin\Login + + + UI\BKWin\RoomList + + + UI\BKWin\Room + + + UI\BKWin\BKWin + + + FrameWork + + + CppTest + + + Net\NMessage\Message + + + Net\NMessage\Message + + + Net\NMessage\Message + + + Net\NMessage\Message + + + Net\NMessage\MsgDataValue + + + Net\NMessage\MsgDataValue + + + Net\NMessage\MsgDataValue + + + Logic\room + + + Net\NMessage + + + Net\NMessage + + + Logic\users + + + Net\NMessage\Message + + + Net\NMessage\Message + + + Net\NMessage + + + + + Util\Public + + + + + Resource Files + + + Resource Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/Client/Client/CppUnitTest/MSG_Message_Test.cpp b/Client/Client/CppUnitTest/MSG_Message_Test.cpp new file mode 100644 index 00000000..bfe56baf --- /dev/null +++ b/Client/Client/CppUnitTest/MSG_Message_Test.cpp @@ -0,0 +1,517 @@ +#ifdef CPPTEST +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../NMessage/MessageUnion.h" +#include "../../NMessage/Message2Pack.h" +#include "../../NMessage/Message2Parser.h" +#include "../../NMessage/ParserMessageXML.h" +#include "../../NMessage/BufferMessage.h" + +using namespace VNOC::Message; +using namespace VNOC::Message::Define; + +CMessage2Pack g_m2pack; +CMessage2Parser g_m2parser; + +class MSG_Message_Test : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( MSG_Message_Test ); + CPPUNIT_TEST( MSG_AnswerClassInfo_Test ); + CPPUNIT_TEST( MSG_AnswerClassList_Test ); + CPPUNIT_TEST( MSG_AnswerLogin_Test ); + CPPUNIT_TEST( MSG_AnswerProfileSync_Test ); + CPPUNIT_TEST( MSG_AnswerRegister_Test ); + CPPUNIT_TEST( MSG_AnswerVerificationCode_Test ); + CPPUNIT_TEST( MSG_RequestClassInfo_Test ); + CPPUNIT_TEST( MSG_RequestClassList_Test ); + CPPUNIT_TEST( MSG_RequestLogin_Test ); + CPPUNIT_TEST( MSG_RequestProfileSync_Test ); + CPPUNIT_TEST( MSG_RequestRegister_Test ); + CPPUNIT_TEST( MSG_RequestVerificationCode_Test ); + CPPUNIT_TEST( MSG_NULL_Test ); + CPPUNIT_TEST_SUITE_END(); +public: + void setUp() + { + + } + void tearDown() + { + + } +public: + + void MSG_AnswerClassInfo_Test() + { + CBufferMessage buf; + MSG_AnswerClassInfo TMAci; + std::vector PeopListId; + TMAci.SetRoomName(""); + TMAci.SetRoomID(22); + TMAci.SetRoomManageId(12); + TMAci.SetRoomPassword("123456789"); + TMAci.SetRoomRank(10); + TMAci.SetRoomPeopleNumMax(1000); + TMAci.SetRoomType(25); + TMAci.SetRoomState(100); + PeopListId.push_back(1); + PeopListId.push_back(2); + PeopListId.push_back(3); + TMAci.SetRoomPeopleListId(PeopListId); + PeopListId.clear(); + + g_m2pack.PackMessage(&TMAci, buf); + CMessage parserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_AnswerClassInfo_Id); + g_m2parser.Parser(&parserMsg, buf); + MSG_AnswerClassInfo TParserAci(parserMsg); + + uint32 RoomId = 0; + uint32 RoomRank = 0; + uint32 RoomType = 0; + uint32 RoomState = 0; + uint32 RoomPeopleNumMax = 0; + uint32 RoomManageId = 0; + std::string strRoomName; + std::string strPassword; + + TParserAci.GetRoomName(strRoomName); + CPPUNIT_ASSERT(strRoomName == ""); + TParserAci.GetRoomID(RoomId); + CPPUNIT_ASSERT(RoomId == 22); + TParserAci.GetRoomRank(RoomRank); + CPPUNIT_ASSERT(RoomRank == 10); + TParserAci.GetRoomPeopleNumMax(RoomPeopleNumMax); + CPPUNIT_ASSERT(RoomPeopleNumMax == 1000); + TParserAci.GetRoomPassword(strPassword); + CPPUNIT_ASSERT(strPassword == "123456789"); + TParserAci.GetRoomState(RoomState); + CPPUNIT_ASSERT(RoomState == 100); + TParserAci.GetRoomManageId(RoomManageId); + CPPUNIT_ASSERT(RoomManageId == 12); + TParserAci.GetRoomType(RoomType); + CPPUNIT_ASSERT(RoomType == 25); + TParserAci.GetRoomPeopleListId(PeopListId); + CPPUNIT_ASSERT(PeopListId[0] == 1); + CPPUNIT_ASSERT(PeopListId[1] == 2); + CPPUNIT_ASSERT(PeopListId[2] == 3); + } + + void MSG_AnswerClassList_Test() + { + CBufferMessage buf; + MSG_AnswerClassList TMAcl; + std::vector RoomIdList; + std::vector RoomStateList; + std::vector RoomNameList; + RoomIdList.push_back(111); + RoomIdList.push_back(1112); + RoomIdList.push_back(11123); + TMAcl.SetRoomIdList(RoomIdList); + RoomStateList.push_back(111); + RoomStateList.push_back(1112); + RoomStateList.push_back(1113); + TMAcl.SetRoomStateList(RoomStateList); + RoomNameList.push_back("1"); + RoomNameList.push_back("2"); + RoomNameList.push_back("3"); + TMAcl.SetRoomNameList(RoomNameList); + RoomIdList.clear(); + RoomNameList.clear(); + RoomStateList.clear(); + + g_m2pack.PackMessage(&TMAcl, buf); + CMessage parserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_AnswerClassList_Id); + g_m2parser.Parser(&parserMsg, buf); + MSG_AnswerClassList TParserAcl(parserMsg); + + TParserAcl.GetRoomIdList(RoomIdList); + CPPUNIT_ASSERT(RoomIdList[0] == 111); + CPPUNIT_ASSERT(RoomIdList[1] == 1112); + CPPUNIT_ASSERT(RoomIdList[2] == 11123); + TParserAcl.GetRoomStateList(RoomStateList); + CPPUNIT_ASSERT(RoomStateList[0] == 111); + CPPUNIT_ASSERT(RoomStateList[1] == 1112); + CPPUNIT_ASSERT(RoomStateList[2] == 1113); + TParserAcl.GetRoomNameList(RoomNameList); + CPPUNIT_ASSERT(RoomNameList[0] == "1"); + CPPUNIT_ASSERT(RoomNameList[1] == "2"); + CPPUNIT_ASSERT(RoomNameList[2] == "3"); + } + + void MSG_AnswerLogin_Test() + { + CBufferMessage buf; + MSG_AnswerLogin TMAl; + std::string ATLGUID; + uint8 LoginResult = 0; + uint32 Token = 0; + TMAl.SetATLGUID(""); + TMAl.SetLoginResult(10); + TMAl.SetToken(10000); + + g_m2pack.PackMessage(&TMAl, buf); + CMessage parserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_AnswerLogin_Id); + g_m2parser.Parser(&parserMsg, buf); + MSG_AnswerLogin TParserAl(parserMsg); + + TParserAl.GetATLGUID(ATLGUID); + CPPUNIT_ASSERT(ATLGUID == ""); + TParserAl.GetToken(Token); + CPPUNIT_ASSERT(Token == 10000); + TParserAl.GetLoginResult(LoginResult); + CPPUNIT_ASSERT(LoginResult == 10); + } + + void MSG_AnswerProfileSync_Test() + { + CBufferMessage buf; + MSG_AnswerProfileSync TMAps; + std::string strMessageSynchro; + TMAps.SetMessageSynchro("!!ee e e e "); + + g_m2pack.PackMessage(&TMAps, buf); + CMessage parserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_AnswerProfileSync_Id); + g_m2parser.Parser(&parserMsg, buf); + MSG_AnswerProfileSync TParserAps(parserMsg); + TParserAps.GetMessageSynchro(strMessageSynchro); + CPPUNIT_ASSERT(strMessageSynchro == "!!ee e e e "); + } + + void MSG_AnswerRegister_Test() + { + CBufferMessage buf; + MSG_AnswerRegister TMAr; + uint32 RetTag = 0; + TMAr.SetRetTag(15000); + + g_m2pack.PackMessage(&TMAr, buf); + CMessage parserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_AnswerRegister_Id); + g_m2parser.Parser(&parserMsg, buf); + MSG_AnswerRegister TParserAr(parserMsg); + + TParserAr.GetRetTag(RetTag); + CPPUNIT_ASSERT(RetTag == 15000); + } + + void MSG_AnswerVerificationCode_Test() + { + CBufferMessage buf; + MSG_AnswerVerificationCode TMAvc; + std::string strCaptcha; + uint8 CaptchaType = 0; + uint8 LoginTag = 0; + TMAvc.SetCaptcha("DZ⣡"); + TMAvc.SetCaptchaType(105); + TMAvc.SetLoginTag(3); + + g_m2pack.PackMessage(&TMAvc, buf); + CMessage parserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_AnswerVerificationCode_Id); + g_m2parser.Parser(&parserMsg, buf); + MSG_AnswerVerificationCode TParserAvc(parserMsg); + + TParserAvc.GetCaptcha(strCaptcha); + CPPUNIT_ASSERT(strCaptcha == "DZ⣡"); + TParserAvc.GetCaptchaType(CaptchaType); + CPPUNIT_ASSERT(CaptchaType == 105); + TParserAvc.GetLoginTag(LoginTag); + CPPUNIT_ASSERT(LoginTag == 3); + } + + void MSG_RequestClassInfo_Test() + { + CBufferMessage buf; + MSG_RequestClassInfo TMRci; + uint32 RoomId = 0; + TMRci.SetRoomID(15016); + + g_m2pack.PackMessage(&TMRci, buf); + CMessage parserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_RequestClassInfo_Id); + g_m2parser.Parser(&parserMsg, buf); + MSG_RequestClassInfo TParserAci(parserMsg); + + TParserAci.GetRoomID(RoomId); + CPPUNIT_ASSERT(RoomId == 15016); + } + + void MSG_RequestClassList_Test() + { + CBufferMessage buf; + uint32 UserType = 0; + MSG_RequestClassList TMRcl; + TMRcl.SetUserType(10000000); + + g_m2pack.PackMessage(&TMRcl, buf); + CMessage parserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_RequestClassList_Id); + g_m2parser.Parser(&parserMsg, buf); + MSG_RequestClassInfo TParserRcl(parserMsg); + + TMRcl.GetUserType(UserType); + CPPUNIT_ASSERT(UserType == 10000000); + } + + void MSG_RequestLogin_Test() + { + CBufferMessage buf; + MSG_RequestLogin TMRl; + std::string strAccountNumber; + std::string strPassword; + std::string strVerificationCode; + TMRl.SetAccountNumber("Sum"); + TMRl.SetPassword("123456789"); + TMRl.SetVerificationCode("EFDA"); + + g_m2pack.PackMessage(&TMRl, buf); + CMessage parserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_RequestLogin_Id); + g_m2parser.Parser(&parserMsg, buf); + MSG_RequestLogin TParserRl(parserMsg); + + TParserRl.GetAccountNumber(strAccountNumber); + CPPUNIT_ASSERT(strAccountNumber == "Sum"); + TParserRl.GetPassword(strPassword); + CPPUNIT_ASSERT(strPassword == "123456789"); + TParserRl.GetVerificationCode(strVerificationCode); + CPPUNIT_ASSERT(strVerificationCode == "EFDA"); + } + + void MSG_RequestProfileSync_Test() + { + CBufferMessage buf; + MSG_RequestProfileSync TMRps; + uint8 Rank = 0; + uint8 HeadForm = 0; + std::string strAutograph; + std::string strHeadPortrait; + std::string strNickName; + TMRps.SetRank(10); + TMRps.SetHeadForm(20); + TMRps.SetAutograph("!!!!!!!!!!!!!!!!!!!!!"); + TMRps.SetHeadPortrait("lalala"); + TMRps.SetNickname("yahoooooooooooooooooooooooooooooooooooo"); + + g_m2pack.PackMessage(&TMRps, buf); + CMessage parserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_RequestProfileSync_Id); + g_m2parser.Parser(&parserMsg, buf); + MSG_RequestProfileSync TParserRps(parserMsg); + + TParserRps.GetRank(Rank); + CPPUNIT_ASSERT(Rank == 10); + TParserRps.GetHeadForm(HeadForm); + CPPUNIT_ASSERT(HeadForm == 20); + TParserRps.GetAutograph(strAutograph); + CPPUNIT_ASSERT(strAutograph == "!!!!!!!!!!!!!!!!!!!!!"); + TParserRps.GetHeadPortrait(strHeadPortrait); + CPPUNIT_ASSERT(strHeadPortrait == "lalala"); + TParserRps.GetNickname(strNickName); + CPPUNIT_ASSERT(strNickName == "yahoooooooooooooooooooooooooooooooooooo"); + } + + void MSG_RequestRegister_Test() + { + CBufferMessage buf; + MSG_RequestRegister TMRr; + uint8 Rank = 0; + uint8 HeadForm = 0; + std::string strAutograph; + std::string strHeadPortrait; + std::string strNickName; + std::string strEmailAddress; + TMRr.SetRank(0); + TMRr.SetHeadForm(20); + TMRr.SetAutograph("!!!!!!!!!!!!!!!!!!!!!"); + TMRr.SetHeadPortrait("lalala"); + TMRr.SetNickname("yahoooooooooooooooooooooooooooooooooooo"); + TMRr.SetEmailAddress("123456@123.com"); + + g_m2pack.PackMessage(&TMRr, buf); + CMessage parserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_RequestRegister_Id); + g_m2parser.Parser(&parserMsg, buf); + MSG_RequestRegister TParserRr(parserMsg); + + TParserRr.GetRank(Rank); + CPPUNIT_ASSERT(Rank == 0); + TParserRr.GetHeadForm(HeadForm); + CPPUNIT_ASSERT(HeadForm == 20); + TParserRr.GetAutograph(strAutograph); + CPPUNIT_ASSERT(strAutograph == "!!!!!!!!!!!!!!!!!!!!!"); + TParserRr.GetHeadPortrait(strHeadPortrait); + CPPUNIT_ASSERT(strHeadPortrait == "lalala"); + TParserRr.GetNickname(strNickName); + CPPUNIT_ASSERT(strNickName == "yahoooooooooooooooooooooooooooooooooooo"); + TMRr.GetEmailAddress(strEmailAddress); + CPPUNIT_ASSERT(strEmailAddress == "123456@123.com"); + } + + void MSG_RequestVerificationCode_Test() + { + CBufferMessage buf; + std::string strMachineAddress; + MSG_RequestVerificationCode TMRvc; + TMRvc.SetMachineAddress(""); + + g_m2pack.PackMessage(&TMRvc, buf); + CMessage parserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_RequestVerificationCode_Id); + g_m2parser.Parser(&parserMsg, buf); + + MSG_RequestVerificationCode TParserRvc(parserMsg); + TParserRvc.GetMachineAddress(strMachineAddress); + CPPUNIT_ASSERT(strMachineAddress == ""); + } + + void MSG_NULL_Test() + { + //NoArrayData Test NULL + CBufferMessage buf; + MSG_RequestRegister TMRr; + char t[1000] = {0}; + uint8 Rank = 0; + uint8 HeadForm = 0; + std::string strAutograph; + std::string strHeadPortrait; + std::string strNickName; + std::string strEmailAddress; + //TMRr.SetRank(10); + //TMRr.SetHeadForm(20); + //TMRr.SetAutograph("!!!!!!!!!!!!!!!!!!!!!"); + TMRr.SetHeadPortrait(""); + TMRr.SetNickname("yahoooooooooooooooooooooooooooooooooooo"); + TMRr.SetEmailAddress("123456@123.com"); + + g_m2pack.PackMessage(&TMRr, buf); + memcpy(t, buf.GetBuffer(), buf.GetSize()); + CMessage parserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_RequestRegister_Id); + g_m2parser.Parser(&parserMsg, buf); + MSG_RequestRegister TParserRr(parserMsg); + + TParserRr.GetRank(Rank); + CPPUNIT_ASSERT(Rank == 0); + TParserRr.GetHeadForm(HeadForm); + CPPUNIT_ASSERT(HeadForm == 0); + TParserRr.GetAutograph(strAutograph); + CPPUNIT_ASSERT(strAutograph == ""); + TParserRr.GetHeadPortrait(strHeadPortrait); + CPPUNIT_ASSERT(strHeadPortrait == ""); + TParserRr.GetNickname(strNickName); + CPPUNIT_ASSERT(strNickName == "yahoooooooooooooooooooooooooooooooooooo"); + TMRr.GetEmailAddress(strEmailAddress); + CPPUNIT_ASSERT(strEmailAddress == "123456@123.com"); + + //ArrayData Test NULL + buf.Clear(); + MSG_AnswerClassList TMAcl; + std::vector RoomIdList; + std::vector RoomStateList; + std::vector RoomNameList; + //RoomIdList.push_back(111); + //RoomIdList.push_back(1112); + //RoomIdList.push_back(11123); + TMAcl.SetRoomIdList(RoomIdList); + RoomStateList.push_back(111); + RoomStateList.push_back(1112); + RoomStateList.push_back(1113); + TMAcl.SetRoomStateList(RoomStateList); + RoomNameList.push_back(""); + RoomNameList.push_back(""); + RoomNameList.push_back(""); + TMAcl.SetRoomNameList(RoomNameList); + RoomIdList.clear(); + RoomNameList.clear(); + RoomStateList.clear(); + + g_m2pack.PackMessage(&TMAcl, buf); + CMessage arrparserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_AnswerClassList_Id); + g_m2parser.Parser(&arrparserMsg, buf); + MSG_AnswerClassList TParserAcl(arrparserMsg); + + TParserAcl.GetRoomIdList(RoomIdList); + CPPUNIT_ASSERT(RoomIdList[0] == 0); + //CPPUNIT_ASSERT(RoomIdList[1] == 1112); + //CPPUNIT_ASSERT(RoomIdList[2] == 11123); + TParserAcl.GetRoomStateList(RoomStateList); + CPPUNIT_ASSERT(RoomStateList[0] == 111); + CPPUNIT_ASSERT(RoomStateList[1] == 1112); + CPPUNIT_ASSERT(RoomStateList[2] == 1113); + TParserAcl.GetRoomNameList(RoomNameList); + CPPUNIT_ASSERT(RoomNameList[0] == ""); + CPPUNIT_ASSERT(RoomNameList[1] == ""); + CPPUNIT_ASSERT(RoomNameList[2] == ""); + + //ArrayData And NO-ArrayData + buf.Clear(); + MSG_AnswerClassInfo TMAci; + std::vector PeopListId; + TMAci.SetRoomName(""); + TMAci.SetRoomID(22); + TMAci.SetRoomManageId(12); + //TMAci.SetRoomPassword("123456789"); + TMAci.SetRoomRank(10); + TMAci.SetRoomPeopleNumMax(1000); + TMAci.SetRoomType(25); + TMAci.SetRoomState(100); + PeopListId.push_back(1); + PeopListId.push_back(2); + PeopListId.push_back(3); + TMAci.SetRoomPeopleListId(PeopListId); + PeopListId.clear(); + + g_m2pack.PackMessage(&TMAci, buf); + CMessage AparserMsg(CMessage2Parser::GetMsgType(buf)); + CPPUNIT_ASSERT(CMessage2Parser::GetMsgType(buf) == MSG_AnswerClassInfo_Id); + g_m2parser.Parser(&AparserMsg, buf); + MSG_AnswerClassInfo TParserAci(AparserMsg); + + uint32 RoomId = 0; + uint32 RoomRank = 0; + uint32 RoomType = 0; + uint32 RoomState = 0; + uint32 RoomPeopleNumMax = 0; + uint32 RoomManageId = 0; + std::string strRoomName; + std::string strPassword; + + TParserAci.GetRoomName(strRoomName); + CPPUNIT_ASSERT(strRoomName == ""); + TParserAci.GetRoomID(RoomId); + CPPUNIT_ASSERT(RoomId == 22); + TParserAci.GetRoomRank(RoomRank); + CPPUNIT_ASSERT(RoomRank == 10); + TParserAci.GetRoomPeopleNumMax(RoomPeopleNumMax); + CPPUNIT_ASSERT(RoomPeopleNumMax == 1000); + TParserAci.GetRoomPassword(strPassword); + CPPUNIT_ASSERT(strPassword == ""); + TParserAci.GetRoomState(RoomState); + CPPUNIT_ASSERT(RoomState == 100); + TParserAci.GetRoomManageId(RoomManageId); + CPPUNIT_ASSERT(RoomManageId == 12); + TParserAci.GetRoomType(RoomType); + CPPUNIT_ASSERT(RoomType == 25); + TParserAci.GetRoomPeopleListId(PeopListId); + CPPUNIT_ASSERT(PeopListId[0] == 1); + CPPUNIT_ASSERT(PeopListId[1] == 2); + CPPUNIT_ASSERT(PeopListId[2] == 3); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION ( MSG_Message_Test ); +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(MSG_Message_Test, "testNMessage"); + +#endif \ No newline at end of file diff --git a/VNOC/VNOC/test/Vnocp1MessageParserTest.cpp b/Client/Client/CppUnitTest/Vnocp1MessageParserTest.cpp similarity index 80% rename from VNOC/VNOC/test/Vnocp1MessageParserTest.cpp rename to Client/Client/CppUnitTest/Vnocp1MessageParserTest.cpp index 62b05f46..e646e2cb 100644 --- a/VNOC/VNOC/test/Vnocp1MessageParserTest.cpp +++ b/Client/Client/CppUnitTest/Vnocp1MessageParserTest.cpp @@ -1,416 +1,504 @@ -#include -#include -#include "..\..\Message\MessageParser.h" -#include -class Vnocp1MessageParserTest : public CppUnit::TestFixture -{ - CPPUNIT_TEST_SUITE( Vnocp1MessageParserTest ); - CPPUNIT_TEST( MSGAVCParseTest ); - CPPUNIT_TEST( MSGRVCParseTest ); - CPPUNIT_TEST( MSGALIParseTest ); - CPPUNIT_TEST( MSGRLIParseTest ); - CPPUNIT_TEST( MSGAPSParseTest ); - CPPUNIT_TEST( MSGRPSParseTest ); - CPPUNIT_TEST_SUITE_END(); -public: - void setUp() - { - - } - void tearDown() - { - - } -public: - - void MSGAVCParseTest() - { - byte testParamO [] = {0x01,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02}; - byte testParamT [] = {0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03}; - byte testParamS [] = {0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04}; - - byte testAVC [] = {0x56, - 0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x3F, - - - 0x01,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x15, - 0x00,0x00,0x00,0x00, - 0x03, - - 0x00,0x00,0x00,0x01, - 0x00,0x00,0x00,0x01, - 0x00,0x00,0x00,0x10, - - 0x1e, - - 0x1e, - - 0x01,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x00,0x00, - 0x43}; - - - byte testPackAVC[63] = {0}; - - //AVC - CMessageParser msgParser; - CMessage* msgAVC = msgParser.Parse(testAVC,sizeof(testAVC)); - CPPUNIT_ASSERT(msgAVC->GetMessageType() == MSG_AVC_TYPE);//֤ϢAVC - MSG_AVC* msg_avc = (MSG_AVC *)msgAVC; - CPPUNIT_ASSERT(msg_avc->GetSerial() == 1); - CPPUNIT_ASSERT(memcmp(msg_avc->GetGUID(),testParamO,sizeof(byte) * 16) == 0); - CPPUNIT_ASSERT(memcmp(msg_avc->GetCaptcha(),testParamO,16) == 0); - CPPUNIT_ASSERT(msg_avc->GetLoginTag() == 0x1e); - CPPUNIT_ASSERT(msg_avc->GetCaptchaType() == 0x1e); - } - - void MSGRVCParseTest() - { - byte testParamO [] = {0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02}; - byte testParamT [] = {0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03}; - byte testParamS [] = {0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04}; - - byte testRVC [] = {0x56, - 0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x35, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x14, - 0x00,0x00,0x00,0x00, - 0x01, - - 0x00,0x00,0x00,0x10, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x00,0x00, - 0x43}; - - byte testPackRVC[53] = {0}; - - CMessageParser msgParser; - CMessage* msgRVC = msgParser.Parse(testRVC,sizeof(testRVC)); - CPPUNIT_ASSERT(msgRVC->GetMessageType() == MSG_RVC_TYPE);//֤ϢRVC - MSG_RVC* msg_rvc = (MSG_RVC *)msgRVC; - - CPPUNIT_ASSERT(msg_rvc->GetSerial() == 1); - - CPPUNIT_ASSERT(memcmp(msg_rvc->GetGUID(),testParamO,sizeof(byte) * 16) == 0); - CPPUNIT_ASSERT(memcmp(msg_rvc->GetMachineAddress(),testParamO,16) == 0); - } - - void MSGRLIParseTest() - { - byte testParamO [] = {0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02}; - byte testParamT [] = {0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03}; - byte testParamS [] = {0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04}; - - byte testRLI [] = {0x56, - 0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x5D, - - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x16, - 0x00,0x00,0x00,0x00, - - 0x03, - - 0x00,0x00,0x00,0x10, - 0x00,0x00,0x00,0x10, - 0x00,0x00,0x00,0x10, - - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - - 0x00,0x00, - 0x43}; - - byte testPackRLI[100] = {0}; - - //RLI - CMessageParser msgParser; - CMessage* msgRLI = msgParser.Parse(testRLI,sizeof(testRLI)); - CPPUNIT_ASSERT(msgRLI->GetMessageType() == MSG_RLI_TYPE);//֤ϢRLI - MSG_RLI* msg_rli = (MSG_RLI *)msgRLI; - - CPPUNIT_ASSERT(msg_rli->GetSerial() == 1); - - CPPUNIT_ASSERT(memcmp(msg_rli->GetGUID(),testParamO,sizeof(byte) * 16) == 0); - - CPPUNIT_ASSERT(memcmp(msg_rli->GetVerificationCode(),testParamO,sizeof(byte) * 16) == 0); - - CPPUNIT_ASSERT(memcmp(msg_rli->GetAccountNumber(),testParamT,16) == 0); - - CPPUNIT_ASSERT(memcmp(msg_rli->GetPassword(),testParamS,16) == 0); - - } - - void MSGRPSParseTest() - { - byte testParamO [] = {0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02}; - byte testParamT [] = {0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03}; - byte testParamS [] = {0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04}; - - - byte testRPS [] = {0x56, - 0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x67, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x18, - 0x00,0x00,0x00,0x00, - - 0x05, - - 0x00,0x00,0x00,0x01, - 0x00,0x00,0x00,0x10, - 0x00,0x00,0x00,0x10, - 0x00,0x00,0x00,0x01, - 0x00,0x00,0x00,0x10, - - 0x01, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - - 'A', - - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - - 0x00,0x00, - 0x43}; - - byte testPackRPS[120] = {0}; - - //RPS - CMessageParser msgParser; - CMessage* msgRPS = msgParser.Parse(testRPS,sizeof(testRPS)); - CPPUNIT_ASSERT(msgRPS->GetMessageType() == MSG_RPS_TYPE);//֤ϢRPS - MSG_RPS* msg_rps = (MSG_RPS *)msgRPS; - - CPPUNIT_ASSERT(msg_rps->GetSerial() == 1); - - CPPUNIT_ASSERT(memcmp(msg_rps->GetGUID(),testParamO,sizeof(byte) * 16) == 0); - - CPPUNIT_ASSERT(msg_rps->GetRank() == 0x01); - - CPPUNIT_ASSERT(memcmp(msg_rps->GetNickname(),testParamO,sizeof(byte) * 16) == 0); - - CPPUNIT_ASSERT(memcmp(msg_rps->GetAutograph(),testParamT,sizeof(byte) * 16) == 0); - - CPPUNIT_ASSERT(msg_rps->GetHeadForm() == 'A'); - - CPPUNIT_ASSERT(memcmp(msg_rps->GetHeadPortrait(),testParamS,sizeof(byte) * 16) == 0); - - } - - void MSGAPSParseTest() - { - byte testParamO [] = {0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02}; - byte testParamT [] = {0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03}; - byte testParamS [] = {0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04}; - - byte testAPS [] = {0x56, - 0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x35, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x19, - 0x00,0x00,0x00,0x00, - 0x01, - - 0x00,0x00,0x00,0x10, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x00,0x00, - 0x43}; - - byte testPackAPS[100] = {0}; - //APS - CMessageParser msgParser; - CMessage* msgAPS = msgParser.Parse(testAPS,sizeof(testAPS)); - CPPUNIT_ASSERT(msgAPS->GetMessageType() == MSG_APS_TYPE);//֤ϢRPS - MSG_APS* msg_aps = (MSG_APS *)msgAPS; - - CPPUNIT_ASSERT(msg_aps->GetSerial() == 1); - - CPPUNIT_ASSERT(memcmp(msg_aps->GetGUID(),testParamO,sizeof(byte) * 16) == 0); - - CPPUNIT_ASSERT(memcmp(msg_aps->GetMessageSynchro(),testParamO,sizeof(byte) * 16) == 0); - } - - void MSGALIParseTest() - { - byte testParamO [] = {0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02}; - byte testParamT [] = {0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03}; - byte testParamS [] = {0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04}; - - byte testALI [] = {0x56, - 0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x4E, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x17, - 0x00,0x00,0x00,0x00, - - 0x03, - - 0x00,0x00,0x00,0x01, - 0x00,0x00,0x00,0x10, - 0x00,0x00,0x00,0x10, - - 0x1e, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - - 0x00,0x00, - 0x43}; - - byte testPackALI[100] = {0}; - - CMessageParser msgParser; - CMessage* msgALI = msgParser.Parse(testALI,sizeof(testALI)); - CPPUNIT_ASSERT(msgALI->GetMessageType() == MSG_ALI_TYPE);//֤ϢALI - MSG_ALI* msg_ali = (MSG_ALI *)msgALI; - - CPPUNIT_ASSERT(msg_ali->GetSerial() == 1); - - CPPUNIT_ASSERT(memcmp(msg_ali->GetGUID(),testParamO,sizeof(byte) * 16) == 0); - - CPPUNIT_ASSERT(msg_ali->GetLoginResult() == 0x1E); - - CPPUNIT_ASSERT(memcmp(msg_ali->GetATLGUID(),testParamT,sizeof(byte) * 16) == 0); - - } - -}; -CPPUNIT_TEST_SUITE_REGISTRATION ( Vnocp1MessageParserTest ); -CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(Vnocp1MessageParserTest, "Vnocp1MessageParserTest"); \ No newline at end of file +#ifdef CPPTEST +#include +#include +#include "..\..\Message\MessageParser.h" +#include +class Vnocp1MessageParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( Vnocp1MessageParserTest ); + CPPUNIT_TEST( MSGParserCheckTest ); + CPPUNIT_TEST( MSGAVCParseTest ); + CPPUNIT_TEST( MSGRVCParseTest ); + CPPUNIT_TEST( MSGALIParseTest ); + CPPUNIT_TEST( MSGRLIParseTest ); + CPPUNIT_TEST( MSGAPSParseTest ); + CPPUNIT_TEST( MSGRPSParseTest ); + CPPUNIT_TEST_SUITE_END(); +public: + void setUp() + { + + } + void tearDown() + { + + } +public: + + void MSGParserCheckTest() + { + byte testAllRubbish[] = { + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + }; + byte testHasHeadRubbish[] = + { + 0x12,0x12,0x12,0x12, + 'V',0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + }; + byte testLengthLack[] = + { + 'V',0x12,0x12,0x12, + 0x00,0x00,0x00,0xff, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + }; + byte testNoTailRubbish[]= + { + 'V',0x12,0x12,0x12, + 0x00,0x00,0x00,0x10, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + }; + byte testGood[]= + { + 'V',0x12,0x12,0x12, + 0x00,0x00,0x00,0x10, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,'C', + }; + byte testRubbishWithGood[]= + { + 0x12,0x12,0x12,0x12, + 'V',0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12, + + 'V',0x12,0x12,0x12, + 0x00,0x00,0x00,0x10, + 0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,'C', + }; + CPPUNIT_ASSERT(CMessageParser::Check(testAllRubbish,sizeof(testAllRubbish)) == -1); + CPPUNIT_ASSERT(CMessageParser::Check(testHasHeadRubbish,sizeof(testHasHeadRubbish)) == -1); + CPPUNIT_ASSERT(CMessageParser::Check(testLengthLack,sizeof(testLengthLack)) == -1); + CPPUNIT_ASSERT(CMessageParser::Check(testNoTailRubbish,sizeof(testNoTailRubbish)) == -1); + CPPUNIT_ASSERT(CMessageParser::Check(testGood,sizeof(testGood)) == 0x10); + CPPUNIT_ASSERT(CMessageParser::Check(testRubbishWithGood,sizeof(testRubbishWithGood)) == 0x2c); + } + + void MSGAVCParseTest() + { + byte testParamO [] = {0x01,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02}; + byte testParamT [] = {0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03}; + byte testParamS [] = {0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04}; + + byte testAVC [] = {0x56, + 0x00, + 0x00,0x01, + 0x00,0x00,0x00,0x3F, + + + 0x01,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x15, + 0x00,0x00,0x00,0x00, + 0x03, + + 0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x10, + + 0x1e, + + 0x1e, + + 0x01,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x00,0x00, + 0x43}; + + + byte testPackAVC[63] = {0}; + + //AVC + CMessageParser msgParser; + CMessage* msgAVC = msgParser.Parse(testAVC,sizeof(testAVC)); + CPPUNIT_ASSERT(msgAVC->GetMessageType() == MSG_AVC_TYPE);//֤ϢAVC + MSG_AVC* msg_avc = (MSG_AVC *)msgAVC; + CPPUNIT_ASSERT(msg_avc->GetSerial() == 1); + CPPUNIT_ASSERT(memcmp(msg_avc->GetGUID(),testParamO,sizeof(byte) * 16) == 0); + CPPUNIT_ASSERT(memcmp(msg_avc->GetCaptcha(),testParamO,16) == 0); + CPPUNIT_ASSERT(msg_avc->GetLoginTag() == 0x1e); + CPPUNIT_ASSERT(msg_avc->GetCaptchaType() == 0x1e); + delete msg_avc; + } + + void MSGRVCParseTest() + { + byte testParamO [] = {0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02}; + byte testParamT [] = {0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03}; + byte testParamS [] = {0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04}; + + byte testRVC [] = {0x56, + 0x00, + 0x00,0x01, + 0x00,0x00,0x00,0x35, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x14, + 0x00,0x00,0x00,0x00, + 0x01, + + 0x00,0x00,0x00,0x10, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x00,0x00, + 0x43}; + + byte testPackRVC[53] = {0}; + + CMessageParser msgParser; + CMessage* msgRVC = msgParser.Parse(testRVC,sizeof(testRVC)); + CPPUNIT_ASSERT(msgRVC->GetMessageType() == MSG_RVC_TYPE);//֤ϢRVC + MSG_RVC* msg_rvc = (MSG_RVC *)msgRVC; + + CPPUNIT_ASSERT(msg_rvc->GetSerial() == 1); + + CPPUNIT_ASSERT(memcmp(msg_rvc->GetGUID(),testParamO,sizeof(byte) * 16) == 0); + CPPUNIT_ASSERT(memcmp(msg_rvc->GetMachineAddress(),testParamO,16) == 0); + delete msg_rvc; + } + + void MSGRLIParseTest() + { + byte testParamO [] = {0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02}; + byte testParamT [] = {0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03}; + byte testParamS [] = {0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04}; + + byte testRLI [] = {0x56, + 0x00, + 0x00,0x01, + 0x00,0x00,0x00,0x5D, + + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x16, + 0x00,0x00,0x00,0x00, + + 0x03, + + 0x00,0x00,0x00,0x10, + 0x00,0x00,0x00,0x10, + 0x00,0x00,0x00,0x10, + + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + + 0x00,0x00, + 0x43}; + + byte testPackRLI[100] = {0}; + + //RLI + CMessageParser msgParser; + CMessage* msgRLI = msgParser.Parse(testRLI,sizeof(testRLI)); + CPPUNIT_ASSERT(msgRLI->GetMessageType() == MSG_RLI_TYPE);//֤ϢRLI + MSG_RLI* msg_rli = (MSG_RLI *)msgRLI; + + CPPUNIT_ASSERT(msg_rli->GetSerial() == 1); + + CPPUNIT_ASSERT(memcmp(msg_rli->GetGUID(),testParamO,sizeof(byte) * 16) == 0); + + CPPUNIT_ASSERT(memcmp(msg_rli->GetVerificationCode(),testParamO,sizeof(byte) * 16) == 0); + + CPPUNIT_ASSERT(memcmp(msg_rli->GetAccountNumber(),testParamT,16) == 0); + + CPPUNIT_ASSERT(memcmp(msg_rli->GetPassword(),testParamS,16) == 0); + delete msg_rli; + + } + + void MSGRPSParseTest() + { + byte testParamO [] = {0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02}; + byte testParamT [] = {0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03}; + byte testParamS [] = {0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04}; + + + byte testRPS [] = {0x56, + 0x00, + 0x00,0x01, + 0x00,0x00,0x00,0x67, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x18, + 0x00,0x00,0x00,0x00, + + 0x05, + + 0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x10, + 0x00,0x00,0x00,0x10, + 0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x10, + + 0x01, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + + 'A', + + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + + 0x00,0x00, + 0x43}; + + byte testPackRPS[120] = {0}; + + //RPS + CMessageParser msgParser; + CMessage* msgRPS = msgParser.Parse(testRPS,sizeof(testRPS)); + CPPUNIT_ASSERT(msgRPS->GetMessageType() == MSG_RPS_TYPE);//֤ϢRPS + MSG_RPS* msg_rps = (MSG_RPS *)msgRPS; + + CPPUNIT_ASSERT(msg_rps->GetSerial() == 1); + + CPPUNIT_ASSERT(memcmp(msg_rps->GetGUID(),testParamO,sizeof(byte) * 16) == 0); + + CPPUNIT_ASSERT(msg_rps->GetRank() == 0x01); + + CPPUNIT_ASSERT(memcmp(msg_rps->GetNickname(),testParamO,sizeof(byte) * 16) == 0); + + CPPUNIT_ASSERT(memcmp(msg_rps->GetAutograph(),testParamT,sizeof(byte) * 16) == 0); + + CPPUNIT_ASSERT(msg_rps->GetHeadForm() == 'A'); + + CPPUNIT_ASSERT(memcmp(msg_rps->GetHeadPortrait(),testParamS,sizeof(byte) * 16) == 0); + delete msg_rps; + + } + + void MSGAPSParseTest() + { + byte testParamO [] = {0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02}; + byte testParamT [] = {0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03}; + byte testParamS [] = {0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04}; + + byte testAPS [] = {0x56, + 0x00, + 0x00,0x01, + 0x00,0x00,0x00,0x35, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x19, + 0x00,0x00,0x00,0x00, + 0x01, + + 0x00,0x00,0x00,0x10, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x00,0x00, + 0x43}; + + byte testPackAPS[100] = {0}; + //APS + CMessageParser msgParser; + CMessage* msgAPS = msgParser.Parse(testAPS,sizeof(testAPS)); + CPPUNIT_ASSERT(msgAPS->GetMessageType() == MSG_APS_TYPE);//֤ϢRPS + MSG_APS* msg_aps = (MSG_APS *)msgAPS; + + CPPUNIT_ASSERT(msg_aps->GetSerial() == 1); + + CPPUNIT_ASSERT(memcmp(msg_aps->GetGUID(),testParamO,sizeof(byte) * 16) == 0); + + CPPUNIT_ASSERT(memcmp(msg_aps->GetMessageSynchro(),testParamO,sizeof(byte) * 16) == 0); + delete msg_aps; + } + + void MSGALIParseTest() + { + byte testParamO [] = {0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02}; + byte testParamT [] = {0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03}; + byte testParamS [] = {0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04}; + + byte testALI [] = {0x56, + 0x00, + 0x00,0x01, + 0x00,0x00,0x00,0x4E, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x17, + 0x00,0x00,0x00,0x00, + + 0x03, + + 0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x10, + 0x00,0x00,0x00,0x10, + + 0x1e, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + + 0x00,0x00, + 0x43}; + + byte testPackALI[100] = {0}; + + CMessageParser msgParser; + CMessage* msgALI = msgParser.Parse(testALI,sizeof(testALI)); + CPPUNIT_ASSERT(msgALI->GetMessageType() == MSG_ALI_TYPE);//֤ϢALI + MSG_ALI* msg_ali = (MSG_ALI *)msgALI; + + CPPUNIT_ASSERT(msg_ali->GetSerial() == 1); + + CPPUNIT_ASSERT(memcmp(msg_ali->GetGUID(),testParamO,sizeof(byte) * 16) == 0); + + CPPUNIT_ASSERT(msg_ali->GetLoginResult() == 0x1E); + + CPPUNIT_ASSERT(memcmp(msg_ali->GetATLGUID(),testParamT,sizeof(byte) * 16) == 0); + delete msg_ali; + } + +}; +CPPUNIT_TEST_SUITE_REGISTRATION ( Vnocp1MessageParserTest ); +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(Vnocp1MessageParserTest, "Vnocp1MessageParserTest"); + +#endif \ No newline at end of file diff --git a/VNOC/VNOC/test/testPackMessage.cpp b/Client/Client/CppUnitTest/testPackMessage.cpp similarity index 78% rename from VNOC/VNOC/test/testPackMessage.cpp rename to Client/Client/CppUnitTest/testPackMessage.cpp index 11b1f9ca..818c9faa 100644 --- a/VNOC/VNOC/test/testPackMessage.cpp +++ b/Client/Client/CppUnitTest/testPackMessage.cpp @@ -1,501 +1,638 @@ - -#include -#include -#include "..\..\Message\PackMessage.h" -#include - - -class testPackMessage :public CppUnit::TestFixture -{ - CPPUNIT_TEST_SUITE( testPackMessage ); - CPPUNIT_TEST( MSGAVCPackTest ); - CPPUNIT_TEST( MSGRVCPackTest ); - CPPUNIT_TEST( MSGALIPackTest ); - CPPUNIT_TEST( MSGRLIPackTest ); - CPPUNIT_TEST( MSGAPSPackTest ); - CPPUNIT_TEST( MSGRPSPackTest ); - CPPUNIT_TEST_SUITE_END(); - -public: - void setUp() - { - - } - void tearDown() - { - - } - -public: - - void MSGAVCPackTest() - { - byte testParamO [] = {0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02}; - byte testParamT [] = {0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03}; - byte testParamS [] = {0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04}; - - byte testAVC [] = {0x56, - 0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x3F, - - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x15, - 0x00,0x00,0x00,0x00, - 0x03, - - 0x00,0x00,0x00,0x01, - 0x00,0x00,0x00,0x01, - 0x00,0x00,0x00,0x10, - - 0x1e, - - 0x1e, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x00,0x00, - 0x43}; - - - byte testPackAVC[63] = {0}; - - //AVC - MSG_AVC msg_avc; - PackMessage msg_pack; - - msg_avc.SetSerial(1); - CPPUNIT_ASSERT(msg_avc.GetSerial() == 1); - msg_avc.SetGUID(testParamO); - CPPUNIT_ASSERT(memcmp(msg_avc.GetGUID(),testParamO,sizeof(byte) * 16) == 0); - //CPPUNIT_ASSERT(msg_avc.SetCmlListLen(testComLenAVC,3)); - msg_avc.SetCaptcha(testParamO,16); - CPPUNIT_ASSERT(memcmp(msg_avc.GetCaptcha(),testParamO,16) == 0); - msg_avc.SetLoginTag(0x1e); - CPPUNIT_ASSERT(msg_avc.GetLoginTag() == 0x1e); - msg_avc.SetCaptchaType(0x1e); - CPPUNIT_ASSERT(msg_avc.GetCaptchaType() == 0x1e); - CPPUNIT_ASSERT(msg_pack.Pack(&msg_avc,testPackAVC,msg_pack.GetMessageLen(&msg_avc)) != -1); - //ȷԱ - CPPUNIT_ASSERT(memcmp(testAVC,testPackAVC,sizeof(testAVC)) == 0); - - CPPUNIT_ASSERT(true); - } - - void MSGRVCPackTest() - { - byte testParamO [] = {0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02}; - byte testParamT [] = {0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03}; - byte testParamS [] = {0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04}; - - byte testRVC [] = {0x56, - 0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x35, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x14, - 0x00,0x00,0x00,0x00, - 0x01, - - 0x00,0x00,0x00,0x10, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x00,0x00, - 0x43}; - - byte testPackRVC[53] = {0}; - PackMessage msg_pack; - - //RVC - MSG_RVC msg_rvc; - - - msg_rvc.SetSerial(1); - - msg_rvc.SetGUID(testParamO); - CPPUNIT_ASSERT(memcmp(msg_rvc.GetGUID(),testParamO,sizeof(byte) * 16) == 0); - //CPPUNIT_ASSERT(msg_rvc.SetCmlListLen(testComLenRVC,1)); - msg_rvc.SetMachineAddress(testParamO,16); - CPPUNIT_ASSERT(memcmp(msg_rvc.GetMachineAddress(),testParamO,16) == 0); - - CPPUNIT_ASSERT(msg_pack.Pack(&msg_rvc,testPackRVC,msg_pack.GetMessageLen(&msg_rvc)) != -1); - - //ȷԱ - CPPUNIT_ASSERT(memcmp(testRVC,testPackRVC,sizeof(testRVC)) == 0); - - CPPUNIT_ASSERT(true); - } - - void MSGRLIPackTest() - { - byte testParamO [] = {0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02}; - byte testParamT [] = {0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03}; - byte testParamS [] = {0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04}; - - byte testRLI [] = {0x56, - 0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x5D, - - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x16, - 0x00,0x00,0x00,0x00, - - 0x03, - - 0x00,0x00,0x00,0x10, - 0x00,0x00,0x00,0x10, - 0x00,0x00,0x00,0x10, - - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - - 0x00,0x00, - 0x43}; - - byte testPackRLI[100] = {0}; - //RLI - MSG_RLI msg_rli; - PackMessage msg_pack; - - msg_rli.SetSerial(1); - CPPUNIT_ASSERT(msg_rli.GetSerial() == 1); - - msg_rli.SetGUID(testParamO); - CPPUNIT_ASSERT(memcmp(msg_rli.GetGUID(),testParamO,sizeof(byte) * 16) == 0); - - //CPPUNIT_ASSERT(msg_rli.SetCmlListLen(testComLenRLI,3)); - - msg_rli.SetVerificationCode(testParamO,16); - CPPUNIT_ASSERT(memcmp(msg_rli.GetVerificationCode(),testParamO,sizeof(byte) * 16) == 0); - - msg_rli.SetAccountNumber(testParamT,16); - CPPUNIT_ASSERT(memcmp(msg_rli.GetAccountNumber(),testParamT,16) == 0); - - msg_rli.SetPassword(testParamS,16); - CPPUNIT_ASSERT(memcmp(msg_rli.GetPassword(),testParamS,16) == 0); - CPPUNIT_ASSERT(msg_pack.Pack(&msg_rli,testPackRLI,msg_pack.GetMessageLen(&msg_rli)) != -1); - - - //ȷԱ - CPPUNIT_ASSERT(memcmp(testRLI,testPackRLI,sizeof(testRLI)) == 0); - - CPPUNIT_ASSERT(true); - } - - void MSGRPSPackTest() - { - byte testParamO [] = {0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02}; - byte testParamT [] = {0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03}; - byte testParamS [] = {0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04}; - - - byte testRPS [] = {0x56, - 0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x67, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x18, - 0x00,0x00,0x00,0x00, - - 0x05, - - 0x00,0x00,0x00,0x01, - 0x00,0x00,0x00,0x10, - 0x00,0x00,0x00,0x10, - 0x00,0x00,0x00,0x01, - 0x00,0x00,0x00,0x10, - - 0x01, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - - 'A', - - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - - 0x00,0x00, - 0x43}; - - byte testPackRPS[120] = {0}; - - //RPS - MSG_RPS msg_rps; - PackMessage msg_pack; - - msg_rps.SetSerial(1); - CPPUNIT_ASSERT(msg_rps.GetSerial() == 1); - - msg_rps.SetGUID(testParamO); - CPPUNIT_ASSERT(memcmp(msg_rps.GetGUID(),testParamO,sizeof(byte) * 16) == 0); - - //CPPUNIT_ASSERT(msg_rps.SetCmlListLen(testComLenRPS,5)); - - msg_rps.SetRank(0x01); - CPPUNIT_ASSERT(msg_rps.GetRank() == 0x01); - - msg_rps.SetNickname(testParamO,16); - CPPUNIT_ASSERT(memcmp(msg_rps.GetNickname(),testParamO,sizeof(byte) * 16) == 0); - - msg_rps.SetAutograph(testParamT,16); - CPPUNIT_ASSERT(memcmp(msg_rps.GetAutograph(),testParamT,sizeof(byte) * 16) == 0); - - msg_rps.SetHeadForm('A'); - CPPUNIT_ASSERT(msg_rps.GetHeadForm() == 'A'); - - msg_rps.SetHeadPortrait(testParamS,16); - CPPUNIT_ASSERT(memcmp(msg_rps.GetHeadPortrait(),testParamS,sizeof(byte) * 16) == 0); - - CPPUNIT_ASSERT(msg_pack.Pack(&msg_rps,testPackRPS,msg_pack.GetMessageLen(&msg_rps)) != -1); - - //ȷԱ - CPPUNIT_ASSERT(memcmp(testRPS,testPackRPS,sizeof(testRPS)) == 0); - - CPPUNIT_ASSERT(true); - - } - - void MSGAPSPackTest() - { - byte testParamO [] = {0x01,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02}; - byte testParamT [] = {0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03}; - byte testParamS [] = {0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04}; - - byte testAPS [] = {0x56, - 0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x35, - - 0x01,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x19, - 0x00,0x00,0x00,0x00, - 0x01, - - 0x00,0x00,0x00,0x10, - - 0x01,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x00,0x00, - 0x43}; - - byte testPackAPS[100] = {0}; - //APS - MSG_APS msg_aps; - PackMessage msg_pack; - - msg_aps.SetSerial(1); - - CPPUNIT_ASSERT(msg_aps.GetSerial() == 1); - - msg_aps.SetGUID(testParamO); - CPPUNIT_ASSERT(memcmp(msg_aps.GetGUID(),testParamO,sizeof(byte) * 16) == 0); - - //CPPUNIT_ASSERT(msg_aps.SetCmlListLen(testComLenAPS,1)); - - - msg_aps.SetMessageSynchro(testParamO,16); - CPPUNIT_ASSERT(memcmp(msg_aps.GetMessageSynchro(),testParamO,sizeof(byte) * 16) == 0); - - CPPUNIT_ASSERT(msg_pack.Pack(&msg_aps,testPackAPS,msg_pack.GetMessageLen(&msg_aps)) != -1); - - //ȷԱ - int index = 0; - for (;index < sizeof(testAPS); index++) - { - if (testAPS[index] != testPackAPS[index]) - { - break; - } - - } - CPPUNIT_ASSERT(memcmp(testAPS,testPackAPS,sizeof(testAPS)) == 0); - - CPPUNIT_ASSERT(true); - } - - void MSGALIPackTest() - { - byte testParamO [] = {0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02}; - byte testParamT [] = {0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03}; - byte testParamS [] = {0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04}; - - byte testALI [] = {0x56, - 0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x4E, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x17, - 0x00,0x00,0x00,0x00, - - 0x03, - - 0x00,0x00,0x00,0x01, - 0x00,0x00,0x00,0x10, - 0x00,0x00,0x00,0x10, - - 0x00, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - - 0x00,0x00, - 0x43}; - - byte testPackALI[100] = {0}; - - //ALI - MSG_ALI msg_ali; - PackMessage msg_pack; - - msg_ali.SetSerial(1); - CPPUNIT_ASSERT(msg_ali.GetSerial() == 1); - - msg_ali.SetGUID(testParamO); - CPPUNIT_ASSERT(memcmp(msg_ali.GetGUID(),testParamO,sizeof(byte) * 16) == 0); - - //CPPUNIT_ASSERT(msg_ali.SetCmlListLen(testComLenALI,3)); - - msg_ali.SetLoginResult(0x0); - CPPUNIT_ASSERT(msg_ali.GetLoginResult() == 0x0); - - msg_ali.SetToken(testParamO,16); - //CPPUNIT_ASSERT(memcmp(msg_ali.GetToken(),testParamO,sizeof(byte) * 16) == 0); - - msg_ali.SetATLGUID(testParamT,16); - CPPUNIT_ASSERT(memcmp(msg_ali.GetATLGUID(),testParamT,sizeof(byte) * 16) == 0); - CPPUNIT_ASSERT(msg_pack.GetMessageLen(&msg_ali) == sizeof (testALI)); - CPPUNIT_ASSERT(msg_pack.Pack(&msg_ali,testPackALI,msg_pack.GetMessageLen(&msg_ali)) != -1); - - //ȷԱ - CPPUNIT_ASSERT(memcmp(testALI,testPackALI,sizeof(testALI)) == 0); - - CPPUNIT_ASSERT(true); - } - -}; - -CPPUNIT_TEST_SUITE_REGISTRATION ( testPackMessage ); -CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(testPackMessage, "testPackMessage"); +#ifdef CPPTEST +#include +#include +#include "..\..\Message\PackMessage.h" +#include + + +class testPackMessage :public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( testPackMessage ); + CPPUNIT_TEST( MSGAVCPackTest ); + CPPUNIT_TEST( MSGRVCPackTest ); + CPPUNIT_TEST( MSGALIPackTest ); + CPPUNIT_TEST( MSGRLIPackTest ); + CPPUNIT_TEST( MSGAPSPackTest ); + CPPUNIT_TEST( MSGRPSPackTest ); + CPPUNIT_TEST( MSGACIPackTest ); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp() + { + + } + void tearDown() + { + + } + +public: + + void MSGAVCPackTest() + { + byte testParamO [] = {0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02}; + byte testParamT [] = {0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03}; + byte testParamS [] = {0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04}; + + byte testAVC [] = {0x56, + 0x00, + 0x00,0x01, + 0x00,0x00,0x00,0x3F, + + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x15, + 0x00,0x00,0x00,0x00, + 0x03, + + 0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x10, + + 0x1e, + + 0x1e, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x00,0x00, + 0x43}; + + + byte testPackAVC[63] = {0}; + + //AVC + MSG_AVC msg_avc; + PackMessage msg_pack; + + msg_avc.SetSerial(1); + CPPUNIT_ASSERT(msg_avc.GetSerial() == 1); + msg_avc.SetGUID(testParamO); + CPPUNIT_ASSERT(memcmp(msg_avc.GetGUID(),testParamO,sizeof(byte) * 16) == 0); + //CPPUNIT_ASSERT(msg_avc.SetCmlListLen(testComLenAVC,3)); + msg_avc.SetCaptcha(testParamO,16); + CPPUNIT_ASSERT(memcmp(msg_avc.GetCaptcha(),testParamO,16) == 0); + msg_avc.SetLoginTag(0x1e); + CPPUNIT_ASSERT(msg_avc.GetLoginTag() == 0x1e); + msg_avc.SetCaptchaType(0x1e); + CPPUNIT_ASSERT(msg_avc.GetCaptchaType() == 0x1e); + CPPUNIT_ASSERT(msg_pack.Pack(&msg_avc,testPackAVC,msg_pack.GetMessageLen(&msg_avc)) != -1); + //ȷԱ + CPPUNIT_ASSERT(memcmp(testAVC,testPackAVC,sizeof(testAVC)) == 0); + + CPPUNIT_ASSERT(true); + } + + void MSGRVCPackTest() + { + byte testParamO [] = {0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02}; + byte testParamT [] = {0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03}; + byte testParamS [] = {0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04}; + + byte testRVC [] = {0x56, + 0x00, + 0x00,0x01, + 0x00,0x00,0x00,0x35, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x14, + 0x00,0x00,0x00,0x00, + 0x01, + + 0x00,0x00,0x00,0x10, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x00,0x00, + 0x43}; + + byte testPackRVC[53] = {0}; + PackMessage msg_pack; + + //RVC + MSG_RVC msg_rvc; + + + msg_rvc.SetSerial(1); + + msg_rvc.SetGUID(testParamO); + CPPUNIT_ASSERT(memcmp(msg_rvc.GetGUID(),testParamO,sizeof(byte) * 16) == 0); + //CPPUNIT_ASSERT(msg_rvc.SetCmlListLen(testComLenRVC,1)); + msg_rvc.SetMachineAddress(testParamO,16); + CPPUNIT_ASSERT(memcmp(msg_rvc.GetMachineAddress(),testParamO,16) == 0); + + CPPUNIT_ASSERT(msg_pack.Pack(&msg_rvc,testPackRVC,msg_pack.GetMessageLen(&msg_rvc)) != -1); + + //ȷԱ + CPPUNIT_ASSERT(memcmp(testRVC,testPackRVC,sizeof(testRVC)) == 0); + + CPPUNIT_ASSERT(true); + } + + void MSGRLIPackTest() + { + byte testParamO [] = {0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02}; + byte testParamT [] = {0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03}; + byte testParamS [] = {0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04}; + + byte testRLI [] = {0x56, + 0x00, + 0x00,0x01, + 0x00,0x00,0x00,0x5D, + + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x16, + 0x00,0x00,0x00,0x00, + + 0x03, + + 0x00,0x00,0x00,0x10, + 0x00,0x00,0x00,0x10, + 0x00,0x00,0x00,0x10, + + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + + 0x00,0x00, + 0x43}; + + byte testPackRLI[100] = {0}; + //RLI + MSG_RLI msg_rli; + PackMessage msg_pack; + + msg_rli.SetSerial(1); + CPPUNIT_ASSERT(msg_rli.GetSerial() == 1); + + msg_rli.SetGUID(testParamO); + CPPUNIT_ASSERT(memcmp(msg_rli.GetGUID(),testParamO,sizeof(byte) * 16) == 0); + + //CPPUNIT_ASSERT(msg_rli.SetCmlListLen(testComLenRLI,3)); + + msg_rli.SetVerificationCode(testParamO,16); + CPPUNIT_ASSERT(memcmp(msg_rli.GetVerificationCode(),testParamO,sizeof(byte) * 16) == 0); + + msg_rli.SetAccountNumber(testParamT,16); + CPPUNIT_ASSERT(memcmp(msg_rli.GetAccountNumber(),testParamT,16) == 0); + + msg_rli.SetPassword(testParamS,16); + CPPUNIT_ASSERT(memcmp(msg_rli.GetPassword(),testParamS,16) == 0); + CPPUNIT_ASSERT(msg_pack.Pack(&msg_rli,testPackRLI,msg_pack.GetMessageLen(&msg_rli)) != -1); + + + //ȷԱ + CPPUNIT_ASSERT(memcmp(testRLI,testPackRLI,sizeof(testRLI)) == 0); + + CPPUNIT_ASSERT(true); + } + + void MSGRPSPackTest() + { + byte testParamO [] = {0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02}; + byte testParamT [] = {0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03}; + byte testParamS [] = {0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04}; + + + byte testRPS [] = {0x56, + 0x00, + 0x00,0x01, + 0x00,0x00,0x00,0x67, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x18, + 0x00,0x00,0x00,0x00, + + 0x05, + + 0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x10, + 0x00,0x00,0x00,0x10, + 0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x10, + + 0x01, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + + 'A', + + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + + 0x00,0x00, + 0x43}; + + byte testPackRPS[120] = {0}; + + //RPS + MSG_RPS msg_rps; + PackMessage msg_pack; + + msg_rps.SetSerial(1); + CPPUNIT_ASSERT(msg_rps.GetSerial() == 1); + + msg_rps.SetGUID(testParamO); + CPPUNIT_ASSERT(memcmp(msg_rps.GetGUID(),testParamO,sizeof(byte) * 16) == 0); + + //CPPUNIT_ASSERT(msg_rps.SetCmlListLen(testComLenRPS,5)); + + msg_rps.SetRank(0x01); + CPPUNIT_ASSERT(msg_rps.GetRank() == 0x01); + + msg_rps.SetNickname(testParamO,16); + CPPUNIT_ASSERT(memcmp(msg_rps.GetNickname(),testParamO,sizeof(byte) * 16) == 0); + + msg_rps.SetAutograph(testParamT,16); + CPPUNIT_ASSERT(memcmp(msg_rps.GetAutograph(),testParamT,sizeof(byte) * 16) == 0); + + msg_rps.SetHeadForm('A'); + CPPUNIT_ASSERT(msg_rps.GetHeadForm() == 'A'); + + msg_rps.SetHeadPortrait(testParamS,16); + CPPUNIT_ASSERT(memcmp(msg_rps.GetHeadPortrait(),testParamS,sizeof(byte) * 16) == 0); + + CPPUNIT_ASSERT(msg_pack.Pack(&msg_rps,testPackRPS,msg_pack.GetMessageLen(&msg_rps)) != -1); + + //ȷԱ + + CPPUNIT_ASSERT(memcmp(testRPS,testPackRPS,sizeof(testRPS)) == 0); + + CPPUNIT_ASSERT(true); + + } + + void MSGAPSPackTest() + { + byte testParamO [] = {0x01,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02}; + byte testParamT [] = {0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03}; + byte testParamS [] = {0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04}; + + byte testAPS [] = {0x56, + 0x00, + 0x00,0x01, + 0x00,0x00,0x00,0x35, + + 0x01,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x19, + 0x00,0x00,0x00,0x00, + 0x01, + + 0x00,0x00,0x00,0x10, + + 0x01,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x00,0x00, + 0x43}; + + byte testPackAPS[100] = {0}; + //APS + MSG_APS msg_aps; + PackMessage msg_pack; + + msg_aps.SetSerial(1); + + CPPUNIT_ASSERT(msg_aps.GetSerial() == 1); + + msg_aps.SetGUID(testParamO); + CPPUNIT_ASSERT(memcmp(msg_aps.GetGUID(),testParamO,sizeof(byte) * 16) == 0); + + //CPPUNIT_ASSERT(msg_aps.SetCmlListLen(testComLenAPS,1)); + + + msg_aps.SetMessageSynchro(testParamO,16); + CPPUNIT_ASSERT(memcmp(msg_aps.GetMessageSynchro(),testParamO,sizeof(byte) * 16) == 0); + + CPPUNIT_ASSERT(msg_pack.Pack(&msg_aps,testPackAPS,msg_pack.GetMessageLen(&msg_aps)) != -1); + + //ȷԱ + int index = 0; + for (;index < sizeof(testAPS); index++) + { + if (testAPS[index] != testPackAPS[index]) + { + break; + } + + } + CPPUNIT_ASSERT(memcmp(testAPS,testPackAPS,sizeof(testAPS)) == 0); + + CPPUNIT_ASSERT(true); + } + + void MSGALIPackTest() + { + byte testParamO [] = {0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02}; + byte testParamT [] = {0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03}; + byte testParamS [] = {0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04}; + + byte testALI [] = {0x56, + 0x00, + 0x00,0x01, + 0x00,0x00,0x00,0x4E, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x17, + 0x00,0x00,0x00,0x00, + + 0x03, + + 0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x10, + 0x00,0x00,0x00,0x10, + + 0x00, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + + 0x00,0x00, + 0x43}; + + byte testPackALI[100] = {0}; + + //ALI + MSG_ALI msg_ali; + PackMessage msg_pack; + + msg_ali.SetSerial(1); + CPPUNIT_ASSERT(msg_ali.GetSerial() == 1); + + msg_ali.SetGUID(testParamO); + CPPUNIT_ASSERT(memcmp(msg_ali.GetGUID(),testParamO,sizeof(byte) * 16) == 0); + + //CPPUNIT_ASSERT(msg_ali.SetCmlListLen(testComLenALI,3)); + + msg_ali.SetLoginResult(0x0); + CPPUNIT_ASSERT(msg_ali.GetLoginResult() == 0x0); + + msg_ali.SetToken(testParamO,16); + //CPPUNIT_ASSERT(memcmp(msg_ali.GetToken(),testParamO,sizeof(byte) * 16) == 0); + + msg_ali.SetATLGUID(testParamT,16); + CPPUNIT_ASSERT(memcmp(msg_ali.GetATLGUID(),testParamT,sizeof(byte) * 16) == 0); + CPPUNIT_ASSERT(msg_pack.GetMessageLen(&msg_ali) == sizeof (testALI)); + CPPUNIT_ASSERT(msg_pack.Pack(&msg_ali,testPackALI,msg_pack.GetMessageLen(&msg_ali)) != -1); + + //ȷԱ + CPPUNIT_ASSERT(memcmp(testALI,testPackALI,sizeof(testALI)) == 0); + + CPPUNIT_ASSERT(true); + } + + void MSGACIPackTest() + { + byte testParamO [] = {0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02}; + byte testParamT [] = {0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03}; + byte testParamS [] = {0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04}; + + byte testACI [] = {0x56, + 0x00, + 0x00,0x01, + 0x00,0x00,0x00,0x8D, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x21, + 0x00,0x00,0x00,0x00, + + 0x0A, + + 0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x10, + 0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x10, + 0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x08, + 0x00,0x00,0x00,0x04, + + 0x00,0x00,0x00,0x01, + + 0x00,0x00,0x00,0x01, + + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, + + 0x00,0x00,0x00,0x01, + + 0x00,0x00,0x00,0x01, + + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, + + 0x00,0x00,0x00,0x01, + + 0x00,0x00,0x00,0x01, + + 0x00,0x00,0x00,0x0A, + 0x00,0x00,0x00,0x0B, + + 0x00,0x00,0x00,0x01, + + 0x00,0x00, + 0x43}; + + byte testPackACI[141] = {0}; + + //ACI + MSG_ACI msg_aci; + PackMessage msg_pack; + + + + msg_aci.SetSerial(1); + CPPUNIT_ASSERT(msg_aci.GetSerial() == 1); + + msg_aci.SetGUID(testParamO); + CPPUNIT_ASSERT(memcmp(msg_aci.GetGUID(),testParamO,sizeof(byte) * 16) == 0); + + msg_aci.SetRoomID(1); + CPPUNIT_ASSERT(msg_aci.GetRoomID() == 1); + + msg_aci.SetRoomManageID(1); + CPPUNIT_ASSERT(msg_aci.GetRoomManageID() == 1); + + msg_aci.SetRoomName(testParamO,16); + CPPUNIT_ASSERT(memcmp(msg_aci.GetRoomName(),testParamO,sizeof(byte) * 16) == 0); + + msg_aci.SetRoomPassword(testParamT,16); + CPPUNIT_ASSERT(memcmp(msg_aci.GetRoomPassword(),testParamT,sizeof(byte) * 16) == 0); + + std::vector inList; + std::vector outList; + inList.push_back(10); + inList.push_back(11); + msg_aci.SetRoomPeopleList(inList); + +/* + msg_aci.GetRoomPeopleList(outList); + CPPUNIT_ASSERT(outList[0] == 10); + CPPUNIT_ASSERT(outList[1] == 11);*/ + + msg_aci.SetRoomPeopleNum(1); + CPPUNIT_ASSERT(msg_aci.GetRoomPeopleNum() == 1); + + msg_aci.SetRoomPeopleNumMax(1); + CPPUNIT_ASSERT(msg_aci.GetRoomPeopleNumMax() == 1); + + msg_aci.SetRoomRank(1); + CPPUNIT_ASSERT(msg_aci.GetRoomRank() == 1); + + msg_aci.SetRoomState(1); + CPPUNIT_ASSERT(msg_aci.GetRoomState() == 1); + + msg_aci.SetRoomType(1); + CPPUNIT_ASSERT(msg_aci.GetRoomType() == 1); + + + CPPUNIT_ASSERT(msg_pack.GetMessageLen(&msg_aci) == sizeof (testACI)); + CPPUNIT_ASSERT(msg_pack.Pack(&msg_aci,testPackACI,msg_pack.GetMessageLen(&msg_aci)) != -1); + + + //int a = CheckMsgTrue(testACI,testPackACI,sizeof(testACI)); + CPPUNIT_ASSERT(memcmp(testACI,testPackACI,sizeof(testACI)) == 0); + + CPPUNIT_ASSERT(true); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION ( testPackMessage ); +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(testPackMessage, "testPackMessage"); + +#endif \ No newline at end of file diff --git a/Client/Client/CppUnitTest/testRunner.cpp b/Client/Client/CppUnitTest/testRunner.cpp new file mode 100644 index 00000000..acc881e6 --- /dev/null +++ b/Client/Client/CppUnitTest/testRunner.cpp @@ -0,0 +1,28 @@ +#ifdef CPPTEST +#include "Stdafx.h" +#include "testRunner.h" + +#include +#include +#include +#include +#include +#include + +VOID CTestRunner::StartTest(XMessage_StartTest* msg) +{ + CppUnit::TestResult controller; + CppUnit::TestResultCollector result; + + CppUnit::TextUi::TestRunner runner; + CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry(); + runner.addTest( registry.makeTest() ); + runner.eventManager().addListener( &result ); + runner.run(); + + std::ofstream xmlFileOut("cpptestresults.xml"); + CppUnit::XmlOutputter xmlOut(&result, xmlFileOut); + xmlOut.write(); +} + +#endif \ No newline at end of file diff --git a/Client/Client/CppUnitTest/testRunner.h b/Client/Client/CppUnitTest/testRunner.h new file mode 100644 index 00000000..13690fb0 --- /dev/null +++ b/Client/Client/CppUnitTest/testRunner.h @@ -0,0 +1,14 @@ +#include "../FrameWork/FrameBase.hpp" + +class CTestRunner : public CFrameBase +{ +public: + CTestRunner():CFrameBase(module_CppTestMain) + {}; + + VOID StartTest(XMessage_StartTest* msg); + + Begin_XMessage(CTestRunner) + OnXMessage(XMessage_StartTest,StartTest) + End_XMessage() +}; \ No newline at end of file diff --git a/Client/Client/FrameWork/Factory.cpp b/Client/Client/FrameWork/Factory.cpp new file mode 100644 index 00000000..90896a96 --- /dev/null +++ b/Client/Client/FrameWork/Factory.cpp @@ -0,0 +1,53 @@ +#include "stdafx.h" +#include "Factory.h" + +#include "../Logic/room/Room.h" +#include "../Logic/room/RoomMgr.h" +#include "../Logic/UserSession/LoginImpl.h" + +#include "../GUI/LoginWin/BKWinLogin.h" +#include "../GUI/RoomListWin/BKWinRoomList.h" +#include "../gui/RoomWin/BKWinClassroom.h" + +#ifdef CPPTEST +#include "../CppUnitTest/testRunner.h" +#endif + +ResultCode CFrameModuleFactory::CreateFrameModule( FrameModule module,IFrameModule** ppModule ) +{ + if (!ppModule) + { + return Result_InvalidParam; + } + *ppModule = NULL; + switch(module) + { + case module_LoginData: + *ppModule = new CLoginImpl; + break; + case module_LoginWin: + *ppModule = new CLoginWnd; + break; + case module_RoomListData: + *ppModule = new CRoomMgr; + break; + case module_RoomListWin: + *ppModule = new CRoomListWnd; + break; + case module_ClassroomWinData: + *ppModule = new CRoomBase; + break; + case module_ClassroomWin: + *ppModule = new CClassroomWnd; + break; +#ifdef CPPTEST + case module_CppTestMain: + *ppModule = new CTestRunner; + break; +#endif + default: + ATLASSERT(FALSE && "invalid module"); + return Result_NotFound; + } + return Result_Success; +} diff --git a/Client/Client/FrameWork/Factory.h b/Client/Client/FrameWork/Factory.h new file mode 100644 index 00000000..5aa5577f --- /dev/null +++ b/Client/Client/FrameWork/Factory.h @@ -0,0 +1,8 @@ +#pragma once +#include "IFrameWork.h" + +class CFrameModuleFactory +{ +public: + static ResultCode CreateFrameModule(FrameModule module,IFrameModule** ppModule); +}; diff --git a/Client/Client/FrameWork/FrameBase.hpp b/Client/Client/FrameWork/FrameBase.hpp new file mode 100644 index 00000000..983789c4 --- /dev/null +++ b/Client/Client/FrameWork/FrameBase.hpp @@ -0,0 +1,130 @@ +#pragma once +#include "IFrameWork.h" +#include "IRefCountImpl.h" +#include +#include + +struct XMessage : public IRefCountImpl +{ + virtual VOID GetID(CString& id) = 0; + + XMessage() + : destModule(module_Any) + , srcModule(module_Any) + , result(Result_NotSet) + { + } + + VOID MarkProcessed(ResultCode result) + { + ATLASSERT(result != Result_NotSet); + this->result = result; + } + BOOL IsProcessed() + { + return result != Result_NotSet; + } + + FrameModule destModule; + FrameModule srcModule; + + ResultCode result; +}; + +class CFrameBase : public IFrameModule +{ +public: + CFrameBase(FrameModule module) + : m_moduleType(module) + { + } + virtual ~CFrameBase() + { + } + ResultCode SendXMessage(XMessage* msg) + { + ATLASSERT(msg); + IFrameWork* pFrameWork; + Global->GetIFrameModule(&pFrameWork); + Global->PtrAssert(pFrameWork); + return pFrameWork->SendXMessage(msg); + } + FrameModule GetModuleType() + { + return m_moduleType; + } + virtual BOOL IsView() + { + return GetModuleType()>module_ViewBegin && GetModuleType()GetID(msgID); \ + } \ + else \ + { \ + pListMsg = dynamic_cast(pMsgGetList); \ + if (!pListMsg) \ + { \ + return Result_FatalError; \ + } \ + } \ + +#define OnXMessage(_msg,_proc) \ + if (pListMsg) \ + { \ + CString id; \ + _msg::Static_GetID(id); \ + pListMsg->msgIDList.push_back(id); \ + } \ + if ( pmsg && _msg::Static_IsTypeOf(msgID) ) \ + { \ + _proc((_msg*)pmsg); \ + } + +#define Chain_XMessage(_class) \ + {} \ + { \ + _class::ProcessXMessage(pmsg); \ + } + +#define End_XMessage() \ + {} \ + return Result_Success; \ + } + +#define ImTheMessageOf(_msg) \ +public: \ + virtual VOID GetID(CString& id) \ + { \ + Static_GetID(id); \ + } \ + static VOID Static_GetID(CString& id) \ + { \ + id = #_msg; \ + } \ + static BOOL Static_IsTypeOf(LPCTSTR id) \ + { \ + CString tempID; \ + Static_GetID(tempID); \ + return (tempID.CompareNoCase(id)==0)? TRUE: FALSE; \ + } diff --git a/Client/Client/FrameWork/FrameWork.cpp b/Client/Client/FrameWork/FrameWork.cpp new file mode 100644 index 00000000..d2bb8f5b --- /dev/null +++ b/Client/Client/FrameWork/FrameWork.cpp @@ -0,0 +1,239 @@ +#include "stdafx.h" +#include "FrameWork.h" +#include "Factory.h" + +CFrameWork::CFrameWork() +{ + +} + +CFrameWork::~CFrameWork() +{ + +} + +ResultCode CFrameWork::Initialize( IModule* UpperFrame/*=NULL*/ ) +{ +#ifndef CPPTEST + _InitUILib(); +#else + _InitTest(); +#endif + _LoadModule(); + return Result_Success; +} + +ResultCode CFrameWork::UnInitialize() +{ + _ClearModule(); + return Result_Success; +} + +ResultCode CFrameWork::Run() +{ +#ifndef CPPTEST + XMessage_FrameStart firstMessage; +#else + XMessage_StartTest firstMessage; +#endif + SendXMessage(&firstMessage); + return Result_Success; +} + +ResultCode CFrameWork::Terminate() +{ + return Result_Success; +} + +ResultCode CFrameWork::RegisterModule( IFrameModule* iModule ) +{ + FrameModule module; + module = iModule->GetModuleType(); + ATLASSERT(module != module_Invalid); + Util::CAutoCS ac(m_mapcs); + m_map[module] = iModule; + + _GetModulesListenList(module); + iModule->Initialize(this); + iModule->Run(); + return Result_Success; +} + +ResultCode CFrameWork::GetModule( IFrameModule** piModule,FrameModule module ) +{ + Util::CAutoCS ac(m_mapcs); + if (piModule == NULL) + { + return Result_InvalidParam; + } + IFrameModule* var = _FindModule(module); + if (var) + { + *piModule = var; + return Result_Success; + } + return Result_Fail; +} + +ResultCode CFrameWork::RemoveModule( IFrameModule* iModule ) +{ + Util::CAutoCS ac(m_mapcs); + + for (auto i=m_map.begin(); i!=m_map.end();) + { + if (!iModule || (i->second==iModule)) + { + if (i->second) + { + i->second->Terminate(); + i->second->UnInitialize(); + } + i = m_map.erase(i); + } + else + { + ++i; + } + } + return Result_Success; +} + +IFrameModule* CFrameWork::_FindModule( FrameModule module ) +{ + Util::CAutoCS ac(m_mapcs); + auto i = m_map.find(module); + if (i != m_map.end()) + { + return i->second; + } + return NULL; +} + +ResultCode CFrameWork::SendXMessage( XMessage* pMsg ) +{ + Util::CAutoCS ac(m_mapcs); + if (pMsg->destModule == module_Any) + { // broadcast + Util::CAutoCS ac(m_msgMapCS); + + CString strID; + pMsg->GetID(strID); + auto& moduleSet = m_msgMap[strID]; + for (auto i=moduleSet.begin(); i!=moduleSet.end() && !pMsg->IsProcessed(); ++i) + { + IFrameModule* pModule = m_map[*i]; + if (pModule) + { + pModule->ProcessXMessage(pMsg); + } + } + } + else + { + auto i = m_map.find(pMsg->destModule); + if (i != m_map.end()) + { + i->second->ProcessXMessage(pMsg); + } + else + { + return Result_Fail; + } + } + return Result_Success; +} + +VOID CFrameWork::_ClearModule() +{ + RemoveModule(NULL); +} + +VOID CFrameWork::_LoadModule() +{ + int i; + for (i = module_DataBegin + 1; i < module_DataEnd; ++i) + { + _LoadModule(static_cast(i)); + } + +#ifndef CPPTEST + + for (i = module_ViewBegin + 1; i < module_ViewEnd; ++i) + { + _LoadModule(static_cast(i)); + } + +#else + + for (i = module_CppTestBegin + 1; i < module_CppTestEnd; ++i) + { + _LoadModule(static_cast(i)); + } + +#endif +} + +VOID CFrameWork::_LoadModule( FrameModule module ) +{ + IFrameModule *pModule=NULL; + CFrameModuleFactory::CreateFrameModule(module,&pModule); + if (pModule) + { + RegisterModule(pModule); + } +} + +VOID CFrameWork::_GetModulesListenList(FrameModule module) +{ + if (module == module_Any) + { + XMessage_GetListenList msg; + Util::CAutoCS ac(m_mapcs); + for (auto i=m_map.begin(); i!=m_map.end(); ++i) + { + msg.msgIDList.clear(); + i->second->ProcessXMessage(NULL,&msg); + + Util::CAutoCS ac(m_msgMapCS); + for (auto j=msg.msgIDList.begin(); j!=msg.msgIDList.end(); ++j) + { + m_msgMap[*j].insert( i->first ); + } + } + } + else + { + Util::CAutoCS ac(m_mapcs); + auto i = m_map.find(module); + if (i != m_map.end()) + { + XMessage_GetListenList msg; + i->second->ProcessXMessage(NULL,&msg); + + Util::CAutoCS ac(m_msgMapCS); + for (auto j=msg.msgIDList.begin(); j!=msg.msgIDList.end(); ++j) + { + m_msgMap[*j].insert( i->first ); + } + } + } +} + +VOID CFrameWork::_InitUILib() +{ + BkFontPool::SetDefaultFont(_T("Courier New"), -12); + BkSkin::LoadSkins(IDR_XML_SKIN_DEF); + BkStyle::LoadStyles(IDR_BK_STYLE_DEF); + CString strPath; + GetModuleFileName(nullptr,strPath.GetBuffer(MAX_PATH),MAX_PATH); + strPath.ReleaseBuffer(); + Util::Filesys::SplitPath(strPath,strPath,CString()); + strPath += BKWinResDir; + Global->Logf(LogFile_FrameWork,_T("ʼԴļ: %s"),strPath); + BkResManager::SetResourcePath(strPath); +} + +VOID CFrameWork::_InitTest() +{ +} + diff --git a/Client/Client/FrameWork/FrameWork.h b/Client/Client/FrameWork/FrameWork.h new file mode 100644 index 00000000..2de0a889 --- /dev/null +++ b/Client/Client/FrameWork/FrameWork.h @@ -0,0 +1,38 @@ +#pragma once +#include "IFrameWork.h" +#include +#include +#include +#include + +class CFrameWork : public IFrameWork +{ +public: + CFrameWork(); + ~CFrameWork(); +public: + virtual ResultCode Initialize(IModule* UpperFrame=NULL); + virtual ResultCode UnInitialize(); + virtual ResultCode Run(); + virtual ResultCode Terminate(); + virtual ResultCode RegisterModule (IFrameModule* iModule); + virtual ResultCode GetModule (IFrameModule** piModule,FrameModule module); + virtual ResultCode RemoveModule (IFrameModule* iModule); + virtual ResultCode SendXMessage (XMessage* pMsg); +private: + typedef std::map ModuleMap; + typedef std::map> XMessageMap; + + IFrameModule* _FindModule(FrameModule module); + VOID _InitUILib(); + VOID _InitTest(); + VOID _LoadModule(); + VOID _LoadModule(FrameModule module); + VOID _ClearModule(); + VOID _GetModulesListenList(FrameModule module=module_Any); +private: + ModuleMap m_map; + ATL::CCriticalSection m_mapcs; + XMessageMap m_msgMap; + ATL::CCriticalSection m_msgMapCS; +}; \ No newline at end of file diff --git a/VNOC/VNOC/GlobalCenter.cpp b/Client/Client/FrameWork/GlobalCenter.cpp similarity index 54% rename from VNOC/VNOC/GlobalCenter.cpp rename to Client/Client/FrameWork/GlobalCenter.cpp index 3cf0ca9b..17aee1d3 100644 --- a/VNOC/VNOC/GlobalCenter.cpp +++ b/Client/Client/FrameWork/GlobalCenter.cpp @@ -1,118 +1,151 @@ -#include "StdAfx.h" -#include "GlobalCenter.h" - -CGlobalCenter Global2; // ʵ -IGlobal* Global = &Global2; // Appȫַʽӿ - -CGlobalCenter::CGlobalCenter(void) -{ -} - - -CGlobalCenter::~CGlobalCenter(void) -{ -} - -HRESULT CGlobalCenter::Initialize( IModule* UpperFrame/*=NULL*/ ) -{ - _InitializeLog(); // еطlogԵȳʼ - _InitializeConfig(); - _InitializeNetCenter(); - return S_OK; -} - -HRESULT CGlobalCenter::UnInitialize() -{ - _UnInitializeNetCenter(); - _UnInitializeConfig(); - _UnInitializeLog(); - return S_OK; -} - -HRESULT CGlobalCenter::Run() -{ - return S_OK; -} - -HRESULT CGlobalCenter::Terminate() -{ - return S_OK; -} - -HRESULT CGlobalCenter::GetIConfig( IConfig** pConfig ) -{ - *pConfig = dynamic_cast(&m_config); - return S_OK; -} - -void CGlobalCenter::_InitializeConfig() -{ - UINT buffSize = MAX_PATH * sizeof(TCHAR); - GetModuleFileName(GetModuleHandle(NULL),m_configFilePath.GetBuffer(buffSize),buffSize); - m_configFilePath.ReleaseBuffer(); - int nPos=0; - Util::Filesys::GetDirFromPath(m_configFilePath,nPos); - m_configFilePath = m_configFilePath.Left(nPos); - - m_config.Initialize(NULL); - m_configFilePath += PathSplit; - m_configFilePath += CONFIGXMLFILE; - Global->Logf(LogFile_General,_T("XML·Ϊ:%s\n"),m_configFilePath); - m_config.LoadConfigFromXML(m_configFilePath); -} - -void CGlobalCenter::_UnInitializeConfig() -{ - m_config.SaveConfigToXML(); - m_config.UnInitialize(); -} - -HRESULT CGlobalCenter::CheckLastError(LPCTSTR helpStr) -{ - DWORD dw = GetLastError(); - CString str; - str.Format(_T("LastError : %d"),dw); - if (helpStr) - { - str.AppendFormat(_T("(%s)"),helpStr); - } - Log(LogFile_General,str); - return dw; -} - -HRESULT CGlobalCenter::PtrAssert( void* p ) -{ - ATLASSERT(p && "ָΪ"); - if (!p) - { - MessageBox(0,_T("ش󣬳˳ִС"),_T(""),0); - ExitProcess(8); - } - return S_OK; -} - -void CGlobalCenter::_InitializeNetCenter() -{ - m_netCenter.Initialize(NULL); - m_netCenter.Run(); -} - -void CGlobalCenter::_UnInitializeNetCenter() -{ - m_netCenter.Terminate(); - m_netCenter.UnInitialize(); -} - -HRESULT CGlobalCenter::GetINetCenter( INetCenter** pNetCenter ) -{ - *pNetCenter = dynamic_cast(&m_netCenter); - return S_OK; -} - -HRESULT CGlobalCenter::CriticalError( LPCTSTR message ) -{ - MessageBox(NULL,message,0,0); - TerminateProcess(GetCurrentProcess(),1); - return S_OK; -} - +#include "StdAfx.h" +#include "GlobalCenter.h" + +IGlobal* Global = NULL; // Appȫַʽӿ + +VOID IGlobal::GlobalDeliver() +{ + static CGlobalCenter globalCenter(_T("VNOC")); + Global = &globalCenter; +} + +CGlobalCenter::CGlobalCenter(void) +{ +} + +CGlobalCenter::~CGlobalCenter(void) +{ +} + +ResultCode CGlobalCenter::Initialize( IModule* UpperFrame/*=NULL*/ ) +{ + _InitializeLog(); // еطlogԵȳʼ + _InitializeConfig(); + _InitializeNetCenter(); + _InitializeFrameWork(); + return Result_Success; +} + +ResultCode CGlobalCenter::UnInitialize() +{ + _UnInitializeFrameWork(); + _UnInitializeNetCenter(); + _UnInitializeConfig(); + _UnInitializeLog(); + return Result_Success; +} + +ResultCode CGlobalCenter::Run() +{ + m_pFrameWork->Run(); + return Result_Success; +} + +ResultCode CGlobalCenter::Terminate() +{ + return Result_Success; +} + +ResultCode CGlobalCenter::GetIConfig( IConfig** pConfig ) +{ + *pConfig = dynamic_cast(&m_config); + return Result_Success; +} + +void CGlobalCenter::_InitializeConfig() +{ + UINT buffSize = MAX_PATH * sizeof(TCHAR); + GetModuleFileName(GetModuleHandle(NULL),m_configFilePath.GetBuffer(buffSize),buffSize); + m_configFilePath.ReleaseBuffer(); + int nPos=0; + Util::Filesys::GetDirFromPath(m_configFilePath,nPos); + m_configFilePath = m_configFilePath.Left(nPos); + + m_config.Initialize(NULL); + m_config.Run(); + m_configFilePath += PathSplit; + m_configFilePath += CONFIGXMLFILE; + Global->Logf(LogFile_General,_T("XML·Ϊ:%s\n"),m_configFilePath); + m_config.LoadConfigFromXML(m_configFilePath); +} + +void CGlobalCenter::_UnInitializeConfig() +{ + m_config.SaveConfigToXML(); + m_config.UnInitialize(); +} + +DWORD CGlobalCenter::CheckLastError(LPCTSTR helpStr) +{ + DWORD dw = GetLastError(); + CString str; + str.Format(_T("LastError : %d"),dw); + if (helpStr) + { + str.AppendFormat(_T("(%s)"),helpStr); + } + Log(LogFile_General,str); + return dw; +} + +ResultCode CGlobalCenter::PtrAssert( void* p ) +{ + ATLASSERT(p && "ָΪ"); + if (!p) + { + MessageBox(0,_T("ش󣬳˳ִС"),_T(""),0); + ExitProcess(8); + } + return Result_Success; +} + +void CGlobalCenter::_InitializeNetCenter() +{ + m_netCenter.Initialize(this); + m_netCenter.Run(); +} + +void CGlobalCenter::_UnInitializeNetCenter() +{ + m_netCenter.Terminate(); + m_netCenter.UnInitialize(); +} + +ResultCode CGlobalCenter::GetINetCenter( INetCenter** pNetCenter ) +{ + *pNetCenter = dynamic_cast(&m_netCenter); + return Result_Success; +} + +ResultCode CGlobalCenter::CriticalError( LPCTSTR message ) +{ + MessageBox(NULL,message,0,0); + TerminateProcess(GetCurrentProcess(),1); + return Result_Success; +} + +ResultCode CGlobalCenter::GetIFrameModule( IFrameWork** pFrame ) +{ + if (m_pFrameWork) + { + *pFrame = m_pFrameWork; + return Result_Success; + } + return Result_Fail; +} + +void CGlobalCenter::_InitializeFrameWork() +{ + m_pFrameWork = new CFrameWork; + PtrAssert(m_pFrameWork); + m_pFrameWork->Initialize(this); +} + +void CGlobalCenter::_UnInitializeFrameWork() +{ + if (m_pFrameWork) + { + m_pFrameWork->Terminate(); + m_pFrameWork->UnInitialize(); + } +} \ No newline at end of file diff --git a/Client/Client/FrameWork/GlobalCenter.h b/Client/Client/FrameWork/GlobalCenter.h new file mode 100644 index 00000000..66b4316b --- /dev/null +++ b/Client/Client/FrameWork/GlobalCenter.h @@ -0,0 +1,74 @@ +////////////////////////////////////////////////////////////////////////// +// ӦóȫݣϢȡ +#pragma once +#include "IGlobal.h" +#include "../config/Config.h" +#include "../net/Net.h" +#include "../util/BLog.h" +#include "../FrameWork/FrameWork.h" + +typedef std::map LogMap; +typedef std::map ThreadNameMap; + +class CGlobalCenter : public IGlobal +{ +public: + CGlobalCenter(CString appName){m_appName = appName;}; + ~CGlobalCenter(void); +private: + CGlobalCenter(void); + CGlobalCenter(const CGlobalCenter&){}; + CGlobalCenter& operator=(const CGlobalCenter&){}; +public: + virtual ResultCode Initialize(IModule* UpperFrame=NULL); + virtual ResultCode UnInitialize(); + virtual ResultCode Run(); + virtual ResultCode Terminate(); + // ȡýӿ + virtual ResultCode GetIConfig(IConfig** pConfig); + + virtual ResultCode Log(CString file,CString str,BOOL info=TRUE,BOOL endLine=TRUE); + virtual ResultCode Logf(CString file,LPCTSTR str,...); + virtual ResultCode Lognf(CString file,LPCTSTR str,...); + virtual ResultCode SetLog(CString file,BOOL bDbgView=TRUE,BOOL bConsole=FALSE); + virtual ResultCode LogPrefix(CString file,CString prefix,BOOL bAdd); + virtual ResultCode LogIndent(CString file,BOOL bAdd); + virtual ResultCode SetThreadName(CString name); + virtual ResultCode GetThreadName(DWORD threadID,CString& name); + virtual DWORD CheckLastError(LPCTSTR helpStr=NULL); + virtual ResultCode PtrAssert(void* p); + virtual ResultCode CriticalError(LPCTSTR message); + + virtual ResultCode GetINetCenter(INetCenter** pNetCenter); + + virtual ResultCode GetIFrameModule(IFrameWork** pFrame); +private: + void _InitializeConfig(); + void _UnInitializeConfig(); + + void _InitializeLog(); + void _UnInitializeLog(); + blog::CBLog* _GetLogInstance(CString file); + blog::CBLog* _CreateLogInstance(CString file,BOOL bDbgView=TRUE,BOOL bConsole=FALSE); + void _FillThreadNameToLogInstance(blog::CBLog* inst); + + void _InitializeNetCenter(); + void _UnInitializeNetCenter(); + + void _InitializeFrameWork(); + void _UnInitializeFrameWork(); +private: + CString m_appName; + + CConfigImpl m_config; + CNetCenter m_netCenter; + CFrameWork* m_pFrameWork; + CString m_configFilePath; + + LogMap m_log; + blog::CLogDeviceDBGView m_logdbgView; + blog::CLogDeviceConsole m_logConsole; + CString m_logPath; + + ThreadNameMap m_threadName; +}; diff --git a/VNOC/VNOC/GlobalDefine.h b/Client/Client/FrameWork/GlobalDefine.h similarity index 84% rename from VNOC/VNOC/GlobalDefine.h rename to Client/Client/FrameWork/GlobalDefine.h index 61e27c55..a527fe8e 100644 --- a/VNOC/VNOC/GlobalDefine.h +++ b/Client/Client/FrameWork/GlobalDefine.h @@ -1,35 +1,40 @@ -#pragma once - -////////////////////////////////////////////////////////////////////////// -// Լ - -#define VNOC_Private public - -////////////////////////////////////////////////////////////////////////// -// - -#define PRODUCT_NAME _T("VNOC") -#define PathSplit _T('\\') - -#define CONFIGXMLFILE _T("config.xml") -#define ConfigPathSplit _T('/') // xPathеķָ - -#define _LogFileExt _T(".log") -#define _LogFileMaxSizeBytes 64*1024*1024 -#define _LogFormatBufferSize 1024 -#define LogMask_ALL 0xffffffff - -////////////////////////////////////////////////////////////////////////// -// log - -#define LogFile_General _T("General") -#define LogFile_Config _T("Config") -#define LogFile_Scintilla _T("Scintilla") -#define LogFile_Net _T("Net") - -class CGlobalUtilBase -{ -public: - CString m_file; - CString m_prefix; -}; +#pragma once +#include + +////////////////////////////////////////////////////////////////////////// +// Լ + +#define VNOC_Private public + +////////////////////////////////////////////////////////////////////////// +// + +#define PRODUCT_NAME _T("VNOC") +#define PathSplit _T('\\') + +#define CONFIGXMLFILE _T("config.xml") +#define ConfigPathSplit _T('/') // xPathеķָ + +#define _LogFileExt _T(".log") +#define _LogFileMaxSizeBytes 64*1024*1024 +#define _LogFormatBufferSize 1024 +#define LogMask_ALL 0xffffffff + +////////////////////////////////////////////////////////////////////////// +// FrameWork + +////////////////////////////////////////////////////////////////////////// +// log + +#define LogFile_General _T("General") +#define LogFile_Config _T("Config") +#define LogFile_FrameWork _T("FrameWork") +#define LogFile_Scintilla _T("Scintilla") +#define LogFile_Net _T("Net") + +class CGlobalUtilBase +{ +public: + CString m_file; + CString m_prefix; +}; diff --git a/VNOC/VNOC/GlobalLog.cpp b/Client/Client/FrameWork/GlobalLog.cpp similarity index 78% rename from VNOC/VNOC/GlobalLog.cpp rename to Client/Client/FrameWork/GlobalLog.cpp index 1a4a5fb0..62b34e68 100644 --- a/VNOC/VNOC/GlobalLog.cpp +++ b/Client/Client/FrameWork/GlobalLog.cpp @@ -1,283 +1,289 @@ -#include "stdafx.h" -#include "GlobalCenter.h" - -////////////////////////////////////////////////////////////////////////// -// ֲutil - -void _CheckFileSize(LPCTSTR file,long size) -{ - long fileSize = 0; - FILE *fp; - _tfopen_s(&fp,file,_T("rb")); - if (fp) - { - fseek(fp,0,SEEK_END); - fileSize = ftell(fp); - fclose(fp); - } - if (fileSize > size) - { - DeleteFile(file); - } -} - -////////////////////////////////////////////////////////////////////////// -// ʵgloballogӿ - -void CGlobalCenter::_InitializeLog() -{ - Util::Filesys::GetSpecialPath(CSIDL_APPDATA,m_logPath); - if (!m_logPath.IsEmpty()) - { - m_logPath += PathSplit; - m_logPath += PRODUCT_NAME; - m_logPath += PathSplit; - Util::Filesys::ForceCreateDir(m_logPath); - } -} - -void CGlobalCenter::_UnInitializeLog() -{ - LogMap::iterator i; - i = m_log.begin(); - while (i != m_log.end()) - { - i->second->RemoveDevice(BLOG_DBGVIEW); - i->second->RemoveDevice(BLOG_CONSOLE); - delete i->second; - ++i; - } -} - -HRESULT CGlobalCenter::Log( CString file,CString str,BOOL info,BOOL endLine) -{ - blog::CBLog* log = _GetLogInstance(file); - if (log) - { - log->Log(LogMask_ALL,str,info,endLine); - } - else - { - ASSERT(FALSE && L"޷ȡlog"); - } - return S_OK; -} - -HRESULT CGlobalCenter::Logf( CString file,LPCTSTR str,... ) -{ - static TCHAR buffer[_LogFormatBufferSize]; - buffer[_LogFormatBufferSize-1] = L'\0'; - va_list vl; - va_start(vl,str); - _vstprintf_s(buffer,str,vl); - va_end(vl); - return Log(file,buffer,TRUE,FALSE); -} - -HRESULT CGlobalCenter::Lognf( CString file,LPCTSTR str,... ) -{ - static TCHAR buffer[_LogFormatBufferSize]; - buffer[_LogFormatBufferSize-1] = L'\0'; - va_list vl; - va_start(vl,str); - _vstprintf_s(buffer,str,vl); - va_end(vl); - return Log(file,buffer,FALSE,FALSE); -} - -HRESULT CGlobalCenter::SetLog( CString file,BOOL bDbgView/*=TRUE*/,BOOL bConsole/*=FALSE*/ ) -{ - LogMap::iterator i; - i = m_log.begin(); - if (i != m_log.end()) - { - if (i->second) - { - LogMap::iterator i; - i = m_log.find(file); - if (i != m_log.end()) - { - if (bDbgView) - { - i->second->AddDevice(BLOG_DBGVIEW,&m_logdbgView); - } - else - { - i->second->RemoveDevice(BLOG_DBGVIEW); - } - if (bConsole) - { - i->second->AddDevice(BLOG_CONSOLE,&m_logConsole); - } - else - { - i->second->RemoveDevice(BLOG_CONSOLE); - } - return S_OK; - } - } - } - return S_OK; -} - -HRESULT CGlobalCenter::SetThreadName( CString name ) -{ - m_threadName[GetCurrentThreadId()] = name; - LogMap::iterator i; - i = m_log.begin(); - while (i != m_log.end()) - { - i->second->SetThreadName(GetCurrentThreadId(),name); - ++i; - } - return S_OK; -} - -HRESULT CGlobalCenter::GetThreadName( DWORD threadID,CString& name ) -{ - ThreadNameMap::iterator i; - i = m_threadName.find(threadID); - if (i != m_threadName.end()) - { - name = i->second; - return S_OK; - } - return S_FALSE; -} - -HRESULT CGlobalCenter::LogPrefix( CString file,CString prefix,BOOL bAdd ) -{ - blog::CBLog* log = _GetLogInstance(file); - if (log) - { - if (bAdd) - { - log->AddPrefix(prefix); - } - else - { - log->RemoveLastPrefix(); - } - } - return S_OK; -} - -HRESULT CGlobalCenter::LogIndent( CString file,BOOL bAdd ) -{ - blog::CBLog* log = _GetLogInstance(file); - if (log) - { - if (bAdd) - { - log->IncreaseIndent(); - } - else - { - log->DecreaseIndent(); - } - } - return S_OK; -} - -blog::CBLog* CGlobalCenter::_GetLogInstance(CString file) -{ - LogMap::iterator i; - i = m_log.find(file); - if (i != m_log.end()) - { - return (i->second); - } - else - { - return _CreateLogInstance(file); - } - return NULL; -} - -blog::CBLog* CGlobalCenter::_CreateLogInstance(CString file,BOOL bDbgView/* =TRUE */,BOOL bConsole/* =FALSE */) -{ - LogMap::iterator i; - i = m_log.find(file); - if (i != m_log.end()) - { - return i->second; - } - else - { - blog::CBLog*log = new blog::CBLog; - ASSERT(log); - if (log) - { - _FillThreadNameToLogInstance(log); - if (bDbgView) - { - log->AddDevice(BLOG_DBGVIEW,&m_logdbgView); - } - if (bConsole) - { - log->AddDevice(BLOG_CONSOLE,&m_logConsole); - } - CString fileName = m_logPath; - fileName += file; - fileName += _LogFileExt; - blog::CLogDeviceFile *logFile = new blog::CLogDeviceFile; - if (logFile) - { - _CheckFileSize(fileName,_LogFileMaxSizeBytes); - BOOL bResult = logFile->Open(fileName); - ATLASSERT(bResult && "logļʧ!"); - if (bResult) - { - log->AddDevice(BLOG_FILE,logFile); - } - else - { - DWORD dw = GetLastError(); - dw = dw; - } - } - m_log.insert(std::make_pair(file,log)); - return log; - } - } - ASSERT(FALSE); - return NULL; -} - -void CGlobalCenter::_FillThreadNameToLogInstance( blog::CBLog* inst ) -{ - ASSERT(inst); - if (inst) - { - ThreadNameMap::iterator i; - for (i=m_threadName.begin(); i!=m_threadName.end(); ++i) - { - inst->SetThreadName(i->first,i->second); - } - } -} - -////////////////////////////////////////////////////////////////////////// - -CLogIndent::CLogIndent(CString file) -{ - m_file = file; - Global2.LogIndent(m_file,TRUE); -} - -CLogIndent::~CLogIndent() -{ - Global2.LogIndent(m_file,FALSE); -} - -CLogPrefix::CLogPrefix(CString file,CString prefix) -{ - m_file = file; - m_prefix = prefix; - Global2.LogPrefix(m_file,m_prefix,TRUE); -} - -CLogPrefix::~CLogPrefix() -{ - Global2.LogPrefix(m_file,m_prefix,FALSE); -} +#include "stdafx.h" +#include "GlobalCenter.h" +#include "../util/DbgHelper.hpp" + +////////////////////////////////////////////////////////////////////////// +// ֲutil + +void _CheckFileSize(LPCTSTR file,long size) +{ + long fileSize = 0; + FILE *fp; + _tfopen_s(&fp,file,_T("rb")); + if (fp) + { + fseek(fp,0,SEEK_END); + fileSize = ftell(fp); + fclose(fp); + } + if (fileSize > size) + { + DeleteFile(file); + } +} + +////////////////////////////////////////////////////////////////////////// +// ʵgloballogӿ + +void CGlobalCenter::_InitializeLog() +{ + Util::Filesys::GetSpecialPath(CSIDL_APPDATA,m_logPath); + if (!m_logPath.IsEmpty()) + { + m_logPath += PathSplit; + m_logPath += PRODUCT_NAME; + m_logPath += PathSplit; + Util::Filesys::ForceCreateDir(m_logPath); + } +} + +void CGlobalCenter::_UnInitializeLog() +{ + LogMap::iterator i; + i = m_log.begin(); + while (i != m_log.end()) + { + i->second->RemoveDevice(BLOG_DBGVIEW); + i->second->RemoveDevice(BLOG_CONSOLE); + delete i->second; + ++i; + } +} + +ResultCode CGlobalCenter::Log( CString file,CString str,BOOL info,BOOL endLine) +{ + blog::CBLog* log = _GetLogInstance(file); + if (log) + { + log->Log(LogMask_ALL,str,info,endLine); + } + else + { + ATLASSERT(FALSE && L"޷ȡlog"); + } + return Result_Success; +} + +ResultCode CGlobalCenter::Logf( CString file,LPCTSTR str,... ) +{ + static TCHAR buffer[_LogFormatBufferSize]; + buffer[_LogFormatBufferSize-1] = L'\0'; + va_list vl; + va_start(vl,str); + _vstprintf_s(buffer,str,vl); + va_end(vl); + return Log(file,buffer,TRUE,FALSE); +} + +ResultCode CGlobalCenter::Lognf( CString file,LPCTSTR str,... ) +{ + static TCHAR buffer[_LogFormatBufferSize]; + buffer[_LogFormatBufferSize-1] = L'\0'; + va_list vl; + va_start(vl,str); + _vstprintf_s(buffer,str,vl); + va_end(vl); + return Log(file,buffer,FALSE,FALSE); +} + +ResultCode CGlobalCenter::SetLog( CString file,BOOL bDbgView/*=TRUE*/,BOOL bConsole/*=FALSE*/ ) +{ + LogMap::iterator i; + i = m_log.begin(); + if (i != m_log.end()) + { + if (i->second) + { + LogMap::iterator i; + i = m_log.find(file); + if (i != m_log.end()) + { + if (bDbgView) + { + i->second->AddDevice(BLOG_DBGVIEW,&m_logdbgView); + } + else + { + i->second->RemoveDevice(BLOG_DBGVIEW); + } + if (bConsole) + { + i->second->AddDevice(BLOG_CONSOLE,&m_logConsole); + } + else + { + i->second->RemoveDevice(BLOG_CONSOLE); + } + return Result_Success; + } + } + } + return Result_Success; +} + +ResultCode CGlobalCenter::SetThreadName( CString name ) +{ + if (name.IsEmpty()) + { + return Result_Fail; + } + SetThreadNameToDebugInfo(GetCurrentThreadId(),CStringA(name)); + m_threadName[GetCurrentThreadId()] = name; + LogMap::iterator i; + i = m_log.begin(); + while (i != m_log.end()) + { + i->second->SetThreadName(GetCurrentThreadId(),name); + ++i; + } + return Result_Success; +} + +ResultCode CGlobalCenter::GetThreadName( DWORD threadID,CString& name ) +{ + ThreadNameMap::iterator i; + i = m_threadName.find(threadID); + if (i != m_threadName.end()) + { + name = i->second; + return Result_Success; + } + return Result_Fail; +} + +ResultCode CGlobalCenter::LogPrefix( CString file,CString prefix,BOOL bAdd ) +{ + blog::CBLog* log = _GetLogInstance(file); + if (log) + { + if (bAdd) + { + log->AddPrefix(prefix); + } + else + { + log->RemoveLastPrefix(); + } + } + return Result_Success; +} + +ResultCode CGlobalCenter::LogIndent( CString file,BOOL bAdd ) +{ + blog::CBLog* log = _GetLogInstance(file); + if (log) + { + if (bAdd) + { + log->IncreaseIndent(); + } + else + { + log->DecreaseIndent(); + } + } + return Result_Success; +} + +blog::CBLog* CGlobalCenter::_GetLogInstance(CString file) +{ + LogMap::iterator i; + i = m_log.find(file); + if (i != m_log.end()) + { + return (i->second); + } + else + { + return _CreateLogInstance(file); + } + return NULL; +} + +blog::CBLog* CGlobalCenter::_CreateLogInstance(CString file,BOOL bDbgView/* =TRUE */,BOOL bConsole/* =FALSE */) +{ + LogMap::iterator i; + i = m_log.find(file); + if (i != m_log.end()) + { + return i->second; + } + else + { + blog::CBLog*log = new blog::CBLog; + ATLASSERT(log); + if (log) + { + _FillThreadNameToLogInstance(log); + if (bDbgView) + { + log->AddDevice(BLOG_DBGVIEW,&m_logdbgView); + } + if (bConsole) + { + log->AddDevice(BLOG_CONSOLE,&m_logConsole); + } + CString fileName = m_logPath; + fileName += file; + fileName += _LogFileExt; + blog::CLogDeviceFile *logFile = new blog::CLogDeviceFile; + if (logFile) + { + _CheckFileSize(fileName,_LogFileMaxSizeBytes); + BOOL bResult = logFile->Open(fileName); + ATLASSERT(bResult && "logļʧ!"); + if (bResult) + { + log->AddDevice(BLOG_FILE,logFile); + } + else + { + DWORD dw = GetLastError(); + dw = dw; + } + } + m_log.insert(std::make_pair(file,log)); + return log; + } + } + ATLASSERT(FALSE); + return NULL; +} + +void CGlobalCenter::_FillThreadNameToLogInstance( blog::CBLog* inst ) +{ + ATLASSERT(inst); + if (inst) + { + ThreadNameMap::iterator i; + for (i=m_threadName.begin(); i!=m_threadName.end(); ++i) + { + inst->SetThreadName(i->first,i->second); + } + } +} + +////////////////////////////////////////////////////////////////////////// + +CLogIndent::CLogIndent(CString file) +{ + m_file = file; + Global->LogIndent(m_file,TRUE); +} + +CLogIndent::~CLogIndent() +{ + Global->LogIndent(m_file,FALSE); +} + +CLogPrefix::CLogPrefix(CString file,CString prefix) +{ + m_file = file; + m_prefix = prefix; + Global->LogPrefix(m_file,m_prefix,TRUE); +} + +CLogPrefix::~CLogPrefix() +{ + Global->LogPrefix(m_file,m_prefix,FALSE); +} diff --git a/Client/Client/FrameWork/IFrameWork.h b/Client/Client/FrameWork/IFrameWork.h new file mode 100644 index 00000000..f0a42150 --- /dev/null +++ b/Client/Client/FrameWork/IFrameWork.h @@ -0,0 +1,50 @@ +#pragma once +#include "IModule.h" +#include "ResDefine.h" + +enum FrameModule +{ + module_Invalid = -1, + module_FrameWork = 0, + module_Any, + + module_ViewBegin = 1024, + module_LoginWin, + module_RoomListWin, + module_ClassroomWin, + module_ViewEnd, + + module_DataBegin = 2048, + module_LoginData, + module_RoomListData, + module_ClassroomWinData, + module_DataEnd, + + module_CppTestBegin = 3072, + module_CppTestMain, + module_CppTestEnd, + module_CppTest_PrivateModule_Begin=3584, + module_CppTest_PrivateModule_End=4095, +}; + +struct XMessage; + +interface IFrameModule : public IModule +{ +public: + virtual FrameModule GetModuleType()=0; + virtual ResultCode SendXMessage(XMessage* msg)=0; + virtual ResultCode ProcessXMessage(XMessage* pMsg,XMessage* pMsgGetList=NULL)=0; +}; + +interface IFrameWork : public IModule +{ +public: + virtual ResultCode RegisterModule (IFrameModule* iModule)=0; + virtual ResultCode GetModule (IFrameModule** piModule,FrameModule module)=0; + virtual ResultCode RemoveModule (IFrameModule* iModule)=0; + virtual ResultCode SendXMessage (XMessage* msg)=0; +}; + +template +BOOL GetIFrameModule(){} diff --git a/VNOC/VNOC/IGlobal.h b/Client/Client/FrameWork/IGlobal.h similarity index 55% rename from VNOC/VNOC/IGlobal.h rename to Client/Client/FrameWork/IGlobal.h index d38254f0..8818942c 100644 --- a/VNOC/VNOC/IGlobal.h +++ b/Client/Client/FrameWork/IGlobal.h @@ -1,67 +1,75 @@ -#pragma once -// ȫֹĽӿ -#include "IModule.h" -#include "IConfig.h" -#include "INet.h" -#include "GlobalDefine.h" - -interface IGlobal:public IModule -{ -public: - ////////////////////////////////////////////////////////////////////////// - // ӿ - STDMETHOD( GetIConfig(IConfig** pConfig) = 0); - STDMETHOD( GetINetCenter(INetCenter** pNetCenter) = 0); - - ////////////////////////////////////////////////////////////////////////// - // logӿ - // printInfo ʱ䡢߳IDǰ׺ - // endLine Զس - STDMETHOD( Log(CString file,CString str,BOOL printInfo=TRUE,BOOL endLine=TRUE) = 0 ); - - // ǿƲԶس,ʱϢ - STDMETHOD( Logf(CString file,LPCTSTR str,...) = 0 ); - // ǿƲԶس,ʱϢ - STDMETHOD( Lognf(CString file,LPCTSTR str,...) = 0 ); - - // log - // bDebugView ǷͨdbgView鿴 - // bConsole ǷConsoleʾ - STDMETHOD( SetLog(CString file,BOOL bDbgView=TRUE,BOOL bConsole=FALSE) = 0 ); - - ////////////////////////////////////////////////////////////////////////// - // ߳ - // ߳ƣҪlogʹá - // ÿ̴߳Ӧӿڡ - STDMETHOD( SetThreadName(CString name) = 0 ); - STDMETHOD( GetThreadName(DWORD threadID,CString& name) = 0 ); - - ////////////////////////////////////////////////////////////////////////// - // GetLastError,Ὣͨlog - // helpStr ֺ - STDMETHOD( CheckLastError(LPCTSTR helpStr=NULL) = 0 ); - // ָǷΪNULLΪNULLΪش󣬲Ѻõ˳ - STDMETHOD( PtrAssert(void* p) = 0 ); - STDMETHOD( CriticalError(LPCTSTR message) = 0 ); - - ////////////////////////////////////////////////////////////////////////// - // Ϣ -}; - -extern IGlobal* Global; // ָģڶǺϷġ - -// ڵlogǰ׺ -class CLogPrefix : private CGlobalUtilBase -{ -public: - CLogPrefix(CString file,CString prefix); - ~CLogPrefix(); -}; - -// ڵlogԶ -class CLogIndent : private CGlobalUtilBase -{ -public: - CLogIndent(CString file); - ~CLogIndent(); -}; +#pragma once +// ȫֹĽӿ +#include "IModule.h" +#include "../config/IConfig.h" +#include "../net/INet.h" +#include "../FrameWork/IFrameWork.h" +#include "GlobalDefine.h" +#include "Error.hpp" + +interface IGlobal:public IModule +{ +public: + // Global󡣳Ҫ + static VOID GlobalDeliver(); + ////////////////////////////////////////////////////////////////////////// + // ӿ + virtual ResultCode GetIConfig(IConfig** pConfig) = 0; + virtual ResultCode GetINetCenter(INetCenter** pNetCenter) = 0; + virtual ResultCode GetIFrameModule(IFrameWork** pFrame) = 0; + + ////////////////////////////////////////////////////////////////////////// + // logӿ + // printInfo ʱ䡢߳IDǰ׺ + // endLine Զس + virtual ResultCode Log(CString file,CString str,BOOL printInfo=TRUE,BOOL endLine=TRUE) = 0; + + // ǿƲԶس,ʱϢ + virtual ResultCode Logf(CString file,LPCTSTR str,...) = 0; + // ǿƲԶس,ʱϢ + virtual ResultCode Lognf(CString file,LPCTSTR str,...) = 0; + + virtual ResultCode LogPrefix(CString file,CString prefix,BOOL bAdd) = 0; + virtual ResultCode LogIndent(CString file,BOOL bAdd) = 0; + + // log + // bDebugView ǷͨdbgView鿴 + // bConsole ǷConsoleʾ + virtual ResultCode SetLog(CString file,BOOL bDbgView=TRUE,BOOL bConsole=FALSE) = 0; + + ////////////////////////////////////////////////////////////////////////// + // ߳ + // ߳ƣҪlogʹá + // ÿ̴߳Ӧӿڡ + virtual ResultCode SetThreadName(CString name) = 0; + virtual ResultCode GetThreadName(DWORD threadID,CString& name) = 0; + + ////////////////////////////////////////////////////////////////////////// + // GetLastError,Ὣͨlog + // helpStr ֺ + virtual DWORD CheckLastError(LPCTSTR helpStr=NULL) = 0; + // ָǷΪNULLΪNULLΪش󣬲Ѻõ˳ + virtual ResultCode PtrAssert(void* p) = 0; + virtual ResultCode CriticalError(LPCTSTR message) = 0; + + ////////////////////////////////////////////////////////////////////////// + // Ϣ +}; + +extern IGlobal* Global; // ָģڶǺϷġ + +// ڵlogǰ׺ +class CLogPrefix : private CGlobalUtilBase +{ +public: + CLogPrefix(CString file,CString prefix); + ~CLogPrefix(); +}; + +// ڵlogԶ +class CLogIndent : private CGlobalUtilBase +{ +public: + CLogIndent(CString file); + ~CLogIndent(); +}; diff --git a/Client/Client/FrameWork/Main.cpp b/Client/Client/FrameWork/Main.cpp new file mode 100644 index 00000000..741ec32d --- /dev/null +++ b/Client/Client/FrameWork/Main.cpp @@ -0,0 +1,56 @@ +// VNOC.cpp : Defines the entry point for the application. +// + +#include "stdafx.h" + +//#define USE_VLD + +#ifdef USE_VLD +#ifdef _DEBUG +#pragma comment(lib,"VisualLeakDetector/lib/win32/vld.lib") +#include "VisualLeakDetector/include/vld.h" +#endif +#endif + +void VnocMain() +{ + IGlobal::GlobalDeliver(); + + ::CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); + Global->Initialize(); + + Global->Run(); + + Global->UnInitialize(); + ::CoUninitialize(); +} + +#ifndef CONSOLE +#include "../GUI/BKWin/wtl/atlapp.h" + +CAppModule _Module; + +int APIENTRY _tWinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) +{ + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + _Module.Init(NULL,hInstance); + + VnocMain(); + + _Module.Term(); + return 0; +} + +#else + +int _tmain(int argc, _TCHAR* argv[]) +{ + VnocMain(); + return 0; +} + +#endif diff --git a/Client/Client/FrameWork/ResDefine.h b/Client/Client/FrameWork/ResDefine.h new file mode 100644 index 00000000..e9b16bc7 --- /dev/null +++ b/Client/Client/FrameWork/ResDefine.h @@ -0,0 +1,26 @@ +#pragma once +// Դ + +#define BKWinResDir _T("../res") + +////////////////////////////////////////////////////////////////////////// +// Dialogs + +#define BKDlg_LoginWin _T("LoginWin.xml") +#define BKDlg_RoomListWin _T("RoomListWin.xml") +#define BKDlg_ClassroomWin _T("ClassroomWin.xml") + +#define DlgControl_LoginWin_Edit_UserName 10100 +#define DlgControl_LoginWin_Edit_PassWord 10101 +#define DlgControl_RoomListWin_Edit_ClsId 10111 + +#define DlgControl_LoginWin_ImgBtn_Minimize 10003 +#define DlgControl_LoginWin_ImgBtn_Maximize 10002 +#define DlgControl_LoginWin_ImgBtn_Close 10001 +#define DlgControl_RoomListWin_ImgBtn_Close 10001 +#define DlgControl_ClassroomWin_ImgBtn_Close 10001 + +#define DlgControl_LoginWin_Button_Login 10110 +#define DlgControl_RoomlistWin_Button_Search 10004 + +#define DlgControl_RoomListWin_Realwnd 1001 diff --git a/Client/Client/GUI/BKWin/bkconsole.h b/Client/Client/GUI/BKWin/bkconsole.h new file mode 100644 index 00000000..cc688cbf --- /dev/null +++ b/Client/Client/GUI/BKWin/bkconsole.h @@ -0,0 +1,138 @@ +#pragma once + +#include + +class bkconsole +{ +public: + bkconsole(LPCTSTR console_title = NULL, SHORT console_height = 300, SHORT console_width = 80, BOOL bAllowClose = FALSE) + { + if (is_existent) + return; + + ::AllocConsole(); + + if (console_title) + ::SetConsoleTitle(console_title); + + Attach(console_height, console_width); + + if (!bAllowClose) + DisableCloseButton(); + + is_existent = true; + } + + ~bkconsole() + { + if (is_existent) + { + ::FreeConsole(); + + is_existent = FALSE; + } + } + + static void __cdecl settextcolor(BOOL bRed, BOOL bGreen, BOOL bBlue, BOOL bIntensity) + { + ::SetConsoleTextAttribute( + ::GetStdHandle(STD_OUTPUT_HANDLE), + (bRed ? FOREGROUND_RED : 0) | + (bGreen ? FOREGROUND_GREEN : 0) | + (bBlue ? FOREGROUND_BLUE : 0) | + (bIntensity ? FOREGROUND_INTENSITY : 0) + ); + } + + static BOOL __cdecl printf(const TCHAR *format, ...) + { + CString strTrace; + va_list args; + DWORD dwWriten = 0; + + va_start(args, format); + strTrace.FormatV(format, args); + va_end(args); + + if (is_existent) + { + return ::WriteConsole(::GetStdHandle(STD_OUTPUT_HANDLE), strTrace, strTrace.GetLength(), &dwWriten, NULL); + } + else + { + DWORD dwAttrib = INVALID_FILE_ATTRIBUTES; + CString strPath; + + ::GetModuleFileName(NULL, strPath.GetBuffer(MAX_PATH + 1), MAX_PATH); + strPath.ReleaseBuffer(); + strPath = strPath.Left(strPath.ReverseFind(_T('\\')) + 1) + _T("Trace"); + + dwAttrib = ::GetFileAttributes(strPath); + if ((INVALID_FILE_ATTRIBUTES != dwAttrib) && (FILE_ATTRIBUTE_DIRECTORY == (FILE_ATTRIBUTE_DIRECTORY & dwAttrib))) + { + ::OutputDebugString(strTrace); + } + + return TRUE; + } + } + + static TCHAR _cdecl getch(HANDLE hEventExit = NULL) + { + INPUT_RECORD ir; + DWORD dwGet = 0; + TCHAR chRet = 0; + + if (!is_existent) + return 0; + + while (TRUE) + { + if (hEventExit) + { + dwGet = ::WaitForSingleObject(hEventExit, 0); + if (WAIT_OBJECT_0 == dwGet) + break; + } + + ::ReadConsoleInput(::GetStdHandle(STD_INPUT_HANDLE), &ir, 1, &dwGet); + +#ifdef _UNICODE + chRet = ir.Event.KeyEvent.uChar.UnicodeChar; +#else + chRet = ir.Event.KeyEvent.uChar.AsciiChar; +#endif + + ir.Event.KeyEvent.dwControlKeyState &= RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED; + + if (KEY_EVENT == ir.EventType && ir.Event.KeyEvent.bKeyDown && _T('\0') != chRet && 0 == ir.Event.KeyEvent.dwControlKeyState) + break; + } + + return chRet; + } + +private: + void Attach(SHORT console_height, SHORT console_width) + { + HANDLE hStd; + COORD size; + + hStd = ::GetStdHandle(STD_OUTPUT_HANDLE); + size.X = console_width; + size.Y = console_height; + ::SetConsoleScreenBufferSize(hStd, size); + } + + void DisableCloseButton() + { + HMENU hMenu = ::GetSystemMenu(::GetConsoleWindow(), FALSE); + + ::EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); + ::DestroyMenu(hMenu); + } + + static BOOL is_existent; +}; + +__declspec(selectany) BOOL bkconsole::is_existent = FALSE; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkres/NOTICE.txt b/Client/Client/GUI/BKWin/bkres/NOTICE.txt new file mode 100644 index 00000000..e06e3651 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkres/NOTICE.txt @@ -0,0 +1,9 @@ +============================================================ +Notices for files contained in this directory: +------------------------------------------------------------ +Copyright [2010] [liushuo AT conew.com] +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/Client/Client/GUI/BKWin/bkres/bkbmppool.h b/Client/Client/GUI/BKWin/bkres/bkbmppool.h new file mode 100644 index 00000000..5b4ee6f2 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkres/bkbmppool.h @@ -0,0 +1,66 @@ +////////////////////////////////////////////////////////////////////////// +// Class Name: BKBmpPool +// Description: Bitmap Pool +// Creator: ZhangXiaoxuan +// Version: 2009.4.24 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include + +class BkBmpPool +{ +public: + BkBmpPool() + { + } + virtual ~BkBmpPool() + { + HBITMAP hbmp = NULL; + + POSITION pos = m_mapBitmap.GetStartPosition(); + + while (pos != NULL) + { + hbmp = m_mapBitmap.GetNextValue(pos); + if (hbmp) + ::DeleteObject(hbmp); + } + + m_mapBitmap.RemoveAll(); + } + + typedef CAtlMap _TypeBitmapPool; + + static HBITMAP GetBitmap(UINT uBmpResID) + { + _TypeBitmapPool::CPair* pPairRet = _Instance().m_mapBitmap.Lookup(uBmpResID); + HBITMAP hbmpRet = NULL; + + if (NULL == pPairRet) + { + BkResManager::LoadResource(uBmpResID, hbmpRet); + if (hbmpRet) + _Instance().m_mapBitmap[uBmpResID] = hbmpRet; + } + else + hbmpRet = pPairRet->m_value; + + return hbmpRet; + } + + static size_t GetCount() + { + return _Instance().m_mapBitmap.GetCount(); + } + +protected: + _TypeBitmapPool m_mapBitmap; + + static BkBmpPool& _Instance() + { + static BkBmpPool bmpPool; + return bmpPool; + } +}; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkres/bkfontpool.h b/Client/Client/GUI/BKWin/bkres/bkfontpool.h new file mode 100644 index 00000000..3db5d7b9 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkres/bkfontpool.h @@ -0,0 +1,156 @@ +////////////////////////////////////////////////////////////////////////// +// Class Name: BKFontPool +// Description: Font Pool +// Creator: ZhangXiaoxuan +// Version: 2009.4.22 - 1.0 - Change stl::map to CAtlMap +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include + +#define BKF_BOLD 0x0004U +#define BKF_UNDERLINE 0x0002U +#define BKF_ITALIC 0x0001U + +#define BKF_MAKEKEY(bold, underline, italic, adding) \ + (WORD)((adding << 8) \ + | (bold ? BKF_BOLD : 0) \ + | (underline ? BKF_UNDERLINE : 0) \ + | (italic ? BKF_ITALIC : 0)) + +#define BKF_ISBOLD(key) ((key & BKF_BOLD) == BKF_BOLD) +#define BKF_ISUNDERLINE(key) ((key & BKF_UNDERLINE) == BKF_UNDERLINE) +#define BKF_ISITALIC(key) ((key & BKF_ITALIC) == BKF_ITALIC) +#define BKF_GETADDING(key) (key >> 8) + +#define BKF_DEFAULTFONT (BKF_MAKEKEY(FALSE, FALSE, FALSE, 0)) +#define BKF_BOLDFONT (BKF_MAKEKEY(TRUE, FALSE, FALSE, 0)) + +#define BKF_GetFont(key) BkFontPool::GetFont(key) + +class BkFontPool +{ +protected: + + typedef CAtlMap _TypeFontPool; + +public: + BkFontPool() + : m_strFaceName(_T("Tahoma")) + , m_lFontSize(-11) + { + m_mapFont[BKF_DEFAULTFONT] = _GetDefaultGUIFont(); + } + virtual ~BkFontPool() + { + HFONT hFont = NULL; + + POSITION pos = m_mapFont.GetStartPosition(); + + while (pos != NULL) + { + hFont = m_mapFont.GetNextValue(pos); + if (hFont) + ::DeleteObject(hFont); + } + + m_mapFont.RemoveAll(); + } + + static HFONT GetFont(WORD uKey) + { + _TypeFontPool::CPair* pPairRet = _Instance().m_mapFont.Lookup(uKey); + HFONT hftRet = NULL; + + if (NULL == pPairRet) + { + hftRet = _Instance()._CreateNewFont( + BKF_ISBOLD(uKey), BKF_ISUNDERLINE(uKey), BKF_ISITALIC(uKey), BKF_GETADDING(uKey) + ); + if (hftRet) + _Instance().m_mapFont[uKey] = hftRet; + } + else + hftRet = pPairRet->m_value; + + return hftRet; + } + + static HFONT GetFont(BOOL bBold, BOOL bUnderline, BOOL bItalic, char chAdding = 0) + { + return GetFont(BKF_MAKEKEY(bBold, bUnderline, bItalic, chAdding)); + } + + static void SetDefaultFont(LPCTSTR lpszFaceName, LONG lSize) + { + _Instance().m_strFaceName = lpszFaceName; + _Instance().m_lFontSize = lSize; + + HFONT hftOld = _Instance().m_mapFont[BKF_DEFAULTFONT]; + _Instance().m_mapFont[BKF_DEFAULTFONT] = _Instance()._GetDefaultGUIFont(); + ::DeleteObject(hftOld); + } + + static size_t GetCount() + { + return _Instance().m_mapFont.GetCount(); + } + +protected: + + LOGFONT m_lfDefault; + _TypeFontPool m_mapFont; + CString m_strFaceName; + LONG m_lFontSize; + + static BkFontPool& _Instance() + { + static BkFontPool fontPool; + return fontPool; + } + + HFONT _GetDefaultGUIFont() + { + DWORD dwSysVer = ::GetVersion(); + + ::GetObject(::GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &m_lfDefault); + + m_lfDefault.lfHeight = _GetFontAbsHeight(m_lFontSize); + _tcscpy_s(m_lfDefault.lfFaceName, LF_FACESIZE, m_strFaceName); + + m_lfDefault.lfQuality = ANTIALIASED_QUALITY; + + return ::CreateFontIndirect(&m_lfDefault); + } + + HFONT _CreateNewFont(BOOL bBold, BOOL bUnderline, BOOL bItalic, char chAdding) + { + LOGFONT lfNew; + + memcpy(&lfNew, &m_lfDefault, sizeof(LOGFONT)); + + lfNew.lfWeight = (bBold ? FW_BOLD : FW_NORMAL); + lfNew.lfUnderline = (FALSE != bUnderline); + lfNew.lfItalic = (FALSE != bItalic); + + lfNew.lfHeight = _GetFontAbsHeight(lfNew.lfHeight - chAdding); + + return ::CreateFontIndirect(&lfNew); + } + + inline LONG _GetFontAbsHeight(LONG lSize) + { + return lSize; + // HDC hDC = ::GetDC(NULL); + // LONG lHeight = chSize; + // + // lHeight *= 96; + // lHeight /= ::GetDeviceCaps(hDC, LOGPIXELSY); + // + // ::ReleaseDC(NULL, hDC); + // + // + // return lHeight; + } +}; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkres/bkpngpool.h b/Client/Client/GUI/BKWin/bkres/bkpngpool.h new file mode 100644 index 00000000..a69eec92 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkres/bkpngpool.h @@ -0,0 +1,101 @@ +////////////////////////////////////////////////////////////////////////// +// Class Name: BKPngPool +// Description: PNG Pool +// Creator: ZhangXiaoxuan +// Version: 2010.2.24 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#pragma comment(lib, "gdiplus.lib") + +#include + +#include "bkresutil.h" + +class BkPngPool +{ +public: + BkPngPool() + { + Gdiplus::GdiplusStartupInput gdiplusStartupInput; + Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); + } + virtual ~BkPngPool() + { + Gdiplus::Image *pImg = NULL; + + POSITION pos = m_mapPng.GetStartPosition(); + + while (pos != NULL) + { + pImg = m_mapPng.GetNextValue(pos); + if (pImg) + delete pImg; + } + + m_mapPng.RemoveAll(); + + Gdiplus::GdiplusShutdown(m_gdiplusToken); + } + + typedef CAtlMap _TypePngPool; + + static Gdiplus::Image* Get(UINT uResID) + { + _TypePngPool::CPair* pPairRet = _Instance().m_mapPng.Lookup(uResID); + Gdiplus::Image* pImg = NULL; + + if (NULL == pPairRet) + { + _LoadPNGImageFromResourceID(uResID, pImg); + if (pImg) + _Instance().m_mapPng[uResID] = pImg; + } + else + pImg = pPairRet->m_value; + + return pImg; + } + + static size_t GetCount() + { + return _Instance().m_mapPng.GetCount(); + } + +protected: + + ULONG_PTR m_gdiplusToken; + + _TypePngPool m_mapPng; + + static BkPngPool& _Instance() + { + static BkPngPool pngPool; + return pngPool; + } + + static BOOL _LoadPNGImageFromResourceID(UINT nID, Gdiplus::Image* &pImg) + { + CStringA strResource; + + BOOL bRet = BkResManager::LoadResource(nID, strResource, BKRES_PNG_TYPE); + int len = strResource.GetLength(); + + HGLOBAL hMem = ::GlobalAlloc(GMEM_FIXED, len); + BYTE* pMem = (BYTE*)::GlobalLock(hMem); + + memcpy(pMem, (LPCSTR)strResource, len); + + IStream* pStm = NULL; + ::CreateStreamOnHGlobal(hMem, FALSE, &pStm); + + pImg = Gdiplus::Image::FromStream(pStm); + + ::GlobalUnlock(hMem); + pStm->Release(); + + return TRUE; + } +}; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkres/bkres.h b/Client/Client/GUI/BKWin/bkres/bkres.h new file mode 100644 index 00000000..9e56016f --- /dev/null +++ b/Client/Client/GUI/BKWin/bkres/bkres.h @@ -0,0 +1,39 @@ +#pragma once + +////////////////////////////////////////////////////////////////////////// + +#ifdef __BKRES_RC + +# define DEFINE_BKRES(id, type, id_number, file_name) \ + id_number type file_name + +#else + +# define DEFINE_BKRES(id, type, id_number, file_name) \ + const UINT id = id_number; + +#endif + +////////////////////////////////////////////////////////////////////////// + +# define DEFINE_XML(id, id_number, file_name) \ + DEFINE_BKRES(id, XML, id_number, file_name) + +# define DEFINE_BMP(id, id_number, file_name) \ + DEFINE_BKRES(id, BITMAP, id_number, file_name) + +# define DEFINE_ICO(id, id_number, file_name) \ + DEFINE_BKRES(id, ICON, id_number, file_name) + +# define DEFINE_PNG(id, id_number, file_name) \ + DEFINE_BKRES(id, PNG, id_number, file_name) + +////////////////////////////////////////////////////////////////////////// + +#ifndef __BKRES_RC + +# include "bkwinres.rc2" + +# include "bkwinres.h" + +#endif diff --git a/Client/Client/GUI/BKWin/bkres/bkres.rc b/Client/Client/GUI/BKWin/bkres/bkres.rc new file mode 100644 index 00000000..f289cae5 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkres/bkres.rc @@ -0,0 +1,63 @@ +// Microsoft Visual C++ generated resource script. +// + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +#define __BKRES_RC 1 + +#include "bkres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) +LANGUAGE 4, 2 +#pragma code_page(936) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#include ""bkwinres.rc2""\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "bkwinres.rc2" +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Client/Client/GUI/BKWin/bkres/bkresutil.h b/Client/Client/GUI/BKWin/bkres/bkresutil.h new file mode 100644 index 00000000..b37e31de --- /dev/null +++ b/Client/Client/GUI/BKWin/bkres/bkresutil.h @@ -0,0 +1,184 @@ +////////////////////////////////////////////////////////////////////////// +// File Name: bkresutil.h +// Description: Beike Resource Helper +// Creator: Zhang Xiaoxuan +// Version: 2009.5.13 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#define BKRES_TYPE _T("xml") +#define BKRES_PNG_TYPE _T("png") + +#ifdef _DEBUG +# define BKRES_ASSERT(expr, format, ...) \ + (void) ((!!(expr)) || \ + (1 != _CrtDbgReportW(_CRT_ASSERT, _CRT_WIDE(__FILE__), __LINE__, NULL, format, __VA_ARGS__)) || \ + (_CrtDbgBreak(), 0)) +#else +# define BKRES_ASSERT +#endif + +class BkResManager +{ +public: + BkResManager() + : m_hInstanceRes(NULL) + { + + } + + static void SetResourcePath(LPCTSTR lpszPath) + { + _Instance().m_strResourcePath = lpszPath; + } + + static void SetResourceDLL(LPCTSTR lpszPath) + { + if (_Instance().m_hInstanceRes) + ::FreeLibrary(_Instance().m_hInstanceRes); + + _Instance().m_hInstanceRes = ::LoadLibrary(lpszPath); + } + + static BOOL LoadResource(UINT uResID, CStringA &strBuffRet, LPCTSTR lpszResType = BKRES_TYPE) + { + BOOL bRet = FALSE; + + if (!_Instance().m_strResourcePath.IsEmpty()) + { + CString strFileName; + + strFileName.Format(_T("%s\\%d.%s"), _Instance().m_strResourcePath, uResID, lpszResType); + + HANDLE hFile = ::CreateFile( + strFileName, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (INVALID_HANDLE_VALUE != hFile) + { + DWORD dwSize = ::GetFileSize(hFile, NULL); + if (0 != dwSize) + { + DWORD dwRead = 0; + bRet = ::ReadFile(hFile, strBuffRet.GetBuffer(dwSize + 10), dwSize, &dwRead, NULL); + if (bRet && dwRead == dwSize) + { + strBuffRet.ReleaseBuffer(dwSize); + return TRUE; + } + + strBuffRet.ReleaseBuffer(0); + } + + ::CloseHandle(hFile); + } + } + bRet = _LoadEmbedResource(uResID, strBuffRet, lpszResType); + BKRES_ASSERT(bRet, L"Failed loading %s %u", lpszResType, uResID); + return bRet; + } + + static BOOL LoadResource(LPCTSTR fileName, CStringA &strBuffRet, LPCTSTR lpszResType = BKRES_TYPE) + { + BOOL bRet = FALSE; + + if (!_Instance().m_strResourcePath.IsEmpty()) + { + CString strFileName; + + strFileName.Format(_T("%s\\%s"), _Instance().m_strResourcePath, fileName); + + HANDLE hFile = ::CreateFile( + strFileName, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (INVALID_HANDLE_VALUE != hFile) + { + DWORD dwSize = ::GetFileSize(hFile, NULL); + if (0 != dwSize) + { + DWORD dwRead = 0; + bRet = ::ReadFile(hFile, strBuffRet.GetBuffer(dwSize + 10), dwSize, &dwRead, NULL); + if (bRet && dwRead == dwSize) + { + strBuffRet.ReleaseBuffer(dwSize); + return TRUE; + } + + strBuffRet.ReleaseBuffer(0); + } + + ::CloseHandle(hFile); + } + } + + return bRet; + } + + static BOOL LoadResource(UINT uResID, HBITMAP &hBitmap) + { + BOOL bRet = FALSE; + + if (!_Instance().m_strResourcePath.IsEmpty()) + { + CString strFileName; + + strFileName.Format(_T("%s\\%d.bmp"), _Instance().m_strResourcePath, uResID); + + hBitmap = (HBITMAP)::LoadImage(NULL, strFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); + + if (NULL != hBitmap) + return TRUE; + } + + if (_Instance().m_hInstanceRes) + { + hBitmap = ::LoadBitmap(_Instance().m_hInstanceRes, MAKEINTRESOURCE(uResID)); + if (NULL != hBitmap) + return TRUE; + } + + hBitmap = ::LoadBitmap((HINSTANCE)&__ImageBase, MAKEINTRESOURCE(uResID)); + + BKRES_ASSERT(NULL != hBitmap, L"Failed loading bitmap %u", uResID); + + return NULL != hBitmap; + } + +protected: + + static BkResManager& _Instance() + { + static BkResManager resManager; + return resManager; + } + + static BOOL _LoadEmbedResource(UINT uResID, CStringA &strRet, LPCTSTR lpszResType = BKRES_TYPE) + { + HRSRC hRsrc = ::FindResource((HINSTANCE)&__ImageBase, MAKEINTRESOURCE(uResID), lpszResType); + + if (NULL == hRsrc) + return FALSE; + + DWORD dwSize = ::SizeofResource((HINSTANCE)&__ImageBase, hRsrc); + if (0 == dwSize) + return FALSE; + + HGLOBAL hGlobal = ::LoadResource((HINSTANCE)&__ImageBase, hRsrc); + if (NULL == hGlobal) + return FALSE; + + LPVOID pBuffer = ::LockResource(hGlobal); + if (NULL == pBuffer) + return FALSE; + + memcpy(strRet.GetBuffer(dwSize + 1), pBuffer, dwSize); + strRet.ReleaseBuffer(dwSize); + + ::FreeResource(hGlobal); + + return TRUE; + } + + CString m_strResourcePath; + HINSTANCE m_hInstanceRes; +}; diff --git a/Client/Client/GUI/BKWin/bkres/bkstringpool.h b/Client/Client/GUI/BKWin/bkres/bkstringpool.h new file mode 100644 index 00000000..cfcd7047 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkres/bkstringpool.h @@ -0,0 +1,132 @@ +////////////////////////////////////////////////////////////////////////// +// File Name: bkstringpool.h +// Description: String Pool +// Creator: Zhang Xiaoxuan +// Version: 2009.5.13 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include "bkresutil.h" + +#if !defined(TINYXML_INCLUDED) + #error Please include tinyxml.h first! +#endif + +class BkString +{ +protected: + + typedef CAtlMap _TypeStringResPool; + +public: + BkString() + { + } + virtual ~BkString() + { + m_mapString.RemoveAll(); + } + + static LPCTSTR Get(UINT uResID) + { + const _TypeStringResPool::CPair* pPair = _Instance().m_mapString.Lookup(uResID); + if (!pPair) + { + BKRES_ASSERT(FALSE, L"Failed loading string %u", uResID); + + return NULL; + } + + return pPair->m_value; + } + + static BOOL Load(UINT uResID) + { + CStringA strXml; + BOOL bRet = FALSE; + + bRet = BkResManager::LoadResource(uResID, strXml); + if (!bRet) + return FALSE; + + TiXmlDocument xmlDoc; + + xmlDoc.Parse(strXml, NULL, TIXML_ENCODING_UTF8); + + if (xmlDoc.Error()) + return FALSE; + + LPCSTR lpszStringID = NULL; + UINT uStringID = 0; + + TiXmlElement *pXmlStringRootElem = xmlDoc.RootElement(); + + if (!pXmlStringRootElem) + return FALSE; + + if (strcmp(pXmlStringRootElem->Value(), "string") != 0) + return FALSE; + + for (TiXmlElement* pXmlChild = pXmlStringRootElem->FirstChildElement("s"); NULL != pXmlChild; pXmlChild = pXmlChild->NextSiblingElement("s")) + { + lpszStringID = pXmlChild->Attribute("id"); + if (!lpszStringID) + continue; + + uStringID = (UINT)(ULONG)::StrToIntA(lpszStringID); + + { + _Instance().m_mapString[uStringID] = CA2T(pXmlChild->GetText(), CP_UTF8); + } + } + + return TRUE; + } + + static size_t GetCount() + { + return _Instance().m_mapString.GetCount(); + } + +protected: + + _TypeStringResPool m_mapString; + + static BkString* ms_pInstance; + + static BkString& _Instance() + { + static BkString instance; + return instance; + } +}; + +class CBkStringArray +{ +public: + CBkStringArray(UINT arrStringID[]) + { + if (m_arrStringID.IsEmpty()) + { + size_t nCount = sizeof(arrStringID) / sizeof(UINT); + m_arrStringID.SetCount(nCount); + + for (size_t i = 0; i < nCount; i ++) + m_arrStringID[i] = arrStringID[i]; + } + } + + LPCTSTR operator[](size_t nIndex) + { + if (nIndex >= m_arrStringID.GetCount()) + return _T(""); + + return BkString::Get(m_arrStringID[nIndex]); + } + + CAtlArray m_arrStringID; +}; + +// __declspec(selectany) BkString* BkString::ms_pInstance = NULL; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkres/bkwinres.h b/Client/Client/GUI/BKWin/bkres/bkwinres.h new file mode 100644 index 00000000..61902c6f --- /dev/null +++ b/Client/Client/GUI/BKWin/bkres/bkwinres.h @@ -0,0 +1,15 @@ +#pragma once + + +#define IDC_BTN_SYS_CLOSE 60001 +#define IDC_BTN_SYS_MAX 60002 +#define IDC_BTN_SYS_MIN 60003 +#define IDC_LBL_MSGBOX_TITLE 60004 +#define IDC_ICON_MSGBOX_ICON 60005 +#define IDC_LBL_MSGBOX_TEXT 60006 +#define IDC_CHK_MSGBOX_NONOTIFYLATER 60007 +#define IDC_DIV_MSGBOX_BUTTONS 60008 +#define IDC_DIV_MSGBOX_CONTENT 60009 +#define IDC_CHK_MSGBOX_NEVERSHOW 60010 + +#define IDC_BTN_MORE_BKWIN 60066 \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkres/bkwinres.rc2 b/Client/Client/GUI/BKWin/bkres/bkwinres.rc2 new file mode 100644 index 00000000..efce4841 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkres/bkwinres.rc2 @@ -0,0 +1,68 @@ +#pragma once + +DEFINE_XML(IDR_XML_SKIN_DEF, 100, "../res/def_skin.xml") +DEFINE_XML(IDR_BK_STYLE_DEF, 101, "../res\\def_style.xml") +DEFINE_XML(IDR_BK_STRING_DEF, 102, "../res\\def_string.xml") +DEFINE_XML(IDR_BK_MAIN_DIALOG, 103, "../res\\dlg_main.xml") +DEFINE_XML(IDR_BK_MESSAGEBOX, 105, "../res\\dlg_msgbox.xml") +DEFINE_XML(IDR_BK_RUNOPT_LIST, 128, "../res\\dlg_runopt_list.xml") +DEFINE_XML(IDR_BK_RUNOPT_IGNORE_DLG, 134, "../res\\dlg_runopt_ignore.xml") +DEFINE_XML(IDR_BK_MESSAGEBOX2, 150, "../res\\dlg_msgbox2.xml") +DEFINE_XML(IDR_BK_SYSOPT_SETTING_DLG, 152, "../res\\dlg_sysopt_setting.xml") + +// dlgfile ǩļ +DEFINE_XML(IDR_BK_DLGFILE_OPT, 504, "../res\\dlgfile_opt.xml") +DEFINE_XML(IDR_BK_DLGFILE_FOOT, 508, "../res\\dlgfile_foot.xml") +DEFINE_XML(IDR_BK_DLGFILE_HEADER, 509, "../res\\dlgfile_header.xml") + +DEFINE_XML(IDR_BK_MORE_BKWIN, 600, "../res\\dlg_more_bkwin.xml") + + +////////////////////////////////////////////////////////////////////////// +// ICON + +DEFINE_ICO(IDI_BEIKESAFE, 100, "../res\\beikesafe.ico") +DEFINE_ICO(IDI_SMALL, 101, "../res\\small.ico") + +////////////////////////////////////////////////////////////////////////// +// PNG +DEFINE_PNG(IDP_PNG_STATUS15, 40, "../res\\status_icon.png") +DEFINE_PNG(IDP_PNG_EXAM_STATUS15, 41, "../res\\exam_status_icon.png") +DEFINE_PNG(IDB_BTN_SYS_CLOSE_PNG, 44, "../res\\btn_sys_close.png") +DEFINE_PNG(IDB_BTN_SYS_MAXIMIZE_PNG, 46, "../res\\btn_sys_maximize.png") +DEFINE_PNG(IDB_BTN_SYS_MINIMIZE_PNG, 47, "../res\\btn_sys_minimize.png") +DEFINE_PNG(IDB_BTN_SYS_RESTORE_PNG, 48, "../res\\btn_sys_restore.png") +DEFINE_BMP(IDB_MSGBOX_BG, 4, "../res\\msgbox_bg.bmp") +DEFINE_BMP(IDB_TAB_NORMAL, 6, "../res\\tab_normal.bmp") +DEFINE_BMP(IDB_STATUS_40, 15, "../res\\status_40.bmp") +DEFINE_BMP(IDB_TAB_LEFT, 16, "../res\\tab_left.bmp") +DEFINE_BMP(IDB_TAB_LEFT_SPLITTER, 17, "../res\\tab_left_splitter.bmp") +DEFINE_BMP(IDB_BTN_VIRSCAN_BG, 27, "../res\\btn_virscan_bg.bmp") +DEFINE_BMP(IDP_BG_MSGBOX_BODY, 29, "../res\\msgbox_body_bg.bmp") +DEFINE_BMP(IDB_BTN_SYS_CLOSE, 101, "../res\\btn_sys_close.bmp") +DEFINE_BMP(IDB_BTN_SYS_MAXIMIZE, 103, "../res\\btn_sys_maximize.bmp") +DEFINE_BMP(IDB_BTN_SYS_MINIMIZE, 104, "../res\\btn_sys_minimize.bmp") +DEFINE_BMP(IDB_BTN_SYS_RESTORE, 105, "../res\\btn_sys_restore.bmp") +DEFINE_BMP(IDB_FRAME_PANEL_GRAY, 106, "../res\\frame_panel_gray.bmp") +DEFINE_BMP(IDB_FRAME_PANEL, 107, "../res\\frame_panel.bmp") +DEFINE_BMP(IDB_STATUS_ICON, 111, "../res\\status_icon.bmp") +DEFINE_BMP(IDB_SCAN_RESULT_LIST_BAR, 122, "../res\\scan_result_list_bar.bmp") +DEFINE_PNG(IDP_LITTLE_LOGO, 201, "../res\\little_logo.png") +DEFINE_BMP(IDB_BITMAP_LISTCTRL_HEADER, 210, "../res\\listctrl_header.bmp") +DEFINE_BMP(IDB_BITMAP_MINUS_PLUS, 212, "../res\\minus_plus.bmp") +DEFINE_BMP(IDB_BITMAP_LISTCTRL_CHECK, 211, "../res\\listctrl_check.bmp") +DEFINE_BMP(IDB_BITMAP_LISTCTRL_RADIO, 213, "../res\\listctrl_radio.bmp") +DEFINE_PNG(IDP_ROOMLIST_PANE, 214, "../res\\frame_roomlistpane.png") +DEFINE_PNG(IDP_LOADINFO_TIP, 8020, "../res\\loadinfo_tip_softmgr.png") +DEFINE_BMP(IDB_SOFTMGR_CLEAR_BK, 8034, "../res\\clear_bk.bmp") +DEFINE_BMP(IDB_SYSOPT_LIST_HEADERBK, 8035, "../res\\sysopt_listbk.bmp") +DEFINE_BMP(IDB_LOADINFO_DLGBK, 8036, "../res\\loadinfo_dlgbk.bmp") + +////////////////////////////////////////////////////////////////////////// +// +DEFINE_BMP(IDB_RUNOPT_STATUS, 20007, "../res\\stat_runopt.bmp") +DEFINE_PNG(IDP_RUNOPT_LOADING_TIP, 20008, "../res\\loading_runopt.png") +DEFINE_BMP(IDB_RUNOPT_LIST_HEADER, 20010, "../res\\runopt_listheader.bmp") +DEFINE_BMP(IDB_RUNOPT_PANEL_DELAY, 20011, "../res\\loaddlg_panel.bmp") +DEFINE_PNG(IDP_RUNOPT_STARTUPTIME_SETTING, 20012, "../res\\startuptime_setting.png") +DEFINE_PNG(IDP_RUNOPT_IGNORE_TIP, 20013, "../res\\ignore_tip.png") diff --git a/Client/Client/GUI/BKWin/bkwin/ListViewCtrlEx.cpp b/Client/Client/GUI/BKWin/bkwin/ListViewCtrlEx.cpp new file mode 100644 index 00000000..a164759e --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/ListViewCtrlEx.cpp @@ -0,0 +1,1412 @@ +#include "stdafx.h" +#include "ListViewCtrlEx.h" +#include +#include "../bkres/bkres.h" +//#include "beikesafetipdlg.h" +//#include "KAutoSync.h" +#pragma warning(push) +#pragma warning(disable:4018) + +#define COLOR_LIST_LINK RGB(40,100,165) +#define LEFT_MARGIN_TEXT_COLUMN 2 +#define XX_TIMER_ID_TIPS 1 + + +enum { + WMH_LISTEX_HOVERCHANGED = WM_USER + 0x300, + WMH_LISTEX_LINK +}; + +void CreateBitmapMask( CBitmap &pBmpSource, CBitmap &pBmpMask, COLORREF clrpTransColor, int iTransPixelX, int iTransPixelY) +{ + BITMAP bm; + + // Get the dimensions of the source bitmap + pBmpSource.GetBitmap(&bm); + + // Create the mask bitmap + //pBmpMask.DeleteObject(); + pBmpMask.CreateBitmap( bm.bmWidth, bm.bmHeight, 1, 1, NULL); + + // We will need two DCs to work with. One to hold the Image + // (the source), and one to hold the mask (destination). + // When blitting onto a monochrome bitmap from a color, pixels + // in the source color bitmap that are equal to the background + // color are blitted as white. All the remaining pixels are + // blitted as black. + + CDC hdcSrc, hdcDst; + + hdcSrc.CreateCompatibleDC(NULL); + hdcDst.CreateCompatibleDC(NULL); + + // Load the bitmaps into memory DC + HBITMAP hbmSrcT = hdcSrc.SelectBitmap(pBmpSource); + HBITMAP hbmDstT = hdcDst.SelectBitmap(pBmpMask); + + // Dynamically get the transparent color + COLORREF clrTrans; + if (clrpTransColor == NULL) + { + // User did not specify trans color so get it from bmp + clrTrans = hdcSrc.GetPixel(iTransPixelX, iTransPixelY); + } + else + { + clrTrans = clrpTransColor; + } + + // Change the background to trans color + COLORREF clrSaveBk = hdcSrc.SetBkColor(clrTrans); + + // This call sets up the mask bitmap. + hdcDst.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, hdcSrc, 0, 0, SRCCOPY); + + // Now, we need to paint onto the original image, making + // sure that the "transparent" area is set to black. What + // we do is AND the monochrome image onto the color Image + // first. When blitting from mono to color, the monochrome + // pixel is first transformed as follows: + // if 1 (black) it is mapped to the color set by SetTextColor(). + // if 0 (white) is is mapped to the color set by SetBkColor(). + // Only then is the raster operation performed. + + COLORREF clrSaveDstText = hdcSrc.SetTextColor(RGB(255,255,255)); + hdcSrc.SetBkColor(RGB(0,0,0)); + + hdcSrc.BitBlt(0,0,bm.bmWidth, bm.bmHeight, hdcDst,0,0,SRCAND); + + // Clean up by deselecting any objects, and delete the + // DC's. + hdcDst.SetTextColor(clrSaveDstText); + + hdcSrc.SetBkColor(clrSaveBk); + hdcSrc.SelectBitmap(hbmSrcT); + hdcDst.SelectBitmap(hbmDstT); + + hdcSrc.DeleteDC(); + hdcDst.DeleteDC(); +} + +CHeaderCtrlEx::CHeaderCtrlEx() +{ + m_nHeight = -1; + m_font.Attach( BkFontPool::GetFont(BKF_DEFAULTFONT) ); + m_bitmapHeader.Attach( BkBmpPool::GetBitmap(IDB_BITMAP_LISTCTRL_HEADER)); +} + +CHeaderCtrlEx::~CHeaderCtrlEx() +{ + m_font.Detach(); + m_bitmapHeader.Detach(); +} + +void CHeaderCtrlEx::SetHeight(INT nHeight) +{ + m_nHeight = nHeight; +} + +void CHeaderCtrlEx::OnPaint( CDCHandle ) +{ + CPaintDC dc(m_hWnd); + CDC dcTemp; + + dcTemp.CreateCompatibleDC( dc ); + HBITMAP hOldBitmap = dcTemp.SelectBitmap(m_bitmapHeader); + + HFONT hOldFont = dc.SelectFont( m_font ); + dc.SetBkMode( TRANSPARENT ); + + RECT rc = {0}; + GetClientRect( &rc ); + dc.StretchBlt(rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, dcTemp, 0, 0, 3, 20, SRCCOPY); + int nItems = GetItemCount(); + for(int i=0; i::DefWindowProc(uMsg, wParam, lParam); + HD_LAYOUT &hdl = *( HD_LAYOUT * ) lParam; + RECT *prc = hdl.prc; + WINDOWPOS *pwpos = hdl.pwpos; + int nHeight = (int)(pwpos->cy); + if(m_nHeight>=0) + nHeight = m_nHeight; + pwpos->cy = nHeight; + prc->top = nHeight; + return lResult; +} + +LRESULT CHeaderCtrlEx::OnMouseMove( UINT nFlags, CPoint point ) +{ + SetMsgHandled(FALSE); + return S_OK; +} + +CListViewCtrlEx::CListViewCtrlEx( void ) +{ + m_hWndObserver = NULL; + m_nHoverItem = -1; + m_nHoverSubItem = -1; + + m_fontLink.Attach( BkFontPool::GetFont(FALSE,TRUE,FALSE,0) ); + m_fontBold.Attach( BkFontPool::GetFont(TRUE,FALSE,FALSE) ); + m_fontTitle.Attach( BkFontPool::GetFont(TRUE,FALSE,FALSE,4) ); + m_fontDef.Attach( BkFontPool::GetFont(BKF_DEFAULTFONT)); + m_bitmapCheck.Attach( BkBmpPool::GetBitmap(IDB_BITMAP_LISTCTRL_CHECK) ); + m_bitmapExpand.Attach( BkBmpPool::GetBitmap(IDB_BITMAP_MINUS_PLUS) ); + m_bitmapRadio.Attach( BkBmpPool::GetBitmap(IDB_BITMAP_LISTCTRL_RADIO) ); +// m_bitmapCombo.Attach(BkBmpPool::GetBitmap(IDB_BITMAP_LISTCTRL_COMBO)); + CreateBitmapMask(m_bitmapRadio, m_bitmapRadioMask, 0, 0, 0); + m_strEmptyString = _T("û"); + + m_bOnlyShowRisk = false; + ::InitializeCriticalSection(&m_hListLock); +} + +CListViewCtrlEx::~CListViewCtrlEx( void ) +{ + m_fontLink.Detach(); + m_fontBold.Detach(); + m_fontTitle.Detach(); + m_bitmapCheck.Detach(); + m_bitmapExpand.Detach(); + m_bitmapRadio.Detach(); + m_fontDef.Detach(); + m_bitmapCombo.Detach(); + m_bitmapRadioMask.DeleteObject(); + + ::DeleteCriticalSection(&m_hListLock); +} + +HWND CListViewCtrlEx::Create( HWND hWndParent, _U_RECT rect /*= NULL*/, LPCTSTR szWindowName /*= NULL*/, DWORD dwStyle /*= 0*/, DWORD dwExStyle /*= 0*/, _U_MENUorID MenuOrID /*= 0U*/, LPVOID lpCreateParam /*= NULL*/ ) +{ + HWND hWnd = _super::Create(hWndParent, rect, szWindowName, dwStyle|LVS_OWNERDRAWFIXED, dwExStyle, MenuOrID, lpCreateParam); + _super::SetExtendedListViewStyle( LVS_EX_CHECKBOXES|LVS_EX_FULLROWSELECT|_super::GetExtendedListViewStyle() ); + + m_ctlHeader.SubclassWindow( GetHeader().m_hWnd ); + m_ctlHeader.SetHeight(25); + m_ctlHeader.ModifyStyle(HDS_FULLDRAG, 0, 0); + + _super::SetBkColor(RGB(0xfb,0xfc,0xfd)); + return hWnd; +} + +BOOL CListViewCtrlEx::GetCheckState( int nIndex, BOOL *pIsRadio ) const +{ + const TListItem *pItem = _GetItemData(nIndex); + if( pItem && (pItem->dwFlags&(LISTITEM_CHECKBOX|LISTITEM_RADIOBOX)) ) + { + if(pIsRadio && pItem->dwFlags&LISTITEM_RADIOBOX) + *pIsRadio = TRUE; + return _super::GetCheckState( nIndex ); + } + return FALSE; +} + +BOOL CListViewCtrlEx::SetCheckState( int nItem, BOOL bCheck ) +{ + TListItem *pItem = _GetItemData( nItem ); + if( pItem && (pItem->dwFlags&LISTITEM_CHECKBOX) ) + { + if( bCheck ) + ClearRadioCheck(); + return _super::SetCheckState( nItem, bCheck ); + } + return FALSE; +} + +int CListViewCtrlEx::SetRadioState( int nItem, BOOL bCheck ) +{ + TListItem *pItem = _GetItemData( nItem ); + if( pItem && (pItem->dwFlags&LISTITEM_RADIOBOX) ) + { + if( bCheck ) + CleanCheck( nItem ); + return _super::SetCheckState( nItem, bCheck ); + } + return -1; +} + +void CListViewCtrlEx::ClearRadioCheck() +{ + for(int i=0; i<_super::GetItemCount(); ++i) + { + TListItem *pItem = _GetItemData( i ); + if( pItem && pItem->dwFlags & LISTITEM_RADIOBOX ) + { + _super::SetCheckState(i, FALSE); + } + } +} + +void CListViewCtrlEx::CleanCheck( int nItem/*=-1 */ ) +{ + for(int i=0; i<_super::GetItemCount(); ++i) + { + if(nItem!=i) + _super::SetCheckState( i, FALSE ); + } +} + +void CListViewCtrlEx::CheckAll() +{ + ClearRadioCheck(); + for(int i=0; i<_super::GetItemCount(); ++i) + { + TListItem *pItem = _GetItemData( i ); + if( pItem && (pItem->dwFlags&LISTITEM_CHECKBOX) ) + { + _super::SetCheckState( i, TRUE ); + } + } +} + +void CListViewCtrlEx::SetObserverWindow( HWND hWnd ) +{ + m_hWndObserver = hWnd; +} + +int CListViewCtrlEx::AppendTitle( LPCTSTR strItem, COLORREF clr, UINT uFlags) +{ +// return Append(strItem, LISTITEM_TITLE); + + int nItem = _super::AddItem(_super::GetItemCount(), 0, _T("")); + TListItem *pitem = new TListItem; + pitem->dwFlags = LISTITEM_TITLE | uFlags; + pitem->clrBg =RGB(248,248,248); + pitem->bBold = uFlags & LISTITEM_BOLD; + pitem->nLeftmargin = 15; + + TListSubItem subItem(strItem, SUBITEM_TEXT); + subItem.clr = clr; + pitem->subItems.push_back( subItem ); + m_arrItems.push_back( pitem ); + return nItem; +} + +int CListViewCtrlEx::Append( LPCTSTR strItem, DWORD dwFlags /*=0*/, E_SubItemType itemType/*=SUBITEM_TEXT*/ ) +{ + int nItem = _super::AddItem(_super::GetItemCount(), 0, _T("")); + TListItem *pitem = new TListItem; + pitem->dwFlags = dwFlags; + pitem->subItems.push_back( TListSubItem(strItem, itemType) ); + m_arrItems.push_back( pitem ); + return nItem; +} + +int CListViewCtrlEx::Append(LPCTSTR strItem, HICON hIcon, LEVEL nLevel /*= enumLevelSafe*/, DWORD dwFlags /*= 0*/ ) +{ + //KAutoSync autoCS(&m_hListLock); + + + if (!m_bOnlyShowRisk || nLevel == enumLevelRisk) + _super::AddItem(_super::GetItemCount(), 0, _T("")); + + TListItem *pitem = new TListItem; + pitem->dwFlags = dwFlags; + pitem->nLevel = nLevel; + pitem->subItems.push_back( TListSubItem(strItem, hIcon) ); + pitem->nRiskRefIndex = -1; + m_arrItems.push_back( pitem ); + + if (pitem->nLevel == enumLevelRisk) + { + m_RiskItemIDArray.Add(m_arrItems.size() - 1); + m_arrItems[m_arrItems.size() - 1]->nRiskRefIndex = m_RiskItemIDArray.GetSize(); + } + else if (pitem->nLevel == enumLevelUnknown) + { + m_UnknownItemIDArray.Add(m_arrItems.size() - 1); + } + + return m_arrItems.size() - 1; +} + +int CListViewCtrlEx::Append(LPCTSTR strItem, HICON hIcon, DWORD dwMapId, DWORD dwFlags /*= 0*/ ) +{ + //KAutoSync autoCS(&m_hListLock); + + + _super::AddItem(_super::GetItemCount(), 0, _T("")); + + TListItem *pitem = new TListItem; + pitem->dwFlags = dwFlags; + pitem->dwMapId = dwMapId; + pitem->subItems.push_back( TListSubItem(strItem, hIcon) ); + m_arrItems.push_back( pitem ); + + return m_arrItems.size() - 1; +} + +void CListViewCtrlEx::SetOnlyShowRisk(bool bShowRisk) +{ + //m_bOnlyShowRisk = bShowRisk; + //if (m_arrItems.size()) + // m_ActorRefresh.Startup(this); +} + +DWORD CListViewCtrlEx::GetAllSafeCount() +{ + return m_arrItems.size() - m_RiskItemIDArray.GetSize() - m_UnknownItemIDArray.GetSize(); +} + +DWORD CListViewCtrlEx::GetAllRiskCount() +{ + return m_RiskItemIDArray.GetSize(); +} + +DWORD CListViewCtrlEx::GetAllUnknownCount() +{ + return m_UnknownItemIDArray.GetSize(); +} + + +LRESULT CListViewCtrlEx::OnDeleteAll(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam) +{ + _super::DeleteAllItems(); + return 0; +} + +LRESULT CListViewCtrlEx::OnAddItem(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam) +{ + _super::AddItem(_super::GetItemCount(), 0, _T("")); + return 0; +} +/* +void CListViewCtrlEx::OnActivate(KActor* pActor) +{ + if (m_ActorRefresh.IsActive()) + { + if (m_bOnlyShowRisk) + { + PostMessage(MSG_DEL_ALL); + for (int i = 0; i < m_RiskItemIDArray.GetSize(); i++) + { + if (m_ActorRefresh.WaitForStop(1)) + return; + + PostMessage(MSG_ADD_ITEM); + } + } + else + { + PostMessage(MSG_DEL_ALL); + for (int i = 0; i < m_arrItems.size(); i++) + { + if (m_ActorRefresh.WaitForStop(1)) + return; + + PostMessage(MSG_ADD_ITEM); + } + } + + } +} +*/ +int CListViewCtrlEx::AppendTitleItem(int nItem, LPCTSTR strItem, CRect rc, E_SubItemType itemType, COLORREF clr, LPCTSTR szURL ) +{ + BOOL bValid = nItem>=0 && nItemsubItems.push_back( isubitem ); + return m_arrItems[nItem]->subItems.size(); +} + +int CListViewCtrlEx::AppendSubItem( int nItem, LPCTSTR strItem, E_SubItemType itemType/*=SUBITEM_TEXT*/ ) +{ + BOOL bValid = nItem>=0 && nItemsubItems.push_back( TListSubItem(strItem, itemType) ); + return m_arrItems[nItem]->subItems.size(); +} + +int CListViewCtrlEx::AppendSubItem( int nItem, LPCTSTR strItem, DWORD dwImg, E_SubItemType itemType) +{ + BOOL bValid = nItem>=0 && nItemsubItems.push_back( TListSubItem(strItem, dwImg, itemType) ); + return m_arrItems[nItem]->subItems.size(); +} + + +bool CListViewCtrlEx::SetSubItem( int nItem, int nSubItem, LPCTSTR lpszItem, E_SubItemType itemType/*=SUBITEM_TEXT*/, BOOL bRedraw ) +{ + if(nItem>=0 && nItem &subItems = m_arrItems[nItem]->subItems; + if(nSubItem>=0 && nSubItem=0 && nItem &subItems = m_arrItems[nItem]->subItems; + if(nSubItem>=0 && nSubItem=0 && nItem &subItems = m_arrItems[nItem]->subItems; + if(nSubItem>=0 && nSubItemdwFlags |= LISTITEM_CHECKBOX; + else if(dwFlags & LISTITEM_RADIOBOX) + pItem->dwFlags |= LISTITEM_RADIOBOX; + else + { + DWORD dwFlags = LISTITEM_CHECKBOX|LISTITEM_RADIOBOX; + pItem->dwFlags &= ~dwFlags; + _super::SetCheckState( nItem, FALSE ); + } + } + return pItem!=NULL; +} + +BOOL CListViewCtrlEx::DeleteItem( int nItem ) +{ + if(nItem < 0 || nItem >= m_arrItems.size()) + return FALSE; + + + //KAutoSync autoCS(&m_hListLock); + + if (m_arrItems[nItem]->nRiskRefIndex != -1) + m_RiskItemIDArray.RemoveAt(m_arrItems[nItem]->nRiskRefIndex); + + TListItemPtrs::iterator it = m_arrItems.begin(); + if(nItem>0) + std::advance(it, nItem); + delete *it; + m_arrItems.erase( it ); + return _super::DeleteItem( nItem ); +} + +VOID CListViewCtrlEx::DeleteItem( LPDELETEITEMSTRUCT ) +{ + ATLASSERT(FALSE); +} + +BOOL CListViewCtrlEx::DeleteAllItems() +{ + //KAutoSync autoCS(&m_hListLock); +// m_ActorRefresh.Stop(); + + for(TListItemPtrs::iterator it=m_arrItems.begin(); it!=m_arrItems.end(); ++it) + delete *it; + m_arrItems.clear(); + m_RiskItemIDArray.RemoveAll(); + m_UnknownItemIDArray.RemoveAll(); + return _super::DeleteAllItems(); +} + + +BOOL CListViewCtrlEx::InSubItemCheckBox(const POINT& pt, int nItem ) +{ + return _PtInSubItemCheckBox(pt, nItem); +} + + +LRESULT CListViewCtrlEx::OnClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + bHandled = FALSE; + + LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE) pnmh; + + // - title collapsed + TListItem *pItem = _GetItemData(lpnmitem->iItem); + if(!pItem) + return 0; + + if(pItem->dwFlags & LISTITEM_TITLE) + { + if(pItem->dwFlags & LISTITEM_EXPANDABLE) + { + INT iItem = lpnmitem->iItem; + RECT rcItem = {0}; + if( GetItemRect(iItem, &rcItem, LVIR_BOUNDS) ) + { + _ExpandItem(pItem, lpnmitem->iItem, pItem->_isclapsed); + InvalidateRect( &rcItem ); + } + return 0; + } + } + else + { + // - link check + int iSubItem = lpnmitem->iSubItem; + if(_PtInSubItemLink(lpnmitem->ptAction, lpnmitem->iItem, iSubItem) ) + _FireEvent(WMH_LISTEX_LINK, lpnmitem->iItem, iSubItem); + else if( pItem->dwFlags & (LISTITEM_CHECKBOX|LISTITEM_RADIOBOX) ) + { + // - check box + BOOL bDirty = FALSE; + if (pItem->dwFlags&LISTITEM_RADIOBOX) + { + bDirty = TRUE; + SetRadioState( lpnmitem->iItem, !_super::GetCheckState(lpnmitem->iItem) ); + } + else if (_PtInSubItemCheckBox(lpnmitem->ptAction, lpnmitem->iItem)) + { + bDirty = TRUE; + SetCheckState( lpnmitem->iItem, !_super::GetCheckState(lpnmitem->iItem) ); + } + + if( bDirty ) + { + CRect rcItem; + GetItemRect( lpnmitem->iItem, &rcItem, LVIR_BOUNDS); + InvalidateRect( rcItem ); + } + + /*const TListSubItem *pSubItem = _GetSubItemData(lpnmitem->iItem,lpnmitem->iSubItem); + if(pSubItem->type==SUBITEM_COMBO) + { + + }*/ + } + } + return 0; +} + +void CListViewCtrlEx::OnPaint( CDCHandle ) +{ + if(m_arrItems.empty()) + { + CPaintDC dc(m_hWnd); + RECT rc = {0}; + GetClientRect( &rc ); + //dc.FillSolidRect(&rc, RGB(0,0,255)); + rc.top += 50; + HFONT hOldFont = dc.SelectFont(m_fontDef); + dc.DrawText(m_strEmptyString, -1, &rc, DT_SINGLELINE|DT_LEFT|DT_CENTER); + dc.SelectFont( hOldFont ); + } + else + { + SetMsgHandled(FALSE); + } +} + +void CListViewCtrlEx::OnMouseMove(UINT nFlags, CPoint point) +{ + TRACKMOUSEEVENT trkMouse; + trkMouse.cbSize = sizeof( TRACKMOUSEEVENT ); + trkMouse.dwFlags = TME_LEAVE; + trkMouse.hwndTrack = m_hWnd; + + // notify when the mouse leaves button + _TrackMouseEvent( &trkMouse ); + + CRect rcItem; + + LVHITTESTINFO hti; + hti.pt = point; + SubItemHitTest( &hti ); + + if( m_nHoverItem != hti.iItem || m_nHoverSubItem != hti.iSubItem) + { + m_nHoverItem = hti.iItem; + m_nHoverSubItem = hti.iSubItem; + _FireEvent(WMH_LISTEX_HOVERCHANGED, m_nHoverItem); + + KillTimer(XX_TIMER_ID_TIPS); + //CBkSafeTip::Hide(); + } + + static CPoint ptLast; + if (ptLast != point && hti.iItem != -1) + SetTimer(XX_TIMER_ID_TIPS, 200); + + ptLast = point; +} + +void CListViewCtrlEx::OnMouseLeave() +{ + KillTimer(XX_TIMER_ID_TIPS); + //CBkSafeTip::Hide(); +} + +void CListViewCtrlEx::OnTimer(UINT_PTR nIDEvent) +{ + if (nIDEvent == XX_TIMER_ID_TIPS) + { + CPoint ptx; + CPoint ptxbak; + ::GetCursorPos(&ptx); + ptxbak = ptx; + ptxbak.y -= 25; + ScreenToClient(&ptx); + + LVHITTESTINFO hti; + hti.pt = ptx; + SubItemHitTest( &hti ); + + const TListItem* pItem = _GetItemData( hti.iItem ); + //if (pItem && hti.iSubItem >= 0 && hti.iSubItem < pItem->subItems.size()) + // CBkSafeTip::Show(pItem->subItems[hti.iSubItem].str, ptxbak, m_hWnd); + + KillTimer(nIDEvent); + } +} + +BOOL CListViewCtrlEx::OnSetCursor(CWindow wnd, UINT nHitTest, UINT message) +{ + CPoint pt; + GetCursorPos( &pt ); + ScreenToClient( &pt ); + + LVHITTESTINFO hti; + hti.pt = pt; + SubItemHitTest( &hti ); + bool bInLink = _PtInSubItemLink(pt, hti.iItem, hti.iSubItem); + ::SetCursor(::LoadCursor(NULL, bInLink?IDC_HAND:IDC_ARROW)); + return TRUE; +} + +void CListViewCtrlEx::MeasureItem( LPMEASUREITEMSTRUCT lpMes ) +{ + /* + const TListItem *pItem = _GetItemData( lpMes->itemID ); + if(pItem) + { + if(pItem->dwFlags&LISTITEM_TITLE) + lpMes->itemHeight = 30; + else + lpMes->itemHeight = 28; + } + */ + + lpMes->itemHeight = 24; +} + +void CListViewCtrlEx::DrawItem( LPDRAWITEMSTRUCT lpdis ) +{ + int nItem = lpdis->itemID; + TListItem* pItem = _GetItemData( nItem ); + if(!pItem) + return; + if(pItem->dwFlags & LISTITEM_TITLE) + { + _DrawTitleItem(lpdis, pItem); + } + else + { + _DrawNormalItem(lpdis, pItem); + } + return; +} + +void CListViewCtrlEx::SetEmptyString( LPCTSTR szEmptyString ) +{ + if(szEmptyString) + m_strEmptyString = szEmptyString; + else + m_strEmptyString = _T(""); +} + +void CListViewCtrlEx::ExpandGroup( INT nItem, BOOL bExpand ) +{ + // - title collapsed + TListItem *pItem = _GetItemData( nItem ); + if(!pItem) + return; + + if( (pItem->dwFlags & LISTITEM_TITLE) + && (pItem->dwFlags & LISTITEM_EXPANDABLE) ) + { + BOOL needRedraw = _ExpandItem(pItem, nItem, bExpand); + RECT rcItem = {0}; + if( GetItemRect(nItem, &rcItem, LVIR_BOUNDS) ) + InvalidateRect( &rcItem ); + } +} + +void CListViewCtrlEx::_DrawTitleItem( LPDRAWITEMSTRUCT lpdis, const TListItem *pItem ) +{ + ATLASSERT(pItem); + + if(pItem->subItems.empty()) + return ; + + int nWinWidth=lpdis->rcItem.right-lpdis->rcItem.left; + CRect rcWindows; + GetWindowRect(rcWindows); + if ( nWinWidth > rcWindows.Width()) + nWinWidth = rcWindows.Width()-20; + + int nItem = lpdis->itemID; + + CDCHandle dc; + dc.Attach(lpdis->hDC); + dc.FillSolidRect( &lpdis->rcItem, pItem->clrBg); + HFONT hOldFont = dc.SelectFont(m_fontDef); + COLORREF clrOld = dc.GetTextColor(); + COLORREF clrDef = clrOld; + + // + RECT rcItem = lpdis->rcItem; + if( pItem->dwFlags&LISTITEM_EXPANDABLE ) + { + //3 + 9 + 3 + if(rcItem.left>-12) + { + CDC dcTmp; + dcTmp.CreateCompatibleDC(dc); + HBITMAP hBmpOld = dcTmp.SelectBitmap(m_bitmapExpand); + RECT rcMinus = _GetRectMinus(rcItem); + dc.BitBlt( rcMinus.left, rcMinus.top, 9, 9, dcTmp, pItem->_isclapsed? 9:0, 0, SRCCOPY); + dcTmp.SelectBitmap(hBmpOld); + } + } + + for ( int i = 0; i < pItem->subItems.size(); i++) + { + bool bVCenter=TRUE; + const TListSubItem& subItem = pItem->subItems[i]; + CRect rcItem = subItem.rcOffset; + if ( i == 0 ) + { + rcItem = lpdis->rcItem; + + if(pItem->nTopMargin>=0) + { + rcItem.top += pItem->nTopMargin; + rcItem.bottom -= 0; + bVCenter=FALSE; + } + else + { + rcItem.top += 2; + rcItem.bottom -= 2; + } + rcItem.left+= pItem->nLeftmargin; + } + else + { + if ( rcItem.left < 0 ) + { + rcItem.left = nWinWidth+rcItem.left; + } + if (rcItem.right < 0) + { + rcItem.right = nWinWidth+rcItem.right; + } + rcItem.OffsetRect( lpdis->rcItem.left, lpdis->rcItem.top); + } + + if ( subItem.type == SUBITEM_TEXT ) + { + dc.SetTextColor( subItem.clr); + dc.SelectFont(m_fontDef); + } + else if ( subItem.type == SUBITEM_LINK ) + { + dc.SelectFont(m_fontLink); + dc.SetTextColor(COLOR_LIST_LINK); + } + else + { + dc.SetTextColor( subItem.clr); + dc.SelectFont(m_fontDef); + } + + CString strTitle = subItem.str; + DWORD nFlag=DT_SINGLELINE|DT_LEFT|DT_NOPREFIX|DT_END_ELLIPSIS; + if(bVCenter) + nFlag|=DT_VCENTER; + + if (i==0&&pItem->bBold||pItem->nHeightAdd!=0) + { + HFONT fntOld=dc.SelectFont(BkFontPool::GetFont(pItem->bBold,FALSE,FALSE,pItem->nHeightAdd)); + dc.DrawText( strTitle, -1, &rcItem, nFlag); + dc.SelectFont(fntOld); + } + else + dc.DrawText( strTitle, -1, &rcItem, nFlag); + } + + CPen pex; + pex.CreatePen(PS_SOLID,1,pItem->clrBtmGapLine); + HPEN penOld = dc.SelectPen(pex); + dc.MoveTo( lpdis->rcItem.left, lpdis->rcItem.bottom-1 ); + dc.LineTo( lpdis->rcItem.right, lpdis->rcItem.bottom-1 ); + + dc.SetTextColor(clrOld); + dc.SelectPen(penOld); + dc.SelectFont(hOldFont); + dc.Detach(); +} + +void CListViewCtrlEx::_DrawNormalItem( LPDRAWITEMSTRUCT lpdis, const TListItem *pItem ) +{ + if (!pItem) + return; + + int nItem = lpdis->itemID; + + CDCHandle dc; + dc.Attach(lpdis->hDC); + + HFONT hOldFont = dc.SelectFont(m_fontDef); + + BOOL bSelect = FALSE ; + if ((lpdis->itemAction | ODA_SELECT) && + (lpdis->itemState & ODS_SELECTED)) + { + bSelect = TRUE ; + } + + if ( bSelect ) + dc.FillSolidRect( &lpdis->rcItem, RGB(185,219,255)); + else + dc.FillSolidRect( &lpdis->rcItem, pItem->clrBg); + + // draw check box + if( pItem->dwFlags&(LISTITEM_CHECKBOX|LISTITEM_RADIOBOX) ) + _DrawCheckBox(dc, lpdis->rcItem, _super::GetCheckState(nItem), pItem->dwFlags); + + COLORREF oldClr = dc.GetTextColor(); + for(int i=0; isubItems.size(); ++i) + { + CRect rcSubItem; + DWORD nMarginWidth = 0; + CRect rcBounds; + GetSubItemRect(nItem, i, LVIR_LABEL, &rcSubItem); + + nMarginWidth = LEFT_MARGIN_TEXT_COLUMN+3; + + if(i==0) + { + if( pItem->dwFlags&(LISTITEM_CHECKBOX|LISTITEM_RADIOBOX) ) + { + nMarginWidth+=rcSubItem.left; + } + else + { + rcSubItem.left -= 19; + nMarginWidth+=5; + } + } + +#define DT_FLAGS_DRAW_TEXT (DT_SINGLELINE|DT_LEFT|DT_NOPREFIX|DT_END_ELLIPSIS|DT_VCENTER) + + rcSubItem.left += LEFT_MARGIN_TEXT_COLUMN; + rcSubItem.right -= 3; + const TListSubItem &subItem = pItem->subItems[i]; + if(subItem.type == SUBITEM_LINK) + { + dc.SelectFont(m_fontLink); + dc.SetTextColor(COLOR_LIST_LINK); + + CRect rcProbeItem; + dc.DrawText( subItem.str, -1, &rcProbeItem, DT_SINGLELINE|DT_LEFT|DT_NOPREFIX|DT_VCENTER|DT_CALCRECT); + dc.DrawText( subItem.str, -1, &rcSubItem, DT_FLAGS_DRAW_TEXT); + + DWORD nMaxWidth = rcProbeItem.Width()+nMarginWidth; + _SetColumnNeedWidth(i,nMaxWidth); + } + else + { + if (subItem.type == SUBITEM_ICON && subItem.nImg != NULL) + { + dc.DrawIconEx( rcSubItem.left, rcSubItem.top + 3, (HICON)subItem.nImg, 16 , 16, 0, 0, DI_NORMAL ); + rcSubItem.left = rcSubItem.left + 18; + } + else if (subItem.type == SUBITEM_PNG) + { + Gdiplus::Image* pImg = BkPngPool::Get(subItem.nImg); + if (pImg) + { + Gdiplus::Graphics graphics(dc); + + SIZE size = {0, 0}; + if (pImg) + { + size.cx = pImg->GetWidth(); + size.cy = pImg->GetHeight(); + } + + graphics.DrawImage(pImg, Gdiplus::Rect(rcSubItem.left, rcSubItem.top + 5, size.cx, size.cy)); + } + rcSubItem.left = rcSubItem.left + 18; + }else if(subItem.type==SUBITEM_COMBO) + { + CDC dcTmp; + dcTmp.CreateCompatibleDC(dc); + HBITMAP hBmpOld = dcTmp.SelectBitmap(m_bitmapCombo); + dc.BitBlt(rcSubItem.right-20, rcSubItem.top + 3, 20, 20, dcTmp, 0, 0, SRCCOPY); + dcTmp.SelectBitmap(hBmpOld); + dcTmp.DeleteDC(); + } + + UINT uFormat = DT_SINGLELINE|DT_LEFT|DT_NOPREFIX|DT_PATH_ELLIPSIS|DT_VCENTER; + if (i == 3) + { + if (pItem->nLevel == enumLevelRisk) + { + rcSubItem.DeflateRect(2, 3); + + CPen penBorder; + penBorder.CreatePen( PS_SOLID, 1, RGB(224, 0, 0) ); + CBrush bshInterior; + bshInterior.CreateSolidBrush( RGB(224, 0, 0) ); + + HPEN hOldPen = dc.SelectPen( penBorder ); + HBRUSH hOldBrush = dc.SelectBrush( bshInterior ); + + dc.RoundRect( rcSubItem, CPoint( 3, 3 ) ); + dc.SelectPen(hOldPen); + dc.SelectBrush(hOldBrush); + dc.SetTextColor( RGB(255, 255, 255) ); + } + else if (pItem->nLevel == enumLevelUnknown) + { + rcSubItem.DeflateRect(2, 3); + + CPen penBorder; + penBorder.CreatePen( PS_SOLID, 1, RGB(250, 115, 5) ); + CBrush bshInterior; + bshInterior.CreateSolidBrush( RGB(250, 115, 5) ); + + HPEN hOldPen = dc.SelectPen( penBorder ); + HBRUSH hOldBrush = dc.SelectBrush( bshInterior ); + + dc.RoundRect( rcSubItem, CPoint( 3, 3 ) ); + dc.SelectPen(hOldPen); + dc.SelectBrush(hOldBrush); + dc.SetTextColor( RGB(255, 255, 255) ); + } + else + dc.SetTextColor( subItem.clr ); + + uFormat = DT_SINGLELINE|DT_CENTER|DT_NOPREFIX|DT_PATH_ELLIPSIS|DT_VCENTER; + } + else + dc.SetTextColor( subItem.clr ); + + dc.DrawText( subItem.str, -1, &rcSubItem, uFormat); + if (subItem.type == SUBITEM_ICON || subItem.type == SUBITEM_PNG) + rcSubItem.left = rcSubItem.left - 18; + + CRect rcProbeItem; + dc.DrawText( subItem.str, -1, &rcProbeItem, DT_SINGLELINE|DT_LEFT|DT_NOPREFIX|DT_VCENTER|DT_CALCRECT); + DWORD nMaxWidth = rcProbeItem.Width()+nMarginWidth; + _SetColumnNeedWidth(i,nMaxWidth); + } + } + + CPen penx; + penx.CreatePen(PS_SOLID,1,pItem->clrBtmGapLine); + HPEN penOld = dc.SelectPen(penx); + dc.MoveTo( lpdis->rcItem.left, lpdis->rcItem.bottom-1 ); + CRect rcClient; + GetClientRect(rcClient); + + dc.LineTo( lpdis->rcItem.left + rcClient.Width(), lpdis->rcItem.bottom-1); + dc.SelectPen(penOld); + + dc.SelectFont(hOldFont); + dc.SetTextColor(oldClr); + dc.Detach(); +} + +const CListViewCtrlEx::TListSubItem * CListViewCtrlEx::_GetSubItemData( int nItem, int nSubItem ) +{ + if(nItem>=0 && nItem &subItems = m_arrItems[nItem]->subItems; + if(nSubItem>=0 && nSubItem= m_arrItems.size()) + return NULL; + + if (m_bOnlyShowRisk) + { + if (nItem >= m_RiskItemIDArray.GetSize()) + return NULL; + + return m_arrItems[m_RiskItemIDArray[nItem]]; + } + else + return m_arrItems[nItem]; +} + +CListViewCtrlEx::TListItem * CListViewCtrlEx::_GetItemData( int nItem ) +{ + if (nItem < 0 || nItem >= m_arrItems.size()) + return NULL; + + if (m_bOnlyShowRisk) + { + if (nItem >= m_RiskItemIDArray.GetSize()) + return NULL; + + return m_arrItems[m_RiskItemIDArray[nItem]]; + } + else + return m_arrItems[nItem]; +} + +BOOL CListViewCtrlEx::_PtInSubItemCheckBox( const POINT& pt, int nItem ) +{ + RECT rcItem = {0}; + if( nItem>=0 && nItem<_super::GetItemCount() && GetItemRect(nItem, &rcItem, LVIR_BOUNDS) ) + { + TListItem *pItem = _GetItemData(nItem); + + // + if( pItem && pItem->dwFlags&(LISTITEM_CHECKBOX|LISTITEM_RADIOBOX) ) + { + RECT rcCheckBox = _GetRectCheckBox( rcItem ); + return PtInRect(&rcCheckBox, pt); + } + } + return FALSE; +} + +BOOL CListViewCtrlEx::_GetSubItemLinkRect( int nItem, int nSubItem, LPCTSTR szText, RECT &rc ) +{ + _super::GetSubItemRect( nItem, nSubItem, LVIR_LABEL, &rc ); + HDC hDC = GetWindowDC(); + if(!hDC) + return FALSE; + + rc.left += LEFT_MARGIN_TEXT_COLUMN; + CDC dc; + dc.Attach( hDC ); + HFONT hOldFont = dc.SelectFont(m_fontLink); + dc.DrawText( szText, -1, &rc, DT_CALCRECT|DT_SINGLELINE|DT_LEFT|DT_NOPREFIX|DT_END_ELLIPSIS|DT_VCENTER ); + dc.SelectFont(hOldFont); + dc.Detach(); + ReleaseDC( hDC ); + return TRUE; +} + +bool CListViewCtrlEx::_PtInSubItemLink( const POINT &pt, int nItem, int& nSubItem ) +{ + if( nItem>=0 && nItem<_super::GetItemCount() ) + { + TListItem *pItem = _GetItemData(nItem); + if (!pItem) + return false; + + if ( pItem->dwFlags & LISTITEM_TITLE ) + { + for ( int i = 0; i < pItem->subItems.size(); i++) + { + const TListSubItem& subItem = pItem->subItems[i]; + if ( subItem.type == SUBITEM_LINK) + { + CRect rcItem; + CRect rcLink = subItem.rcOffset; + GetItemRect(nItem,rcItem, LVIR_BOUNDS); + rcLink.OffsetRect(rcItem.left, rcItem.top); + if ( rcLink.PtInRect(pt) ) + { + nSubItem = i; + return true; + } + } + } + } + else if(nSubItem>=0 && nSubItemsubItems.size()) + { + const TListSubItem &subItem = pItem->subItems[nSubItem]; + if( subItem.type==SUBITEM_LINK ) + { + // Check if in LINK Rect + RECT rcLink = {0}; + return _GetSubItemLinkRect(nItem, nSubItem, subItem.str, rcLink) && PtInRect(&rcLink, pt); + } + } + } + return false; +} + +int CListViewCtrlEx::_DrawCheckBox( CDCHandle &dc, RECT &rcItem, BOOL bChecked, DWORD dwFlags ) +{ + if(rcItem.left>-16) + { + CDC dcTmp; + dcTmp.CreateCompatibleDC(dc); + + RECT rcCheckBox = _GetRectCheckBox( rcItem ); + HBITMAP hBmpOld = NULL; + int x=rcCheckBox.left + 3, y=rcCheckBox.top, nWidth=13, nHeight=13, xSrc=bChecked ? 0 : 13, ySrc=0; + + if(dwFlags&LISTITEM_CHECKBOX) + { + hBmpOld = dcTmp.SelectBitmap(m_bitmapCheck); + dc.BitBlt(x, y, nWidth, nHeight, dcTmp, xSrc, ySrc, SRCCOPY); + } + else + { + // Need Mask + hBmpOld = dcTmp.SelectBitmap(m_bitmapRadioMask); + dc.BitBlt(x, y, nWidth, nHeight, dcTmp, xSrc, ySrc, SRCAND); + dcTmp.SelectBitmap(m_bitmapRadio); + dc.BitBlt(x, y, nWidth, nHeight, dcTmp, xSrc, ySrc, SRCPAINT); + } + + dcTmp.SelectBitmap(hBmpOld); + dcTmp.DeleteDC(); + } + return 3 + 13 + 3; +} + +RECT CListViewCtrlEx::_GetRectCheckBox( RECT &rcItem ) +{ + INT nHeight = rcItem.bottom - rcItem.top; + int nTop = rcItem.top + (nHeight-13)/2; + RECT rcCheckBox = {rcItem.left+3, nTop, rcItem.left+3+13, nTop+13}; + return rcCheckBox; +} + + +RECT CListViewCtrlEx::_GetRectMinus( RECT &rcItem ) +{ + INT nHeight = rcItem.bottom - rcItem.top; + int nTop = rcItem.top + (nHeight-9)/2; + RECT rcMinus = {rcItem.left+3, nTop, rcItem.left+3+9, nTop+9}; + return rcMinus; +} + +void CListViewCtrlEx::_InvalidateRect( int nItem, int nSubItem ) +{ + RECT rcItem = {0}; + //_super::GetItemRect(nItem, &rcItem, LVIR_BOUNDS); + _super::GetSubItemRect(nItem, nSubItem, LVIR_LABEL, &rcItem); + InvalidateRect( &rcItem ); +} + +BOOL CListViewCtrlEx::_FireEvent( UINT message, WPARAM wParam /*= 0*/, LPARAM lParam /*= 0*/ ) +{ + if(m_hWndObserver) + return ::PostMessage(m_hWndObserver, message, wParam, lParam); + else + return GetParent().PostMessage(message, wParam, lParam); +} + +void CListViewCtrlEx::_SetColumnNeedWidth( int i, DWORD nWidth ) +{ + if ((int)nWidth<=0) + { + return; + } + + DWORD nOrgWidth = 0; + if ( m_columnMaxWidth.Lookup(i, nOrgWidth) ) + { + if ( nOrgWidth < nWidth ) + m_columnMaxWidth.SetAt(i,nWidth); + } + else + m_columnMaxWidth.SetAt(i,nWidth); +} + +LRESULT CListViewCtrlEx::OnTrackDbClickHeader( int idCtrl, LPNMHDR pnmhx, BOOL& bHandled ) +{ + DWORD nWidth = 0; + LPNMHEADER pnmh = (LPNMHEADER)pnmhx; + + bHandled = FALSE; + INT col = pnmh->iItem; + if ( m_columnMaxWidth.Lookup(col,nWidth) ) + { + SetColumnWidth(pnmh->iItem,nWidth); + InvalidateRect(NULL); + bHandled = TRUE; + return S_OK; + } + + return S_OK; +} + +void CListViewCtrlEx::Reset() +{ + m_columnMaxWidth.RemoveAll(); +} + +void CListViewCtrlEx::_RedrawTitle() +{ + for ( int i = 0; i < GetItemCount(); i++) + { + TListItem* pItem = (TListItem*)_GetItemData(i); + + if ( pItem && pItem->dwFlags&LISTITEM_TITLE) + { + CListViewCtrl::RedrawItems(i,i); + } + } +} + +LRESULT CListViewCtrlEx::OnTrackMoveHeader( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + bHandled = TRUE; + //_RedrawTitle(); + //InvalidateRect(NULL); + return S_OK; +} + +LRESULT CListViewCtrlEx::OnHeaderEndTrack( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + //bHandled = FALSE; + bHandled = TRUE; + InvalidateRect(NULL); + return S_OK; +} + +BOOL CListViewCtrlEx::_ExpandItem( TListItem * pItem, INT iItem, BOOL expand ) +{ + if(expand && pItem->_isclapsed) + { + // expand if collapsed + _super::SetRedraw(FALSE); + + TListItemPtrs::iterator it = std::find(m_arrItems.begin(), m_arrItems.end(), pItem); + ATLASSERT( it!=m_arrItems.end() ); + ++it; + m_arrItems.insert(it, pItem->_clapsed_items.begin(), pItem->_clapsed_items.end()); + + INT nNext = iItem + 1; + for(int i=0; i_clapsed_items.size(); ++i) + { + _super::AddItem(nNext, 0, _T("")); + _super::SetItemData( nNext, pItem->_clapsed_items[i]->_itemData ); + ++nNext; + } + _super::SelectItem( iItem ); + pItem->_clapsed_items.clear(); + pItem->_isclapsed = FALSE; + + _super::SetRedraw(TRUE); +#if 0 + _tcprintf(_T("-ListCtrlEx expanded %d\n"), _super::GetItemCount()); + for(int i=0; i<_super::GetItemCount(); ++i) + { + _tcprintf(_T("%d - %s %x\n"), i, m_arrItems[i]->subItems[1].str, _super::GetItemData(i)); + } +#endif + return TRUE; + } + else if(!expand && !pItem->_isclapsed) + { + _super::SetRedraw(FALSE); + // collapse if expanded + int nEnd = iItem; + for( int i=iItem+1; i<_super::GetItemCount(); ++i) + { + TListItem *p = _GetItemData( i ); + if (!p) + break; + if(p->dwFlags & LISTITEM_TITLE) + break; + + p->_itemData = _super::GetItemData( i ); + pItem->_clapsed_items.push_back( p ); + nEnd = i; + } + + for(int i=nEnd; i > iItem; --i) + { + TListItemPtrs::iterator it = m_arrItems.begin(); + if(i>0) + std::advance(it, i); + _super::DeleteItem( i ); + m_arrItems.erase( it ); + } + pItem->_isclapsed = TRUE; + _super::SetRedraw(TRUE); + return TRUE; + } + return FALSE; +} + +#pragma warning(pop) \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkwin/ListViewCtrlEx.h b/Client/Client/GUI/BKWin/bkwin/ListViewCtrlEx.h new file mode 100644 index 00000000..c847eca7 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/ListViewCtrlEx.h @@ -0,0 +1,333 @@ +#pragma once + +#include "../wtl/atlcrack.h" +#include +//#include "KActor.h" + + +#define MSG_DEL_ALL (WM_APP + 200) +#define MSG_ADD_ITEM (WM_APP + 201) + +class CHeaderCtrlEx : public CWindowImpl +{ +public: + CHeaderCtrlEx(); + virtual ~CHeaderCtrlEx(); + void SetHeight(INT nHeight); + + +protected: + void OnPaint(CDCHandle dc); + BOOL OnEraseBkgnd(CDCHandle dc); + LRESULT OnHDMLayout(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + + LRESULT OnMouseMove(UINT nFlags, CPoint point); + +protected: + CBitmap m_bitmapHeader; + CFont m_font; + INT m_nHeight; + + CRBMap m_mapHeaderDrag; + +public: + BEGIN_MSG_MAP_EX(CHeaderCtrlEx) + MSG_WM_PAINT(OnPaint) + MSG_WM_MOUSEMOVE(OnMouseMove) + MSG_WM_ERASEBKGND(OnEraseBkgnd) + MESSAGE_HANDLER(HDM_LAYOUT, OnHDMLayout) + END_MSG_MAP() +}; + +enum E_SubItemType +{ + SUBITEM_TEXT, + SUBITEM_LINK, + SUBITEM_ICON, + SUBITEM_PNG, + SUBITEM_COMBO +}; + +enum E_ListItemType +{ + LISTITEM_TITLE = 1, + LISTITEM_CHECKBOX = 2, + LISTITEM_RADIOBOX = 4, + LISTITEM_EXPANDABLE = 8, + LISTITEM_BOLD = 16, +}; + +enum E_ListTitleType +{ + LISTTITLE_DEFAULT = 0x1, + + LISTITEM_THIRD_LINE_TOP = 0x2, + LISTITEM_THIRD_LINE_MID = 0x4, + LISTITEM_THIRD_LINE_BTM = 0x8, + + // + LISTTILTE_CENTER=0x10, +}; + +class CListViewCtrlEx : + public CWindowImpl, + public COwnerDraw +{ + typedef CWindowImpl _super; + +public: + typedef enum _LEVEL + { + enumLevelSafe, + enumLevelRisk, + enumLevelUnknown + } LEVEL; + struct TListItem; + struct TListSubItem; + typedef std::vector TListItemPtrs; + typedef std::vector TListSubItems; + struct TListSubItem + { + TListSubItem() : type(SUBITEM_TEXT) + { + nMarginLeft = 2; + clr = RGB(0,0,0); + rcOffset = CRect(0,0,0,0); + nImg = 0; + } + + TListSubItem(LPCTSTR szText, CRect rc, E_SubItemType aType = SUBITEM_TEXT) + : str(szText), type(aType), rcOffset(rc) + { + nImg = 0; + } + + TListSubItem(LPCTSTR szText, E_SubItemType aType = SUBITEM_TEXT) + : str(szText), type(aType) + { + rcOffset = CRect(0,0,0,0); + nMarginLeft = 2; + clr = RGB(0,0,0); + nImg = 0; + ATLASSERT(szText); + } + + TListSubItem(LPCTSTR szText, HICON hIcon, E_SubItemType aType = SUBITEM_ICON) + : str(szText), nImg((DWORD)hIcon), type(aType) + { + rcOffset = CRect(0,0,0,0); + nMarginLeft = 2; + clr = RGB(0,0,0); + ATLASSERT(szText); + } + + TListSubItem(LPCTSTR szText, DWORD nImgId, E_SubItemType aType = SUBITEM_PNG) + : str(szText), nImg(nImgId), type(aType) + { + rcOffset = CRect(0,0,0,0); + nMarginLeft = 2; + clr = RGB(0,0,0); + ATLASSERT(szText); + } + + E_SubItemType type; + CString str; + COLORREF clr; + int nMarginLeft; + CRect rcOffset; + CString strUrl; + DWORD nImg; + }; + + struct TListItem + { + public: + TListItem() + { + dwFlags =0; + clrBg = RGB(0xfb,0xfc,0xfd); + clrBtmGapLine=RGB(234,233,225); + nLeftmargin =10; + nTopMargin =-1; + bBold =FALSE; + nHeightAdd =0; + + _isclapsed = FALSE; + } + ~TListItem() + { + for(TListItemPtrs::iterator it=_clapsed_items.begin(); it!=_clapsed_items.end(); ++it) + delete *it; + _clapsed_items.clear(); + } + + int nLeftmargin; + int nTopMargin; + BOOL bBold; + int nHeightAdd; + DWORD dwFlags; + COLORREF clrBg; + COLORREF clrBtmGapLine; + TListSubItems subItems; + + LEVEL nLevel; + DWORD dwMapId; + + BOOL _isclapsed; + TListItemPtrs _clapsed_items; + DWORD_PTR _itemData; + int nRiskRefIndex; + }; + +public: + CListViewCtrlEx(void); + ~CListViewCtrlEx(void); + CHeaderCtrlEx m_ctlHeader; + +protected: + CFont m_fontLink, m_fontBold, m_fontTitle, m_fontDef; + CBitmap m_bitmapCheck, m_bitmapExpand, m_bitmapRadio,m_bitmapCombo; + CBitmap m_bitmapRadioMask; + int m_nHoverItem; + int m_nHoverSubItem; + + TListItemPtrs m_arrItems; + HWND m_hWndObserver; + + CString m_strEmptyString; + bool m_bOnlyShowRisk; + CSimpleArray m_RiskItemIDArray; + CSimpleArray m_UnknownItemIDArray; + CRITICAL_SECTION m_hListLock; + //KActor m_ActorRefresh; + +public: + HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL); + BOOL GetCheckState(int nIndex, BOOL *pIsRadio=NULL) const; + BOOL SetCheckState(int nItem, BOOL bCheck); + int SetRadioState(int nItem, BOOL bCheck); // -1: not valid , 0 : not checked, 1: checked + + void ClearRadioCheck(); + void CleanCheck( int nItem=-1 ); + void CheckAll( ); + template void CheckAll(Func fn) + { + ClearRadioCheck(); + for(int i=0; i<_super::GetItemCount(); ++i) + { + T_VulListItemData *pItemData = (T_VulListItemData*)_super::GetItemData(i); + TListItem *pItem = _GetItemData( i ); + if( pItem && (pItem->dwFlags&LISTITEM_CHECKBOX) ) + { + _super::SetCheckState( i, fn(pItemData) ); + } + } + } + void SetObserverWindow(HWND hWnd); + +protected: + DWORD SetExtendedListViewStyle(DWORD dwExStyle, DWORD dwExMask = 0) + { + ATLASSERT(FALSE); + return _super::SetExtendedListViewStyle(dwExStyle, dwExMask); + } + int AddItem(int nItem, int nSubItem, LPCTSTR strItem, int nImageIndex = -1) + { + ATLASSERT(FALSE); + return _super::AddItem(nItem, nSubItem, strItem, nImageIndex); + } + BOOL SetItemText(int nItem, int nSubItem, LPCTSTR lpszText) + { + ATLASSERT(FALSE); + return _super::SetItemText(nItem, nSubItem, lpszText); + } + +public: + void Reset(); + + int AppendTitle(LPCTSTR strItem, COLORREF clr, UINT uFlags=0); + int AppendTitleItem(int nItem, LPCTSTR strItem, CRect rc, E_SubItemType itemType, COLORREF clr, LPCTSTR szURL); + int Append(LPCTSTR strItem, DWORD dwFlags=0, E_SubItemType itemType=SUBITEM_TEXT); + int Append(LPCTSTR strItem, HICON hIcon, LEVEL nLevel = enumLevelSafe, DWORD dwFlags = 0); + int Append(LPCTSTR strItem, HICON hIcon, DWORD dwMapId, DWORD dwFlags = 0); + int AppendSubItem(int nItem, LPCTSTR strItem, E_SubItemType itemType = SUBITEM_TEXT); + int AppendSubItem(int nItem, LPCTSTR strItem, DWORD dwImg, E_SubItemType itemType); + bool SetSubItem(int nItem, int nSubItem, LPCTSTR lpszItem, E_SubItemType itemType=SUBITEM_TEXT, BOOL bRedraw=TRUE); + bool GetSubItemText(int nItem, int nSubItem, CString &str); + bool SetSubItemColor(int nItem, int nSubItem, COLORREF clr, BOOL bRedraw=TRUE); + bool SetItemCheckX(int nItem, DWORD dwFlags); + BOOL DeleteItem(int nItem); + BOOL DeleteAllItems(); + void SetEmptyString(LPCTSTR szEmptyString); + void ExpandGroup(INT nItem, BOOL bExpand); + + void SetOnlyShowRisk(bool bShowRisk); + DWORD GetAllSafeCount(); + DWORD GetAllRiskCount(); + DWORD GetAllUnknownCount(); + + //////////////////////////z//////////////////////////////////////////////// + // ʵIActorCallBack + //virtual void OnActivate(KActor* pActor); + +public: + BEGIN_MSG_MAP(CListViewCtrlEx) + MSG_WM_PAINT(OnPaint) + MSG_WM_MOUSEMOVE(OnMouseMove) + MSG_WM_MOUSELEAVE(OnMouseLeave) + MSG_WM_SETCURSOR(OnSetCursor) + //MSG_WM_TIMER(OnTimer) + NOTIFY_CODE_HANDLER(NM_CLICK, OnClick) + NOTIFY_CODE_HANDLER(HDN_DIVIDERDBLCLICK , OnTrackDbClickHeader) + NOTIFY_CODE_HANDLER(HDN_TRACK , OnTrackMoveHeader) + NOTIFY_CODE_HANDLER(HDN_ENDTRACK , OnHeaderEndTrack) + MESSAGE_HANDLER_EX(MSG_DEL_ALL, OnDeleteAll) + MESSAGE_HANDLER_EX(MSG_ADD_ITEM, OnAddItem) + REFLECTED_NOTIFY_CODE_HANDLER(NM_CLICK, OnClick) + CHAIN_MSG_MAP_ALT(COwnerDraw, 1) + DEFAULT_REFLECTION_HANDLER() + END_MSG_MAP() + + void OnPaint(CDCHandle dc); + void OnMouseMove(UINT nFlags, CPoint point); + void OnMouseLeave(); + void OnTimer(UINT_PTR nIDEvent); + BOOL OnSetCursor(CWindow wnd, UINT nHitTest, UINT message); + LRESULT OnClick(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + + LRESULT OnTrackDbClickHeader(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnTrackMoveHeader(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnHeaderEndTrack(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnDeleteAll(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam); + LRESULT OnAddItem(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam); + + void MeasureItem(LPMEASUREITEMSTRUCT lpMes); + void DrawItem ( LPDRAWITEMSTRUCT lpdis ); + VOID DeleteItem(LPDELETEITEMSTRUCT ); + +public: + const TListItem *_GetItemData(int nItem) const; + TListItem *_GetItemData(int nItem); + const TListSubItem *_GetSubItemData(int nItem, int nSubItem); + BOOL InSubItemCheckBox(const POINT& pt, int nItem ); + +protected: + void _DrawTitleItem( LPDRAWITEMSTRUCT lpdis, const TListItem *pItem ); + void _DrawNormalItem( LPDRAWITEMSTRUCT lpdis, const TListItem *pItem ); + BOOL _PtInSubItemCheckBox( const POINT& pt, int nItem ); + BOOL _GetSubItemLinkRect( int nItem, int nSubItem, LPCTSTR szText, RECT &rc ); + bool _PtInSubItemLink( const POINT &pt, int nItem, int & nSubItem ); + int _DrawCheckBox( CDCHandle &dc, RECT &rcItem, BOOL bChecked, DWORD dwFlags ); + RECT _GetRectCheckBox( RECT &rcItem ); + RECT _GetRectMinus( RECT &rcItem ); + void _InvalidateRect( int nItem, int nSubItem ); + BOOL _FireEvent(UINT message, WPARAM wParam = 0, LPARAM lParam = 0); + + void _SetColumnNeedWidth(int i, DWORD nWidth); + void _RedrawTitle(); + BOOL _ExpandItem( TListItem * pItem, INT iItem, BOOL expand ); +protected: + CRBMap m_columnMaxWidth; +}; diff --git a/Client/Client/GUI/BKWin/bkwin/Schemadef.h b/Client/Client/GUI/BKWin/bkwin/Schemadef.h new file mode 100644 index 00000000..618ec60c --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/Schemadef.h @@ -0,0 +1,93 @@ +//----------------------------------------------------------------- +// SchemaDef.h - defines needed to build a Theme Manager schema +// file +//----------------------------------------------------------------- +#ifndef SCHEMA_STRINGS // FIRST PASS of this hdr file +//----------------------------------------------------------------- +#ifndef SCHEMADEF_H +#define SCHEMADEF_H +//----------------------------------------------------------------- +#define SCHEMADEF_VERSION 1 // defines the exported func(s) implemented +//----------------------------------------------------------------- +struct TMPROPINFO +{ + LPCWSTR pszName; + SHORT sEnumVal; + BYTE bPrimVal; +}; +//----------------------------------------------------------------- +struct TMSCHEMAINFO +{ + DWORD dwSize; // size of this struct + int iSchemaDefVersion; // version number from this file + int iThemeMgrVersion; // version number from "thschema.h" + int iPropCount; // # of entries in prop table + const struct TMPROPINFO *pPropTable; // ptr to prop table +}; +//--------------------------------------------------------------------------- +#define BEGIN_TM_SCHEMA(name) +#define BEGIN_TM_PROPS() enum PropValues { DummyProp = 49, +#define BEGIN_TM_ENUM(name) enum name { +#define BEGIN_TM_CLASS_PARTS(name) enum name##PARTS { name##PartFiller0, +#define BEGIN_TM_PART_STATES(name) enum name##STATES { name##StateFiller0, + +#define TM_PROP(val, prefix, name, primval) prefix##_##name = val, +#define TM_ENUM(val, prefix, name) prefix##_##name = val, +#define TM_PART(val, prefix, name) prefix##_##name = val, +#define TM_STATE(val, prefix, name) prefix##_##name = val, + +#define END_TM_CLASS_PARTS() }; +#define END_TM_PART_STATES() }; +#define END_TM_PROPS() }; +#define END_TM_ENUM() }; +#define END_TM_SCHEMA(name) +//--------------------------------------------------------------------------- +#endif // SCHEMADEF_H +//--------------------------------------------------------------------------- +#else // SECOND PASS of this hdr file +//--------------------------------------------------------------------------- +#undef BEGIN_TM_SCHEMA +#undef BEGIN_TM_PROPS +#undef BEGIN_TM_ENUM +#undef BEGIN_TM_CLASS_PARTS +#undef BEGIN_TM_PART_STATES +#undef TM_PROP +#undef TM_PART +#undef TM_STATE +#undef TM_ENUM +#undef END_TM_CLASS_PARTS +#undef END_TM_PART_STATES +#undef END_TM_PROPS +#undef END_TM_ENUM +#undef END_TM_SCHEMA +//--------------------------------------------------------------------------- +#define BEGIN_TM_SCHEMA(name) static const TMPROPINFO name[] = { +#define BEGIN_TM_PROPS() +#define BEGIN_TM_ENUM(name) {L#name, TMT_ENUMDEF, TMT_ENUMDEF}, +#define BEGIN_TM_CLASS_PARTS(name) {L#name L"PARTS", TMT_ENUMDEF, TMT_ENUMDEF}, +#define BEGIN_TM_PART_STATES(name) {L#name L"STATES", TMT_ENUMDEF, TMT_ENUMDEF}, + +#define TM_PROP(val, prefix, name, primval) {L#name, prefix##_##name, TMT_##primval}, +#define TM_PART(val, prefix, name) {L#name, prefix##_##name, TMT_ENUMVAL}, +#define TM_STATE(val, prefix, name) {L#name, prefix##_##name, TMT_ENUMVAL}, +#define TM_ENUM(val, prefix, name) {L#name, prefix##_##name, TMT_ENUMVAL}, + +#define END_TM_CLASS_PARTS() +#define END_TM_PART_STATES() +#define END_TM_PROPS() +#define END_TM_ENUM() +#define END_TM_SCHEMA(name) }; \ + static const TMSCHEMAINFO *GetSchemaInfo() \ + { \ + static TMSCHEMAINFO si = {sizeof(si)}; \ + si.iSchemaDefVersion = SCHEMADEF_VERSION; \ + si.iThemeMgrVersion = THEMEMGR_VERSION; \ + si.iPropCount = sizeof(name)/sizeof(name[0]); \ + si.pPropTable = name; \ + \ + return &si; \ + } + +//----------------------------------------------------------------- +#endif +//----------------------------------------------------------------- diff --git a/Client/Client/GUI/BKWin/bkwin/Tmschema.h b/Client/Client/GUI/BKWin/bkwin/Tmschema.h new file mode 100644 index 00000000..aaf4760d --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/Tmschema.h @@ -0,0 +1,1221 @@ +//----------------------------------------------------------------- +// TmSchema.h - Theme Manager schema (properties, parts, etc) +//----------------------------------------------------------------- +// Note: this file is normally #include-ed twice a single .cpp +// file. The 2nd time, SCHEME_STRINGS should be defined. +// This allows the enums and strings to be kept in a +// single logical table and ensure they stay in sync with +// each other. +//----------------------------------------------------------------- +#if (defined(SCHEMA_STRINGS)) || (! defined(TMSCHEMA_H)) +//----------------------------------------------------------------- +#define TMSCHEMA_H +//----------------------------------------------------------------- +#include "SchemaDef.h" +//----------------------------------------------------------------- +#define THEMEMGR_VERSION 1 // increment if order of props changes or + // any props are deleted (will prevent loading + // of controlsets that use older version +//----------------------------------------------------------------- +BEGIN_TM_SCHEMA(ThemeMgrSchema) + +//----------------------------------------------------------------- +// TM_ENUM (must also be declared in PROPERTIES section) +// +// these cannot be renumbered (part of uxtheme API) +//----------------------------------------------------------------- +BEGIN_TM_ENUM(BGTYPE) + TM_ENUM(0, BT, IMAGEFILE) + TM_ENUM(1, BT, BORDERFILL) + TM_ENUM(2, BT, NONE) +END_TM_ENUM() + +BEGIN_TM_ENUM(IMAGELAYOUT) + TM_ENUM(0, IL, VERTICAL) + TM_ENUM(1, IL, HORIZONTAL) +END_TM_ENUM() + +BEGIN_TM_ENUM(BORDERTYPE) + TM_ENUM(0, BT, RECT) + TM_ENUM(1, BT, ROUNDRECT) + TM_ENUM(2, BT, ELLIPSE) +END_TM_ENUM() + +BEGIN_TM_ENUM(FILLTYPE) + TM_ENUM(0, FT, SOLID) + TM_ENUM(1, FT, VERTGRADIENT) + TM_ENUM(2, FT, HORZGRADIENT) + TM_ENUM(3, FT, RADIALGRADIENT) + TM_ENUM(4, FT, TILEIMAGE) +END_TM_ENUM() + +BEGIN_TM_ENUM(SIZINGTYPE) + TM_ENUM(0, ST, TRUESIZE) + TM_ENUM(1, ST, STRETCH) + TM_ENUM(2, ST, TILE) +END_TM_ENUM() + +BEGIN_TM_ENUM(HALIGN) + TM_ENUM(0, HA, LEFT) + TM_ENUM(1, HA, CENTER) + TM_ENUM(2, HA, RIGHT) +END_TM_ENUM() + +BEGIN_TM_ENUM(CONTENTALIGNMENT) + TM_ENUM(0, CA, LEFT) + TM_ENUM(1, CA, CENTER) + TM_ENUM(2, CA, RIGHT) +END_TM_ENUM() + +BEGIN_TM_ENUM(VALIGN) + TM_ENUM(0, VA, TOP) + TM_ENUM(1, VA, CENTER) + TM_ENUM(2, VA, BOTTOM) +END_TM_ENUM() + +BEGIN_TM_ENUM(OFFSETTYPE) + TM_ENUM(0, OT, TOPLEFT) + TM_ENUM(1, OT, TOPRIGHT) + TM_ENUM(2, OT, TOPMIDDLE) + TM_ENUM(3, OT, BOTTOMLEFT) + TM_ENUM(4, OT, BOTTOMRIGHT) + TM_ENUM(5, OT, BOTTOMMIDDLE) + TM_ENUM(6, OT, MIDDLELEFT) + TM_ENUM(7, OT, MIDDLERIGHT) + TM_ENUM(8, OT, LEFTOFCAPTION) + TM_ENUM(9, OT, RIGHTOFCAPTION) + TM_ENUM(10, OT, LEFTOFLASTBUTTON) + TM_ENUM(11, OT, RIGHTOFLASTBUTTON) + TM_ENUM(12, OT, ABOVELASTBUTTON) + TM_ENUM(13, OT, BELOWLASTBUTTON) +END_TM_ENUM() + +BEGIN_TM_ENUM(ICONEFFECT) + TM_ENUM(0, ICE, NONE) + TM_ENUM(1, ICE, GLOW) + TM_ENUM(2, ICE, SHADOW) + TM_ENUM(3, ICE, PULSE) + TM_ENUM(4, ICE, ALPHA) +END_TM_ENUM() + +BEGIN_TM_ENUM(TEXTSHADOWTYPE) + TM_ENUM(0, TST, NONE) + TM_ENUM(1, TST, SINGLE) + TM_ENUM(2, TST, CONTINUOUS) +END_TM_ENUM() + +BEGIN_TM_ENUM(GLYPHTYPE) + TM_ENUM(0, GT, NONE) + TM_ENUM(1, GT, IMAGEGLYPH) + TM_ENUM(2, GT, FONTGLYPH) +END_TM_ENUM() + +BEGIN_TM_ENUM(IMAGESELECTTYPE) + TM_ENUM(0, IST, NONE) + TM_ENUM(1, IST, SIZE) + TM_ENUM(2, IST, DPI) +END_TM_ENUM() + +BEGIN_TM_ENUM(TRUESIZESCALINGTYPE) + TM_ENUM(0, TSST, NONE) + TM_ENUM(1, TSST, SIZE) + TM_ENUM(2, TSST, DPI) +END_TM_ENUM() + +BEGIN_TM_ENUM(GLYPHFONTSIZINGTYPE) + TM_ENUM(0, GFST, NONE) + TM_ENUM(1, GFST, SIZE) + TM_ENUM(2, GFST, DPI) +END_TM_ENUM() + +//----------------------------------------------------------------- +// PROPERTIES - used by uxtheme rendering and controls +// +// these cannot be renumbered (part of uxtheme API) +//----------------------------------------------------------------- +BEGIN_TM_PROPS() + + //---- primitive types ---- + TM_PROP(201, TMT, STRING, STRING) + TM_PROP(202, TMT, INT, INT) + TM_PROP(203, TMT, BOOL, BOOL) + TM_PROP(204, TMT, COLOR, COLOR) + TM_PROP(205, TMT, MARGINS, MARGINS) + TM_PROP(206, TMT, FILENAME, FILENAME) + TM_PROP(207, TMT, SIZE, SIZE) + TM_PROP(208, TMT, POSITION, POSITION) + TM_PROP(209, TMT, RECT, RECT) + TM_PROP(210, TMT, FONT, FONT) + TM_PROP(211, TMT, INTLIST, INTLIST) + + //---- special misc. properties ---- + TM_PROP(401, TMT, COLORSCHEMES, STRING) + TM_PROP(402, TMT, SIZES, STRING) + TM_PROP(403, TMT, CHARSET, INT) + + //---- [documentation] properties ---- + +#define TMT_FIRST_RCSTRING_NAME TMT_DISPLAYNAME +#define TMT_LAST_RCSTRING_NAME TMT_DESCRIPTION + + TM_PROP(601, TMT, DISPLAYNAME, STRING) + TM_PROP(602, TMT, TOOLTIP, STRING) + TM_PROP(603, TMT, COMPANY, STRING) + TM_PROP(604, TMT, AUTHOR, STRING) + TM_PROP(605, TMT, COPYRIGHT, STRING) + TM_PROP(606, TMT, URL, STRING) + TM_PROP(607, TMT, VERSION, STRING) + TM_PROP(608, TMT, DESCRIPTION, STRING) + + //---- theme metrics: fonts ---- + +#define TMT_FIRSTFONT TMT_CAPTIONFONT +#define TMT_LASTFONT TMT_ICONTITLEFONT + + TM_PROP(801, TMT, CAPTIONFONT, FONT) + TM_PROP(802, TMT, SMALLCAPTIONFONT, FONT) + TM_PROP(803, TMT, MENUFONT, FONT) + TM_PROP(804, TMT, STATUSFONT, FONT) + TM_PROP(805, TMT, MSGBOXFONT, FONT) + TM_PROP(806, TMT, ICONTITLEFONT, FONT) + + //---- theme metrics: bools ---- + +#define TMT_FIRSTBOOL TMT_FLATMENUS +#define TMT_LASTBOOL TMT_FLATMENUS + + TM_PROP(1001, TMT, FLATMENUS, BOOL) + + //---- theme metrics: sizes ---- + +#define TMT_FIRSTSIZE TMT_SIZINGBORDERWIDTH +#define TMT_LASTSIZE TMT_MENUBARHEIGHT + + TM_PROP(1201, TMT, SIZINGBORDERWIDTH, SIZE) + TM_PROP(1202, TMT, SCROLLBARWIDTH, SIZE) + TM_PROP(1203, TMT, SCROLLBARHEIGHT, SIZE) + TM_PROP(1204, TMT, CAPTIONBARWIDTH, SIZE) + TM_PROP(1205, TMT, CAPTIONBARHEIGHT, SIZE) + TM_PROP(1206, TMT, SMCAPTIONBARWIDTH, SIZE) + TM_PROP(1207, TMT, SMCAPTIONBARHEIGHT, SIZE) + TM_PROP(1208, TMT, MENUBARWIDTH, SIZE) + TM_PROP(1209, TMT, MENUBARHEIGHT, SIZE) + + //---- theme metrics: ints ---- + +#define TMT_FIRSTINT TMT_MINCOLORDEPTH +#define TMT_LASTINT TMT_MINCOLORDEPTH + + TM_PROP(1301, TMT, MINCOLORDEPTH, INT) + + //---- theme metrics: strings ---- + +#define TMT_FIRSTSTRING TMT_CSSNAME +#define TMT_LASTSTRING TMT_XMLNAME + + TM_PROP(1401, TMT, CSSNAME, STRING) + TM_PROP(1402, TMT, XMLNAME, STRING) + + //---- theme metrics: colors ---- + +#define TMT_FIRSTCOLOR TMT_SCROLLBAR +#define TMT_LASTCOLOR TMT_MENUBAR + + TM_PROP(1601, TMT, SCROLLBAR, COLOR) + TM_PROP(1602, TMT, BACKGROUND, COLOR) + TM_PROP(1603, TMT, ACTIVECAPTION, COLOR) + TM_PROP(1604, TMT, INACTIVECAPTION, COLOR) + TM_PROP(1605, TMT, MENU, COLOR) + TM_PROP(1606, TMT, WINDOW, COLOR) + TM_PROP(1607, TMT, WINDOWFRAME, COLOR) + TM_PROP(1608, TMT, MENUTEXT, COLOR) + TM_PROP(1609, TMT, WINDOWTEXT, COLOR) + TM_PROP(1610, TMT, CAPTIONTEXT, COLOR) + TM_PROP(1611, TMT, ACTIVEBORDER, COLOR) + TM_PROP(1612, TMT, INACTIVEBORDER, COLOR) + TM_PROP(1613, TMT, APPWORKSPACE, COLOR) + TM_PROP(1614, TMT, HIGHLIGHT, COLOR) + TM_PROP(1615, TMT, HIGHLIGHTTEXT, COLOR) + TM_PROP(1616, TMT, BTNFACE, COLOR) + TM_PROP(1617, TMT, BTNSHADOW, COLOR) + TM_PROP(1618, TMT, GRAYTEXT, COLOR) + TM_PROP(1619, TMT, BTNTEXT, COLOR) + TM_PROP(1620, TMT, INACTIVECAPTIONTEXT, COLOR) + TM_PROP(1621, TMT, BTNHIGHLIGHT, COLOR) + TM_PROP(1622, TMT, DKSHADOW3D, COLOR) + TM_PROP(1623, TMT, LIGHT3D, COLOR) + TM_PROP(1624, TMT, INFOTEXT, COLOR) + TM_PROP(1625, TMT, INFOBK, COLOR) + TM_PROP(1626, TMT, BUTTONALTERNATEFACE, COLOR) + TM_PROP(1627, TMT, HOTTRACKING, COLOR) + TM_PROP(1628, TMT, GRADIENTACTIVECAPTION, COLOR) + TM_PROP(1629, TMT, GRADIENTINACTIVECAPTION, COLOR) + TM_PROP(1630, TMT, MENUHILIGHT, COLOR) + TM_PROP(1631, TMT, MENUBAR, COLOR) + + //---- hue substitutions ---- + TM_PROP(1801, TMT, FROMHUE1, INT) + TM_PROP(1802, TMT, FROMHUE2, INT) + TM_PROP(1803, TMT, FROMHUE3, INT) + TM_PROP(1804, TMT, FROMHUE4, INT) + TM_PROP(1805, TMT, FROMHUE5, INT) + TM_PROP(1806, TMT, TOHUE1, INT) + TM_PROP(1807, TMT, TOHUE2, INT) + TM_PROP(1808, TMT, TOHUE3, INT) + TM_PROP(1809, TMT, TOHUE4, INT) + TM_PROP(1810, TMT, TOHUE5, INT) + + //---- color substitutions ---- + TM_PROP(2001, TMT, FROMCOLOR1, COLOR) + TM_PROP(2002, TMT, FROMCOLOR2, COLOR) + TM_PROP(2003, TMT, FROMCOLOR3, COLOR) + TM_PROP(2004, TMT, FROMCOLOR4, COLOR) + TM_PROP(2005, TMT, FROMCOLOR5, COLOR) + TM_PROP(2006, TMT, TOCOLOR1, COLOR) + TM_PROP(2007, TMT, TOCOLOR2, COLOR) + TM_PROP(2008, TMT, TOCOLOR3, COLOR) + TM_PROP(2009, TMT, TOCOLOR4, COLOR) + TM_PROP(2010, TMT, TOCOLOR5, COLOR) + + //---- rendering BOOL properties ---- + TM_PROP(2201, TMT, TRANSPARENT, BOOL) // image has transparent areas (see TransparentColor) + TM_PROP(2202, TMT, AUTOSIZE, BOOL) // if TRUE, nonclient caption width varies with text extent + TM_PROP(2203, TMT, BORDERONLY, BOOL) // only draw the border area of the image + TM_PROP(2204, TMT, COMPOSITED, BOOL) // control will handle the composite drawing + TM_PROP(2205, TMT, BGFILL, BOOL) // if TRUE, TRUESIZE images should be drawn on bg fill + TM_PROP(2206, TMT, GLYPHTRANSPARENT, BOOL) // glyph has transparent areas (see GlyphTransparentColor) + TM_PROP(2207, TMT, GLYPHONLY, BOOL) // only draw glyph (not background) + TM_PROP(2208, TMT, ALWAYSSHOWSIZINGBAR, BOOL) + TM_PROP(2209, TMT, MIRRORIMAGE, BOOL) // default=TRUE means image gets mirrored in RTL (Mirror) windows + TM_PROP(2210, TMT, UNIFORMSIZING, BOOL) // if TRUE, height & width must be uniformly sized + TM_PROP(2211, TMT, INTEGRALSIZING, BOOL) // for TRUESIZE and Border sizing; if TRUE, factor must be integer + TM_PROP(2212, TMT, SOURCEGROW, BOOL) // if TRUE, will scale up src image when needed + TM_PROP(2213, TMT, SOURCESHRINK, BOOL) // if TRUE, will scale down src image when needed + + //---- rendering INT properties ---- + TM_PROP(2401, TMT, IMAGECOUNT, INT) // the number of state images in an imagefile + TM_PROP(2402, TMT, ALPHALEVEL, INT) // (0-255) alpha value for an icon (DrawThemeIcon part) + TM_PROP(2403, TMT, BORDERSIZE, INT) // the size of the border line for bgtype=BorderFill + TM_PROP(2404, TMT, ROUNDCORNERWIDTH, INT) // (0-100) % of roundness for rounded rects + TM_PROP(2405, TMT, ROUNDCORNERHEIGHT, INT) // (0-100) % of roundness for rounded rects + TM_PROP(2406, TMT, GRADIENTRATIO1, INT) // (0-255) - amt of gradient color 1 to use (all must total=255) + TM_PROP(2407, TMT, GRADIENTRATIO2, INT) // (0-255) - amt of gradient color 2 to use (all must total=255) + TM_PROP(2408, TMT, GRADIENTRATIO3, INT) // (0-255) - amt of gradient color 3 to use (all must total=255) + TM_PROP(2409, TMT, GRADIENTRATIO4, INT) // (0-255) - amt of gradient color 4 to use (all must total=255) + TM_PROP(2410, TMT, GRADIENTRATIO5, INT) // (0-255) - amt of gradient color 5 to use (all must total=255) + TM_PROP(2411, TMT, PROGRESSCHUNKSIZE, INT) // size of progress control chunks + TM_PROP(2412, TMT, PROGRESSSPACESIZE, INT) // size of progress control spaces + TM_PROP(2413, TMT, SATURATION, INT) // (0-255) amt of saturation for DrawThemeIcon() part + TM_PROP(2414, TMT, TEXTBORDERSIZE, INT) // size of border around text chars + TM_PROP(2415, TMT, ALPHATHRESHOLD, INT) // (0-255) the min. alpha value of a pixel that is solid + TM_PROP(2416, TMT, WIDTH, SIZE) // custom window prop: size of part (min. window) + TM_PROP(2417, TMT, HEIGHT, SIZE) // custom window prop: size of part (min. window) + TM_PROP(2418, TMT, GLYPHINDEX, INT) // for font-based glyphs, the char index into the font + TM_PROP(2419, TMT, TRUESIZESTRETCHMARK, INT) // stretch TrueSize image when target exceeds source by this percent + TM_PROP(2420, TMT, MINDPI1, INT) // min DPI ImageFile1 was designed for + TM_PROP(2421, TMT, MINDPI2, INT) // min DPI ImageFile1 was designed for + TM_PROP(2422, TMT, MINDPI3, INT) // min DPI ImageFile1 was designed for + TM_PROP(2423, TMT, MINDPI4, INT) // min DPI ImageFile1 was designed for + TM_PROP(2424, TMT, MINDPI5, INT) // min DPI ImageFile1 was designed for + + //---- rendering FONT properties ---- + TM_PROP(2601, TMT, GLYPHFONT, FONT) // the font that the glyph is drawn with + + //---- rendering INTLIST properties ---- + // start with 2801 + // (from smallest to largest) + //---- rendering FILENAME properties ---- + TM_PROP(3001, TMT, IMAGEFILE, FILENAME) // the filename of the image (or basename, for mult. images) + TM_PROP(3002, TMT, IMAGEFILE1, FILENAME) // multiresolution image file + TM_PROP(3003, TMT, IMAGEFILE2, FILENAME) // multiresolution image file + TM_PROP(3004, TMT, IMAGEFILE3, FILENAME) // multiresolution image file + TM_PROP(3005, TMT, IMAGEFILE4, FILENAME) // multiresolution image file + TM_PROP(3006, TMT, IMAGEFILE5, FILENAME) // multiresolution image file + TM_PROP(3007, TMT, STOCKIMAGEFILE, FILENAME) // These are the only images that you can call GetThemeBitmap on + TM_PROP(3008, TMT, GLYPHIMAGEFILE, FILENAME) // the filename for the glyph image + + //---- rendering STRING properties ---- + TM_PROP(3201, TMT, TEXT, STRING) + + //---- rendering POSITION (x and y values) properties ---- + TM_PROP(3401, TMT, OFFSET, POSITION) // for window part layout + TM_PROP(3402, TMT, TEXTSHADOWOFFSET, POSITION) // where char shadows are drawn, relative to orig. chars + TM_PROP(3403, TMT, MINSIZE, POSITION) // min dest rect than ImageFile was designed for + TM_PROP(3404, TMT, MINSIZE1, POSITION) // min dest rect than ImageFile1 was designed for + TM_PROP(3405, TMT, MINSIZE2, POSITION) // min dest rect than ImageFile2 was designed for + TM_PROP(3406, TMT, MINSIZE3, POSITION) // min dest rect than ImageFile3 was designed for + TM_PROP(3407, TMT, MINSIZE4, POSITION) // min dest rect than ImageFile4 was designed for + TM_PROP(3408, TMT, MINSIZE5, POSITION) // min dest rect than ImageFile5 was designed for + TM_PROP(3409, TMT, NORMALSIZE, POSITION) // size of dest rect that exactly source + + //---- rendering MARGIN properties ---- + TM_PROP(3601, TMT, SIZINGMARGINS, MARGINS) // margins used for 9-grid sizing + TM_PROP(3602, TMT, CONTENTMARGINS, MARGINS) // margins that define where content can be placed + TM_PROP(3603, TMT, CAPTIONMARGINS, MARGINS) // margins that define where caption text can be placed + + //---- rendering COLOR properties ---- + TM_PROP(3801, TMT, BORDERCOLOR, COLOR) // color of borders for BorderFill + TM_PROP(3802, TMT, FILLCOLOR, COLOR) // color of bg fill + TM_PROP(3803, TMT, TEXTCOLOR, COLOR) // color text is drawn in + TM_PROP(3804, TMT, EDGELIGHTCOLOR, COLOR) // edge color + TM_PROP(3805, TMT, EDGEHIGHLIGHTCOLOR, COLOR) // edge color + TM_PROP(3806, TMT, EDGESHADOWCOLOR, COLOR) // edge color + TM_PROP(3807, TMT, EDGEDKSHADOWCOLOR, COLOR) // edge color + TM_PROP(3808, TMT, EDGEFILLCOLOR, COLOR) // edge color + TM_PROP(3809, TMT, TRANSPARENTCOLOR, COLOR) // color of pixels that are treated as transparent (not drawn) + TM_PROP(3810, TMT, GRADIENTCOLOR1, COLOR) // first color in gradient + TM_PROP(3811, TMT, GRADIENTCOLOR2, COLOR) // second color in gradient + TM_PROP(3812, TMT, GRADIENTCOLOR3, COLOR) // third color in gradient + TM_PROP(3813, TMT, GRADIENTCOLOR4, COLOR) // forth color in gradient + TM_PROP(3814, TMT, GRADIENTCOLOR5, COLOR) // fifth color in gradient + TM_PROP(3815, TMT, SHADOWCOLOR, COLOR) // color of text shadow + TM_PROP(3816, TMT, GLOWCOLOR, COLOR) // color of glow produced by DrawThemeIcon + TM_PROP(3817, TMT, TEXTBORDERCOLOR, COLOR) // color of text border + TM_PROP(3818, TMT, TEXTSHADOWCOLOR, COLOR) // color of text shadow + TM_PROP(3819, TMT, GLYPHTEXTCOLOR, COLOR) // color that font-based glyph is drawn with + TM_PROP(3820, TMT, GLYPHTRANSPARENTCOLOR, COLOR) // color of transparent pixels in GlyphImageFile + TM_PROP(3821, TMT, FILLCOLORHINT, COLOR) // hint about fill color used (for custom controls) + TM_PROP(3822, TMT, BORDERCOLORHINT, COLOR) // hint about border color used (for custom controls) + TM_PROP(3823, TMT, ACCENTCOLORHINT, COLOR) // hint about accent color used (for custom controls) + + //---- rendering enum properties (must be declared in TM_ENUM section above) ---- + TM_PROP(4001, TMT, BGTYPE, ENUM) // basic drawing type for each part + TM_PROP(4002, TMT, BORDERTYPE, ENUM) // type of border for BorderFill parts + TM_PROP(4003, TMT, FILLTYPE, ENUM) // fill shape for BorderFill parts + TM_PROP(4004, TMT, SIZINGTYPE, ENUM) // how to size ImageFile parts + TM_PROP(4005, TMT, HALIGN, ENUM) // horizontal alignment for TRUESIZE parts & glyphs + TM_PROP(4006, TMT, CONTENTALIGNMENT, ENUM) // custom window prop: how text is aligned in caption + TM_PROP(4007, TMT, VALIGN, ENUM) // horizontal alignment for TRUESIZE parts & glyphs + TM_PROP(4008, TMT, OFFSETTYPE, ENUM) // how window part should be placed + TM_PROP(4009, TMT, ICONEFFECT, ENUM) // type of effect to use with DrawThemeIcon + TM_PROP(4010, TMT, TEXTSHADOWTYPE, ENUM) // type of shadow to draw with text + TM_PROP(4011, TMT, IMAGELAYOUT, ENUM) // how multiple images are arranged (horz. or vert.) + TM_PROP(4012, TMT, GLYPHTYPE, ENUM) // controls type of glyph in imagefile objects + TM_PROP(4013, TMT, IMAGESELECTTYPE, ENUM) // controls when to select from IMAGEFILE1...IMAGEFILE5 + TM_PROP(4014, TMT, GLYPHFONTSIZINGTYPE, ENUM) // controls when to select a bigger/small glyph font size + TM_PROP(4015, TMT, TRUESIZESCALINGTYPE, ENUM) // controls how TrueSize image is scaled + + //---- custom properties (used only by controls/shell) ---- + TM_PROP(5001, TMT, USERPICTURE, BOOL) + TM_PROP(5002, TMT, DEFAULTPANESIZE, RECT) + TM_PROP(5003, TMT, BLENDCOLOR, COLOR) + +END_TM_PROPS() + +//--------------------------------------------------------------------------------------- +// "Window" (i.e., non-client) Parts & States +// +// these cannot be renumbered (part of uxtheme API) +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(WINDOW) + TM_PART(1, WP, CAPTION) + TM_PART(2, WP, SMALLCAPTION) + TM_PART(3, WP, MINCAPTION) + TM_PART(4, WP, SMALLMINCAPTION) + TM_PART(5, WP, MAXCAPTION) + TM_PART(6, WP, SMALLMAXCAPTION) + TM_PART(7, WP, FRAMELEFT) + TM_PART(8, WP, FRAMERIGHT) + TM_PART(9, WP, FRAMEBOTTOM) + TM_PART(10, WP, SMALLFRAMELEFT) + TM_PART(11, WP, SMALLFRAMERIGHT) + TM_PART(12, WP, SMALLFRAMEBOTTOM) + //---- window frame buttons ---- + TM_PART(13, WP, SYSBUTTON) + TM_PART(14, WP, MDISYSBUTTON) + TM_PART(15, WP, MINBUTTON) + TM_PART(16, WP, MDIMINBUTTON) + TM_PART(17, WP, MAXBUTTON) + TM_PART(18, WP, CLOSEBUTTON) + TM_PART(19, WP, SMALLCLOSEBUTTON) + TM_PART(20, WP, MDICLOSEBUTTON) + TM_PART(21, WP, RESTOREBUTTON) + TM_PART(22, WP, MDIRESTOREBUTTON) + TM_PART(23, WP, HELPBUTTON) + TM_PART(24, WP, MDIHELPBUTTON) + //---- scrollbars + TM_PART(25, WP, HORZSCROLL) + TM_PART(26, WP, HORZTHUMB) + TM_PART(27, WP, VERTSCROLL) + TM_PART(28, WP, VERTTHUMB) + //---- dialog ---- + TM_PART(29, WP, DIALOG) + //---- hit-test templates --- + TM_PART(30, WP, CAPTIONSIZINGTEMPLATE) + TM_PART(31, WP, SMALLCAPTIONSIZINGTEMPLATE) + TM_PART(32, WP, FRAMELEFTSIZINGTEMPLATE) + TM_PART(33, WP, SMALLFRAMELEFTSIZINGTEMPLATE) + TM_PART(34, WP, FRAMERIGHTSIZINGTEMPLATE) + TM_PART(35, WP, SMALLFRAMERIGHTSIZINGTEMPLATE) + TM_PART(36, WP, FRAMEBOTTOMSIZINGTEMPLATE) + TM_PART(37, WP, SMALLFRAMEBOTTOMSIZINGTEMPLATE) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(FRAME) + TM_STATE(1, FS, ACTIVE) + TM_STATE(2, FS, INACTIVE) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(CAPTION) + TM_STATE(1, CS, ACTIVE) + TM_STATE(2, CS, INACTIVE) + TM_STATE(3, CS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(MAXCAPTION) + TM_STATE(1, MXCS, ACTIVE) + TM_STATE(2, MXCS, INACTIVE) + TM_STATE(3, MXCS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(MINCAPTION) + TM_STATE(1, MNCS, ACTIVE) + TM_STATE(2, MNCS, INACTIVE) + TM_STATE(3, MNCS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(HORZSCROLL) + TM_STATE(1, HSS, NORMAL) + TM_STATE(2, HSS, HOT) + TM_STATE(3, HSS, PUSHED) + TM_STATE(4, HSS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(HORZTHUMB) + TM_STATE(1, HTS, NORMAL) + TM_STATE(2, HTS, HOT) + TM_STATE(3, HTS, PUSHED) + TM_STATE(4, HTS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(VERTSCROLL) + TM_STATE(1, VSS, NORMAL) + TM_STATE(2, VSS, HOT) + TM_STATE(3, VSS, PUSHED) + TM_STATE(4, VSS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(VERTTHUMB) + TM_STATE(1, VTS, NORMAL) + TM_STATE(2, VTS, HOT) + TM_STATE(3, VTS, PUSHED) + TM_STATE(4, VTS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(SYSBUTTON) + TM_STATE(1, SBS, NORMAL) + TM_STATE(2, SBS, HOT) + TM_STATE(3, SBS, PUSHED) + TM_STATE(4, SBS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(MINBUTTON) + TM_STATE(1, MINBS, NORMAL) + TM_STATE(2, MINBS, HOT) + TM_STATE(3, MINBS, PUSHED) + TM_STATE(4, MINBS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(MAXBUTTON) + TM_STATE(1, MAXBS, NORMAL) + TM_STATE(2, MAXBS, HOT) + TM_STATE(3, MAXBS, PUSHED) + TM_STATE(4, MAXBS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(RESTOREBUTTON) + TM_STATE(1, RBS, NORMAL) + TM_STATE(2, RBS, HOT) + TM_STATE(3, RBS, PUSHED) + TM_STATE(4, RBS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(HELPBUTTON) + TM_STATE(1, HBS, NORMAL) + TM_STATE(2, HBS, HOT) + TM_STATE(3, HBS, PUSHED) + TM_STATE(4, HBS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(CLOSEBUTTON) + TM_STATE(1, CBS, NORMAL) + TM_STATE(2, CBS, HOT) + TM_STATE(3, CBS, PUSHED) + TM_STATE(4, CBS, DISABLED) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "Button" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(BUTTON) + TM_PART(1, BP, PUSHBUTTON) + TM_PART(2, BP, RADIOBUTTON) + TM_PART(3, BP, CHECKBOX) + TM_PART(4, BP, GROUPBOX) + TM_PART(5, BP, USERBUTTON) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(PUSHBUTTON) + TM_STATE(1, PBS, NORMAL) + TM_STATE(2, PBS, HOT) + TM_STATE(3, PBS, PRESSED) + TM_STATE(4, PBS, DISABLED) + TM_STATE(5, PBS, DEFAULTED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(RADIOBUTTON) + TM_STATE(1, RBS, UNCHECKEDNORMAL) + TM_STATE(2, RBS, UNCHECKEDHOT) + TM_STATE(3, RBS, UNCHECKEDPRESSED) + TM_STATE(4, RBS, UNCHECKEDDISABLED) + TM_STATE(5, RBS, CHECKEDNORMAL) + TM_STATE(6, RBS, CHECKEDHOT) + TM_STATE(7, RBS, CHECKEDPRESSED) + TM_STATE(8, RBS, CHECKEDDISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(CHECKBOX) + TM_STATE(1, CBS, UNCHECKEDNORMAL) + TM_STATE(2, CBS, UNCHECKEDHOT) + TM_STATE(3, CBS, UNCHECKEDPRESSED) + TM_STATE(4, CBS, UNCHECKEDDISABLED) + TM_STATE(5, CBS, CHECKEDNORMAL) + TM_STATE(6, CBS, CHECKEDHOT) + TM_STATE(7, CBS, CHECKEDPRESSED) + TM_STATE(8, CBS, CHECKEDDISABLED) + TM_STATE(9, CBS, MIXEDNORMAL) + TM_STATE(10, CBS, MIXEDHOT) + TM_STATE(11, CBS, MIXEDPRESSED) + TM_STATE(12, CBS, MIXEDDISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(GROUPBOX) + TM_STATE(1, GBS, NORMAL) + TM_STATE(2, GBS, DISABLED) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "Rebar" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(REBAR) + TM_PART(1, RP, GRIPPER) + TM_PART(2, RP, GRIPPERVERT) + TM_PART(3, RP, BAND) + TM_PART(4, RP, CHEVRON) + TM_PART(5, RP, CHEVRONVERT) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(CHEVRON) + TM_STATE(1, CHEVS, NORMAL) + TM_STATE(2, CHEVS, HOT) + TM_STATE(3, CHEVS, PRESSED) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "Toolbar" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(TOOLBAR) + TM_PART(1, TP, BUTTON) + TM_PART(2, TP, DROPDOWNBUTTON) + TM_PART(3, TP, SPLITBUTTON) + TM_PART(4, TP, SPLITBUTTONDROPDOWN) + TM_PART(5, TP, SEPARATOR) + TM_PART(6, TP, SEPARATORVERT) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(TOOLBAR) + TM_STATE(1, TS, NORMAL) + TM_STATE(2, TS, HOT) + TM_STATE(3, TS, PRESSED) + TM_STATE(4, TS, DISABLED) + TM_STATE(5, TS, CHECKED) + TM_STATE(6, TS, HOTCHECKED) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "Status" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(STATUS) + TM_PART(1, SP, PANE) + TM_PART(2, SP, GRIPPERPANE) + TM_PART(3, SP, GRIPPER) +END_TM_CLASS_PARTS() + +//--------------------------------------------------------------------------------------- +// "Menu" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(MENU) + TM_PART(1, MP, MENUITEM) + TM_PART(2, MP, MENUDROPDOWN) + TM_PART(3, MP, MENUBARITEM) + TM_PART(4, MP, MENUBARDROPDOWN) + TM_PART(5, MP, CHEVRON) + TM_PART(6, MP, SEPARATOR) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(MENU) + TM_STATE(1, MS, NORMAL) + TM_STATE(2, MS, SELECTED) + TM_STATE(3, MS, DEMOTED) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "ListView" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(LISTVIEW) + TM_PART(1, LVP, LISTITEM) + TM_PART(2, LVP, LISTGROUP) + TM_PART(3, LVP, LISTDETAIL) + TM_PART(4, LVP, LISTSORTEDDETAIL) + TM_PART(5, LVP, EMPTYTEXT) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(LISTITEM) + TM_STATE(1, LIS, NORMAL) + TM_STATE(2, LIS, HOT) + TM_STATE(3, LIS, SELECTED) + TM_STATE(4, LIS, DISABLED) + TM_STATE(5, LIS, SELECTEDNOTFOCUS) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "Header" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(HEADER) + TM_PART(1, HP, HEADERITEM) + TM_PART(2, HP, HEADERITEMLEFT) + TM_PART(3, HP, HEADERITEMRIGHT) + TM_PART(4, HP, HEADERSORTARROW) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(HEADERITEM) + TM_STATE(1, HIS, NORMAL) + TM_STATE(2, HIS, HOT) + TM_STATE(3, HIS, PRESSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(HEADERITEMLEFT) + TM_STATE(1, HILS, NORMAL) + TM_STATE(2, HILS, HOT) + TM_STATE(3, HILS, PRESSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(HEADERITEMRIGHT) + TM_STATE(1, HIRS, NORMAL) + TM_STATE(2, HIRS, HOT) + TM_STATE(3, HIRS, PRESSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(HEADERSORTARROW) + TM_STATE(1, HSAS, SORTEDUP) + TM_STATE(2, HSAS, SORTEDDOWN) +END_TM_PART_STATES() +//--------------------------------------------------------------------------------------- +// "Progress" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(PROGRESS) + TM_PART(1, PP, BAR) + TM_PART(2, PP, BARVERT) + TM_PART(3, PP, CHUNK) + TM_PART(4, PP, CHUNKVERT) +END_TM_CLASS_PARTS() + +//--------------------------------------------------------------------------------------- +// "Tab" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(TAB) + TM_PART(1, TABP, TABITEM) + TM_PART(2, TABP, TABITEMLEFTEDGE) + TM_PART(3, TABP, TABITEMRIGHTEDGE) + TM_PART(4, TABP, TABITEMBOTHEDGE) + TM_PART(5, TABP, TOPTABITEM) + TM_PART(6, TABP, TOPTABITEMLEFTEDGE) + TM_PART(7, TABP, TOPTABITEMRIGHTEDGE) + TM_PART(8, TABP, TOPTABITEMBOTHEDGE) + TM_PART(9, TABP, PANE) + TM_PART(10, TABP, BODY) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(TABITEM) + TM_STATE(1, TIS, NORMAL) + TM_STATE(2, TIS, HOT) + TM_STATE(3, TIS, SELECTED) + TM_STATE(4, TIS, DISABLED) + TM_STATE(5, TIS, FOCUSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(TABITEMLEFTEDGE) + TM_STATE(1, TILES, NORMAL) + TM_STATE(2, TILES, HOT) + TM_STATE(3, TILES, SELECTED) + TM_STATE(4, TILES, DISABLED) + TM_STATE(5, TILES, FOCUSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(TABITEMRIGHTEDGE) + TM_STATE(1, TIRES, NORMAL) + TM_STATE(2, TIRES, HOT) + TM_STATE(3, TIRES, SELECTED) + TM_STATE(4, TIRES, DISABLED) + TM_STATE(5, TIRES, FOCUSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(TABITEMBOTHEDGES) + TM_STATE(1, TIBES, NORMAL) + TM_STATE(2, TIBES, HOT) + TM_STATE(3, TIBES, SELECTED) + TM_STATE(4, TIBES, DISABLED) + TM_STATE(5, TIBES, FOCUSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(TOPTABITEM) + TM_STATE(1, TTIS, NORMAL) + TM_STATE(2, TTIS, HOT) + TM_STATE(3, TTIS, SELECTED) + TM_STATE(4, TTIS, DISABLED) + TM_STATE(5, TTIS, FOCUSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(TOPTABITEMLEFTEDGE) + TM_STATE(1, TTILES, NORMAL) + TM_STATE(2, TTILES, HOT) + TM_STATE(3, TTILES, SELECTED) + TM_STATE(4, TTILES, DISABLED) + TM_STATE(5, TTILES, FOCUSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(TOPTABITEMRIGHTEDGE) + TM_STATE(1, TTIRES, NORMAL) + TM_STATE(2, TTIRES, HOT) + TM_STATE(3, TTIRES, SELECTED) + TM_STATE(4, TTIRES, DISABLED) + TM_STATE(5, TTIRES, FOCUSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(TOPTABITEMBOTHEDGES) + TM_STATE(1, TTIBES, NORMAL) + TM_STATE(2, TTIBES, HOT) + TM_STATE(3, TTIBES, SELECTED) + TM_STATE(4, TTIBES, DISABLED) + TM_STATE(5, TTIBES, FOCUSED) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "Trackbar" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(TRACKBAR) + TM_PART(1, TKP, TRACK) + TM_PART(2, TKP, TRACKVERT) + TM_PART(3, TKP, THUMB) + TM_PART(4, TKP, THUMBBOTTOM) + TM_PART(5, TKP, THUMBTOP) + TM_PART(6, TKP, THUMBVERT) + TM_PART(7, TKP, THUMBLEFT) + TM_PART(8, TKP, THUMBRIGHT) + TM_PART(9, TKP, TICS) + TM_PART(10, TKP, TICSVERT) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(TRACKBAR) + TM_STATE(1, TKS, NORMAL) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(TRACK) + TM_STATE(1, TRS, NORMAL) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(TRACKVERT) + TM_STATE(1, TRVS, NORMAL) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(THUMB) + TM_STATE(1, TUS, NORMAL) + TM_STATE(2, TUS, HOT) + TM_STATE(3, TUS, PRESSED) + TM_STATE(4, TUS, FOCUSED) + TM_STATE(5, TUS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(THUMBBOTTOM) + TM_STATE(1, TUBS, NORMAL) + TM_STATE(2, TUBS, HOT) + TM_STATE(3, TUBS, PRESSED) + TM_STATE(4, TUBS, FOCUSED) + TM_STATE(5, TUBS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(THUMBTOP) + TM_STATE(1, TUTS, NORMAL) + TM_STATE(2, TUTS, HOT) + TM_STATE(3, TUTS, PRESSED) + TM_STATE(4, TUTS, FOCUSED) + TM_STATE(5, TUTS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(THUMBVERT) + TM_STATE(1, TUVS, NORMAL) + TM_STATE(2, TUVS, HOT) + TM_STATE(3, TUVS, PRESSED) + TM_STATE(4, TUVS, FOCUSED) + TM_STATE(5, TUVS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(THUMBLEFT) + TM_STATE(1, TUVLS, NORMAL) + TM_STATE(2, TUVLS, HOT) + TM_STATE(3, TUVLS, PRESSED) + TM_STATE(4, TUVLS, FOCUSED) + TM_STATE(5, TUVLS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(THUMBRIGHT) + TM_STATE(1, TUVRS, NORMAL) + TM_STATE(2, TUVRS, HOT) + TM_STATE(3, TUVRS, PRESSED) + TM_STATE(4, TUVRS, FOCUSED) + TM_STATE(5, TUVRS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(TICS) + TM_STATE(1, TSS, NORMAL) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(TICSVERT) + TM_STATE(1, TSVS, NORMAL) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "Tooltips" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(TOOLTIP) + TM_PART(1, TTP, STANDARD) + TM_PART(2, TTP, STANDARDTITLE) + TM_PART(3, TTP, BALLOON) + TM_PART(4, TTP, BALLOONTITLE) + TM_PART(5, TTP, CLOSE) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(CLOSE) + TM_STATE(1, TTCS, NORMAL) + TM_STATE(2, TTCS, HOT) + TM_STATE(3, TTCS, PRESSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(STANDARD) + TM_STATE(1, TTSS, NORMAL) + TM_STATE(2, TTSS, LINK) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(BALLOON) + TM_STATE(1, TTBS, NORMAL) + TM_STATE(2, TTBS, LINK) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "TreeView" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(TREEVIEW) + TM_PART(1, TVP, TREEITEM) + TM_PART(2, TVP, GLYPH) + TM_PART(3, TVP, BRANCH) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(TREEITEM) + TM_STATE(1, TREIS, NORMAL) + TM_STATE(2, TREIS, HOT) + TM_STATE(3, TREIS, SELECTED) + TM_STATE(4, TREIS, DISABLED) + TM_STATE(5, TREIS, SELECTEDNOTFOCUS) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(GLYPH) + TM_STATE(1, GLPS, CLOSED) + TM_STATE(2, GLPS, OPENED) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "Spin" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(SPIN) + TM_PART(1, SPNP, UP) + TM_PART(2, SPNP, DOWN) + TM_PART(3, SPNP, UPHORZ) + TM_PART(4, SPNP, DOWNHORZ) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(UP) + TM_STATE(1, UPS, NORMAL) + TM_STATE(2, UPS, HOT) + TM_STATE(3, UPS, PRESSED) + TM_STATE(4, UPS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(DOWN) + TM_STATE(1, DNS, NORMAL) + TM_STATE(2, DNS, HOT) + TM_STATE(3, DNS, PRESSED) + TM_STATE(4, DNS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(UPHORZ) + TM_STATE(1, UPHZS, NORMAL) + TM_STATE(2, UPHZS, HOT) + TM_STATE(3, UPHZS, PRESSED) + TM_STATE(4, UPHZS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(DOWNHORZ) + TM_STATE(1, DNHZS, NORMAL) + TM_STATE(2, DNHZS, HOT) + TM_STATE(3, DNHZS, PRESSED) + TM_STATE(4, DNHZS, DISABLED) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "Page" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(PAGE) + TM_PART(1, PGRP, UP) + TM_PART(2, PGRP, DOWN) + TM_PART(3, PGRP, UPHORZ) + TM_PART(4, PGRP, DOWNHORZ) +END_TM_CLASS_PARTS() + +//--- Pager uses same states as Spin --- + +//--------------------------------------------------------------------------------------- +// "Scrollbar" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(SCROLLBAR) + TM_PART(1, SBP, ARROWBTN) + TM_PART(2, SBP, THUMBBTNHORZ) + TM_PART(3, SBP, THUMBBTNVERT) + TM_PART(4, SBP, LOWERTRACKHORZ) + TM_PART(5, SBP, UPPERTRACKHORZ) + TM_PART(6, SBP, LOWERTRACKVERT) + TM_PART(7, SBP, UPPERTRACKVERT) + TM_PART(8, SBP, GRIPPERHORZ) + TM_PART(9, SBP, GRIPPERVERT) + TM_PART(10, SBP, SIZEBOX) +END_TM_CLASS_PARTS() + + + +BEGIN_TM_PART_STATES(ARROWBTN) + TM_STATE(1, ABS, UPNORMAL) + TM_STATE(2, ABS, UPHOT) + TM_STATE(3, ABS, UPPRESSED) + TM_STATE(4, ABS, UPDISABLED) + TM_STATE(5, ABS, DOWNNORMAL) + TM_STATE(6, ABS, DOWNHOT) + TM_STATE(7, ABS, DOWNPRESSED) + TM_STATE(8, ABS, DOWNDISABLED) + TM_STATE(9, ABS, LEFTNORMAL) + TM_STATE(10, ABS, LEFTHOT) + TM_STATE(11, ABS, LEFTPRESSED) + TM_STATE(12, ABS, LEFTDISABLED) + TM_STATE(13, ABS, RIGHTNORMAL) + TM_STATE(14, ABS, RIGHTHOT) + TM_STATE(15, ABS, RIGHTPRESSED) + TM_STATE(16, ABS, RIGHTDISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(SCROLLBAR) + TM_STATE(1, SCRBS, NORMAL) + TM_STATE(2, SCRBS, HOT) + TM_STATE(3, SCRBS, PRESSED) + TM_STATE(4, SCRBS, DISABLED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(SIZEBOX) + TM_STATE(1, SZB, RIGHTALIGN) + TM_STATE(2, SZB, LEFTALIGN) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "Edit" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(EDIT) + TM_PART(1, EP, EDITTEXT) + TM_PART(2, EP, CARET) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(EDITTEXT) + TM_STATE(1, ETS, NORMAL) + TM_STATE(2, ETS, HOT) + TM_STATE(3, ETS, SELECTED) + TM_STATE(4, ETS, DISABLED) + TM_STATE(5, ETS, FOCUSED) + TM_STATE(6, ETS, READONLY) + TM_STATE(7, ETS, ASSIST) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "ComboBox" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(COMBOBOX) + TM_PART(1, CP, DROPDOWNBUTTON) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(COMBOBOX) + TM_STATE(1, CBXS, NORMAL) + TM_STATE(2, CBXS, HOT) + TM_STATE(3, CBXS, PRESSED) + TM_STATE(4, CBXS, DISABLED) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "Taskbar Clock" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(CLOCK) + TM_PART(1, CLP, TIME) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(CLOCK) + TM_STATE(1, CLS, NORMAL) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "Tray Notify" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(TRAYNOTIFY) + TM_PART(1, TNP, BACKGROUND) + TM_PART(2, TNP, ANIMBACKGROUND) +END_TM_CLASS_PARTS() + +//--------------------------------------------------------------------------------------- +// "TaskBar" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(TASKBAR) + TM_PART(1, TBP, BACKGROUNDBOTTOM) + TM_PART(2, TBP, BACKGROUNDRIGHT) + TM_PART(3, TBP, BACKGROUNDTOP) + TM_PART(4, TBP, BACKGROUNDLEFT) + TM_PART(5, TBP, SIZINGBARBOTTOM) + TM_PART(6, TBP, SIZINGBARRIGHT) + TM_PART(7, TBP, SIZINGBARTOP) + TM_PART(8, TBP, SIZINGBARLEFT) +END_TM_CLASS_PARTS() + +//--------------------------------------------------------------------------------------- +// "TaskBand" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(TASKBAND) + TM_PART(1, TDP, GROUPCOUNT) + TM_PART(2, TDP, FLASHBUTTON) + TM_PART(3, TDP, FLASHBUTTONGROUPMENU) +END_TM_CLASS_PARTS() + +//--------------------------------------------------------------------------------------- +// "StartPanel" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(STARTPANEL) + TM_PART(1, SPP, USERPANE) + TM_PART(2, SPP, MOREPROGRAMS) + TM_PART(3, SPP, MOREPROGRAMSARROW) + TM_PART(4, SPP, PROGLIST) + TM_PART(5, SPP, PROGLISTSEPARATOR) + TM_PART(6, SPP, PLACESLIST) + TM_PART(7, SPP, PLACESLISTSEPARATOR) + TM_PART(8, SPP, LOGOFF) + TM_PART(9, SPP, LOGOFFBUTTONS) + TM_PART(10, SPP, USERPICTURE) + TM_PART(11, SPP, PREVIEW) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(MOREPROGRAMSARROW) + TM_STATE(1, SPS, NORMAL) + TM_STATE(2, SPS, HOT) + TM_STATE(3, SPS, PRESSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(LOGOFFBUTTONS) + TM_STATE(1, SPLS, NORMAL) + TM_STATE(2, SPLS, HOT) + TM_STATE(3, SPLS, PRESSED) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "ExplorerBar" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(EXPLORERBAR) + TM_PART(1, EBP, HEADERBACKGROUND) + TM_PART(2, EBP, HEADERCLOSE) + TM_PART(3, EBP, HEADERPIN) + TM_PART(4, EBP, IEBARMENU) + TM_PART(5, EBP, NORMALGROUPBACKGROUND) + TM_PART(6, EBP, NORMALGROUPCOLLAPSE) + TM_PART(7, EBP, NORMALGROUPEXPAND) + TM_PART(8, EBP, NORMALGROUPHEAD) + TM_PART(9, EBP, SPECIALGROUPBACKGROUND) + TM_PART(10, EBP, SPECIALGROUPCOLLAPSE) + TM_PART(11, EBP, SPECIALGROUPEXPAND) + TM_PART(12, EBP, SPECIALGROUPHEAD) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(HEADERCLOSE) + TM_STATE(1, EBHC, NORMAL) + TM_STATE(2, EBHC, HOT) + TM_STATE(3, EBHC, PRESSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(HEADERPIN) + TM_STATE(1, EBHP, NORMAL) + TM_STATE(2, EBHP, HOT) + TM_STATE(3, EBHP, PRESSED) + TM_STATE(4, EBHP, SELECTEDNORMAL) + TM_STATE(5, EBHP, SELECTEDHOT) + TM_STATE(6, EBHP, SELECTEDPRESSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(IEBARMENU) + TM_STATE(1, EBM, NORMAL) + TM_STATE(2, EBM, HOT) + TM_STATE(3, EBM, PRESSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(NORMALGROUPCOLLAPSE) + TM_STATE(1, EBNGC, NORMAL) + TM_STATE(2, EBNGC, HOT) + TM_STATE(3, EBNGC, PRESSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(NORMALGROUPEXPAND) + TM_STATE(1, EBNGE, NORMAL) + TM_STATE(2, EBNGE, HOT) + TM_STATE(3, EBNGE, PRESSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(SPECIALGROUPCOLLAPSE) + TM_STATE(1, EBSGC, NORMAL) + TM_STATE(2, EBSGC, HOT) + TM_STATE(3, EBSGC, PRESSED) +END_TM_PART_STATES() + +BEGIN_TM_PART_STATES(SPECIALGROUPEXPAND) + TM_STATE(1, EBSGE, NORMAL) + TM_STATE(2, EBSGE, HOT) + TM_STATE(3, EBSGE, PRESSED) +END_TM_PART_STATES() + +//--------------------------------------------------------------------------------------- +// "TaskBand" Parts & States +//--------------------------------------------------------------------------------------- +BEGIN_TM_CLASS_PARTS(MENUBAND) + TM_PART(1, MDP, NEWAPPBUTTON) + TM_PART(2, MDP, SEPERATOR) +END_TM_CLASS_PARTS() + +BEGIN_TM_PART_STATES(MENUBAND) + TM_STATE(1, MDS, NORMAL) + TM_STATE(2, MDS, HOT) + TM_STATE(3, MDS, PRESSED) + TM_STATE(4, MDS, DISABLED) + TM_STATE(5, MDS, CHECKED) + TM_STATE(6, MDS, HOTCHECKED) +END_TM_PART_STATES() +//--------------------------------------------------------------------------- +END_TM_SCHEMA(ThemeMgrSchema) +//--------------------------------------------------------------------------- +#endif // TMSCHEMA_H +//--------------------------------------------------------------------------- diff --git a/Client/Client/GUI/BKWin/bkwin/Uxtheme.h b/Client/Client/GUI/BKWin/bkwin/Uxtheme.h new file mode 100644 index 00000000..d75076e6 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/Uxtheme.h @@ -0,0 +1,925 @@ +//--------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// File : uxtheme.h +// Version: 1.0 +//--------------------------------------------------------------------------- +#ifndef _UXTHEME_H_ +#define _UXTHEME_H_ +//--------------------------------------------------------------------------- +#include +//--------------------------------------------------------------------------- +//#if (_WIN32_WINNT >= 0x0500) // only available on XP +//--------------------------------------------------------------------------- +// Define API decoration for direct importing of DLL references. +#ifndef THEMEAPI +#if !defined(_UXTHEME_) +#define THEMEAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE +#define THEMEAPI_(type) EXTERN_C DECLSPEC_IMPORT type STDAPICALLTYPE +#else +#define THEMEAPI STDAPI +#define THEMEAPI_(type) STDAPI_(type) +#endif +#endif // THEMEAPI +//--------------------------------------------------------------------------- +typedef HANDLE HTHEME; // handle to a section of theme data for class + +//--------------------------------------------------------------------------- +// NOTE: PartId's and StateId's used in the theme API are defined in the +// hdr file using the TM_PART and TM_STATE macros. For +// example, "TM_PART(BP, PUSHBUTTON)" defines the PartId "BP_PUSHBUTTON". + +//--------------------------------------------------------------------------- +// OpenThemeData() - Open the theme data for the specified HWND and +// semi-colon separated list of class names. +// +// OpenThemeData() will try each class name, one at +// a time, and use the first matching theme info +// found. If a match is found, a theme handle +// to the data is returned. If no match is found, +// a "NULL" handle is returned. +// +// When the window is destroyed or a WM_THEMECHANGED +// msg is received, "CloseThemeData()" should be +// called to close the theme handle. +// +// hwnd - window handle of the control/window to be themed +// +// pszClassList - class name (or list of names) to match to theme data +// section. if the list contains more than one name, +// the names are tested one at a time for a match. +// If a match is found, OpenThemeData() returns a +// theme handle associated with the matching class. +// This param is a list (instead of just a single +// class name) to provide the class an opportunity +// to get the "best" match between the class and +// the current theme. For example, a button might +// pass L"OkButton, Button" if its ID=ID_OK. If +// the current theme has an entry for OkButton, +// that will be used. Otherwise, we fall back on +// the normal Button entry. +//--------------------------------------------------------------------------- +THEMEAPI_(HTHEME) OpenThemeData(HWND hwnd, LPCWSTR pszClassList); + +//--------------------------------------------------------------------------- +// CloseTHemeData() - closes the theme data handle. This should be done +// when the window being themed is destroyed or +// whenever a WM_THEMECHANGED msg is received +// (followed by an attempt to create a new Theme data +// handle). +// +// hTheme - open theme data handle (returned from prior call +// to OpenThemeData() API). +//--------------------------------------------------------------------------- +THEMEAPI CloseThemeData(HTHEME hTheme); + +//--------------------------------------------------------------------------- +// functions for basic drawing support +//--------------------------------------------------------------------------- +// The following methods are the theme-aware drawing services. +// Controls/Windows are defined in drawable "parts" by their author: a +// parent part and 0 or more child parts. Each of the parts can be +// described in "states" (ex: disabled, hot, pressed). +//--------------------------------------------------------------------------- +// For the list of all themed classes and the definition of all +// parts and states, see the file "tmschmea.h". +//--------------------------------------------------------------------------- +// Each of the below methods takes a "iPartId" param to specify the +// part and a "iStateId" to specify the state of the part. +// "iStateId=0" refers to the root part. "iPartId" = "0" refers to +// the root class. +//----------------------------------------------------------------------- +// Note: draw operations are always scaled to fit (and not to exceed) +// the specified "Rect". +//----------------------------------------------------------------------- + +//------------------------------------------------------------------------ +// DrawThemeBackground() +// - draws the theme-specified border and fill for +// the "iPartId" and "iStateId". This could be +// based on a bitmap file, a border and fill, or +// other image description. +// +// hTheme - theme data handle +// hdc - HDC to draw into +// iPartId - part number to draw +// iStateId - state number (of the part) to draw +// pRect - defines the size/location of the part +// pClipRect - optional clipping rect (don't draw outside it) +//------------------------------------------------------------------------ +THEMEAPI DrawThemeBackground(HTHEME hTheme, HDC hdc, + int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); + +//--------------------------------------------------------------------------- +//----- DrawThemeText() flags ---- + +#define DTT_GRAYED 0x1 // draw a grayed-out string + +//------------------------------------------------------------------------- +// DrawThemeText() - draws the text using the theme-specified +// color and font for the "iPartId" and +// "iStateId". +// +// hTheme - theme data handle +// hdc - HDC to draw into +// iPartId - part number to draw +// iStateId - state number (of the part) to draw +// pszText - actual text to draw +// dwCharCount - number of chars to draw (-1 for all) +// dwTextFlags - same as DrawText() "uFormat" param +// dwTextFlags2 - additional drawing options +// pRect - defines the size/location of the part +//------------------------------------------------------------------------- +THEMEAPI DrawThemeText(HTHEME hTheme, HDC hdc, int iPartId, + int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, + DWORD dwTextFlags2, const RECT *pRect); + +//------------------------------------------------------------------------- +// GetThemeBackgroundContentRect() +// - gets the size of the content for the theme-defined +// background. This is usually the area inside +// the borders or Margins. +// +// hTheme - theme data handle +// hdc - (optional) device content to be used for drawing +// iPartId - part number to draw +// iStateId - state number (of the part) to draw +// pBoundingRect - the outer RECT of the part being drawn +// pContentRect - RECT to receive the content area +//------------------------------------------------------------------------- +THEMEAPI GetThemeBackgroundContentRect(HTHEME hTheme, OPTIONAL HDC hdc, + int iPartId, int iStateId, const RECT *pBoundingRect, + OUT RECT *pContentRect); + +//------------------------------------------------------------------------- +// GetThemeBackgroundExtent() - calculates the size/location of the theme- +// specified background based on the +// "pContentRect". +// +// hTheme - theme data handle +// hdc - (optional) device content to be used for drawing +// iPartId - part number to draw +// iStateId - state number (of the part) to draw +// pContentRect - RECT that defines the content area +// pBoundingRect - RECT to receive the overall size/location of part +//------------------------------------------------------------------------- +THEMEAPI GetThemeBackgroundExtent(HTHEME hTheme, OPTIONAL HDC hdc, + int iPartId, int iStateId, const RECT *pContentRect, + OUT RECT *pExtentRect); + +//------------------------------------------------------------------------- +typedef enum THEMESIZE +{ + TS_MIN, // minimum size + TS_TRUE, // size without stretching + TS_DRAW, // size that theme mgr will use to draw part +}; +//------------------------------------------------------------------------- +// GetThemePartSize() - returns the specified size of the theme part +// +// hTheme - theme data handle +// hdc - HDC to select font into & measure against +// iPartId - part number to retrieve size for +// iStateId - state number (of the part) +// prc - (optional) rect for part drawing destination +// eSize - the type of size to be retreived +// psz - receives the specified size of the part +//------------------------------------------------------------------------- +THEMEAPI GetThemePartSize(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, + OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); + +//------------------------------------------------------------------------- +// GetThemeTextExtent() - calculates the size/location of the specified +// text when rendered in the Theme Font. +// +// hTheme - theme data handle +// hdc - HDC to select font & measure into +// iPartId - part number to draw +// iStateId - state number (of the part) +// pszText - the text to be measured +// dwCharCount - number of chars to draw (-1 for all) +// dwTextFlags - same as DrawText() "uFormat" param +// pszBoundingRect - optional: to control layout of text +// pszExtentRect - receives the RECT for text size/location +//------------------------------------------------------------------------- +THEMEAPI GetThemeTextExtent(HTHEME hTheme, HDC hdc, + int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, + DWORD dwTextFlags, OPTIONAL const RECT *pBoundingRect, + OUT RECT *pExtentRect); + +//------------------------------------------------------------------------- +// GetThemeTextMetrics() +// - returns info about the theme-specified font +// for the part/state passed in. +// +// hTheme - theme data handle +// hdc - optional: HDC for screen context +// iPartId - part number to draw +// iStateId - state number (of the part) +// ptm - receives the font info +//------------------------------------------------------------------------- +THEMEAPI GetThemeTextMetrics(HTHEME hTheme, OPTIONAL HDC hdc, + int iPartId, int iStateId, OUT TEXTMETRIC* ptm); + +//------------------------------------------------------------------------- +// GetThemeBackgroundRegion() +// - computes the region for a regular or partially +// transparent theme-specified background that is +// bound by the specified "pRect". +// If the rectangle is empty, sets the HRGN to NULL +// and return S_FALSE. +// +// hTheme - theme data handle +// hdc - optional HDC to draw into (DPI scaling) +// iPartId - part number to draw +// iStateId - state number (of the part) +// pRect - the RECT used to draw the part +// pRegion - receives handle to calculated region +//------------------------------------------------------------------------- +THEMEAPI GetThemeBackgroundRegion(HTHEME hTheme, OPTIONAL HDC hdc, + int iPartId, int iStateId, const RECT *pRect, OUT HRGN *pRegion); + +//------------------------------------------------------------------------- +//----- HitTestThemeBackground, HitTestThemeBackgroundRegion flags ---- + +// Theme background segment hit test flag (default). possible return values are: +// HTCLIENT: hit test succeeded in the middle background segment +// HTTOP, HTLEFT, HTTOPLEFT, etc: // hit test succeeded in the the respective theme background segment. +#define HTTB_BACKGROUNDSEG 0x0000 + +// Fixed border hit test option. possible return values are: +// HTCLIENT: hit test succeeded in the middle background segment +// HTBORDER: hit test succeeded in any other background segment +#define HTTB_FIXEDBORDER 0x0002 // Return code may be either HTCLIENT or HTBORDER. + +// Caption hit test option. Possible return values are: +// HTCAPTION: hit test succeeded in the top, top left, or top right background segments +// HTNOWHERE or another return code, depending on absence or presence of accompanying flags, resp. +#define HTTB_CAPTION 0x0004 + +// Resizing border hit test flags. Possible return values are: +// HTCLIENT: hit test succeeded in middle background segment +// HTTOP, HTTOPLEFT, HTLEFT, HTRIGHT, etc: hit test succeeded in the respective system resizing zone +// HTBORDER: hit test failed in middle segment and resizing zones, but succeeded in a background border segment +#define HTTB_RESIZINGBORDER_LEFT 0x0010 // Hit test left resizing border, +#define HTTB_RESIZINGBORDER_TOP 0x0020 // Hit test top resizing border +#define HTTB_RESIZINGBORDER_RIGHT 0x0040 // Hit test right resizing border +#define HTTB_RESIZINGBORDER_BOTTOM 0x0080 // Hit test bottom resizing border + +#define HTTB_RESIZINGBORDER (HTTB_RESIZINGBORDER_LEFT|HTTB_RESIZINGBORDER_TOP|\ + HTTB_RESIZINGBORDER_RIGHT|HTTB_RESIZINGBORDER_BOTTOM) + +// Resizing border is specified as a template, not just window edges. +// This option is mutually exclusive with HTTB_SYSTEMSIZINGWIDTH; HTTB_SIZINGTEMPLATE takes precedence +#define HTTB_SIZINGTEMPLATE 0x0100 + +// Use system resizing border width rather than theme content margins. +// This option is mutually exclusive with HTTB_SIZINGTEMPLATE, which takes precedence. +#define HTTB_SYSTEMSIZINGMARGINS 0x0200 + +//------------------------------------------------------------------------- +// HitTestThemeBackground() +// - returns a HitTestCode (a subset of the values +// returned by WM_NCHITTEST) for the point "ptTest" +// within the theme-specified background +// (bound by pRect). "pRect" and "ptTest" should +// both be in the same coordinate system +// (client, screen, etc). +// +// hTheme - theme data handle +// hdc - HDC to draw into +// iPartId - part number to test against +// iStateId - state number (of the part) +// pRect - the RECT used to draw the part +// hrgn - optional region to use; must be in same coordinates as +// - pRect and pTest. +// ptTest - the hit point to be tested +// dwOptions - HTTB_xxx constants +// pwHitTestCode - receives the returned hit test code - one of: +// +// HTNOWHERE, HTLEFT, HTTOPLEFT, HTBOTTOMLEFT, +// HTRIGHT, HTTOPRIGHT, HTBOTTOMRIGHT, +// HTTOP, HTBOTTOM, HTCLIENT +//------------------------------------------------------------------------- +THEMEAPI HitTestThemeBackground(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, + int iStateId, DWORD dwOptions, const RECT *pRect, OPTIONAL HRGN hrgn, + POINT ptTest, OUT WORD *pwHitTestCode); + +//------------------------------------------------------------------------ +// DrawThemeEdge() - Similar to the DrawEdge() API, but uses part colors +// and is high-DPI aware +// hTheme - theme data handle +// hdc - HDC to draw into +// iPartId - part number to draw +// iStateId - state number of part +// pDestRect - the RECT used to draw the line(s) +// uEdge - Same as DrawEdge() API +// uFlags - Same as DrawEdge() API +// pContentRect - Receives the interior rect if (uFlags & BF_ADJUST) +//------------------------------------------------------------------------ +THEMEAPI DrawThemeEdge(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, + const RECT *pDestRect, UINT uEdge, UINT uFlags, OPTIONAL OUT RECT *pContentRect); + +//------------------------------------------------------------------------ +// DrawThemeIcon() - draws an image within an imagelist based on +// a (possible) theme-defined effect. +// +// hTheme - theme data handle +// hdc - HDC to draw into +// iPartId - part number to draw +// iStateId - state number of part +// pRect - the RECT to draw the image within +// himl - handle to IMAGELIST +// iImageIndex - index into IMAGELIST (which icon to draw) +//------------------------------------------------------------------------ +THEMEAPI DrawThemeIcon(HTHEME hTheme, HDC hdc, int iPartId, + int iStateId, const RECT *pRect, HIMAGELIST himl, int iImageIndex); + +//--------------------------------------------------------------------------- +// IsThemePartDefined() - returns TRUE if the theme has defined parameters +// for the specified "iPartId" and "iStateId". +// +// hTheme - theme data handle +// iPartId - part number to find definition for +// iStateId - state number of part +//--------------------------------------------------------------------------- +THEMEAPI_(BOOL) IsThemePartDefined(HTHEME hTheme, int iPartId, + int iStateId); + +//--------------------------------------------------------------------------- +// IsThemeBackgroundPartiallyTransparent() +// - returns TRUE if the theme specified background for +// the part/state has transparent pieces or +// alpha-blended pieces. +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +//--------------------------------------------------------------------------- +THEMEAPI_(BOOL) IsThemeBackgroundPartiallyTransparent(HTHEME hTheme, + int iPartId, int iStateId); + +//--------------------------------------------------------------------------- +// lower-level theme information services +//--------------------------------------------------------------------------- +// The following methods are getter routines for each of the Theme Data types. +// Controls/Windows are defined in drawable "parts" by their author: a +// parent part and 0 or more child parts. Each of the parts can be +// described in "states" (ex: disabled, hot, pressed). +//--------------------------------------------------------------------------- +// Each of the below methods takes a "iPartId" param to specify the +// part and a "iStateId" to specify the state of the part. +// "iStateId=0" refers to the root part. "iPartId" = "0" refers to +// the root class. +//----------------------------------------------------------------------- +// Each method also take a "iPropId" param because multiple instances of +// the same primitive type can be defined in the theme schema. +//----------------------------------------------------------------------- + + +//----------------------------------------------------------------------- +// GetThemeColor() - Get the value for the specified COLOR property +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// pColor - receives the value of the property +//----------------------------------------------------------------------- +THEMEAPI GetThemeColor(HTHEME hTheme, int iPartId, + int iStateId, int iPropId, OUT COLORREF *pColor); + +//----------------------------------------------------------------------- +// GetThemeMetric() - Get the value for the specified metric/size +// property +// +// hTheme - theme data handle +// hdc - (optional) hdc to be drawn into (DPI scaling) +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// piVal - receives the value of the property +//----------------------------------------------------------------------- +THEMEAPI GetThemeMetric(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, + int iStateId, int iPropId, OUT int *piVal); + +//----------------------------------------------------------------------- +// GetThemeString() - Get the value for the specified string property +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// pszBuff - receives the string property value +// cchMaxBuffChars - max. number of chars allowed in pszBuff +//----------------------------------------------------------------------- +THEMEAPI GetThemeString(HTHEME hTheme, int iPartId, + int iStateId, int iPropId, OUT LPWSTR pszBuff, int cchMaxBuffChars); + +//----------------------------------------------------------------------- +// GetThemeBool() - Get the value for the specified BOOL property +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// pfVal - receives the value of the property +//----------------------------------------------------------------------- +THEMEAPI GetThemeBool(HTHEME hTheme, int iPartId, + int iStateId, int iPropId, OUT BOOL *pfVal); + +//----------------------------------------------------------------------- +// GetThemeInt() - Get the value for the specified int property +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// piVal - receives the value of the property +//----------------------------------------------------------------------- +THEMEAPI GetThemeInt(HTHEME hTheme, int iPartId, + int iStateId, int iPropId, OUT int *piVal); + +//----------------------------------------------------------------------- +// GetThemeEnumValue() - Get the value for the specified ENUM property +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// piVal - receives the value of the enum (cast to int*) +//----------------------------------------------------------------------- +THEMEAPI GetThemeEnumValue(HTHEME hTheme, int iPartId, + int iStateId, int iPropId, OUT int *piVal); + +//----------------------------------------------------------------------- +// GetThemePosition() - Get the value for the specified position +// property +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// pPoint - receives the value of the position property +//----------------------------------------------------------------------- +THEMEAPI GetThemePosition(HTHEME hTheme, int iPartId, + int iStateId, int iPropId, OUT POINT *pPoint); + +//----------------------------------------------------------------------- +// GetThemeFont() - Get the value for the specified font property +// +// hTheme - theme data handle +// hdc - (optional) hdc to be drawn to (DPI scaling) +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// pFont - receives the value of the LOGFONT property +// (scaled for the current logical screen dpi) +//----------------------------------------------------------------------- +THEMEAPI GetThemeFont(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, + int iStateId, int iPropId, OUT LOGFONT *pFont); + +//----------------------------------------------------------------------- +// GetThemeRect() - Get the value for the specified RECT property +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// pRect - receives the value of the RECT property +//----------------------------------------------------------------------- +THEMEAPI GetThemeRect(HTHEME hTheme, int iPartId, + int iStateId, int iPropId, OUT RECT *pRect); + +//----------------------------------------------------------------------- +typedef struct _MARGINS +{ + int cxLeftWidth; // width of left border that retains its size + int cxRightWidth; // width of right border that retains its size + int cyTopHeight; // height of top border that retains its size + int cyBottomHeight; // height of bottom border that retains its size +} MARGINS, *PMARGINS; + +//----------------------------------------------------------------------- +// GetThemeMargins() - Get the value for the specified MARGINS property +// +// hTheme - theme data handle +// hdc - (optional) hdc to be used for drawing +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// prc - RECT for area to be drawn into +// pMargins - receives the value of the MARGINS property +//----------------------------------------------------------------------- +THEMEAPI GetThemeMargins(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, + int iStateId, int iPropId, OPTIONAL RECT *prc, OUT MARGINS *pMargins); + +//----------------------------------------------------------------------- +#define MAX_INTLIST_COUNT 10 + +typedef struct _INTLIST +{ + int iValueCount; // number of values in iValues + int iValues[MAX_INTLIST_COUNT]; +} INTLIST, *PINTLIST; + +//----------------------------------------------------------------------- +// GetThemeIntList() - Get the value for the specified INTLIST struct +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// pIntList - receives the value of the INTLIST property +//----------------------------------------------------------------------- +THEMEAPI GetThemeIntList(HTHEME hTheme, int iPartId, + int iStateId, int iPropId, OUT INTLIST *pIntList); + +//----------------------------------------------------------------------- +typedef enum PROPERTYORIGIN +{ + PO_STATE, // property was found in the state section + PO_PART, // property was found in the part section + PO_CLASS, // property was found in the class section + PO_GLOBAL, // property was found in [globals] section + PO_NOTFOUND // property was not found +}; + +//----------------------------------------------------------------------- +// GetThemePropertyOrigin() +// - searches for the specified theme property +// and sets "pOrigin" to indicate where it was +// found (or not found) +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to search for +// pOrigin - receives the value of the property origin +//----------------------------------------------------------------------- +THEMEAPI GetThemePropertyOrigin(HTHEME hTheme, int iPartId, + int iStateId, int iPropId, OUT enum PROPERTYORIGIN *pOrigin); + +//--------------------------------------------------------------------------- +// SetWindowTheme() +// - redirects an existing Window to use a different +// section of the current theme information than its +// class normally asks for. +// +// hwnd - the handle of the window (cannot be NULL) +// +// pszSubAppName - app (group) name to use in place of the calling +// app's name. If NULL, the actual calling app +// name will be used. +// +// pszSubIdList - semicolon separated list of class Id names to +// use in place of actual list passed by the +// window's class. if NULL, the id list from the +// calling class is used. +//--------------------------------------------------------------------------- +// The Theme Manager will remember the "pszSubAppName" and the +// "pszSubIdList" associations thru the lifetime of the window (even +// if themes are subsequently changed). The window is sent a +// "WM_THEMECHANGED" msg at the end of this call, so that the new +// theme can be found and applied. +//--------------------------------------------------------------------------- +// When "pszSubAppName" or "pszSubIdList" are NULL, the Theme Manager +// removes the previously remember association. To turn off theme-ing for +// the specified window, you can pass an empty string (L"") so it +// won't match any section entries. +//--------------------------------------------------------------------------- +THEMEAPI SetWindowTheme(HWND hwnd, LPCWSTR pszSubAppName, + LPCWSTR pszSubIdList); + +//--------------------------------------------------------------------------- +// GetThemeFilename() - Get the value for the specified FILENAME property. +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to search for +// pszThemeFileName - output buffer to receive the filename +// cchMaxBuffChars - the size of the return buffer, in chars +//--------------------------------------------------------------------------- +THEMEAPI GetThemeFilename(HTHEME hTheme, int iPartId, + int iStateId, int iPropId, OUT LPWSTR pszThemeFileName, int cchMaxBuffChars); + +//--------------------------------------------------------------------------- +// GetThemeSysColor() - Get the value of the specified System color. +// +// hTheme - the theme data handle. if non-NULL, will return +// color from [SysMetrics] section of theme. +// if NULL, will return the global system color. +// +// iColorId - the system color index defined in winuser.h +//--------------------------------------------------------------------------- +THEMEAPI_(COLORREF) GetThemeSysColor(HTHEME hTheme, int iColorId); + +//--------------------------------------------------------------------------- +// GetThemeSysColorBrush() +// - Get the brush for the specified System color. +// +// hTheme - the theme data handle. if non-NULL, will return +// brush matching color from [SysMetrics] section of +// theme. if NULL, will return the brush matching +// global system color. +// +// iColorId - the system color index defined in winuser.h +//--------------------------------------------------------------------------- +THEMEAPI_(HBRUSH) GetThemeSysColorBrush(HTHEME hTheme, int iColorId); + +//--------------------------------------------------------------------------- +// GetThemeSysBool() - Get the boolean value of specified System metric. +// +// hTheme - the theme data handle. if non-NULL, will return +// BOOL from [SysMetrics] section of theme. +// if NULL, will return the specified system boolean. +// +// iBoolId - the TMT_XXX BOOL number (first BOOL +// is TMT_FLATMENUS) +//--------------------------------------------------------------------------- +THEMEAPI_(BOOL) GetThemeSysBool(HTHEME hTheme, int iBoolId); + +//--------------------------------------------------------------------------- +// GetThemeSysSize() - Get the value of the specified System size metric. +// (scaled for the current logical screen dpi) +// +// hTheme - the theme data handle. if non-NULL, will return +// size from [SysMetrics] section of theme. +// if NULL, will return the global system metric. +// +// iSizeId - the following values are supported when +// hTheme is non-NULL: +// +// SM_CXBORDER (border width) +// SM_CXVSCROLL (scrollbar width) +// SM_CYHSCROLL (scrollbar height) +// SM_CXSIZE (caption width) +// SM_CYSIZE (caption height) +// SM_CXSMSIZE (small caption width) +// SM_CYSMSIZE (small caption height) +// SM_CXMENUSIZE (menubar width) +// SM_CYMENUSIZE (menubar height) +// +// when hTheme is NULL, iSizeId is passed directly +// to the GetSystemMetrics() function +//--------------------------------------------------------------------------- +THEMEAPI_(int) GetThemeSysSize(HTHEME hTheme, int iSizeId); + +//--------------------------------------------------------------------------- +// GetThemeSysFont() - Get the LOGFONT for the specified System font. +// +// hTheme - the theme data handle. if non-NULL, will return +// font from [SysMetrics] section of theme. +// if NULL, will return the specified system font. +// +// iFontId - the TMT_XXX font number (first font +// is TMT_CAPTIONFONT) +// +// plf - ptr to LOGFONT to receive the font value. +// (scaled for the current logical screen dpi) +//--------------------------------------------------------------------------- +THEMEAPI GetThemeSysFont(HTHEME hTheme, int iFontId, OUT LOGFONT *plf); + +//--------------------------------------------------------------------------- +// GetThemeSysString() - Get the value of specified System string metric. +// +// hTheme - the theme data handle (required) +// +// iStringId - must be one of the following values: +// +// TMT_CSSNAME +// TMT_XMLNAME +// +// pszStringBuff - the buffer to receive the string value +// +// cchMaxStringChars - max. number of chars that pszStringBuff can hold +//--------------------------------------------------------------------------- +THEMEAPI GetThemeSysString(HTHEME hTheme, int iStringId, + OUT LPWSTR pszStringBuff, int cchMaxStringChars); + +//--------------------------------------------------------------------------- +// GetThemeSysInt() - Get the value of specified System int. +// +// hTheme - the theme data handle (required) +// +// iIntId - must be one of the following values: +// +// TMT_DPIX +// TMT_DPIY +// TMT_MINCOLORDEPTH +// +// piValue - ptr to int to receive value +//--------------------------------------------------------------------------- +THEMEAPI GetThemeSysInt(HTHEME hTheme, int iIntId, int *piValue); + +//--------------------------------------------------------------------------- +// IsThemeActive() - can be used to test if a system theme is active +// for the current user session. +// +// use the API "IsAppThemed()" to test if a theme is +// active for the calling process. +//--------------------------------------------------------------------------- +THEMEAPI_(BOOL) IsThemeActive(); + +//--------------------------------------------------------------------------- +// IsAppThemed() - returns TRUE if a theme is active and available to +// the current process +//--------------------------------------------------------------------------- +THEMEAPI_(BOOL) IsAppThemed(); + + +//--------------------------------------------------------------------------- +// GetWindowTheme() - if window is themed, returns its most recent +// HTHEME from OpenThemeData() - otherwise, returns +// NULL. +// +// hwnd - the window to get the HTHEME of +//--------------------------------------------------------------------------- +THEMEAPI_(HTHEME) GetWindowTheme(HWND hwnd); + + +//--------------------------------------------------------------------------- +// EnableThemeDialogTexture() +// +// - Enables/disables dialog background theme. This method can be used to +// tailor dialog compatibility with child windows and controls that +// may or may not coordinate the rendering of their client area backgrounds +// with that of their parent dialog in a manner that supports seamless +// background texturing. +// +// hdlg - the window handle of the target dialog +// dwFlags - ETDT_ENABLE to enable the theme-defined dialog background texturing, +// ETDT_DISABLE to disable background texturing, +// ETDT_ENABLETAB to enable the theme-defined background +// texturing using the Tab texture +//--------------------------------------------------------------------------- + +#define ETDT_DISABLE 0x00000001 +#define ETDT_ENABLE 0x00000002 +#define ETDT_USETABTEXTURE 0x00000004 +#define ETDT_ENABLETAB (ETDT_ENABLE | ETDT_USETABTEXTURE) + +THEMEAPI EnableThemeDialogTexture(HWND hwnd, DWORD dwFlags); + + +//--------------------------------------------------------------------------- +// IsThemeDialogTextureEnabled() +// +// - Reports whether the dialog supports background texturing. +// +// hdlg - the window handle of the target dialog +//--------------------------------------------------------------------------- +THEMEAPI_(BOOL) IsThemeDialogTextureEnabled(HWND hwnd); + + +//--------------------------------------------------------------------------- +//---- flags to control theming within an app ---- + +#define STAP_ALLOW_NONCLIENT (1 << 0) +#define STAP_ALLOW_CONTROLS (1 << 1) +#define STAP_ALLOW_WEBCONTENT (1 << 2) + +//--------------------------------------------------------------------------- +// GetThemeAppProperties() +// - returns the app property flags that control theming +//--------------------------------------------------------------------------- +THEMEAPI_(DWORD) GetThemeAppProperties(); + +//--------------------------------------------------------------------------- +// SetThemeAppProperties() +// - sets the flags that control theming within the app +// +// dwFlags - the flag values to be set +//--------------------------------------------------------------------------- +THEMEAPI_(void) SetThemeAppProperties(DWORD dwFlags); + +//--------------------------------------------------------------------------- +// GetCurrentThemeName() +// - Get the name of the current theme in-use. +// Optionally, return the ColorScheme name and the +// Size name of the theme. +// +// pszThemeFileName - receives the theme path & filename +// cchMaxNameChars - max chars allowed in pszNameBuff +// +// pszColorBuff - (optional) receives the canonical color scheme name +// (not the display name) +// cchMaxColorChars - max chars allowed in pszColorBuff +// +// pszSizeBuff - (optional) receives the canonical size name +// (not the display name) +// cchMaxSizeChars - max chars allowed in pszSizeBuff +//--------------------------------------------------------------------------- +THEMEAPI GetCurrentThemeName( + OUT LPWSTR pszThemeFileName, int cchMaxNameChars, + OUT OPTIONAL LPWSTR pszColorBuff, int cchMaxColorChars, + OUT OPTIONAL LPWSTR pszSizeBuff, int cchMaxSizeChars); + +//--------------------------------------------------------------------------- +// GetThemeDocumentationProperty() +// - Get the value for the specified property name from +// the [documentation] section of the themes.ini file +// for the specified theme. If the property has been +// localized in the theme files string table, the +// localized version of the property value is returned. +// +// pszThemeFileName - filename of the theme file to query +// pszPropertyName - name of the string property to retreive a value for +// pszValueBuff - receives the property string value +// cchMaxValChars - max chars allowed in pszValueBuff +//--------------------------------------------------------------------------- +#define SZ_THDOCPROP_DISPLAYNAME L"DisplayName" +#define SZ_THDOCPROP_CANONICALNAME L"ThemeName" +#define SZ_THDOCPROP_TOOLTIP L"ToolTip" +#define SZ_THDOCPROP_AUTHOR L"author" + +THEMEAPI GetThemeDocumentationProperty(LPCWSTR pszThemeName, + LPCWSTR pszPropertyName, OUT LPWSTR pszValueBuff, int cchMaxValChars); + +//--------------------------------------------------------------------------- +// Theme API Error Handling +// +// All functions in the Theme API not returning an HRESULT (THEMEAPI_) +// use the WIN32 function "SetLastError()" to record any call failures. +// +// To retreive the error code of the last failure on the +// current thread for these type of API's, use the WIN32 function +// "GetLastError()". +// +// All Theme API error codes (HRESULT's and GetLastError() values) +// should be normal win32 errors which can be formatted into +// strings using the Win32 API FormatMessage(). +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// DrawThemeParentBackground() +// - used by partially-transparent or alpha-blended +// child controls to draw the part of their parent +// that they appear in front of. +// +// hwnd - handle of the child control + +// hdc - hdc of the child control + +// prc - (optional) rect that defines the area to be +// drawn (CHILD coordinates) +//--------------------------------------------------------------------------- +THEMEAPI DrawThemeParentBackground(HWND hwnd, HDC hdc, OPTIONAL RECT* prc); + +//--------------------------------------------------------------------------- +// EnableTheming() - enables or disables themeing for the current user +// in the current and future sessions. +// +// fEnable - if FALSE, disable theming & turn themes off. +// - if TRUE, enable themeing and, if user previously +// had a theme active, make it active now. +//--------------------------------------------------------------------------- +THEMEAPI EnableTheming(BOOL fEnable); + +//------------------------------------------------------------------------ +//---- bits used in dwFlags of DTBGOPTS ---- +#define DTBG_CLIPRECT 0x00000001 // rcClip has been specified +#define DTBG_DRAWSOLID 0x00000002 // draw transparent/alpha images as solid +#define DTBG_OMITBORDER 0x00000004 // don't draw border of part +#define DTBG_OMITCONTENT 0x00000008 // don't draw content area of part + +#define DTBG_COMPUTINGREGION 0x00000010 // TRUE if calling to compute region + +#define DTBG_MIRRORDC 0x00000020 // assume the hdc is mirrorred and + // flip images as appropriate (currently + // only supported for bgtype=imagefile) +//------------------------------------------------------------------------ +typedef struct _DTBGOPTS +{ + DWORD dwSize; // size of the struct + DWORD dwFlags; // which options have been specified + RECT rcClip; // clipping rectangle +} +DTBGOPTS, *PDTBGOPTS; + +//------------------------------------------------------------------------ +// DrawThemeBackgroundEx() +// - draws the theme-specified border and fill for +// the "iPartId" and "iStateId". This could be +// based on a bitmap file, a border and fill, or +// other image description. NOTE: This will be +// merged back into DrawThemeBackground() after +// BETA 2. +// +// hTheme - theme data handle +// hdc - HDC to draw into +// iPartId - part number to draw +// iStateId - state number (of the part) to draw +// pRect - defines the size/location of the part +// pOptions - ptr to optional params +//------------------------------------------------------------------------ +THEMEAPI DrawThemeBackgroundEx(HTHEME hTheme, HDC hdc, + int iPartId, int iStateId, const RECT *pRect, OPTIONAL const DTBGOPTS *pOptions); + + +//--------------------------------------------------------------------------- +//#endif /* (_WIN32_WINNT >= 0x0500) *// +//--------------------------------------------------------------------------- +#endif // _UXTHEME_H_ +//--------------------------------------------------------------------------- diff --git a/Client/Client/GUI/BKWin/bkwin/bkatldefine.h b/Client/Client/GUI/BKWin/bkwin/bkatldefine.h new file mode 100644 index 00000000..5ef03fe0 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkatldefine.h @@ -0,0 +1,48 @@ +#pragma once + + +#define BEGIN_MSG_MAP_EX_DECLARE(theClass) \ +public: \ + BOOL m_bMsgHandled; \ + /* "handled" management for cracked handlers */ \ + BOOL IsMsgHandled() const \ + { \ + return m_bMsgHandled; \ + } \ + void SetMsgHandled(BOOL bHandled) \ + { \ + m_bMsgHandled = bHandled; \ + } \ + BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \ + { \ + BOOL bOldMsgHandled = m_bMsgHandled; \ + BOOL bRet = _ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, dwMsgMapID); \ + m_bMsgHandled = bOldMsgHandled; \ + return bRet; \ + } \ + BOOL _ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID); + +#define BEGIN_MSG_MAP_EX_IMP(theClass) \ + BOOL theClass::_ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID) \ + { \ + BOOL bHandled = TRUE; \ + hWnd; \ + uMsg; \ + wParam; \ + lParam; \ + lResult; \ + bHandled; \ + switch(dwMsgMapID) \ + { \ + case 0: + + +#define END_MSG_MAP_IMP() \ + break; \ + default: \ + ATLTRACE(ATL::atlTraceWindowing, 0, _T("Invalid message map ID (%i)\n"), dwMsgMapID); \ + ATLASSERT(FALSE); \ + break; \ + } \ + return FALSE; \ + } \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkwin/bkcolor.h b/Client/Client/GUI/BKWin/bkwin/bkcolor.h new file mode 100644 index 00000000..b34509e4 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkcolor.h @@ -0,0 +1,169 @@ +////////////////////////////////////////////////////////////////////////// +// File Name: bkcolor.h +// Description: HLS & RGB processor +// Creator: Zhang Xiaoxuan +// Version: 2009.6.10 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +class BkColor +{ + typedef enum + { + Red, + Green, + Blue + }; + +public: + + unsigned char red; + unsigned char green; + unsigned char blue; + + double lightness, saturation, hue; + + BkColor() + : red(0) + , green(0) + , blue(0) + , lightness(0) + , saturation(0) + , hue(0) + { + } + + BkColor(double h, double l, double s) + { + hue = h; + lightness = l; + saturation = s; + + ToRGB(); + } + + BkColor (BYTE r, BYTE g, BYTE b) + { + red = r; + green = g; + blue = b; + + ToHLS(); + } + + BkColor(COLORREF color) + { + red = GetRValue(color); + green = GetGValue(color); + blue = GetBValue(color); + + ToHLS(); + } + + // lightness [0..1] + // saturation [0..1] + // hue [0..360) + void ToHLS(void) + { + double mn, mx; + int major; + + if ( red < green ) + { + mn = red; mx = green; major = Green; + } + else + { + mn = green; mx = red; major = Red; + } + + if ( blue < mn ) + mn = blue; + else if ( blue > mx ) + { + mx = blue; major = Blue; + } + + if ( mn==mx ) + { + lightness = mn/255; + saturation = 0; + hue = 0; + } + else + { + lightness = (mn+mx) / 510; + + if ( lightness <= 0.5 ) + saturation = (mx-mn) / (mn+mx); + else + saturation = (mx-mn) / (510-mn-mx); + + switch ( major ) + { + case Red : hue = (green-blue) * 60 / (mx-mn) + 360; break; + case Green: hue = (blue-red) * 60 / (mx-mn) + 120; break; + case Blue : hue = (red-green) * 60 / (mx-mn) + 240; + } + + if (hue >= 360) + hue = hue - 360; + } + } + + void ToRGB(void) + { + // lightness [0..1] + // saturation [0..1] + // hue [0..360) + + lightness = max(0, min(1, lightness)); + saturation = max(0, min(1, saturation)); + hue = max(0, min(360, hue)); + if (360 == hue) + hue = 0; + + if (saturation == 0) + { + red = green = blue = (unsigned char) (lightness*255); + } + else + { + double m1, m2; + + if ( lightness <= 0.5 ) + m2 = lightness + lightness * saturation; + else + m2 = lightness + saturation - lightness * saturation; + + m1 = 2 * lightness - m2; + + red = _Value(m1, m2, hue + 120); + green = _Value(m1, m2, hue); + blue = _Value(m1, m2, hue - 120); + } + } + + operator COLORREF() const throw() + { + return RGB(red, green, blue); + } + +private: + + unsigned char _Value(double m1, double m2, double h) + { + while (h >= 360) h -= 360; + while (h < 0) h += 360; + + if (h < 60) + m1 = m1 + (m2 - m1) * h / 60; + else if (h < 180) + m1 = m2; + else if (h < 240) + m1 = m1 + (m2 - m1) * (240 - h) / 60; + + return (unsigned char)(m1 * 255); + } +}; diff --git a/Client/Client/GUI/BKWin/bkwin/bkdlgview.h b/Client/Client/GUI/BKWin/bkwin/bkdlgview.h new file mode 100644 index 00000000..a89e7ec9 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkdlgview.h @@ -0,0 +1,1950 @@ +////////////////////////////////////////////////////////////////////////// +// Class Name: CBkDlgView +// Description: Dialog View, Real Container of BkWindow +// Creator: ZhangXiaoxuan +// Version: 2010.3.12 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include + +#include "bkwndnotify.h" +#include "bkwndpanel.h" + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// BkWinManager +// CBkViewImpl +// CBkDialogViewTraits +// CBkDialogViewImpl +// CBkDialogView +// CBkDialogImpl +// CBkSimpleDialog + +////////////////////////////////////////////////////////////////////////// +// BkWinManager + +class BkWinManager +{ +public: + BkWinManager() + : m_hWndActive(NULL) + { + if (NULL == ms_mangager) + ms_mangager = this; + + ::InitializeCriticalSection(&m_lockRepaint); + } + + virtual ~BkWinManager() + { + if (this == ms_mangager) + ms_mangager = NULL; + + ::DeleteCriticalSection(&m_lockRepaint); + } + + static HWND SetActive(HWND hWnd) + { + HWND hWndLastActive = NULL; + + if (ms_mangager) + { + hWndLastActive = ms_mangager->m_hWndActive; + ms_mangager->m_hWndActive = hWnd; + } + + return hWndLastActive; + } + + static HWND GetActive() + { + if (ms_mangager) + return ms_mangager->m_hWndActive; + + return NULL; + } + + static void EnterPaintLock() + { + if (ms_mangager) + ::EnterCriticalSection(&(ms_mangager->m_lockRepaint)); + } + + static void LeavePaintLock() + { + if (ms_mangager) + ::LeaveCriticalSection(&(ms_mangager->m_lockRepaint)); + } + +protected: + static BkWinManager* ms_mangager; + + HWND m_hWndActive; + CRITICAL_SECTION m_lockRepaint; +}; + +__declspec(selectany) BkWinManager* BkWinManager::ms_mangager = NULL; + +////////////////////////////////////////////////////////////////////////// + +template +class ATL_NO_VTABLE CBkViewImpl +{ +public: + + BOOL SetRichText(UINT uItemID, UINT uResID) + { + CStringA strXml; + BOOL bRet = BkResManager::LoadResource(uResID, strXml); + if (!bRet) + return FALSE; + + return SetRichText(uItemID, strXml); + } + + BOOL SetRichText(UINT uItemID, LPCWSTR lpszXml) + { + CStringA strXml = CW2A(lpszXml, CP_UTF8); + + return SetRichText(uItemID, strXml); + } + + BOOL SetRichText(UINT uItemID, LPCSTR lpszXml) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + + if (!pWnd) + return FALSE; + + if (!pWnd->IsClass(CBkRichText::GetClassName())) + return FALSE; + + TiXmlDocument xmlDoc; + + { // Free stack + CStringA strXml; + strXml = L'<'; + strXml += CBkRichText::GetClassName(); + strXml += L'>'; + strXml += lpszXml; + strXml += L'<'; + strXml += L'/'; + strXml += CBkRichText::GetClassName(); + strXml += L'>'; + xmlDoc.Parse(strXml, NULL, TIXML_ENCODING_UTF8); + } + + if (xmlDoc.Error()) + return FALSE; + + CBkRichText *pWndRichText = (CBkRichText *)pWnd; + pWndRichText->LoadChilds(xmlDoc.RootElement()); + + pT->_InvalidateControl(pWnd); + + if (pWnd->IsVisible(TRUE)) + pWnd->BkSendMessage(WM_SHOWWINDOW, TRUE); + + return TRUE; + } + + BOOL SetItemText(UINT uItemID, LPCTSTR lpszText) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + + if (pWnd) + { + pT->_InvalidateControl(pWnd); + + pWnd->SetInnerText(lpszText); + + pT->_InvalidateControl(pWnd); + + return TRUE; + } + + return FALSE; + } + + BOOL SetItemAttribute(UINT uItemID, LPCSTR lpszAttrib, LPCSTR lpszValue) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + + if (pWnd) + { + pT->_InvalidateControl(pWnd); + + pWnd->SetAttribute(lpszAttrib, lpszValue, FALSE); + + pT->_InvalidateControl(pWnd); + + return TRUE; + } + + return FALSE; + } + + BOOL SetItemStringAttribute(UINT uItemID, LPCSTR lpszAttrib, LPCTSTR lpszValue) + { + return SetItemAttribute(uItemID, lpszAttrib, CT2A(lpszValue, CP_UTF8)); + } + + BOOL SetItemIntAttribute(UINT uItemID, LPCSTR lpszAttrib, int nValue) + { + CStringA strValue; + strValue.Format("%d", nValue); + + return SetItemAttribute(uItemID, lpszAttrib, strValue); + } + + BOOL SetItemDWordAttribute(UINT uItemID, LPCSTR lpszAttrib, DWORD dwValue) + { + CStringA strValue; + strValue.Format("%u", dwValue); + + return SetItemAttribute(uItemID, lpszAttrib, strValue); + } + + BOOL SetItemColorAttribute(UINT uItemID, LPCSTR lpszAttrib, COLORREF crValue) + { + CStringA strValue; + strValue.Format("%02X%02X%02X", GetRValue(crValue), GetGValue(crValue), GetBValue(crValue)); + + return SetItemAttribute(uItemID, lpszAttrib, strValue); + } + + BOOL GetItemCheck(UINT uItemID) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + + if (pWnd) + return pWnd->IsChecked(); + + return FALSE; + } + + BOOL SetItemCheck(UINT uItemID, BOOL bCheck) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + + if (pWnd) + { + if (bCheck) + pWnd->ModifyState(BkWndState_Check, 0); + else + pWnd->ModifyState(0, BkWndState_Check); + + pT->_InvalidateControl(pWnd); + + return TRUE; + } + + return FALSE; + } + + BOOL EnableItem(UINT uItemID, BOOL bEnable) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + + if (pWnd) + { + if (bEnable) + pWnd->ModifyState(0, BkWndState_Disable); + else + pWnd->ModifyState(BkWndState_Disable, BkWndState_Hover); + + pT->_InvalidateControl(pWnd); + + return TRUE; + } + + return FALSE; + } + + BOOL IsItemEnable(UINT uItemID, BOOL bCheckParent = FALSE) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + + if (pWnd) + return !pWnd->IsDisabled(bCheckParent); + + return FALSE; + } + + BOOL SetItemVisible(UINT uItemID, BOOL bVisible) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + + if (pWnd) + { + pWnd->BkSendMessage(WM_SHOWWINDOW, (WPARAM)bVisible); + + pT->_InvalidateControl(pWnd, FALSE); + + return TRUE; + } + + return FALSE; + } + + BOOL IsItemVisible(UINT uItemID, BOOL bCheckParent = FALSE) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + + if (pWnd) + return pWnd->IsVisible(bCheckParent); + + return FALSE; + } + + BOOL GetItemRect(UINT uItemID, RECT &rcItem) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + if (!pWnd) + return FALSE; + + pWnd->GetRect(&rcItem); + + return TRUE; + } + + BOOL SetTabCurSel(UINT uItemID, int nPage) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + if (!pWnd) + return FALSE; + + if (!pWnd->IsClass(CBkTabCtrl::GetClassName())) + return FALSE; + + BOOL bRet = ((CBkTabCtrl *)pWnd)->SetCurSel(nPage); + + return bRet; + } + + BOOL SetTabTitle(UINT uItemID, int nPage, LPCTSTR lpszTitle) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + if (!pWnd) + return FALSE; + + if (!pWnd->IsClass(CBkTabCtrl::GetClassName())) + return FALSE; + + BOOL bRet = ((CBkTabCtrl *)pWnd)->SetTabTitle(nPage, lpszTitle); + + return bRet; + } + + int GetTabCurSel(UINT uItemID) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + if (!pWnd) + return -1; + + if (!pWnd->IsClass(CBkTabCtrl::GetClassName())) + return -1; + + return ((CBkTabCtrl *)pWnd)->GetCurSel(); + } + + BOOL IsTabPageVisible(UINT uItemID, int nPage) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + if (!pWnd) + return FALSE; + + if (!pWnd->IsClass(CBkTabCtrl::GetClassName())) + return FALSE; + + return ((CBkTabCtrl *)pWnd)->IsPageVisible(nPage); + } + + BOOL SetTabPageVisible(UINT uItemID, int nPage, BOOL bVisible) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + if (!pWnd) + return FALSE; + + if (!pWnd->IsClass(CBkTabCtrl::GetClassName())) + return FALSE; + + ((CBkTabCtrl *)pWnd)->SetPageVisible(nPage, bVisible); + + return TRUE; + } + + BOOL SetItemIconHandle(UINT uItemID, HICON hIcon) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + if (!pWnd) + return FALSE; + + if (!pWnd->IsClass(CBkIconWnd::GetClassName())) + return FALSE; + + ((CBkIconWnd *)pWnd)->AttachIcon(hIcon); + + pT->_InvalidateControl(pWnd); + + return TRUE; + } + + BOOL SetItemPaintHook(UINT uItemID, IBkWindowPaintHook* pPaintHook) + { + T* pT = static_cast(this); + CBkWindow *pWnd = pT->FindChildByCmdID(uItemID); + if (!pWnd) + return FALSE; + + pWnd->SetPaintHook(pPaintHook); + + return TRUE; + } + + BOOL FormatRichText(UINT uItemID, LPCTSTR lpszFormat, ...) + { + va_list args; + CString strText; + + va_start(args, lpszFormat); + + strText.FormatV(lpszFormat, args); + + return SetRichText(uItemID, strText); + } + + BOOL FormatItemText(UINT uItemID, LPCTSTR lpszFormat, ...) + { + va_list args; + CString strText; + + va_start(args, lpszFormat); + + strText.FormatV(lpszFormat, args); + + return SetItemText(uItemID, strText); + } +}; + +// NOTICE: WS_TABSTOP needed for accept focus +// WS_CLIPSIBLINGS may cause IE Control Redraw Error +typedef CWinTraits CBkDialogViewTraits; + +////////////////////////////////////////////////////////////////////////// +// CBkDialogViewImpl + +template +class ATL_NO_VTABLE CBkDialogViewImpl + : public ATL::CWindowImpl + , public CBkViewImpl +{ + friend CBkViewImpl; + +public: + DECLARE_WND_CLASS_EX(NULL, CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, COLOR_WINDOW) + +public: + CBkDialogViewImpl() + : m_hBkWndHover(NULL) + , m_hBkWndPushDown(NULL) + , m_bTrackFlag(FALSE) + , m_bPushDownFlag(FALSE) + , m_dwDlgStyle(0) + , m_dwDlgExStyle(0) + , m_bHasHeader(FALSE) + , m_bHasBody(FALSE) + , m_bHasFooter(FALSE) + , m_bXmlLoaded(FALSE) + , m_bCaptureSetted(FALSE) + , m_bCanMaximize(FALSE) + , m_bNeedRepaint(FALSE) + , m_bNeedAllRepaint(TRUE) + { + } + + ~CBkDialogViewImpl() + { + m_bkHeader.BkSendMessage(WM_DESTROY); + m_bkBody.BkSendMessage(WM_DESTROY); + m_bkFooter.BkSendMessage(WM_DESTROY); + } + +protected: + + typedef ATL::CWindowImpl __baseClass; + typedef CBkDialogViewImpl __thisClass; + + TBkWin m_bkHeader; + TBkWin m_bkBody; + TBkWin m_bkFooter; + + // Double Cached + CBkImage m_imgMem; + + // Only one hover control + HBKWND m_hBkWndHover; + // Only one pushdown control + HBKWND m_hBkWndPushDown; + + // Tracking flag + BOOL m_bTrackFlag; + + // Pushdown flag + BOOL m_bPushDownFlag; + + BOOL m_bCaptureSetted; + + CString m_strWindowCaption; + SIZE m_sizeDefault; + + DWORD m_dwDlgStyle; + DWORD m_dwDlgExStyle; + + BOOL m_bHasHeader; + BOOL m_bHasBody; + BOOL m_bHasFooter; + + BOOL m_bCanMaximize; + + BOOL m_bXmlLoaded; + BOOL m_bNeedRepaint; + BOOL m_bNeedAllRepaint; + + CToolTipCtrl m_wndToolTip; + + CRgn m_rgnInvalidate; + +public: + + HWND Create( + HWND hWndParent, _U_RECT rect = NULL, DWORD dwStyle = 0, + DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + if (NULL != m_hWnd) + return m_hWnd; + + HWND hWnd = __baseClass::Create(hWndParent, rect, m_strWindowCaption, dwStyle, dwExStyle, MenuOrID, lpCreateParam); + + if (hWnd) + { + m_bkHeader.SetContainer(m_hWnd); + m_bkBody.SetContainer(m_hWnd); + m_bkFooter.SetContainer(m_hWnd); + + m_wndToolTip.Create(hWnd); + + CToolInfo ti(0, hWnd); + m_wndToolTip.AddTool(ti); + m_wndToolTip.Activate(TRUE); + + if (!m_rgnInvalidate.IsNull()) + m_rgnInvalidate.DeleteObject(); + } + + return hWnd; + }; + + HWND Create(HWND hWndParent, _U_MENUorID MenuOrID) + { + return Create(hWndParent, NULL, 0, 0, MenuOrID, NULL); + }; + + BOOL Load(UINT uResID) + { + CStringA strXml; + + BOOL bRet = BkResManager::LoadResource(uResID, strXml); + + if (!bRet) + return FALSE; + + return SetXml(strXml); + } + + BOOL XmlLoaded() + { + return m_bXmlLoaded; + } + + BOOL SetXml(LPCSTR lpszXml) + { + CStringA strValue; + + TiXmlDocument xmlDoc; + + m_bXmlLoaded = FALSE; + + m_dwDlgStyle = WS_POPUP | WS_SYSMENU | 0; + m_dwDlgExStyle = 0; + + m_bkHeader.BkSendMessage(WM_DESTROY); + m_bkBody.BkSendMessage(WM_DESTROY); + m_bkFooter.BkSendMessage(WM_DESTROY); + + m_bHasHeader = FALSE; + m_bHasBody = FALSE; + m_bHasFooter = FALSE; + + { // Free stack + xmlDoc.Parse(lpszXml, NULL, TIXML_ENCODING_UTF8); + } + + if (xmlDoc.Error()) + { + _Redraw(); + return FALSE; + } + + TiXmlElement *pXmlRootElem = xmlDoc.RootElement(); + + strValue = pXmlRootElem->Value(); + if (strValue != "layer") + { + _Redraw(); + return FALSE; + } + + { + m_strWindowCaption = CA2T(pXmlRootElem->Attribute("title"), CP_UTF8); + m_sizeDefault.cx = 0; + m_sizeDefault.cy = 0; + pXmlRootElem->Attribute("width", (int *)&m_sizeDefault.cx); + pXmlRootElem->Attribute("height", (int *)&m_sizeDefault.cy); + + BOOL bValue = FALSE; + + pXmlRootElem->Attribute("appwin", &bValue); + if (bValue) + m_dwDlgExStyle |= WS_EX_APPWINDOW; + + bValue = FALSE; + + pXmlRootElem->Attribute("resize", &bValue); + + if (bValue) + { + m_bCanMaximize = TRUE; + m_dwDlgStyle |= WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME; + } + else + m_bCanMaximize = FALSE; + + bValue = FALSE; + + pXmlRootElem->Attribute("noborder", &bValue); + + if (bValue) + { + m_dwDlgExStyle |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST; + } + else + { + m_dwDlgExStyle |= WS_EX_OVERLAPPEDWINDOW; + } + + } + + TiXmlElement *pTiElement = NULL; + + pTiElement = pXmlRootElem->FirstChildElement("header"); + m_bHasHeader = m_bkHeader.Load(pTiElement); + if (m_bHasHeader) + { + CStringA strPos; + int nHeight = 0; + pTiElement->Attribute("height", &nHeight); + strPos.Format("0,0,-0,%d", nHeight); + m_bkHeader.SetAttribute("pos", strPos, TRUE); + } + + pTiElement = pXmlRootElem->FirstChildElement("footer"); + m_bHasFooter = m_bkFooter.Load(pTiElement); + if (m_bHasFooter) + { + CStringA strPos; + int nHeight = 0; + pTiElement->Attribute("height", &nHeight); + strPos.Format("0,-%d,-0,-0", nHeight); + m_bkFooter.SetAttribute("pos", strPos, TRUE); + } + + m_bHasBody = m_bkBody.Load(pXmlRootElem->FirstChildElement("body")); + if (m_bHasBody) + { + m_bkBody.SetAttribute("pos", "0,0,-0,-0", TRUE); + } + + m_bXmlLoaded = TRUE; + + if (!m_hWnd) + return TRUE; + + _Redraw(); + + m_hBkWndHover = NULL; + m_hBkWndPushDown = NULL; + + return TRUE; + } + + LPCTSTR GetWindowCaption() + { + return m_strWindowCaption; + } + + void SetWindowCaption(LPCTSTR lpszCaption) + { + m_strWindowCaption = lpszCaption; + } + + SIZE GetDefaultSize() + { + return m_sizeDefault; + } + + DWORD GetDlgStyle() + { + return m_dwDlgStyle; + } + + DWORD GetDlgExStyle() + { + return m_dwDlgExStyle; + } + + void ShowAllRealWindows(BOOL bShow) + { + if (m_bHasHeader) + m_bkHeader.ShowAllRealWindowChilds(bShow); + if (m_bHasFooter) + m_bkFooter.ShowAllRealWindowChilds(bShow); + if (m_bHasBody) + m_bkBody.ShowAllRealWindowChilds(bShow); + } + + void RecomposeItems(BOOL bRedraw) + { + + } + + void Redraw() + { + + } + + CBkWindow* FindChildByCmdID(UINT uCmdID) + { + CBkWindow *pWnd = NULL; + + pWnd = m_bkHeader.FindChildByCmdID(uCmdID); + if (pWnd) + return pWnd; + + pWnd = m_bkBody.FindChildByCmdID(uCmdID); + if (pWnd) + return pWnd; + + pWnd = m_bkFooter.FindChildByCmdID(uCmdID); + + return pWnd; + } + + BOOL SetPanelXml(UINT uItemID, UINT uResID) + { + CStringA strXml; + BOOL bRet = BkResManager::LoadResource(uResID, strXml); + if (!bRet) + return FALSE; + + return SetPanelXml(uItemID, strXml); + } + + BOOL SetPanelXml(UINT uItemID, LPCSTR lpszXml) + { + TiXmlDocument xmlDoc; + + { // Free stack + xmlDoc.Parse(lpszXml, NULL, TIXML_ENCODING_UTF8); + } + + if (xmlDoc.Error()) + return FALSE; + + CBkWindow *pWnd = FindChildByCmdID(uItemID); + + if (!pWnd) + return FALSE; + + if (!pWnd->IsClass(CBkDialog::GetClassName()) && + !pWnd->IsClass(CBkPanel::GetClassName()) && + !pWnd->IsClass(CBkTab::GetClassName()) && + !pWnd->IsClass(CBkDialogFile::GetClassName()) ) + return FALSE; + + TiXmlElement *pXmlRootElem = xmlDoc.RootElement(); + + CBkPanel *pWndPanel = (CBkPanel *)pWnd; + + pWndPanel->LoadChilds(pXmlRootElem); + pWndPanel->RepositionChilds(); + + _InvalidateControl(pWnd); + + if (pWnd->IsVisible(TRUE)) + pWnd->BkSendMessage(WM_SHOWWINDOW, TRUE); + + return TRUE; + } + +protected: + + void _Redraw() + { + m_bNeedAllRepaint = TRUE; + m_bNeedRepaint = TRUE; + if (!m_rgnInvalidate.IsNull()) + m_rgnInvalidate.DeleteObject(); + + Invalidate(FALSE); + } + + void _RepositionItems(BOOL bRedraw = TRUE) + { + CRect rcClient, rcHeader, rcFooter, rcBody; + + if (!m_hWnd) + return; + + GetClientRect(rcClient); + + if (rcClient.Width() == 0) + return; + + WINDOWPOS WndPos = { 0, 0, rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), SWP_SHOWWINDOW }; + + if (m_bHasHeader) + { + m_bkHeader.BkSendMessage(WM_WINDOWPOSCHANGED, 0, (LPARAM)&WndPos); + m_bkHeader.GetRect(rcHeader); + } + + if (m_bHasFooter) + { + m_bkFooter.BkSendMessage(WM_WINDOWPOSCHANGED, 0, (LPARAM)&WndPos); + m_bkFooter.GetRect(rcFooter); + + WndPos.y = rcClient.bottom - rcFooter.Height(); + WndPos.cy = rcFooter.Height(); + m_bkFooter.BkSendMessage(WM_WINDOWPOSCHANGED, 0, (LPARAM)&WndPos); + } + + if (m_bHasBody) + { + WndPos.y = rcHeader.bottom; + WndPos.cy = rcClient.bottom - rcFooter.Height() - rcHeader.bottom; + + m_bkBody.BkSendMessage(WM_WINDOWPOSCHANGED, 0, (LPARAM)&WndPos); + } + + _Redraw(); + } + + void _ModifyWndState(CBkWindow *pWnd, DWORD dwStateAdd, DWORD dwStateRemove) + { + pWnd->ModifyState(dwStateAdd, dwStateRemove); + if (pWnd->NeedRedrawWhenStateChange()) + _InvalidateControl(pWnd); + } + + void _InvalidateControl(CBkWindow *pWnd, BOOL bCheckVisible = TRUE) + { + if (!bCheckVisible || pWnd->IsVisible(TRUE)) + { + CRect rcInvalidate; + + pWnd->GetRect(rcInvalidate); + _InvalidateRect(rcInvalidate); + } + } + + void _InvalidateRect(CRect& rcInvalidate) + { + if (m_rgnInvalidate.IsNull()) + { + m_rgnInvalidate.CreateRectRgnIndirect(rcInvalidate); + } + else + { + CRgn rgnInvalidate; + + rgnInvalidate.CreateRectRgnIndirect(rcInvalidate); + + m_rgnInvalidate.CombineRgn(rgnInvalidate, RGN_OR); + } + + if (IsWindow()) + InvalidateRect(rcInvalidate, FALSE); + + m_bNeedRepaint = TRUE; + } + + ////////////////////////////////////////////////////////////////////////// + // Message handler + + void OnPrint(CDCHandle dc, UINT uFlags) + { + if (m_bNeedAllRepaint) + { + if (!m_rgnInvalidate.IsNull()) + m_rgnInvalidate.DeleteObject(); + + m_bNeedAllRepaint = FALSE; + } + + if (m_bNeedRepaint) + { + BkWinManager::EnterPaintLock(); + + CDC dcMem; + CDCHandle dcMemHandle; + HDC hDCDesktop = ::GetDC(NULL); + dcMem.CreateCompatibleDC(hDCDesktop); + ::ReleaseDC(NULL, hDCDesktop); + HBITMAP hbmpOld = dcMem.SelectBitmap(m_imgMem); + + HFONT hftOld = dcMem.SelectFont(BkFontPool::GetFont(BKF_DEFAULTFONT)); + + dcMem.SetBkMode(TRANSPARENT); + + if (!m_rgnInvalidate.IsNull()) + dcMem.SelectClipRgn(m_rgnInvalidate); + + dcMemHandle.Attach(dcMem); + + if (m_bHasHeader) + m_bkHeader.RedrawRegion(dcMemHandle, m_rgnInvalidate); + if (m_bHasBody) + m_bkBody.RedrawRegion(dcMemHandle, m_rgnInvalidate); + if (m_bHasFooter) + m_bkFooter.RedrawRegion(dcMemHandle, m_rgnInvalidate); + + dcMemHandle.Detach(); + + if (!m_rgnInvalidate.IsNull()) + m_rgnInvalidate.DeleteObject(); + + dcMem.SelectFont(hftOld); + dcMem.SelectBitmap(hbmpOld); + + BkWinManager::LeavePaintLock(); + + m_bNeedRepaint = FALSE; + } + + m_imgMem.Draw(dc, 0, 0); + } + + void OnPaint(CDCHandle dc) + { + CPaintDC dcPaint(m_hWnd); + + OnPrint((HDC)dcPaint, 0); + } + + BOOL OnEraseBkgnd(CDCHandle dc) + { + return TRUE; + } + + void OnDestroy() + { + if (m_imgMem.M_HOBJECT) + m_imgMem.DeleteObject(); + } + + void OnSize(UINT nType, CSize size) + { + if (m_imgMem.M_HOBJECT) + m_imgMem.DeleteObject(); + + CRect rcClient; + + GetClientRect(rcClient); + + if (0 == rcClient.Width()) + return; + + m_imgMem.CreateBitmap(rcClient.Width(), rcClient.Height(), RGB(0, 0, 0)); + + _RepositionItems(); + } + + void OnMouseMove(UINT nFlags, CPoint point) + { + if (!m_bTrackFlag) + { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(tme); + tme.hwndTrack = m_hWnd; + tme.dwFlags = TME_LEAVE; + tme.dwHoverTime = 0; + m_bTrackFlag = _TrackMouseEvent(&tme); + + { + NMHDR nms; + nms.code = BKNM_MOUSEHOVER; + nms.hwndFrom = m_hWnd; + nms.idFrom = GetDlgCtrlID(); + ::SendMessage(GetParent(), WM_NOTIFY, (LPARAM)nms.idFrom, (WPARAM)&nms); + } + } + + HBKWND hBkWndHitTest = NULL; + + hBkWndHitTest = m_bkHeader.BkGetHWNDFromPoint(point, TRUE); + if (NULL == hBkWndHitTest) + hBkWndHitTest = m_bkBody.BkGetHWNDFromPoint(point, TRUE); + if (NULL == hBkWndHitTest) + hBkWndHitTest = m_bkFooter.BkGetHWNDFromPoint(point, TRUE); + + CBkWindow* pWndHover = BkWnds::GetWindow(hBkWndHitTest); + + if (pWndHover) + { + BOOL bDisabled = pWndHover->IsDisabled(TRUE); + if (!bDisabled) + pWndHover->BkSendMessage(WM_MOUSEMOVE, (WPARAM)nFlags, MAKELPARAM(point.x, point.y)); + + if (hBkWndHitTest != m_hBkWndHover) + { + CRect rcInvalidate; + + if (NULL != m_hBkWndHover) + { + CBkWindow* pWndHoverOld = BkWnds::GetWindow(m_hBkWndHover); + + if (pWndHoverOld && !pWndHoverOld->IsDisabled(TRUE)) + { + _ModifyWndState(pWndHoverOld, 0, BkWndState_Hover); + pWndHoverOld->BkSendMessage(WM_MOUSELEAVE); + } + } + + if (!bDisabled) + _ModifyWndState(pWndHover, BkWndState_Hover, 0); + + m_hBkWndHover = hBkWndHitTest; + + if (pWndHover) + m_wndToolTip.UpdateTipText(pWndHover->GetToolTipText(), m_hWnd); + } + } + } + + void OnMouseLeave() + { + m_bTrackFlag = FALSE; + + if (m_hBkWndHover) + { + CBkWindow* pWndHover = BkWnds::GetWindow(m_hBkWndHover); + if (pWndHover) + { + _ModifyWndState(pWndHover, 0, BkWndState_Hover); + pWndHover->BkSendMessage(WM_MOUSELEAVE); + } + + m_hBkWndHover = NULL; + } + + if (m_hBkWndPushDown) + { + CBkWindow* pWndPushdown = BkWnds::GetWindow(m_hBkWndPushDown); + if (pWndPushdown) + _ModifyWndState(pWndPushdown, 0, BkWndState_PushDown); + + m_hBkWndPushDown = NULL; + } + + { + NMHDR nms; + nms.code = BKNM_MOUSELEAVE; + nms.hwndFrom = m_hWnd; + nms.idFrom = GetDlgCtrlID(); + ::SendMessage(GetParent(), WM_NOTIFY, (LPARAM)nms.idFrom, (WPARAM)&nms); + } + } + + void OnLButtonDown(UINT nFlags, CPoint point) + { + HBKWND hBkWndHitTest = m_bkHeader.BkGetHWNDFromPoint(point, TRUE); + + if (hBkWndHitTest) + { + CBkWindow* pWndPushDown = BkWnds::GetWindow(hBkWndHitTest); + + if (!(pWndPushDown->IsClass("button") || pWndPushDown->IsClass("imgbtn") || pWndPushDown->IsClass("link"))) + { + CWindow &wndParent = GetParent(); + + if (0 == (wndParent.GetStyle() & (WS_MAXIMIZE | WS_MINIMIZE))) + wndParent.SendMessage(WM_SYSCOMMAND, SC_MOVE | HTCAPTION); + + return; + } + } + + if (NULL == hBkWndHitTest) + hBkWndHitTest = m_bkBody.BkGetHWNDFromPoint(point, TRUE); + if (NULL == hBkWndHitTest) + hBkWndHitTest = m_bkFooter.BkGetHWNDFromPoint(point, TRUE); + + CBkWindow* pWndPushDown = BkWnds::GetWindow(hBkWndHitTest); + + if (pWndPushDown) + { + if (pWndPushDown->IsDisabled(TRUE)) + return; + + if (!m_bCaptureSetted) + { + SetCapture(); + m_bCaptureSetted = TRUE; + + if (hBkWndHitTest != m_hBkWndHover) + { + // HoverPushdownͬԭǣһֱûˢ£лλõĿؼ + //ATLASSERT(FALSE); + m_hBkWndHover = hBkWndHitTest; + } + + m_hBkWndPushDown = hBkWndHitTest; + + _ModifyWndState(pWndPushDown, BkWndState_PushDown, 0); + pWndPushDown->BkSendMessage(WM_LBUTTONDOWN, (WPARAM)nFlags, MAKELPARAM(point.x, point.y)); + } + } + } + + void OnLButtonUp(UINT nFlags, CPoint point) + { + BOOL bNotifyClick = FALSE; + UINT uCmdID = 0; + CBkWindow* pWndClick = NULL; + + if (m_bCaptureSetted) + { + ReleaseCapture(); + m_bCaptureSetted = FALSE; + } + + if (m_hBkWndPushDown) + { + pWndClick = BkWnds::GetWindow(m_hBkWndPushDown); + + if (pWndClick) + { + _ModifyWndState(pWndClick, 0, BkWndState_PushDown); + + if (m_hBkWndPushDown == m_hBkWndHover) + { + pWndClick->BkSendMessage(WM_LBUTTONUP, (WPARAM)nFlags, MAKELPARAM(point.x, point.y)); + + LPCTSTR lpszUrl = pWndClick->GetLinkUrl(); + if (lpszUrl && lpszUrl[0]) + { + HINSTANCE hRet = ::ShellExecute(NULL, _T("open"), lpszUrl, NULL, NULL, SW_SHOWNORMAL); + } + else if (pWndClick->GetCmdID()) + { + bNotifyClick = TRUE; + uCmdID = pWndClick->GetCmdID(); + } + } + } + + m_hBkWndPushDown = NULL; + } + + if (bNotifyClick) + { + BKNMCOMMAND nms; + nms.hdr.code = BKNM_COMMAND; + nms.hdr.hwndFrom = m_hWnd; + nms.hdr.idFrom = GetDlgCtrlID(); + nms.uItemID = uCmdID; + nms.szItemClass = pWndClick->GetObjectClass(); + + LRESULT lRet = ::SendMessage(GetParent(), WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + } + + } + + void OnLButtonDblClk(UINT nFlags, CPoint point) + { + HBKWND hBkWndHitTest = m_bkHeader.BkGetHWNDFromPoint(point, TRUE); + + if (hBkWndHitTest) + { + CBkWindow* pWndPushDown = BkWnds::GetWindow(hBkWndHitTest); + + if (!(pWndPushDown->IsClass("button") || pWndPushDown->IsClass("imgbtn") || pWndPushDown->IsClass("link"))) + { + if (m_bCanMaximize) + { + CWindow &wndParent = GetParent(); + DWORD dwStyle = wndParent.GetStyle(); + + if (WS_MAXIMIZE == (dwStyle & WS_MAXIMIZE)) + wndParent.SendMessage(WM_SYSCOMMAND, SC_RESTORE | HTCAPTION); + else + wndParent.SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE | HTCAPTION); + } + + return; + } + } + } + + BOOL OnSetCursor(CWindow /*wnd*/, UINT nHitTest, UINT message) + { + if (m_hBkWndHover) + { + CBkWindow *pBkWndHover = BkWnds::GetWindow(m_hBkWndHover); + + if (pBkWndHover && !pBkWndHover->IsDisabled(TRUE)) + { + pBkWndHover->SetCursor(); + return TRUE; + } + } + + ::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW))); + + return TRUE; + } + + BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) + { + return FALSE; + } + + LRESULT OnChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + return ::SendMessage(::GetParent(m_hWnd), uMsg, wParam, lParam); + } + + LRESULT OnToolTipEvent(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + if(m_wndToolTip.IsWindow()) + { + MSG msg = { m_hWnd, uMsg, wParam, lParam }; + + m_wndToolTip.RelayEvent(&msg); + } + + SetMsgHandled(FALSE); + + return 0; + } + + LRESULT OnBKINMInvalidateRect(LPNMHDR pnmh) + { + LPBKINMINVALIDATERECT pnms = (LPBKINMINVALIDATERECT)pnmh; + CRect rcWnd = pnms->rect; + + _InvalidateRect(rcWnd); + + return 0; + } + +protected: + BEGIN_MSG_MAP_EX(CBkDialogViewImpl) + MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnToolTipEvent) + MSG_WM_SIZE(OnSize) + MSG_WM_PRINT(OnPrint) + MSG_WM_PAINT(OnPaint) + MSG_WM_DESTROY(OnDestroy) + MSG_WM_ERASEBKGND(OnEraseBkgnd) + MSG_WM_MOUSEMOVE(OnMouseMove) + MSG_WM_MOUSELEAVE(OnMouseLeave) + MSG_WM_LBUTTONDOWN(OnLButtonDown) + MSG_WM_LBUTTONUP(OnLButtonUp) + MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk) + MSG_WM_SETCURSOR(OnSetCursor) + MSG_WM_MOUSEWHEEL(OnMouseWheel) + NOTIFY_CODE_HANDLER_EX(BKINM_INVALIDATERECT, OnBKINMInvalidateRect) + REFLECT_NOTIFY_CODE(NM_CUSTOMDRAW) + MESSAGE_HANDLER_EX(WM_NOTIFY, OnChildNotify) + MESSAGE_HANDLER_EX(WM_COMMAND, OnChildNotify) + MESSAGE_HANDLER_EX(WM_VSCROLL, OnChildNotify) + MESSAGE_HANDLER_EX(WM_HSCROLL, OnChildNotify) + REFLECT_NOTIFICATIONS_EX() + END_MSG_MAP() +}; + +////////////////////////////////////////////////////////////////////////// +// CBkDialogView + +class CBkDialogView + : public CBkDialogViewImpl +{ +}; + +////////////////////////////////////////////////////////////////////////// +// Default view control id in CBkDialogImpl + +#define IDC_RICHVIEW_WIN 1000 + +////////////////////////////////////////////////////////////////////////// +// CBkDialogImpl + +template +class ATL_NO_VTABLE CBkDialogImpl : public CWindowImpl +{ +public: + + static BOOL IsWinXPAndLater() + { + DWORD dwVersion = GetVersion(); + DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); + DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); + + if (dwMajorVersion > 5) // Vista and later + return TRUE; + else if (dwMajorVersion < 5) // 98/NT4 and before + return FALSE; + else if (dwMinorVersion > 0) // XP and 2003 + return TRUE; + else // 2000 + return FALSE; + } + + static ATL::CWndClassInfo& GetWndClassInfo() + { + static ATL::CWndClassInfo wc = { + { sizeof(WNDCLASSEX), + CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | (IsWinXPAndLater() ? CS_DROPSHADOW : 0), + StartWindowProc, 0, 0, NULL, NULL, NULL, + (HBRUSH)(COLOR_WINDOW + 1), NULL, NULL, NULL }, + NULL, NULL, IDC_ARROW, TRUE, 0, _T("") + }; + return wc; + } + +public: + CBkDialogImpl(UINT uResID = 0) + : m_uResID(uResID) + , m_bShowWindow(TRUE) + , m_bExitModalLoop(FALSE) + { + } + CBkDialogImpl(LPCTSTR xmlPath) + : m_xmlPath(xmlPath) + , m_uResID(0) + , m_bShowWindow(TRUE) + , m_bExitModalLoop(FALSE) + { + } + virtual ~CBkDialogImpl() + { + + } + +protected: + typedef CBkDialogImpl __thisClass; + + UINT m_uResID; + CString m_xmlPath; + UINT m_uRetCode; + + TBkView m_richView; + + BOOL m_bShowWindow; + + void ResizeClient(SIZE sizeClient, BOOL bRedraw) + { + ResizeClient(sizeClient.cx, sizeClient.cy, bRedraw); + } + + void ResizeClient(int cx, int cy, BOOL bRedraw) + { + CRect rcWindow, rcClient; + CPoint ptWindow; + + GetWindowRect(rcWindow); + GetClientRect(rcClient); + + ptWindow = rcWindow.TopLeft(); + + rcWindow.MoveToXY(0, 0); + + rcWindow -= rcClient; + rcClient.SetRect(0, 0, cx, cy); + rcWindow += rcClient; + + rcWindow.MoveToXY(ptWindow); + + MoveWindow(rcWindow, bRedraw); + } + + void OnSize(UINT nType, CSize size) + { + CRect rcClient; + + GetClientRect(rcClient); + + if (SIZE_MINIMIZED != nType) + { + if (m_richView.m_hWnd) + m_richView.MoveWindow(rcClient); + + } + + SetMsgHandled(FALSE); + } + + BOOL OnEraseBkgnd(CDCHandle dc) + { + return TRUE; + } + + LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam) + { + if (bCalcValidRects) + { + CRect rcWindow; + + GetWindowRect(rcWindow); + + LPNCCALCSIZE_PARAMS pParam = (LPNCCALCSIZE_PARAMS)lParam; + + if (SWP_NOSIZE == (SWP_NOSIZE & pParam->lppos->flags)) + return 0; + + if (0 == (SWP_NOMOVE & pParam->lppos->flags)) + { + rcWindow.left = pParam->lppos->x; + rcWindow.top = pParam->lppos->y; + } + + rcWindow.right = rcWindow.left + pParam->lppos->cx; + rcWindow.bottom = rcWindow.top + pParam->lppos->cy; + pParam->rgrc[0] = rcWindow; + pParam->rgrc[1] = pParam->rgrc[0]; + } + + return 0; + } + + void OnGetMinMaxInfo(LPMINMAXINFO lpMMI) + { + HMONITOR hMonitor = ::MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONULL); + + if (hMonitor) + { + MONITORINFO mi = {sizeof(MONITORINFO)}; + ::GetMonitorInfo(hMonitor, &mi); + + CRect rcWork = mi.rcWork, rcMonitor = mi.rcMonitor; + lpMMI->ptMaxPosition.x = abs(rcWork.left - rcMonitor.left) - 1; + lpMMI->ptMaxPosition.y = abs(rcWork.top - rcMonitor.top) - 1; + lpMMI->ptMaxSize.x = abs(rcWork.Width()) + 2; + lpMMI->ptMaxSize.y = abs(rcWork.Height()) + 2; + lpMMI->ptMaxTrackSize.x = abs(rcWork.Width()) + 2; + lpMMI->ptMaxTrackSize.y = abs(rcWork.Height()) + 2; + } + } + + BOOL OnNcActivate(BOOL bActive) + { + return TRUE; + } + +public: + + BOOL Load(UINT uResID) + { + CStringA strXml; + + BOOL bRet = BkResManager::LoadResource(uResID, strXml); + + if (!bRet) + return FALSE; + + return SetXml(strXml); + } + + BOOL Load(LPCTSTR fileName) + { + CStringA strXml; + + BOOL bRet = BkResManager::LoadResource(fileName, strXml); + + if (!bRet) + return FALSE; + + return SetXml(strXml); + } + + BOOL Load() // already set xml + { + BOOL bRet = FALSE; + if (m_uResID) + { + bRet = Load(m_uResID); + } + if (!bRet && !m_xmlPath.IsEmpty()) + { + bRet = Load(m_xmlPath); + } + return bRet; + } + + BOOL SetXml(LPCSTR lpszXml) + { + return m_richView.SetXml(lpszXml); + } + + HWND GetViewHWND() + { + return m_richView.m_hWnd; + } + + BOOL SetPanelXml(UINT uItemID, UINT uResID) + { + return m_richView.SetPanelXml(uItemID, uResID); + } + + BOOL SetPanelXml(UINT uItemID, LPCSTR lpszXml) + { + return m_richView.SetPanelXml(uItemID, lpszXml); + } + + BOOL SetRichText(UINT uItemID, UINT uResID) + { + return m_richView.SetRichText(uItemID, uResID); + } + + BOOL FormatRichText(UINT uItemID, LPCTSTR lpszFormat, ...) + { + va_list args; + CString strText; + + va_start(args, lpszFormat); + + strText.FormatV(lpszFormat, args); + + return m_richView.SetRichText(uItemID, strText); + } + + BOOL SetRichText(UINT uItemID, LPCWSTR lpszXml) + { + return m_richView.SetRichText(uItemID, lpszXml); + } + + BOOL SetRichText(UINT uItemID, LPCSTR lpszXml) + { + return m_richView.SetRichText(uItemID, lpszXml); + } + + BOOL SetItemText(UINT uItemID, LPCTSTR lpszText) + { + return m_richView.SetItemText(uItemID, lpszText); + } + + BOOL FormatItemText(UINT uItemID, LPCTSTR lpszFormat, ...) + { + va_list args; + CString strText; + + va_start(args, lpszFormat); + + strText.FormatV(lpszFormat, args); + + return m_richView.SetItemText(uItemID, strText); + } + + BOOL SetItemAttribute(UINT uItemID, LPCSTR lpszAttrib, LPCSTR lpszValue) + { + return m_richView.SetItemAttribute(uItemID, lpszAttrib, lpszValue); + } + + BOOL GetItemRect(UINT uItemID, RECT &rcItem) + { + return m_richView.GetItemRect(uItemID, rcItem); + } + + BOOL SetItemStringAttribute(UINT uItemID, LPCSTR lpszAttrib, LPCTSTR lpszValue) + { + return m_richView.SetItemStringAttribute(uItemID, lpszAttrib, lpszValue); + } + + BOOL SetItemIntAttribute(UINT uItemID, LPCSTR lpszAttrib, int nValue) + { + return m_richView.SetItemIntAttribute(uItemID, lpszAttrib, nValue); + } + + BOOL SetItemDWordAttribute(UINT uItemID, LPCSTR lpszAttrib, DWORD dwValue) + { + return m_richView.SetItemDWordAttribute(uItemID, lpszAttrib, dwValue); + } + + BOOL SetItemColorAttribute(UINT uItemID, LPCSTR lpszAttrib, COLORREF crValue) + { + return m_richView.SetItemColorAttribute(uItemID, lpszAttrib, crValue); + } + + BOOL GetItemCheck(UINT uItemID) + { + return m_richView.GetItemCheck(uItemID); + } + + BOOL SetItemCheck(UINT uItemID, BOOL bCheck) + { + return m_richView.SetItemCheck(uItemID, bCheck); + } + + BOOL IsItemEnable(UINT uItemID, BOOL bCheckParent = FALSE) + { + return m_richView.IsItemEnable(uItemID, bCheckParent); + } + + BOOL EnableItem(UINT uItemID, BOOL bEnable) + { + return m_richView.EnableItem(uItemID, bEnable); + } + + BOOL IsItemVisible(UINT uItemID, BOOL bCheckParent = FALSE) + { + return m_richView.IsItemVisible(uItemID, bCheckParent); + } + + BOOL SetItemVisible(UINT uItemID, BOOL bVisible) + { + return m_richView.SetItemVisible(uItemID, bVisible); + } + + BOOL SetTabCurSel(UINT uItemID, int nPage) + { + return m_richView.SetTabCurSel(uItemID, nPage); + } + + int GetTabCurSel(UINT uItemID) + { + return m_richView.GetTabCurSel(uItemID); + } + + BOOL SetTabTitle(UINT uItemID, int nPage, LPCTSTR lpszTitle) + { + return m_richView.SetTabTitle(uItemID, nPage, lpszTitle); + } + + BOOL IsTabPageVisible(UINT uItemID, int nPage) + { + return m_richView.IsTabPageVisible(uItemID, nPage); + } + + BOOL SetTabPageVisible(UINT uItemID, int nPage, BOOL bVisible) + { + return m_richView.SetTabPageVisible(uItemID, nPage, bVisible); + } + + BOOL SetItemIconHandle(UINT uItemID, HICON hIcon) + { + return m_richView.SetItemIconHandle(uItemID, hIcon); + } + + BOOL SetItemPaintHook(UINT uItemID, IBkWindowPaintHook* lpPaintHook) + { + return m_richView.SetItemPaintHook(uItemID, lpPaintHook); + } + + void SetWindowCaption(LPCTSTR lpszCaption) + { + m_richView.SetWindowCaption(lpszCaption); + } + + // Call at WM_INITDIALOG + void DontShowWindow() + { + m_bShowWindow = FALSE; + } + + HWND Create(HWND hWndParent = ::GetActiveWindow(), LPRECT rect = NULL) + { + if (!m_richView.XmlLoaded()) + { + if (!Load()) + { + return NULL; + } + } + + CRect rcWnd(0, 0, 0, 0); + LPCTSTR lpszCaption = m_richView.GetWindowCaption(); + + if (_T('\0') == lpszCaption[0]) + lpszCaption = NULL; + + if (rect) + rcWnd = rect; + + HWND hWnd = __super::Create(hWndParent, rcWnd, lpszCaption, m_richView.GetDlgStyle(), m_richView.GetDlgExStyle()); + if (!hWnd) + return NULL; + + BkWinThemeFunc::SetWindowTheme(hWnd, L"", L""); + + if (rect) + { + rcWnd.MoveToXY(0, 0); + m_richView.Create(m_hWnd, rcWnd, 0, 0, IDC_RICHVIEW_WIN); + } + else + m_richView.Create(m_hWnd, NULL, 0, 0, IDC_RICHVIEW_WIN); + + m_bShowWindow = TRUE; + + SendMessage(WM_INITDIALOG, (WPARAM)hWnd); + + m_richView.ShowAllRealWindows(TRUE); + + if (m_hWnd == hWnd) + { + SIZE sizeDefault = m_richView.GetDefaultSize(); + if (sizeDefault.cx && sizeDefault.cy) + { + ResizeClient(sizeDefault, FALSE); + } + } + else + hWnd = m_hWnd; + + return hWnd; + } + + UINT_PTR DoModal(HWND hWndParent = NULL, LPRECT rect = NULL) + { + BOOL bEnableParent = FALSE; + + if (NULL == hWndParent) + { + hWndParent = BkWinManager::GetActive(); + if (NULL == hWndParent) + hWndParent = ::GetActiveWindow(); + } + + if (hWndParent && hWndParent != ::GetDesktopWindow() && ::IsWindowEnabled(hWndParent)) + { + ::EnableWindow(hWndParent, FALSE); + bEnableParent = TRUE; + } + + m_bExitModalLoop = FALSE; + + HWND hWnd = Create(hWndParent, rect); + if (!hWnd) + { + ::EnableWindow(hWndParent, TRUE); + return 0; + } + + HWND hWndLastActive = BkWinManager::SetActive(hWnd); + + if (!rect) + CenterWindow(); + + if (m_bShowWindow) + { + + ::SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW); + } + + _ModalMessageLoop(); + + m_bExitModalLoop = FALSE; + + // From MFC + // hide the window before enabling the parent, etc. + SetWindowPos( + NULL, 0, 0, 0, 0, + SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); + + if (bEnableParent) + { + ::EnableWindow(hWndParent, TRUE); + } + + if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd) + ::SetActiveWindow(hWndParent); + + BkWinManager::SetActive(hWndLastActive); + + DestroyWindow(); + + return m_uRetCode; + } + + void OnClose() + { + SendMessage(WM_COMMAND, MAKELONG(IDCANCEL, 0), NULL); + } + + void EndDialog(UINT uRetCode) + { + m_uRetCode = uRetCode; + + m_bExitModalLoop = TRUE; + + // DestroyWindowֱSendWM_DESTROYԲܵDoModalϢѭд + // DestroyWindow(); + + // dzҪDoModalϢѭһΣֹGetMessageᱼ~~~~~~~ + ::PostThreadMessage(::GetCurrentThreadId(), WM_NULL, 0, 0); + } + + void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) + { + if (IsWindowEnabled()) + { + if (::GetKeyState(VK_CONTROL) >= 0) + { + if (VK_ESCAPE == nChar) + { + SendMessage(WM_COMMAND, MAKELONG(IDCANCEL, 0), NULL); + } + else if (VK_RETURN == nChar) + { + SendMessage(WM_COMMAND, MAKELONG(IDOK, 0), NULL); + } + } + + SetMsgHandled(FALSE); + } + } + + void OnOK(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wndCtl*/) + { + BKNMCOMMAND nms; + nms.hdr.code = BKNM_COMMAND; + nms.hdr.hwndFrom = m_hWnd; + nms.hdr.idFrom = IDC_RICHVIEW_WIN; + nms.uItemID = IDOK; + nms.szItemClass = ""; + + LRESULT lRet = ::SendMessage(m_hWnd, WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + } + + void OnCancel(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wndCtl*/) + { + BKNMCOMMAND nms; + nms.hdr.code = BKNM_COMMAND; + nms.hdr.hwndFrom = m_hWnd; + nms.hdr.idFrom = IDC_RICHVIEW_WIN; + nms.uItemID = IDCANCEL; + nms.szItemClass = ""; + + LRESULT lRet = ::SendMessage(m_hWnd, WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + } + +protected: + + BOOL m_bExitModalLoop; + + void _ModalMessageLoop() + { + BOOL bRet; + MSG msg; + + for(;;) + { + if (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) + { + if (WM_QUIT == msg.message) + break; + } + + if (m_bExitModalLoop || NULL == m_hWnd || !::IsWindow(m_hWnd)) + break; + + bRet = ::GetMessage(&msg, NULL, 0, 0); + + if (bRet == -1) + { + continue; // error, don't process + } + else if (!bRet) + { + ATLTRACE(L"Why Receive WM_QUIT here?\r\n"); + break; // WM_QUIT, exit message loop + } + + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + } + + BEGIN_MSG_MAP_EX(CBkDialogImpl) + MSG_WM_NCACTIVATE(OnNcActivate) + MSG_WM_ERASEBKGND(OnEraseBkgnd) + MSG_WM_NCCALCSIZE(OnNcCalcSize) + MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo) + MSG_WM_SIZE(OnSize) + MSG_WM_KEYDOWN(OnKeyDown) + MSG_WM_CLOSE(OnClose) + COMMAND_ID_HANDLER_EX(IDOK, OnOK) + COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) + END_MSG_MAP() +}; + +////////////////////////////////////////////////////////////////////////// +// CBkSimpleDialog + +class CBkSimpleDialog + : public CBkDialogImpl +{ +public: + CBkSimpleDialog(UINT uResID = 0) + : CBkDialogImpl(uResID) + { + } +protected: + + void OnBkCommand(UINT uItemID, LPCSTR szItemClass) + { + if (strcmp(CBkButton::GetClassName(), szItemClass) != 0 && strcmp(CBkImageBtnWnd::GetClassName(), szItemClass) != 0) + return; + + EndDialog(uItemID); + } + + BK_NOTIFY_MAP(IDC_RICHVIEW_WIN) + BK_NOTIFY_COMMAND(OnBkCommand) + BK_NOTIFY_MAP_END() + + BEGIN_MSG_MAP_EX(CBkDialogImpl) + MSG_BK_NOTIFY(IDC_RICHVIEW_WIN) + CHAIN_MSG_MAP(CBkDialogImpl) + END_MSG_MAP() +}; diff --git a/Client/Client/GUI/BKWin/bkwin/bkimage.h b/Client/Client/GUI/BKWin/bkwin/bkimage.h new file mode 100644 index 00000000..a075f72b --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkimage.h @@ -0,0 +1,734 @@ +////////////////////////////////////////////////////////////////////////// +// Class Name: CBkImage +// Description: Image Helper for KAV32 (Ver.2008) +// Creator: Zhang Xiaoxuan +// Version: 2007.10.19 - 1.0 - Create +// 2007.10.20 - 1.1 - Finish the draw method of 32bit bitmap +// with alpha channel +// 2007.10.23 - 1.2 - support no MFC and no WTL +// 2007.11.01 - 1.3 - add some method for use: +// CreateBitmap +// Draw(HBITMAP, int, int, int) +// +// Notice: 1. 32bit bitmap should be loaded by LoadDIBSection to +// get faster +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "../bkres/bkbmppool.h" +#include + +#ifdef __AFXWIN_H__ // If MFC + #define M_HOBJECT m_hObject +#else + #ifdef __ATLGDI_H__ // If WTL + #define M_HOBJECT m_hBitmap + #else + #define _KIMAGE_SDK_VER_ + #define M_HOBJECT m_hObject + #endif +#endif + +extern "C" IMAGE_DOS_HEADER __ImageBase; + +class CBkImage +#ifndef _KIMAGE_SDK_VER_ + #ifdef __AFXWIN_H__ // If MFC + : public CBitmap + #else // If WTL + : public CBitmapHandle + #endif +#endif +{ +public: + + CBkImage(void) + : m_lSubImageWidth(0) + , m_nTransparentMode(ModeNone) + , m_crMask(RGB(0xFF, 0, 0xFF)) + { +#ifdef _KIMAGE_SDK_VER_ + M_HOBJECT = NULL; +#endif + } + ~CBkImage(void) + { +#ifdef _KIMAGE_SDK_VER_ + if (M_HOBJECT) + { + ::DeleteObject(M_HOBJECT); + m_hObject = NULL; + } +#endif + } + +#ifdef _KIMAGE_SDK_VER_ + int GetBitmap(BITMAP* pBitMap) + { + if (NULL == M_HOBJECT) + return -1; + + return ::GetObject(M_HOBJECT, sizeof(BITMAP), pBitMap); + } + + BOOL Attach(HGDIOBJ hObject) + { + if (NULL == hObject) + return FALSE; + + M_HOBJECT = hObject; + + return TRUE; + } + + HGDIOBJ Detach() + { + HGDIOBJ hObject = M_HOBJECT; + + M_HOBJECT = NULL; + + return hObject; + } + + BOOL DeleteObject() + { + if (NULL == M_HOBJECT) + return FALSE; + + return ::DeleteObject(Detach()); + } + + operator HBITMAP() const + { + return (HBITMAP)m_hObject; + } +#endif + + CBkImage& operator=( __in const CBkImage& src) + { + M_HOBJECT = src.M_HOBJECT; + m_lSubImageWidth = src.m_lSubImageWidth; + m_crMask = src.m_crMask; + m_nTransparentMode = src.m_nTransparentMode; + + return( *this ); + } + + CBkImage& operator=( __in const HBITMAP hBmp) + { + Attach(hBmp); + + return( *this ); + } + + CBkImage& operator=( __in const UINT uResID) + { + Attach(BkBmpPool::GetBitmap(uResID)); + + return( *this ); + } + + BOOL GetImageSize(SIZE &sizeImage) + { + BITMAP bmp; + BOOL bRet = GetBitmap(&bmp); + + if (!bRet) + return FALSE; + + sizeImage.cx = bmp.bmWidth; + sizeImage.cy = bmp.bmHeight; + + return TRUE; + } + + void SetSubImageWidth(LONG lWidth) + { + m_lSubImageWidth = lWidth; + } + + LONG GetSubImageWidth() + { + return m_lSubImageWidth; + } + + enum { ModeNone, ModeMaskColor, ModeAlpha }; + + void SetTransparentMode(int nMode) + { + m_nTransparentMode = nMode; + } + + void SetMaskColor(COLORREF crMask) + { + m_crMask = crMask; + } + + BOOL LoadDIBSection(UINT nIDResource, HINSTANCE hInst = (HINSTANCE)&__ImageBase) + { + HGDIOBJ hLoad = ::LoadImage(hInst, MAKEINTRESOURCE(nIDResource), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); + BOOL bResult = FALSE; + + if (!hLoad) + return FALSE; + + Attach((HBITMAP)hLoad); + + return bResult; + } + + BOOL LoadDIBSectionFromFile(LPCTSTR lpszFileName) + { + HGDIOBJ hLoad = ::LoadImage(NULL, lpszFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE); + BOOL bResult = FALSE; + + if (!hLoad) + return FALSE; + + Attach((HBITMAP)hLoad); + + return bResult; + } + + BOOL CreateBitmap(int nWidth, int nHeight, COLORREF crBackground = CLR_INVALID) + { + HDC hDCDesktop = ::GetDC(NULL); + HBITMAP hBmpCreate = ::CreateCompatibleBitmap(hDCDesktop, nWidth, nHeight); + + Attach(hBmpCreate); + + if (crBackground != CLR_INVALID) + { + HDC hDCDraw = ::CreateCompatibleDC(hDCDesktop); + HGDIOBJ hbmpOld = ::SelectObject(hDCDraw, hBmpCreate); + RECT rcDraw = {0, 0, nWidth, nHeight}; + COLORREF clrOld = ::SetBkColor(hDCDraw, crBackground); + + ATLASSERT(clrOld != CLR_INVALID); + + if(clrOld != CLR_INVALID) + { + ::ExtTextOut(hDCDraw, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, NULL); + ::SetBkColor(hDCDraw, clrOld); + } + + ::SelectObject(hDCDraw, hbmpOld); + ::DeleteDC(hDCDraw); + } + + ::ReleaseDC(NULL, hDCDesktop); + + return hBmpCreate != NULL; + } + + BOOL BitBlt(HDC hDC, int x, int y, int nWidth, int nHeight, int xSrc, int ySrc, DWORD dwRop, int nSubImage = -1) + { + BOOL bRet = FALSE; + HDC hDCDesktop = ::GetDC(NULL); + HDC hDCDraw = ::CreateCompatibleDC(hDCDesktop); + HGDIOBJ hbmpOld = ::SelectObject(hDCDraw, M_HOBJECT); + + ::ReleaseDC(NULL, hDCDesktop); + + if (-1 != nSubImage && 0 != m_lSubImageWidth) + { + xSrc += nSubImage * m_lSubImageWidth; + } + + if (ModeNone == m_nTransparentMode) + bRet = ::BitBlt(hDC, x, y, nWidth, nHeight, hDCDraw, xSrc, ySrc, dwRop); + else if (ModeMaskColor == m_nTransparentMode) + bRet = TransparentBlt2(hDC, x, y, nWidth, nHeight, hDCDraw, xSrc, ySrc, nWidth, nHeight, m_crMask); + + ::SelectObject(hDCDraw, hbmpOld); + ::DeleteDC(hDCDraw); + + return bRet; + } + + BOOL StretchBlt(HDC hDC, int x, int y, int nWidth, int nHeight, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop, int nSubImage = -1) + { + HDC hDCDesktop = ::GetDC(NULL); + HDC hDCDraw = ::CreateCompatibleDC(hDCDesktop); + HGDIOBJ hbmpOld = ::SelectObject(hDCDraw, M_HOBJECT); + + ::ReleaseDC(NULL, hDCDesktop); + + if (-1 != nSubImage && 0 != m_lSubImageWidth) + { + xSrc += nSubImage * m_lSubImageWidth; + } + + BOOL bRet = FALSE; + + if (ModeNone == m_nTransparentMode) + bRet = ::StretchBlt(hDC, x, y, nWidth, nHeight, hDCDraw, xSrc, ySrc, nSrcWidth, nSrcHeight, dwRop); + else if (ModeMaskColor == m_nTransparentMode) + bRet = TransparentBlt2(hDC, x, y, nWidth, nHeight, hDCDraw, xSrc, ySrc, nSrcWidth, nSrcHeight, m_crMask); + + ::SelectObject(hDCDraw, hbmpOld); + ::DeleteDC(hDCDraw); + + return bRet; + } + + BOOL Draw(HBITMAP hBmpDest, int nPosX, int nPosY, int nSubImage = -1/* All */) + { + HDC hDCDesktop = ::GetDC(NULL); + HDC hDCDraw = ::CreateCompatibleDC(hDCDesktop); + HGDIOBJ hbmpOld = ::SelectObject(hDCDraw, hBmpDest); + + BOOL bRet = Draw(hDCDraw, nPosX, nPosY, nSubImage); + + ::SelectObject(hDCDraw, hbmpOld); + ::DeleteDC(hDCDraw); + ::ReleaseDC(NULL, hDCDesktop); + + return bRet; + } + + BOOL Draw(HDC hDC, int nPosX, int nPosY, int nSubImage = -1/* All */) + { + BOOL bResult = FALSE; + int nDrawWidth = 0, nDrawHeight = 0, nSrcPosX = 0, nSrcPosY = 0; + HDC hDCDesktop = NULL, hDCSrc = NULL; + BITMAP bmp; + HGDIOBJ hbmpOld = NULL; + + BLENDFUNCTION fnBlend = {AC_SRC_OVER, 0, 0xFF, AC_SRC_ALPHA}; + + if (NULL == M_HOBJECT) + goto Exit0; + + if (0 == m_lSubImageWidth && -1 != nSubImage) + goto Exit0; + + GetBitmap(&bmp); + + nDrawHeight = bmp.bmHeight; + + if (-1 == nSubImage) + { + nDrawWidth = bmp.bmWidth; + } + else + { + nDrawWidth = m_lSubImageWidth; + nSrcPosX = nSubImage * m_lSubImageWidth; + } + + if (ModeAlpha == m_nTransparentMode) + { + //_PreAlphaBlend((HBITMAP)m_hObject); + + bResult = AlphaBlend(hDC, nPosX, nPosY, nDrawWidth, nDrawHeight, (HBITMAP)M_HOBJECT, nSrcPosX, nSrcPosY); + + goto Exit0; + } + + hDCDesktop = ::GetDC(NULL); + hDCSrc = ::CreateCompatibleDC(hDCDesktop); + ::ReleaseDC(NULL, hDCDesktop); + + hbmpOld = ::SelectObject(hDCSrc, M_HOBJECT); + + switch (m_nTransparentMode) + { + case ModeNone: + bResult = ::BitBlt(hDC, nPosX, nPosY, nDrawWidth, nDrawHeight, hDCSrc, nSrcPosX, nSrcPosY, SRCCOPY); + break; + + case ModeMaskColor: + bResult = TransparentBlt2(hDC, nPosX, nPosY, nDrawWidth, nDrawHeight, hDCSrc, nSrcPosX, nSrcPosY, nDrawWidth, nDrawHeight, m_crMask); + break; + case ModeAlpha: + // API AlphaBlendΪԤˣɫʧɴԼдһ + //::AlphaBlend(hDC, nPosX, nPosY, nDrawWidth, nDrawHeight, hDCSrc, nSrcPosX, nSrcPosY, nDrawWidth, nDrawHeight, fnBlend); + break; + + default: + bResult = FALSE; + + break; + } + + ::SelectObject(hDCSrc, hbmpOld); + + Exit0: + + if (NULL != hDCSrc) + { + ::DeleteDC(hDCSrc); + hDCSrc = NULL; + } + + return bResult; + } + + + BOOL Draw2(HDC hDC, int nPosX, int nPosY, int cx, int cy, int nSubImage = -1/* All */) + { + BOOL bResult = FALSE; + int nDrawWidth = 0, nDrawHeight = 0, nSrcPosX = 0, nSrcPosY = 0; + HDC hDCDesktop = NULL, hDCSrc = NULL; + BITMAP bmp; + HGDIOBJ hbmpOld = NULL; + + BLENDFUNCTION fnBlend = {AC_SRC_OVER, 0, 0xFF, AC_SRC_ALPHA}; + + if (NULL == M_HOBJECT) + goto Exit0; + + if (0 == m_lSubImageWidth && -1 != nSubImage) + goto Exit0; + + GetBitmap(&bmp); + + nDrawHeight = cy; + + if (-1 == nSubImage) + { + nDrawWidth = cx; + } + else + { + nDrawWidth = m_lSubImageWidth; + nSrcPosX = nSubImage * m_lSubImageWidth; + } + + if (ModeAlpha == m_nTransparentMode) + { + //_PreAlphaBlend((HBITMAP)m_hObject); + + bResult = AlphaBlend(hDC, nPosX, nPosY, nDrawWidth, nDrawHeight, (HBITMAP)M_HOBJECT, nSrcPosX, nSrcPosY); + + goto Exit0; + } + + hDCDesktop = ::GetDC(NULL); + hDCSrc = ::CreateCompatibleDC(hDCDesktop); + ::ReleaseDC(NULL, hDCDesktop); + + hbmpOld = ::SelectObject(hDCSrc, M_HOBJECT); + + switch (m_nTransparentMode) + { + case ModeNone: + bResult = ::BitBlt(hDC, nPosX, nPosY, nDrawWidth, nDrawHeight, hDCSrc, nSrcPosX, nSrcPosY, SRCCOPY); + break; + + case ModeMaskColor: + bResult = TransparentBlt2(hDC, nPosX, nPosY, nDrawWidth, nDrawHeight, hDCSrc, nSrcPosX, nSrcPosY, nDrawWidth, nDrawHeight, m_crMask); + break; + case ModeAlpha: + // API AlphaBlendΪԤˣɫʧɴԼдһ + //::AlphaBlend(hDC, nPosX, nPosY, nDrawWidth, nDrawHeight, hDCSrc, nSrcPosX, nSrcPosY, nDrawWidth, nDrawHeight, fnBlend); + break; + + default: + bResult = FALSE; + + break; + } + + ::SelectObject(hDCSrc, hbmpOld); + +Exit0: + + if (NULL != hDCSrc) + { + ::DeleteDC(hDCSrc); + hDCSrc = NULL; + } + + return bResult; + } + + + // СڵnAlphaĵطΪ͸ط͸ + HRGN CreateHollyRgn(INT nAlpha) + { + return CreateHollyRgn((HBITMAP)M_HOBJECT, nAlpha); + } + +protected: + + LONG m_lSubImageWidth; + int m_nTransparentMode; + COLORREF m_crMask; + +public: + +#ifdef _KIMAGE_SDK_VER_ + HGDIOBJ m_hObject; +#endif + + // Ԥ + static BOOL AlphaPremultiplication(HBITMAP hbmpSrc) + { + LPVOID pBitsSrc = NULL; + BYTE* psrc = NULL; + BOOL bResult = FALSE; + + BITMAP bmpSrc; + + ::GetObject(hbmpSrc, sizeof(BITMAP), &bmpSrc); + + // Only support 32bit DIB section + if (32 != bmpSrc.bmBitsPixel || NULL == bmpSrc.bmBits) + goto Exit0; + + psrc = (BYTE *) bmpSrc.bmBits; + + // Just mix it + for (int nPosY = 0; nPosY < abs(bmpSrc.bmHeight); nPosY ++) + { + for (int nPosX = bmpSrc.bmWidth; nPosX > 0; nPosX --) + { + BYTE alpha = psrc[3]; + + psrc[0] = (BYTE)((psrc[0] * alpha) / 255); + psrc[1] = (BYTE)((psrc[1] * alpha) / 255); + psrc[2] = (BYTE)((psrc[2] * alpha) / 255); + + psrc += 4; + } + } + +Exit0: + + return bResult; + } + + static HRGN CreateHollyRgn(HBITMAP hbmpSrc, INT nAlpha) + { + LPVOID pBitsSrc = NULL; + BYTE* psrc = NULL; + BOOL bResult = FALSE; + HRGN hRgn = NULL; + BITMAP bmpSrc; + + ::GetObject(hbmpSrc, sizeof(BITMAP), &bmpSrc); + + // Only support 32bit DIB section + if (32 != bmpSrc.bmBitsPixel || NULL == bmpSrc.bmBits) + return NULL; + + psrc = (BYTE *) bmpSrc.bmBits; + for (int nPosY = 0; nPosY < abs(bmpSrc.bmHeight); nPosY ++) + { + int nLastEmpty = -1; + int nLastSolid = -1; + + for (int nPosX = 0; nPosX < bmpSrc.bmWidth;) + { + while ((nPosX < bmpSrc.bmWidth) && (psrc[3] <= nAlpha)) + { + nPosX ++, psrc += 4; + } + int nLeft = nPosX; + if (nPosX < bmpSrc.bmWidth) + { + while ((nPosX < bmpSrc.bmWidth) && (psrc[3] > nAlpha)) + { + nPosX ++, psrc += 4; + } + int nRight = nPosX; + // ҵһRECT + int nTop = bmpSrc.bmHeight - nPosY-1; + int nBottom = nTop+1; + + HRGN hRgnNew = ::CreateRectRgn(nLeft, nTop, nRight, nBottom); + if (!hRgn) + hRgn = hRgnNew; + else + { + if (::CombineRgn(hRgn, hRgn, hRgnNew, RGN_OR) == ERROR) + { + if (hRgn) + ::DeleteObject(hRgn); + ::DeleteObject(hRgnNew); + return NULL; + } + ::DeleteObject(hRgnNew); + } + } + } + } + return hRgn; + } + + static BOOL AlphaBlend(HDC hDC, int x, int y, int cx, int cy, HBITMAP hbmpSrc, int srcx, int srcy) + { + BITMAPINFOHEADER bmihDraw = { sizeof(BITMAPINFOHEADER), 0, 0, 1, 24 }; + LPVOID pBitsTemp = NULL, pBitsSrc = NULL; + HBITMAP hBmpSrcTemp = NULL, hBmpTemp = NULL; + HDC hMemDC = NULL, hMemDCDraw = NULL; + HGDIOBJ hOld = NULL, hOldDraw = NULL; + const BYTE* psrc = NULL; + BYTE *pdst = NULL; + BOOL bResult = FALSE; + + BITMAP bmpSrc; + + ::GetObject(hbmpSrc, sizeof(BITMAP), &bmpSrc); + + // Only support 32bit bitmap + if (32 != bmpSrc.bmBitsPixel) + goto Exit0; + + hMemDC = ::CreateCompatibleDC(hDC); + + bmihDraw.biWidth = cx; + bmihDraw.biHeight = cy; + + if (bmpSrc.bmBits) // hbmpSrc is DIB section now + pBitsSrc = bmpSrc.bmBits; + else + { // Create a DIB section + bmihDraw.biBitCount = 32; + + hBmpSrcTemp = ::CreateDIBSection(NULL, (BITMAPINFO *)&bmihDraw, DIB_RGB_COLORS, &pBitsSrc, NULL, NULL); + if (hBmpSrcTemp == NULL) + goto Exit0; + + hMemDCDraw = ::CreateCompatibleDC(hDC); + + hOldDraw = ::SelectObject(hMemDCDraw, hbmpSrc); + hOld = ::SelectObject(hMemDC, hBmpSrcTemp); + + ::BitBlt(hMemDC, 0, 0, bmpSrc.bmWidth, bmpSrc.bmHeight, hMemDCDraw, 0, 0, SRCCOPY); + + ::SelectObject(hMemDC, hOld); + ::SelectObject(hMemDCDraw, hOldDraw); + + ::DeleteDC(hMemDCDraw); + + bmihDraw.biBitCount = 24; + } + + // Create a temp canvas for mix images + hBmpTemp = ::CreateDIBSection(NULL, (BITMAPINFO *)&bmihDraw, DIB_RGB_COLORS, &pBitsTemp, NULL, NULL); + + if (hBmpTemp == NULL) + goto Exit0; + + hOld = ::SelectObject(hMemDC, hBmpTemp); + + // Draw background to the temp canvas + ::BitBlt(hMemDC, 0, 0, cx, cy, hDC, x, y, SRCCOPY); + + psrc = (const BYTE *) pBitsSrc; + pdst = (BYTE *) pBitsTemp; + + // Just mix it + for (int nPosY = 0; nPosY < abs(bmpSrc.bmHeight); nPosY ++) + { + for (int nPosX = bmpSrc.bmWidth; nPosX > 0; nPosX --) + { + if (bmpSrc.bmWidth - nPosX >= srcx && bmpSrc.bmWidth - nPosX < srcx + cx && nPosY >= srcy && nPosY < srcy + cy) + { + BYTE alpha = psrc[3]; + BYTE salpha = 255 - alpha; + + pdst[0] = (BYTE)((psrc[0] * alpha + pdst[0] * salpha) / 255); + pdst[1] = (BYTE)((psrc[1] * alpha + pdst[1] * salpha) / 255); + pdst[2] = (BYTE)((psrc[2] * alpha + pdst[2] * salpha) / 255); + + pdst += 3; + } + + psrc += 4; + } + + pdst += ((4 - (cx * 3) % 4) & 3); + } + + // Do the real thing + bResult = ::BitBlt(hDC, x, y, cx, cy, hMemDC, 0, 0, SRCCOPY); + +Exit0: + + if (hMemDC) + { + ::SelectObject(hMemDC, hOld); + ::DeleteObject(hMemDC); + } + + if (hBmpTemp) + { + ::DeleteObject(hBmpTemp); + } + + if (hBmpSrcTemp) + ::DeleteObject(hBmpSrcTemp); + + return bResult; + } + + static BOOL TransparentBlt2( + HDC hdcDest, // ĿDC + int nXOriginDest, // ĿXƫ + int nYOriginDest, // ĿYƫ + int nWidthDest, // Ŀ + int nHeightDest, // Ŀ߶ + HDC hdcSrc, // ԴDC + int nXOriginSrc, // ԴX + int nYOriginSrc, // ԴY + int nWidthSrc, // Դ + int nHeightSrc, // Դ߶ + UINT crTransparent // ͸ɫ,COLORREF + ) + { + HBITMAP hOldImageBMP = NULL, hImageBMP = NULL, hOldMaskBMP = NULL, hMaskBMP = NULL; + HDC hImageDC = NULL, hMaskDC = NULL; + + hImageBMP = ::CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest); // λͼ + hMaskBMP = ::CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL); // ɫλͼ + hImageDC = ::CreateCompatibleDC(hdcDest); + hMaskDC = ::CreateCompatibleDC(hdcDest); + + hOldImageBMP = (HBITMAP)::SelectObject(hImageDC, hImageBMP); + hOldMaskBMP = (HBITMAP)::SelectObject(hMaskDC, hMaskBMP); + + // ԴDCеλͼʱDC + if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc) + ::BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY); + else + ::StretchBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, + hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY); + + // ͸ɫ + ::SetBkColor(hImageDC, crTransparent); + + // ͸ΪɫΪɫλͼ + ::BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY); + + // ͸Ϊɫ򱣳ֲλͼ + ::SetBkColor(hImageDC, RGB(0,0,0)); + ::SetTextColor(hImageDC, RGB(255,255,255)); + ::BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND); + + // ͸ֱĻ䣬ֱɺɫ + COLORREF crBg = ::SetBkColor(hdcDest, RGB(255, 255, 255)); + COLORREF crText = ::SetTextColor(hdcDest, RGB(0, 0, 0)); + ::BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND); + + // "",Ч + ::BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT); + + // ָ + ::SelectObject(hImageDC, hOldImageBMP); + ::DeleteDC(hImageDC); + ::SelectObject(hMaskDC, hOldMaskBMP); + ::DeleteDC(hMaskDC); + ::DeleteObject(hImageBMP); + ::DeleteObject(hMaskBMP); + + ::SetBkColor(hdcDest, crBg); + ::SetTextColor(hdcDest, crText); + + return TRUE; + } +}; diff --git a/Client/Client/GUI/BKWin/bkwin/bklistbox.h b/Client/Client/GUI/BKWin/bkwin/bklistbox.h new file mode 100644 index 00000000..2e3bc2b4 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bklistbox.h @@ -0,0 +1,886 @@ +////////////////////////////////////////////////////////////////////////// +// Class Name: CBkListBox +// Creator: yykingking +// Version: 2010.9.10 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include + +////////////////////////////////////////////////////////////////////////// +// Beike List Box Notify + +// Get Display Info Notify +#define BKLBM_GET_DISPINFO 1 + +typedef struct _BKLBMGETDISPINFO +{ + NMHDR hdr; + int nListItemID; + BOOL bHover; + BOOL bSelect; + DWORD nHeight; +} BKLBMGETDISPINFO, *LPBKLBMGETDISPINFO; + +// Item Click Notify +#define BKLBM_ITEMCLICK 2 + +typedef struct _BKLBMITEMCLICK +{ + NMHDR hdr; + int nListItemID; + UINT uCmdID; +} BKLBMITEMCLICK, *LPBKLBMITEMCLICK; + +#define BKLBM_CALC_ITEM_HEIGHT 3 + +typedef struct _BKLBITEMMEASUREITEM +{ + NMHDR hdr; + int nListItemId; + BOOL bHover; + BOOL bSelect; + DWORD nHeight; +} BKLBITEMCACLHEIGHT, *LPBKLBITEMMEASUREITEM; + +#define BKLBM_CALC_MAX_HEIGHT 4 + +typedef struct _BKLBITEMCALCMAXITEM +{ + NMHDR hdr; + DWORD nMaxHeight; +} BKLBITEMCALCMAXITEM, *LPBKLBITEMCALCMAXITEM; + +// Item Click Notify +#define BKLBM_ITEMDBCLICK 5 + +typedef struct _BKLBMITEMDBCLICK +{ + NMHDR hdr; + int nListItemID; +} BKLBMITEMDBCLICK, *LPBKLBMITEMDBCLICK; + +////////////////////////////////////////////////////////////////////////// + + + +template +class CBkListBoxImpl : + public CBkListBoxBase + , public CBkViewImpl +{ + friend CBkViewImpl; + +protected: + + typedef CBkListBoxBase __baseClass; + typedef CBkListBoxImpl __thisClass; + + CBkDialog m_bkListTemplate; + CToolTipCtrl m_wndToolTip; + BOOL m_bXmlLoaded; + CBkImage m_imgMem; + int m_nMaxItemHeight; + + // Only one hover control + HBKWND m_hBkWndHover; + // Only one pushdown control + HBKWND m_hBkWndPushDown; + + int m_nHoverItem; + int m_nPushItem; + int m_nLastDrawItem; + int m_nFixHeight; + + // Tracking flag + BOOL m_bTrackFlag; + + BOOL m_bCaptureSetted; + BOOL m_bCanGetFocus; +public: + + CBkListBoxImpl() + : m_bXmlLoaded(FALSE) + , m_nMaxItemHeight(0) + , m_hBkWndHover(NULL) + , m_hBkWndPushDown(NULL) + , m_bTrackFlag(FALSE) + , m_bCaptureSetted(FALSE) + , m_nHoverItem(-1) + , m_nPushItem(-1) + , m_nLastDrawItem(-1) + , m_bCanGetFocus(TRUE) + , m_nFixHeight(-1) + { + } + + ~CBkListBoxImpl() + { + if (m_imgMem.m_hBitmap) + m_imgMem.DeleteObject(); + } + + HWND Create( + HWND hWndParent, _U_RECT rect = NULL, DWORD dwStyle = 0, + DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + if (NULL != m_hWnd) + return m_hWnd; + + HWND hWnd = __baseClass::Create(hWndParent, rect, NULL, dwStyle, dwExStyle, MenuOrID, lpCreateParam); + + if (hWnd) + { + // SetExtendedListViewStyle(LVS_EX_FULLROWSELECT); + + ModifyStyle(LBS_MULTIPLESEL, 0); + + // InsertColumn(0, L"", LVCFMT_LEFT, 1); + + m_bkListTemplate.SetContainer(m_hWnd); + + m_wndToolTip.Create(hWnd); + m_wndToolTip.SetMaxTipWidth(400); + + CToolInfo ti(0, hWnd); + m_wndToolTip.AddTool(ti); + m_wndToolTip.Activate(TRUE); + } + + return hWnd; + }; + + HWND Create(HWND hWndParent, _U_MENUorID MenuOrID) + { + return Create(hWndParent, NULL, 0, 0, MenuOrID, NULL); + }; + + BOOL Load(UINT uResID) + { + CStringA strXml; + + BOOL bRet = BkResManager::LoadResource(uResID, strXml); + + if (!bRet) + return FALSE; + + return SetXml(strXml); + } + + BOOL XmlLoaded() + { + return m_bXmlLoaded; + } + + BOOL SetXml(LPCSTR lpszXml) + { + CStringA strValue; + + TiXmlDocument xmlDoc; + + m_bXmlLoaded = FALSE; + + m_bkListTemplate.BkSendMessage(WM_DESTROY); + + { // Free stack + xmlDoc.Parse(lpszXml, NULL, TIXML_ENCODING_UTF8); + } + + if (xmlDoc.Error()) + { +// _Redraw(); + return FALSE; + } + + TiXmlElement *pXmlRootElem = xmlDoc.RootElement(); + + strValue = pXmlRootElem->Value(); + if (strValue != "listitem") + { +// _Redraw(); + return FALSE; + } + + int nItemHeight = 0; + pXmlRootElem->Attribute("height", &nItemHeight); + + if (0 != nItemHeight) + { + _SetMaxItemHeight(nItemHeight); + + m_bkListTemplate.Load(pXmlRootElem); + CStringA strPos; + strPos.Format("0,0,-0,%d", nItemHeight); + m_bkListTemplate.SetAttribute("pos", strPos, TRUE); + } + + m_bXmlLoaded = TRUE; + + if (!m_hWnd) + return TRUE; + +// _Redraw(); + +// m_hBkWndHover = NULL; +// m_hBkWndPushDown = NULL; + + return TRUE; + } + + void RedrawItem(int nItem) + { + _RedrawItem(nItem, TRUE); + } + + CBkWindow* FindChildByCmdID(UINT uCmdID) + { + return m_bkListTemplate.FindChildByCmdID(uCmdID); + } + + BOOL SetItemText(UINT uItemID, LPCTSTR lpszText) + { + return CBkViewImpl::SetItemText(uItemID, lpszText); + } + + BOOL SetCanGetFocus(BOOL bCan) + { + m_bCanGetFocus = bCan; + return TRUE; + } + +// BOOL SetItemCount(int nItems) +// { +// SetColumnWidth(0, 1); +// +// BOOL bRet = __super::SetItemCount(nItems); +// +// _ResizeColumn(); +// +// return bRet; +// } + +public: + + VOID SetItemFixHeight(DWORD nHeight) + { + m_nFixHeight = nHeight; + } + // ˷ᴥһеĸ߶ + void SetItemCount(int nCount) + { + __baseClass::SetRedraw(FALSE); + + m_nLastDrawItem = -1; + m_nHoverItem = -1; + m_nPushItem = -1; + + __baseClass::ResetContent(); + __baseClass::SetCount(nCount); + + if ( m_nFixHeight == -1 ) + { + BKLBITEMCALCMAXITEM calcMax; + + calcMax.hdr.code = BKLBM_CALC_MAX_HEIGHT; + calcMax.hdr.hwndFrom = m_hWnd; + calcMax.hdr.idFrom = GetDlgCtrlID(); + calcMax.nMaxHeight = 0; + + ::SendMessage(GetParent(), WM_NOTIFY, (LPARAM)calcMax.hdr.idFrom, (WPARAM)&calcMax); + _SetMaxItemHeight(calcMax.nMaxHeight); + } + else + { + _SetMaxItemHeight(m_nFixHeight); + } + + __baseClass::SetRedraw(TRUE); + __baseClass::InvalidateRect(NULL,FALSE); + } + + void DrawItem(LPDRAWITEMSTRUCT lpcd) + { + int nItem = (int)lpcd->itemID; + + if ( nItem < 0 ) + return; + + BkWinManager::EnterPaintLock(); + + CRect rcItem; + __baseClass::GetItemRect(nItem, rcItem); + + if (m_nLastDrawItem != nItem) + { + _GetItemDisplayInfo(nItem); + } + + + CDC dcMem; + CDCHandle dcMemHandle; + HDC hDCDesktop = ::GetDC(NULL); + dcMem.CreateCompatibleDC(hDCDesktop); + ::ReleaseDC(NULL, hDCDesktop); + HBITMAP hbmpOld = dcMem.SelectBitmap(m_imgMem); + + HFONT hftOld = dcMem.SelectFont(BkFontPool::GetFont(BKF_DEFAULTFONT)); + + dcMem.SetBkMode(TRANSPARENT); + + CRgn rgnNull; + + dcMemHandle.Attach(dcMem); + + CBkWindow *pWndHover = NULL, *pWndPush = NULL; + + if (nItem != m_nHoverItem && NULL != m_hBkWndHover) + { + pWndHover = BkWnds::GetWindow(m_hBkWndHover); + pWndHover->ModifyState(0, BkWndState_Hover); + } + + if (nItem != m_nPushItem && NULL != m_hBkWndPushDown) + { + pWndPush = BkWnds::GetWindow(m_hBkWndPushDown); + pWndPush->ModifyState(0, BkWndState_PushDown); + } + + + // drawitemĴСһô²һ + CRect rcLast; + m_bkListTemplate.GetRect(&rcLast); + if ( rcLast.Width() != rcItem.Width() || rcLast.Height() != rcItem.Height() ) + { + WINDOWPOS WndPos = { 0, 0, 0, 0, rcItem.Width(), rcItem.Height(), SWP_SHOWWINDOW }; + + m_bkListTemplate.BkSendMessage(WM_WINDOWPOSCHANGED, 0, (LPARAM)&WndPos); + } + + m_bkListTemplate.RedrawRegion(dcMemHandle, rgnNull); + + if (pWndHover) + pWndHover->ModifyState(BkWndState_Hover, 0); + + if (pWndPush) + pWndPush->ModifyState(BkWndState_PushDown, 0); + + dcMemHandle.Detach(); + + dcMem.SelectFont(hftOld); + dcMem.SelectBitmap(hbmpOld); + + BkWinManager::LeavePaintLock(); + + m_imgMem.Draw2( lpcd->hDC, rcItem.left, rcItem.top, rcItem.Width(), rcItem.Height() ); + } + + void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) + { + if ( m_nFixHeight == -1 ) + { + BKLBITEMCACLHEIGHT nms; + int nItem = lpMeasureItemStruct->itemID; + + nms.hdr.code = BKLBM_CALC_ITEM_HEIGHT; + nms.hdr.hwndFrom = m_hWnd; + nms.hdr.idFrom = GetDlgCtrlID(); + nms.nListItemId = nItem; + nms.bHover = nItem == m_nHoverItem; + nms.bSelect = nItem == __baseClass::GetCurSel(); + nms.nHeight = 0; + + ::SendMessage(GetParent(), WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + + lpMeasureItemStruct->itemHeight = nms.nHeight; + } + else + { + lpMeasureItemStruct->itemHeight = m_nFixHeight; + } + } + +protected: + + BOOL SetItemText(int nItem, int nSubItem, LPCTSTR lpszText) + { + return FALSE; + } + + void _RedrawItem(int nItem, BOOL bReload = FALSE) + { + if (-1 == nItem) + return; + + if (bReload) + m_nLastDrawItem = -1; + + __baseClass::ReDrawItem(nItem); + } + + void _SetMaxItemHeight(int nHeight) + { + if (nHeight <= m_nMaxItemHeight) + return; + + m_nMaxItemHeight = nHeight; + + CRect rcClient; + + GetClientRect(rcClient); + + if (rcClient.Width() == 0) + return; + + if (m_imgMem.M_HOBJECT) + m_imgMem.DeleteObject(); + + m_imgMem.CreateBitmap(rcClient.Width(), m_nMaxItemHeight, RGB(0, 0, 0)); + } + + void _ModifyWndState(CBkWindow *pWnd, DWORD dwStateAdd, DWORD dwStateRemove) + { + pWnd->ModifyState(dwStateAdd, dwStateRemove); + } + + void _GetItemDisplayInfo(int nItem) + { + BKLBMGETDISPINFO nms; + nms.hdr.code = BKLBM_GET_DISPINFO; + nms.hdr.hwndFrom = m_hWnd; + nms.hdr.idFrom = GetDlgCtrlID(); + nms.bHover = nItem == m_nHoverItem; + nms.bSelect = nItem == __baseClass::GetCurSel(); + nms.nListItemID = nItem; + nms.nHeight = 0; + ::SendMessage(GetParent(), WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + + m_nLastDrawItem = nItem; + + // xmlС + CStringA strPos; + if (m_nFixHeight != -1 ) + strPos.Format("0,0,-0,%d", m_nFixHeight); + else + strPos.Format("0,0,-0,%d", nms.nHeight); + m_bkListTemplate.SetAttribute("pos", strPos, TRUE); + } + + void _InvalidateControl(CBkWindow *pWnd, BOOL bCheckVisible = TRUE) + { + } + + int _HitTest(CPoint& point) + { + BOOL uFlags = 0; + int nItem = __baseClass::ItemFromPoint(point, uFlags); + + HBKWND hBkWndHitTest = NULL; + + if (-1 != nItem) + { + CRect rcItem; + __baseClass::GetItemRect(nItem, rcItem); + point -= rcItem.TopLeft(); + } + + return nItem; + } + + void _ResizeColumn() + { + CRect rcClient; + + GetWindowRect(rcClient); + + if (rcClient.Width() == 0) + return; + + if (m_imgMem.M_HOBJECT) + m_imgMem.DeleteObject(); + + rcClient.MoveToXY(0, 0); + rcClient.right -= ::GetSystemMetrics(SM_CXVSCROLL); + + m_imgMem.CreateBitmap(rcClient.Width(), m_nMaxItemHeight, RGB(0, 0, 0)); + + SetColumnWidth(rcClient.Width()); + + WINDOWPOS WndPos = { 0, 0, rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), SWP_SHOWWINDOW }; + + m_bkListTemplate.BkSendMessage(WM_WINDOWPOSCHANGED, 0, (LPARAM)&WndPos); + } + + void OnSize(UINT nType, CSize /*size*/) + { + _ResizeColumn(); + + __baseClass::Referesh(); + } + + void OnMouseMove(UINT nFlags, CPoint point) + { + if (!m_bTrackFlag) + { + m_nLastDrawItem = -1; + + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(tme); + tme.hwndTrack = m_hWnd; + tme.dwFlags = TME_LEAVE; + tme.dwHoverTime = 0; + m_bTrackFlag = _TrackMouseEvent(&tme); + } + + HBKWND hBkWndHitTest = NULL; + int nItem = _HitTest(point); + + if (-1 != nItem) + hBkWndHitTest = m_bkListTemplate.BkGetHWNDFromPoint(point, TRUE); + + if (m_nHoverItem != nItem) + { + CBkWindow* pWndHoverOld = BkWnds::GetWindow(m_hBkWndHover); + + if (pWndHoverOld && !pWndHoverOld->IsDisabled(TRUE)) + { + _ModifyWndState(pWndHoverOld, 0, BkWndState_Hover); + pWndHoverOld->BkSendMessage(WM_MOUSELEAVE); + } + + m_hBkWndHover = NULL; + + int nOldHoverItem = m_nHoverItem; + + m_nHoverItem = nItem; + + _RedrawItem(nOldHoverItem, TRUE); + _RedrawItem(m_nHoverItem, TRUE); + m_wndToolTip.UpdateTipText(L"", m_hWnd); + } + + CBkWindow* pWndHover = BkWnds::GetWindow(hBkWndHitTest); + + if (pWndHover) + { + pWndHover->BkSendMessage(WM_MOUSEMOVE, (WPARAM)nFlags, MAKELPARAM(point.x, point.y)); + + if (hBkWndHitTest != m_hBkWndHover) + { + CRect rcInvalidate; + + if (NULL != m_hBkWndHover) + { + CBkWindow* pWndHoverOld = BkWnds::GetWindow(m_hBkWndHover); + + if (pWndHoverOld && !pWndHoverOld->IsDisabled(TRUE)) + { + _ModifyWndState(pWndHoverOld, 0, BkWndState_Hover); + if (pWndHoverOld->NeedRedrawWhenStateChange()) + _RedrawItem(m_nHoverItem); + pWndHoverOld->BkSendMessage(WM_MOUSELEAVE); + } + } + + if (!pWndHover->IsDisabled(TRUE)) + { + _ModifyWndState(pWndHover, BkWndState_Hover, 0); + if (pWndHover->NeedRedrawWhenStateChange()) + _RedrawItem(m_nHoverItem); + } + + m_hBkWndHover = hBkWndHitTest; + + if (pWndHover) + { + _GetItemDisplayInfo(m_nHoverItem); + m_wndToolTip.UpdateTipText(pWndHover->GetToolTipText(), m_hWnd); + } + } + } + } + + void OnMouseLeave() + { + m_wndToolTip.UpdateTipText(L"", m_hWnd); + + m_bTrackFlag = FALSE; + + if (m_hBkWndHover) + { + CBkWindow* pWndHover = BkWnds::GetWindow(m_hBkWndHover); + if (pWndHover) + { + _ModifyWndState(pWndHover, 0, BkWndState_Hover); + pWndHover->BkSendMessage(WM_MOUSELEAVE); + } + + m_hBkWndHover = NULL; + } + +// if (m_hBkWndPushDown) +// { +// CBkWindow* pWndPushdown = BkWnds::GetWindow(m_hBkWndPushDown); +// if (pWndPushdown) +// _ModifyWndState(pWndPushdown, 0, BkWndState_PushDown); +// +// m_hBkWndPushDown = NULL; +// } + + _RedrawItem(m_nHoverItem, TRUE); + + m_nHoverItem = -1; + } + + void OnLButtonDbClick(UINT nFlags, CPoint point) + { + if (m_bCanGetFocus) + SetFocus(); + + HBKWND hBkWndHitTest = NULL; + int nItem = _HitTest(point), nSelectItem = __baseClass::GetCurSel(); + + if (-1 != nItem) + hBkWndHitTest = m_bkListTemplate.BkGetHWNDFromPoint(point, TRUE); + + __baseClass::SetCurSel(nItem); + + if (nItem != nSelectItem) + { + int nOldSelect = nSelectItem; + nSelectItem = nItem; + _RedrawItem(nOldSelect, TRUE); + _RedrawItem(nItem, TRUE); + } + + CBkWindow* pWndPushDown = BkWnds::GetWindow(hBkWndHitTest); + + if (pWndPushDown) + { + if (pWndPushDown->IsDisabled(TRUE)) + return; + + if (!m_bCaptureSetted) + { + SetCapture(); + m_bCaptureSetted = TRUE; + + if (hBkWndHitTest != m_hBkWndHover) + { + // HoverPushdownͬԭǣһֱûˢ£лλõĿؼ + //ATLASSERT(FALSE); + m_hBkWndHover = hBkWndHitTest; + } + + m_hBkWndPushDown = hBkWndHitTest; + + _ModifyWndState(pWndPushDown, BkWndState_PushDown, 0); + + m_nPushItem = nItem; + + pWndPushDown->BkSendMessage(WM_LBUTTONDBLCLK, (WPARAM)nFlags, MAKELPARAM(point.x, point.y)); + + if (pWndPushDown->NeedRedrawWhenStateChange()) + _RedrawItem(nItem); + } + + BKLBMITEMDBCLICK nms; + nms.hdr.code = BKLBM_ITEMDBCLICK; + nms.hdr.hwndFrom = m_hWnd; + nms.hdr.idFrom = GetDlgCtrlID(); + nms.nListItemID = m_nPushItem; + + ::SendMessage(GetParent(), WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + } + } + + void OnLButtonDown(UINT nFlags, CPoint point) + { + if (m_bCanGetFocus) + SetFocus(); + + HBKWND hBkWndHitTest = NULL; + int nItem = _HitTest(point), nSelectItem = __baseClass::GetCurSel(); + + if (-1 != nItem) + hBkWndHitTest = m_bkListTemplate.BkGetHWNDFromPoint(point, TRUE); + + __baseClass::SetCurSel(nItem); + + if (nItem != nSelectItem) + { + int nOldSelect = nSelectItem; + nSelectItem = nItem; + _RedrawItem(nOldSelect, TRUE); + _RedrawItem(nItem, TRUE); + } + + CBkWindow* pWndPushDown = BkWnds::GetWindow(hBkWndHitTest); + + if (pWndPushDown) + { + if (pWndPushDown->IsDisabled(TRUE)) + return; + + if (!m_bCaptureSetted) + { + SetCapture(); + m_bCaptureSetted = TRUE; + + if (hBkWndHitTest != m_hBkWndHover) + { + // HoverPushdownͬԭǣһֱûˢ£лλõĿؼ + //ATLASSERT(FALSE); + m_hBkWndHover = hBkWndHitTest; + } + + m_hBkWndPushDown = hBkWndHitTest; + + _ModifyWndState(pWndPushDown, BkWndState_PushDown, 0); + + m_nPushItem = nItem; + + pWndPushDown->BkSendMessage(WM_LBUTTONDOWN, (WPARAM)nFlags, MAKELPARAM(point.x, point.y)); + + if (pWndPushDown->NeedRedrawWhenStateChange()) + _RedrawItem(nItem); + } + } + } + + void OnLButtonUp(UINT nFlags, CPoint point) + { + BOOL bNotifyClick = FALSE; + UINT uCmdID = 0; + CBkWindow* pWndClick = NULL; + + if (m_bCaptureSetted) + { + ReleaseCapture(); + m_bCaptureSetted = FALSE; + } + + if (m_hBkWndPushDown) + { + pWndClick = BkWnds::GetWindow(m_hBkWndPushDown); + + if (pWndClick) + { + _ModifyWndState(pWndClick, 0, BkWndState_PushDown); + + if (m_hBkWndPushDown == m_hBkWndHover && m_nHoverItem == m_nPushItem) + { + if (m_nLastDrawItem != m_nPushItem) + _GetItemDisplayInfo(m_nPushItem); + + pWndClick->BkSendMessage(WM_LBUTTONUP, (WPARAM)nFlags, MAKELPARAM(point.x, point.y)); + + LPCTSTR lpszUrl = pWndClick->GetLinkUrl(); + if (lpszUrl && lpszUrl[0]) + { + HINSTANCE hRet = ::ShellExecute(NULL, L"open", lpszUrl, NULL, NULL, SW_SHOWNORMAL); + } + else if (pWndClick->GetCmdID()) + { + bNotifyClick = TRUE; + uCmdID = pWndClick->GetCmdID(); + } + } + + if (bNotifyClick) + { + BKLBMITEMCLICK nms; + nms.hdr.code = BKLBM_ITEMCLICK; + nms.hdr.hwndFrom = m_hWnd; + nms.hdr.idFrom = GetDlgCtrlID(); + nms.nListItemID = m_nPushItem; + nms.uCmdID = uCmdID; + + LRESULT lRet = ::SendMessage(GetParent(), WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + } + + _RedrawItem(m_nPushItem, pWndClick->IsClass("check") || pWndClick->IsClass("radio")); + m_nPushItem = -1; + } + + m_hBkWndPushDown = NULL; + } + + } + + BOOL OnSetCursor(CWindow /*wnd*/, UINT nHitTest, UINT message) + { + if (m_hBkWndHover) + { + CBkWindow *pBkWndHover = BkWnds::GetWindow(m_hBkWndHover); + + if (pBkWndHover && !pBkWndHover->IsDisabled(TRUE)) + { + pBkWndHover->SetCursor(); + return TRUE; + } + } + + ::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW))); + + return TRUE; + } + + BOOL OnEraseBkgnd(CDCHandle dc) + { + return TRUE; + } + + BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) + { + DefWindowProc(); + + ScreenToClient(&pt); + + OnMouseMove(nFlags, pt); + + return FALSE; + } + + LRESULT OnToolTipEvent(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + if(m_wndToolTip.IsWindow()) + { + MSG msg = { m_hWnd, uMsg, wParam, lParam }; + + m_wndToolTip.RelayEvent(&msg); + } + + SetMsgHandled(FALSE); + + return 0; + } + + void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) + { + + } + +protected: + + BEGIN_MSG_MAP_EX(CBkListBoxImpl) + CHAIN_MSG_MAP(__baseClass) + MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnToolTipEvent) + MSG_WM_ERASEBKGND(OnEraseBkgnd) + MSG_WM_MOUSEMOVE(OnMouseMove) + MSG_WM_MOUSELEAVE(OnMouseLeave) + MSG_WM_MOUSEWHEEL(OnMouseWheel) + MSG_WM_LBUTTONDOWN(OnLButtonDown) + MSG_WM_LBUTTONUP(OnLButtonUp) + MSG_WM_LBUTTONDBLCLK(OnLButtonDbClick) + MSG_WM_SIZE(OnSize) + MSG_WM_SETCURSOR(OnSetCursor) + MSG_WM_KEYDOWN(OnKeyDown) + DEFAULT_REFLECTION_HANDLER() + END_MSG_MAP() +}; + +class CBkListBox : public CBkListBoxImpl +{ +}; diff --git a/Client/Client/GUI/BKWin/bkwin/bklistview.h b/Client/Client/GUI/BKWin/bkwin/bklistview.h new file mode 100644 index 00000000..f5baf5fb --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bklistview.h @@ -0,0 +1,758 @@ +////////////////////////////////////////////////////////////////////////// +// Class Name: CBkDlgView +// Description: Dialog View, Real Container of BkWindow +// Creator: ZhangXiaoxuan +// Version: 2010.5.11 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "bkdlgview.h" + +////////////////////////////////////////////////////////////////////////// +// Beike List View Notify + +// Get Display Info Notify +#define BKLVM_GET_DISPINFO 1 + +typedef struct _BKLVMGETDISPINFO +{ + NMHDR hdr; + int nListItemID; + BOOL bHover; + BOOL bSelect; +} BKLVMGETDISPINFO, *LPBKLVMGETDISPINFO; + +// Item Click Notify +#define BKLVM_ITEMCLICK 2 + +typedef struct _BKLVMITEMCLICK +{ + NMHDR hdr; + int nListItemID; + UINT uCmdID; +} BKLVMITEMCLICK, *LPBKLVMITEMCLICK; + +////////////////////////////////////////////////////////////////////////// + +typedef CWinTraits CBkListViewTraits; + +template +class CBkListViewImpl + : public ATL::CWindowImpl + , public CBkViewImpl + , public CCustomDraw +{ + friend CBkViewImpl; + +protected: + + typedef ATL::CWindowImpl __baseClass; + typedef CBkListViewImpl __thisClass; + + CBkDialog m_bkListTemplate; + CToolTipCtrl m_wndToolTip; + BOOL m_bXmlLoaded; + CBkImage m_imgMem; + int m_nItemHeight; + + // Only one hover control + HBKWND m_hBkWndHover; + // Only one pushdown control + HBKWND m_hBkWndPushDown; + + int m_nHoverItem; + int m_nPushItem; + int m_nLastDrawItem; + BOOL m_bWhenResizeScrollTop; + + // Tracking flag + BOOL m_bTrackFlag; + + BOOL m_bCaptureSetted; +public: + + CBkListViewImpl() + : m_bXmlLoaded(FALSE) + , m_nItemHeight(0) + , m_hBkWndHover(NULL) + , m_hBkWndPushDown(NULL) + , m_bTrackFlag(FALSE) + , m_bCaptureSetted(FALSE) + , m_nHoverItem(-1) + , m_nPushItem(-1) + , m_nLastDrawItem(-1) + , m_bWhenResizeScrollTop(FALSE) + { + } + + ~CBkListViewImpl() + { + if(NULL != m_imgMem.m_hBitmap) + m_imgMem.DeleteObject(); + } + + HWND Create( + HWND hWndParent, _U_RECT rect = NULL, DWORD dwStyle = 0, + DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + if (NULL != m_hWnd) + return m_hWnd; + + HWND hWnd = __baseClass::Create(hWndParent, rect, NULL, dwStyle, dwExStyle, MenuOrID, lpCreateParam); + + if (hWnd) + { + SetExtendedListViewStyle(LVS_EX_FULLROWSELECT); + + InsertColumn(0, L"", LVCFMT_LEFT, 1); + + m_bkListTemplate.SetContainer(m_hWnd); + + m_wndToolTip.Create(hWnd); + m_wndToolTip.SetMaxTipWidth(400); + + CToolInfo ti(0, hWnd); + m_wndToolTip.AddTool(ti); + m_wndToolTip.Activate(TRUE); + } + + return hWnd; + }; + + HWND Create(HWND hWndParent, _U_MENUorID MenuOrID) + { + return Create(hWndParent, NULL, 0, 0, MenuOrID, NULL); + }; + + BOOL Load(UINT uResID) + { + CStringA strXml; + + BOOL bRet = BkResManager::LoadResource(uResID, strXml); + + if (!bRet) + return FALSE; + + return SetXml(strXml); + } + + BOOL XmlLoaded() + { + return m_bXmlLoaded; + } + + BOOL SetXml(LPCSTR lpszXml) + { + CStringA strValue; + + TiXmlDocument xmlDoc; + + m_bXmlLoaded = FALSE; + + m_bkListTemplate.BkSendMessage(WM_DESTROY); + + { // Free stack + xmlDoc.Parse(lpszXml, NULL, TIXML_ENCODING_UTF8); + } + + if (xmlDoc.Error()) + { +// _Redraw(); + return FALSE; + } + + TiXmlElement *pXmlRootElem = xmlDoc.RootElement(); + + strValue = pXmlRootElem->Value(); + if (strValue != "listitem") + { +// _Redraw(); + return FALSE; + } + + int nItemHeight = 0; + pXmlRootElem->Attribute("height", &nItemHeight); + + if (0 != nItemHeight) + { + _SetItemHeight(nItemHeight); + + m_bkListTemplate.Load(pXmlRootElem); + CStringA strPos; + strPos.Format("0,0,-0,%d", nItemHeight); + m_bkListTemplate.SetAttribute("pos", strPos, TRUE); + } + + m_bXmlLoaded = TRUE; + + if (!m_hWnd) + return TRUE; + +// _Redraw(); + +// m_hBkWndHover = NULL; +// m_hBkWndPushDown = NULL; + + return TRUE; + } + + void RedrawItem(int nItem) + { + _RedrawItem(nItem, TRUE); + } + + CBkWindow* FindChildByCmdID(UINT uCmdID) + { + return m_bkListTemplate.FindChildByCmdID(uCmdID); + } + + BOOL SetItemText(UINT uItemID, LPCTSTR lpszText) + { + return CBkViewImpl::SetItemText(uItemID, lpszText); + } + + VOID SetWhenResizeScrollToTop( BOOL bAutoTop ) + { + m_bWhenResizeScrollTop = bAutoTop; + } + +// BOOL SetItemCount(int nItems) +// { +// SetColumnWidth(0, 1); +// +// BOOL bRet = __super::SetItemCount(nItems); +// +// _ResizeColumn(); +// +// return bRet; +// } + +public: + + DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) + { + return CDRF_NOTIFYITEMDRAW; + } + + DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw) + { + LPNMLVCUSTOMDRAW lpcd = (LPNMLVCUSTOMDRAW)lpNMCustomDraw; + + BkWinManager::EnterPaintLock(); + + int nItem = (int)lpcd->nmcd.dwItemSpec; + + if (m_nLastDrawItem != nItem) + { + _GetItemDisplayInfo(nItem); + } + + CDC dcMem; + CDCHandle dcMemHandle; + HDC hDCDesktop = ::GetDC(NULL); + dcMem.CreateCompatibleDC(hDCDesktop); + ::ReleaseDC(NULL, hDCDesktop); + HBITMAP hbmpOld = dcMem.SelectBitmap(m_imgMem); + + HFONT hftOld = dcMem.SelectFont(BkFontPool::GetFont(BKF_DEFAULTFONT)); + + dcMem.SetBkMode(TRANSPARENT); + + CRgn rgnNull; + + dcMemHandle.Attach(dcMem); + + CBkWindow *pWndHover = NULL, *pWndPush = NULL; + + if (nItem != m_nHoverItem && NULL != m_hBkWndHover) + { + pWndHover = BkWnds::GetWindow(m_hBkWndHover); + pWndHover->ModifyState(0, BkWndState_Hover); + } + + if (nItem != m_nPushItem && NULL != m_hBkWndPushDown) + { + pWndPush = BkWnds::GetWindow(m_hBkWndPushDown); + pWndPush->ModifyState(0, BkWndState_PushDown); + } + + m_bkListTemplate.RedrawRegion(dcMemHandle, rgnNull); + + if (pWndHover) + pWndHover->ModifyState(BkWndState_Hover, 0); + + if (pWndPush) + pWndPush->ModifyState(BkWndState_PushDown, 0); + + dcMemHandle.Detach(); + + dcMem.SelectFont(hftOld); + dcMem.SelectBitmap(hbmpOld); + + BkWinManager::LeavePaintLock(); + + CRect rcItem; + TBase::GetItemRect(nItem, rcItem, LVIR_BOUNDS); + + //CDCHandle dc = lpcd->nmcd.hdc; + + //dc.FillSolidRect(rcItem, RGB(0xCC, 0xCC, 0xCC)); + + m_imgMem.Draw(lpcd->nmcd.hdc, rcItem.left, rcItem.top); + + return CDRF_SKIPDEFAULT; + } + + void SetItemHeight(int nHeight) + { + _SetItemHeight( nHeight ); + } + +protected: + + BOOL SetItemText(int nItem, int nSubItem, LPCTSTR lpszText) + { + return FALSE; + } + + void _RedrawItem(int nItem, BOOL bReload = FALSE) + { + if (-1 == nItem) + return; + + if (bReload) + m_nLastDrawItem = -1; + + ATLTRACE(L"RedrawItem(%d)\r\n", nItem); + + RedrawItems(nItem, nItem); + } + + void _SetItemHeight(int nHeight) + { + CImageList imglst; + + imglst.Create(1, nHeight - 1, ILC_COLOR24, 0, 1); + + __super::SetImageList(imglst, LVSIL_SMALL); + __super::SetImageList(NULL, LVSIL_SMALL); + + imglst.Destroy(); + + m_nItemHeight = nHeight; + + CRect rcClient; + + GetClientRect(rcClient); + + if (rcClient.Width() == 0) + return; + + if (m_imgMem.M_HOBJECT) + m_imgMem.DeleteObject(); + + m_imgMem.CreateBitmap(rcClient.Width(), m_nItemHeight, RGB(0, 0, 0)); + } + + void _ModifyWndState(CBkWindow *pWnd, DWORD dwStateAdd, DWORD dwStateRemove) + { + pWnd->ModifyState(dwStateAdd, dwStateRemove); + } + + void _GetItemDisplayInfo(int nItem) + { + BKLVMGETDISPINFO nms; + nms.hdr.code = BKLVM_GET_DISPINFO; + nms.hdr.hwndFrom = m_hWnd; + nms.hdr.idFrom = GetDlgCtrlID(); + nms.bHover = nItem == m_nHoverItem; + nms.bSelect = nItem == CListViewCtrl::GetSelectedIndex(); + nms.nListItemID = nItem; + ::SendMessage(GetParent(), WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + + m_nLastDrawItem = nItem; + } + + void _InvalidateControl(CBkWindow *pWnd, BOOL bCheckVisible = TRUE) + { + } + + int _HitTest(CPoint& point) + { + UINT uFlags = 0; + int nItem = CListViewCtrl::HitTest(point, &uFlags); + + HBKWND hBkWndHitTest = NULL; + + if (-1 != nItem) + { + CRect rcItem; + TBase::GetItemRect(nItem, rcItem, LVIR_BOUNDS); + point -= rcItem.TopLeft(); + } + + return nItem; + } + + void _ResizeColumn() + { + CRect rcClient; + + GetWindowRect(rcClient); + + if (rcClient.Width() == 0) + return; + + if (m_imgMem.M_HOBJECT) + m_imgMem.DeleteObject(); + + rcClient.MoveToXY(0, 0); + // rcClient.right -= ::GetSystemMetrics(SM_CXVSCROLL); + + ModifyStyle(WS_HSCROLL,0); + + SetColumnWidth(0, rcClient.Width()); + + m_imgMem.CreateBitmap(rcClient.Width(), m_nItemHeight, RGB(0, 0, 0)); + + WINDOWPOS WndPos = { 0, 0, rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), SWP_SHOWWINDOW }; + + m_bkListTemplate.BkSendMessage(WM_WINDOWPOSCHANGED, 0, (LPARAM)&WndPos); + + } + + void OnSize(UINT nType, CSize /*size*/) + { + _ResizeColumn(); + } + + LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam) + { + SetMsgHandled(FALSE); + + if ( m_bWhenResizeScrollTop && GetItemCount() > 0 ) + { + Scroll( CSize(0,-65536) ); + } + + return 0; + } + + void OnMouseMove(UINT nFlags, CPoint point) + { + if (!m_bTrackFlag) + { + m_nLastDrawItem = -1; + + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(tme); + tme.hwndTrack = m_hWnd; + tme.dwFlags = TME_LEAVE; + tme.dwHoverTime = 0; + m_bTrackFlag = _TrackMouseEvent(&tme); + } + + HBKWND hBkWndHitTest = NULL; + int nItem = _HitTest(point); + + if (-1 != nItem) + hBkWndHitTest = m_bkListTemplate.BkGetHWNDFromPoint(point, TRUE); + + if (m_nHoverItem != nItem) + { + CBkWindow* pWndHoverOld = BkWnds::GetWindow(m_hBkWndHover); + + if (pWndHoverOld && !pWndHoverOld->IsDisabled(TRUE)) + { + _ModifyWndState(pWndHoverOld, 0, BkWndState_Hover); + pWndHoverOld->BkSendMessage(WM_MOUSELEAVE); + } + + m_hBkWndHover = NULL; + + int nOldHoverItem = m_nHoverItem; + + m_nHoverItem = nItem; + + _RedrawItem(nOldHoverItem, TRUE); + _RedrawItem(m_nHoverItem, TRUE); + m_wndToolTip.UpdateTipText(L"", m_hWnd); + } + + CBkWindow* pWndHover = BkWnds::GetWindow(hBkWndHitTest); + + if (pWndHover) + { + pWndHover->BkSendMessage(WM_MOUSEMOVE, (WPARAM)nFlags, MAKELPARAM(point.x, point.y)); + + if (hBkWndHitTest != m_hBkWndHover) + { + CRect rcInvalidate; + + if (NULL != m_hBkWndHover) + { + CBkWindow* pWndHoverOld = BkWnds::GetWindow(m_hBkWndHover); + + if (pWndHoverOld && !pWndHoverOld->IsDisabled(TRUE)) + { + _ModifyWndState(pWndHoverOld, 0, BkWndState_Hover); + if (pWndHoverOld->NeedRedrawWhenStateChange()) + _RedrawItem(m_nHoverItem); + pWndHoverOld->BkSendMessage(WM_MOUSELEAVE); + } + } + + if (!pWndHover->IsDisabled(TRUE)) + { + _ModifyWndState(pWndHover, BkWndState_Hover, 0); + if (pWndHover->NeedRedrawWhenStateChange()) + _RedrawItem(m_nHoverItem); + } + + m_hBkWndHover = hBkWndHitTest; + + if (pWndHover) + { + _GetItemDisplayInfo(m_nHoverItem); + m_wndToolTip.UpdateTipText(pWndHover->GetToolTipText(), m_hWnd); + } + } + } + } + + void OnMouseLeave() + { + m_wndToolTip.UpdateTipText(L"", m_hWnd); + + m_bTrackFlag = FALSE; + + if (m_hBkWndHover) + { + CBkWindow* pWndHover = BkWnds::GetWindow(m_hBkWndHover); + if (pWndHover) + { + _ModifyWndState(pWndHover, 0, BkWndState_Hover); + pWndHover->BkSendMessage(WM_MOUSELEAVE); + } + + m_hBkWndHover = NULL; + } + +// if (m_hBkWndPushDown) +// { +// CBkWindow* pWndPushdown = BkWnds::GetWindow(m_hBkWndPushDown); +// if (pWndPushdown) +// _ModifyWndState(pWndPushdown, 0, BkWndState_PushDown); +// +// m_hBkWndPushDown = NULL; +// } + + _RedrawItem(m_nHoverItem, TRUE); + + m_nHoverItem = -1; + } + + void OnLButtonDown(UINT nFlags, CPoint point) + { + SetFocus(); + + HBKWND hBkWndHitTest = NULL; + int nItem = _HitTest(point), nSelectItem = CListViewCtrl::GetSelectedIndex(); + + if (-1 != nItem) + hBkWndHitTest = m_bkListTemplate.BkGetHWNDFromPoint(point, TRUE); + + CListViewCtrl::SelectItem(nItem); + + if (nItem != nSelectItem) + { + int nOldSelect = nSelectItem; + nSelectItem = nItem; + _RedrawItem(nOldSelect, TRUE); + } + + CBkWindow* pWndPushDown = BkWnds::GetWindow(hBkWndHitTest); + + if (pWndPushDown) + { + if (pWndPushDown->IsDisabled(TRUE)) + return; + + if (!m_bCaptureSetted) + { + SetCapture(); + m_bCaptureSetted = TRUE; + + if (hBkWndHitTest != m_hBkWndHover) + { + // HoverPushdownͬԭǣһֱûˢ£лλõĿؼ + //ATLASSERT(FALSE); + m_hBkWndHover = hBkWndHitTest; + } + + m_hBkWndPushDown = hBkWndHitTest; + + _ModifyWndState(pWndPushDown, BkWndState_PushDown, 0); + + m_nPushItem = nItem; + + pWndPushDown->BkSendMessage(WM_LBUTTONDOWN, (WPARAM)nFlags, MAKELPARAM(point.x, point.y)); + + if (pWndPushDown->NeedRedrawWhenStateChange()) + _RedrawItem(nItem); + } + } + } + + void OnLButtonUp(UINT nFlags, CPoint point) + { + BOOL bNotifyClick = FALSE; + UINT uCmdID = 0; + CBkWindow* pWndClick = NULL; + + if (m_bCaptureSetted) + { + ReleaseCapture(); + m_bCaptureSetted = FALSE; + } + + if (m_hBkWndPushDown) + { + pWndClick = BkWnds::GetWindow(m_hBkWndPushDown); + + if (pWndClick) + { + _ModifyWndState(pWndClick, 0, BkWndState_PushDown); + + if (m_hBkWndPushDown == m_hBkWndHover && m_nHoverItem == m_nPushItem) + { + if (m_nLastDrawItem != m_nPushItem) + _GetItemDisplayInfo(m_nPushItem); + + pWndClick->BkSendMessage(WM_LBUTTONUP, (WPARAM)nFlags, MAKELPARAM(point.x, point.y)); + + LPCTSTR lpszUrl = pWndClick->GetLinkUrl(); + if (lpszUrl && lpszUrl[0]) + { + HINSTANCE hRet = ::ShellExecute(NULL, L"open", lpszUrl, NULL, NULL, SW_SHOWNORMAL); + } + else if (pWndClick->GetCmdID()) + { + bNotifyClick = TRUE; + uCmdID = pWndClick->GetCmdID(); + } + } + + if (bNotifyClick) + { + BKLVMITEMCLICK nms; + nms.hdr.code = BKLVM_ITEMCLICK; + nms.hdr.hwndFrom = m_hWnd; + nms.hdr.idFrom = GetDlgCtrlID(); + nms.nListItemID = m_nPushItem; + nms.uCmdID = uCmdID; + + LRESULT lRet = ::SendMessage(GetParent(), WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + } + + _RedrawItem(m_nPushItem, pWndClick->IsClass("check") || pWndClick->IsClass("radio")); + m_nPushItem = -1; + } + + m_hBkWndPushDown = NULL; + } + + } + + BOOL OnSetCursor(CWindow /*wnd*/, UINT nHitTest, UINT message) + { + if (m_hBkWndHover) + { + CBkWindow *pBkWndHover = BkWnds::GetWindow(m_hBkWndHover); + + if (pBkWndHover && !pBkWndHover->IsDisabled(TRUE)) + { + pBkWndHover->SetCursor(); + return TRUE; + } + } + + ::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW))); + + return TRUE; + } + + BOOL OnEraseBkgnd(CDCHandle dc) + { + int nTop = GetTopIndex(); + int nBottom = nTop + GetCountPerPage(); + + nBottom = min(nBottom, GetItemCount() - 1); + + CRect rcClient, rcItemTop, rcItemBottom; + COLORREF crBg = RGB(0xFF, 0xFF, 0xFF); + + GetClientRect(rcClient); + TBase::GetItemRect(nTop, rcItemTop, LVIR_BOUNDS); + TBase::GetItemRect(nBottom, rcItemBottom, LVIR_BOUNDS); + + dc.FillSolidRect(rcItemBottom.right, rcItemTop.top, rcClient.right - rcItemBottom.right, rcClient.bottom - rcItemTop.top, crBg); + dc.FillSolidRect(rcClient.left, rcItemBottom.bottom, rcItemBottom.Width(), rcClient.bottom - rcItemBottom.bottom, crBg); + + return TRUE; + } + + BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) + { + DefWindowProc(); + + ScreenToClient(&pt); + + OnMouseMove(nFlags, pt); + + return FALSE; + } + + LRESULT OnToolTipEvent(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + if(m_wndToolTip.IsWindow()) + { + MSG msg = { m_hWnd, uMsg, wParam, lParam }; + + m_wndToolTip.RelayEvent(&msg); + } + + SetMsgHandled(FALSE); + + return 0; + } + + void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) + { + + } + +protected: + + BEGIN_MSG_MAP_EX(CBkListViewImpl) + MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnToolTipEvent) + MSG_WM_ERASEBKGND(OnEraseBkgnd) + MSG_WM_MOUSEMOVE(OnMouseMove) + MSG_WM_MOUSELEAVE(OnMouseLeave) + MSG_WM_MOUSEWHEEL(OnMouseWheel) + MSG_WM_LBUTTONDOWN(OnLButtonDown) + MSG_WM_LBUTTONUP(OnLButtonUp) + MSG_WM_LBUTTONDBLCLK(OnLButtonDown) + MSG_WM_SIZE(OnSize) + MSG_WM_NCCALCSIZE(OnNcCalcSize) + MSG_WM_SETCURSOR(OnSetCursor) + MSG_WM_KEYDOWN(OnKeyDown) + CHAIN_MSG_MAP_ALT(CCustomDraw, 1) + DEFAULT_REFLECTION_HANDLER() + END_MSG_MAP() +}; + +class CBkListView : public CBkListViewImpl +{ +}; diff --git a/Client/Client/GUI/BKWin/bkwin/bkobject.h b/Client/Client/GUI/BKWin/bkwin/bkobject.h new file mode 100644 index 00000000..ae66dbb3 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkobject.h @@ -0,0 +1,260 @@ +////////////////////////////////////////////////////////////////////////// +// File Name: BkObject.h +// Description: BkObject Definition +// Creator: Zhang Xiaoxuan +// Version: 2009.04.28 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#if !defined(TINYXML_INCLUDED) + #error Please include tinyxml.h first! +#endif + +#include "../bkres/bkfontpool.h" +#include "../bkres/bkresutil.h" + +////////////////////////////////////////////////////////////////////////// + +// BkObject Class Name Declaration +#define BKOBJ_DECLARE_CLASS_NAME(theclass, classname) \ +public: \ + static theclass* CheckAndNew(LPCSTR lpszName) \ + { \ + if (strcmp(GetClassName(), lpszName) == 0) \ + return new theclass; \ + else \ + return NULL; \ + } \ + \ + static LPCSTR GetClassName() \ + { \ + return classname; \ + } \ + \ + virtual LPCSTR GetObjectClass() \ + { \ + return classname; \ + } \ + \ + virtual BOOL IsClass(LPCSTR lpszName) \ + { \ + return strcmp(GetClassName(), lpszName) == 0; \ + } \ + +////////////////////////////////////////////////////////////////////////// +// Xml Attributes Declaration Map + +// Attribute Declaration +#define BKWIN_DECLARE_ATTRIBUTES_BEGIN() \ +public: \ + virtual HRESULT SetAttribute( \ + CStringA strAttribName, \ + CStringA strValue, \ + BOOL bLoading) \ + { \ + HRESULT hRet = __super::SetAttribute( \ + strAttribName, \ + strValue, \ + bLoading \ + ); \ + if (SUCCEEDED(hRet)) \ + return hRet; \ + +#define BKWIN_DECLARE_ATTRIBUTES_END() \ + return E_FAIL; \ + \ + return hRet; \ + } \ + +#define BKWIN_CHAIN_ATTRIBUTE(varname, allredraw) \ + if (SUCCEEDED(hRet = varname.SetAttribute(strAttribName, strValue, bLoading))) \ + { \ + return hRet; \ + } \ + else \ + +// Custom Attribute +// HRESULT OnAttributeChange(CStringA& strValue, BOOL bLoading) +#define BKWIN_CUSTOM_ATTRIBUTE(attribname, func) \ + if (attribname == strAttribName) \ + { \ + hRet = func(strValue, bLoading); \ + } \ + else \ + +// Int = %d StringA +#define BKWIN_INT_ATTRIBUTE(attribname, varname, allredraw) \ + if (attribname == strAttribName) \ + { \ + varname = ::StrToIntA(strValue); \ + hRet = allredraw ? S_OK : S_FALSE; \ + } \ + else \ + +// UInt = %u StringA +#define BKWIN_UINT_ATTRIBUTE(attribname, varname, allredraw) \ + if (attribname == strAttribName) \ + { \ + varname = (UINT)::StrToIntA(strValue); \ + hRet = allredraw ? S_OK : S_FALSE; \ + } \ + else \ + +// DWORD = %u StringA +#define BKWIN_DWORD_ATTRIBUTE(attribname, varname, allredraw) \ + if (attribname == strAttribName) \ + { \ + varname = (DWORD)::StrToIntA(strValue); \ + hRet = allredraw ? S_OK : S_FALSE; \ + } \ + else \ + +// StringA = StringA +#define BKWIN_STRING_ATTRIBUTE(attribname, varname, allredraw) \ + if (attribname == strAttribName) \ + { \ + varname = strValue; \ + hRet = allredraw ? S_OK : S_FALSE; \ + } \ + else \ + +// StringT = StringA +#define BKWIN_TSTRING_ATTRIBUTE(attribname, varname, allredraw) \ + if (attribname == strAttribName) \ + { \ + varname = CA2T(strValue, CP_UTF8); \ + hRet = allredraw ? S_OK : S_FALSE; \ + } \ + else \ + +// DWORD = %X StringA +#define BKWIN_HEX_ATTRIBUTE(attribname, varname, allredraw) \ + if (attribname == strAttribName) \ + { \ + varname = CBkObject::HexStringToULong(strValue); \ + hRet = allredraw ? S_OK : S_FALSE; \ + } \ + else \ + +// COLORREF = %08X StringA +#define BKWIN_COLOR_ATTRIBUTE(attribname, varname, allredraw) \ + if (attribname == strAttribName) \ + { \ + varname = CBkObject::HexStringToColor(strValue); \ + hRet = allredraw ? S_OK : S_FALSE; \ + } \ + else \ + +// HFONT = %04X StringA +#define BKWIN_FONT_ATTRIBUTE(attribname, varname, allredraw) \ + if (attribname == strAttribName) \ + { \ + DWORD dwValue = CBkObject::HexStringToULong(strValue); \ + varname = BkFontPool::GetFont(LOWORD(dwValue)); \ + hRet = allredraw ? S_OK : S_FALSE; \ + } \ + else \ + +// Value In {String1 : Value1, String2 : Value2 ...} +#define BKWIN_ENUM_ATTRIBUTE(attribname, vartype, allredraw) \ + if (attribname == strAttribName) \ + { \ + vartype varTemp; \ + \ + hRet = allredraw ? S_OK : S_FALSE; \ + +#define BKWIN_ENUM_VALUE(enumstring, enumvalue) \ + if (strValue == enumstring) \ + varTemp = enumvalue; \ + else \ + +#define BKWIN_ENUM_END(varname) \ + return E_FAIL; \ + \ + varname = varTemp; \ + } \ + else \ + +// BkStyle From StringA Key +#define BKWIN_STYLE_ATTRIBUTE(attribname, varname, allredraw) \ + if (attribname == strAttribName) \ + { \ + varname = BkStyle::GetStyle(strValue); \ + hRet = allredraw ? S_OK : S_FALSE; \ + } \ + else \ + +// BkSkin From StringA Key +#define BKWIN_SKIN_ATTRIBUTE(attribname, varname, allredraw) \ + if (attribname == strAttribName) \ + { \ + varname = BkSkin::GetSkin(strValue); \ + hRet = allredraw ? S_OK : S_FALSE; \ + } \ + else \ + +class CBkObject +{ +public: + CBkObject() + { + } + + virtual ~CBkObject() + { + } + + virtual BOOL IsClass(LPCSTR lpszName) = 0; + virtual LPCSTR GetObjectClass() = 0; + + virtual BOOL Load(TiXmlElement* pXmlElem) + { + for (TiXmlAttribute *pAttrib = pXmlElem->FirstAttribute(); NULL != pAttrib; pAttrib = pAttrib->Next()) + { + SetAttribute(pAttrib->Name(), pAttrib->Value(), TRUE); + } + + return TRUE; + } + + virtual HRESULT SetAttribute(CStringA strAttribName, CStringA strValue, BOOL bLoading) + { + return E_FAIL; + } + +protected: + static ULONG HexStringToULong(LPCSTR lpszValue, int nSize = -1) + { + LPCSTR pchValue = lpszValue; + ULONG ulValue = 0; + + while (*pchValue && nSize != 0) + { + ulValue <<= 4; + + if ('a' <= *pchValue && 'f' >= *pchValue) + ulValue |= (*pchValue - 'a' + 10); + else if ('A' <= *pchValue && 'F' >= *pchValue) + ulValue |= (*pchValue - 'A' + 10); + else if ('0' <= *pchValue && '9' >= *pchValue) + ulValue |= (*pchValue - '0'); + else + return 0; + + ++ pchValue; + -- nSize; + } + + return ulValue; + } + + static COLORREF HexStringToColor(LPCSTR lpszValue) + { + return RGB( + HexStringToULong(lpszValue, 2), + HexStringToULong(lpszValue + 2, 2), + HexStringToULong(lpszValue + 4, 2) + ); + } +}; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkwin/bkskin.h b/Client/Client/GUI/BKWin/bkwin/bkskin.h new file mode 100644 index 00000000..8a44be5b --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkskin.h @@ -0,0 +1,847 @@ +////////////////////////////////////////////////////////////////////////// +// File Name: BkSkin +// Description: BkWindow Skin Definition +// Creator: ZhangXiaoxuan +// Version: 2009.4.22 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "bkobject.h" +#include "bkimage.h" +#include "../bkres/bkpngpool.h" + +// State Define +enum { + BkWndState_Normal = 0x00000000UL, + BkWndState_Hover = 0x00000001UL, + BkWndState_PushDown = 0x00000002UL, + BkWndState_Check = 0x00000004UL, + BkWndState_Invisible = 0x00000008UL, + BkWndState_Disable = 0x00000010UL, +}; + +#define IIF_STATE2(the_state, normal_value, hover_value) \ + (((the_state) & BkWndState_Hover) ? (hover_value) : (normal_value)) + +#define IIF_STATE3(the_state, normal_value, hover_value, pushdown_value) \ + (((the_state) & BkWndState_PushDown) ? (pushdown_value) : IIF_STATE2(the_state, normal_value, hover_value)) + +#define IIF_STATE4(the_state, normal_value, hover_value, pushdown_value, disable_value) \ + (((the_state) & BkWndState_Disable) ? (disable_value) : IIF_STATE3(the_state, normal_value, hover_value, pushdown_value)) + +class CBkSkinBase : public CBkObject +{ +public: + virtual void Draw(CDCHandle dc, CRect rcDraw, DWORD dwState) = NULL; + + virtual SIZE GetSkinSize() + { + SIZE ret = {0, 0}; + + return ret; + } + + virtual BOOL IgnoreState() + { + return TRUE; + } + + enum { + Frame_Part_All = 0x0000002FUL, + Frame_Part_Top = 0x00000001UL, + Frame_Part_Middle = 0x00000002UL, + Frame_Part_Bottom = 0x00000004UL, + Frame_Part_Left = 0x00000008UL, + Frame_Part_Center = 0x00000010UL, + Frame_Part_Right = 0x00000020UL, + }; + + static void HorzExtendDraw(CDCHandle &dc, CBkImage &imgDraw, CRect &rcDraw, LONG lSkinLeft, int nSubImage = -1) + { + SIZE sizeSkin; + + imgDraw.GetImageSize(sizeSkin); + + if (sizeSkin.cx > rcDraw.Width()) + rcDraw.right = rcDraw.left + sizeSkin.cx; + + if (imgDraw.GetSubImageWidth() > 0) + { + sizeSkin.cx = imgDraw.GetSubImageWidth(); + } + + imgDraw.BitBlt( + dc, + rcDraw.left, rcDraw.top, + lSkinLeft, sizeSkin.cy, + 0, 0, + SRCCOPY, nSubImage + ); + imgDraw.BitBlt( + dc, + rcDraw.right - sizeSkin.cx + lSkinLeft + 1, rcDraw.top, + sizeSkin.cx - lSkinLeft - 1, sizeSkin.cy, + lSkinLeft + 1, 0, + SRCCOPY, nSubImage + ); + imgDraw.StretchBlt( + dc, + rcDraw.left + lSkinLeft, rcDraw.top, + rcDraw.Width() - sizeSkin.cx + 1, sizeSkin.cy, + lSkinLeft, 0, + 1, sizeSkin.cy, + SRCCOPY, nSubImage + ); + } + + static void FrameDraw(CDCHandle &dc, CBkImage &imgDraw, CRect &rcDraw, LONG lSkinLeft, LONG lSkinTop, COLORREF crBg, UINT uDrawPart = Frame_Part_All) + { + SIZE sizeSkin; + CRect rcClient = rcDraw; + + ATLASSERT(dc.m_hDC); + ATLASSERT(imgDraw.m_hBitmap); + ATLASSERT(rcDraw.Width() && rcDraw.Height()); + + imgDraw.GetImageSize(sizeSkin); + + rcClient.DeflateRect( + (uDrawPart & Frame_Part_Left) ? lSkinLeft : 0, + (uDrawPart & Frame_Part_Top) ? lSkinTop : 0, + (uDrawPart & Frame_Part_Right) ? (sizeSkin.cx - lSkinLeft - 1) : 0, + (uDrawPart & Frame_Part_Bottom) ? (sizeSkin.cy - lSkinTop - 1) : 0 + ); + + if ((Frame_Part_Left | Frame_Part_Top) == (uDrawPart & (Frame_Part_Left | Frame_Part_Top))) + { + imgDraw.BitBlt( + dc, + rcDraw.left, rcDraw.top, + lSkinLeft, lSkinTop, + 0, 0, + SRCCOPY + ); + } + if ((Frame_Part_Right | Frame_Part_Top) == (uDrawPart & (Frame_Part_Right | Frame_Part_Top))) + { + imgDraw.BitBlt( + dc, + rcClient.right, rcDraw.top, + sizeSkin.cx - lSkinLeft - 1, lSkinTop, + lSkinLeft + 1, 0, + SRCCOPY + ); + } + if ((Frame_Part_Left | Frame_Part_Bottom) == (uDrawPart & (Frame_Part_Left | Frame_Part_Bottom))) + { + imgDraw.BitBlt( + dc, + rcDraw.left, rcClient.bottom, + lSkinLeft, lSkinTop, + 0, lSkinTop + 1, + SRCCOPY + ); + } + if ((Frame_Part_Right | Frame_Part_Bottom) == (uDrawPart & (Frame_Part_Right | Frame_Part_Bottom))) + { + imgDraw.BitBlt( + dc, + rcClient.right, rcClient.bottom, + sizeSkin.cx - lSkinLeft - 1, lSkinTop, + lSkinLeft + 1, lSkinTop + 1, + SRCCOPY + ); + } + if (Frame_Part_Top == (uDrawPart & Frame_Part_Top)) + { + imgDraw.StretchBlt( + dc, + rcClient.left, rcDraw.top, + rcClient.Width(), lSkinTop, + lSkinLeft, 0, + 1, lSkinTop, + SRCCOPY + ); + } + if (Frame_Part_Left == (uDrawPart & Frame_Part_Left)) + { + imgDraw.StretchBlt( + dc, + rcDraw.left, rcClient.top, + lSkinLeft, rcClient.Height(), + 0, lSkinTop, + lSkinLeft, 1, + SRCCOPY + ); + } + if (Frame_Part_Bottom == (uDrawPart & Frame_Part_Bottom)) + { + imgDraw.StretchBlt( + dc, + rcClient.left, rcDraw.bottom - sizeSkin.cy + lSkinTop + 1, + rcClient.Width(), sizeSkin.cy - lSkinTop - 1, + lSkinLeft, lSkinTop + 1, + 1, sizeSkin.cy - lSkinTop - 1, + SRCCOPY + ); + } + if (Frame_Part_Right == (uDrawPart & Frame_Part_Right)) + { + imgDraw.StretchBlt( + dc, + rcClient.right, rcClient.top, + sizeSkin.cx - lSkinLeft - 1, rcClient.Height(), + lSkinLeft + 1, lSkinTop, + sizeSkin.cx - lSkinLeft - 1, 1, + SRCCOPY + ); + } + + if (CLR_INVALID != crBg) + dc.FillSolidRect(rcClient, crBg); + } + + typedef struct _FRG_PARAM + { + LONG lOffset; + COLORREF crColor; + } FRG_PARAM; + + typedef BOOL (WINAPI * FnGradientFill)(HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG); + + static BOOL WINAPI GradientFill2(HDC hDC, PTRIVERTEX pVertices, DWORD nVertices, PVOID pMeshElements, ULONG nMeshElements, ULONG dwMode) + { + HMODULE hMod = ::LoadLibrary(_T("msimg32.dll")); + if (hMod) + { + FnGradientFill pfnGradientFill = (FnGradientFill)::GetProcAddress(hMod, "GradientFill"); + if (pfnGradientFill) + pfnGradientFill(hDC, pVertices, nVertices, pMeshElements, nMeshElements, dwMode); + ::FreeLibrary(hMod); + } + + return TRUE; + } + + static void GradientFillRectV(HDC hdc, CRect &rcFill, FRG_PARAM params[], int nCount) + { + GRADIENT_RECT gRect = {0, 1}; + TRIVERTEX vert[2] = { + {rcFill.left, rcFill.top, 0, 0, 0, 0}, + {rcFill.right, rcFill.top, 0, 0, 0, 0} + }; + int i = 0; + + for (i = 1; i < nCount && vert[0].y <= rcFill.bottom; i ++) + { + vert[0].y = vert[1].y; + vert[1].y += params[i].lOffset; + vert[0].Red = GetRValue(params[i - 1].crColor) << 8; + vert[0].Green = GetGValue(params[i - 1].crColor) << 8; + vert[0].Blue = GetBValue(params[i - 1].crColor) << 8; + vert[1].Red = GetRValue(params[i].crColor) << 8; + vert[1].Green = GetGValue(params[i].crColor) << 8; + vert[1].Blue = GetBValue(params[i].crColor) << 8; + + HMODULE hMod = ::LoadLibrary(_T("msimg32.dll")); + if (hMod) + { + GradientFill2(hdc, vert, 2, &gRect, 1, GRADIENT_FILL_RECT_V); + } + } + } + + static void GradientFillRectH(HDC hdc, CRect &rcFill, FRG_PARAM params[], int nCount) + { + GRADIENT_RECT gRect = {0, 1}; + TRIVERTEX vert[2] = { + {rcFill.left, rcFill.top, 0, 0, 0, 0}, + {rcFill.left, rcFill.bottom, 0, 0, 0, 0} + }; + int i = 0; + + for (i = 1; i < nCount && vert[0].x <= rcFill.right; i ++) + { + vert[0].x = vert[1].x; + vert[1].x += params[i].lOffset; + vert[0].Red = GetRValue(params[i - 1].crColor) << 8; + vert[0].Green = GetGValue(params[i - 1].crColor) << 8; + vert[0].Blue = GetBValue(params[i - 1].crColor) << 8; + vert[1].Red = GetRValue(params[i].crColor) << 8; + vert[1].Green = GetGValue(params[i].crColor) << 8; + vert[1].Blue = GetBValue(params[i].crColor) << 8; + GradientFill2(hdc, vert, 2, &gRect, 1, GRADIENT_FILL_RECT_H); + } + } + + static void GradientFillRectV(HDC hdc, CRect &rcFill, COLORREF crTop, COLORREF crBottom) + { + FRG_PARAM frgDraw[2] = { + {0, crTop}, + {rcFill.Height(), crBottom}, + }; + + GradientFillRectV(hdc, rcFill, frgDraw, 2); + } + + static void GradientFillRectH(HDC hdc, CRect &rcFill, COLORREF crLeft, COLORREF crRight) + { + FRG_PARAM frgDraw[2] = { + {0, crLeft}, + {rcFill.Width(), crRight}, + }; + + GradientFillRectH(hdc, rcFill, frgDraw, 2); + } +}; + +class CBkImageSkin + : public CBkImage + , public CBkSkinBase +{ + BKOBJ_DECLARE_CLASS_NAME(CBkImageSkin, "imglst") + +public: + CBkImageSkin() + { + + } + + virtual void Draw(CDCHandle dc, CRect rcDraw, DWORD dwState) + { + CBkImage::Draw(dc, rcDraw.left, rcDraw.top, dwState); + } + + virtual SIZE GetSkinSize() + { + SIZE ret = {0, 0}; + + GetImageSize(ret); + + if (0 != m_lSubImageWidth) + ret.cx = m_lSubImageWidth; + + return ret; + } + + virtual BOOL IgnoreState() + { + return (0 == m_lSubImageWidth); + } + +protected: + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_UINT_ATTRIBUTE("src", *(CBkImage *)(this), TRUE) + BKWIN_ENUM_ATTRIBUTE("mode", int, TRUE) + BKWIN_ENUM_VALUE("none", CBkImage::ModeNone) + BKWIN_ENUM_VALUE("mask", CBkImage::ModeMaskColor) + BKWIN_ENUM_VALUE("alpha", CBkImage::ModeAlpha) + BKWIN_ENUM_END(m_nTransparentMode) + BKWIN_COLOR_ATTRIBUTE("maskcolor", m_crMask, TRUE) + BKWIN_INT_ATTRIBUTE("subwidth", m_lSubImageWidth, TRUE) + BKWIN_DECLARE_ATTRIBUTES_END() +}; + +class CBkSkinImgFrame : public CBkSkinBase +{ + BKOBJ_DECLARE_CLASS_NAME(CBkSkinImgFrame, "imgframe") + +public: + CBkSkinImgFrame() + : m_crBg(CLR_INVALID) + , m_lSkinParamLeft(0) + , m_lSkinParamTop(0) + , m_uDrawPart(Frame_Part_All) + { + } + + virtual void Draw(CDCHandle dc, CRect rcDraw, DWORD dwState) + { + if (m_imgSkin.M_HOBJECT) + { + FrameDraw(dc, m_imgSkin, rcDraw, m_lSkinParamLeft, m_lSkinParamTop, m_crBg, m_uDrawPart); + } + } + + virtual BOOL IgnoreState() + { + return m_imgSkin.IgnoreState(); + } + +protected: + CBkImageSkin m_imgSkin; + LONG m_lSkinParamLeft; + LONG m_lSkinParamTop; + COLORREF m_crBg; + UINT m_uDrawPart; + +public: + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_CHAIN_ATTRIBUTE(m_imgSkin, TRUE) +// BKWIN_UINT_ATTRIBUTE("src", m_imgSkin, TRUE) + BKWIN_COLOR_ATTRIBUTE("crbg", m_crBg, TRUE) + BKWIN_INT_ATTRIBUTE("left", m_lSkinParamLeft, TRUE) + BKWIN_INT_ATTRIBUTE("top", m_lSkinParamTop, TRUE) + BKWIN_ENUM_ATTRIBUTE("part", UINT, TRUE) + BKWIN_ENUM_VALUE("all", Frame_Part_All) + BKWIN_ENUM_VALUE("top", (Frame_Part_All & ~Frame_Part_Bottom)) + BKWIN_ENUM_VALUE("middle", (Frame_Part_All & ~(Frame_Part_Bottom | Frame_Part_Top))) + BKWIN_ENUM_VALUE("bottom", (Frame_Part_All & ~Frame_Part_Top)) + BKWIN_ENUM_VALUE("left", (Frame_Part_All & ~Frame_Part_Right)) + BKWIN_ENUM_VALUE("center", (Frame_Part_All & ~(Frame_Part_Right | Frame_Part_Left))) + BKWIN_ENUM_VALUE("right", (Frame_Part_All & ~Frame_Part_Left)) + BKWIN_ENUM_END(m_uDrawPart) + BKWIN_DECLARE_ATTRIBUTES_END() + +private: +}; + +class CBkSkinImgHorzExtend : public CBkSkinBase +{ + BKOBJ_DECLARE_CLASS_NAME(CBkSkinImgHorzExtend, "imghorzex") +public: + CBkSkinImgHorzExtend() + : /* + m_lSkinSubWidth(0) + , */ + m_lSkinParamLeft(0) + { + } + + virtual void Draw(CDCHandle dc, CRect rcDraw, DWORD dwState) + { + if (m_imgSkin.M_HOBJECT) + { +// m_imgSkin.SetSubImageWidth(m_lSkinSubWidth); + HorzExtendDraw( + dc, m_imgSkin, rcDraw, m_lSkinParamLeft, + (-1 == dwState) ? -1 : IIF_STATE4(dwState, 0, 1, 2, 3) +// (dwState & BkWndState_PushDown) ? 2 : ((dwState & BkWndState_Hover) ? 1 : 0) + ); + } + } + + SIZE GetSkinSize() + { + SIZE size; + + m_imgSkin.GetImageSize(size); + +// LONG lSubImageWidth = m_imgSkin.GetSubImageWidth(); +// if (lSubImageWidth > 0) +// size.cx = lSubImageWidth; + + size.cx = 0; + + return size; + } + + virtual BOOL IgnoreState() + { + return m_imgSkin.IgnoreState(); + } + +protected: + CBkImageSkin m_imgSkin; +// LONG m_lSkinSubWidth; + LONG m_lSkinParamLeft; + +public: + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_CHAIN_ATTRIBUTE(m_imgSkin, TRUE) +// BKWIN_UINT_ATTRIBUTE("src", m_imgSkin, TRUE) +// BKWIN_INT_ATTRIBUTE("subwidth", m_lSkinSubWidth, TRUE) + BKWIN_INT_ATTRIBUTE("left", m_lSkinParamLeft, TRUE) + BKWIN_DECLARE_ATTRIBUTES_END() + +private: +}; + +class CBkSkinButton : public CBkSkinBase +{ + BKOBJ_DECLARE_CLASS_NAME(CBkSkinButton, "button") +public: + CBkSkinButton() + : m_crBorder(RGB(0x70, 0x70, 0x70)) + , m_crBg(RGB(0xEE, 0xEE, 0xEE)) + , m_crBgUpNormal(RGB(0xEE, 0xEE, 0xEE)) + , m_crBgUpHover(RGB(0xEE, 0xEE, 0xEE)) + , m_crBgUpPush(RGB(0xCE, 0xCE, 0xCE)) + , m_crBgDownNormal(RGB(0xD6, 0xD6, 0xD6)) + , m_crBgDownHover(RGB(0xE0, 0xE0, 0xE0)) + , m_crBgDownPush(RGB(0xC0, 0xC0, 0xC0)) + { + + } + + virtual void Draw(CDCHandle dc, CRect rcDraw, DWORD dwState) + { + CPen penFrame; + CRect rcBg = rcDraw; + + dc.FillSolidRect(rcDraw, m_crBg); + + rcBg.DeflateRect(2, 2); + + if (BkWndState_Disable == (BkWndState_Disable & dwState)) + { + + } + else + GradientFillRectV( + dc, rcBg, + IIF_STATE3(dwState, m_crBgUpNormal, m_crBgUpHover, m_crBgUpPush), + IIF_STATE3(dwState, m_crBgDownNormal, m_crBgDownHover, m_crBgDownPush)); + +// rcBg.DeflateRect(2, 2, 2, rcDraw.Height() / 2); +// dc.FillSolidRect( +// rcBg, +// IIF_STATE3(dwState, m_crBgUpNormal, m_crBgUpHover, m_crBgUpPush) +// ); +// +// rcBg.OffsetRect(0, rcBg.Height()); +// dc.FillSolidRect( +// rcBg, +// IIF_STATE3(dwState, m_crBgDownNormal, m_crBgDownHover, m_crBgDownPush) +// ); + + penFrame.CreatePen( + PS_SOLID, + 1, + m_crBorder + ); + + HPEN hpenOld = dc.SelectPen(penFrame); + HBRUSH hbshOld = NULL, hbshNull = (HBRUSH)::GetStockObject(NULL_BRUSH); + + hbshOld = dc.SelectBrush(hbshNull); + + dc.Rectangle(rcDraw); + + //dc.RoundRect(rcDraw, CPoint(2, 2)); + +// if (dwState & BkWndState_PushDown) +// { +// rcDraw.DeflateRect(1, 1, 0, 0); +// +// dc.Rectangle(rcDraw); +// } + + dc.SelectBrush(hbshOld); + dc.SelectPen(hpenOld); + } + + virtual BOOL IgnoreState() + { + return FALSE; + } + +protected: + + COLORREF m_crBg; + COLORREF m_crBorder; + COLORREF m_crBgUpNormal; + COLORREF m_crBgUpHover; + COLORREF m_crBgUpPush; + COLORREF m_crBgDownNormal; + COLORREF m_crBgDownHover; + COLORREF m_crBgDownPush; + +public: + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_COLOR_ATTRIBUTE("bg", m_crBg, TRUE) + BKWIN_COLOR_ATTRIBUTE("border", m_crBorder, TRUE) + BKWIN_COLOR_ATTRIBUTE("bgup", m_crBgUpNormal, TRUE) + BKWIN_COLOR_ATTRIBUTE("bguphover", m_crBgUpHover, TRUE) + BKWIN_COLOR_ATTRIBUTE("bguppush", m_crBgUpPush, TRUE) + BKWIN_COLOR_ATTRIBUTE("bgdown", m_crBgDownNormal, TRUE) + BKWIN_COLOR_ATTRIBUTE("bgdownhover", m_crBgDownHover, TRUE) + BKWIN_COLOR_ATTRIBUTE("bgdownpush", m_crBgDownPush, TRUE) + BKWIN_DECLARE_ATTRIBUTES_END() +}; + +class CBkSkinGradation + : public CBkSkinBase +{ + BKOBJ_DECLARE_CLASS_NAME(CBkSkinGradation, "gradation") +public: + CBkSkinGradation() + : m_uDirection(0) + , m_crFrom(CLR_INVALID) + , m_crTo(CLR_INVALID) + , m_nSize(0) + { + } + + virtual void Draw(CDCHandle dc, CRect rcDraw, DWORD dwState) + { + CRect rcGradation = rcDraw; + CRgn rgnDraw; + + rgnDraw.CreateRectRgn(rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom); + + dc.FillSolidRect(rcDraw, m_crTo); + + int nID = dc.SaveDC(); + + dc.SelectClipRgn(rgnDraw); + + if (0 == m_uDirection) + { + if (0 < m_nSize) + rcGradation.right = rcGradation.left + m_nSize; + GradientFillRectH(dc, rcGradation, m_crFrom, m_crTo); + } + else + { + if (0 < m_nSize) + rcGradation.bottom = rcGradation.top + m_nSize; + GradientFillRectV(dc, rcGradation, m_crFrom, m_crTo); + } + + dc.RestoreDC(nID); + } + +protected: + COLORREF m_crFrom; + COLORREF m_crTo; + UINT m_uDirection; + int m_nSize; +public: + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_COLOR_ATTRIBUTE("from", m_crFrom, TRUE) + BKWIN_COLOR_ATTRIBUTE("to", m_crTo, TRUE) + BKWIN_INT_ATTRIBUTE("size", m_nSize, TRUE) + BKWIN_ENUM_ATTRIBUTE("direction", UINT, TRUE) + BKWIN_ENUM_VALUE("horz", 0) + BKWIN_ENUM_VALUE("vert", 1) + BKWIN_ENUM_END(m_uDirection) + BKWIN_DECLARE_ATTRIBUTES_END() + +private: +}; + +class CBkPngSkin + : public CBkSkinBase +{ + BKOBJ_DECLARE_CLASS_NAME(CBkPngSkin, "png") + +public: + CBkPngSkin() + : m_uResID(0) + , m_lSubImageWidth(0) + , m_pImg(NULL) + { + } + + ~CBkPngSkin() + { + } + + virtual BOOL Load(TiXmlElement* pXmlElem) + { + __super::Load(pXmlElem); + + if (0 == m_uResID) + return TRUE; + + m_pImg = BkPngPool::Get(m_uResID); + + return TRUE; + } + + virtual void Draw(CDCHandle dc, CRect rcDraw, DWORD dwState) + { + if (m_pImg) + { + Gdiplus::Graphics graphics(dc); + + SIZE size = {0, 0}; + if (m_pImg) + { + if (0 == m_lSubImageWidth) + size.cx = m_pImg->GetWidth(); + else + size.cx = m_lSubImageWidth; + size.cy = m_pImg->GetHeight(); + } + + if (0 == m_lSubImageWidth) + graphics.DrawImage(m_pImg, Gdiplus::Rect(rcDraw.left, rcDraw.top, size.cx, size.cy)); + else + graphics.DrawImage(m_pImg, Gdiplus::Rect(rcDraw.left, rcDraw.top, size.cx, size.cy), m_lSubImageWidth * dwState, 0, size.cx, size.cy, Gdiplus::UnitPixel); + } + } + + virtual SIZE GetSkinSize() + { + SIZE ret = {0, 0}; + if (m_pImg) + { + if (0 == m_lSubImageWidth) + ret.cx = m_pImg->GetWidth(); + else + ret.cx = m_lSubImageWidth; + ret.cy = m_pImg->GetHeight(); + } + + return ret; + } + + virtual BOOL IgnoreState() + { + return 0 == m_lSubImageWidth; + } + +protected: + + Gdiplus::Image* m_pImg; + UINT m_uResID; + LONG m_lSubImageWidth; + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_UINT_ATTRIBUTE("src", m_uResID, TRUE) + BKWIN_INT_ATTRIBUTE("subwidth", m_lSubImageWidth, TRUE) + BKWIN_DECLARE_ATTRIBUTES_END() +}; + +class BkSkin +{ +public: + BkSkin() + { + } + + ~BkSkin() + { + _Clear(); + } + + static BOOL LoadSkins(UINT uResID) + { + CStringA strXml; + BOOL bRet = BkResManager::LoadResource(uResID, strXml); + + if (!bRet) + return FALSE; + + return LoadSkins(strXml); + } + + static BOOL LoadSkins(LPCSTR lpszXml) + { + TiXmlDocument xmlDoc; + + _Instance()._Clear(); + + xmlDoc.Parse(lpszXml, NULL, TIXML_ENCODING_UTF8); + + if (xmlDoc.Error()) + return FALSE; + + _Instance()._LoadSkins(xmlDoc.RootElement()); + + return TRUE; + } + + static CBkSkinBase* GetSkin(LPCSTR lpszSkinName) + { + __BkSkinPool::CPair *pairRet = _Instance().m_mapPool.Lookup(lpszSkinName); + + if (pairRet) + return pairRet->m_value; + else + return NULL; + } + + static size_t GetCount() + { + return _Instance().m_mapPool.GetCount(); + } + +protected: + + typedef CAtlMap __BkSkinPool; + + static BkSkin& _Instance() + { + static BkSkin s_obj; + + return s_obj; + } + + __BkSkinPool m_mapPool; + + void _Clear() + { + POSITION pos = m_mapPool.GetStartPosition(); + + while (pos) + { + CBkSkinBase *pSkin = m_mapPool.GetNextValue(pos); + delete pSkin; + } + + m_mapPool.RemoveAll(); + } + + void _LoadSkins(TiXmlElement *pXmlSkinRootElem) + { + LPCSTR lpszSkinName = NULL, lpszTypeName = NULL; + + if (!pXmlSkinRootElem) + return; + + if (strcmp(pXmlSkinRootElem->Value(), "skins") != 0) + return; + + for (TiXmlElement* pXmlChild = pXmlSkinRootElem->FirstChildElement(); NULL != pXmlChild; pXmlChild = pXmlChild->NextSiblingElement()) + { + lpszSkinName = pXmlChild->Attribute("name"); + lpszTypeName = pXmlChild->Value(); + if (!lpszSkinName || !lpszTypeName) + continue; + + CBkSkinBase *pSkin = _CreateBkSkinByName(lpszTypeName); + if (!pSkin) + continue; + + pSkin->Load(pXmlChild); + + m_mapPool[lpszSkinName] = pSkin; + } + } + + static CBkSkinBase* _CreateBkSkinByName(LPCSTR lpszName) + { + CBkSkinBase *pNewSkin = NULL; + + pNewSkin = CBkImageSkin::CheckAndNew(lpszName); + if (pNewSkin) + return pNewSkin; + + pNewSkin = CBkSkinImgFrame::CheckAndNew(lpszName); + if (pNewSkin) + return pNewSkin; + + pNewSkin = CBkSkinButton::CheckAndNew(lpszName); + if (pNewSkin) + return pNewSkin; + + pNewSkin = CBkSkinImgHorzExtend::CheckAndNew(lpszName); + if (pNewSkin) + return pNewSkin; + + pNewSkin = CBkSkinGradation::CheckAndNew(lpszName); + if (pNewSkin) + return pNewSkin; + + pNewSkin = CBkPngSkin::CheckAndNew(lpszName); + if (pNewSkin) + return pNewSkin; + + return NULL; + } +}; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkwin/bktheme.h b/Client/Client/GUI/BKWin/bkwin/bktheme.h new file mode 100644 index 00000000..29dc05d9 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bktheme.h @@ -0,0 +1,172 @@ +////////////////////////////////////////////////////////////////////////// +// Class Name: BkTheme +// Description: Windows Theme(XP later) +// Creator: ZhangXiaoxuan +// Version: 2009.5.12 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include "tmschema.h" + +class BkWinThemeFunc +{ + typedef HTHEME (WINAPI *FnOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); + typedef HRESULT (WINAPI *FnCloseThemeData)(HTHEME hTheme); + typedef HRESULT (WINAPI *FnDrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); + typedef HRESULT (WINAPI *FnSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList); + +public: + BkWinThemeFunc() + : m_bThemeValid(FALSE) + , m_pfnOpenThemeData(NULL) + , m_pfnCloseThemeData(NULL) + , m_pfnDrawThemeBackground(NULL) + , m_pfnSetWindowTheme(NULL) + { + HMODULE hModTheme = ::GetModuleHandle(_T("uxtheme.dll")); + + if (!hModTheme) + return; + + m_bThemeValid = TRUE; + m_pfnOpenThemeData = (FnOpenThemeData)::GetProcAddress(hModTheme, "OpenThemeData"); + m_pfnCloseThemeData = (FnCloseThemeData)::GetProcAddress(hModTheme, "CloseThemeData"); + m_pfnDrawThemeBackground = (FnDrawThemeBackground)::GetProcAddress(hModTheme, "DrawThemeBackground"); + m_pfnSetWindowTheme = (FnSetWindowTheme)::GetProcAddress(hModTheme, "SetWindowTheme"); + } + + static BOOL IsValid() + { + return _Instance().m_bThemeValid; + } + + static HTHEME OpenThemeData(HWND hwnd, LPCWSTR pszClassList) + { + if (_Instance().m_pfnOpenThemeData) + { + return _Instance().m_pfnOpenThemeData(hwnd, pszClassList); + } + else + return NULL; + } + + static HRESULT CloseThemeData(HTHEME hTheme) + { + if (_Instance().m_pfnCloseThemeData) + { + return _Instance().m_pfnCloseThemeData(hTheme); + } + else + return E_NOTIMPL; + } + + static HRESULT DrawThemeBackground(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect) + { + if (_Instance().m_pfnDrawThemeBackground) + { + return _Instance().m_pfnDrawThemeBackground(hTheme, hdc, iPartId, iStateId, pRect, pClipRect); + } + else + return E_NOTIMPL; + } + + static HRESULT SetWindowTheme(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList) + { + if (_Instance().m_pfnSetWindowTheme) + { + return _Instance().m_pfnSetWindowTheme(hwnd, pszSubAppName, pszSubIdList); + } + else + return E_NOTIMPL; + } + + enum + { + BkThemeNameButton = 0, + BkThemeNameEnd, + }; + + static LPCWSTR ThemeName(int nID) + { + static const LPCWSTR Names[] = + { + L"BUTTON", + L"", + }; + + static int NamesCount = sizeof(Names) / sizeof(LPCWSTR) - 1; + + if (nID >= 0 && nID < NamesCount) + return Names[BkThemeNameButton]; + else + return NULL; + } + +private: + + BOOL m_bThemeValid; + + FnOpenThemeData m_pfnOpenThemeData; + FnCloseThemeData m_pfnCloseThemeData; + FnDrawThemeBackground m_pfnDrawThemeBackground; + FnSetWindowTheme m_pfnSetWindowTheme; + + + static BkWinThemeFunc& _Instance() + { + static BkWinThemeFunc s_obj; + return s_obj; + } +}; + +//__declspec(selectany) BkWinThemeFunc* BkWinThemeFunc::ms_pInstance = NULL; + +template +class CBkWinTheme +{ +public: + CBkWinTheme(HWND hWnd = NULL) + : m_hTheme(NULL) + { + if (hWnd) + OpenTheme(hWnd); + } + + ~CBkWinTheme() + { + BkWinThemeFunc::CloseThemeData(m_hTheme); + } + + BOOL IsValid() + { + return (NULL != m_hTheme); + } + + BOOL OpenTheme(HWND hWnd) + { + if (m_hTheme) + return FALSE; + + m_hTheme = BkWinThemeFunc::OpenThemeData(NULL, BkWinThemeFunc::ThemeName(t_nThemeId)); + + if (m_hTheme) + return TRUE; + + return FALSE; + } + + void DrawBackground(HDC hdc, int iStateId, const RECT *pRect) + { + BkWinThemeFunc::DrawThemeBackground(m_hTheme, hdc, t_partid, iStateId, pRect, NULL); + } + +protected: + + HTHEME m_hTheme; +}; + +typedef CBkWinTheme CBkCheckBoxTheme; +typedef CBkWinTheme CBkRadioBoxTheme; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkwin/bkwnd.h b/Client/Client/GUI/BKWin/bkwin/bkwnd.h new file mode 100644 index 00000000..be0674b4 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkwnd.h @@ -0,0 +1,1273 @@ +////////////////////////////////////////////////////////////////////////// +// File Name: BkWnd.h +// Description: BkWindow Definition +// Creator: Zhang Xiaoxuan +// Version: 2009.04.28 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "bkwndstyle.h" +#include "../bkres/bkstringpool.h" + +class CBkWindow; + +// by dummyz@126.com +class IBkWindowPaintHook +{ +public: + virtual BOOL NotifyPaint(CBkWindow* win, HDC hDC, const RECT& rcWin, BOOL bBeforePaint) = 0; +}; + +////////////////////////////////////////////////////////////////////////// + +// Not Used +#define BKWIN_DECLARE_RETURN_SETTING(before, after) \ +public: \ + virtual BOOL ReturnBeforeThisControl(void) \ + { \ + return before; \ + } \ + virtual BOOL ReturnAfterThisControl(void) \ + { \ + return after; \ + } \ + +////////////////////////////////////////////////////////////////////////// + +// BkWindow Message Map Define +// Use WTL Message Map Ex (include atlcrack.h) +#define BKWIN_BEGIN_MSG_MAP() \ +protected: \ + virtual BOOL ProcessWindowMessage( \ + HWND hWnd, UINT uMsg, WPARAM wParam, \ + LPARAM lParam, LRESULT& lResult) \ + { \ + +#define BKWIN_END_MSG_MAP() \ + if (!IsMsgHandled()) \ + return __super::ProcessWindowMessage( \ + hWnd, uMsg, wParam, lParam, lResult); \ + return TRUE; \ + } \ + +#define BKWIN_END_MSG_MAP_BASE() \ + return TRUE; \ + } \ + + +////////////////////////////////////////////////////////////////////////// +// CBkWindow Handle Manager +////////////////////////////////////////////////////////////////////////// + +class CBkWindow; + +// BkWindow Handle +typedef DWORD HBKWND; + +class BkWnds +{ +public: + + BkWnds() + : m_hNextWnd(NULL) + { + ::InitializeCriticalSection(&ms_lockWndMap); + } + + ~BkWnds() + { + ::DeleteCriticalSection(&ms_lockWndMap); + } + + // Get BkWindow pointer from handle + static CBkWindow* GetWindow(HBKWND hBkWnd) + { + ::EnterCriticalSection(&ms_lockWndMap); + + const _BkWndHandlePool::CPair *pairRet = _Instance().m_mapPool.Lookup(hBkWnd); + + ::LeaveCriticalSection(&ms_lockWndMap); + + if (pairRet) + { + return pairRet->m_value; + } + else + return NULL; + } + + // Get BkWindow pointer from command id + static CBkWindow* GetWindow(UINT uCmdID, HWND hWndInContainer = NULL); + + // Specify a handle to a BkWindow + static HBKWND NewWindow(CBkWindow *pBkWnd) + { + //static int s_n_new = 0; + //ATLTRACE(_T("NewWindow %d\r\n"), ++ s_n_new); + + if (pBkWnd) + { + _Instance(); // ﱣ֤Ψһʵɹٽδʼ + + ::EnterCriticalSection(&ms_lockWndMap); + + HBKWND hBkWndNext = ++ _Instance().m_hNextWnd; + _Instance().m_mapPool[hBkWndNext] = pBkWnd; + + ::LeaveCriticalSection(&ms_lockWndMap); + + return hBkWndNext; + } + else + return NULL; + } + + // Destroy BkWindow + static BOOL DestroyWindow(HBKWND hBkWnd) + { + //static int s_n_del = 0; + //ATLTRACE(_T("DestroyWindow %d\r\n"), ++ s_n_del); + + ::EnterCriticalSection(&ms_lockWndMap); + + BOOL bRet = (BOOL)_Instance().m_mapPool.RemoveKey(hBkWnd); + + ::LeaveCriticalSection(&ms_lockWndMap); + + return bRet; + } + + static size_t GetCount() + { + ::EnterCriticalSection(&ms_lockWndMap); + + size_t nRet = _Instance().m_mapPool.GetCount(); + + ::LeaveCriticalSection(&ms_lockWndMap); + + return nRet; + } + + static BOOL RegisterRadioGroup(CBkWindow *pbkWnd, LPCSTR lpszGroupName) + { + ::EnterCriticalSection(&ms_lockWndMap); + + POSITION pos = _Instance().m_mapRadioPool[lpszGroupName].AddTail(pbkWnd); + + ::LeaveCriticalSection(&ms_lockWndMap); + + return (NULL != pos); + } + + static void UnregisterRadioGroup(CBkWindow *pbkWnd, LPCSTR lpszGroupName) + { + ::EnterCriticalSection(&ms_lockWndMap); + + CAtlList &ListGroup = _Instance().m_mapRadioPool[lpszGroupName]; + + POSITION posCurrent = NULL, pos = ListGroup.GetHeadPosition(); + + while (pos) + { + posCurrent = pos; + + if (ListGroup.GetNext(pos) != pbkWnd) + continue; + + ListGroup.RemoveAt(posCurrent); + } + + ::LeaveCriticalSection(&ms_lockWndMap); + + } + + static void SelectRadio(CBkWindow* pbkWnd, LPCSTR lpszGroupName, CBkWindow **ppbkWndLastSelect); +// { +// CAtlList &ListGroup = _Instance().m_mapRadioPool[lpszGroupName]; +// +// pbkWnd->ModifyState(BkWndState_Check, 0); +// +// POSITION posCurrent = NULL, pos = ListGroup.GetHeadPosition(); +// +// while (pos) +// { +// posCurrent = pos; +// CBkWindow *pbkWndFind = ListGroup.GetNext(pos); +// +// if (pbkWndFind == pbkWnd) +// continue; +// +// if (pbkWndFind->IsChecked()) +// { +// pbkWndFind->ModifyState(0, BkWndState_Check); +// if (ppbkWndLastSelect) +// *ppbkWndLastSelect = pbkWndFind; +// } +// } +// } + +protected: + + static BkWnds ms_instance; + static CRITICAL_SECTION ms_lockWndMap; + + static BkWnds& _Instance() + { + return ms_instance; + } + +// static BkWnds& _Instance() +// { +// static BkWnds s_obj; +// return s_obj; +// } + + typedef CAtlMap _BkWndHandlePool; + typedef CAtlMap> _BkWndGroupPool; + + _BkWndHandlePool m_mapPool; + _BkWndGroupPool m_mapRadioPool; + HBKWND m_hNextWnd; +}; + +__declspec(selectany) BkWnds BkWnds::ms_instance; +__declspec(selectany) CRITICAL_SECTION BkWnds::ms_lockWndMap; + +////////////////////////////////////////////////////////////////////////// +// Inner Notify (BkWindows to Container) + +#define BKINM_FIRST 1000 +#define BKINM_LAST 1999 + +// Invalidate Rect Notify +#define BKINM_INVALIDATERECT BKINM_FIRST + +typedef struct _BKINMINVALIDATERECT +{ + NMHDR hdr; + HBKWND hbkWnd; + RECT rect; +} BKINMINVALIDATERECT, *LPBKINMINVALIDATERECT; + +////////////////////////////////////////////////////////////////////////// +// CBkWindow Implement +////////////////////////////////////////////////////////////////////////// + +class CBkWindow : public CBkObject +{ +public: + CBkWindow() + : m_hBkWnd(BkWnds::NewWindow(this)) + , m_hBkWndParent(NULL) + , m_hWndContainer(NULL) + , m_bMsgHandled(FALSE) + , m_uCmdID(NULL) + , m_uPositionType(0) + , m_lSpecifyWidth(0) + , m_lSpecifyHeight(0) + , m_dwState(BkWndState_Normal) + , m_uVAlign(0) + , m_uHAlign(0) + , m_bTransparent(FALSE) + , m_pPaintHook(NULL) + { + } + virtual ~CBkWindow() + { + BkWnds::DestroyWindow(m_hBkWnd); + } + + enum { + // Specify by "width" attribute + SizeX_Mask = 0x0007UL, + SizeX_Specify = 0x0001UL, // width > 0 + SizeX_FitContent = 0x0002UL, // width <= 0 + SizeX_FitParent = 0x0004UL, // width = "full" default + + // Specify by "height" attribute + SizeY_Mask = 0x0070UL, + SizeY_Specify = 0x0010UL, // height > 0 + SizeY_FitContent = 0x0020UL, // height <= 0 default + SizeY_FitParent = 0x0040UL, // height = "full" default + // Specify by "float" attribute + + Position_Mask = 0x0300UL, + Position_Relative = 0x0100UL, // float = 0 default + Position_Float = 0x0200UL, // float = 1 + + // Specify by "valign" and "align" attribute, only using at float = 1 or panel control (Vert-Align) + Align_Mask = 0xF000UL, + VAlign_Top = 0x0000UL, // valign = top + VAlign_Middle = 0x1000UL, // valign = middle + VAlign_Bottom = 0x2000UL, // valign = bottom + Align_Left = 0x0000UL, // align = left + Align_Center = 0x4000UL, // align = center + Align_Right = 0x8000UL, // align = right + }; + + struct BKDLG_POSITION_ITEM + { + BOOL bCenter; + BOOL bMinus; + int nPos; + }; + + struct BKDLG_POSITION + { + int nCount; + union + { + struct + { + BKDLG_POSITION_ITEM Left; + BKDLG_POSITION_ITEM Top; + BKDLG_POSITION_ITEM Right; + BKDLG_POSITION_ITEM Bottom; + }; + BKDLG_POSITION_ITEM Item[4]; + }; + }; + +protected: + HBKWND m_hBkWnd; + HBKWND m_hBkWndParent; + HWND m_hWndContainer; + UINT m_uCmdID; + CRect m_rcWindow; + UINT m_uPositionType; + BkStyle m_style; + CString m_strInnerText; + LONG m_lSpecifyWidth; + LONG m_lSpecifyHeight; + DWORD m_dwState; + UINT m_uVAlign; + UINT m_uHAlign; + CString m_strLinkUrl; + BOOL m_bTransparent; + CString m_strToolTipText; + + BKDLG_POSITION m_dlgpos; + IBkWindowPaintHook* m_pPaintHook; + +public: + + ////////////////////////////////////////////////////////////////////////// + // Method Define + + // Get align + UINT GetAlign() + { + return m_uVAlign | m_uHAlign; + } + + // Get position type + DWORD GetPositionType() + { + return m_uPositionType; + } + + // Set position type + void SetPositionType(DWORD dwPosType, DWORD dwMask = 0xFFFFFFFF) + { + m_uPositionType = (m_uPositionType & ~dwMask) | (dwPosType & dwMask); + } + + // Get BkWindow rect(position in container) + void GetRect(LPRECT prect) + { + if (prect) + { + prect->left = m_rcWindow.left; + prect->right = m_rcWindow.right; + prect->top = m_rcWindow.top; + prect->bottom = m_rcWindow.bottom; + } + } + + void GetDlgPosition(BKDLG_POSITION *pPos) + { + if (pPos) + memcpy(pPos, &m_dlgpos, sizeof(BKDLG_POSITION)); + } + + // Get inner text + LPCTSTR GetInnerText() + { + return m_strInnerText; + } + + // Get tooltip text + LPCTSTR GetToolTipText() + { + return m_strToolTipText; + } + + // Set inner text + HRESULT SetInnerText(LPCTSTR lpszText) + { + m_strInnerText = lpszText; + + if ((m_uPositionType & SizeX_FitContent | SizeY_FitContent) || CLR_INVALID == m_style.m_crBg) + { + if ((m_uPositionType & (SizeX_FitContent | SizeY_FitContent)) && (4 != m_dlgpos.nCount)) + { + SIZE sizeRet = {0, 0}; + + BkSendMessage(WM_NCCALCSIZE, FALSE, (LPARAM)&sizeRet); + + if (m_uPositionType & SizeX_FitContent) + m_rcWindow.right = m_rcWindow.left + sizeRet.cx; + if (m_uPositionType & SizeY_FitContent) + m_rcWindow.bottom = m_rcWindow.top + sizeRet.cy; + } + + return S_OK; + } + else + return S_FALSE; + } + + // Send a message to BkWindow + LRESULT BkSendMessage(UINT Msg, WPARAM wParam = 0, LPARAM lParam = 0) + { + LRESULT lResult = 0; + + SetMsgHandled(FALSE); + ProcessWindowMessage(NULL, Msg, wParam, lParam, lResult); + + return lResult; + } + + // Move BkWindow to new place + // + // NOTICE: Dangerous + void Move(LPRECT prect) + { + if (prect) + m_rcWindow = prect; + } + + // Set current cursor, when hover + virtual void SetCursor() + { + HCURSOR hCur = ::LoadCursor(NULL, m_style.m_lpCursorName); + ::SetCursor(hCur); + } + + // Get BkWindow state + DWORD GetState(void) + { + return m_dwState; + } + + // Modify BkWindow state + DWORD ModifyState(DWORD dwStateAdd, DWORD dwStateRemove) + { + DWORD dwOldState = m_dwState; + + m_dwState |= dwStateAdd; + m_dwState &= ~dwStateRemove; + + return dwOldState; + } + + // Get Command ID + UINT GetCmdID() + { + return m_uCmdID; + } + + HBKWND GetBkHWnd() + { + return m_hBkWnd; + } + + HBKWND GetParent() + { + return m_hBkWndParent; + } + + void SetParent(HBKWND hBkWndParent) + { + m_hBkWndParent = hBkWndParent; + } + + BOOL IsChecked() + { + return BkWndState_Check == (m_dwState & BkWndState_Check); + } + + BOOL IsDisabled(BOOL bCheckParent = FALSE) + { + BOOL bDisable = (BkWndState_Disable == (m_dwState & BkWndState_Disable)); + + if (bCheckParent && !bDisable) + { + CBkWindow *pWndParent = this; + + while (pWndParent = BkWnds::GetWindow(pWndParent->GetParent())) + { + if (pWndParent->IsDisabled()) + return TRUE; + } + } + + return bDisable; + } + + BOOL IsVisible(BOOL bCheckParent = FALSE) + { + BOOL bVisible = (0 == (m_dwState & BkWndState_Invisible)); + + if (bCheckParent && bVisible) + { + CBkWindow *pWndParent = this; + + while (pWndParent = BkWnds::GetWindow(pWndParent->GetParent())) + { + if (!pWndParent->IsVisible()) + return FALSE; + } + } + + return bVisible; + } + + void SetVisible(BOOL bVisible) + { + if (bVisible) + ModifyState(0, BkWndState_Invisible); + else + ModifyState(BkWndState_Invisible, 0); + } + + BOOL NeedRedrawParent() + { + return (m_style.m_strSkinName.IsEmpty() && (m_style.m_crBg == CLR_INVALID)); + } + +// void Invalidate() +// { +// m_bNeedRedraw = TRUE; +// } +// +// void Validate() +// { +// m_bNeedRedraw = FALSE; +// } + + LPCTSTR GetLinkUrl() + { + return m_strLinkUrl; + } + + // Get container, container is a REAL window + HWND GetContainer() + { + return m_hWndContainer; + } + + BOOL IsTransparent() + { + return m_bTransparent; + } + + // add by dummyz@126.com + BkStyle& GetStyle() + { + return m_style; + } + + void SetPaintHook(IBkWindowPaintHook* pPaintHook) + { + m_pPaintHook = pPaintHook; + } + +public: + + ////////////////////////////////////////////////////////////////////////// + // Virtual functions + + // Create BkWindow from xml element + virtual BOOL Load(TiXmlElement* pTiXmlElem) + { + if (!pTiXmlElem) + return FALSE; + + { + m_strInnerText = CA2T(pTiXmlElem->GetText(), CP_UTF8); + if (!m_strInnerText.IsEmpty()) + { + int nSubStringStart = 0, nSubStringEnd = 0; + + while (TRUE) + { + nSubStringStart = m_strInnerText.Find(_T("%str"), nSubStringEnd); + if (-1 == nSubStringStart) + break; + + int nID = ::StrToInt((LPCTSTR)m_strInnerText + nSubStringStart + 4); + if (0 >= nID) + break; + + nSubStringEnd = m_strInnerText.Find(L'%', nSubStringStart + 4) + 1; + if (-1 == nSubStringEnd) + break; + + m_strInnerText = m_strInnerText.Left(nSubStringStart) + + BkString::Get((UINT)nID) + + m_strInnerText.Mid(nSubStringEnd); + } + } + } + + m_uPositionType = 0; + + __super::Load(pTiXmlElem); + + int nValue = 0; + CStringA strValue; + + strValue = pTiXmlElem->Attribute("show", &nValue); + if (!strValue.IsEmpty()) + { + SetVisible(nValue); + } + + if (2 == m_dlgpos.nCount || 4 == m_dlgpos.nCount) + return TRUE; + + strValue = pTiXmlElem->Attribute("width", &nValue); + if (0 == nValue && "full" == strValue) + { + m_rcWindow.right = 0; + m_uPositionType = (m_uPositionType & ~SizeX_Mask) | SizeX_FitParent; + } + else + { + if (nValue > 0) + { + m_rcWindow.right = nValue; + m_lSpecifyWidth = nValue; + m_uPositionType = (m_uPositionType & ~SizeX_Mask) | SizeX_Specify; + } + else + { + m_rcWindow.right = 0; + m_uPositionType = (m_uPositionType & ~SizeX_Mask) | SizeX_FitContent; + } + } + + strValue = pTiXmlElem->Attribute("height", &nValue); + if (0 == nValue && "full" == strValue) + { + m_rcWindow.bottom = 0; + m_uPositionType = (m_uPositionType & ~SizeY_Mask) | SizeY_FitParent; + } + else + { + if (nValue > 0) + { + m_rcWindow.bottom = nValue; + m_lSpecifyHeight = nValue; + m_uPositionType = (m_uPositionType & ~SizeY_Mask) | SizeY_Specify; + } + else + { + m_rcWindow.bottom = 0; + m_uPositionType = (m_uPositionType & ~SizeY_Mask) | SizeY_FitContent; + } + } + + if (m_uPositionType & (SizeX_FitContent | SizeY_FitContent)) + { + SIZE sizeRet = {0, 0}; + + BkSendMessage(WM_NCCALCSIZE, FALSE, (LPARAM)&sizeRet); + + if (m_uPositionType & SizeX_FitContent) + m_rcWindow.right = sizeRet.cx; + if (m_uPositionType & SizeY_FitContent) + m_rcWindow.bottom = sizeRet.cy; + } + + nValue = 0; + pTiXmlElem->Attribute("float", &nValue); + m_uPositionType |= (nValue != 0 ? Position_Float : Position_Relative); + + return TRUE; + } + + // Set container, container is a REAL window + virtual void SetContainer(HWND hWndContainer) + { + m_hWndContainer = hWndContainer; + } + + // Get handle from point + virtual HBKWND BkGetHWNDFromPoint(POINT ptHitTest, BOOL bOnlyText) + { + if (m_rcWindow.PtInRect(ptHitTest)) + return m_hBkWnd; + else + return NULL; + } + + virtual BOOL NeedRedrawWhenStateChange() + { + if (!m_style.m_strSkinName.IsEmpty()) + { + CBkSkinBase* pSkin = BkSkin::GetSkin(m_style.m_strSkinName); + if (pSkin && !pSkin->IgnoreState()) + return TRUE; + } + + return (CLR_INVALID != m_style.m_crHoverText) || (NULL != m_style.m_ftHover) || (CLR_INVALID != m_style.m_crBgHover); + } + +// virtual BOOL NeedRedraw() +// { +// return m_bNeedRedraw; +// } + + virtual BOOL IsContainer() + { + return FALSE; + } + + virtual BOOL RedrawRegion(CDCHandle& dc, CRgn& rgn) + { + if (rgn.IsNull() || rgn.RectInRegion(m_rcWindow)) + { + DrawBkgnd(dc); + + if ( m_pPaintHook != NULL && !m_pPaintHook->NotifyPaint(this, (HDC)dc, m_rcWindow, TRUE) ) + { + return TRUE; + } + + BkSendMessage(WM_PAINT, (WPARAM)(HDC)dc); + + if ( m_pPaintHook != NULL ) + { + m_pPaintHook->NotifyPaint(this, (HDC)dc, m_rcWindow, FALSE); + } + + return TRUE; + } + + return FALSE; + } + + void NotifyInvalidate() + { + NotifyInvalidateRect(m_rcWindow); + } + + void NotifyInvalidateRect(LPRECT lprect) + { + if (lprect) + { + CRect rect = *lprect; + NotifyInvalidateRect(rect); + } + } + + void NotifyInvalidateRect(const CRect& rect) + { + if (IsVisible(TRUE) && m_hWndContainer && ::IsWindow(m_hWndContainer)) + { + BKINMINVALIDATERECT nms; + + nms.hdr.code = BKINM_INVALIDATERECT; + nms.hdr.hwndFrom = NULL; + nms.hdr.idFrom = m_uCmdID; + nms.hbkWnd = m_hBkWnd; + nms.rect = rect; + + ::SendMessage(m_hWndContainer, WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + } + } + +public: + + ////////////////////////////////////////////////////////////////////////// + // Message Handler + + void OnWindowPosChanged(LPWINDOWPOS lpWndPos) + { + m_rcWindow.MoveToXY(lpWndPos->x, lpWndPos->y); + SIZE sizeRet = {lpWndPos->cx, lpWndPos->cy}; + + BkSendMessage(WM_NCCALCSIZE, TRUE, (LPARAM)&sizeRet); + + m_rcWindow.SetRect(lpWndPos->x, lpWndPos->y, lpWndPos->x + sizeRet.cx, lpWndPos->y + sizeRet.cy); + + if (GetPositionType() & SizeX_FitParent) + m_rcWindow.right = max(lpWndPos->x + lpWndPos->cx, m_rcWindow.left); + else if (GetPositionType() & SizeX_Specify) + m_rcWindow.right = m_rcWindow.left + m_lSpecifyWidth; + + if (GetPositionType() & SizeY_FitParent) + m_rcWindow.bottom = max(lpWndPos->y + lpWndPos->cy, m_rcWindow.top); + else if (GetPositionType() & SizeY_Specify) + m_rcWindow.bottom = m_rcWindow.top + m_lSpecifyHeight; + } + + int OnCreate(LPCREATESTRUCT /*lpCreateStruct*/) + { + return TRUE; + } + + void OnDestroy() + { + } + + // Draw background default + void DrawBkgnd(CDCHandle& dc) + { + if (m_style.m_strSkinName.IsEmpty()) + { + COLORREF crBg = m_style.m_crBg; + + if (BkWndState_Hover == (GetState() & BkWndState_Hover) && CLR_INVALID != m_style.m_crBgHover) + { + crBg = m_style.m_crBgHover; + } + + if (CLR_INVALID != crBg) + dc.FillSolidRect(m_rcWindow, crBg); + } + else + { + CBkSkinBase* pSkin = BkSkin::GetSkin(m_style.m_strSkinName); + if (pSkin) + { + pSkin->Draw(dc, m_rcWindow, m_dwState); + } + } + } + + struct BkDCPaint + { + BkDCPaint() + : bBkModeChanged(FALSE) + , nOldBkMode(OPAQUE) + , bFontChanged(FALSE) + , hftOld(NULL) + , bTextColorChanged(FALSE) + , crOld(CLR_INVALID) + , bBgColorChanged(FALSE) + , crOldBg(CLR_INVALID) + { + } + BOOL bBkModeChanged; + int nOldBkMode; + BOOL bFontChanged; + HFONT hftOld; + BOOL bTextColorChanged; + COLORREF crOld; + BOOL bBgColorChanged; + COLORREF crOldBg; + CRect rcClient; + }; + + void BeforePaint(CDCHandle &dc, BkDCPaint &BkDC) + { + HFONT /*hftOld = NULL, */hftDraw = NULL; + COLORREF /*crOld = CLR_INVALID, crOldBg = CLR_INVALID, */crDraw = CLR_INVALID; + /*int nOldBkMode = OPAQUE;*/ + + BkDC.rcClient = m_rcWindow; + BkDC.rcClient.DeflateRect(m_style.m_nMarginX, m_style.m_nMarginY); + + if (!m_style.m_strSkinName.IsEmpty()) + { + BkDC.bBkModeChanged = TRUE; + BkDC.nOldBkMode = dc.SetBkMode(TRANSPARENT); + } + if (CLR_INVALID != m_style.m_crBg) + { + BkDC.bBgColorChanged = TRUE; + BkDC.crOldBg = dc.SetBkColor(m_style.m_crBg); + } + + if (m_style.m_ftText) + hftDraw = m_style.m_ftText; + + if (m_style.m_crText != CLR_INVALID) + crDraw = m_style.m_crText; + + if (IsDisabled(TRUE)/*BkWndState_Disable == (GetState() & BkWndState_Disable)*/) + { + if (m_style.m_crDisabledText != CLR_INVALID) + crDraw = m_style.m_crDisabledText; + } + else if (BkWndState_Hover == (GetState() & BkWndState_Hover)) + { + if (m_style.m_ftHover) + hftDraw = m_style.m_ftHover; + + if (m_style.m_crHoverText != CLR_INVALID) + crDraw = m_style.m_crHoverText; + } + + if (hftDraw) + { + BkDC.bFontChanged = TRUE; + BkDC.hftOld = dc.SelectFont(hftDraw); + } + + if (crDraw != CLR_INVALID) + { + BkDC.bTextColorChanged = TRUE; + BkDC.crOld = dc.SetTextColor(crDraw); + } + } + + void AfterPaint(CDCHandle &dc, BkDCPaint &BkDC) + { + if (BkDC.bFontChanged) + dc.SelectFont(BkDC.hftOld); + + if (BkDC.bTextColorChanged) + dc.SetTextColor(BkDC.crOld); + + if (BkDC.bBkModeChanged) + dc.SetBkMode(BkDC.nOldBkMode); + + if (BkDC.bBgColorChanged) + dc.SetBkColor(BkDC.crOldBg); + } + + // Draw inner text default + void OnPaint(CDCHandle dc) + { + BkDCPaint BkDC; + + BeforePaint(dc, BkDC); + + dc.DrawText(m_strInnerText, m_strInnerText.GetLength(), BkDC.rcClient, m_style.m_nTextAlign); + + AfterPaint(dc, BkDC); + } + + // Calc BkWindow size + LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam) + { + LPSIZE pSize = (LPSIZE)lParam; + + if (4 == m_dlgpos.nCount) + { + CRect rect; + + if (m_dlgpos.Left.bCenter) + rect.left = pSize->cx / 2 + (m_dlgpos.Left.bMinus ? -1 : 1) * m_dlgpos.Left.nPos; + else if (m_dlgpos.Left.bMinus) + rect.left = pSize->cx - m_dlgpos.Left.nPos; + else + rect.left = m_dlgpos.Left.nPos; + + if (m_dlgpos.Right.bCenter) + rect.right = pSize->cx / 2 + (m_dlgpos.Right.bMinus ? -1 : 1) * m_dlgpos.Right.nPos; + else if (m_dlgpos.Right.bMinus) + rect.right = pSize->cx - m_dlgpos.Right.nPos; + else + rect.right = m_dlgpos.Right.nPos; + + if (m_dlgpos.Top.bCenter) + rect.top = pSize->cy / 2 + (m_dlgpos.Top.bMinus ? -1 : 1) * m_dlgpos.Top.nPos; + else if (m_dlgpos.Top.bMinus) + rect.top = pSize->cy - m_dlgpos.Top.nPos; + else + rect.top = m_dlgpos.Top.nPos; + + if (m_dlgpos.Bottom.bCenter) + rect.bottom = pSize->cy / 2 + (m_dlgpos.Bottom.bMinus ? -1 : 1) * m_dlgpos.Bottom.nPos; + else if (m_dlgpos.Bottom.bMinus) + rect.bottom = pSize->cy - m_dlgpos.Bottom.nPos; + else + rect.bottom = m_dlgpos.Bottom.nPos; + + *pSize = rect.Size(); + } + else + { + CDCHandle dcDesktop = ::GetDC(::GetDesktopWindow()); + CDC dcTest; + HFONT hftOld = NULL, hftTest = NULL; + CRect rcTest = m_rcWindow; + + dcTest.CreateCompatibleDC(dcDesktop); + + if (bCalcValidRects) + { + rcTest.right = rcTest.left + pSize->cx; + rcTest.bottom = rcTest.top + pSize->cy; + } + + if (m_style.m_ftText) + hftTest = m_style.m_ftText; + else + { + CBkWindow* pWnd = this; + HBKWND hWndParent = NULL; + + while (hWndParent = pWnd->GetParent()) + { + pWnd = BkWnds::GetWindow(hWndParent); + if (pWnd->m_style.m_ftText) + { + hftTest = pWnd->m_style.m_ftText; + break; + } + } + + } + + if (BkWndState_Hover == (GetState() & BkWndState_Hover)) + { + if (m_style.m_ftHover) + hftTest = m_style.m_ftHover; + else + { + CBkWindow* pWnd = this; + HBKWND hWndParent = NULL; + + while (hWndParent = pWnd->GetParent()) + { + pWnd = BkWnds::GetWindow(hWndParent); + if (pWnd->m_style.m_ftHover) + { + hftTest = pWnd->m_style.m_ftHover; + break; + } + } + } + } + + if (NULL == hftTest) + hftTest = BkFontPool::GetFont(BKF_DEFAULTFONT); + + hftOld = dcTest.SelectFont(hftTest); + + rcTest.DeflateRect(m_style.m_nMarginX, m_style.m_nMarginY); + + int nTestDrawMode = m_style.m_nTextAlign & ~(DT_CENTER | DT_RIGHT | DT_VCENTER | DT_BOTTOM); + + if (nTestDrawMode & DT_WORDBREAK) + rcTest.bottom = 0x7FFF; + + dcTest.DrawText(m_strInnerText, m_strInnerText.GetLength(), rcTest, nTestDrawMode | DT_CALCRECT); + + pSize->cx = rcTest.Width() + 2 * m_style.m_nMarginX; + pSize->cy = rcTest.Height() + 2 * m_style.m_nMarginY; + + dcTest.SelectFont(hftOld); + + ::ReleaseDC(::GetDesktopWindow(), dcDesktop); + } + + return 0; + } + + void OnShowWindow(BOOL bShow, UINT nStatus) + { + if (bShow) + ModifyState(0, BkWndState_Invisible); + else + ModifyState(BkWndState_Invisible, 0); + } + + HRESULT OnAttributePosChange(CStringA& strValue, BOOL bLoading) + { + if (!strValue.IsEmpty()) + { + LPCSTR lpszValue = strValue; + int nPos = 0, nPosPrev = 0; + + for (m_dlgpos.nCount = 0; m_dlgpos.nCount < 4; m_dlgpos.nCount ++) + { + nPosPrev = nPos; + nPos = strValue.Find(',', nPosPrev) + 1; + + m_dlgpos.Item[m_dlgpos.nCount].bCenter = ('|' == lpszValue[nPosPrev]); + if (m_dlgpos.Item[m_dlgpos.nCount].bCenter) + nPosPrev ++; + m_dlgpos.Item[m_dlgpos.nCount].bMinus = ('-' == lpszValue[nPosPrev]); + if (m_dlgpos.Item[m_dlgpos.nCount].bMinus) + nPosPrev ++; + + if (0 == nPos) + { + m_dlgpos.Item[m_dlgpos.nCount].nPos = ::StrToIntA(strValue.Mid(nPosPrev)); + m_dlgpos.nCount ++; + break; + } + + m_dlgpos.Item[m_dlgpos.nCount].nPos = ::StrToIntA(strValue.Mid(nPosPrev, nPos - nPosPrev)); + } + + if (2 == m_dlgpos.nCount || 4 == m_dlgpos.nCount) + { + m_uPositionType = (m_uPositionType & ~SizeX_Mask) | SizeX_FitContent; + m_uPositionType = (m_uPositionType & ~SizeY_Mask) | SizeY_FitContent; + } + else + m_dlgpos.nCount = 0; + + if (!bLoading) + { + _RepositionSelf(); + } + } + + return S_FALSE; + } + + void _RepositionSelf(); + +protected: + BOOL m_bMsgHandled; + + BOOL IsMsgHandled() const + { + return m_bMsgHandled; + } + void SetMsgHandled(BOOL bHandled) + { + m_bMsgHandled = bHandled; + } + + BKWIN_DECLARE_RETURN_SETTING(FALSE, FALSE) + + BKWIN_BEGIN_MSG_MAP() + MSG_WM_CREATE(OnCreate) + MSG_WM_PAINT(OnPaint) + MSG_WM_DESTROY(OnDestroy) + MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged) + MSG_WM_NCCALCSIZE(OnNcCalcSize) + MSG_WM_SHOWWINDOW(OnShowWindow) + BKWIN_END_MSG_MAP_BASE() +// +// enum { +// BKWND_INNERTEXT = 1, +// }; + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_STYLE_ATTRIBUTE("class", m_style, TRUE) + BKWIN_INT_ATTRIBUTE("id", m_uCmdID, FALSE)//, 0) + BKWIN_COLOR_ATTRIBUTE("crbg", m_style.m_crBg, FALSE) + BKWIN_COLOR_ATTRIBUTE("crtext", m_style.m_crText, FALSE) + BKWIN_FONT_ATTRIBUTE("font", m_style.m_ftText, FALSE) + BKWIN_TSTRING_ATTRIBUTE("href", m_strLinkUrl, FALSE) + BKWIN_TSTRING_ATTRIBUTE("tip", m_strToolTipText, FALSE) + BKWIN_ENUM_ATTRIBUTE("valign", UINT, TRUE) + BKWIN_ENUM_VALUE("top", VAlign_Top) + BKWIN_ENUM_VALUE("middle", VAlign_Middle) + BKWIN_ENUM_VALUE("bottom", VAlign_Bottom) + BKWIN_ENUM_END(m_uVAlign) + BKWIN_ENUM_ATTRIBUTE("align", UINT, TRUE) + BKWIN_ENUM_VALUE("left", Align_Left) + BKWIN_ENUM_VALUE("center", Align_Center) + BKWIN_ENUM_VALUE("right", Align_Right) + BKWIN_ENUM_END(m_uHAlign) + BKWIN_CUSTOM_ATTRIBUTE("pos", OnAttributePosChange) + BKWIN_INT_ATTRIBUTE("transparent", m_bTransparent, FALSE)//, 0) + BKWIN_DECLARE_ATTRIBUTES_END() +}; + +// ѷ +inline CBkWindow* BkWnds::GetWindow(UINT uCmdID, HWND hWndInContainer/* = NULL*/) +{ + CBkWindow* pWndRet = NULL; + + ::EnterCriticalSection(&ms_lockWndMap); + + POSITION pos = _Instance().m_mapPool.GetStartPosition(); + + while (pos) + { + const _BkWndHandlePool::CPair *pairRet = _Instance().m_mapPool.GetNext(pos); + + if (pairRet->m_value->GetCmdID() == uCmdID) + { + if (NULL == hWndInContainer || hWndInContainer == pairRet->m_value->GetContainer()) + { + pWndRet = pairRet->m_value; + break; + } + } + } + + ::LeaveCriticalSection(&ms_lockWndMap); + + return pWndRet; +} + + +inline void BkWnds::SelectRadio(CBkWindow* pbkWnd, LPCSTR lpszGroupName, CBkWindow **ppbkWndLastSelect) +{ + ::EnterCriticalSection(&ms_lockWndMap); + + CAtlList &ListGroup = _Instance().m_mapRadioPool[lpszGroupName]; + + pbkWnd->ModifyState(BkWndState_Check, 0); + + POSITION posCurrent = NULL, pos = ListGroup.GetHeadPosition(); + + while (pos) + { + posCurrent = pos; + CBkWindow *pbkWndFind = ListGroup.GetNext(pos); + + if (pbkWndFind == pbkWnd) + continue; + + if (pbkWndFind->IsChecked()) + { + pbkWndFind->ModifyState(0, BkWndState_Check); + pbkWndFind->NotifyInvalidate(); + + if (ppbkWndLastSelect) + *ppbkWndLastSelect = pbkWndFind; + } + } + + ::LeaveCriticalSection(&ms_lockWndMap); +} + +class CBkContainerWnd : public CBkWindow +{ +public: + virtual CBkWindow* FindChildByCmdID(UINT uCmdID) + { + ATLASSERT(FALSE); + + return NULL; + } + + virtual void RepositionChilds() + { + } + + virtual void RepositionChild(CBkWindow *pBkWndChild) + { + } + + BOOL IsContainer() + { + return TRUE; + } +}; + +inline void CBkWindow::_RepositionSelf() +{ + CBkWindow *pWndParent = BkWnds::GetWindow(GetParent()); + if (pWndParent && pWndParent->IsContainer()) + { + CBkContainerWnd *pWndParentContainer = (CBkContainerWnd *)pWndParent; + pWndParentContainer->RepositionChild(this); + } +} diff --git a/Client/Client/GUI/BKWin/bkwin/bkwndcmnctrl.h b/Client/Client/GUI/BKWin/bkwin/bkwndcmnctrl.h new file mode 100644 index 00000000..04c9b5ca --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkwndcmnctrl.h @@ -0,0 +1,1041 @@ +////////////////////////////////////////////////////////////////////////// +// File Name: bkwndcmnctrl.h +// Description: BkWindow Definition +// Creator: Zhang Xiaoxuan +// Version: 2009.04.28 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "bkwnd.h" +#include "bkimage.h" +#include "bktheme.h" +#include "bkwndnotify.h" + + + + +////////////////////////////////////////////////////////////////////////// +// Memory gdiplus Image Draw +// +// Usage: +// +class CBkMemoryImage : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkMemoryImage, "memimage") + + CBkMemoryImage() + { + m_gdiPlusImage = NULL; + } +public: + + // Do nothing + void OnPaint(CDCHandle dc) + { + if (m_gdiPlusImage==NULL) + return; + + Gdiplus::Graphics gh(dc.m_hDC); + + gh.DrawImage( m_gdiPlusImage, Gdiplus::Rect(m_rcWindow.left,m_rcWindow.top,m_rcWindow.Width(),m_rcWindow.Height()), + 0,0, m_gdiPlusImage->GetWidth(), m_gdiPlusImage->GetHeight(), Gdiplus::UnitPixel ); + } + + HRESULT OnAttributeChange(CStringA& strValue, BOOL bLoading) + { + m_gdiPlusImage = (Gdiplus::Image*)IntToPtr(atoi( strValue )); + return S_OK; + } + +protected: + BKWIN_BEGIN_MSG_MAP() + MSG_WM_PAINT(OnPaint) + BKWIN_END_MSG_MAP() + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_CUSTOM_ATTRIBUTE("mempointer", OnAttributeChange) + BKWIN_DECLARE_ATTRIBUTES_END() + +protected: + Gdiplus::Image* m_gdiPlusImage; +}; + +////////////////////////////////////////////////////////////////////////// +// Spacing Control +// Only leave a space, faster than "div" (... a little) +// +// Usage: +// +class CBkSpacing : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkSpacing, "spacing") + +public: + + // Do nothing + void OnPaint(CDCHandle dc) + { + } + +protected: + BKWIN_BEGIN_MSG_MAP() + MSG_WM_PAINT(OnPaint) + BKWIN_END_MSG_MAP() +}; + +////////////////////////////////////////////////////////////////////////// +// New line +// Panel control process return thing, so define a blank class +// +// Usage:
+// +class CBkReturn : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkReturn, "br") +}; + +////////////////////////////////////////////////////////////////////////// +// Static Control +// +// Usage: inner text example +// +class CBkStatic : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkStatic, "text") +}; + +////////////////////////////////////////////////////////////////////////// +// Link Control +// Only For Header Drag Test +// Usage: inner text example +// +class CBkLink : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkLink, "link") +public: + + virtual BOOL Load(TiXmlElement* pTiXmlElem) + { + if (!CBkWindow::Load(pTiXmlElem)) + return FALSE; + + return TRUE; + } + +private: + BOOL m_hasUnderLine; + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_INT_ATTRIBUTE("underline", m_hasUnderLine, FALSE) + BKWIN_DECLARE_ATTRIBUTES_END() +}; + +////////////////////////////////////////////////////////////////////////// +// Button Control +// Use id attribute to process click event +// +// Usage: +// +class CBkButton : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkButton, "button") +public: + + virtual BOOL NeedRedrawWhenStateChange() + { + return TRUE; + } +}; + +////////////////////////////////////////////////////////////////////////// +// Image Control +// Use src attribute specify a resource id +// +// Usage: +// +class CBkImageWnd : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkImageWnd, "img") +public: + CBkImageWnd() + : m_nSubImageID(-1) + , m_pSkin(NULL) + { + + } + + virtual BOOL Load(TiXmlElement* pTiXmlElem) + { + if (!CBkWindow::Load(pTiXmlElem)) + return FALSE; +// +// m_pSkin = BkSkin::GetSkin(m_strSkin); +// if (m_pSkin && m_pSkin->IsClass(CBkImageSkin::GetClassName())) +// return TRUE; +// +// // if (m_imgSrc.M_HOBJECT) +// // return TRUE; + + return TRUE; + } + + void OnPaint(CDCHandle dc) + { + if (m_pSkin) + m_pSkin->Draw(dc, m_rcWindow, m_nSubImageID); + } + + LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam) + { + __super::OnNcCalcSize(bCalcValidRects, lParam); + + LPSIZE pSize = (LPSIZE)lParam; + + if (m_pSkin) + { + SIZE sizeImage; + sizeImage = m_pSkin->GetSkinSize(); + + if (sizeImage.cx) + pSize->cx = sizeImage.cx; + if (sizeImage.cy) + pSize->cy = sizeImage.cy; + + return TRUE; + } + + return 0; + } + +protected: +// CBkImageSkin m_imgSrc; +// int m_nSubImageWidth; + int m_nSubImageID; + CBkSkinBase *m_pSkin; + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_SKIN_ATTRIBUTE("skin", m_pSkin, TRUE) +// BKWIN_CHAIN_ATTRIBUTE(m_imgSrc, TRUE) +// BKWIN_UINT_ATTRIBUTE("src", m_imgSrc, TRUE) +// BKWIN_INT_ATTRIBUTE("subwidth", m_nSubImageWidth, TRUE) + BKWIN_INT_ATTRIBUTE("sub", m_nSubImageID, FALSE) + BKWIN_DECLARE_ATTRIBUTES_END() + + BKWIN_BEGIN_MSG_MAP() + MSG_WM_PAINT(OnPaint) + MSG_WM_NCCALCSIZE(OnNcCalcSize) + BKWIN_END_MSG_MAP() +}; + +////////////////////////////////////////////////////////////////////////// +// Progress Control +// Use id attribute to process click event +// +// Usage: +// +class CBkProgress : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkProgress, "progress") +public: + CBkProgress() + : m_dwMinValue(0) + , m_dwMaxValue(0) + , m_dwValue(0) + , m_bShowPercent(FALSE) + , m_pSkinBg(NULL) + , m_pSkinPos(NULL) + { + + } + + virtual BOOL Load(TiXmlElement* pTiXmlElem) + { + if (!CBkWindow::Load(pTiXmlElem)) + return FALSE; + +// CBkSkinBase *pSkin = NULL; +// pSkin = BkSkin::GetSkin(m_strSkinBg); +// +// if (pSkin) +// { +// if (pSkin->IsClass(CBkSkinImgHorzExtend::GetClassName())) +// m_pSkinBg = (CBkSkinImgHorzExtend *)pSkin; +// else +// m_pSkinBg = NULL; +// } +// +// pSkin = BkSkin::GetSkin(m_strSkinPos); +// +// if (pSkin) +// { +// if (pSkin->IsClass(CBkSkinImgHorzExtend::GetClassName())) +// m_pSkinPos = (CBkSkinImgHorzExtend *)pSkin; +// else +// m_pSkinPos = NULL; +// } +// + return TRUE; + } + + LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam) + { + __super::OnNcCalcSize(bCalcValidRects, lParam); + + LPSIZE pSize = (LPSIZE)lParam; + + if (m_pSkinBg) + { + SIZE sizeBg = m_pSkinBg->GetSkinSize(); + + pSize->cy = sizeBg.cy; + + return TRUE; + } + + return TRUE; + } + + void OnPaint(CDCHandle dc) + { + BkDCPaint bkdc; + CPen penFrame; + CString strPercent; + double dPos = 0; + + BeforePaint(dc, bkdc); + + penFrame.CreatePen( + PS_SOLID, + 1, + RGB(0x70, 0x70, 0x70) + ); + + HPEN hpenOld = dc.SelectPen(penFrame); + + if (m_pSkinBg) + { + m_pSkinBg->Draw(dc, m_rcWindow, BkWndState_Normal); + } + else + { + dc.RoundRect(m_rcWindow, CPoint(2, 2)); + } + + if (m_dwMaxValue == m_dwMinValue) + { + dPos = 0; + } + else + { + if (m_dwMaxValue < m_dwMinValue) + { + DWORD dwTemp = m_dwMaxValue; + m_dwMaxValue = m_dwMinValue; + m_dwMinValue = dwTemp; + } + + if (m_dwValue < m_dwMinValue) + { + m_dwValue = m_dwMinValue; + } + else if (m_dwValue > m_dwMaxValue) + { + m_dwValue = m_dwMaxValue; + } + + dPos = (double)(m_dwValue - m_dwMinValue) / (double)(m_dwMaxValue - m_dwMinValue); + } + + if (m_bShowPercent) + { + strPercent.Format(_T("%d%%"), (int)(dPos * 100)); + dc.DrawText(strPercent, strPercent.GetLength(), m_rcWindow, DT_SINGLELINE | DT_CENTER | DT_VCENTER); + } + + CRect rcPosBar = m_rcWindow; + + if (m_pSkinPos) + { + SIZE sizePosBar = m_pSkinPos->GetSkinSize(); + + rcPosBar.DeflateRect(2, (m_rcWindow.Height() - sizePosBar.cy) / 2); + rcPosBar.right = rcPosBar.left + (LONG)(rcPosBar.Width() * dPos); + + m_pSkinPos->Draw(dc, rcPosBar, BkWndState_Normal); + } + else + { + rcPosBar.DeflateRect(2, 2); + rcPosBar.right = rcPosBar.left + (LONG)(rcPosBar.Width() * dPos); + + dc.RoundRect(rcPosBar, CPoint(2, 2)); + + dc.FillSolidRect(rcPosBar, RGB(66, 97, 144)); + } + + dc.SelectPen(hpenOld); + + if (m_bShowPercent) + { + CRgn rgnClipOld, rgnClip; + rgnClip.CreateRectRgnIndirect(rcPosBar); + dc.GetClipRgn(rgnClipOld); + dc.SelectClipRgn(rgnClip); + + if (CLR_INVALID == m_style.m_crBg) + dc.SetTextColor(RGB(0xFF, 0xFF, 0xFF)); + else + dc.SetTextColor(m_style.m_crBg); + + dc.DrawText(strPercent, strPercent.GetLength(), m_rcWindow, DT_SINGLELINE | DT_CENTER | DT_VCENTER); + + dc.SetTextColor(m_style.m_crText); + dc.SelectClipRgn(rgnClipOld); + } + + AfterPaint(dc, bkdc); + } + +protected: + DWORD m_dwMinValue; + DWORD m_dwMaxValue; + DWORD m_dwValue; + BOOL m_bShowPercent; +// CStringA m_strSkinBg; +// CStringA m_strSkinPos; + CBkSkinBase *m_pSkinBg; + CBkSkinBase *m_pSkinPos; + + BKWIN_BEGIN_MSG_MAP() + MSG_WM_PAINT(OnPaint) + MSG_WM_NCCALCSIZE(OnNcCalcSize) + BKWIN_END_MSG_MAP() + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_SKIN_ATTRIBUTE("bgskin", m_pSkinBg, TRUE) + BKWIN_SKIN_ATTRIBUTE("posskin", m_pSkinPos, TRUE) +// BKWIN_STRING_ATTRIBUTE("bgskin", m_strSkinBg, TRUE) +// BKWIN_STRING_ATTRIBUTE("posskin", m_strSkinPos, TRUE) + BKWIN_DWORD_ATTRIBUTE("min", m_dwMinValue, FALSE) + BKWIN_DWORD_ATTRIBUTE("max", m_dwMaxValue, FALSE) + BKWIN_DWORD_ATTRIBUTE("value", m_dwValue, FALSE) + BKWIN_UINT_ATTRIBUTE("showpercent", m_bShowPercent, FALSE) + BKWIN_DECLARE_ATTRIBUTES_END() +}; + +////////////////////////////////////////////////////////////////////////// +// Image Button Control +// +// Usage: +// +class CBkImageBtnWnd : public CBkImageWnd +{ + BKOBJ_DECLARE_CLASS_NAME(CBkImageBtnWnd, "imgbtn") +public: + CBkImageBtnWnd() + { + + } + + virtual BOOL NeedRedrawWhenStateChange() + { + return TRUE; + } + +// virtual BOOL Load(TiXmlElement* pTiXmlElem) +// { +// if (!CBkWindow::Load(pTiXmlElem)) +// return FALSE; +// +// if (m_imgSrc.M_HOBJECT) +// return TRUE; +// +// return FALSE; +// } + + void OnPaint(CDCHandle dc) + { + //DWORD dwState = GetState(); + + if (m_pSkin) + { + m_pSkin->Draw( + dc, m_rcWindow, + IIF_STATE4(GetState(), 0, 1, 2, 3) + ); + } + } + +// LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam) +// { +// LPSIZE pSize = (LPSIZE)lParam; +// +// if (m_imgSrc.M_HOBJECT) +// { +// SIZE sizeImage; +// +// m_imgSrc.GetImageSize(sizeImage); +// +// pSize->cx = (m_imgSrc.GetSubImageWidth() != 0) ? m_imgSrc.GetSubImageWidth() : sizeImage.cx; +// pSize->cy = sizeImage.cy; +// +// return TRUE; +// } +// +// return FALSE; +// } + +protected: + + BKWIN_BEGIN_MSG_MAP() + MSG_WM_PAINT(OnPaint) +// MSG_WM_NCCALCSIZE(OnNcCalcSize) + BKWIN_END_MSG_MAP() +}; + +////////////////////////////////////////////////////////////////////////// +// Real Window Control +// Binding a real window +// +// Usage: +// +class CBkRealWnd : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkRealWnd, "realwnd") +public: + CBkRealWnd() +// : m_uRealWinDlgResID(0) + { + + } + + virtual BOOL NeedRedrawWhenStateChange() + { + return FALSE; + } + + void ShowRealWindow(BOOL bShow) + { + ::ShowWindow(_GetRealWindow(), bShow ? SW_SHOW : SW_HIDE); + } + + void OnWindowPosChanged(LPWINDOWPOS lpWndPos) + { + CRect rcOldWnd = m_rcWindow; + + __super::OnWindowPosChanged(lpWndPos); + + if (rcOldWnd != m_rcWindow) + { + HWND hWndReal = _GetRealWindow(); + ::SetWindowPos(hWndReal, HWND_TOP, m_rcWindow.left, m_rcWindow.top, m_rcWindow.Width(), m_rcWindow.Height(), SWP_NOREDRAW); + + BKNMREALWNDRESIZED nms; + nms.hdr.code = BKNM_REALWND_RESIZED; + nms.hdr.hwndFrom = m_hWndContainer; + nms.hdr.idFrom = ::GetDlgCtrlID(m_hWndContainer); + nms.uItemID = GetCmdID(); + nms.rcWnd = m_rcWindow; + + LRESULT lRet = ::SendMessage(m_hWndContainer, WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + + if (::IsWindowVisible(hWndReal)) + { + CRect rcUpdate = m_rcWindow; + rcUpdate.MoveToXY(0, 0); + //::RedrawWindow(_GetRealWindow(), rcUpdate, NULL, RDW_INVALIDATE | RDW_UPDATENOW); +// ::RedrawWindow(hWndReal, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ERASENOW); + ::InvalidateRect(hWndReal, NULL, TRUE); + ::SetWindowPos(hWndReal, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_FRAMECHANGED); + } + } + } + + void OnShowWindow(BOOL bShow, UINT nStatus) + { + __super::OnShowWindow(bShow, nStatus); + + if (bShow) + { + // ڻ߸ڵĸأҪTabлʾʵ + CBkWindow* pWnd = this; + + while (TRUE) + { + pWnd = BkWnds::GetWindow(pWnd->GetParent()); + + if (NULL == pWnd) + break; + + if (!pWnd->IsVisible()) + return; + } + } + + ShowRealWindow(bShow); + } + + void OnDestroy() + { + HWND hWndReal = _GetRealWindow(); + if (hWndReal && ::IsWindow(hWndReal)) + ::ShowWindow(hWndReal, SW_HIDE); + } + + // Do nothing + void OnPaint(CDCHandle dc) + { + } + +protected: + + HWND _GetRealWindow() + { + return ::GetDlgItem(m_hWndContainer, m_uCmdID); + } + +// UINT m_uRealWinDlgResID; + +// BKWIN_DECLARE_ATTRIBUTES_BEGIN() +// BKWIN_UINT_ATTRIBUTE("ctrlid", m_uRealWinDlgResID, FALSE) +// BKWIN_DECLARE_ATTRIBUTES_END() + + BKWIN_BEGIN_MSG_MAP() + MSG_WM_PAINT(OnPaint) + MSG_WM_DESTROY(OnDestroy) + MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged) + MSG_WM_SHOWWINDOW(OnShowWindow) + BKWIN_END_MSG_MAP() +}; + +////////////////////////////////////////////////////////////////////////// +// Line Control +// Simple HTML "HR" tag +// +// Usage:
+// +class CBkLine : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkLine, "hr") + +public: + + CBkLine() + : m_nPenStyle(PS_SOLID) + , m_nLineSize(1) + { + } + + // Do nothing + void OnPaint(CDCHandle dc) + { + CPen pen; + + pen.CreatePen(m_nPenStyle, m_nLineSize, m_style.m_crBg); + + HPEN hpenOld = dc.SelectPen(pen); + + dc.MoveTo(m_rcWindow.left, m_rcWindow.top/* + m_rcWindow.Height() / 2*/); + dc.LineTo(m_rcWindow.right, m_rcWindow.bottom/*top + m_rcWindow.Height() / 2*/); + + dc.SelectPen(hpenOld); + } + +protected: + int m_nPenStyle; + int m_nLineSize; + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_INT_ATTRIBUTE("size", m_nLineSize, FALSE) + BKWIN_ENUM_ATTRIBUTE("style", int, FALSE) + BKWIN_ENUM_VALUE("solid", PS_SOLID) // default + BKWIN_ENUM_VALUE("dash", PS_DASH) /* ------- */ + BKWIN_ENUM_VALUE("dot", PS_DOT) /* ....... */ + BKWIN_ENUM_VALUE("dashdot", PS_DASHDOT) /* _._._._ */ + BKWIN_ENUM_VALUE("dashdotdot", PS_DASHDOTDOT) /* _.._.._ */ + BKWIN_ENUM_END(m_nPenStyle) + BKWIN_DECLARE_ATTRIBUTES_END() + + BKWIN_BEGIN_MSG_MAP() + MSG_WM_PAINT(OnPaint) + BKWIN_END_MSG_MAP() +}; + +////////////////////////////////////////////////////////////////////////// +// Check Box +// +// Usage: This is a check-box +// +class CBkCheckBox : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkCheckBox, "check") + + enum { + CheckBoxSize = 13, + CheckBoxSpacing = 4, + }; + +public: + + CBkCheckBox() + : m_theme() + { + } + + void OnPaint(CDCHandle dc) + { + CRect rcCheckBox = m_rcWindow; + rcCheckBox.right = rcCheckBox.left + CheckBoxSize; + + m_theme.OpenTheme(m_hWndContainer); + + if (m_theme.IsValid()) + { + m_theme.DrawBackground(dc, _GetDrawState(), rcCheckBox); + } + else + { + dc.DrawFrameControl(rcCheckBox, DFC_BUTTON, _GetDrawState()); + } + + m_rcWindow.left += CheckBoxSize + CheckBoxSpacing; + + m_style.m_nTextAlign &= ~DT_BOTTOM; + m_style.m_nTextAlign |= DT_VCENTER; + + __super::OnPaint(dc); + + m_rcWindow.left -= CheckBoxSize + CheckBoxSpacing; + } + + LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam) + { + LPSIZE pSize = (LPSIZE)lParam; + + __super::OnNcCalcSize(bCalcValidRects, lParam); + + pSize->cx += CheckBoxSize + CheckBoxSpacing; + pSize->cy = max(pSize->cy, CheckBoxSize); + + return FALSE; + } + +protected: + + CBkCheckBoxTheme m_theme; + + int m_nState; + + UINT _GetDrawState() + { + DWORD dwState = GetState(); + UINT uState = m_theme.IsValid() ? 0 : DFCS_BUTTONCHECK | DFCS_TRANSPARENT; + + if (m_theme.IsValid()) + { + if (dwState & BkWndState_Check) + { + if (dwState & BkWndState_Disable) + uState = CBS_CHECKEDDISABLED; + else if (dwState & BkWndState_PushDown) + uState = CBS_CHECKEDPRESSED; + else if (dwState & BkWndState_Hover) + uState = CBS_CHECKEDHOT; + else + uState = CBS_CHECKEDNORMAL; + } + else + { + if (dwState & BkWndState_Disable) + uState = CBS_UNCHECKEDDISABLED; + else if (dwState & BkWndState_PushDown) + uState = CBS_UNCHECKEDPRESSED; + else if (dwState & BkWndState_Hover) + uState = CBS_UNCHECKEDHOT; + else + uState = CBS_UNCHECKEDNORMAL; + } + } + else + { + uState = DFCS_BUTTONCHECK | DFCS_TRANSPARENT; + if (dwState & BkWndState_Disable) + uState |= DFCS_INACTIVE; + if (dwState & BkWndState_Hover) + uState |= DFCS_HOT; + if (dwState & BkWndState_PushDown) + uState |= DFCS_PUSHED; + if (dwState & BkWndState_Check) + uState |= DFCS_CHECKED; + } + + return uState; + } + + virtual BOOL NeedRedrawWhenStateChange() + { + return TRUE; + } + + void OnLButtonUp(UINT nFlags, CPoint point) + { + if (IsChecked()) + ModifyState(0, BkWndState_Check); + else + ModifyState(BkWndState_Check, 0); + } + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_UINT_ATTRIBUTE("check", m_nState, FALSE) + BKWIN_DECLARE_ATTRIBUTES_END() + + BKWIN_BEGIN_MSG_MAP() + MSG_WM_PAINT(OnPaint) + MSG_WM_NCCALCSIZE(OnNcCalcSize) + MSG_WM_LBUTTONUP(OnLButtonUp) + BKWIN_END_MSG_MAP() +}; + +////////////////////////////////////////////////////////////////////////// +// Icon Control +// Use src attribute specify a resource id +// +// Usage: +// +class CBkIconWnd : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkIconWnd, "icon") +public: + CBkIconWnd() + : m_uResID(-1) + , m_nSize(16) + , m_bOemIcon(FALSE) + { + + } + + virtual BOOL Load(TiXmlElement* pTiXmlElem) + { + if (!CBkWindow::Load(pTiXmlElem)) + return FALSE; + + _ReloadIcon(); + + return TRUE; + } + + void OnPaint(CDCHandle dc) + { + if (m_uResIDCurrent != m_uResID) + _ReloadIcon(); + + if (NULL == m_theIcon.m_hIcon) + { + if (m_hIcoAttach) + { + CIconHandle ico(m_hIcoAttach); + + ico.DrawIconEx(dc, m_rcWindow.TopLeft(), m_rcWindow.Size()); + } + } + else + m_theIcon.DrawIconEx(dc, m_rcWindow.TopLeft(), m_rcWindow.Size()); + } + + LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam) + { + LPSIZE pSize = (LPSIZE)lParam; + + pSize->cx = m_nSize; + pSize->cy = m_nSize; + + return TRUE; + } + + void AttachIcon(HICON hIcon) + { + m_hIcoAttach = hIcon; + } + +protected: + + void _ReloadIcon() + { + if (m_theIcon.m_hIcon) + m_theIcon.DestroyIcon(); + + if (m_bOemIcon) + m_theIcon.LoadOEMIcon(MAKEINTRESOURCE(m_uResID)); + else + m_theIcon.LoadIcon(MAKEINTRESOURCE(m_uResID), m_nSize, m_nSize); + + m_uResIDCurrent = m_uResID; + } + + CIcon m_theIcon; + UINT m_uResID; + UINT m_uResIDCurrent; + int m_nSize; + BOOL m_bOemIcon; + HICON m_hIcoAttach; + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_UINT_ATTRIBUTE("src", m_uResID, FALSE) + BKWIN_UINT_ATTRIBUTE("oem", m_bOemIcon, FALSE) + BKWIN_INT_ATTRIBUTE("size", m_nSize, FALSE) + BKWIN_DECLARE_ATTRIBUTES_END() + + BKWIN_BEGIN_MSG_MAP() + MSG_WM_PAINT(OnPaint) + MSG_WM_NCCALCSIZE(OnNcCalcSize) + BKWIN_END_MSG_MAP() +}; + +////////////////////////////////////////////////////////////////////////// +// Radio Box +// +// Usage: This is a check-box +// +class CBkRadioBox : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkRadioBox, "radio") + + enum { + RadioBoxSize = 12, + RadioBoxSpacing = 2, + }; + +public: + + CBkRadioBox() + : m_theme() + { + } + + ~CBkRadioBox() + { + BkWnds::UnregisterRadioGroup(this, m_strGroup); + } + + virtual BOOL Load(TiXmlElement* pTiXmlElem) + { + if (!CBkWindow::Load(pTiXmlElem)) + return FALSE; + + return BkWnds::RegisterRadioGroup(this, m_strGroup);; + } + + void OnPaint(CDCHandle dc) + { + CRect rcCheckBox(0, 0, RadioBoxSize, RadioBoxSize); + + rcCheckBox.MoveToXY(m_rcWindow.left, m_rcWindow.top + (m_rcWindow.Height() - RadioBoxSize) / 2); + + m_theme.OpenTheme(m_hWndContainer); + + if (m_theme.IsValid()) + { + m_theme.DrawBackground(dc, _GetDrawState(), rcCheckBox); + } + else + { + dc.DrawFrameControl(rcCheckBox, DFC_BUTTON, _GetDrawState()); + } + + m_rcWindow.left += RadioBoxSize + RadioBoxSpacing; + + m_style.m_nTextAlign &= ~DT_BOTTOM; + m_style.m_nTextAlign |= DT_VCENTER | DT_SINGLELINE; + + __super::OnPaint(dc); + + m_rcWindow.left -= RadioBoxSize + RadioBoxSpacing; + } + + LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam) + { + LPSIZE pSize = (LPSIZE)lParam; + + __super::OnNcCalcSize(bCalcValidRects, lParam); + + pSize->cx += RadioBoxSize + RadioBoxSpacing; + pSize->cy = max(pSize->cy, RadioBoxSize); + + return FALSE; + } + +protected: + + CBkRadioBoxTheme m_theme; + + int m_nState; + CStringA m_strGroup; + + UINT _GetDrawState() + { + DWORD dwState = GetState(); + UINT uState = m_theme.IsValid() ? 0 : DFCS_BUTTONRADIO | DFCS_TRANSPARENT; + + if (m_theme.IsValid()) + { + if (dwState & BkWndState_Check) + { + if (dwState & BkWndState_Disable) + uState = RBS_CHECKEDDISABLED; + else if (dwState & BkWndState_PushDown) + uState = RBS_CHECKEDPRESSED; + else if (dwState & BkWndState_Hover) + uState = RBS_CHECKEDHOT; + else + uState = RBS_CHECKEDNORMAL; + } + else + { + if (dwState & BkWndState_Disable) + uState = RBS_UNCHECKEDDISABLED; + else if (dwState & BkWndState_PushDown) + uState = RBS_UNCHECKEDPRESSED; + else if (dwState & BkWndState_Hover) + uState = RBS_UNCHECKEDHOT; + else + uState = RBS_UNCHECKEDNORMAL; + } + } + else + { + uState = DFCS_BUTTONRADIO | DFCS_TRANSPARENT; + if (dwState & BkWndState_Disable) + uState |= DFCS_INACTIVE; + if (dwState & BkWndState_Hover) + uState |= DFCS_HOT; + if (dwState & BkWndState_PushDown) + uState |= DFCS_PUSHED; + if (dwState & BkWndState_Check) + uState |= DFCS_CHECKED; + } + + return uState; + } + + virtual BOOL NeedRedrawWhenStateChange() + { + return TRUE; + } + + void OnLButtonUp(UINT nFlags, CPoint point) + { + BkWnds::SelectRadio(this, m_strGroup, NULL); + //ModifyState(BkWndState_Check, 0); + } + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_UINT_ATTRIBUTE("check", m_nState, FALSE) + BKWIN_STRING_ATTRIBUTE("group", m_strGroup, FALSE) + BKWIN_DECLARE_ATTRIBUTES_END() + + BKWIN_BEGIN_MSG_MAP() + MSG_WM_PAINT(OnPaint) + MSG_WM_NCCALCSIZE(OnNcCalcSize) + MSG_WM_LBUTTONUP(OnLButtonUp) + BKWIN_END_MSG_MAP() +}; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkwin/bkwnddlg.h b/Client/Client/GUI/BKWin/bkwin/bkwnddlg.h new file mode 100644 index 00000000..77a08008 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkwnddlg.h @@ -0,0 +1,79 @@ +#pragma once + +#include "bkwndpanel.h" + +class CBkDialog + : public CBkPanel +{ + BKOBJ_DECLARE_CLASS_NAME(CBkDialog, "dlg") + +public: + + void OnWindowPosChanged(LPWINDOWPOS lpWndPos) + { + CBkWindow::OnWindowPosChanged(lpWndPos); + + _RepositionChilds(); + } + + virtual BOOL Load(TiXmlElement* pTiXmlElem) + { + BOOL bRet = __super::Load(pTiXmlElem); + + return bRet; + } + + virtual void RepositionChilds() + { + _RepositionChilds(); + } + + virtual void RepositionChild(CBkWindow *pBkWndChild) + { + BKDLG_POSITION dlgPos; + WINDOWPOS WndPos = {0}; + CRect rcDlg = m_rcWindow; + + rcDlg.DeflateRect(m_style.m_nMarginX, m_style.m_nMarginY); + + pBkWndChild->GetDlgPosition(&dlgPos); + + if (dlgPos.Left.bCenter) + WndPos.x = rcDlg.left + rcDlg.Width() / 2 + (dlgPos.Left.bMinus ? -1 : 1) * dlgPos.Left.nPos; + else if (dlgPos.Left.bMinus) + WndPos.x = rcDlg.left + rcDlg.Width() - dlgPos.Left.nPos; + else + WndPos.x = rcDlg.left + dlgPos.Left.nPos; + + if (dlgPos.Top.bCenter) + WndPos.y = rcDlg.top + rcDlg.Height() / 2 + (dlgPos.Top.bMinus ? -1 : 1) * dlgPos.Top.nPos; + else if (dlgPos.Top.bMinus) + WndPos.y = rcDlg.top + rcDlg.Height() - dlgPos.Top.nPos; + else + WndPos.y = rcDlg.top + dlgPos.Top.nPos; + + WndPos.cx = rcDlg.Width(); + WndPos.cy = rcDlg.Height(); + pBkWndChild->BkSendMessage(WM_WINDOWPOSCHANGED, NULL, (LPARAM)&WndPos); + } + +protected: + + void _RepositionChilds() + { + POSITION pos = m_lstWndChild.GetHeadPosition(); + + while (pos != NULL) + { + CBkWindow *pBkWndChild = m_lstWndChild.GetNext(pos); + + RepositionChild(pBkWndChild); + } + } + +protected: + + BKWIN_BEGIN_MSG_MAP() + MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged) + BKWIN_END_MSG_MAP() +}; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkwin/bkwnddlgfile.h b/Client/Client/GUI/BKWin/bkwin/bkwnddlgfile.h new file mode 100644 index 00000000..4a6d931c --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkwnddlgfile.h @@ -0,0 +1,61 @@ +#pragma once + +#include "bkwnddlg.h" + +/* +ʹһԴXMLԪ + + +*/ +class CBkDialogFile + : public CBkDialog +{ + BKOBJ_DECLARE_CLASS_NAME(CBkDialogFile, "dlgfile") + +public: + + virtual BOOL Load(TiXmlElement* pTiXmlElem) + { + if (!CBkWindow::Load(pTiXmlElem)) + return FALSE; + + CStringA strSrc = pTiXmlElem->Attribute("src"); + + ATLASSERT( !strSrc.IsEmpty() ); + + if (strSrc.IsEmpty()) + return FALSE; + + CStringA strXML; + BOOL bRet = FALSE; + bRet = BkResManager::LoadResource(CString(strSrc),strXML); + if (!bRet) + { + UINT uResId = atoi(strSrc); + bRet = BkResManager::LoadResource(uResId,strXML); + } + + ATLASSERT(bRet); + + if (!bRet) + return TRUE; + + TiXmlDocument xmlDoc; + { + xmlDoc.Parse(strXML, NULL, TIXML_ENCODING_UTF8); + } + if (xmlDoc.Error()) + { + ATLASSERT(NULL); + return FALSE; + } + + TiXmlElement *pSubTiElement = xmlDoc.RootElement(); + bRet = __super::LoadChilds(pSubTiElement); + + return bRet; + } + +protected: + +}; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkwin/bkwndedit.h b/Client/Client/GUI/BKWin/bkwin/bkwndedit.h new file mode 100644 index 00000000..7f60406a --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkwndedit.h @@ -0,0 +1,611 @@ +////////////////////////////////////////////////////////////////////////// +// File Name: bkwndedit.h +// Description: Edit Control +// Creator: skylly +// Version: 2012.3.25 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "bkwndnotify.h" + +class CBkEdit : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkEdit, "edit") + + CBkEdit() : + m_pImg(NULL) + , m_dwFont(0) + , hPenNormal(NULL) + , hPenFocus(NULL) + , m_hWndEditor(NULL) + , m_hBkBrush(NULL) + , m_bFocused(false) + , m_bMouseOver(false) + , m_bEnabled(true) //֮ǰ˸ֵ + , m_uMaxChar(0) + , m_bReadOnly(FALSE) + , m_bNumberMode(false) + , m_bMultiLine(false) + , m_bForever(true) //Ƿ + , m_bPasswordMode(FALSE) + , m_cPasswordChar(_T('*')) + , m_strGroup(_T("")) + { + } + ~CBkEdit() + { + // BkWnds::UnregisterEditGroup(this, m_strGroup); + } + bool IsEnabled() + { + return m_bEnabled; + } + + BOOL IsPasswordMode() + { + return m_bPasswordMode; + } + + TCHAR GetPasswordChar() const + { + return m_cPasswordChar; + } + + // Create children + virtual BOOL Load(TiXmlElement* pTiXmlElem) + { + if (!CBkWindow::Load(pTiXmlElem)) + return FALSE; + return TRUE; //BkWnds::RegisterEditGroup(this, m_strGroup); + } + + void OnDestroy() + { + + } + + HRESULT SetInnerText(LPCTSTR pText) + { + __super::SetInnerText(pText); + if (m_hWndEditor) + { + ::SetWindowText(m_hWndEditor, pText); + } + return 0; + } + + void DrawBkColor(CDCHandle& dc) + { + COLORREF colorbk = 0; + if (m_bEnabled) + { + colorbk = RGB(255, 255, 255); + } + else + { + colorbk = RGB(244, 244, 244); + } + + dc.SetBkColor(colorbk); + dc.ExtTextOut(0, 0, ETO_OPAQUE, &m_rcWindow, NULL, 0, NULL); + } + + void DrawBkImage(CDCHandle& dc) + { + } + + virtual BOOL NeedRedrawWhenStateChange() + { + return TRUE; + } + + void DrawStatusImage(CDCHandle& dc) + { + if (m_pImg == NULL) + { + // BkPngPool::_LoadPNGImageFromResourceID(3005, m_pImg); + } + + Gdiplus::Graphics graphics(dc); + CRect rc = m_rcWindow; + //СʾͼƬ + graphics.DrawImage(m_pImg, Gdiplus::Rect(rc.left, rc.top, rc.Width(), rc.Height()), 0, 0, rc.Width(), rc.Height(), Gdiplus::UnitPixel); + } + + LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + LRESULT lRes = ::DefWindowProc(m_hWndEditor, uMsg, wParam, lParam); + if (!m_bForever) + ::PostMessage(m_hWndEditor, WM_CLOSE, 0, 0); + return lRes; + } + + LRESULT OnEditChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + // Copy text back + int cchLen = ::GetWindowTextLength(m_hWndEditor) + 1; + LPTSTR pstr = static_cast(_alloca(cchLen * sizeof(TCHAR))); + ATLASSERT(pstr); + if( pstr == NULL ) return 0; + ::GetWindowText(m_hWndEditor, pstr, cchLen); + m_strInnerText = pstr; + //ˢbkwinؼ + NotifyInvalidate(); + //SendNotify(m_pOwner, _T("textchanged")); + return 0; + } + + COLORREF GetTextColor() + { + return RGB(0, 0, 0); + } + + COLORREF GetNativeEditBkColor() + { + return RGB(255, 255, 255); + } + + BOOL StartTrackMouseLeave() + { + TRACKMOUSEEVENT tme = { 0 }; + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = m_hWndEditor; + return _TrackMouseEvent(&tme); + } + + LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + LRESULT lRes = 0; + bHandled = TRUE; + + if (uMsg == WM_KILLFOCUS ) + lRes = OnKillFocus(uMsg, wParam, lParam, bHandled); + else if (uMsg == OCM_COMMAND) + { + if (HIWORD(wParam) == EN_CHANGE) + lRes = OnEditChanged(uMsg, wParam, lParam, bHandled); + else if( HIWORD(wParam) == EN_UPDATE ) + { + RECT rcClient; + ::GetClientRect(m_hWndEditor, &rcClient); + ::InvalidateRect(m_hWndEditor, &rcClient, FALSE); + } + } + else if (uMsg == WM_MOUSELEAVE) + { + m_bMouseOver = false; + //ˢbkwinؼ + NotifyInvalidate(); + } + else if (uMsg == WM_MOUSEMOVE) + { + m_bMouseOver = true; + //ˢbkwinؼ + NotifyInvalidate(); + StartTrackMouseLeave(); + } + else if( uMsg == WM_KEYDOWN && TCHAR(wParam) == VK_RETURN ) + { + //SendNotify(m_pOwner, _T("return")); + } + else if( uMsg == OCM__BASE + WM_CTLCOLOREDIT || uMsg == OCM__BASE + WM_CTLCOLORSTATIC ) + { + if( GetNativeEditBkColor() == 0xFFFFFFFF ) return NULL; + ::SetBkMode((HDC)wParam, TRANSPARENT); + DWORD dwTextColor = GetTextColor(); + ::SetTextColor((HDC)wParam, RGB(GetBValue(dwTextColor),GetGValue(dwTextColor),GetRValue(dwTextColor))); + if( m_hBkBrush == NULL ) { + DWORD clrColor = GetNativeEditBkColor(); + m_hBkBrush = ::CreateSolidBrush(RGB(GetBValue(clrColor), GetGValue(clrColor), GetRValue(clrColor))); + } + return (LRESULT)m_hBkBrush; + } + else + { + bHandled = FALSE; + } + return lRes; + } + + void OnFinalMessage(HWND hWnd) + { + // Clear reference and die + if( m_hBkBrush != NULL ) + ::DeleteObject(m_hBkBrush); + } + + static LRESULT CALLBACK __ControlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + CBkEdit* pThis = NULL; + if (uMsg == WM_NCCREATE) + { + LPCREATESTRUCT lpcs = reinterpret_cast(lParam); + pThis = static_cast(lpcs->lpCreateParams); + ::SetProp(hWnd, _T("WndX"), (HANDLE) pThis); + pThis->m_hWndEditor = hWnd; + } + else + { + pThis = reinterpret_cast(::GetProp(hWnd, _T("WndX"))); + if (uMsg == WM_NCDESTROY && pThis != NULL) + { + LRESULT lRes = ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam); + // if( pThis->m_bSubclassed ) pThis->Unsubclass(); + ::SetProp(hWnd, _T("WndX"), NULL); + pThis->m_hWndEditor = NULL; + pThis->OnFinalMessage(hWnd); + return lRes; + } + } + if (pThis != NULL) + { + BOOL bHandled; + pThis->HandleMessage(uMsg, wParam, lParam, bHandled); + } + return ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam); + } + + LPCTSTR GetSuperClassName() const + { + return WC_EDIT; + } + + LPCTSTR GetWindowClassName() const + { + return _T("BkEdit"); + } + + //עᴰ + bool RegisterSuperclass() + { + // Get the class information from an existing + // window so we can subclass it later on... + WNDCLASSEX wc = { 0 }; + wc.cbSize = sizeof(WNDCLASSEX); + if( !::GetClassInfoEx(NULL, GetSuperClassName(), &wc) ) { + if( !::GetClassInfoEx((HINSTANCE)&__ImageBase, GetSuperClassName(), &wc) ) { + ATLASSERT(!"Unable to locate window class"); + return NULL; + } + } + m_OldWndProc = wc.lpfnWndProc; + wc.lpfnWndProc = &CBkEdit::__ControlProc; + wc.hInstance = (HINSTANCE)&__ImageBase; + wc.lpszClassName = GetWindowClassName(); + ATOM ret = ::RegisterClassEx(&wc); + ATLASSERT(ret!=NULL || ::GetLastError()==ERROR_CLASS_ALREADY_EXISTS); + return ret != NULL || ::GetLastError() == ERROR_CLASS_ALREADY_EXISTS; + } +#define UI_CLASSSTYLE_DIALOG (CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_SAVEBITS) + UINT GetClassStyle() const { return UI_CLASSSTYLE_DIALOG; }; + + // + static LRESULT CALLBACK __WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + CBkEdit* pThis = NULL; + if( uMsg == WM_NCCREATE ) { + LPCREATESTRUCT lpcs = reinterpret_cast(lParam); + pThis = static_cast(lpcs->lpCreateParams); + pThis->m_hWndEditor = hWnd; + ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast(pThis)); + } + else + { + pThis = reinterpret_cast(::GetWindowLongPtr(hWnd, GWLP_USERDATA)); + if( uMsg == WM_NCDESTROY && pThis != NULL ) { + LRESULT lRes = ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam); + ::SetWindowLongPtr(pThis->m_hWndEditor, GWLP_USERDATA, 0L); + //if( pThis->m_bSubclassed ) pThis->Unsubclass(); + pThis->m_hWndEditor = NULL; + pThis->OnFinalMessage(hWnd); + return lRes; + } + } + if (pThis != NULL) + { + BOOL bHandled; + pThis->HandleMessage(uMsg, wParam, lParam, bHandled); + } + return ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam); + } + + // + bool RegisterWindowClass() + { + WNDCLASS wc = { 0 }; + wc.style = GetClassStyle(); + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hIcon = NULL; + wc.lpfnWndProc = &CBkEdit::__WndProc; + wc.hInstance = (HINSTANCE)&__ImageBase; + wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = GetWindowClassName(); + ATOM ret = ::RegisterClass(&wc); + ATLASSERT(ret!=NULL || ::GetLastError()==ERROR_CLASS_ALREADY_EXISTS); + return ret != NULL || ::GetLastError() == ERROR_CLASS_ALREADY_EXISTS; + } + + void InitEditor() + { + if (!m_hWndContainer) + return; + DWORD dwStyle = WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL | ES_AUTOVSCROLL | WS_TABSTOP; + DWORD dwExStyle = 0; + HMENU hMenu = (HMENU)m_uCmdID; + CRect rc = m_rcWindow; + rc.DeflateRect(2, 2, 2, 2); //߿ + if (IsPasswordMode()) + dwStyle |= ES_PASSWORD; + + if (GetSuperClassName() != NULL && !RegisterSuperclass()) return; + if (GetSuperClassName() == NULL && !RegisterWindowClass()) return; + m_hWndEditor = ::CreateWindowEx(dwExStyle, GetWindowClassName(), NULL, dwStyle, rc.left, rc.top, rc.Width(),rc.Height(), m_hWndContainer,(HMENU)hMenu,(HINSTANCE)&__ImageBase, this); + + if (!m_hWndEditor) + { + DWORD dd = GetLastError(); + ATLVERIFY(FALSE); + return; + } + + ::SendMessage(m_hWndEditor, WM_SETFONT, (WPARAM)((HFONT)BkFontPool::GetFont(LOWORD(m_dwFont))), MAKELPARAM(TRUE, 0)); + + int cchMax = 100; + ::SendMessage(m_hWndEditor, EM_LIMITTEXT, (WPARAM)(cchMax), 0L); + if (IsPasswordMode()) + ::SendMessage(m_hWndEditor, EM_SETPASSWORDCHAR, (WPARAM)(UINT)(GetPasswordChar()), 0L); + ::SetWindowText(m_hWndEditor, m_strInnerText); + ::SendMessage(m_hWndEditor, EM_SETMODIFY, (WPARAM)(UINT)(FALSE), 0L); + ::SendMessage(m_hWndEditor, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELPARAM(0, 0)); + bool bEnabled = IsEnabled(); + ::EnableWindow(m_hWndEditor, bEnabled); + BOOL bReadOnly = m_bReadOnly; + ::SendMessage(m_hWndEditor, EM_SETREADONLY, (WPARAM)(BOOL)(bReadOnly), 0L); + ::ShowWindow(m_hWndEditor, SW_SHOWNOACTIVATE);// + //::SetFocus(m_hWndEditor); + } + + void DrawText(CDCHandle& dc) + { + CString sText = m_strInnerText; + if (m_bPasswordMode ) + {//ʾ* + sText.Empty(); + LPCTSTR p = m_strInnerText.GetBuffer(0); + while( *p != _T('\0') ) + { + sText += m_cPasswordChar; + p = ::CharNext(p); + } + } + + HFONT hftOld = dc.SelectFont(BkFontPool::GetFont(LOWORD(m_dwFont))); + CRect rcText = m_rcWindow; + rcText.DeflateRect(2, 2, 2, 2); //߿ (2ر߿) + dc.DrawText(sText, sText.GetLength(), rcText, DT_SINGLELINE | DT_VCENTER); + dc.SelectFont(hftOld); + } + + void DrawBtn(CDCHandle& dc) + { + } + + void DrawBorder(CDCHandle& dc) + { + COLORREF colorbd = 0; + CRect rc = m_rcWindow; + HPEN hPenOld = NULL; + if (m_bMouseOver) + { + colorbd = RGB(133, 228, 255); + if (!hPenFocus) + { + hPenFocus = CreatePen(PS_INSIDEFRAME, 2, colorbd); + } + hPenOld = dc.SelectPen(hPenFocus); + } + else + { + colorbd = RGB(78, 160, 209); + if (!hPenNormal) + { + hPenNormal = CreatePen(PS_INSIDEFRAME, 1, colorbd); //colorbd + } + hPenOld = dc.SelectPen(hPenNormal); + } + HBRUSH hBrushOld = dc.SelectBrush((HBRUSH)::GetStockObject(HOLLOW_BRUSH)); + dc.Rectangle(rc); + dc.SelectBrush(hBrushOld); + //CBrush brush1(::CreateSolidBrush(colorbd)); + //dc.FrameRect( &rc, brush1); + dc.SelectPen(hPenOld); + } + + // ѭ򣺱ɫ->ͼ->״̬ͼ->ı->߿ + void OnPaint(CDCHandle dc) + { + //dc.SetBkMode(TRANSPARENT); + DrawBkColor(dc); + DrawBkImage(dc); + DrawStatusImage(dc); + DrawText(dc); + DrawBtn( dc ); + DrawBorder(dc); + } + + void SetFocus() + { + m_bFocused = true; + ::SetFocus(m_hWndEditor); + } + + void OnLButtonDown(UINT nFlags, CPoint point) + { + if( IsEnabled() ) + { + if (m_hWndEditor == NULL) + { + InitEditor(); + } + m_bFocused = true; + if (m_rcWindow.PtInRect(point) ) + { + int nSize = GetWindowTextLength(m_hWndEditor); + if( nSize == 0 ) + nSize = 1; + + ::SendMessage(m_hWndEditor, EM_SETSEL, (0), (nSize)); + } + }//if( IsEnabled() ) + } + + void OnMouseMove(UINT nFlags, CPoint point) + { + if (m_bEnabled) + { + m_bMouseOver = true; + } + } + + HWND _GetRealWindow() + { + if (m_bForever && m_hWndEditor == NULL) + { + InitEditor(); + } + return m_hWndEditor; + } + + void OnWindowPosChanged(LPWINDOWPOS lpWndPos) + { + CRect rcOldWnd = m_rcWindow; + + __super::OnWindowPosChanged(lpWndPos); + + if (rcOldWnd != m_rcWindow) + { + //ƶλ + HWND hWndReal = _GetRealWindow(); + //by skylly úӴŵǰӴǰ + + CRect rc = m_rcWindow; + rc.DeflateRect(2, 2, 2, 2); //߿ + //::SetWindowPos(hWndReal, HWND_TOP, m_rcWindow.left, m_rcWindow.top, m_rcWindow.Width(), m_rcWindow.Height(), SWP_NOREDRAW); + ::SetWindowPos(hWndReal, HWND_TOP, rc.left, rc.top, rc.Width(), rc.Height(), SWP_NOZORDER | SWP_NOREDRAW); + + BKNMREALWNDRESIZED nms; + nms.hdr.code = BKNM_REALWND_RESIZED; + nms.hdr.hwndFrom = m_hWndContainer; + nms.hdr.idFrom = ::GetDlgCtrlID(m_hWndContainer); + nms.uItemID = GetCmdID(); + nms.rcWnd = rc; + + ::SendMessage(m_hWndContainer, WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + + //ʾ + if (::IsWindowVisible(hWndReal)) + { + CRect rcUpdate = rc; + rcUpdate.MoveToXY(0, 0); + //::RedrawWindow(_GetRealWindow(), rcUpdate, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + //::RedrawWindow(hWndReal, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ERASENOW); + ::InvalidateRect(hWndReal, NULL, TRUE); + ::SetWindowPos(hWndReal, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_FRAMECHANGED); + } + } + } + + void ShowRealWindow(BOOL bShow) + { + CRect rc; + GetClientRect(_GetRealWindow(), rc); + if (rc != m_rcWindow) + { + rc = m_rcWindow; + rc.DeflateRect(2, 2, 2, 2); //߿ + ::SetWindowPos(_GetRealWindow(), HWND_TOP, rc.left, rc.top, rc.Width(), rc.Height(), SWP_NOZORDER | SWP_NOREDRAW); + } + ::ShowWindow(_GetRealWindow(), bShow ? SW_SHOW : SW_HIDE); + } + + void OnShowWindow(BOOL bShow, UINT nStatus) + { + __super::OnShowWindow(bShow, nStatus); + + if (bShow) + { + // ڻ߸ڵĸأҪTabлʾʵ + CBkWindow* pWnd = this; + + while (TRUE) + { + pWnd = BkWnds::GetWindow(pWnd->GetParent()); + + if (NULL == pWnd) + break; + + if (!pWnd->IsVisible()) + return; + } + } + + ShowRealWindow(bShow); + } + + void OnMouseLeave() + { + m_bMouseOver = false; + } + + virtual void SetCursor() + { + ::SetCursor(::LoadCursor(NULL, (m_bMouseOver) ? IDC_IBEAM : IDC_ARROW)); + } +protected: + HBRUSH m_hBkBrush; //ˢ + HPEN hPenNormal; //pen + HPEN hPenFocus; //pen + Gdiplus::Image* m_pImg; //ͼ + WNDPROC m_OldWndProc; //ԭʼڴ + DWORD m_dwFont; // + HWND m_hWndEditor; //ؼ + BOOL m_bPasswordMode; //ģʽ + TCHAR m_cPasswordChar; // + + bool m_bEnabled; //Ƿ񼤻 + bool m_bFocused; //Ƿ񽹵 + bool m_bMouseOver; //Ƿͣ + + // + CStringA m_strGroup; + + bool m_bForever; //Ƿ + + //漸ʱδõ + BOOL m_bReadOnly; //Ƿֻ + bool m_bNumberMode; //Ƿ + bool m_bMultiLine; //Ƿ + UINT m_uMaxChar; //ַ + +protected: + BKWIN_BEGIN_MSG_MAP() + MSG_WM_PAINT(OnPaint) + MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged) + MSG_WM_LBUTTONDOWN(OnLButtonDown) + MSG_WM_MOUSEMOVE(OnMouseMove) + MSG_WM_MOUSELEAVE(OnMouseLeave) + MSG_WM_SHOWWINDOW(OnShowWindow) + BKWIN_END_MSG_MAP() + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_HEX_ATTRIBUTE("defaultfont", m_dwFont, FALSE) + BKWIN_INT_ATTRIBUTE("password", m_bPasswordMode, FALSE) + BKWIN_INT_ATTRIBUTE("readonly", m_bReadOnly, FALSE) + + BKWIN_DECLARE_ATTRIBUTES_END() +}; diff --git a/Client/Client/GUI/BKWin/bkwin/bkwndnotify.h b/Client/Client/GUI/BKWin/bkwin/bkwndnotify.h new file mode 100644 index 00000000..23b1aac2 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkwndnotify.h @@ -0,0 +1,118 @@ +#pragma once + +////////////////////////////////////////////////////////////////////////// +// Notify Messages For BkWin User + +#define MSG_BK_NOTIFY(ctrlid) NOTIFY_ID_HANDLER_EX(ctrlid, OnBkNotify_##ctrlid) + +#define BK_NOTIFY_MAP(ctrlid) \ + LRESULT OnBkNotify_##ctrlid(LPNMHDR pnmh) \ + { \ + UINT_PTR uCode = pnmh->code; \ + +#define BK_NOTIFY_MAP_END() \ + SetMsgHandled(FALSE); \ + return FALSE; \ + } \ + +#define BK_CHAIN_NOTIFY_MAP(ChainClass, ctrlid) \ + if(ChainClass::OnBkNotify_##ctrlid(pnmh)) \ + return TRUE; \ + +// Command Notify +#define BKNM_COMMAND 1 + +// void OnBkItemCommand() +#define BK_NOTIFY_ID_COMMAND(itemid, func) \ + if (BKNM_COMMAND == uCode && itemid == ((LPBKNMCOMMAND)pnmh)->uItemID) \ + { \ + func(); \ + return TRUE; \ + } \ + +#define BK_NOTIFY_ID_COMMAND_EX(itemidbegin, itemidend, func) \ + if (BKNM_COMMAND == uCode && itemidbegin <= ((LPBKNMCOMMAND)pnmh)->uItemID \ + && itemidend >= ((LPBKNMCOMMAND)pnmh)->uItemID ) \ + { \ + func(((LPBKNMCOMMAND)pnmh)->uItemID); \ + return TRUE; \ + } \ +// void OnBkCommand(UINT uItemID, LPCSTR szItemClass) +#define BK_NOTIFY_COMMAND(func) \ + if (BKNM_COMMAND == uCode) \ + { \ + func(((LPBKNMCOMMAND)pnmh)->uItemID, ((LPBKNMCOMMAND)pnmh)->szItemClass); \ + return TRUE; \ + } \ + +typedef struct _BKNMCOMMAND +{ + NMHDR hdr; + UINT uItemID; + LPCSTR szItemClass; +} BKNMCOMMAND, *LPBKNMCOMMAND; + +// Real Window Resized Notify +#define BKNM_REALWND_RESIZED 2 + +// void OnBkRealWndResized(CRect rcWnd) +#define BK_NOTIFY_REALWND_RESIZED(itemid, func) \ + if (BKNM_REALWND_RESIZED == uCode && itemid == ((LPBKNMREALWNDRESIZED)pnmh)->uItemID) \ + { \ + func(((LPBKNMREALWNDRESIZED)pnmh)->rcWnd); \ + return TRUE; \ + } \ + +typedef struct _BKNMREALWNDRESIZED +{ + NMHDR hdr; + UINT uItemID; + CRect rcWnd; +} BKNMREALWNDRESIZED, *LPBKNMREALWNDRESIZED; + +// Mouse Hover Notify +// void OnBkMouseHover() +#define BKNM_MOUSEHOVER 3 + +#define BK_NOTIFY_MOUSEHOVER(func) \ + if (BKNM_MOUSEHOVER == uCode) \ + { \ + func(); \ + return TRUE; \ + } \ + +// Mouse Leave Notify +// void OnBkMouseLeave() +#define BKNM_MOUSELEAVE 4 + +#define BK_NOTIFY_MOUSELEAVE(func) \ + if (BKNM_MOUSELEAVE == uCode) \ + { \ + func(); \ + return TRUE; \ + } \ + +// Tab Sel Change Notify +#define BKNM_TAB_SELCHANGE 5 + +typedef struct _BKNMTABSELCHANGE +{ + NMHDR hdr; + UINT uTabID; + UINT uTabItemIDNew; + UINT uTabItemIDOld; + BOOL bCancel; +} BKNMTABSELCHANGE, *LPBKNMTABSELCHANGE; + +// BOOL OnBkTabSelChange(int nTabItemIDOld, int nTabItemIDNew) +#define BK_NOTIFY_TAB_SELCHANGE(tabid, func) \ + if (BKNM_TAB_SELCHANGE == uCode && tabid == ((LPBKNMTABSELCHANGE)pnmh)->uTabID) \ + { \ + BOOL bRet = func( \ + ((LPBKNMTABSELCHANGE)pnmh)->uTabItemIDOld, \ + ((LPBKNMTABSELCHANGE)pnmh)->uTabItemIDNew); \ + if (!bRet) \ + ((LPBKNMTABSELCHANGE)pnmh)->bCancel = TRUE; \ + return TRUE; \ + } \ + diff --git a/Client/Client/GUI/BKWin/bkwin/bkwndpanel.h b/Client/Client/GUI/BKWin/bkwin/bkwndpanel.h new file mode 100644 index 00000000..543847ce --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkwndpanel.h @@ -0,0 +1,730 @@ +////////////////////////////////////////////////////////////////////////// +// File Name: bkwndpanel.h +// Description: CBkPanel Definition, Virtual Container of BkWindows +// Creator: Zhang Xiaoxuan +// Version: 2009.04.28 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "bkwndcmnctrl.h" +#include "bkwndrichtxt.h" +#include "bkwndedit.h" + +class CBkPanel : public CBkContainerWnd +{ + BKOBJ_DECLARE_CLASS_NAME(CBkPanel, "div") + +public: + CBkPanel() + : m_bOnlyDrawChild(FALSE) + { + } + +protected: + + CAtlList m_lstWndChild; + BOOL m_bOnlyDrawChild; + +protected: + + CBkWindow* _CreateBkWindowByName(LPCSTR lpszName); + + // Vert-Align Process + // Called after this line composed + void _ProcessLineVAlign(POSITION posLineStart, POSITION posLineEnd, LONG lLineTop, LONG lLineBottom) + { + CRect rcChild; + + if (m_uVAlign == VAlign_Top) + return; + + POSITION posLine = posLineStart; + int nNewTop = 0; + + while (posLine != posLineEnd) + { + CBkWindow *pBkWndLine = m_lstWndChild.GetNext(posLine); + + pBkWndLine->GetRect(rcChild); + + if (m_uVAlign == VAlign_Middle) + nNewTop = lLineTop + (lLineBottom - lLineTop - rcChild.Height()) / 2; + else if(m_uVAlign == VAlign_Bottom) + nNewTop = lLineBottom - rcChild.Height(); + + rcChild.MoveToY(nNewTop); + pBkWndLine->Move(rcChild); + } + } + + // Composing ..... + void _ComposingPanel(LPWINDOWPOS lpWndPos) + { + POSITION pos = m_lstWndChild.GetHeadPosition(), posPrev = NULL, posThisLineStart = NULL; + WINDOWPOS WndPos; + CRect rcChild; + + LONG lNextLineTop = lpWndPos->y + m_style.m_nMarginY + m_style.m_nLineSpacing; + LONG lMaxRight = m_rcWindow.right; + LONG lMaxBottom = m_rcWindow.top; + BOOL bFirstInBlock = TRUE, bNewLine = FALSE; + + memcpy(&WndPos, lpWndPos, sizeof(WINDOWPOS)); + + WndPos.x += m_style.m_nMarginX; + WndPos.y += m_style.m_nMarginY; + WndPos.cx = ((GetPositionType() & SizeX_Specify) ? m_lSpecifyWidth : WndPos.cx) - m_style.m_nMarginX * 2; + WndPos.cy -= m_style.m_nMarginY * 2; + + while (pos != NULL) + { + posPrev = pos; + + CBkWindow *pBkWndChild = m_lstWndChild.GetNext(pos); + + if (!pBkWndChild->IsVisible()) + continue; + + if (Position_Float & pBkWndChild->GetPositionType()) + continue; + + if (bFirstInBlock) + posThisLineStart = posPrev; + + // Return + if (pBkWndChild->IsClass(CBkReturn::GetClassName())) + { + _ProcessLineVAlign(posThisLineStart, posPrev, WndPos.y, lNextLineTop); + posThisLineStart = posPrev; + + WndPos.x = lpWndPos->x + m_style.m_nMarginX; + WndPos.y = lNextLineTop + m_style.m_nLineSpacing; + WndPos.cx = ((GetPositionType() & SizeX_Specify) ? m_lSpecifyWidth : lpWndPos->cx) - m_style.m_nMarginX * 2; + WndPos.cy = lpWndPos->y + lpWndPos->cy - WndPos.y - m_style.m_nMarginY; + + bFirstInBlock = FALSE; + + continue; + } + + if (WndPos.cx == 0) + { + bNewLine = TRUE; + } + else + { + pBkWndChild->BkSendMessage(WM_WINDOWPOSCHANGED, NULL, (LPARAM)&WndPos); + pBkWndChild->GetRect(rcChild); + + bNewLine = FALSE; + + // Is this line full? + if ((rcChild.right > WndPos.x + WndPos.cx || rcChild.right <= rcChild.left) && !bFirstInBlock) + { + bNewLine = TRUE; + _ProcessLineVAlign(posThisLineStart, posPrev, WndPos.y, lNextLineTop); + posThisLineStart = posPrev; + } + } + + bFirstInBlock = FALSE; + + if (bNewLine) + { + // Reposition this control to next line + WndPos.x = lpWndPos->x + m_style.m_nMarginX; + WndPos.y = lNextLineTop + m_style.m_nLineSpacing; + WndPos.cx = ((GetPositionType() & SizeX_Specify) ? m_lSpecifyWidth : lpWndPos->cx) - m_style.m_nMarginX * 2; + WndPos.cy = lpWndPos->y + lpWndPos->cy - WndPos.y - m_style.m_nMarginY; + + pBkWndChild->BkSendMessage(WM_WINDOWPOSCHANGED, NULL, (LPARAM)&WndPos); + pBkWndChild->GetRect(rcChild); + } + + // Next control position + WndPos.x += rcChild.Width() + m_style.m_nSpacing; + WndPos.cx -= rcChild.Width() + m_style.m_nSpacing; + + if (lNextLineTop < rcChild.bottom) + { + lNextLineTop = rcChild.bottom; + } + + if (lMaxRight < rcChild.right + m_style.m_nMarginX) + { + lMaxRight = rcChild.right + m_style.m_nMarginX; + } + } + + // Process last line + _ProcessLineVAlign(posThisLineStart, NULL, WndPos.y, lNextLineTop); + + switch (GetPositionType() & SizeX_Mask) + { + case SizeX_FitParent: + m_rcWindow.right = lpWndPos->x + lpWndPos->cx; + break; + case SizeX_FitContent: + m_rcWindow.right = lMaxRight; + break; + case SizeX_Specify: + m_rcWindow.right = lpWndPos->x + m_lSpecifyWidth; + break; + } + + switch (GetPositionType() & SizeY_Mask) + { + case SizeY_FitParent: + m_rcWindow.bottom = lpWndPos->y + lpWndPos->cy; + break; + case SizeY_FitContent: + m_rcWindow.bottom = lNextLineTop + m_style.m_nMarginY; + break; + case SizeY_Specify: + m_rcWindow.bottom = lpWndPos->y + m_lSpecifyHeight; + break; + } + + // Process float children here + pos = m_lstWndChild.GetHeadPosition(); + + while (pos != NULL) + { + posPrev = pos; + + CBkWindow *pBkWndChild = m_lstWndChild.GetNext(pos); + + if (!pBkWndChild->IsVisible()) + continue; + + if (0 == (Position_Float & pBkWndChild->GetPositionType())) + continue; + + memcpy(&WndPos, lpWndPos, sizeof(WINDOWPOS)); + + WndPos.x += m_style.m_nMarginX; + WndPos.y += m_style.m_nMarginY; + WndPos.cx = ((GetPositionType() & SizeX_Specify) ? m_lSpecifyWidth : WndPos.cx) - m_style.m_nMarginX * 2; + WndPos.cy -= m_style.m_nMarginY * 2; + + pBkWndChild->BkSendMessage(WM_WINDOWPOSCHANGED, NULL, (LPARAM)&WndPos); + pBkWndChild->GetRect(rcChild); + + if (Align_Right & pBkWndChild->GetAlign()) + { + WndPos.x = WndPos.x + WndPos.cx - rcChild.Width(); + } + else if (Align_Center & pBkWndChild->GetAlign()) + { + WndPos.x = WndPos.x + (WndPos.cx - rcChild.Width()) / 2; + } + + if (VAlign_Bottom & pBkWndChild->GetAlign()) + { + WndPos.y = WndPos.y + WndPos.cy - rcChild.Height(); + } + else if (VAlign_Middle & pBkWndChild->GetAlign()) + { + WndPos.y = WndPos.y + (WndPos.cy - rcChild.Height()) / 2; + } + + WndPos.cx = rcChild.Width(); + WndPos.cy = rcChild.Height(); + + pBkWndChild->BkSendMessage(WM_WINDOWPOSCHANGED, NULL, (LPARAM)&WndPos); + + } + } + +public: + + BOOL LoadChilds(TiXmlElement* pTiXmlChildElem) + { + BkSendMessage(WM_DESTROY); + + BOOL bVisible = IsVisible(TRUE); + + for (TiXmlElement* pXmlChild = pTiXmlChildElem; NULL != pXmlChild; pXmlChild = pXmlChild->NextSiblingElement()) + { + CBkWindow *pNewChildWindow = _CreateBkWindowByName(pXmlChild->Value()); + if (!pNewChildWindow) + continue; + +// int nID = 0; +// pXmlChild->Attribute("id", &nID); + + pNewChildWindow->SetParent(m_hBkWnd); + pNewChildWindow->SetContainer(m_hWndContainer); + pNewChildWindow->Load(pXmlChild); + +// if (pNewChildWindow->IsVisible()) +// pNewChildWindow->BkSendMessage(WM_SHOWWINDOW, bVisible); + + m_lstWndChild.AddTail(pNewChildWindow); + } + + return TRUE; + } + + // Create children + virtual BOOL Load(TiXmlElement* pTiXmlElem) + { + if (!CBkWindow::Load(pTiXmlElem)) + return FALSE; + + return LoadChilds(pTiXmlElem->FirstChildElement()); + } + + // Hittest children + virtual HBKWND BkGetHWNDFromPoint(POINT ptHitTest, BOOL bOnlyText) + { + if (m_rcWindow.PtInRect(ptHitTest)) + { + if (m_bOnlyDrawChild) + return m_hBkWnd; + + HBKWND hBkWndChild = NULL; + + POSITION pos = m_lstWndChild.GetTailPosition(); + + while (pos != NULL) + { + CBkWindow *pBkWndChild = m_lstWndChild.GetPrev(pos); + if (!pBkWndChild->IsVisible() || pBkWndChild->IsTransparent()) + continue; + + if (Position_Float == (pBkWndChild->GetPositionType() & Position_Float)) + { + hBkWndChild = pBkWndChild->BkGetHWNDFromPoint(ptHitTest, bOnlyText); + + if (hBkWndChild) + break; + } + } + + if (hBkWndChild) + return hBkWndChild; + + pos = m_lstWndChild.GetTailPosition(); + + while (pos != NULL) + { + CBkWindow *pBkWndChild = m_lstWndChild.GetPrev(pos); + if (!pBkWndChild->IsVisible() || pBkWndChild->IsTransparent()) + continue; + + if (0 == (pBkWndChild->GetPositionType() & Position_Float)) + { + hBkWndChild = pBkWndChild->BkGetHWNDFromPoint(ptHitTest, bOnlyText); + + if (hBkWndChild) + break; + } + } + + if (hBkWndChild) + return hBkWndChild; + else + return m_hBkWnd; + } + else + return NULL; + } + + void SetContainer(HWND hWndContainer) + { + __super::SetContainer(hWndContainer); + + POSITION pos = m_lstWndChild.GetHeadPosition(); + + while (pos != NULL) + { + CBkWindow *pBkWndChild = m_lstWndChild.GetNext(pos); + + if (pBkWndChild) + { + pBkWndChild->SetContainer(hWndContainer); + } + } + } + + CBkWindow* FindChildByCmdID(UINT uCmdID) + { + CBkWindow *pChildFind = NULL; + + POSITION pos = m_lstWndChild.GetHeadPosition(); + + while (pos != NULL) + { + CBkWindow *pBkWndChild = m_lstWndChild.GetNext(pos); + + if (pBkWndChild->GetCmdID() == uCmdID) + return pBkWndChild; + } + + pos = m_lstWndChild.GetHeadPosition(); + + while (pos != NULL) + { + CBkWindow *pBkWndChild = m_lstWndChild.GetNext(pos); + + if (pBkWndChild->IsContainer()) + { + pChildFind = ((CBkContainerWnd *)pBkWndChild)->FindChildByCmdID(uCmdID); + if (pChildFind) + return pChildFind; + } + } + + return NULL; + } + + virtual BOOL RedrawRegion(CDCHandle& dc, CRgn& rgn) + { + if (__super::RedrawRegion(dc, rgn)) + { + POSITION pos = m_lstWndChild.GetHeadPosition(); + BkDCPaint BkDC; + + BeforePaint(dc, BkDC); + + while (pos != NULL) + { + CBkWindow *pBkWndChild = m_lstWndChild.GetNext(pos); + + if (pBkWndChild && pBkWndChild->IsVisible()) + { + pBkWndChild->RedrawRegion(dc, rgn); + } + } + + AfterPaint(dc, BkDC); + + return TRUE; + } + + return FALSE; + } + + void ShowAllRealWindowChilds(BOOL bShow); + + void OnWindowPosChanged(LPWINDOWPOS lpWndPos) + { + // Calc default panel size + CBkWindow::OnWindowPosChanged(lpWndPos); + + _ComposingPanel(lpWndPos); + + } + + int OnCreate(LPCREATESTRUCT /*lpCreateStruct*/) + { + POSITION pos = m_lstWndChild.GetHeadPosition(); + + while (pos != NULL) + { + CBkWindow *pBkWndChild = m_lstWndChild.GetNext(pos); + + pBkWndChild->OnCreate(NULL); + } + + return TRUE; + } + + void OnDestroy() + { + POSITION pos = m_lstWndChild.GetHeadPosition(); + + while (pos != NULL) + { + CBkWindow *pBkWndChild = m_lstWndChild.GetNext(pos); + + pBkWndChild->BkSendMessage(WM_DESTROY); + + delete pBkWndChild; + } + + m_lstWndChild.RemoveAll(); + } + + BOOL OnEraseBkgnd(CDCHandle dc) + { +// CBkWindow::OnEraseBkgnd(dc); + + POSITION pos = m_lstWndChild.GetHeadPosition(); + + BOOL bDisabled = IsDisabled(), bIsChildDisabled = FALSE; + + while (pos != NULL) + { + CBkWindow *pBkWndChild = m_lstWndChild.GetNext(pos); + if (!pBkWndChild->IsVisible()) + continue; + + if (bDisabled) + { + bIsChildDisabled = pBkWndChild->IsDisabled(); + + if (!bIsChildDisabled) + pBkWndChild->ModifyState(BkWndState_Disable, 0); + } + + pBkWndChild->BkSendMessage(WM_ERASEBKGND, (WPARAM)(HDC)dc); + + if (bDisabled && !bIsChildDisabled) + { + pBkWndChild->ModifyState(0, BkWndState_Disable); + } + } + + return TRUE; + } + + void OnPaint(CDCHandle dc) + { + return; + + HFONT hftOld = NULL, hftDraw = NULL; + COLORREF crOld = CLR_INVALID, crOldBg = CLR_INVALID, crDraw = CLR_INVALID; + CRect rcText = m_rcWindow; + int nOldBkMode = OPAQUE; + + if (!m_style.m_strSkinName.IsEmpty()) + nOldBkMode = dc.SetBkMode(TRANSPARENT); + if (CLR_INVALID != m_style.m_crBg) + crOldBg = dc.SetBkColor(m_style.m_crBg); + + if (m_style.m_ftText) + hftDraw = m_style.m_ftText; + + if (m_style.m_crText != CLR_INVALID) + crDraw = m_style.m_crText; + + if (BkWndState_Hover == (GetState() & BkWndState_Hover)) + { + if (m_style.m_ftHover) + hftDraw = m_style.m_ftHover; + + if (m_style.m_crHoverText != CLR_INVALID) + crDraw = m_style.m_crHoverText; + } + + if (hftDraw) + hftOld = dc.SelectFont(hftDraw); + + if (crDraw != CLR_INVALID) + crOld = dc.SetTextColor(crDraw); +// int nOldBkMode = OPAQUE; +// COLORREF crOldBg = CLR_INVALID; +// COLORREF crOldText = CLR_INVALID; +// +// if (!m_style.m_strSkinName.IsEmpty()) +// nOldBkMode = dc.SetBkMode(TRANSPARENT); +// if (CLR_INVALID != m_style.m_crBg) +// crOldBg = dc.SetBkColor(m_style.m_crBg); +// if (CLR_INVALID != m_style.m_crText) +// crOldText = dc.SetTextColor(m_style.m_crText); + + POSITION pos = m_lstWndChild.GetHeadPosition(); + + BOOL bDisabled = IsDisabled(), bIsChildDisabled = FALSE; + + while (pos != NULL) + { + CBkWindow *pBkWndChild = m_lstWndChild.GetNext(pos); + + if (!pBkWndChild->IsVisible()) + continue; + + if (bDisabled) + { + bIsChildDisabled = pBkWndChild->IsDisabled(); + + if (!bIsChildDisabled) + pBkWndChild->ModifyState(BkWndState_Disable, 0); + } + + pBkWndChild->BkSendMessage(WM_PAINT, (WPARAM)(HDC)dc); + + if (bDisabled && !bIsChildDisabled) + { + pBkWndChild->ModifyState(0, BkWndState_Disable); + } + } + + if (hftDraw) + dc.SelectFont(hftOld); + + if (crDraw != CLR_INVALID) + dc.SetTextColor(crOld); + + if (!m_style.m_strSkinName.IsEmpty()) + dc.SetBkMode(nOldBkMode); + if (CLR_INVALID != m_style.m_crBg) + dc.SetBkColor(crOldBg); + } + + void OnMouseMove(UINT nFlags, CPoint point) + { + POSITION pos = m_lstWndChild.GetHeadPosition(); + CRect rcChild; + + while (pos != NULL) + { + CBkWindow *pBkWndChild = m_lstWndChild.GetNext(pos); + if (!pBkWndChild->IsVisible()) + continue; + + pBkWndChild->GetRect(rcChild); + + if (rcChild.PtInRect(point)) + { + pBkWndChild->BkSendMessage(WM_MOUSEMOVE, (WPARAM)nFlags, (LPARAM)MAKELONG(point.x, point.y)); + } + } + } + + void OnShowWindow(BOOL bShow, UINT nStatus) + { + __super::OnShowWindow(bShow, nStatus); + + ShowAllRealWindowChilds(bShow); + } + +protected: + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_INT_ATTRIBUTE("onlydrawchild", m_bOnlyDrawChild, FALSE) + BKWIN_DECLARE_ATTRIBUTES_END() + + BKWIN_BEGIN_MSG_MAP() + MSG_WM_PAINT(OnPaint) +// MSG_WM_ERASEBKGND(OnEraseBkgnd) + MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged) + MSG_WM_DESTROY(OnDestroy) + MSG_WM_MOUSEMOVE(OnMouseMove) + MSG_WM_SHOWWINDOW(OnShowWindow) + BKWIN_END_MSG_MAP() +}; + +#include "bkwnddlg.h" +#include "bkwnddlgfile.h" +#include "bkwndtabctrl.h" + +inline CBkWindow* CBkPanel::_CreateBkWindowByName(LPCSTR lpszName) +{ + CBkWindow *pNewWindow = NULL; + +// pNewWindow = CBkPanel::CheckAndNew(lpszName); +// if (pNewWindow) +// return pNewWindow; + + pNewWindow = CBkDialog::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + pNewWindow = CBkDialogFile::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + pNewWindow = CBkStatic::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + pNewWindow = CBkButton::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + +// pNewWindow = CBkSpacing::CheckAndNew(lpszName); +// if (pNewWindow) +// return pNewWindow; + + pNewWindow = CBkImageWnd::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + +// pNewWindow = CBkReturn::CheckAndNew(lpszName); +// if (pNewWindow) +// return pNewWindow; + + pNewWindow = CBkProgress::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + pNewWindow = CBkImageBtnWnd::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + pNewWindow = CBkRealWnd::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + pNewWindow = CBkLine::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + pNewWindow = CBkCheckBox::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + pNewWindow = CBkIconWnd::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + pNewWindow = CBkTabCtrl::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + pNewWindow = CBkRadioBox::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + pNewWindow = CBkRichText::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + pNewWindow = CBkLink::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + pNewWindow = CBkMemoryImage::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + pNewWindow = CBkEdit::CheckAndNew(lpszName); + if (pNewWindow) + return pNewWindow; + + return NULL; +} + +inline void CBkPanel::ShowAllRealWindowChilds(BOOL bShow) +{ + POSITION pos = m_lstWndChild.GetHeadPosition(); + + BOOL bVisible = IsVisible(TRUE); + + while (pos != NULL) + { + CBkWindow *pBkWndChild = m_lstWndChild.GetNext(pos); + + BOOL bChildVisible = bVisible && pBkWndChild->IsVisible(); + +// if (!pBkWndChild->IsVisible()) +// continue; + + if (pBkWndChild->IsClass(CBkRealWnd::GetClassName())) + { + ((CBkRealWnd *)pBkWndChild)->ShowRealWindow(bShow && bChildVisible); + } + else if (pBkWndChild->IsClass(CBkPanel::GetClassName()) || pBkWndChild->IsClass(CBkDialog::GetClassName()) || pBkWndChild->IsClass(CBkDialogFile::GetClassName()) ) + { + ((CBkPanel *)pBkWndChild)->ShowAllRealWindowChilds(bShow && bChildVisible); + } + else if (pBkWndChild->IsClass(CBkTabCtrl::GetClassName())) + { + ((CBkTabCtrl *)pBkWndChild)->ShowAllRealWindowChilds(bShow && bChildVisible); + } + } +} diff --git a/Client/Client/GUI/BKWin/bkwin/bkwndrichtxt.h b/Client/Client/GUI/BKWin/bkwin/bkwndrichtxt.h new file mode 100644 index 00000000..ef21a414 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkwndrichtxt.h @@ -0,0 +1,379 @@ +#pragma once + +////////////////////////////////////////////////////////////////////////// +// Rich Text Control +// +class CBkRichText : public CBkWindow +{ + BKOBJ_DECLARE_CLASS_NAME(CBkRichText, "richtext") + +public: + CBkRichText() + : m_XmlElemChilds("") + , m_dwFont(0) + , m_bLinkLoaded(FALSE) + , m_posHover(NULL) + , m_posPushDown(NULL) + { + + } + + virtual ~CBkRichText() + { + } + + virtual BOOL Load(TiXmlElement* pTiXmlElem) + { + if (!CBkWindow::Load(pTiXmlElem)) + return FALSE; + + + return LoadChilds(pTiXmlElem); + } + + BOOL LoadChilds(TiXmlElement* pTiXmlElem) + { + m_lstLink.RemoveAll(); + m_bLinkLoaded = FALSE; + m_posHover = NULL; + + m_XmlElemChilds = *pTiXmlElem; + + return TRUE; + } + + virtual void SetCursor() + { + ::SetCursor(::LoadCursor(NULL, (0 != m_posHover) ? IDC_HAND : IDC_ARROW)); + } + +protected: + + void OnWindowPosChanged(LPWINDOWPOS lpWndPos) + { + __super::OnWindowPosChanged(lpWndPos); + + m_lstLink.RemoveAll(); + m_bLinkLoaded = FALSE; + m_posHover = NULL; + } + + void OnPaint(CDCHandle dc) + { + HFONT hftOld = dc.SelectFont(BkFontPool::GetFont(LOWORD(m_dwFont))); + + CRect rcDraw = m_rcWindow; + CRgn rgnDraw; + + rcDraw.DeflateRect(m_style.m_nMarginX, m_style.m_nMarginY); + rgnDraw.CreateRectRgnIndirect(rcDraw); + + int nDC = dc.SaveDC(); + dc.SelectClipRgn(rgnDraw); + + POINT pt = rcDraw.TopLeft(); + + _DrawElement(dc, &m_XmlElemChilds, LOWORD(m_dwFont), pt); + + _DrawLinks(dc); + + dc.RestoreDC(nDC); + + dc.SelectFont(hftOld); + + m_bLinkLoaded = TRUE; + } + + void OnMouseMove(UINT nFlags, CPoint point) + { + POSITION posHover = NULL; + POSITION pos = m_lstLink.GetHeadPosition(); + + while (pos) + { + posHover = pos; + const _LinkInfo& link = m_lstLink.GetNext(pos); + + if (link.rcLink.PtInRect(point)) + { + if (m_posHover != posHover) + { + if (m_posHover) + { + _LinkInfo& linkOldHover = m_lstLink.GetAt(m_posHover); + NotifyInvalidateRect(linkOldHover.rcLink); + } + + m_posHover = posHover; + NotifyInvalidateRect(link.rcLink); + } + + return; + } + } + + OnMouseLeave(); + } + + void OnMouseLeave() + { + if (m_posHover) + { + const _LinkInfo& linkOldHover = m_lstLink.GetAt(m_posHover); + NotifyInvalidateRect(linkOldHover.rcLink); + } + + m_posHover = NULL; + } + + void OnLButtonDown(UINT nFlags, CPoint point) + { + if (m_posHover) + { + m_posPushDown = m_posHover; + } + } + + void OnLButtonUp(UINT nFlags, CPoint point) + { + if (m_posPushDown && m_posHover == m_posPushDown) + { + const _LinkInfo& link = m_lstLink.GetAt(m_posPushDown); + + BKNMCOMMAND nms; + nms.hdr.code = BKNM_COMMAND; + nms.hdr.hwndFrom = GetContainer(); + nms.hdr.idFrom = ::GetDlgCtrlID(nms.hdr.hwndFrom); + nms.uItemID = link.uCmdID; + nms.szItemClass = GetObjectClass(); + + LRESULT lRet = ::SendMessage(::GetParent(nms.hdr.hwndFrom), WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + } + + m_posPushDown = NULL; + } + + void _AddLink(CDCHandle &dc, TiXmlElement *pElemChild, POINT &pt) + { + _LinkInfo newLink; + + HFONT hftOld = NULL; + + if (NULL != m_styleLink.m_ftText) + hftOld = dc.SelectFont(m_styleLink.m_ftText); + + newLink.strText = CA2T(pElemChild->GetText(), CP_UTF8); + + SIZE sz = {0, 0}; + + dc.GetTextExtent(newLink.strText, newLink.strText.GetLength(), &sz); + + if (NULL != m_styleLink.m_ftText) + dc.SelectFont(hftOld); + + if (pt.x + sz.cx > m_rcWindow.right - m_style.m_nMarginX) + { + pt.x = m_rcWindow.left + m_style.m_nMarginX; + pt.y += m_style.m_nLineSpacing; + } + + newLink.rcLink.SetRect(pt.x, pt.y, pt.x + sz.cx, pt.y + sz.cy); + + pt.x = newLink.rcLink.right + m_style.m_nSpacing; + + pElemChild->Attribute("id", (int *)&newLink.uCmdID); + + m_lstLink.AddTail(newLink); + } + + void _DrawElement(CDCHandle &dc, TiXmlElement *pElemChild, WORD wFont, POINT &pt) + { + TiXmlNode *pNodeChild = NULL; + + WORD wNewFont = wFont; + COLORREF crTextOld = CLR_INVALID; + + BOOL bOnlyCalcPoint = FALSE; + + if (0 == _stricmp(pElemChild->Value(), "br")) + { + pt.x = m_rcWindow.left + m_style.m_nMarginX; + pt.y += m_style.m_nLineSpacing; + } + else if (0 == _stricmp(pElemChild->Value(), "b")) + { + wNewFont = wFont | BKF_BOLD; + } + else if (0 == _stricmp(pElemChild->Value(), "i")) + { + wNewFont = wFont | BKF_ITALIC; + } + else if (0 == _stricmp(pElemChild->Value(), "u")) + { + wNewFont = wFont | BKF_UNDERLINE; + } + else if (0 == _stricmp(pElemChild->Value(), "c")) + { + crTextOld = dc.SetTextColor(CBkObject::HexStringToColor(pElemChild->Attribute("color"))); + } + else if (0 == _stricmp(pElemChild->Value(), "a")) + { + if (!m_bLinkLoaded) + { + _AddLink(dc, pElemChild, pt); + + return; + } + + bOnlyCalcPoint = TRUE; + } + + dc.SelectFont(BkFontPool::GetFont(wNewFont)); + + while (pNodeChild = pElemChild->IterateChildren(pNodeChild)) + { + _DrawNode(dc, pNodeChild, wNewFont, pt, bOnlyCalcPoint); + } + + dc.SelectFont(BkFontPool::GetFont(wFont)); + + if (CLR_INVALID != crTextOld) + dc.SetTextColor(crTextOld); + } + + void _DrawLinks(CDCHandle &dc) + { + BOOL bDisabled = IsDisabled(TRUE); + BOOL bHover = FALSE; + POSITION pos = m_lstLink.GetHeadPosition(); + + if (NULL != m_styleLink.m_ftText) + dc.SelectFont(m_styleLink.m_ftText); + + if (bDisabled) + { + if (CLR_INVALID != m_styleLink.m_crDisabledText) + dc.SetTextColor(m_styleLink.m_crDisabledText); + } + else + { + if (CLR_INVALID != m_styleLink.m_crText) + dc.SetTextColor(m_styleLink.m_crText); + } + + while (pos) + { + if (pos == m_posHover) + { + if (NULL != m_styleLink.m_ftText) + dc.SelectFont(m_styleLink.m_ftHover); + + if (CLR_INVALID != m_styleLink.m_crText) + dc.SetTextColor(m_styleLink.m_crHoverText); + + bHover = TRUE; + } + + const _LinkInfo& link = m_lstLink.GetNext(pos); + + dc.TextOut(link.rcLink.left, link.rcLink.top, link.strText); + + if (bHover) + { + if (NULL != m_styleLink.m_ftText) + dc.SelectFont(m_styleLink.m_ftText); + + if (CLR_INVALID != m_styleLink.m_crText) + dc.SetTextColor(m_styleLink.m_crText); + + bHover = FALSE; + } + } + } + + void _DrawNode(CDCHandle &dc, TiXmlNode *pNodeChild, WORD wFont, POINT &pt, BOOL bOnlyCalcPoint = FALSE) + { + switch (pNodeChild->Type()) + { + case TiXmlNode::ELEMENT: + { + TiXmlElement *pElemChild = pNodeChild->ToElement(); + + _DrawElement(dc, pElemChild, wFont, pt); + } + break; + + case TiXmlNode::TEXT: + { + CString strText = CA2T(pNodeChild->Value(), CP_UTF8); + LPCTSTR lpszDraw = strText; + int nFullLength = strText.GetLength(), nLength = 0; + + while (TRUE) + { + nLength = nFullLength - nLength; + nFullLength = nLength; + SIZE sz = {0, 0}; + + while (nLength > 0) + { + dc.GetTextExtent(lpszDraw, nLength, &sz); + if (pt.x + sz.cx <= m_rcWindow.right - m_style.m_nMarginX) + break; + + nLength --; + } + + if (!bOnlyCalcPoint) + dc.TextOut(pt.x, pt.y, lpszDraw, nLength); + + if (nFullLength == nLength) + { + pt.x += sz.cx; + break; + } + + pt.x = m_rcWindow.left + m_style.m_nMarginX; + pt.y += m_style.m_nLineSpacing; + lpszDraw += nLength; + } + + pt.x += m_style.m_nSpacing; + } + break; + } + } + +protected: + + TiXmlElement m_XmlElemChilds; + DWORD m_dwFont; + BkStyle m_styleLink; + BOOL m_bLinkLoaded; + POSITION m_posHover; + POSITION m_posPushDown; + + class _LinkInfo + { + public: + CString strText; + UINT uCmdID; + CRect rcLink; + }; + + CAtlList<_LinkInfo> m_lstLink; + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_HEX_ATTRIBUTE("defaultfont", m_dwFont, FALSE) + BKWIN_STYLE_ATTRIBUTE("linkclass", m_styleLink, FALSE) + BKWIN_DECLARE_ATTRIBUTES_END() + + BKWIN_BEGIN_MSG_MAP() + MSG_WM_PAINT(OnPaint) + MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged) + MSG_WM_MOUSEMOVE(OnMouseMove) + MSG_WM_MOUSELEAVE(OnMouseLeave) + MSG_WM_LBUTTONDOWN(OnLButtonDown) + MSG_WM_LBUTTONUP(OnLButtonUp) + BKWIN_END_MSG_MAP() +}; diff --git a/Client/Client/GUI/BKWin/bkwin/bkwndstyle.h b/Client/Client/GUI/BKWin/bkwin/bkwndstyle.h new file mode 100644 index 00000000..e7701a91 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkwndstyle.h @@ -0,0 +1,171 @@ +////////////////////////////////////////////////////////////////////////// +// File Name: BkWndStyle.h +// Description: BkWindow Styles Definition +// Creator: Zhang Xiaoxuan +// Version: 2009.04.28 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "bkskin.h" + +class BkStyle : public CBkObject +{ + BKOBJ_DECLARE_CLASS_NAME(BkStyle, "style") + +public: + BkStyle() + : m_uAlign(0) + , m_nTextAlign(DT_BOTTOM | DT_SINGLELINE) + , m_crBg(CLR_INVALID) + , m_crBgHover(CLR_INVALID) + , m_crText(CLR_INVALID) + , m_crHoverText(CLR_INVALID) + , m_crDisabledText(RGB(0xCC, 0xCC, 0xCC)) + , m_ftText(NULL) + , m_ftHover(NULL) + , m_nMarginX(0) + , m_nMarginY(0) + , m_nSpacing(0) + , m_nLineSpacing(20) + , m_lpCursorName(IDC_ARROW) + { + } + + enum { + // Specify by "cursor" attribute + Cursor_Mask = 0xF00UL, + Cursor_Arrow = 0x000UL, // cursor = "arrow" + Cursor_Hand = 0x100UL, // cursor = "hand" + }; + + COLORREF m_crBg; + COLORREF m_crBgHover; + COLORREF m_crText; + COLORREF m_crHoverText; + COLORREF m_crDisabledText; + UINT m_uAlign; + int m_nTextAlign; + HFONT m_ftText; + HFONT m_ftHover; + int m_nMarginX; + int m_nMarginY; + int m_nSpacing; + int m_nLineSpacing; + LPCTSTR m_lpCursorName; + CStringA m_strSkinName; + + // Get class name + LPCSTR GetName() + { + return m_strClassName; + } + + // Get style object from pool by class name + static const BkStyle& GetStyle(LPCSTR lpszName) + { + CStringA strName = lpszName; + const __StylePoolClass::CPair *pFindRet = _GetStylePool().Lookup(strName); + + if (pFindRet) + return pFindRet->m_value; + else + return _GetStylePool()[""]; + } + + static BOOL LoadStyles(UINT uResID) + { + CStringA strXml; + BOOL bRet = BkResManager::LoadResource(uResID, strXml); + + if (!bRet) + return FALSE; + + return LoadStyles(strXml); + } + + static BOOL LoadStyles(LPCSTR lpszXml) + { + TiXmlDocument xmlDoc; + + _GetStylePool().RemoveAll(); + + xmlDoc.Parse(lpszXml, NULL, TIXML_ENCODING_UTF8); + + if (xmlDoc.Error()) + return FALSE; + + _LoadStylePool(xmlDoc.RootElement()); + + return TRUE; + } + + static size_t GetCount() + { + return _GetStylePool().GetCount(); + } + +protected: + + typedef CAtlMap __StylePoolClass; + + CStringA m_strClassName; + + static __StylePoolClass& _GetStylePool() + { + static __StylePoolClass stylePool; + return stylePool; + } + +// static __StylePoolClass& _GetStylePool() +// { +// static __StylePoolClass s_mapStylePool; +// +// return s_mapStylePool; +// } + + // Load style-pool from xml tree + static void _LoadStylePool(TiXmlElement *pXmlStyleRootElem) + { + LPCSTR lpszClassName = NULL; + + if (!pXmlStyleRootElem) + return; + + if (strcmp(pXmlStyleRootElem->Value(), "style") != 0) + return; + + for (TiXmlElement* pXmlChild = pXmlStyleRootElem->FirstChildElement("class"); NULL != pXmlChild; pXmlChild = pXmlChild->NextSiblingElement("class")) + { + lpszClassName = pXmlChild->Attribute("name"); + if (!lpszClassName) + continue; + + _GetStylePool()[lpszClassName].Load(pXmlChild); + } + } + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_STRING_ATTRIBUTE("name", m_strClassName, TRUE) + BKWIN_STRING_ATTRIBUTE("skin", m_strSkinName, TRUE) + BKWIN_HEX_ATTRIBUTE("textmode", m_nTextAlign, TRUE) + BKWIN_COLOR_ATTRIBUTE("crbg", m_crBg, FALSE) + BKWIN_COLOR_ATTRIBUTE("crbghover", m_crBgHover, FALSE) + BKWIN_COLOR_ATTRIBUTE("crtext", m_crText, FALSE) + BKWIN_COLOR_ATTRIBUTE("crhover", m_crHoverText, FALSE) + BKWIN_COLOR_ATTRIBUTE("crdisabled", m_crDisabledText, FALSE) + BKWIN_FONT_ATTRIBUTE("font", m_ftText, TRUE) + BKWIN_FONT_ATTRIBUTE("hoverfont", m_ftHover, TRUE) + BKWIN_INT_ATTRIBUTE("x-margin", m_nMarginX, TRUE) + BKWIN_INT_ATTRIBUTE("y-margin", m_nMarginY, TRUE) + BKWIN_INT_ATTRIBUTE("margin", m_nMarginX = m_nMarginY, TRUE) // Ƚbt.....պð + BKWIN_INT_ATTRIBUTE("spacing", m_nSpacing, TRUE) + BKWIN_INT_ATTRIBUTE("linespacing", m_nLineSpacing, TRUE) + BKWIN_ENUM_ATTRIBUTE("cursor", LPCTSTR, FALSE) + BKWIN_ENUM_VALUE("hand", IDC_HAND) + BKWIN_ENUM_VALUE("arrow", IDC_ARROW) + BKWIN_ENUM_END(m_lpCursorName) + BKWIN_DECLARE_ATTRIBUTES_END() +}; + +//__declspec(selectany) BkStyle::__StylePoolClass* BkStyle::ms_pStylePool = NULL; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/bkwin/bkwndtabctrl.h b/Client/Client/GUI/BKWin/bkwin/bkwndtabctrl.h new file mode 100644 index 00000000..4c5ac3de --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/bkwndtabctrl.h @@ -0,0 +1,746 @@ +////////////////////////////////////////////////////////////////////////// +// File Name: bkwndtabctrl.h +// Description: Tab Control +// Creator: Zhang Xiaoxuan +// Version: 2009.6.8 - 1.0 - Create +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "bkwndnotify.h" + +class CBkTab : public CBkDialog +{ + BKOBJ_DECLARE_CLASS_NAME(CBkTab, "tab") + +public: + CBkTab() + { + m_bHidden = FALSE; + } + + LPCTSTR GetTitle() + { + return m_strTitle; + } + + void SetTitle(LPCTSTR lpszTitle) + { + m_strTitle = lpszTitle; + } + + BOOL IsHidden() + { + return m_bHidden; + } + + void Hide(BOOL bHide) + { + m_bHidden = bHide; + } + +protected: + + CString m_strTitle; + BOOL m_bHidden; + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_TSTRING_ATTRIBUTE("title", m_strTitle, FALSE) + BKWIN_UINT_ATTRIBUTE("hide", m_bHidden, FALSE) + BKWIN_DECLARE_ATTRIBUTES_END() +}; + +class CBkTabCtrl : public CBkContainerWnd +{ + BKOBJ_DECLARE_CLASS_NAME(CBkTabCtrl, "tabctrl") + +protected: + CAtlList m_lstPages; + int m_nHoverTabItem; + int m_nCurrentPage; + int m_nTabSpacing; + int m_nTabPos; + int m_nFramePos; + int m_nTabWidth; + int m_nTabHeight; + CBkSkinBase *m_pSkinTab; + CBkSkinBase *m_pSkinFrame; + CBkSkinBase *m_pSkinIcon; + CBkSkinBase *m_pSkinSplitter; + CRect m_rcClient; + POINT m_ptIcon; + POINT m_ptText; + int m_nTabAlign; + + enum { + AlignTop, + AlignLeft, + }; + +public: + + CBkTabCtrl() + : m_nCurrentPage(0) + , m_pSkinTab(NULL) + , m_pSkinFrame(NULL) + , m_pSkinIcon(NULL) + , m_pSkinSplitter(NULL) + , m_nTabSpacing(0) + , m_nTabPos(0) + , m_nFramePos(0) + , m_nTabWidth(0) + , m_nTabHeight(0) + , m_nHoverTabItem(-1) + , m_nTabAlign(AlignTop) + { + m_ptIcon.x = m_ptIcon.y = 0; + m_ptText.x = m_ptText.y = 0; + } + + int GetCurSel() + { + return m_nCurrentPage; + } + + BOOL SetCurSel(int nIndex) + { + int nOldPage = m_nCurrentPage; + + BKNMTABSELCHANGE nms; + nms.hdr.code = BKNM_TAB_SELCHANGE; + nms.hdr.hwndFrom = m_hWndContainer; + nms.hdr.idFrom = ::GetDlgCtrlID(m_hWndContainer); + nms.uTabID = GetCmdID(); + nms.uTabItemIDNew = nIndex; + nms.uTabItemIDOld = nOldPage; + nms.bCancel = FALSE; + + LRESULT lRet = ::SendMessage(m_hWndContainer, WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + + if (nms.bCancel) + return FALSE; + + if (m_nCurrentPage != nIndex) + { + if (nIndex < 0 || nIndex >= (int)m_lstPages.GetCount()) + return FALSE; + + CRect rcItem; + + GetTabItemRect(m_nCurrentPage, rcItem); + NotifyInvalidateRect(rcItem); + GetTabItemRect(nIndex, rcItem); + NotifyInvalidateRect(rcItem); + + GetTab(m_nCurrentPage)->BkSendMessage(WM_SHOWWINDOW, (WPARAM)FALSE); + + m_nCurrentPage = nIndex; + + GetTab(nIndex)->BkSendMessage(WM_SHOWWINDOW, (WPARAM)TRUE); + + WINDOWPOS WndPos = {0}; + + WndPos.x = m_rcClient.left; + WndPos.y = m_rcClient.top; + WndPos.cx = m_rcClient.Width(); + WndPos.cy = m_rcClient.Height(); + GetTab(nIndex)->BkSendMessage(WM_WINDOWPOSCHANGED, NULL, (LPARAM)&WndPos); + + NotifyInvalidateRect(m_rcClient); + } + + return TRUE; + } + + BOOL SetTabTitle(int nIndex, LPCTSTR lpszTitle) + { + CRect rcItem; + + CBkTab* pTab = GetTab(nIndex); + if (pTab) + { + pTab->SetTitle(lpszTitle); + GetTabItemRect(nIndex, rcItem); + NotifyInvalidateRect(rcItem); + + return TRUE; + } + + return FALSE; + } + + BOOL IsPageVisible(int nIndex) + { + return !GetTab(nIndex)->IsHidden(); + } + + BOOL SetPageVisible(int nIndex, BOOL bVisible) + { + CBkTab* pTab = GetTab(nIndex); + if (!pTab) + return FALSE; + + if (pTab->IsHidden() != bVisible) + return TRUE; + + pTab->Hide(!bVisible); + + if (!bVisible && m_nCurrentPage == nIndex) + { + int i = 0; + int nPageCount = (int)m_lstPages.GetCount(); + + for (i = 0; i < nPageCount; i ++) + { + if (!GetTab(i)->IsHidden()) + { + m_nCurrentPage = i; + break; + } + } + + if (i == nPageCount) + m_nCurrentPage = -1; + } + + NotifyInvalidate(); + + return TRUE; + } + + BOOL LoadChilds(TiXmlElement* pTiXmlChildElem) + { + BOOL bFirstPage = TRUE; + int nPage = -1, nFirstShowPage = -1; + + BkSendMessage(WM_DESTROY); + + for (TiXmlElement* pXmlChild = pTiXmlChildElem; NULL != pXmlChild; pXmlChild = pXmlChild->NextSiblingElement()) + { + CBkTab *pNewChildWindow = CBkTab::CheckAndNew(pXmlChild->Value()); + if (!pNewChildWindow) + continue; + + nPage ++; + + pNewChildWindow->SetParent(m_hBkWnd); + pNewChildWindow->SetContainer(m_hWndContainer); + pNewChildWindow->Load(pXmlChild); + pNewChildWindow->SetAttribute("pos", "0,0,-0,-0", TRUE); + + BOOL bVisible = !pNewChildWindow->IsHidden(); + + pNewChildWindow->BkSendMessage(WM_SHOWWINDOW, bFirstPage && bVisible); + if (bFirstPage && bVisible) + { + nFirstShowPage = nPage; + if (0 == m_nCurrentPage) + m_nCurrentPage = nPage; + bFirstPage = FALSE; + } + + m_lstPages.AddTail(pNewChildWindow); + } + + //ָNΪĬѡTABǵN,ôͰѵһʵԵTABΪĬϵ + CBkTab *pNewChildWindow = GetTab(m_nCurrentPage); + if (NULL != pNewChildWindow && + TRUE == pNewChildWindow->IsHidden() && + nFirstShowPage >= 0 && + m_nCurrentPage > 0) + {// + m_nCurrentPage = nFirstShowPage; + } + + return TRUE; + } + + void SetContainer(HWND hWndContainer) + { + __super::SetContainer(hWndContainer); + + POSITION pos = m_lstPages.GetHeadPosition(); + + while (pos != NULL) + { + CBkTab *pBkWndChild = m_lstPages.GetNext(pos); + + if (pBkWndChild) + { + pBkWndChild->SetContainer(hWndContainer); + } + } + } + + int GetVisibleTabCount() + { + POSITION pos = m_lstPages.GetHeadPosition(); + int nCount = 0; + + while (pos) + { + CBkTab *pBkWndChild = m_lstPages.GetNext(pos); + + if (pBkWndChild && !pBkWndChild->IsHidden()) + { + nCount ++; + } + } + + return nCount; + } + + BOOL GetTabItemRect(int nIndex, CRect &rcItem) + { + if (nIndex < 0 || nIndex >= (int)m_lstPages.GetCount()) + return FALSE; + + SIZE size = {0, 0}; + + if (m_pSkinTab) + size = m_pSkinTab->GetSkinSize(); + + if (0 != m_nTabHeight) + size.cy = m_nTabHeight; + if (0 != m_nTabWidth) + size.cx = m_nTabWidth; + + rcItem.SetRect(m_rcWindow.left, m_rcWindow.top, m_rcWindow.left + size.cx, m_rcWindow.top + size.cy); + + POSITION pos = m_lstPages.GetHeadPosition(); + int nDrawIndex = 0; + + for (int i = 0; i < nIndex && pos != NULL; i ++) + { + CBkTab *pBkWndChild = m_lstPages.GetNext(pos); + + if (pBkWndChild && !pBkWndChild->IsHidden()) + { + nDrawIndex ++; + } + } + + switch (m_nTabAlign) + { + case AlignTop: + rcItem.OffsetRect(m_nTabPos + (m_nTabWidth + m_nTabSpacing) * nDrawIndex, 0); + break; + case AlignLeft: + rcItem.OffsetRect(0, m_nTabPos + (m_nTabHeight + m_nTabSpacing) * nDrawIndex); + break; + } + + return TRUE; + } + + CBkTab* GetTab(int nIndex) + { + if (nIndex < 0 || nIndex >= (int)m_lstPages.GetCount()) + return NULL; + + return m_lstPages.GetAt(m_lstPages.FindIndex(nIndex)); + } + + // Create children + virtual BOOL Load(TiXmlElement* pTiXmlElem) + { + if (!CBkWindow::Load(pTiXmlElem)) + return FALSE; + + BOOL bRet = LoadChilds(pTiXmlElem->FirstChildElement()); + if (!bRet) + return FALSE; + +// CBkSkinBase *pSkin = NULL; +// pSkin = BkSkin::GetSkin(m_strSkinTab); +// +// if (pSkin) +// { +// if (pSkin->IsClass(CBkSkinImgHorzExtend::GetClassName())) +// m_pSkinTab = (CBkSkinImgHorzExtend *)pSkin; +// else +// m_pSkinTab = NULL; +// } +// +// pSkin = BkSkin::GetSkin(m_strSkinFrame); +// +// if (pSkin) +// { +// if (pSkin->IsClass(CBkSkinImgFrame::GetClassName())) +// m_pSkinFrame = (CBkSkinImgFrame *)pSkin; +// else +// m_pSkinFrame = NULL; +// } + + return TRUE; + } + + // Hittest children + virtual HBKWND BkGetHWNDFromPoint(POINT ptHitTest, BOOL bOnlyText) + { + if (m_rcWindow.PtInRect(ptHitTest)) + { + if (m_rcClient.PtInRect(ptHitTest)) + return GetTab(m_nCurrentPage)->BkGetHWNDFromPoint(ptHitTest, bOnlyText); + else + return GetBkHWnd(); + } + else + return NULL; + } + + CBkWindow* FindChildByCmdID(UINT uCmdID) + { + CBkWindow *pChildFind = NULL; + POSITION pos = m_lstPages.GetHeadPosition(); + + while (pos != NULL) + { + CBkTab *pBkWndChild = m_lstPages.GetNext(pos); + + if (pBkWndChild) + { + if (uCmdID == pBkWndChild->GetCmdID()) + return pBkWndChild; + + pChildFind = pBkWndChild->FindChildByCmdID(uCmdID); + if (pChildFind) + return pChildFind; + } + } + + return NULL; + } + + void ShowAllRealWindowChilds(BOOL bShow) + { + int nPageCount = (int)m_lstPages.GetCount(); + + for (int i = 0; i < nPageCount; i ++) + { + GetTab(i)->ShowAllRealWindowChilds((i == m_nCurrentPage) ? bShow : FALSE); + } + } + + virtual BOOL RedrawRegion(CDCHandle& dc, CRgn& rgn) + { + if (__super::RedrawRegion(dc, rgn)) + { + CBkTab *pCurPage = GetTab(m_nCurrentPage); + if (pCurPage) + pCurPage->RedrawRegion(dc, rgn); + + return TRUE; + } + + return FALSE; + } + + void OnDestroy() + { + POSITION pos = m_lstPages.GetHeadPosition(); + + while (pos != NULL) + { + CBkTab *pBkWndChild = m_lstPages.GetNext(pos); + + pBkWndChild->BkSendMessage(WM_DESTROY); + + delete pBkWndChild; + } + + m_lstPages.RemoveAll(); + } + + void OnPaint(CDCHandle dc) + { + int nPageCount = (int)m_lstPages.GetCount(); + CRect rcItem; + SIZE sizeTab = {0, 0}, sizeIcon = {0, 0}, sizeSplitter = {0, 0}; + CString strTabText; + + rcItem = m_rcWindow; + + if (m_pSkinTab) + sizeTab = m_pSkinTab->GetSkinSize(); + + if (m_pSkinIcon) + sizeIcon = m_pSkinIcon->GetSkinSize(); + + if (m_pSkinSplitter) + sizeSplitter = m_pSkinSplitter->GetSkinSize(); + + if (0 != m_nTabHeight) + sizeTab.cy = m_nTabHeight; + + if (0 != m_nTabWidth) + sizeTab.cx = m_nTabWidth; + + switch (m_nTabAlign) + { + case AlignTop: + rcItem.top += sizeTab.cy + m_nFramePos; + break; + case AlignLeft: + rcItem.left += sizeTab.cx + m_nFramePos; + break; + } + + if (m_pSkinFrame) + m_pSkinFrame->Draw(dc, rcItem, BkWndState_Normal); + + dc.SetBkMode(TRANSPARENT); + + if (CLR_INVALID != m_style.m_crText) + dc.SetTextColor(m_style.m_crText); + + HFONT hFontOld = NULL; + + if (NULL != m_style.m_ftText) + hFontOld = dc.SelectFont(m_style.m_ftText); + + int nVisibleCount = GetVisibleTabCount(); + + for (int i = 0; i < nPageCount; i ++) + { + if (GetTab(i)->IsHidden()) + continue; + + GetTabItemRect(i, rcItem); + + if (m_pSkinSplitter && nVisibleCount > 1) + { + nVisibleCount --; + + CRect rcDraw; + + switch (m_nTabAlign) + { + case AlignTop: + rcDraw.SetRect(rcItem.right, rcItem.top, rcItem.right + m_nTabSpacing, rcItem.bottom); + rcDraw.NormalizeRect(); + rcDraw.DeflateRect((rcDraw.Width() - sizeSplitter.cx) / 2, 0); + break; + case AlignLeft: + rcDraw.SetRect(rcItem.left, rcItem.bottom, rcItem.right, rcItem.bottom + m_nTabSpacing); + rcDraw.NormalizeRect(); + rcDraw.DeflateRect(0, (rcDraw.Height() - sizeSplitter.cy) / 2); + break; + } + + m_pSkinSplitter->Draw(dc, rcDraw, -1); + } + + if (i == m_nCurrentPage) + continue; + + if (m_pSkinTab) + m_pSkinTab->Draw(dc, rcItem, (i != m_nHoverTabItem) ? BkWndState_Normal : BkWndState_Hover); + + if (m_pSkinIcon) + { + CRect rcDraw = rcItem; + rcDraw.OffsetRect(m_ptIcon); + m_pSkinIcon->Draw(dc, rcDraw, i); + } + + rcItem.OffsetRect(m_ptText); + + strTabText = GetTab(i)->GetTitle(); + dc.DrawText(strTabText, strTabText.GetLength(), rcItem, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX | DT_TABSTOP); + } + + if (NULL != m_style.m_ftHover) + hFontOld = (NULL == hFontOld) ? dc.SelectFont(m_style.m_ftHover) : NULL; + + if (CLR_INVALID != m_style.m_crHoverText) + dc.SetTextColor(m_style.m_crHoverText); + + for (int i = 0; i < nPageCount; i ++) + { + if (GetTab(i)->IsHidden()) + continue; + + if (i != m_nCurrentPage) + continue; + + GetTabItemRect(i, rcItem); + + if (m_pSkinTab) + m_pSkinTab->Draw(dc, rcItem, BkWndState_PushDown); + + if (m_pSkinIcon) + { + CRect rcDraw = rcItem; + rcDraw.OffsetRect(m_ptIcon); + m_pSkinIcon->Draw(dc, rcDraw, i); + } + + rcItem.OffsetRect(m_ptText); + + strTabText = GetTab(i)->GetTitle(); + dc.DrawText(strTabText, strTabText.GetLength(), rcItem, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX | DT_TABSTOP); + + break; + } + + if (NULL != hFontOld) + dc.SelectFont(hFontOld); + } + + void OnWindowPosChanged(LPWINDOWPOS lpWndPos) + { + CBkWindow::OnWindowPosChanged(lpWndPos); + + SIZE sizeTab = {0, 0}; + + if (m_pSkinTab) + sizeTab = m_pSkinTab->GetSkinSize(); + + if (0 != m_nTabHeight) + sizeTab.cy = m_nTabHeight; + if (0 != m_nTabWidth) + sizeTab.cx = m_nTabWidth; + + m_rcClient = m_rcWindow; + switch (m_nTabAlign) + { + case AlignTop: + m_rcClient.top += sizeTab.cy + m_nFramePos; + break; + case AlignLeft: + m_rcClient.left += sizeTab.cx + m_nFramePos; + break; + } + + m_rcClient.DeflateRect(m_style.m_nMarginX, m_style.m_nMarginY); + + for (int i = 0; i < (int)m_lstPages.GetCount(); i ++) + { + WINDOWPOS WndPos = *lpWndPos; + + WndPos.x = m_rcClient.left; + WndPos.y = m_rcClient.top; + WndPos.cx = m_rcClient.Width(); + WndPos.cy = m_rcClient.Height(); + + CBkTab *pCurPage = GetTab(i); + if (pCurPage) + pCurPage->BkSendMessage(WM_WINDOWPOSCHANGED, NULL, (LPARAM)&WndPos); + } + + } + + void OnLButtonDown(UINT nFlags, CPoint point) + { + CRect rcItem; + + for (int i = 0; i < (int)m_lstPages.GetCount(); i ++) + { + if (GetTab(i)->IsHidden()) + continue; + + if (i == m_nCurrentPage) + continue; + + GetTabItemRect(i, rcItem); + + if (rcItem.PtInRect(point)) + { + SetCurSel(i); + break; + } + } + } + + void OnShowWindow(BOOL bShow, UINT nStatus) + { + __super::OnShowWindow(bShow, nStatus); + + GetTab(m_nCurrentPage)->BkSendMessage(WM_SHOWWINDOW, (WPARAM)bShow); + } + + void OnMouseMove(UINT nFlags, CPoint point) + { + CRect rcItem; + int nHoverTabItem = -1; + + for (int i = 0; i < (int)m_lstPages.GetCount(); i ++) + { + if (GetTab(i)->IsHidden()) + continue; + + if (i == m_nCurrentPage) + continue; + + GetTabItemRect(i, rcItem); + + if (rcItem.PtInRect(point)) + { + NotifyInvalidateRect(rcItem); + nHoverTabItem = i; + break; + } + } + + if (nHoverTabItem != m_nHoverTabItem) + { + if (-1 != m_nHoverTabItem) + { + GetTabItemRect(m_nHoverTabItem, rcItem); + NotifyInvalidateRect(rcItem); + } + + m_nHoverTabItem = nHoverTabItem; + } + } + + void OnMouseLeave() + { + if (-1 != m_nHoverTabItem) + { + CRect rcItem; + GetTabItemRect(m_nHoverTabItem, rcItem); + NotifyInvalidateRect(rcItem); + m_nHoverTabItem = -1; + } + } + + virtual void SetCursor() + { + ::SetCursor(::LoadCursor(NULL, (-1 != m_nHoverTabItem) ? IDC_HAND : IDC_ARROW)); + } + +protected: + + BKWIN_BEGIN_MSG_MAP() + MSG_WM_PAINT(OnPaint) + MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged) + MSG_WM_DESTROY(OnDestroy) + MSG_WM_LBUTTONDOWN(OnLButtonDown) + MSG_WM_MOUSEMOVE(OnMouseMove) + MSG_WM_MOUSELEAVE(OnMouseLeave) + MSG_WM_SHOWWINDOW(OnShowWindow) + BKWIN_END_MSG_MAP() + + BKWIN_DECLARE_ATTRIBUTES_BEGIN() + BKWIN_INT_ATTRIBUTE("cursel", m_nCurrentPage, FALSE) + BKWIN_INT_ATTRIBUTE("tabwidth", m_nTabWidth, FALSE) + BKWIN_INT_ATTRIBUTE("tabheight", m_nTabHeight, FALSE) + BKWIN_INT_ATTRIBUTE("tabpos", m_nTabPos, FALSE) + BKWIN_INT_ATTRIBUTE("tabspacing", m_nTabSpacing, FALSE) + BKWIN_SKIN_ATTRIBUTE("tabskin", m_pSkinTab, FALSE) + BKWIN_SKIN_ATTRIBUTE("frameskin", m_pSkinFrame, FALSE) + BKWIN_SKIN_ATTRIBUTE("iconskin", m_pSkinIcon, FALSE) + BKWIN_SKIN_ATTRIBUTE("splitterskin", m_pSkinSplitter, FALSE) + BKWIN_INT_ATTRIBUTE("framepos", m_nFramePos, FALSE) + BKWIN_INT_ATTRIBUTE("icon-x", m_ptIcon.x, FALSE) + BKWIN_INT_ATTRIBUTE("icon-y", m_ptIcon.y, FALSE) + BKWIN_INT_ATTRIBUTE("text-x", m_ptText.x, FALSE) + BKWIN_INT_ATTRIBUTE("text-y", m_ptText.y, FALSE) + BKWIN_ENUM_ATTRIBUTE("tabalign", int, TRUE) + BKWIN_ENUM_VALUE("top", AlignTop) + BKWIN_ENUM_VALUE("left", AlignLeft) + BKWIN_ENUM_END(m_nTabAlign) + BKWIN_DECLARE_ATTRIBUTES_END() +}; diff --git a/Client/Client/GUI/BKWin/bkwin/listboxbase.h b/Client/Client/GUI/BKWin/bkwin/listboxbase.h new file mode 100644 index 00000000..61aa1338 --- /dev/null +++ b/Client/Client/GUI/BKWin/bkwin/listboxbase.h @@ -0,0 +1,857 @@ + + +/////////////////////////////////////////////////////////////////////////////// +// CBkListBoxBaseT - һ򵥵ĻownerdrawĿɱ߶ȵĵѡlistbox + +#define LB_REFRESH (LB_MSGMAX-1) + +typedef CWinTraits CBkListBoxBaseTraits; + +//CListBox +class CBkListBoxBase : + public CWindowImpl +{ +public: + + typedef CWindowImpl TBase; + + #define DEFAULT_SEL_VALUE -1 + #define MARGIN_BOTTOM 5 + // Attributes + static LPCTSTR GetWndClassName() + { + return _T("BKSIMPLELIST"); + } + + // Constructors + CBkListBoxBase() : TBase() + { + _Init(); + } + + CBkListBoxBase& operator =(HWND hWnd) + { + _Init(); + + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + + // for entire listbox + int GetCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_GETCOUNT, 0, 0L); + } + + int SetCount(int cItems) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_SETCOUNT, cItems, 0L); + } + + int GetTopIndex() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_GETTOPINDEX, 0, 0L); + } + + int SetTopIndex(int nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_SETTOPINDEX, nIndex, 0L); + } + + // for single-selection listboxes + int GetCurSel() const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0); + return (int)::SendMessage(m_hWnd, LB_GETCURSEL, 0, 0L); + } + + int SetCurSel(int nSelect) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0); + return (int)::SendMessage(m_hWnd, LB_SETCURSEL, nSelect, 0L); + } + + // for listbox items + DWORD_PTR GetItemData(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD_PTR)::SendMessage(m_hWnd, LB_GETITEMDATA, nIndex, 0L); + } + + int SetItemData(int nIndex, DWORD_PTR dwItemData) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_SETITEMDATA, nIndex, (LPARAM)dwItemData); + } + + int SetItemDataPtr(int nIndex, void* pData) + { + ATLASSERT(::IsWindow(m_hWnd)); + return SetItemData(nIndex, (DWORD_PTR)pData); + } + + int GetItemRect(int nIndex, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_GETITEMRECT, nIndex, (LPARAM)lpRect); + } + + int GetItemHeight(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_GETITEMHEIGHT, nIndex, 0L); + } + + int SetItemHeight(int nIndex, UINT cyItemHeight) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0)); + } + + // Settable only attributes + void SetColumnWidth(int cxWidth) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LB_SETCOLUMNWIDTH, cxWidth, 0L); + } + + void ResetContent() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LB_RESETCONTENT, 0, 0L); + } + + UINT ItemFromPoint(POINT pt, BOOL& bOutside) const + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dw = (DWORD)::SendMessage(m_hWnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(pt.x, pt.y)); + bOutside = (BOOL)HIWORD(dw); + return (UINT)LOWORD(dw); + } + + // manipulating listbox items + int AddString(LPCTSTR lpszItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_ADDSTRING, 0, (LPARAM)lpszItem); + } + + int DeleteString(UINT nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_DELETESTRING, nIndex, 0L); + } + + int InsertString(int nIndex, LPCTSTR lpszItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + + return 0; + } + + VOID ReDrawItem( int nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LB_REFRESH, nIndex, 0L); + } + + VOID Referesh( BOOL bRecalLayout = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LB_REFRESH, (WPARAM)bRecalLayout, (LPARAM)TRUE); + } + +public: + + BEGIN_MSG_MAP_EX(CBkListBoxBase) + MSG_WM_MOUSEWHEEL(OnMouseWheel) + MSG_WM_ERASEBKGND(OnEraseBkgnd) + MSG_WM_SIZE(OnSize) + MSG_WM_NCCALCSIZE(OnNcCalcSize) + MSG_WM_PAINT(OnPaint) + MESSAGE_HANDLER_EX(LB_DELETESTRING,_OnDeleteString) + MESSAGE_HANDLER_EX(LB_ADDSTRING,_OnAddString) + MESSAGE_HANDLER_EX(LB_INSERTSTRING,_OnInsertString) + MESSAGE_HANDLER_EX(LB_RESETCONTENT,_OnResetContent) + MESSAGE_HANDLER_EX(LB_GETCURSEL,_OnGetCursel) + MESSAGE_HANDLER_EX(LB_SETCURSEL,_OnSetCursel) + MESSAGE_HANDLER_EX(LB_GETCOUNT,_OnGetCount) + MESSAGE_HANDLER_EX(LB_SETCOUNT,_OnSetCount) + MESSAGE_HANDLER_EX(LB_GETITEMHEIGHT,_OnGetItemHeight) + MESSAGE_HANDLER_EX(LB_SETITEMHEIGHT,_OnSetItemHeight) + MESSAGE_HANDLER_EX(LB_GETITEMRECT,_OnGetItemRect) + MESSAGE_HANDLER_EX(LB_ITEMFROMPOINT,_OnItemFromPoint) + MESSAGE_HANDLER_EX(LB_SETCOLUMNWIDTH,_OnSetColumnWidth) + MESSAGE_HANDLER_EX(LB_SETITEMDATA,_OnSetItemData) + MESSAGE_HANDLER_EX(LB_GETITEMDATA,_OnGetItemData) + MESSAGE_HANDLER_EX(LB_REFRESH,_OnRefresh) + MSG_WM_VSCROLL(_OnVScroll) + END_MSG_MAP() + + +protected: + +#define FIX_SCROLL_POS(sbInfo) if (sbInfo.nPos < sbInfo.nMin)sbInfo.nPos = sbInfo.nMin;\ + else if (sbInfo.nPos > sbInfo.nMax-(int)sbInfo.nPage )\ + sbInfo.nPos = sbInfo.nMax-sbInfo.nPage; + + BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) + { + if ( TBase::GetStyle() & WS_VSCROLL ) + { + SCROLLINFO sbInfo = {0}; + + sbInfo.cbSize = sizeof(SCROLLINFO); + sbInfo.fMask = SIF_ALL; + + TBase::GetScrollInfo(SB_VERT,&sbInfo); + + sbInfo.nPos -= zDelta; + + FIX_SCROLL_POS(sbInfo); + + TBase::SetScrollPos(SB_VERT,sbInfo.nPos); + + m_nScrollOffset = 0-sbInfo.nPos; + _RefreshIntern(); + } + + return FALSE; + } + + void _OnVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar) + { + SCROLLINFO sbInfo = {0}; + + sbInfo.cbSize = sizeof(SCROLLINFO); + sbInfo.fMask = SIF_ALL; + + TBase::GetScrollInfo(SB_VERT,&sbInfo); + + switch(nSBCode) + { + case SB_PAGEDOWN: + case SB_LINEDOWN: + { + sbInfo.nPos += sbInfo.nPage/4; + + if (sbInfo.nPos < sbInfo.nMin) + sbInfo.nPos = sbInfo.nMin; + else if (sbInfo.nPos > sbInfo.nMax-(int)sbInfo.nPage ) + sbInfo.nPos =sbInfo.nMax-sbInfo.nPage; + + TBase::SetScrollPos(SB_VERT,sbInfo.nPos); + + m_nScrollOffset = 0-sbInfo.nPos; + _RefreshIntern(); + } + break; + case SB_PAGEUP: + case SB_LINEUP: + { + sbInfo.nPos -= sbInfo.nPage/4; + + if (sbInfo.nPos < sbInfo.nMin) + sbInfo.nPos = sbInfo.nMin; + else if (sbInfo.nPos >= sbInfo.nMax) + sbInfo.nPos = sbInfo.nMax; + + TBase::SetScrollPos(SB_VERT,sbInfo.nPos); + + m_nScrollOffset = 0-sbInfo.nPos; + _RefreshIntern(); + } + break; + case SB_THUMBTRACK: + { + sbInfo.nPos = nPos; + + if (sbInfo.nPos < sbInfo.nMin) + sbInfo.nPos = sbInfo.nMin; + else if (sbInfo.nPos >= sbInfo.nMax) + sbInfo.nPos = sbInfo.nMax; + + TBase::SetScrollPos(SB_VERT,sbInfo.nPos); + + m_nScrollOffset = 0-sbInfo.nPos; + _RefreshIntern(); + } + break; + } + + } + + + LRESULT _OnRefresh(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + int nIndex = (int)wParam; + BOOL bAll = (BOOL)lParam; + BOOL bRecal = (BOOL)wParam; + + if (bAll) + { + if (bRecal) + { + m_bNeedRecalLayout = TRUE; + _RecalcLayout(); + } + + m_bNeedRedraw = TRUE; + _RePaint(NULL); + } + else + { + _RePaintItem(NULL,nIndex); + } + + return S_OK; + } + + LRESULT _OnGetItemData(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + int nIndex = (int)wParam; + + if (nIndex< (int)m_listData.GetCount()) + return (LRESULT)m_listData[nIndex].lpParam; + else + return (LRESULT)0; + } + + LRESULT _OnSetItemData(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + int nIndex = (int)wParam; + DWORD_PTR pdata = (DWORD_PTR)lParam; + + if (nIndex<(int)m_listData.GetCount()) + { + m_listData[nIndex].lpParam = pdata; + return (LRESULT)nIndex; + } + else + return (LRESULT)0; + } + + VOID OnPaint(CDCHandle dc) + { + if ( m_bNeedRecalLayout ) + _RecalcLayout(); + + _RePaint(dc.m_hDC); + ValidateRect(NULL); + } + + LRESULT _OnDeleteString(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + UINT nIndex = (UINT)wParam; + + if (nIndex < m_listData.GetCount()) + { + m_listData.RemoveAt( (size_t)nIndex,1); + + if (nIndex==m_nCurSel) + m_nCurSel = DEFAULT_SEL_VALUE; + + _RefreshIntern(); + } + + return S_OK; + } + LRESULT _OnInsertString(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + ATLASSERT(NULL); + return S_OK; + } + + LRESULT _OnAddString(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + LPCTSTR lpstr = (LPCTSTR)lParam; + List_Intern_Data dataNew; + + dataNew.nHeight = 0; + dataNew.strText = lpstr; + m_listData.Add(dataNew); + + _RefreshIntern(); + + return S_OK; + } + LRESULT _OnResetContent(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + m_nCurSel = DEFAULT_SEL_VALUE; + m_listData.RemoveAll(); + _RefreshIntern(TRUE,TRUE,TRUE); + return S_OK; + } + + LRESULT _OnGetCursel(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + return (LRESULT)m_nCurSel; + } + LRESULT _OnSetCursel(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + m_nCurSel = (int)wParam; + return (LRESULT)m_nCurSel; + } + + LRESULT _OnGetCount(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + return (int)m_listData.GetCount(); + } + + LRESULT _OnSetCount(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + ATLASSERT(m_listData.GetCount()==0); + + int nNewCount = (int)wParam; + + for ( int i=0; i= (int)m_listData.GetCount() ) + return (LRESULT)0; + else + return (LRESULT)m_listData[nIndex].nHeight; + } + + LRESULT _OnSetItemHeight(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + int nIndex = (int)wParam; + + int nHeight = (int)lParam; + + m_listData[nIndex].nHeight = nHeight; + + _RefreshIntern(TRUE,TRUE); + + return S_OK; + } + + LRESULT _OnGetItemRect(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + int nIndex = (int)wParam; + LPRECT lprc = (LPRECT)lParam; + + if ( nIndex < (int)m_listData.GetCount() && lprc != NULL ) + { + lprc->left = m_listData[nIndex].rcItem.left; + lprc->right = m_listData[nIndex].rcItem.right; + lprc->bottom = m_listData[nIndex].rcItem.bottom; + lprc->top = m_listData[nIndex].rcItem.top; + } + + return (LRESULT)nIndex; + } + + LRESULT _OnItemFromPoint(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + int ptx = LOWORD(lParam); + int pty = HIWORD(lParam); + + for ( int i = 0; i < (int)m_listData.GetCount(); i++ ) + { + List_Intern_Data& data = m_listData[i]; + + if ( data.rcItem.PtInRect( CPoint(ptx, pty) ) ) + { + return (LRESULT)i; + } + } + + return (LRESULT)DEFAULT_SEL_VALUE; + } + + LRESULT _OnSetColumnWidth(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + m_nColumnWidth = (int)wParam; + + for (int i=0; i < (int)m_listData.GetCount(); i++) + m_listData[i].rcItem.right = m_listData[i].rcItem.left + m_nColumnWidth; + + return S_OK; + } + +private: + VOID _RecalcLayout() + { + if (!m_bNeedRecalLayout) + return; + + CRect rc; + + TBase::GetClientRect(&rc); + + if (rc.Width()==0||rc.Height()==0) + return; + + int nTop = m_nScrollOffset; + int nTotalHeight = 0; + for ( int i=0; i<(int)m_listData.GetCount(); i++) + { + List_Intern_Data& data = m_listData[i]; + MEASUREITEMSTRUCT measure = {0}; + + + measure.itemHeight = 0; + measure.itemID = i; + + MeasureItem(&measure); + + + data.nHeight = measure.itemHeight; + data.rcItem.left = 0; + data.rcItem.top = nTop; + + if (m_nColumnWidth!=-1) + data.rcItem.right = m_nColumnWidth; + else + data.rcItem.right = rc.Width(); + + data.rcItem.bottom = nTop+data.nHeight; + + nTop += data.nHeight; + + nTotalHeight += data.nHeight; + } + + nTotalHeight += MARGIN_BOTTOM; + if ( nTotalHeight <= rc.Height() ) + { + if ( TBase::GetStyle() & WS_VSCROLL ) + { + SCROLLINFO sbInfo = {0}; + CRect rcWin; + + sbInfo.cbSize = sizeof(SCROLLINFO); + sbInfo.fMask = SIF_ALL; + + TBase::GetWindowRect(&rcWin); + TBase::GetScrollInfo(SB_VERT,&sbInfo); + sbInfo.nPos = 0; + TBase::SetScrollInfo(SB_VERT,&sbInfo,FALSE); + m_nScrollOffset = 0; + + TBase::ModifyStyle(WS_VSCROLL,0); + TBase::SetWindowPos(NULL,rcWin.left,rcWin.right,rcWin.Width(),rcWin.Height(), + SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOZORDER|SWP_FRAMECHANGED); + } + } + else + { + if ( !(TBase::GetStyle() & WS_VSCROLL) ) + { + SCROLLINFO sbInfo = {0}; + CRect rcWin; + + sbInfo.cbSize = sizeof(SCROLLINFO); + sbInfo.fMask = SIF_ALL; + + TBase::GetWindowRect(&rcWin); + TBase::ModifyStyle(0,WS_VSCROLL); + + TBase::GetScrollInfo(SB_VERT,&sbInfo); + sbInfo.fMask = SIF_ALL; + sbInfo.nPos = 0; + sbInfo.nMin = 0; + sbInfo.nMax = nTotalHeight; + sbInfo.nPage= rcWin.Height(); + TBase::SetScrollInfo(SB_VERT,&sbInfo,TRUE); + m_nScrollOffset = 0; + + TBase::SetWindowPos(NULL,rcWin.left,rcWin.right,rcWin.Width(),rcWin.Height(), + SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOZORDER|SWP_FRAMECHANGED); + } + else + { + SCROLLINFO sbInfo = {0}; + CRect rcWin; + + sbInfo.cbSize = sizeof(SCROLLINFO); + sbInfo.fMask = SIF_ALL; + + TBase::GetWindowRect(&rcWin); + TBase::ModifyStyle(0,WS_VSCROLL); + + TBase::GetScrollInfo(SB_VERT,&sbInfo); + + if (sbInfo.nMin != 0 || sbInfo.nPage != rcWin.Height() || sbInfo.nMax!= nTotalHeight + || sbInfo.nPos != (-m_nScrollOffset) ) + { + sbInfo.fMask = SIF_ALL; + sbInfo.nPos = (-m_nScrollOffset); + sbInfo.nMin = 0; + sbInfo.nMax = nTotalHeight; + sbInfo.nPage= rcWin.Height(); + TBase::SetScrollInfo(SB_VERT,&sbInfo,TRUE); + + } + } + } + + TBase::GetClientRect(rc); + + m_bNeedRecalLayout = FALSE; + } + + virtual VOID MeasureItem(LPMEASUREITEMSTRUCT){} + + virtual VOID DrawItem(LPDRAWITEMSTRUCT){} + + VOID _ResetScroll() + { + m_nScrollOffset = 0; + } + + VOID _RefreshIntern(BOOL bReCalc = TRUE, BOOL bReDraw = TRUE, BOOL bResetScroll = FALSE) + { + if (bResetScroll) + _ResetScroll(); + + if (bReCalc) + { + m_bNeedRecalLayout = TRUE; + _RecalcLayout(); + } + + if (bReDraw) + { + m_bNeedRedraw = TRUE; + _RePaint(NULL); + } + } + + BOOL OnEraseBkgnd(CDCHandle dc) + { + return TRUE; + } + + void OnSize(UINT nType, CSize /*size*/) + { + m_bNeedRecalLayout = TRUE; + _RecalcLayout(); + + m_bNeedRedraw = TRUE; + + SetMsgHandled(FALSE); + } + + LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam) + { + SetMsgHandled(FALSE); + return 0; + } + + + VOID _RePaintItem(HDC hdc, int nIndex) + { + CRect rc; + TBase::GetClientRect(&rc); + + if (rc.Width() == 0 || rc.Height() == 0 ) + return; + + if (nIndex>=(int)m_listData.GetCount()) + return; + + _CreateMemDC(hdc); + + BOOL bReleaseDC = FALSE; + if (hdc==NULL) + { + hdc = TBase::GetWindowDC(); + bReleaseDC = TRUE; + } + HBITMAP bmpTmp = m_dcMem.SelectBitmap(m_bmpMem); + + if (TRUE) + { + List_Intern_Data& data = m_listData[nIndex]; + + // ǿˢ + if ( TRUE ) + { + DRAWITEMSTRUCT drawData = {0}; + drawData.hDC = m_dcMem.m_hDC; + drawData.itemID = nIndex; + drawData.rcItem = data.rcItem; + drawData.itemData = data.lpParam; + DrawItem(&drawData); + } + + ::BitBlt(hdc,0,0,rc.Width(),rc.Height(),m_dcMem.m_hDC,0,0,SRCCOPY); + } + + m_dcMem.SelectBitmap(bmpTmp); + + if (bReleaseDC) + TBase::ReleaseDC(hdc); + } + + VOID _RePaint(HDC hdc) + { + CRect rc; + TBase::GetClientRect(&rc); + + if (rc.Width() == 0 || rc.Height() == 0 ) + return; + + _CreateMemDC(hdc); + + BOOL bReleaseDC = FALSE; + if (hdc==NULL) + { + hdc = TBase::GetWindowDC(); + bReleaseDC = TRUE; + } + HBITMAP bmpTmp = m_dcMem.SelectBitmap(m_bmpMem); + + if (!m_bNeedRedraw) + { + ::BitBlt(hdc,0,0,rc.Width(),rc.Height(),m_dcMem.m_hDC,0,0,SRCCOPY); + } + else + { + m_dcMem.FillSolidRect(0,0,rc.Width(),rc.Height(),RGB(253,254,255)); + for ( int i=0; i<(int)m_listData.GetCount(); i++) + { + List_Intern_Data& data = m_listData[i]; + + // ֻʾڵ + if ( data.rcItem.bottom > 0 && data.rcItem.top < rc.Height() ) + { + DRAWITEMSTRUCT drawData = {0}; + + drawData.hDC = m_dcMem.m_hDC; + drawData.itemID = i; + drawData.rcItem = data.rcItem; + drawData.itemData = data.lpParam; + + DrawItem(&drawData); + } + } + m_bNeedRedraw = FALSE; + ::BitBlt(hdc,0,0,rc.Width(),rc.Height(),m_dcMem.m_hDC,0,0,SRCCOPY); + } + + m_dcMem.SelectBitmap(bmpTmp); + m_bNeedRedraw = FALSE; + + if (bReleaseDC) + TBase::ReleaseDC(hdc); + } + + VOID _CreateMemDC(HDC hdc) + { + + BOOL bNeedRecreate = FALSE; + CRect rc; + TBase::GetClientRect(&rc); + + + if (!m_dcMem.m_hDC) + { + bNeedRecreate = TRUE; + } + else + { + CSize sz; + BITMAP bitmap; + m_bmpMem.GetBitmap(&bitmap); + if ( bitmap.bmWidth != rc.Width() || bitmap.bmHeight != rc.Height() ) + { + bNeedRecreate = TRUE; + } + } + + if ( bNeedRecreate ) + { + BOOL bReleaseDC = FALSE; + HWND hWndDesk = ::GetDesktopWindow(); + if (hdc==NULL) + { + // hdc = TBase::GetWindowDC(); + + hdc = ::GetDC(hWndDesk); + bReleaseDC = TRUE; + } + + if (m_dcMem.m_hDC) + m_dcMem.DeleteDC(); + if (m_bmpMem.m_hBitmap) + m_bmpMem.DeleteObject(); + + + m_dcMem.Attach( ::CreateCompatibleDC(hdc) ); + m_bmpMem.CreateCompatibleBitmap( hdc, rc.Width(), rc.Height() ); + m_bNeedRedraw = TRUE; + + if (bReleaseDC) + { + ::ReleaseDC(hWndDesk,hdc); + //TBase::ReleaseDC(hdc); + } + } + + } + + VOID _Init() + { + m_bNeedRedraw = TRUE; + m_bNeedRecalLayout = TRUE; + m_nColumnWidth = -1; + m_nCurSel = DEFAULT_SEL_VALUE; + m_nScrollOffset = 0; + } + +private: + + + class List_Intern_Data + { + public: + List_Intern_Data() + { + nHeight = 0; + lpParam = 0; + }; + + int nHeight; // ߶ + DWORD_PTR lpParam; // setIJ + CString strText; // text⣬windowsĺ + CRect rcItem; // item + }; + + CAtlArray m_listData; + CDC m_dcMem; + CBitmap m_bmpMem; + BOOL m_bNeedRedraw; + LONG m_nScrollOffset; + BOOL m_bNeedRecalLayout; + int m_nCurSel; + int m_nColumnWidth; +}; + diff --git a/Client/Client/GUI/BKWin/wtl/atlapp.h b/Client/Client/GUI/BKWin/wtl/atlapp.h new file mode 100644 index 00000000..8f0d657f --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlapp.h @@ -0,0 +1,1685 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLAPP_H__ +#define __ATLAPP_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifndef __ATLBASE_H__ + #error atlapp.h requires atlbase.h to be included first +#endif + +#ifndef _WIN32_WCE + #if (WINVER < 0x0400) + #error WTL requires Windows version 4.0 or higher + #endif + + #if (_WIN32_IE < 0x0300) + #error WTL requires IE version 3.0 or higher + #endif +#endif + +#ifdef _ATL_NO_COMMODULE + #error WTL requires that _ATL_NO_COMMODULE is not defined +#endif // _ATL_NO_COMMODULE + +#if defined(_WIN32_WCE) && defined(_ATL_MIN_CRT) + #pragma message("Warning: WTL for Windows CE doesn't use _ATL_MIN_CRT") +#endif // defined(_WIN32_WCE) && defined(_ATL_MIN_CRT) + +#include +#if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE) + #include // for _beginthreadex +#endif + +#if (_ATL_VER < 0x0800) && !defined(_DEBUG) + #include +#endif + +#include +#ifndef _WIN32_WCE +#pragma comment(lib, "comctl32.lib") +#endif // !_WIN32_WCE + +#ifndef _WIN32_WCE + #include "atlres.h" +#else // CE specific + #include "atlresce.h" +#endif // _WIN32_WCE + +// We need to disable this warning because of template class arguments +#pragma warning(disable: 4127) + + +/////////////////////////////////////////////////////////////////////////////// +// WTL version number + +#define _WTL_VER 0x0800 + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CMessageFilter +// CIdleHandler +// CMessageLoop +// +// CAppModule +// CServerAppModule +// +// Global functions: +// AtlGetDefaultGuiFont() +// AtlCreateBoldFont() +// AtlInitCommonControls() + + +/////////////////////////////////////////////////////////////////////////////// +// Global support for Windows CE + +#ifdef _WIN32_WCE + +#ifndef SW_SHOWDEFAULT + #define SW_SHOWDEFAULT SW_SHOWNORMAL +#endif // !SW_SHOWDEFAULT + +// These get's OR-ed in a constant and will have no effect. +// Defining them reduces the number of #ifdefs required for CE. +#define LR_DEFAULTSIZE 0 +#define LR_LOADFROMFILE 0 + +#ifndef SM_CXCURSOR + #define SM_CXCURSOR 13 +#endif +#ifndef SM_CYCURSOR + #define SM_CYCURSOR 14 +#endif + +inline BOOL IsMenu(HMENU hMenu) +{ + MENUITEMINFO mii = { sizeof(MENUITEMINFO) }; + ::SetLastError(0); + BOOL bRet = ::GetMenuItemInfo(hMenu, 0, TRUE, &mii); + if(!bRet) + bRet = (::GetLastError() != ERROR_INVALID_MENU_HANDLE) ? TRUE : FALSE; + return bRet; +} + +#if (_WIN32_WCE >= 410) +extern "C" void WINAPI ListView_SetItemSpacing(HWND hwndLV, int iHeight); +#endif // (_WIN32_WCE >= 410) + +inline int MulDiv(IN int nNumber, IN int nNumerator, IN int nDenominator) +{ + __int64 multiple = nNumber * nNumerator; + return static_cast(multiple / nDenominator); +} + +#if (_ATL_VER >= 0x0800) + +#ifndef _WTL_KEEP_WS_OVERLAPPEDWINDOW + #ifdef WS_OVERLAPPEDWINDOW + #undef WS_OVERLAPPEDWINDOW + #define WS_OVERLAPPEDWINDOW 0 + #endif // WS_OVERLAPPEDWINDOW +#endif // !_WTL_KEEP_WS_OVERLAPPEDWINDOW + +#ifndef RDW_FRAME + #define RDW_FRAME 0 +#endif // !RDW_FRAME + +#ifndef WM_WINDOWPOSCHANGING + #define WM_WINDOWPOSCHANGING 0 +#endif // !WM_WINDOWPOSCHANGING + +#define FreeResource(x) +#define UnlockResource(x) + +namespace ATL +{ + inline HRESULT CComModule::RegisterClassObjects(DWORD /*dwClsContext*/, DWORD /*dwFlags*/) throw() + { return E_NOTIMPL; } + inline HRESULT CComModule::RevokeClassObjects() throw() + { return E_NOTIMPL; } +}; // namespace ATL + +#ifndef lstrlenW + #define lstrlenW (int)ATL::lstrlenW +#endif // lstrlenW + +inline int WINAPI lstrlenA(LPCSTR lpszString) +{ return ATL::lstrlenA(lpszString); } + +#ifdef lstrcpyn + #undef lstrcpyn + #define lstrcpyn ATL::lstrcpynW +#endif // lstrcpyn + +#ifndef SetWindowLongPtrW + inline LONG_PTR tmp_SetWindowLongPtrW( HWND hWnd, int nIndex, LONG_PTR dwNewLong ) + { + return( ::SetWindowLongW( hWnd, nIndex, LONG( dwNewLong ) ) ); + } + #define SetWindowLongPtrW tmp_SetWindowLongPtrW +#endif + +#ifndef GetWindowLongPtrW + inline LONG_PTR tmp_GetWindowLongPtrW( HWND hWnd, int nIndex ) + { + return( ::GetWindowLongW( hWnd, nIndex ) ); + } + #define GetWindowLongPtrW tmp_GetWindowLongPtrW +#endif + +#ifndef LongToPtr + #define LongToPtr(x) ((void*)x) +#endif + +#ifndef PtrToInt + #define PtrToInt( p ) ((INT)(INT_PTR) (p) ) +#endif + +#else // !(_ATL_VER >= 0x0800) + +#ifdef lstrlenW + #undef lstrlenW + #define lstrlenW (int)::wcslen +#endif // lstrlenW + +#define lstrlenA (int)strlen + +#ifndef lstrcpyn + inline LPTSTR lstrcpyn(LPTSTR lpstrDest, LPCTSTR lpstrSrc, int nLength) + { + if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0) + return NULL; + int nLen = min(lstrlen(lpstrSrc), nLength - 1); + LPTSTR lpstrRet = (LPTSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(TCHAR)); + lpstrDest[nLen] = 0; + return lpstrRet; + } +#endif // !lstrcpyn + +#ifndef lstrcpynW + inline LPWSTR lstrcpynW(LPWSTR lpstrDest, LPCWSTR lpstrSrc, int nLength) + { + return lstrcpyn(lpstrDest, lpstrSrc, nLength); // WinCE is Unicode only + } +#endif // !lstrcpynW + +#ifndef lstrcpynA + inline LPSTR lstrcpynA(LPSTR lpstrDest, LPCSTR lpstrSrc, int nLength) + { + if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0) + return NULL; + int nLen = min(lstrlenA(lpstrSrc), nLength - 1); + LPSTR lpstrRet = (LPSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(char)); + lpstrDest[nLen] = 0; + return lpstrRet; + } +#endif // !lstrcpyn + +#ifdef TrackPopupMenu + #undef TrackPopupMenu +#endif // TrackPopupMenu + +#define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \ +static CWndClassInfo& GetWndClassInfo() \ +{ \ + static CWndClassInfo wc = \ + { \ + { style, StartWindowProc, \ + 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \ + NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \ + }; \ + return wc; \ +} + +#ifndef _MAX_FNAME + #define _MAX_FNAME _MAX_PATH +#endif // _MAX_FNAME + +#if (_WIN32_WCE < 400) + #define MAKEINTATOM(i) (LPTSTR)((ULONG_PTR)((WORD)(i))) +#endif // (_WIN32_WCE < 400) + +#if (_WIN32_WCE < 410) + #define WHEEL_PAGESCROLL (UINT_MAX) + #define WHEEL_DELTA 120 +#endif // (_WIN32_WCE < 410) + +#ifdef DrawIcon + #undef DrawIcon +#endif + +#ifndef VARCMP_LT + #define VARCMP_LT 0 +#endif +#ifndef VARCMP_EQ + #define VARCMP_EQ 1 +#endif +#ifndef VARCMP_GT + #define VARCMP_GT 2 +#endif +#ifndef VARCMP_NULL + #define VARCMP_NULL 3 +#endif + +#ifndef RDW_ALLCHILDREN + #define RDW_ALLCHILDREN 0 +#endif + +#endif // !(_ATL_VER >= 0x0800) + +#endif // _WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// Global support for using original VC++ 6.0 headers with WTL + +#ifndef _ATL_NO_OLD_HEADERS_WIN64 +#if !defined(_WIN64) && (_ATL_VER < 0x0700) + + #ifndef PSM_INSERTPAGE + #define PSM_INSERTPAGE (WM_USER + 119) + #endif // !PSM_INSERTPAGE + + #ifndef GetClassLongPtr + #define GetClassLongPtrA GetClassLongA + #define GetClassLongPtrW GetClassLongW + #ifdef UNICODE + #define GetClassLongPtr GetClassLongPtrW + #else + #define GetClassLongPtr GetClassLongPtrA + #endif // !UNICODE + #endif // !GetClassLongPtr + + #ifndef GCLP_HICONSM + #define GCLP_HICONSM (-34) + #endif // !GCLP_HICONSM + + #ifndef GetWindowLongPtr + #define GetWindowLongPtrA GetWindowLongA + #define GetWindowLongPtrW GetWindowLongW + #ifdef UNICODE + #define GetWindowLongPtr GetWindowLongPtrW + #else + #define GetWindowLongPtr GetWindowLongPtrA + #endif // !UNICODE + #endif // !GetWindowLongPtr + + #ifndef SetWindowLongPtr + #define SetWindowLongPtrA SetWindowLongA + #define SetWindowLongPtrW SetWindowLongW + #ifdef UNICODE + #define SetWindowLongPtr SetWindowLongPtrW + #else + #define SetWindowLongPtr SetWindowLongPtrA + #endif // !UNICODE + #endif // !SetWindowLongPtr + + #ifndef GWLP_WNDPROC + #define GWLP_WNDPROC (-4) + #endif + #ifndef GWLP_HINSTANCE + #define GWLP_HINSTANCE (-6) + #endif + #ifndef GWLP_HWNDPARENT + #define GWLP_HWNDPARENT (-8) + #endif + #ifndef GWLP_USERDATA + #define GWLP_USERDATA (-21) + #endif + #ifndef GWLP_ID + #define GWLP_ID (-12) + #endif + + #ifndef DWLP_MSGRESULT + #define DWLP_MSGRESULT 0 + #endif + + typedef long LONG_PTR; + typedef unsigned long ULONG_PTR; + typedef ULONG_PTR DWORD_PTR; + + #ifndef HandleToUlong + #define HandleToUlong( h ) ((ULONG)(ULONG_PTR)(h) ) + #endif + #ifndef HandleToLong + #define HandleToLong( h ) ((LONG)(LONG_PTR) (h) ) + #endif + #ifndef LongToHandle + #define LongToHandle( h) ((HANDLE)(LONG_PTR) (h)) + #endif + #ifndef PtrToUlong + #define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) ) + #endif + #ifndef PtrToLong + #define PtrToLong( p ) ((LONG)(LONG_PTR) (p) ) + #endif + #ifndef PtrToUint + #define PtrToUint( p ) ((UINT)(UINT_PTR) (p) ) + #endif + #ifndef PtrToInt + #define PtrToInt( p ) ((INT)(INT_PTR) (p) ) + #endif + #ifndef PtrToUshort + #define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) ) + #endif + #ifndef PtrToShort + #define PtrToShort( p ) ((short)(LONG_PTR)(p) ) + #endif + #ifndef IntToPtr + #define IntToPtr( i ) ((VOID *)(INT_PTR)((int)i)) + #endif + #ifndef UIntToPtr + #define UIntToPtr( ui ) ((VOID *)(UINT_PTR)((unsigned int)ui)) + #endif + #ifndef LongToPtr + #define LongToPtr( l ) ((VOID *)(LONG_PTR)((long)l)) + #endif + #ifndef ULongToPtr + #define ULongToPtr( ul ) ((VOID *)(ULONG_PTR)((unsigned long)ul)) + #endif + +#endif // !defined(_WIN64) && (_ATL_VER < 0x0700) +#endif // !_ATL_NO_OLD_HEADERS_WIN64 + + +/////////////////////////////////////////////////////////////////////////////// +// Global support for SecureHelper functions + +#ifndef _TRUNCATE + #define _TRUNCATE ((size_t)-1) +#endif + +#ifndef _ERRCODE_DEFINED + #define _ERRCODE_DEFINED + typedef int errno_t; +#endif + +#ifndef _SECURECRT_ERRCODE_VALUES_DEFINED + #define _SECURECRT_ERRCODE_VALUES_DEFINED + #define EINVAL 22 + #define STRUNCATE 80 +#endif + +#ifndef _countof + #define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0])) +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// Miscellaneous global support + +// define useful macros from winuser.h +#ifndef IS_INTRESOURCE + #define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0) +#endif // IS_INTRESOURCE + +// protect template members from windowsx.h macros +#ifdef _INC_WINDOWSX + #undef SubclassWindow +#endif // _INC_WINDOWSX + +// define useful macros from windowsx.h +#ifndef GET_X_LPARAM + #define GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam)) +#endif +#ifndef GET_Y_LPARAM + #define GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam)) +#endif + +// Dummy structs for compiling with /CLR +#if (_MSC_VER >= 1300) && defined(_MANAGED) + __if_not_exists(_IMAGELIST::_IMAGELIST) { struct _IMAGELIST { }; } + __if_not_exists(_TREEITEM::_TREEITEM) { struct _TREEITEM { }; } + __if_not_exists(_PSP::_PSP) { struct _PSP { }; } +#endif + +// Define ATLVERIFY macro for ATL3 +#if (_ATL_VER < 0x0700) + #ifndef ATLVERIFY + #ifdef _DEBUG + #define ATLVERIFY(expr) ATLASSERT(expr) + #else + #define ATLVERIFY(expr) (expr) + #endif // DEBUG + #endif // ATLVERIFY +#endif // (_ATL_VER < 0x0700) + +// Forward declaration for ATL3 fix +//#if (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE) + namespace ATL { HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor); }; +//#endif + + +namespace WTL +{ + +#if (_ATL_VER >= 0x0700) + DECLARE_TRACE_CATEGORY(atlTraceUI); + #ifdef _DEBUG + __declspec(selectany) ATL::CTraceCategory atlTraceUI(_T("atlTraceUI")); + #endif // _DEBUG +#else // !(_ATL_VER >= 0x0700) + enum wtlTraceFlags + { + atlTraceUI = 0x10000000 + }; +#endif // !(_ATL_VER >= 0x0700) + +// Windows version helper +inline bool AtlIsOldWindows() +{ + OSVERSIONINFO ovi = { 0 }; + ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + BOOL bRet = ::GetVersionEx(&ovi); + return (!bRet || !((ovi.dwMajorVersion >= 5) || (ovi.dwMajorVersion == 4 && ovi.dwMinorVersion >= 90))); +} + +// default GUI font helper +inline HFONT AtlGetDefaultGuiFont() +{ +#ifndef _WIN32_WCE + return (HFONT)::GetStockObject(DEFAULT_GUI_FONT); +#else // CE specific + return (HFONT)::GetStockObject(SYSTEM_FONT); +#endif // _WIN32_WCE +} + +// bold font helper (NOTE: Caller owns the font, and should destroy it when done using it) +inline HFONT AtlCreateBoldFont(HFONT hFont = NULL) +{ + if(hFont == NULL) + hFont = AtlGetDefaultGuiFont(); + ATLASSERT(hFont != NULL); + HFONT hFontBold = NULL; + LOGFONT lf = { 0 }; + if(::GetObject(hFont, sizeof(LOGFONT), &lf) == sizeof(LOGFONT)) + { + lf.lfWeight = FW_BOLD; + hFontBold = ::CreateFontIndirect(&lf); + ATLASSERT(hFontBold != NULL); + } + else + { + ATLASSERT(FALSE); + } + return hFontBold; +} + +// Common Controls initialization helper +inline BOOL AtlInitCommonControls(DWORD dwFlags) +{ + INITCOMMONCONTROLSEX iccx = { sizeof(INITCOMMONCONTROLSEX), dwFlags }; + BOOL bRet = ::InitCommonControlsEx(&iccx); + ATLASSERT(bRet); + return bRet; +} + + +/////////////////////////////////////////////////////////////////////////////// +// RunTimeHelper - helper functions for Windows version and structure sizes + +// Not for Windows CE +#if defined(_WIN32_WCE) && !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) + #define _WTL_NO_RUNTIME_STRUCT_SIZE +#endif + +#ifndef _WTL_NO_RUNTIME_STRUCT_SIZE + +#ifndef _SIZEOF_STRUCT + #define _SIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member)) +#endif + +#if (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE) + #define REBARBANDINFO_V6_SIZE _SIZEOF_STRUCT(REBARBANDINFO, cxHeader) +#endif // (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE) + +#if (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE) + #define LVGROUP_V5_SIZE _SIZEOF_STRUCT(LVGROUP, uAlign) +#endif // (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE) + +#if (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE) + #define LVTILEINFO_V5_SIZE _SIZEOF_STRUCT(LVTILEINFO, puColumns) +#endif // (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE) + +#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE) + #define MCHITTESTINFO_V1_SIZE _SIZEOF_STRUCT(MCHITTESTINFO, st) +#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE) + +#if !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE) + #define NONCLIENTMETRICS_V1_SIZE _SIZEOF_STRUCT(NONCLIENTMETRICS, lfMessageFont) +#endif // !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE) + +#endif // !_WTL_NO_RUNTIME_STRUCT_SIZE + +namespace RunTimeHelper +{ +#ifndef _WIN32_WCE + inline bool IsCommCtrl6() + { + DWORD dwMajor = 0, dwMinor = 0; + HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor); + return (SUCCEEDED(hRet) && (dwMajor >= 6)); + } + + inline bool IsVista() + { + OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) }; + BOOL bRet = ::GetVersionEx(&ovi); + return ((bRet != FALSE) && (ovi.dwMajorVersion >= 6)); + } +#endif // !_WIN32_WCE + + inline int SizeOf_REBARBANDINFO() + { + int nSize = sizeof(REBARBANDINFO); +#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600) + if(!(IsVista() && IsCommCtrl6())) + nSize = REBARBANDINFO_V6_SIZE; +#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600) + return nSize; + } + +#if (_WIN32_WINNT >= 0x501) + inline int SizeOf_LVGROUP() + { + int nSize = sizeof(LVGROUP); +#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600) + if(!IsVista()) + nSize = LVGROUP_V5_SIZE; +#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600) + return nSize; + } + + inline int SizeOf_LVTILEINFO() + { + int nSize = sizeof(LVTILEINFO); +#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600) + if(!IsVista()) + nSize = LVTILEINFO_V5_SIZE; +#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600) + return nSize; + } +#endif // (_WIN32_WINNT >= 0x501) + + inline int SizeOf_MCHITTESTINFO() + { + int nSize = sizeof(MCHITTESTINFO); +#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) + if(!(IsVista() && IsCommCtrl6())) + nSize = MCHITTESTINFO_V1_SIZE; +#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) + return nSize; + } + +#ifndef _WIN32_WCE + inline int SizeOf_NONCLIENTMETRICS() + { + int nSize = sizeof(NONCLIENTMETRICS); +#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600) + if(!IsVista()) + nSize = NONCLIENTMETRICS_V1_SIZE; +#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600) + return nSize; + } +#endif // !_WIN32_WCE +}; + + +/////////////////////////////////////////////////////////////////////////////// +// ModuleHelper - helper functions for ATL3 and ATL7 module classes + +namespace ModuleHelper +{ + inline HINSTANCE GetModuleInstance() + { +#if (_ATL_VER >= 0x0700) + return ATL::_AtlBaseModule.GetModuleInstance(); +#else // !(_ATL_VER >= 0x0700) + return ATL::_pModule->GetModuleInstance(); +#endif // !(_ATL_VER >= 0x0700) + } + + inline HINSTANCE GetResourceInstance() + { +#if (_ATL_VER >= 0x0700) + return ATL::_AtlBaseModule.GetResourceInstance(); +#else // !(_ATL_VER >= 0x0700) + return ATL::_pModule->GetResourceInstance(); +#endif // !(_ATL_VER >= 0x0700) + } + + inline void AddCreateWndData(ATL::_AtlCreateWndData* pData, void* pObject) + { +#if (_ATL_VER >= 0x0700) + ATL::_AtlWinModule.AddCreateWndData(pData, pObject); +#else // !(_ATL_VER >= 0x0700) + ATL::_pModule->AddCreateWndData(pData, pObject); +#endif // !(_ATL_VER >= 0x0700) + } + + inline void* ExtractCreateWndData() + { +#if (_ATL_VER >= 0x0700) + return ATL::_AtlWinModule.ExtractCreateWndData(); +#else // !(_ATL_VER >= 0x0700) + return ATL::_pModule->ExtractCreateWndData(); +#endif // !(_ATL_VER >= 0x0700) + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// SecureHelper - helper functions for VS2005 secure CRT + +namespace SecureHelper +{ + inline void strcpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc) + { +#if _SECURE_ATL + ATL::Checked::strcpy_s(lpstrDest, cchDest, lpstrSrc); +#else + if(cchDest > (size_t)lstrlenA(lpstrSrc)) + ATLVERIFY(lstrcpyA(lpstrDest, lpstrSrc) != NULL); + else + ATLASSERT(FALSE); +#endif + } + + inline void strcpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc) + { +#if _SECURE_ATL + ATL::Checked::wcscpy_s(lpstrDest, cchDest, lpstrSrc); +#else + if(cchDest > (size_t)lstrlenW(lpstrSrc)) + ATLVERIFY(lstrcpyW(lpstrDest, lpstrSrc) != NULL); + else + ATLASSERT(FALSE); +#endif + } + + inline void strcpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc) + { +#ifdef _UNICODE + strcpyW_x(lpstrDest, cchDest, lpstrSrc); +#else + strcpyA_x(lpstrDest, cchDest, lpstrSrc); +#endif + } + + inline errno_t strncpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc, size_t cchCount) + { +#if _SECURE_ATL + return ATL::Checked::strncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount); +#else + errno_t nRet = 0; + if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL) + { + nRet = EINVAL; + } + else if(cchCount == _TRUNCATE) + { + cchCount = min(cchDest - 1, size_t(lstrlenA(lpstrSrc))); + nRet = STRUNCATE; + } + else if(cchDest <= cchCount) + { + lpstrDest[0] = 0; + nRet = EINVAL; + } + if(nRet == 0 || nRet == STRUNCATE) + nRet = (lstrcpynA(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL; + ATLASSERT(nRet == 0 || nRet == STRUNCATE); + return nRet; +#endif + } + + inline errno_t strncpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc, size_t cchCount) + { +#if _SECURE_ATL + return ATL::Checked::wcsncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount); +#else + errno_t nRet = 0; + if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL) + { + nRet = EINVAL; + } + else if(cchCount == _TRUNCATE) + { + cchCount = min(cchDest - 1, size_t(lstrlenW(lpstrSrc))); + nRet = STRUNCATE; + } + else if(cchDest <= cchCount) + { + lpstrDest[0] = 0; + nRet = EINVAL; + } + if(nRet == 0 || nRet == STRUNCATE) + nRet = (lstrcpynW(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL; + ATLASSERT(nRet == 0 || nRet == STRUNCATE); + return nRet; +#endif + } + + inline errno_t strncpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc, size_t cchCount) + { +#ifdef _UNICODE + return strncpyW_x(lpstrDest, cchDest, lpstrSrc, cchCount); +#else + return strncpyA_x(lpstrDest, cchDest, lpstrSrc, cchCount); +#endif + } + + inline void strcatA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc) + { +#if _SECURE_ATL + ATL::Checked::strcat_s(lpstrDest, cchDest, lpstrSrc); +#else + if(cchDest > (size_t)lstrlenA(lpstrSrc)) + ATLVERIFY(lstrcatA(lpstrDest, lpstrSrc) != NULL); + else + ATLASSERT(FALSE); +#endif + } + + inline void strcatW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc) + { +#if _SECURE_ATL + ATL::Checked::wcscat_s(lpstrDest, cchDest, lpstrSrc); +#else + if(cchDest > (size_t)lstrlenW(lpstrSrc)) + ATLVERIFY(lstrcatW(lpstrDest, lpstrSrc) != NULL); + else + ATLASSERT(FALSE); +#endif + } + + inline void strcat_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc) + { +#ifdef _UNICODE + strcatW_x(lpstrDest, cchDest, lpstrSrc); +#else + strcatA_x(lpstrDest, cchDest, lpstrSrc); +#endif + } + + inline void memcpy_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc) + { +#if _SECURE_ATL + ATL::Checked::memcpy_s(pDest, cbDest, pSrc, cbSrc); +#else + if(cbDest >= cbSrc) + memcpy(pDest, pSrc, cbSrc); + else + ATLASSERT(FALSE); +#endif + } + + inline void memmove_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc) + { +#if _SECURE_ATL + ATL::Checked::memmove_s(pDest, cbDest, pSrc, cbSrc); +#else + if(cbDest >= cbSrc) + memmove(pDest, pSrc, cbSrc); + else + ATLASSERT(FALSE); +#endif + } + + inline int vsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args) + { +#if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE) + return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args); +#else + cchBuff; // Avoid unused argument warning + return _vstprintf(lpstrBuff, lpstrFormat, args); +#endif + } + + inline int wvsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args) + { +#if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE) + return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args); +#else + cchBuff; // Avoid unused argument warning + return ::wvsprintf(lpstrBuff, lpstrFormat, args); +#endif + } + + inline int sprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...) + { + va_list args; + va_start(args, lpstrFormat); + int nRes = vsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args); + va_end(args); + return nRes; + } + + inline int wsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...) + { + va_list args; + va_start(args, lpstrFormat); + int nRes = wvsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args); + va_end(args); + return nRes; + } +}; // namespace SecureHelper + + +/////////////////////////////////////////////////////////////////////////////// +// CMessageFilter - Interface for message filter support + +class CMessageFilter +{ +public: + virtual BOOL PreTranslateMessage(MSG* pMsg) = 0; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CIdleHandler - Interface for idle processing + +class CIdleHandler +{ +public: + virtual BOOL OnIdle() = 0; +}; + +#ifndef _ATL_NO_OLD_NAMES + // for compatilibility with old names only + typedef CIdleHandler CUpdateUIObject; + #define DoUpdate OnIdle +#endif // !_ATL_NO_OLD_NAMES + + +/////////////////////////////////////////////////////////////////////////////// +// CMessageLoop - message loop implementation + +class CMessageLoop +{ +public: + ATL::CSimpleArray m_aMsgFilter; + ATL::CSimpleArray m_aIdleHandler; + MSG m_msg; + +// Message filter operations + BOOL AddMessageFilter(CMessageFilter* pMessageFilter) + { + return m_aMsgFilter.Add(pMessageFilter); + } + + BOOL RemoveMessageFilter(CMessageFilter* pMessageFilter) + { + return m_aMsgFilter.Remove(pMessageFilter); + } + +// Idle handler operations + BOOL AddIdleHandler(CIdleHandler* pIdleHandler) + { + return m_aIdleHandler.Add(pIdleHandler); + } + + BOOL RemoveIdleHandler(CIdleHandler* pIdleHandler) + { + return m_aIdleHandler.Remove(pIdleHandler); + } + +#ifndef _ATL_NO_OLD_NAMES + // for compatilibility with old names only + BOOL AddUpdateUI(CIdleHandler* pIdleHandler) + { + ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and AddUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n")); + return AddIdleHandler(pIdleHandler); + } + + BOOL RemoveUpdateUI(CIdleHandler* pIdleHandler) + { + ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and RemoveUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n")); + return RemoveIdleHandler(pIdleHandler); + } +#endif // !_ATL_NO_OLD_NAMES + +// message loop + int Run() + { + BOOL bDoIdle = TRUE; + int nIdleCount = 0; + BOOL bRet; + + for(;;) + { + while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE)) + { + if(!OnIdle(nIdleCount++)) + bDoIdle = FALSE; + } + + bRet = ::GetMessage(&m_msg, NULL, 0, 0); + + if(bRet == -1) + { + ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n")); + continue; // error, don't process + } + else if(!bRet) + { + ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n")); + break; // WM_QUIT, exit message loop + } + + if(!PreTranslateMessage(&m_msg)) + { + ::TranslateMessage(&m_msg); + ::DispatchMessage(&m_msg); + } + + if(IsIdleMessage(&m_msg)) + { + bDoIdle = TRUE; + nIdleCount = 0; + } + } + + return (int)m_msg.wParam; + } + + static BOOL IsIdleMessage(MSG* pMsg) + { + // These messages should NOT cause idle processing + switch(pMsg->message) + { + case WM_MOUSEMOVE: +#ifndef _WIN32_WCE + case WM_NCMOUSEMOVE: +#endif // !_WIN32_WCE + case WM_PAINT: + case 0x0118: // WM_SYSTIMER (caret blink) + return FALSE; + } + + return TRUE; + } + +// Overrideables + // Override to change message filtering + virtual BOOL PreTranslateMessage(MSG* pMsg) + { + // loop backwards + for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--) + { + CMessageFilter* pMessageFilter = m_aMsgFilter[i]; + if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg)) + return TRUE; + } + return FALSE; // not translated + } + + // override to change idle processing + virtual BOOL OnIdle(int /*nIdleCount*/) + { + for(int i = 0; i < m_aIdleHandler.GetSize(); i++) + { + CIdleHandler* pIdleHandler = m_aIdleHandler[i]; + if(pIdleHandler != NULL) + pIdleHandler->OnIdle(); + } + return FALSE; // don't continue + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CStaticDataInitCriticalSectionLock and CWindowCreateCriticalSectionLock +// internal classes to manage critical sections for both ATL3 and ATL7 + +class CStaticDataInitCriticalSectionLock +{ +public: +#if (_ATL_VER >= 0x0700) + ATL::CComCritSecLock m_cslock; + + CStaticDataInitCriticalSectionLock() : m_cslock(ATL::_pAtlModule->m_csStaticDataInitAndTypeInfo, false) + { } +#endif // (_ATL_VER >= 0x0700) + + HRESULT Lock() + { +#if (_ATL_VER >= 0x0700) + return m_cslock.Lock(); +#else // !(_ATL_VER >= 0x0700) + ::EnterCriticalSection(&ATL::_pModule->m_csStaticDataInit); + return S_OK; +#endif // !(_ATL_VER >= 0x0700) + } + + void Unlock() + { +#if (_ATL_VER >= 0x0700) + m_cslock.Unlock(); +#else // !(_ATL_VER >= 0x0700) + ::LeaveCriticalSection(&ATL::_pModule->m_csStaticDataInit); +#endif // !(_ATL_VER >= 0x0700) + } +}; + + +class CWindowCreateCriticalSectionLock +{ +public: +#if (_ATL_VER >= 0x0700) + ATL::CComCritSecLock m_cslock; + + CWindowCreateCriticalSectionLock() : m_cslock(ATL::_AtlWinModule.m_csWindowCreate, false) + { } +#endif // (_ATL_VER >= 0x0700) + + HRESULT Lock() + { +#if (_ATL_VER >= 0x0700) + return m_cslock.Lock(); +#else // !(_ATL_VER >= 0x0700) + ::EnterCriticalSection(&ATL::_pModule->m_csWindowCreate); + return S_OK; +#endif // !(_ATL_VER >= 0x0700) + } + + void Unlock() + { +#if (_ATL_VER >= 0x0700) + m_cslock.Unlock(); +#else // !(_ATL_VER >= 0x0700) + ::LeaveCriticalSection(&ATL::_pModule->m_csWindowCreate); +#endif // !(_ATL_VER >= 0x0700) + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CTempBuffer - helper class for stack allocations for ATL3 + +#ifndef _WTL_STACK_ALLOC_THRESHOLD + #define _WTL_STACK_ALLOC_THRESHOLD 512 +#endif + +#if (_ATL_VER >= 0x0700) + +using ATL::CTempBuffer; + +#else // !(_ATL_VER >= 0x0700) + +#ifndef SIZE_MAX + #ifdef _WIN64 + #define SIZE_MAX _UI64_MAX + #else + #define SIZE_MAX UINT_MAX + #endif +#endif + +#pragma warning(disable: 4284) // warning for operator -> + +template +class CTempBuffer +{ +public: + CTempBuffer() : m_p(NULL) + { + } + + CTempBuffer(size_t nElements) : m_p(NULL) + { + Allocate(nElements); + } + + ~CTempBuffer() + { + if(m_p != reinterpret_cast(m_abFixedBuffer)) + free(m_p); + } + + operator T*() const + { + return m_p; + } + + T* operator ->() const + { + ATLASSERT(m_p != NULL); + return m_p; + } + + T* Allocate(size_t nElements) + { + ATLASSERT(nElements <= (SIZE_MAX / sizeof(T))); + return AllocateBytes(nElements * sizeof(T)); + } + + T* AllocateBytes(size_t nBytes) + { + ATLASSERT(m_p == NULL); + if(nBytes > t_nFixedBytes) + m_p = static_cast(malloc(nBytes)); + else + m_p = reinterpret_cast(m_abFixedBuffer); + + return m_p; + } + +private: + T* m_p; + BYTE m_abFixedBuffer[t_nFixedBytes]; +}; + +#pragma warning(default: 4284) + +#endif // !(_ATL_VER >= 0x0700) + + +/////////////////////////////////////////////////////////////////////////////// +// CAppModule - module class for an application + +class CAppModule : public ATL::CComModule +{ +public: + DWORD m_dwMainThreadID; + ATL::CSimpleMap* m_pMsgLoopMap; + ATL::CSimpleArray* m_pSettingChangeNotify; + +// Overrides of CComModule::Init and Term + HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL) + { + HRESULT hRet = CComModule::Init(pObjMap, hInstance, pLibID); + if(FAILED(hRet)) + return hRet; + + m_dwMainThreadID = ::GetCurrentThreadId(); + typedef ATL::CSimpleMap _mapClass; + m_pMsgLoopMap = NULL; + ATLTRY(m_pMsgLoopMap = new _mapClass); + if(m_pMsgLoopMap == NULL) + return E_OUTOFMEMORY; + m_pSettingChangeNotify = NULL; + + return hRet; + } + + void Term() + { + TermSettingChangeNotify(); + delete m_pMsgLoopMap; + CComModule::Term(); + } + +// Message loop map methods + BOOL AddMessageLoop(CMessageLoop* pMsgLoop) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddMessageLoop.\n")); + ATLASSERT(FALSE); + return FALSE; + } + + ATLASSERT(pMsgLoop != NULL); + ATLASSERT(m_pMsgLoopMap->Lookup(::GetCurrentThreadId()) == NULL); // not in map yet + + BOOL bRet = m_pMsgLoopMap->Add(::GetCurrentThreadId(), pMsgLoop); + + lock.Unlock(); + + return bRet; + } + + BOOL RemoveMessageLoop() + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveMessageLoop.\n")); + ATLASSERT(FALSE); + return FALSE; + } + + BOOL bRet = m_pMsgLoopMap->Remove(::GetCurrentThreadId()); + + lock.Unlock(); + + return bRet; + } + + CMessageLoop* GetMessageLoop(DWORD dwThreadID = ::GetCurrentThreadId()) const + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::GetMessageLoop.\n")); + ATLASSERT(FALSE); + return NULL; + } + + CMessageLoop* pLoop = m_pMsgLoopMap->Lookup(dwThreadID); + + lock.Unlock(); + + return pLoop; + } + +// Setting change notify methods + // Note: Call this from the main thread for MSDI apps + BOOL InitSettingChangeNotify(DLGPROC pfnDlgProc = _SettingChangeDlgProc) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::InitSettingChangeNotify.\n")); + ATLASSERT(FALSE); + return FALSE; + } + + if(m_pSettingChangeNotify == NULL) + { + typedef ATL::CSimpleArray _notifyClass; + ATLTRY(m_pSettingChangeNotify = new _notifyClass); + ATLASSERT(m_pSettingChangeNotify != NULL); + } + + BOOL bRet = (m_pSettingChangeNotify != NULL); + if(bRet && m_pSettingChangeNotify->GetSize() == 0) + { + // init everything + _ATL_EMPTY_DLGTEMPLATE templ; + HWND hNtfWnd = ::CreateDialogIndirect(GetModuleInstance(), &templ, NULL, pfnDlgProc); + ATLASSERT(::IsWindow(hNtfWnd)); + if(::IsWindow(hNtfWnd)) + { +// need conditional code because types don't match in winuser.h +#ifdef _WIN64 + ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, (LONG_PTR)this); +#else + ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, PtrToLong(this)); +#endif + bRet = m_pSettingChangeNotify->Add(hNtfWnd); + } + else + { + bRet = FALSE; + } + } + + lock.Unlock(); + + return bRet; + } + + void TermSettingChangeNotify() + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::TermSettingChangeNotify.\n")); + ATLASSERT(FALSE); + return; + } + + if(m_pSettingChangeNotify != NULL && m_pSettingChangeNotify->GetSize() > 0) + ::DestroyWindow((*m_pSettingChangeNotify)[0]); + delete m_pSettingChangeNotify; + m_pSettingChangeNotify = NULL; + + lock.Unlock(); + } + + BOOL AddSettingChangeNotify(HWND hWnd) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddSettingChangeNotify.\n")); + ATLASSERT(FALSE); + return FALSE; + } + + ATLASSERT(::IsWindow(hWnd)); + BOOL bRet = FALSE; + if(InitSettingChangeNotify() != FALSE) + bRet = m_pSettingChangeNotify->Add(hWnd); + + lock.Unlock(); + + return bRet; + } + + BOOL RemoveSettingChangeNotify(HWND hWnd) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveSettingChangeNotify.\n")); + ATLASSERT(FALSE); + return FALSE; + } + + BOOL bRet = FALSE; + if(m_pSettingChangeNotify != NULL) + bRet = m_pSettingChangeNotify->Remove(hWnd); + + lock.Unlock(); + + return bRet; + } + +// Implementation - setting change notify dialog template and dialog procedure + struct _ATL_EMPTY_DLGTEMPLATE : DLGTEMPLATE + { + _ATL_EMPTY_DLGTEMPLATE() + { + memset(this, 0, sizeof(_ATL_EMPTY_DLGTEMPLATE)); + style = WS_POPUP; + } + WORD wMenu, wClass, wTitle; + }; + +#ifdef _WIN64 + static INT_PTR CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +#else + static BOOL CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +#endif + { + if(uMsg == WM_SETTINGCHANGE) + { +// need conditional code because types don't match in winuser.h +#ifdef _WIN64 + CAppModule* pModule = (CAppModule*)::GetWindowLongPtr(hWnd, GWLP_USERDATA); +#else + CAppModule* pModule = (CAppModule*)LongToPtr(::GetWindowLongPtr(hWnd, GWLP_USERDATA)); +#endif + ATLASSERT(pModule != NULL); + ATLASSERT(pModule->m_pSettingChangeNotify != NULL); + const UINT uTimeout = 1500; // ms + for(int i = 1; i < pModule->m_pSettingChangeNotify->GetSize(); i++) + { +#if !defined(_WIN32_WCE) + ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_ABORTIFHUNG, uTimeout, NULL); +#elif(_WIN32_WCE >= 400) // CE specific + ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_NORMAL, uTimeout, NULL); +#else // _WIN32_WCE < 400 specific + uTimeout; + ::SendMessage((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam); +#endif + } + return TRUE; + } + return FALSE; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CServerAppModule - module class for a COM server application + +class CServerAppModule : public CAppModule +{ +public: + HANDLE m_hEventShutdown; + bool m_bActivity; + DWORD m_dwTimeOut; + DWORD m_dwPause; + +// Override of CAppModule::Init + HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL) + { + m_dwTimeOut = 5000; + m_dwPause = 1000; + return CAppModule::Init(pObjMap, hInstance, pLibID); + } + + void Term() + { + if(m_hEventShutdown != NULL && ::CloseHandle(m_hEventShutdown)) + m_hEventShutdown = NULL; + CAppModule::Term(); + } + +// COM Server methods + LONG Unlock() + { + LONG lRet = CComModule::Unlock(); + if(lRet == 0) + { + m_bActivity = true; + ::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero + } + return lRet; + } + + void MonitorShutdown() + { + for(;;) + { + ::WaitForSingleObject(m_hEventShutdown, INFINITE); + DWORD dwWait = 0; + do + { + m_bActivity = false; + dwWait = ::WaitForSingleObject(m_hEventShutdown, m_dwTimeOut); + } + while(dwWait == WAIT_OBJECT_0); + // timed out + if(!m_bActivity && m_nLockCnt == 0) // if no activity let's really bail + { +#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) && defined(_ATL_FREE_THREADED) && !defined(_WIN32_WCE) + ::CoSuspendClassObjects(); + if(!m_bActivity && m_nLockCnt == 0) +#endif + break; + } + } + // This handle should be valid now. If it isn't, + // check if _Module.Term was called first (it shouldn't) + if(::CloseHandle(m_hEventShutdown)) + m_hEventShutdown = NULL; + ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0); + } + + bool StartMonitor() + { + m_hEventShutdown = ::CreateEvent(NULL, false, false, NULL); + if(m_hEventShutdown == NULL) + return false; + DWORD dwThreadID = 0; +#if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE) + HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))MonitorProc, this, 0, (UINT*)&dwThreadID); +#else + HANDLE hThread = ::CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID); +#endif + bool bRet = (hThread != NULL); + if(bRet) + ::CloseHandle(hThread); + return bRet; + } + + static DWORD WINAPI MonitorProc(void* pv) + { + CServerAppModule* p = (CServerAppModule*)pv; + p->MonitorShutdown(); + return 0; + } + +#if (_ATL_VER < 0x0700) + // search for an occurence of string p2 in string p1 + static LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2) + { + while(p1 != NULL && *p1 != NULL) + { + LPCTSTR p = p2; + while(p != NULL && *p != NULL) + { + if(*p1 == *p) + return ::CharNext(p1); + p = ::CharNext(p); + } + p1 = ::CharNext(p1); + } + return NULL; + } +#endif // (_ATL_VER < 0x0700) +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CString forward reference (enables CString use in atluser.h and atlgdi.h) + +#if defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING) + #define _WTL_USE_CSTRING +#endif // defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING) + +#ifdef _WTL_USE_CSTRING + class CString; // forward declaration (include atlmisc.h for the whole class) +#endif // _WTL_USE_CSTRING + +// CString namespace +#ifndef _CSTRING_NS + #ifdef __ATLSTR_H__ + #define _CSTRING_NS ATL + #else + #define _CSTRING_NS WTL + #endif +#endif // _CSTRING_NS + +// Type classes namespace +#ifndef _WTYPES_NS + #ifdef __ATLTYPES_H__ + #define _WTYPES_NS + #else + #define _WTYPES_NS WTL + #endif +#endif // _WTYPES_NS + +}; // namespace WTL + + +/////////////////////////////////////////////////////////////////////////////// +// General DLL version helpers (excluded from atlbase.h if _ATL_DLL is defined) + +//#if (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE) + +namespace ATL +{ + +inline HRESULT AtlGetDllVersion(HINSTANCE hInstDLL, DLLVERSIONINFO* pDllVersionInfo) +{ + ATLASSERT(pDllVersionInfo != NULL); + if(pDllVersionInfo == NULL) + return E_INVALIDARG; + + // We must get this function explicitly because some DLLs don't implement it. + DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hInstDLL, "DllGetVersion"); + if(pfnDllGetVersion == NULL) + return E_NOTIMPL; + + return (*pfnDllGetVersion)(pDllVersionInfo); +} + +inline HRESULT AtlGetDllVersion(LPCTSTR lpstrDllName, DLLVERSIONINFO* pDllVersionInfo) +{ + HINSTANCE hInstDLL = ::LoadLibrary(lpstrDllName); + if(hInstDLL == NULL) + return E_FAIL; + HRESULT hRet = AtlGetDllVersion(hInstDLL, pDllVersionInfo); + ::FreeLibrary(hInstDLL); + return hRet; +} + +// Common Control Versions: +// Win95/WinNT 4.0 maj=4 min=00 +// IE 3.x maj=4 min=70 +// IE 4.0 maj=4 min=71 +inline HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor) +{ + ATLASSERT(pdwMajor != NULL && pdwMinor != NULL); + if(pdwMajor == NULL || pdwMinor == NULL) + return E_INVALIDARG; + + DLLVERSIONINFO dvi; + ::ZeroMemory(&dvi, sizeof(dvi)); + dvi.cbSize = sizeof(dvi); + HRESULT hRet = AtlGetDllVersion(_T("comctl32.dll"), &dvi); + + if(SUCCEEDED(hRet)) + { + *pdwMajor = dvi.dwMajorVersion; + *pdwMinor = dvi.dwMinorVersion; + } + else if(hRet == E_NOTIMPL) + { + // If DllGetVersion is not there, then the DLL is a version + // previous to the one shipped with IE 3.x + *pdwMajor = 4; + *pdwMinor = 0; + hRet = S_OK; + } + + return hRet; +} + +// Shell Versions: +// Win95/WinNT 4.0 maj=4 min=00 +// IE 3.x, IE 4.0 without Web Integrated Desktop maj=4 min=00 +// IE 4.0 with Web Integrated Desktop maj=4 min=71 +// IE 4.01 with Web Integrated Desktop maj=4 min=72 +inline HRESULT AtlGetShellVersion(LPDWORD pdwMajor, LPDWORD pdwMinor) +{ + ATLASSERT(pdwMajor != NULL && pdwMinor != NULL); + if(pdwMajor == NULL || pdwMinor == NULL) + return E_INVALIDARG; + + DLLVERSIONINFO dvi; + ::ZeroMemory(&dvi, sizeof(dvi)); + dvi.cbSize = sizeof(dvi); + HRESULT hRet = AtlGetDllVersion(_T("shell32.dll"), &dvi); + + if(SUCCEEDED(hRet)) + { + *pdwMajor = dvi.dwMajorVersion; + *pdwMinor = dvi.dwMinorVersion; + } + else if(hRet == E_NOTIMPL) + { + // If DllGetVersion is not there, then the DLL is a version + // previous to the one shipped with IE 4.x + *pdwMajor = 4; + *pdwMinor = 0; + hRet = S_OK; + } + + return hRet; +} + +}; // namespace ATL + +//#endif // (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE) + + +// These are always included +#include "atlwinx.h" +#include "atluser.h" +#include "atlgdi.h" + +#ifndef _WTL_NO_AUTOMATIC_NAMESPACE +using namespace WTL; +#endif // !_WTL_NO_AUTOMATIC_NAMESPACE + +#endif // __ATLAPP_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlcrack.h b/Client/Client/GUI/BKWin/wtl/atlcrack.h new file mode 100644 index 00000000..7708843a --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlcrack.h @@ -0,0 +1,2377 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLCRACK_H__ +#define __ATLCRACK_H__ + +#pragma once + + +/////////////////////////////////////////////////////////////////////////////// +// Message map macro for cracked handlers + +// Note about message maps with cracked handlers: +// For ATL 3.0, a message map using cracked handlers MUST use BEGIN_MSG_MAP_EX. +// For ATL 7.0 or higher, you can use BEGIN_MSG_MAP for CWindowImpl/CDialogImpl derived classes, +// but must use BEGIN_MSG_MAP_EX for classes that don't derive from CWindowImpl/CDialogImpl. + +#define BEGIN_MSG_MAP_EX(theClass) \ +public: \ + BOOL m_bMsgHandled; \ + /* "handled" management for cracked handlers */ \ + BOOL IsMsgHandled() const \ + { \ + return m_bMsgHandled; \ + } \ + void SetMsgHandled(BOOL bHandled) \ + { \ + m_bMsgHandled = bHandled; \ + } \ + BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \ + { \ + BOOL bOldMsgHandled = m_bMsgHandled; \ + BOOL bRet = _ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, dwMsgMapID); \ + m_bMsgHandled = bOldMsgHandled; \ + return bRet; \ + } \ + BOOL _ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID) \ + { \ + BOOL bHandled = TRUE; \ + hWnd; \ + uMsg; \ + wParam; \ + lParam; \ + lResult; \ + bHandled; \ + switch(dwMsgMapID) \ + { \ + case 0: + + +/////////////////////////////////////////////////////////////////////////////// +// Standard Windows message macros + +// int OnCreate(LPCREATESTRUCT lpCreateStruct) +#define MSG_WM_CREATE(func) \ + if (uMsg == WM_CREATE) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam) +#define MSG_WM_INITDIALOG(func) \ + if (uMsg == WM_INITDIALOG) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HWND)wParam, lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// BOOL OnCopyData(CWindow wnd, PCOPYDATASTRUCT pCopyDataStruct) +#define MSG_WM_COPYDATA(func) \ + if (uMsg == WM_COPYDATA) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HWND)wParam, (PCOPYDATASTRUCT)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnDestroy() +#define MSG_WM_DESTROY(func) \ + if (uMsg == WM_DESTROY) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnMove(CPoint ptPos) +#define MSG_WM_MOVE(func) \ + if (uMsg == WM_MOVE) \ + { \ + SetMsgHandled(TRUE); \ + func(_WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnSize(UINT nType, CSize size) +#define MSG_WM_SIZE(func) \ + if (uMsg == WM_SIZE) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnActivate(UINT nState, BOOL bMinimized, CWindow wndOther) +#define MSG_WM_ACTIVATE(func) \ + if (uMsg == WM_ACTIVATE) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)LOWORD(wParam), (BOOL)HIWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnSetFocus(CWindow wndOld) +#define MSG_WM_SETFOCUS(func) \ + if (uMsg == WM_SETFOCUS) \ + { \ + SetMsgHandled(TRUE); \ + func((HWND)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnKillFocus(CWindow wndFocus) +#define MSG_WM_KILLFOCUS(func) \ + if (uMsg == WM_KILLFOCUS) \ + { \ + SetMsgHandled(TRUE); \ + func((HWND)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnEnable(BOOL bEnable) +#define MSG_WM_ENABLE(func) \ + if (uMsg == WM_ENABLE) \ + { \ + SetMsgHandled(TRUE); \ + func((BOOL)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnPaint(CDCHandle dc) +#define MSG_WM_PAINT(func) \ + if (uMsg == WM_PAINT) \ + { \ + SetMsgHandled(TRUE); \ + func((HDC)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnClose() +#define MSG_WM_CLOSE(func) \ + if (uMsg == WM_CLOSE) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// BOOL OnQueryEndSession(UINT nSource, UINT uLogOff) +#define MSG_WM_QUERYENDSESSION(func) \ + if (uMsg == WM_QUERYENDSESSION) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((UINT)wParam, (UINT)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// BOOL OnQueryOpen() +#define MSG_WM_QUERYOPEN(func) \ + if (uMsg == WM_QUERYOPEN) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func(); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// BOOL OnEraseBkgnd(CDCHandle dc) +#define MSG_WM_ERASEBKGND(func) \ + if (uMsg == WM_ERASEBKGND) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HDC)wParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnSysColorChange() +#define MSG_WM_SYSCOLORCHANGE(func) \ + if (uMsg == WM_SYSCOLORCHANGE) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnEndSession(BOOL bEnding, UINT uLogOff) +#define MSG_WM_ENDSESSION(func) \ + if (uMsg == WM_ENDSESSION) \ + { \ + SetMsgHandled(TRUE); \ + func((BOOL)wParam, (UINT)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnShowWindow(BOOL bShow, UINT nStatus) +#define MSG_WM_SHOWWINDOW(func) \ + if (uMsg == WM_SHOWWINDOW) \ + { \ + SetMsgHandled(TRUE); \ + func((BOOL)wParam, (int)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HBRUSH OnCtlColorEdit(CDCHandle dc, CEdit edit) +#define MSG_WM_CTLCOLOREDIT(func) \ + if (uMsg == WM_CTLCOLOREDIT) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HBRUSH OnCtlColorListBox(CDCHandle dc, CListBox listBox) +#define MSG_WM_CTLCOLORLISTBOX(func) \ + if (uMsg == WM_CTLCOLORLISTBOX) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HBRUSH OnCtlColorBtn(CDCHandle dc, CButton button) +#define MSG_WM_CTLCOLORBTN(func) \ + if (uMsg == WM_CTLCOLORBTN) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HBRUSH OnCtlColorDlg(CDCHandle dc, CWindow wnd) +#define MSG_WM_CTLCOLORDLG(func) \ + if (uMsg == WM_CTLCOLORDLG) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HBRUSH OnCtlColorScrollBar(CDCHandle dc, CScrollBar scrollBar) +#define MSG_WM_CTLCOLORSCROLLBAR(func) \ + if (uMsg == WM_CTLCOLORSCROLLBAR) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HBRUSH OnCtlColorStatic(CDCHandle dc, CStatic wndStatic) +#define MSG_WM_CTLCOLORSTATIC(func) \ + if (uMsg == WM_CTLCOLORSTATIC) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnSettingChange(UINT uFlags, LPCTSTR lpszSection) +#define MSG_WM_SETTINGCHANGE(func) \ + if (uMsg == WM_SETTINGCHANGE) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, (LPCTSTR)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnDevModeChange(LPCTSTR lpDeviceName) +#define MSG_WM_DEVMODECHANGE(func) \ + if (uMsg == WM_DEVMODECHANGE) \ + { \ + SetMsgHandled(TRUE); \ + func((LPCTSTR)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnActivateApp(BOOL bActive, DWORD dwThreadID) +#define MSG_WM_ACTIVATEAPP(func) \ + if (uMsg == WM_ACTIVATEAPP) \ + { \ + SetMsgHandled(TRUE); \ + func((BOOL)wParam, (DWORD)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnFontChange() +#define MSG_WM_FONTCHANGE(func) \ + if (uMsg == WM_FONTCHANGE) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnTimeChange() +#define MSG_WM_TIMECHANGE(func) \ + if (uMsg == WM_TIMECHANGE) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnCancelMode() +#define MSG_WM_CANCELMODE(func) \ + if (uMsg == WM_CANCELMODE) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// BOOL OnSetCursor(CWindow wnd, UINT nHitTest, UINT message) +#define MSG_WM_SETCURSOR(func) \ + if (uMsg == WM_SETCURSOR) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// int OnMouseActivate(CWindow wndTopLevel, UINT nHitTest, UINT message) +#define MSG_WM_MOUSEACTIVATE(func) \ + if (uMsg == WM_MOUSEACTIVATE) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnChildActivate() +#define MSG_WM_CHILDACTIVATE(func) \ + if (uMsg == WM_CHILDACTIVATE) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnGetMinMaxInfo(LPMINMAXINFO lpMMI) +#define MSG_WM_GETMINMAXINFO(func) \ + if (uMsg == WM_GETMINMAXINFO) \ + { \ + SetMsgHandled(TRUE); \ + func((LPMINMAXINFO)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnIconEraseBkgnd(CDCHandle dc) +#define MSG_WM_ICONERASEBKGND(func) \ + if (uMsg == WM_ICONERASEBKGND) \ + { \ + SetMsgHandled(TRUE); \ + func((HDC)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnSpoolerStatus(UINT nStatus, UINT nJobs) +#define MSG_WM_SPOOLERSTATUS(func) \ + if (uMsg == WM_SPOOLERSTATUS) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, (UINT)LOWORD(lParam)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) +#define MSG_WM_DRAWITEM(func) \ + if (uMsg == WM_DRAWITEM) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, (LPDRAWITEMSTRUCT)lParam); \ + lResult = TRUE; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) +#define MSG_WM_MEASUREITEM(func) \ + if (uMsg == WM_MEASUREITEM) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, (LPMEASUREITEMSTRUCT)lParam); \ + lResult = TRUE; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnDeleteItem(int nIDCtl, LPDELETEITEMSTRUCT lpDeleteItemStruct) +#define MSG_WM_DELETEITEM(func) \ + if (uMsg == WM_DELETEITEM) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, (LPDELETEITEMSTRUCT)lParam); \ + lResult = TRUE; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +//int OnCharToItem(UINT nChar, UINT nIndex, CListBox listBox) +#define MSG_WM_CHARTOITEM(func) \ + if (uMsg == WM_CHARTOITEM) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// int OnVKeyToItem(UINT nKey, UINT nIndex, CListBox listBox) +#define MSG_WM_VKEYTOITEM(func) \ + if (uMsg == WM_VKEYTOITEM) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HCURSOR OnQueryDragIcon() +#define MSG_WM_QUERYDRAGICON(func) \ + if (uMsg == WM_QUERYDRAGICON) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func(); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// int OnCompareItem(int nIDCtl, LPCOMPAREITEMSTRUCT lpCompareItemStruct) +#define MSG_WM_COMPAREITEM(func) \ + if (uMsg == WM_COMPAREITEM) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((UINT)wParam, (LPCOMPAREITEMSTRUCT)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnCompacting(UINT nCpuTime) +#define MSG_WM_COMPACTING(func) \ + if (uMsg == WM_COMPACTING) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct) +#define MSG_WM_NCCREATE(func) \ + if (uMsg == WM_NCCREATE) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNcDestroy() +#define MSG_WM_NCDESTROY(func) \ + if (uMsg == WM_NCDESTROY) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam) +#define MSG_WM_NCCALCSIZE(func) \ + if (uMsg == WM_NCCALCSIZE) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((BOOL)wParam, lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// UINT OnNcHitTest(CPoint point) +#define MSG_WM_NCHITTEST(func) \ + if (uMsg == WM_NCHITTEST) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func(_WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNcPaint(CRgn rgn) +#define MSG_WM_NCPAINT(func) \ + if (uMsg == WM_NCPAINT) \ + { \ + SetMsgHandled(TRUE); \ + func((HRGN)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// BOOL OnNcActivate(BOOL bActive) +#define MSG_WM_NCACTIVATE(func) \ + if (uMsg == WM_NCACTIVATE) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((BOOL)wParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// UINT OnGetDlgCode(LPMSG lpMsg) +#define MSG_WM_GETDLGCODE(func) \ + if (uMsg == WM_GETDLGCODE) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((LPMSG)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNcMouseMove(UINT nHitTest, CPoint point) +#define MSG_WM_NCMOUSEMOVE(func) \ + if (uMsg == WM_NCMOUSEMOVE) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNcLButtonDown(UINT nHitTest, CPoint point) +#define MSG_WM_NCLBUTTONDOWN(func) \ + if (uMsg == WM_NCLBUTTONDOWN) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNcLButtonUp(UINT nHitTest, CPoint point) +#define MSG_WM_NCLBUTTONUP(func) \ + if (uMsg == WM_NCLBUTTONUP) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNcLButtonDblClk(UINT nHitTest, CPoint point) +#define MSG_WM_NCLBUTTONDBLCLK(func) \ + if (uMsg == WM_NCLBUTTONDBLCLK) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNcRButtonDown(UINT nHitTest, CPoint point) +#define MSG_WM_NCRBUTTONDOWN(func) \ + if (uMsg == WM_NCRBUTTONDOWN) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNcRButtonUp(UINT nHitTest, CPoint point) +#define MSG_WM_NCRBUTTONUP(func) \ + if (uMsg == WM_NCRBUTTONUP) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNcRButtonDblClk(UINT nHitTest, CPoint point) +#define MSG_WM_NCRBUTTONDBLCLK(func) \ + if (uMsg == WM_NCRBUTTONDBLCLK) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNcMButtonDown(UINT nHitTest, CPoint point) +#define MSG_WM_NCMBUTTONDOWN(func) \ + if (uMsg == WM_NCMBUTTONDOWN) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNcMButtonUp(UINT nHitTest, CPoint point) +#define MSG_WM_NCMBUTTONUP(func) \ + if (uMsg == WM_NCMBUTTONUP) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNcMButtonDblClk(UINT nHitTest, CPoint point) +#define MSG_WM_NCMBUTTONDBLCLK(func) \ + if (uMsg == WM_NCMBUTTONDBLCLK) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +#define MSG_WM_KEYDOWN(func) \ + if (uMsg == WM_KEYDOWN) \ + { \ + SetMsgHandled(TRUE); \ + func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) +#define MSG_WM_KEYUP(func) \ + if (uMsg == WM_KEYUP) \ + { \ + SetMsgHandled(TRUE); \ + func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) +#define MSG_WM_CHAR(func) \ + if (uMsg == WM_CHAR) \ + { \ + SetMsgHandled(TRUE); \ + func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags) +#define MSG_WM_DEADCHAR(func) \ + if (uMsg == WM_DEADCHAR) \ + { \ + SetMsgHandled(TRUE); \ + func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +#define MSG_WM_SYSKEYDOWN(func) \ + if (uMsg == WM_SYSKEYDOWN) \ + { \ + SetMsgHandled(TRUE); \ + func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) +#define MSG_WM_SYSKEYUP(func) \ + if (uMsg == WM_SYSKEYUP) \ + { \ + SetMsgHandled(TRUE); \ + func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags) +#define MSG_WM_SYSCHAR(func) \ + if (uMsg == WM_SYSCHAR) \ + { \ + SetMsgHandled(TRUE); \ + func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnSysDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags) +#define MSG_WM_SYSDEADCHAR(func) \ + if (uMsg == WM_SYSDEADCHAR) \ + { \ + SetMsgHandled(TRUE); \ + func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnSysCommand(UINT nID, LPARAM lParam) +#define MSG_WM_SYSCOMMAND(func) \ + if (uMsg == WM_SYSCOMMAND) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnTCard(UINT idAction, DWORD dwActionData) +#define MSG_WM_TCARD(func) \ + if (uMsg == WM_TCARD) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, (DWORD)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnTimer(UINT_PTR nIDEvent) +#define MSG_WM_TIMER(func) \ + if (uMsg == WM_TIMER) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT_PTR)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar) +#define MSG_WM_HSCROLL(func) \ + if (uMsg == WM_HSCROLL) \ + { \ + SetMsgHandled(TRUE); \ + func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar) +#define MSG_WM_VSCROLL(func) \ + if (uMsg == WM_VSCROLL) \ + { \ + SetMsgHandled(TRUE); \ + func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnInitMenu(CMenu menu) +#define MSG_WM_INITMENU(func) \ + if (uMsg == WM_INITMENU) \ + { \ + SetMsgHandled(TRUE); \ + func((HMENU)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnInitMenuPopup(CMenu menuPopup, UINT nIndex, BOOL bSysMenu) +#define MSG_WM_INITMENUPOPUP(func) \ + if (uMsg == WM_INITMENUPOPUP) \ + { \ + SetMsgHandled(TRUE); \ + func((HMENU)wParam, (UINT)LOWORD(lParam), (BOOL)HIWORD(lParam)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnMenuSelect(UINT nItemID, UINT nFlags, CMenu menu) +#define MSG_WM_MENUSELECT(func) \ + if (uMsg == WM_MENUSELECT) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HMENU)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnMenuChar(UINT nChar, UINT nFlags, CMenu menu) +#define MSG_WM_MENUCHAR(func) \ + if (uMsg == WM_MENUCHAR) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((TCHAR)LOWORD(wParam), (UINT)HIWORD(wParam), (HMENU)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnNotify(int idCtrl, LPNMHDR pnmh) +#define MSG_WM_NOTIFY(func) \ + if (uMsg == WM_NOTIFY) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((int)wParam, (LPNMHDR)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnEnterIdle(UINT nWhy, CWindow wndWho) +#define MSG_WM_ENTERIDLE(func) \ + if (uMsg == WM_ENTERIDLE) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnMouseMove(UINT nFlags, CPoint point) +#define MSG_WM_MOUSEMOVE(func) \ + if (uMsg == WM_MOUSEMOVE) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) +#define MSG_WM_MOUSEWHEEL(func) \ + if (uMsg == WM_MOUSEWHEEL) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((UINT)LOWORD(wParam), (short)HIWORD(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnLButtonDown(UINT nFlags, CPoint point) +#define MSG_WM_LBUTTONDOWN(func) \ + if (uMsg == WM_LBUTTONDOWN) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnLButtonUp(UINT nFlags, CPoint point) +#define MSG_WM_LBUTTONUP(func) \ + if (uMsg == WM_LBUTTONUP) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnLButtonDblClk(UINT nFlags, CPoint point) +#define MSG_WM_LBUTTONDBLCLK(func) \ + if (uMsg == WM_LBUTTONDBLCLK) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnRButtonDown(UINT nFlags, CPoint point) +#define MSG_WM_RBUTTONDOWN(func) \ + if (uMsg == WM_RBUTTONDOWN) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnRButtonUp(UINT nFlags, CPoint point) +#define MSG_WM_RBUTTONUP(func) \ + if (uMsg == WM_RBUTTONUP) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnRButtonDblClk(UINT nFlags, CPoint point) +#define MSG_WM_RBUTTONDBLCLK(func) \ + if (uMsg == WM_RBUTTONDBLCLK) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnMButtonDown(UINT nFlags, CPoint point) +#define MSG_WM_MBUTTONDOWN(func) \ + if (uMsg == WM_MBUTTONDOWN) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnMButtonUp(UINT nFlags, CPoint point) +#define MSG_WM_MBUTTONUP(func) \ + if (uMsg == WM_MBUTTONUP) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnMButtonDblClk(UINT nFlags, CPoint point) +#define MSG_WM_MBUTTONDBLCLK(func) \ + if (uMsg == WM_MBUTTONDBLCLK) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnParentNotify(UINT message, UINT nChildID, LPARAM lParam) +#define MSG_WM_PARENTNOTIFY(func) \ + if (uMsg == WM_PARENTNOTIFY) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnMDIActivate(CWindow wndActivate, CWindow wndDeactivate) +#define MSG_WM_MDIACTIVATE(func) \ + if (uMsg == WM_MDIACTIVATE) \ + { \ + SetMsgHandled(TRUE); \ + func((HWND)wParam, (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnRenderFormat(UINT nFormat) +#define MSG_WM_RENDERFORMAT(func) \ + if (uMsg == WM_RENDERFORMAT) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnRenderAllFormats() +#define MSG_WM_RENDERALLFORMATS(func) \ + if (uMsg == WM_RENDERALLFORMATS) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnDestroyClipboard() +#define MSG_WM_DESTROYCLIPBOARD(func) \ + if (uMsg == WM_DESTROYCLIPBOARD) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnDrawClipboard() +#define MSG_WM_DRAWCLIPBOARD(func) \ + if (uMsg == WM_DRAWCLIPBOARD) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnPaintClipboard(CWindow wndViewer, const LPPAINTSTRUCT lpPaintStruct) +#define MSG_WM_PAINTCLIPBOARD(func) \ + if (uMsg == WM_PAINTCLIPBOARD) \ + { \ + SetMsgHandled(TRUE); \ + func((HWND)wParam, (const LPPAINTSTRUCT)::GlobalLock((HGLOBAL)lParam)); \ + ::GlobalUnlock((HGLOBAL)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnVScrollClipboard(CWindow wndViewer, UINT nSBCode, UINT nPos) +#define MSG_WM_VSCROLLCLIPBOARD(func) \ + if (uMsg == WM_VSCROLLCLIPBOARD) \ + { \ + SetMsgHandled(TRUE); \ + func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnContextMenu(CWindow wnd, CPoint point) +#define MSG_WM_CONTEXTMENU(func) \ + if (uMsg == WM_CONTEXTMENU) \ + { \ + SetMsgHandled(TRUE); \ + func((HWND)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnSizeClipboard(CWindow wndViewer, const LPRECT lpRect) +#define MSG_WM_SIZECLIPBOARD(func) \ + if (uMsg == WM_SIZECLIPBOARD) \ + { \ + SetMsgHandled(TRUE); \ + func((HWND)wParam, (const LPRECT)::GlobalLock((HGLOBAL)lParam)); \ + ::GlobalUnlock((HGLOBAL)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnAskCbFormatName(UINT nMaxCount, LPTSTR lpszString) +#define MSG_WM_ASKCBFORMATNAME(func) \ + if (uMsg == WM_ASKCBFORMATNAME) \ + { \ + SetMsgHandled(TRUE); \ + func((DWORD)wParam, (LPTSTR)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnChangeCbChain(CWindow wndRemove, CWindow wndAfter) +#define MSG_WM_CHANGECBCHAIN(func) \ + if (uMsg == WM_CHANGECBCHAIN) \ + { \ + SetMsgHandled(TRUE); \ + func((HWND)wParam, (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnHScrollClipboard(CWindow wndViewer, UINT nSBCode, UINT nPos) +#define MSG_WM_HSCROLLCLIPBOARD(func) \ + if (uMsg == WM_HSCROLLCLIPBOARD) \ + { \ + SetMsgHandled(TRUE); \ + func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// BOOL OnQueryNewPalette() +#define MSG_WM_QUERYNEWPALETTE(func) \ + if (uMsg == WM_QUERYNEWPALETTE) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func(); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnPaletteChanged(CWindow wndFocus) +#define MSG_WM_PALETTECHANGED(func) \ + if (uMsg == WM_PALETTECHANGED) \ + { \ + SetMsgHandled(TRUE); \ + func((HWND)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnPaletteIsChanging(CWindow wndPalChg) +#define MSG_WM_PALETTEISCHANGING(func) \ + if (uMsg == WM_PALETTEISCHANGING) \ + { \ + SetMsgHandled(TRUE); \ + func((HWND)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnDropFiles(HDROP hDropInfo) +#define MSG_WM_DROPFILES(func) \ + if (uMsg == WM_DROPFILES) \ + { \ + SetMsgHandled(TRUE); \ + func((HDROP)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnWindowPosChanging(LPWINDOWPOS lpWndPos) +#define MSG_WM_WINDOWPOSCHANGING(func) \ + if (uMsg == WM_WINDOWPOSCHANGING) \ + { \ + SetMsgHandled(TRUE); \ + func((LPWINDOWPOS)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnWindowPosChanged(LPWINDOWPOS lpWndPos) +#define MSG_WM_WINDOWPOSCHANGED(func) \ + if (uMsg == WM_WINDOWPOSCHANGED) \ + { \ + SetMsgHandled(TRUE); \ + func((LPWINDOWPOS)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnExitMenuLoop(BOOL fIsTrackPopupMenu) +#define MSG_WM_EXITMENULOOP(func) \ + if (uMsg == WM_EXITMENULOOP) \ + { \ + SetMsgHandled(TRUE); \ + func((BOOL)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnEnterMenuLoop(BOOL fIsTrackPopupMenu) +#define MSG_WM_ENTERMENULOOP(func) \ + if (uMsg == WM_ENTERMENULOOP) \ + { \ + SetMsgHandled(TRUE); \ + func((BOOL)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnStyleChanged(int nStyleType, LPSTYLESTRUCT lpStyleStruct) +#define MSG_WM_STYLECHANGED(func) \ + if (uMsg == WM_STYLECHANGED) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, (LPSTYLESTRUCT)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnStyleChanging(int nStyleType, LPSTYLESTRUCT lpStyleStruct) +#define MSG_WM_STYLECHANGING(func) \ + if (uMsg == WM_STYLECHANGING) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, (LPSTYLESTRUCT)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnSizing(UINT fwSide, LPRECT pRect) +#define MSG_WM_SIZING(func) \ + if (uMsg == WM_SIZING) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, (LPRECT)lParam); \ + lResult = TRUE; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnMoving(UINT fwSide, LPRECT pRect) +#define MSG_WM_MOVING(func) \ + if (uMsg == WM_MOVING) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, (LPRECT)lParam); \ + lResult = TRUE; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnCaptureChanged(CWindow wnd) +#define MSG_WM_CAPTURECHANGED(func) \ + if (uMsg == WM_CAPTURECHANGED) \ + { \ + SetMsgHandled(TRUE); \ + func((HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// BOOL OnDeviceChange(UINT nEventType, DWORD dwData) +#define MSG_WM_DEVICECHANGE(func) \ + if (uMsg == WM_DEVICECHANGE) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((UINT)wParam, (DWORD)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl) +#define MSG_WM_COMMAND(func) \ + if (uMsg == WM_COMMAND) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnDisplayChange(UINT uBitsPerPixel, CSize sizeScreen) +#define MSG_WM_DISPLAYCHANGE(func) \ + if (uMsg == WM_DISPLAYCHANGE) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, _WTYPES_NS::CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnEnterSizeMove() +#define MSG_WM_ENTERSIZEMOVE(func) \ + if (uMsg == WM_ENTERSIZEMOVE) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnExitSizeMove() +#define MSG_WM_EXITSIZEMOVE(func) \ + if (uMsg == WM_EXITSIZEMOVE) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HFONT OnGetFont() +#define MSG_WM_GETFONT(func) \ + if (uMsg == WM_GETFONT) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func(); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnGetHotKey() +#define MSG_WM_GETHOTKEY(func) \ + if (uMsg == WM_GETHOTKEY) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func(); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HICON OnGetIcon() +#define MSG_WM_GETICON(func) \ + if (uMsg == WM_GETICON) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((UINT)wParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// int OnGetText(int cchTextMax, LPTSTR lpszText) +#define MSG_WM_GETTEXT(func) \ + if (uMsg == WM_GETTEXT) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((int)wParam, (LPTSTR)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// int OnGetTextLength() +#define MSG_WM_GETTEXTLENGTH(func) \ + if (uMsg == WM_GETTEXTLENGTH) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func(); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnHelp(LPHELPINFO lpHelpInfo) +#define MSG_WM_HELP(func) \ + if (uMsg == WM_HELP) \ + { \ + SetMsgHandled(TRUE); \ + func((LPHELPINFO)lParam); \ + lResult = TRUE; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnHotKey(int nHotKeyID, UINT uModifiers, UINT uVirtKey) +#define MSG_WM_HOTKEY(func) \ + if (uMsg == WM_HOTKEY) \ + { \ + SetMsgHandled(TRUE); \ + func((int)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnInputLangChange(DWORD dwCharSet, HKL hKbdLayout) +#define MSG_WM_INPUTLANGCHANGE(func) \ + if (uMsg == WM_INPUTLANGCHANGE) \ + { \ + SetMsgHandled(TRUE); \ + func((DWORD)wParam, (HKL)lParam); \ + lResult = TRUE; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnInputLangChangeRequest(BOOL bSysCharSet, HKL hKbdLayout) +#define MSG_WM_INPUTLANGCHANGEREQUEST(func) \ + if (uMsg == WM_INPUTLANGCHANGEREQUEST) \ + { \ + SetMsgHandled(TRUE); \ + func((BOOL)wParam, (HKL)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNextDlgCtl(BOOL bHandle, WPARAM wCtlFocus) +#define MSG_WM_NEXTDLGCTL(func) \ + if (uMsg == WM_NEXTDLGCTL) \ + { \ + SetMsgHandled(TRUE); \ + func((BOOL)LOWORD(lParam), wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNextMenu(int nVirtKey, LPMDINEXTMENU lpMdiNextMenu) +#define MSG_WM_NEXTMENU(func) \ + if (uMsg == WM_NEXTMENU) \ + { \ + SetMsgHandled(TRUE); \ + func((int)wParam, (LPMDINEXTMENU)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// int OnNotifyFormat(CWindow wndFrom, int nCommand) +#define MSG_WM_NOTIFYFORMAT(func) \ + if (uMsg == WM_NOTIFYFORMAT) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HWND)wParam, (int)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// BOOL OnPowerBroadcast(DWORD dwPowerEvent, DWORD dwData) +#define MSG_WM_POWERBROADCAST(func) \ + if (uMsg == WM_POWERBROADCAST) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((DWORD)wParam, (DWORD)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnPrint(CDCHandle dc, UINT uFlags) +#define MSG_WM_PRINT(func) \ + if (uMsg == WM_PRINT) \ + { \ + SetMsgHandled(TRUE); \ + func((HDC)wParam, (UINT)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnPrintClient(CDCHandle dc, UINT uFlags) +#define MSG_WM_PRINTCLIENT(func) \ + if (uMsg == WM_PRINTCLIENT) \ + { \ + SetMsgHandled(TRUE); \ + func((HDC)wParam, (UINT)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnRasDialEvent(RASCONNSTATE rasconnstate, DWORD dwError) +#define MSG_WM_RASDIALEVENT(func) \ + if (uMsg == WM_RASDIALEVENT) \ + { \ + SetMsgHandled(TRUE); \ + func((RASCONNSTATE)wParam, (DWORD)lParam); \ + lResult = TRUE; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnSetFont(CFont font, BOOL bRedraw) +#define MSG_WM_SETFONT(func) \ + if (uMsg == WM_SETFONT) \ + { \ + SetMsgHandled(TRUE); \ + func((HFONT)wParam, (BOOL)LOWORD(lParam)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// int OnSetHotKey(int nVirtKey, UINT uFlags) +#define MSG_WM_SETHOTKEY(func) \ + if (uMsg == WM_SETHOTKEY) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((int)LOBYTE(LOWORD(wParam)), (UINT)HIBYTE(LOWORD(wParam))); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HICON OnSetIcon(UINT uType, HICON hIcon) +#define MSG_WM_SETICON(func) \ + if (uMsg == WM_SETICON) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((UINT)wParam, (HICON)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnSetRedraw(BOOL bRedraw) +#define MSG_WM_SETREDRAW(func) \ + if (uMsg == WM_SETREDRAW) \ + { \ + SetMsgHandled(TRUE); \ + func((BOOL)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// int OnSetText(LPCTSTR lpstrText) +#define MSG_WM_SETTEXT(func) \ + if (uMsg == WM_SETTEXT) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((LPCTSTR)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnUserChanged() +#define MSG_WM_USERCHANGED(func) \ + if (uMsg == WM_USERCHANGED) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +/////////////////////////////////////////////////////////////////////////////// +// New NT4 & NT5 messages + +#if(_WIN32_WINNT >= 0x0400) + +// void OnMouseHover(WPARAM wParam, CPoint ptPos) +#define MSG_WM_MOUSEHOVER(func) \ + if (uMsg == WM_MOUSEHOVER) \ + { \ + SetMsgHandled(TRUE); \ + func(wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnMouseLeave() +#define MSG_WM_MOUSELEAVE(func) \ + if (uMsg == WM_MOUSELEAVE) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +#endif /* _WIN32_WINNT >= 0x0400 */ + +#if(WINVER >= 0x0500) + +// void OnMenuRButtonUp(WPARAM wParam, CMenu menu) +#define MSG_WM_MENURBUTTONUP(func) \ + if (uMsg == WM_MENURBUTTONUP) \ + { \ + SetMsgHandled(TRUE); \ + func(wParam, (HMENU)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnMenuDrag(WPARAM wParam, CMenu menu) +#define MSG_WM_MENUDRAG(func) \ + if (uMsg == WM_MENUDRAG) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func(wParam, (HMENU)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnMenuGetObject(PMENUGETOBJECTINFO info) +#define MSG_WM_MENUGETOBJECT(func) \ + if (uMsg == WM_MENUGETOBJECT) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((PMENUGETOBJECTINFO)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnUnInitMenuPopup(UINT nID, CMenu menu) +#define MSG_WM_UNINITMENUPOPUP(func) \ + if (uMsg == WM_UNINITMENUPOPUP) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)HIWORD(lParam), (HMENU)wParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnMenuCommand(WPARAM nIndex, CMenu menu) +#define MSG_WM_MENUCOMMAND(func) \ + if (uMsg == WM_MENUCOMMAND) \ + { \ + SetMsgHandled(TRUE); \ + func(wParam, (HMENU)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +#endif /* WINVER >= 0x0500 */ + +#if(_WIN32_WINNT >= 0x0500) + +// BOOL OnAppCommand(CWindow wndFocus, short cmd, WORD uDevice, int dwKeys) +#define MSG_WM_APPCOMMAND(func) \ + if (uMsg == WM_APPCOMMAND) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HWND)wParam, GET_APPCOMMAND_LPARAM(lParam), GET_DEVICE_LPARAM(lParam), GET_KEYSTATE_LPARAM(lParam)); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNCXButtonDown(int fwButton, short nHittest, CPoint ptPos) +#define MSG_WM_NCXBUTTONDOWN(func) \ + if (uMsg == WM_NCXBUTTONDOWN) \ + { \ + SetMsgHandled(TRUE); \ + func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNCXButtonUp(int fwButton, short nHittest, CPoint ptPos) +#define MSG_WM_NCXBUTTONUP(func) \ + if (uMsg == WM_NCXBUTTONUP) \ + { \ + SetMsgHandled(TRUE); \ + func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnNCXButtonDblClk(int fwButton, short nHittest, CPoint ptPos) +#define MSG_WM_NCXBUTTONDBLCLK(func) \ + if (uMsg == WM_NCXBUTTONDBLCLK) \ + { \ + SetMsgHandled(TRUE); \ + func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnXButtonDown(int fwButton, int dwKeys, CPoint ptPos) +#define MSG_WM_XBUTTONDOWN(func) \ + if (uMsg == WM_XBUTTONDOWN) \ + { \ + SetMsgHandled(TRUE); \ + func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnXButtonUp(int fwButton, int dwKeys, CPoint ptPos) +#define MSG_WM_XBUTTONUP(func) \ + if (uMsg == WM_XBUTTONUP) \ + { \ + SetMsgHandled(TRUE); \ + func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnXButtonDblClk(int fwButton, int dwKeys, CPoint ptPos) +#define MSG_WM_XBUTTONDBLCLK(func) \ + if (uMsg == WM_XBUTTONDBLCLK) \ + { \ + SetMsgHandled(TRUE); \ + func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnChangeUIState(WORD nAction, WORD nState) +#define MSG_WM_CHANGEUISTATE(func) \ + if (uMsg == WM_CHANGEUISTATE) \ + { \ + SetMsgHandled(TRUE); \ + func(LOWORD(wParam), HIWORD(wParam)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnUpdateUIState(WORD nAction, WORD nState) +#define MSG_WM_UPDATEUISTATE(func) \ + if (uMsg == WM_UPDATEUISTATE) \ + { \ + SetMsgHandled(TRUE); \ + func(LOWORD(wParam), HIWORD(wParam)); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnQueryUIState() +#define MSG_WM_QUERYUISTATE(func) \ + if (uMsg == WM_QUERYUISTATE) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func(); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +#endif // (_WIN32_WINNT >= 0x0500) + +#if(_WIN32_WINNT >= 0x0501) + +// void OnInput(WPARAM RawInputCode, HRAWINPUT hRawInput) +#define MSG_WM_INPUT(func) \ + if (uMsg == WM_INPUT) \ + { \ + SetMsgHandled(TRUE); \ + func(GET_RAWINPUT_CODE_WPARAM(wParam), (HRAWINPUT)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnUniChar(TCHAR nChar, UINT nRepCnt, UINT nFlags) +#define MSG_WM_UNICHAR(func) \ + if (uMsg == WM_UNICHAR) \ + { \ + SetMsgHandled(TRUE); \ + func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ + if(IsMsgHandled()) \ + { \ + lResult = (wParam == UNICODE_NOCHAR) ? TRUE : FALSE; \ + return TRUE; \ + } \ + } + +// void OnWTSSessionChange(WPARAM nStatusCode, PWTSSESSION_NOTIFICATION nSessionID) +#define MSG_WM_WTSSESSION_CHANGE(func) \ + if (uMsg == WM_WTSSESSION_CHANGE) \ + { \ + SetMsgHandled(TRUE); \ + func(wParam, (PWTSSESSION_NOTIFICATION)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// OnThemeChanged() +#define MSG_WM_THEMECHANGED(func) \ + if (uMsg == WM_THEMECHANGED) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +#endif /* _WIN32_WINNT >= 0x0501 */ + +/////////////////////////////////////////////////////////////////////////////// +// ATL defined messages + +// BOOL OnForwardMsg(LPMSG Msg, DWORD nUserData) +#define MSG_WM_FORWARDMSG(func) \ + if (uMsg == WM_FORWARDMSG) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((LPMSG)lParam, (DWORD)wParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +/////////////////////////////////////////////////////////////////////////////// +// Dialog specific messages + +// LRESULT OnDMGetDefID() +#define MSG_DM_GETDEFID(func) \ + if (uMsg == DM_GETDEFID) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func(); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnDMSetDefID(UINT DefID) +#define MSG_DM_SETDEFID(func) \ + if (uMsg == DM_SETDEFID) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam); \ + lResult = TRUE; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnDMReposition() +#define MSG_DM_REPOSITION(func) \ + if (uMsg == DM_REPOSITION) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +/////////////////////////////////////////////////////////////////////////////// +// Reflected messages + +// void OnReflectedCommand(UINT uNotifyCode, int nID, CWindow wndCtl) +#define MSG_OCM_COMMAND(func) \ + if (uMsg == OCM_COMMAND) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnReflectedNotify(int idCtrl, LPNMHDR pnmh) +#define MSG_OCM_NOTIFY(func) \ + if (uMsg == OCM_NOTIFY) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((int)wParam, (LPNMHDR)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnReflectedParentNotify(UINT message, UINT nChildID, LPARAM lParam) +#define MSG_OCM_PARENTNOTIFY(func) \ + if (uMsg == OCM_PARENTNOTIFY) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnReflectedDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) +#define MSG_OCM_DRAWITEM(func) \ + if (uMsg == OCM_DRAWITEM) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, (LPDRAWITEMSTRUCT)lParam); \ + lResult = TRUE; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnReflectedMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) +#define MSG_OCM_MEASUREITEM(func) \ + if (uMsg == OCM_MEASUREITEM) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, (LPMEASUREITEMSTRUCT)lParam); \ + lResult = TRUE; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// int OnReflectedCompareItem(int nIDCtl, LPCOMPAREITEMSTRUCT lpCompareItemStruct) +#define MSG_OCM_COMPAREITEM(func) \ + if (uMsg == OCM_COMPAREITEM) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((UINT)wParam, (LPCOMPAREITEMSTRUCT)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnReflectedDeleteItem(int nIDCtl, LPDELETEITEMSTRUCT lpDeleteItemStruct) +#define MSG_OCM_DELETEITEM(func) \ + if (uMsg == OCM_DELETEITEM) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)wParam, (LPDELETEITEMSTRUCT)lParam); \ + lResult = TRUE; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// int OnReflectedVKeyToItem(UINT nKey, UINT nIndex, CListBox listBox) +#define MSG_OCM_VKEYTOITEM(func) \ + if (uMsg == OCM_VKEYTOITEM) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +//int OnReflectedCharToItem(UINT nChar, UINT nIndex, CListBox listBox) +#define MSG_OCM_CHARTOITEM(func) \ + if (uMsg == OCM_CHARTOITEM) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnReflectedHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar) +#define MSG_OCM_HSCROLL(func) \ + if (uMsg == OCM_HSCROLL) \ + { \ + SetMsgHandled(TRUE); \ + func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnReflectedVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar) +#define MSG_OCM_VSCROLL(func) \ + if (uMsg == OCM_VSCROLL) \ + { \ + SetMsgHandled(TRUE); \ + func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HBRUSH OnReflectedCtlColorEdit(CDCHandle dc, CEdit edit) +#define MSG_OCM_CTLCOLOREDIT(func) \ + if (uMsg == OCM_CTLCOLOREDIT) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HBRUSH OnReflectedCtlColorListBox(CDCHandle dc, CListBox listBox) +#define MSG_OCM_CTLCOLORLISTBOX(func) \ + if (uMsg == OCM_CTLCOLORLISTBOX) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HBRUSH OnReflectedCtlColorBtn(CDCHandle dc, CButton button) +#define MSG_OCM_CTLCOLORBTN(func) \ + if (uMsg == OCM_CTLCOLORBTN) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HBRUSH OnReflectedCtlColorDlg(CDCHandle dc, CWindow wnd) +#define MSG_OCM_CTLCOLORDLG(func) \ + if (uMsg == OCM_CTLCOLORDLG) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HBRUSH OnReflectedCtlColorScrollBar(CDCHandle dc, CScrollBar scrollBar) +#define MSG_OCM_CTLCOLORSCROLLBAR(func) \ + if (uMsg == OCM_CTLCOLORSCROLLBAR) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// HBRUSH OnReflectedCtlColorStatic(CDCHandle dc, CStatic wndStatic) +#define MSG_OCM_CTLCOLORSTATIC(func) \ + if (uMsg == OCM_CTLCOLORSTATIC) \ + { \ + SetMsgHandled(TRUE); \ + lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +/////////////////////////////////////////////////////////////////////////////// +// Edit specific messages + +// void OnClear() +#define MSG_WM_CLEAR(func) \ + if (uMsg == WM_CLEAR) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnCopy() +#define MSG_WM_COPY(func) \ + if (uMsg == WM_COPY) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnCut() +#define MSG_WM_CUT(func) \ + if (uMsg == WM_CUT) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnPaste() +#define MSG_WM_PASTE(func) \ + if (uMsg == WM_PASTE) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnUndo() +#define MSG_WM_UNDO(func) \ + if (uMsg == WM_UNDO) \ + { \ + SetMsgHandled(TRUE); \ + func(); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +/////////////////////////////////////////////////////////////////////////////// +// Generic message handlers + +// LRESULT OnMessageHandlerEX(UINT uMsg, WPARAM wParam, LPARAM lParam) +#define MESSAGE_HANDLER_EX(msg, func) \ + if(uMsg == msg) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func(uMsg, wParam, lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnMessageRangeHandlerEX(UINT uMsg, WPARAM wParam, LPARAM lParam) +#define MESSAGE_RANGE_HANDLER_EX(msgFirst, msgLast, func) \ + if(uMsg >= msgFirst && uMsg <= msgLast) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func(uMsg, wParam, lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +/////////////////////////////////////////////////////////////////////////////// +// Commands and notifications + +// void OnCommandHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) +#define COMMAND_HANDLER_EX(id, code, func) \ + if (uMsg == WM_COMMAND && code == HIWORD(wParam) && id == LOWORD(wParam)) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) +#define COMMAND_ID_HANDLER_EX(id, func) \ + if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnCommandCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) +#define COMMAND_CODE_HANDLER_EX(code, func) \ + if (uMsg == WM_COMMAND && code == HIWORD(wParam)) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnNotifyHandlerEX(LPNMHDR pnmh) +#define NOTIFY_HANDLER_EX(id, cd, func) \ + if (uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && id == ((LPNMHDR)lParam)->idFrom) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((LPNMHDR)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnNotifyIDHandlerEX(LPNMHDR pnmh) +#define NOTIFY_ID_HANDLER_EX(id, func) \ + if (uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((LPNMHDR)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnNotifyCodeHandlerEX(LPNMHDR pnmh) +#define NOTIFY_CODE_HANDLER_EX(cd, func) \ + if (uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((LPNMHDR)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnCommandRangeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) +#define COMMAND_RANGE_HANDLER_EX(idFirst, idLast, func) \ + if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnCommandRangeCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) +#define COMMAND_RANGE_CODE_HANDLER_EX(idFirst, idLast, code, func) \ + if(uMsg == WM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnNotifyRangeHandlerEX(LPNMHDR pnmh) +#define NOTIFY_RANGE_HANDLER_EX(idFirst, idLast, func) \ + if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((LPNMHDR)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnNotifyRangeCodeHandlerEX(LPNMHDR pnmh) +#define NOTIFY_RANGE_CODE_HANDLER_EX(idFirst, idLast, cd, func) \ + if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((LPNMHDR)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnReflectedCommandHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) +#define REFLECTED_COMMAND_HANDLER_EX(id, code, func) \ + if (uMsg == OCM_COMMAND && code == HIWORD(wParam) && id == LOWORD(wParam)) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnReflectedCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) +#define REFLECTED_COMMAND_ID_HANDLER_EX(id, func) \ + if (uMsg == OCM_COMMAND && id == LOWORD(wParam)) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnReflectedCommandCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) +#define REFLECTED_COMMAND_CODE_HANDLER_EX(code, func) \ + if (uMsg == OCM_COMMAND && code == HIWORD(wParam)) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnReflectedNotifyHandlerEX(LPNMHDR pnmh) +#define REFLECTED_NOTIFY_HANDLER_EX(id, cd, func) \ + if (uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && id == ((LPNMHDR)lParam)->idFrom) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((LPNMHDR)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnReflectedNotifyIDHandlerEX(LPNMHDR pnmh) +#define REFLECTED_NOTIFY_ID_HANDLER_EX(id, func) \ + if (uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((LPNMHDR)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnReflectedNotifyCodeHandlerEX(LPNMHDR pnmh) +#define REFLECTED_NOTIFY_CODE_HANDLER_EX(cd, func) \ + if (uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((LPNMHDR)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnReflectedCommandRangeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) +#define REFLECTED_COMMAND_RANGE_HANDLER_EX(idFirst, idLast, func) \ + if(uMsg == OCM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// void OnReflectedCommandRangeCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) +#define REFLECTED_COMMAND_RANGE_CODE_HANDLER_EX(idFirst, idLast, code, func) \ + if(uMsg == OCM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ + { \ + SetMsgHandled(TRUE); \ + func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ + lResult = 0; \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnReflectedNotifyRangeHandlerEX(LPNMHDR pnmh) +#define REFLECTED_NOTIFY_RANGE_HANDLER_EX(idFirst, idLast, func) \ + if(uMsg == OCM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((LPNMHDR)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +// LRESULT OnReflectedNotifyRangeCodeHandlerEX(LPNMHDR pnmh) +#define REFLECTED_NOTIFY_RANGE_CODE_HANDLER_EX(idFirst, idLast, cd, func) \ + if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ + { \ + SetMsgHandled(TRUE); \ + lResult = func((LPNMHDR)lParam); \ + if(IsMsgHandled()) \ + return TRUE; \ + } + +#endif // __ATLCRACK_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlctrls.h b/Client/Client/GUI/BKWin/wtl/atlctrls.h new file mode 100644 index 00000000..cbafb29c --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlctrls.h @@ -0,0 +1,10036 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLCTRLS_H__ +#define __ATLCTRLS_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifndef __ATLAPP_H__ + #error atlctrls.h requires atlapp.h to be included first +#endif + +#ifndef __ATLWIN_H__ + #error atlctrls.h requires atlwin.h to be included first +#endif + +#if (_WIN32_IE < 0x0300) + #error atlctrls.h requires IE Version 3.0 or higher +#endif + +#ifndef _WIN32_WCE + #include + #include +#elif defined(WIN32_PLATFORM_WFSP) && !defined(_WINUSERM_H_) + #include +#endif // !_WIN32_WCE + +// protect template members from windowsx.h macros +#ifdef _INC_WINDOWSX + #undef GetNextSibling + #undef GetPrevSibling +#endif // _INC_WINDOWSX + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CStaticT - CStatic +// CButtonT - CButton +// CListBoxT - CListBox +// CComboBoxT - CComboBox +// CEditT - CEdit +// CEditCommands +// CScrollBarT - CScrollBar +// +// CImageList +// CListViewCtrlT - CListViewCtrl +// CTreeViewCtrlT - CTreeViewCtrl +// CTreeItemT - CTreeItem +// CTreeViewCtrlExT - CTreeViewCtrlEx +// CHeaderCtrlT - CHeaderCtrl +// CToolBarCtrlT - CToolBarCtrl +// CStatusBarCtrlT - CStatusBarCtrl +// CTabCtrlT - CTabCtrl +// CToolInfo +// CToolTipCtrlT - CToolTipCtrl +// CTrackBarCtrlT - CTrackBarCtrl +// CUpDownCtrlT - CUpDownCtrl +// CProgressBarCtrlT - CProgressBarCtrl +// CHotKeyCtrlT - CHotKeyCtrl +// CAnimateCtrlT - CAnimateCtrl +// CRichEditCtrlT - CRichEditCtrl +// CRichEditCommands +// CDragListBoxT - CDragListBox +// CDragListNotifyImpl +// CReBarCtrlT - CReBarCtrl +// CComboBoxExT - CComboBoxEx +// CDateTimePickerCtrlT - CDateTimePickerCtrl +// CMonthCalendarCtrlT - CMonthCalendarCtrl +// CFlatScrollBarImpl +// CFlatScrollBarT - CFlatScrollBar +// CIPAddressCtrlT - CIPAddressCtrl +// CPagerCtrlT - CPagerCtrl +// CLinkCtrlT - CLinkCtrl +// +// CCustomDraw +// +// CCECommandBarCtrlT - CCECommandBarCtrl +// CCECommandBandsCtrlT - CCECommandBandsCtrl + + +namespace WTL +{ + +// These are wrapper classes for Windows standard and common controls. +// To implement a window based on a control, use following: +// Example: Implementing a window based on a list box +// +// class CMyListBox : CWindowImpl +// { +// public: +// BEGIN_MSG_MAP(CMyListBox) +// // put your message handler entries here +// END_MSG_MAP() +// }; + + + +// --- Standard Windows controls --- + +/////////////////////////////////////////////////////////////////////////////// +// CStatic - client side for a Windows STATIC control + +template +class CStaticT : public TBase +{ +public: +// Constructors + CStaticT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CStaticT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return _T("STATIC"); + } + +#ifndef _WIN32_WCE + HICON GetIcon() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HICON)::SendMessage(m_hWnd, STM_GETICON, 0, 0L); + } + + HICON SetIcon(HICON hIcon) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HICON)::SendMessage(m_hWnd, STM_SETICON, (WPARAM)hIcon, 0L); + } + + HENHMETAFILE GetEnhMetaFile() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HENHMETAFILE)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_ENHMETAFILE, 0L); + } + + HENHMETAFILE SetEnhMetaFile(HENHMETAFILE hMetaFile) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HENHMETAFILE)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_ENHMETAFILE, (LPARAM)hMetaFile); + } +#else // CE specific + HICON GetIcon() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HICON)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_ICON, 0L); + } + + HICON SetIcon(HICON hIcon) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HICON)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + } +#endif // _WIN32_WCE + + CBitmapHandle GetBitmap() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_BITMAP, 0L)); + } + + CBitmapHandle SetBitmap(HBITMAP hBitmap) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap)); + } + + HCURSOR GetCursor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HCURSOR)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_CURSOR, 0L); + } + + HCURSOR SetCursor(HCURSOR hCursor) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HCURSOR)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_CURSOR, (LPARAM)hCursor); + } +}; + +typedef CStaticT CStatic; + + +/////////////////////////////////////////////////////////////////////////////// +// CButton - client side for a Windows BUTTON control + +template +class CButtonT : public TBase +{ +public: +// Constructors + CButtonT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CButtonT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return _T("BUTTON"); + } + + UINT GetState() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, BM_GETSTATE, 0, 0L); + } + + void SetState(BOOL bHighlight) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, BM_SETSTATE, bHighlight, 0L); + } + + int GetCheck() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, BM_GETCHECK, 0, 0L); + } + + void SetCheck(int nCheck) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, BM_SETCHECK, nCheck, 0L); + } + + UINT GetButtonStyle() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::GetWindowLong(m_hWnd, GWL_STYLE) & 0xFFFF; + } + + void SetButtonStyle(UINT nStyle, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, BM_SETSTYLE, nStyle, (LPARAM)bRedraw); + } + +#ifndef _WIN32_WCE + HICON GetIcon() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HICON)::SendMessage(m_hWnd, BM_GETIMAGE, IMAGE_ICON, 0L); + } + + HICON SetIcon(HICON hIcon) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HICON)::SendMessage(m_hWnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + } + + CBitmapHandle GetBitmap() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, BM_GETIMAGE, IMAGE_BITMAP, 0L)); + } + + CBitmapHandle SetBitmap(HBITMAP hBitmap) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap)); + } +#endif // !_WIN32_WCE + +#if (_WIN32_WINNT >= 0x0501) + BOOL GetIdealSize(LPSIZE lpSize) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, BCM_GETIDEALSIZE, 0, (LPARAM)lpSize); + } + + BOOL GetImageList(PBUTTON_IMAGELIST pButtonImagelist) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, BCM_GETIMAGELIST, 0, (LPARAM)pButtonImagelist); + } + + BOOL SetImageList(PBUTTON_IMAGELIST pButtonImagelist) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, BCM_SETIMAGELIST, 0, (LPARAM)pButtonImagelist); + } + + BOOL GetTextMargin(LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, BCM_GETTEXTMARGIN, 0, (LPARAM)lpRect); + } + + BOOL SetTextMargin(LPRECT lpRect) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, BCM_SETTEXTMARGIN, 0, (LPARAM)lpRect); + } +#endif // (_WIN32_WINNT >= 0x0501) + +#if (WINVER >= 0x0600) + void SetDontClick(BOOL bDontClick) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, BM_SETDONTCLICK, (WPARAM)bDontClick, 0L); + } +#endif // (WINVER >= 0x0600) + +#if (_WIN32_WINNT >= 0x0600) + BOOL SetDropDownState(BOOL bDropDown) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0); + return (BOOL)::SendMessage(m_hWnd, BCM_SETDROPDOWNSTATE, (WPARAM)bDropDown, 0L); + } + + BOOL GetSplitInfo(PBUTTON_SPLITINFO pSplitInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0); + return (BOOL)::SendMessage(m_hWnd, BCM_GETSPLITINFO, 0, (LPARAM)pSplitInfo); + } + + BOOL SetSplitInfo(PBUTTON_SPLITINFO pSplitInfo) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0); + return (BOOL)::SendMessage(m_hWnd, BCM_SETSPLITINFO, 0, (LPARAM)pSplitInfo); + } + + int GetNoteLength() const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0); + return (int)::SendMessage(m_hWnd, BCM_GETNOTELENGTH, 0, 0L); + } + + BOOL GetNote(LPWSTR lpstrNoteText, int cchNoteText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0); + return (BOOL)::SendMessage(m_hWnd, BCM_GETNOTE, cchNoteText, (LPARAM)lpstrNoteText); + } + + BOOL SetNote(LPCWSTR lpstrNoteText) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0); + return (BOOL)::SendMessage(m_hWnd, BCM_SETNOTE, 0, (LPARAM)lpstrNoteText); + } + + LRESULT SetElevationRequiredState(BOOL bSet) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SendMessage(m_hWnd, BCM_SETSHIELD, 0, (LPARAM)bSet); + } +#endif // (_WIN32_WINNT >= 0x0600) + +// Operations + void Click() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, BM_CLICK, 0, 0L); + } +}; + +typedef CButtonT CButton; + + +/////////////////////////////////////////////////////////////////////////////// +// CListBox - client side for a Windows LISTBOX control + +template +class CListBoxT : public TBase +{ +public: +// Constructors + CListBoxT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CListBoxT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return _T("LISTBOX"); + } + + // for entire listbox + int GetCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_GETCOUNT, 0, 0L); + } + +#ifndef _WIN32_WCE + int SetCount(int cItems) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(((GetStyle() & LBS_NODATA) != 0) && ((GetStyle() & LBS_HASSTRINGS) == 0)); + return (int)::SendMessage(m_hWnd, LB_SETCOUNT, cItems, 0L); + } +#endif // !_WIN32_WCE + + int GetHorizontalExtent() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_GETHORIZONTALEXTENT, 0, 0L); + } + + void SetHorizontalExtent(int cxExtent) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LB_SETHORIZONTALEXTENT, cxExtent, 0L); + } + + int GetTopIndex() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_GETTOPINDEX, 0, 0L); + } + + int SetTopIndex(int nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_SETTOPINDEX, nIndex, 0L); + } + + LCID GetLocale() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (LCID)::SendMessage(m_hWnd, LB_GETLOCALE, 0, 0L); + } + + LCID SetLocale(LCID nNewLocale) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (LCID)::SendMessage(m_hWnd, LB_SETLOCALE, (WPARAM)nNewLocale, 0L); + } + +#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) + DWORD GetListBoxInfo() const + { + ATLASSERT(::IsWindow(m_hWnd)); +#if (_WIN32_WINNT >= 0x0501) + return (DWORD)::SendMessage(m_hWnd, LB_GETLISTBOXINFO, 0, 0L); +#else // !(_WIN32_WINNT >= 0x0501) + return ::GetListBoxInfo(m_hWnd); +#endif // !(_WIN32_WINNT >= 0x0501) + } +#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) + + // for single-selection listboxes + int GetCurSel() const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0); + return (int)::SendMessage(m_hWnd, LB_GETCURSEL, 0, 0L); + } + + int SetCurSel(int nSelect) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0); + return (int)::SendMessage(m_hWnd, LB_SETCURSEL, nSelect, 0L); + } + + // for multiple-selection listboxes + int GetSel(int nIndex) const // also works for single-selection + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_GETSEL, nIndex, 0L); + } + + int SetSel(int nIndex, BOOL bSelect = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0); + return (int)::SendMessage(m_hWnd, LB_SETSEL, bSelect, nIndex); + } + + int GetSelCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0); + return (int)::SendMessage(m_hWnd, LB_GETSELCOUNT, 0, 0L); + } + + int GetSelItems(int nMaxItems, LPINT rgIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0); + return (int)::SendMessage(m_hWnd, LB_GETSELITEMS, nMaxItems, (LPARAM)rgIndex); + } + + int GetAnchorIndex() const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0); + return (int)::SendMessage(m_hWnd, LB_GETANCHORINDEX, 0, 0L); + } + + void SetAnchorIndex(int nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0); + ::SendMessage(m_hWnd, LB_SETANCHORINDEX, nIndex, 0L); + } + + int GetCaretIndex() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_GETCARETINDEX, 0, 0); + } + + int SetCaretIndex(int nIndex, BOOL bScroll = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_SETCARETINDEX, nIndex, MAKELONG(bScroll, 0)); + } + + // for listbox items + DWORD_PTR GetItemData(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD_PTR)::SendMessage(m_hWnd, LB_GETITEMDATA, nIndex, 0L); + } + + int SetItemData(int nIndex, DWORD_PTR dwItemData) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_SETITEMDATA, nIndex, (LPARAM)dwItemData); + } + + void* GetItemDataPtr(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (void*)::SendMessage(m_hWnd, LB_GETITEMDATA, nIndex, 0L); + } + + int SetItemDataPtr(int nIndex, void* pData) + { + ATLASSERT(::IsWindow(m_hWnd)); + return SetItemData(nIndex, (DWORD_PTR)pData); + } + + int GetItemRect(int nIndex, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_GETITEMRECT, nIndex, (LPARAM)lpRect); + } + + int GetText(int nIndex, LPTSTR lpszBuffer) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_GETTEXT, nIndex, (LPARAM)lpszBuffer); + } + +#ifndef _ATL_NO_COM +#ifdef _OLEAUTO_H_ + BOOL GetTextBSTR(int nIndex, BSTR& bstrText) const + { + USES_CONVERSION; + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(bstrText == NULL); + + int nLen = GetTextLen(nIndex); + if(nLen == LB_ERR) + return FALSE; + + CTempBuffer buff; + LPTSTR lpstrText = buff.Allocate(nLen + 1); + if(lpstrText == NULL) + return FALSE; + + if(GetText(nIndex, lpstrText) == LB_ERR) + return FALSE; + + bstrText = ::SysAllocString(T2OLE(lpstrText)); + return (bstrText != NULL) ? TRUE : FALSE; + } +#endif // _OLEAUTO_H_ +#endif // !_ATL_NO_COM + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + int GetText(int nIndex, _CSTRING_NS::CString& strText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + int cchLen = GetTextLen(nIndex); + if(cchLen == LB_ERR) + return LB_ERR; + int nRet = LB_ERR; + LPTSTR lpstr = strText.GetBufferSetLength(cchLen); + if(lpstr != NULL) + { + nRet = GetText(nIndex, lpstr); + strText.ReleaseBuffer(); + } + return nRet; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + + int GetTextLen(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_GETTEXTLEN, nIndex, 0L); + } + + int GetItemHeight(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_GETITEMHEIGHT, nIndex, 0L); + } + + int SetItemHeight(int nIndex, UINT cyItemHeight) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0)); + } + + // Settable only attributes + void SetColumnWidth(int cxWidth) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LB_SETCOLUMNWIDTH, cxWidth, 0L); + } + + BOOL SetTabStops(int nTabStops, LPINT rgTabStops) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0); + return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops); + } + + BOOL SetTabStops() + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0); + return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, 0, 0L); + } + + BOOL SetTabStops(const int& cxEachStop) // takes an 'int' + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0); + return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop); + } + +// Operations + int InitStorage(int nItems, UINT nBytes) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_INITSTORAGE, (WPARAM)nItems, nBytes); + } + + void ResetContent() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LB_RESETCONTENT, 0, 0L); + } + + UINT ItemFromPoint(POINT pt, BOOL& bOutside) const + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dw = (DWORD)::SendMessage(m_hWnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(pt.x, pt.y)); + bOutside = (BOOL)HIWORD(dw); + return (UINT)LOWORD(dw); + } + + // manipulating listbox items + int AddString(LPCTSTR lpszItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_ADDSTRING, 0, (LPARAM)lpszItem); + } + + int DeleteString(UINT nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_DELETESTRING, nIndex, 0L); + } + + int InsertString(int nIndex, LPCTSTR lpszItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_INSERTSTRING, nIndex, (LPARAM)lpszItem); + } + +#ifndef _WIN32_WCE + int Dir(UINT attr, LPCTSTR lpszWildCard) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_DIR, attr, (LPARAM)lpszWildCard); + } + + int AddFile(LPCTSTR lpstrFileName) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_ADDFILE, 0, (LPARAM)lpstrFileName); + } +#endif // !_WIN32_WCE + + // selection helpers + int FindString(int nStartAfter, LPCTSTR lpszItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_FINDSTRING, nStartAfter, (LPARAM)lpszItem); + } + + int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_FINDSTRINGEXACT, nIndexStart, (LPARAM)lpszFind); + } + + int SelectString(int nStartAfter, LPCTSTR lpszItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LB_SELECTSTRING, nStartAfter, (LPARAM)lpszItem); + } + + int SelItemRange(BOOL bSelect, int nFirstItem, int nLastItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0); + ATLASSERT(nFirstItem <= nLastItem); + return bSelect ? (int)::SendMessage(m_hWnd, LB_SELITEMRANGEEX, nFirstItem, nLastItem) : (int)::SendMessage(m_hWnd, LB_SELITEMRANGEEX, nLastItem, nFirstItem); + } + +#ifdef WIN32_PLATFORM_WFSP // SmartPhone only messages + DWORD GetInputMode(BOOL bCurrentMode = TRUE) + { + return SendMessage(LB_GETINPUTMODE, 0, (LPARAM)bCurrentMode); + } + + BOOL SetInputMode(DWORD dwMode) + { + return SendMessage(LB_SETINPUTMODE, 0, (LPARAM)dwMode); + } +#endif // WIN32_PLATFORM_WFSP +}; + +typedef CListBoxT CListBox; + + +/////////////////////////////////////////////////////////////////////////////// +// CComboBox - client side for a Windows COMBOBOX control + +#ifndef WIN32_PLATFORM_WFSP // No COMBOBOX on SmartPhones + +template +class CComboBoxT : public TBase +{ +public: +// Constructors + CComboBoxT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CComboBoxT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return _T("COMBOBOX"); + } + + // for entire combo box + int GetCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_GETCOUNT, 0, 0L); + } + + int GetCurSel() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_GETCURSEL, 0, 0L); + } + + int SetCurSel(int nSelect) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_SETCURSEL, nSelect, 0L); + } + + LCID GetLocale() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (LCID)::SendMessage(m_hWnd, CB_GETLOCALE, 0, 0L); + } + + LCID SetLocale(LCID nNewLocale) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (LCID)::SendMessage(m_hWnd, CB_SETLOCALE, (WPARAM)nNewLocale, 0L); + } + + int GetTopIndex() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_GETTOPINDEX, 0, 0L); + } + + int SetTopIndex(int nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_SETTOPINDEX, nIndex, 0L); + } + + UINT GetHorizontalExtent() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, CB_GETHORIZONTALEXTENT, 0, 0L); + } + + void SetHorizontalExtent(UINT nExtent) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, CB_SETHORIZONTALEXTENT, nExtent, 0L); + } + + int GetDroppedWidth() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_GETDROPPEDWIDTH, 0, 0L); + } + + int SetDroppedWidth(UINT nWidth) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_SETDROPPEDWIDTH, nWidth, 0L); + } + +#if ((WINVER >= 0x0500) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420)) + BOOL GetComboBoxInfo(PCOMBOBOXINFO pComboBoxInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); +#if ((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420)) + return (BOOL)::SendMessage(m_hWnd, CB_GETCOMBOBOXINFO, 0, (LPARAM)pComboBoxInfo); +#else // !((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420)) + return ::GetComboBoxInfo(m_hWnd, pComboBoxInfo); +#endif // !((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420)) + } +#endif // ((WINVER >= 0x0500) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420)) + + // for edit control + DWORD GetEditSel() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, CB_GETEDITSEL, 0, 0L); + } + + BOOL SetEditSel(int nStartChar, int nEndChar) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, CB_SETEDITSEL, 0, MAKELONG(nStartChar, nEndChar)); + } + + // for combobox item + DWORD_PTR GetItemData(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD_PTR)::SendMessage(m_hWnd, CB_GETITEMDATA, nIndex, 0L); + } + + int SetItemData(int nIndex, DWORD_PTR dwItemData) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_SETITEMDATA, nIndex, (LPARAM)dwItemData); + } + + void* GetItemDataPtr(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (void*)GetItemData(nIndex); + } + + int SetItemDataPtr(int nIndex, void* pData) + { + ATLASSERT(::IsWindow(m_hWnd)); + return SetItemData(nIndex, (DWORD_PTR)pData); + } + + int GetLBText(int nIndex, LPTSTR lpszText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_GETLBTEXT, nIndex, (LPARAM)lpszText); + } + +#ifndef _ATL_NO_COM + BOOL GetLBTextBSTR(int nIndex, BSTR& bstrText) const + { + USES_CONVERSION; + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(bstrText == NULL); + + int nLen = GetLBTextLen(nIndex); + if(nLen == CB_ERR) + return FALSE; + + CTempBuffer buff; + LPTSTR lpstrText = buff.Allocate(nLen + 1); + if(lpstrText == NULL) + return FALSE; + + if(GetLBText(nIndex, lpstrText) == CB_ERR) + return FALSE; + + bstrText = ::SysAllocString(T2OLE(lpstrText)); + return (bstrText != NULL) ? TRUE : FALSE; + } +#endif // !_ATL_NO_COM + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + int GetLBText(int nIndex, _CSTRING_NS::CString& strText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + int cchLen = GetLBTextLen(nIndex); + if(cchLen == CB_ERR) + return CB_ERR; + int nRet = CB_ERR; + LPTSTR lpstr = strText.GetBufferSetLength(cchLen); + if(lpstr != NULL) + { + nRet = GetLBText(nIndex, lpstr); + strText.ReleaseBuffer(); + } + return nRet; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + + int GetLBTextLen(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_GETLBTEXTLEN, nIndex, 0L); + } + + int GetItemHeight(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_GETITEMHEIGHT, nIndex, 0L); + } + + int SetItemHeight(int nIndex, UINT cyItemHeight) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0)); + } + + BOOL GetExtendedUI() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, CB_GETEXTENDEDUI, 0, 0L); + } + + int SetExtendedUI(BOOL bExtended = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_SETEXTENDEDUI, bExtended, 0L); + } + + void GetDroppedControlRect(LPRECT lprect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)lprect); + } + + BOOL GetDroppedState() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, CB_GETDROPPEDSTATE, 0, 0L); + } + +#if (_WIN32_WINNT >= 0x0501) + int GetMinVisible() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_GETMINVISIBLE, 0, 0L); + } + + BOOL SetMinVisible(int nMinVisible) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, CB_SETMINVISIBLE, nMinVisible, 0L); + } + + // Vista only + BOOL GetCueBannerText(LPWSTR lpwText, int cchText) const + { +#ifndef CB_GETCUEBANNER + const UINT CB_GETCUEBANNER = (CBM_FIRST + 4); +#endif + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, CB_GETCUEBANNER, (WPARAM)lpwText, cchText); + } + + // Vista only + BOOL SetCueBannerText(LPCWSTR lpcwText) + { +#ifndef CB_SETCUEBANNER + const UINT CB_SETCUEBANNER = (CBM_FIRST + 3); +#endif + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, CB_SETCUEBANNER, 0, (LPARAM)lpcwText); + } +#endif // (_WIN32_WINNT >= 0x0501) + +// Operations + int InitStorage(int nItems, UINT nBytes) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_INITSTORAGE, (WPARAM)nItems, nBytes); + } + + void ResetContent() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, CB_RESETCONTENT, 0, 0L); + } + + // for edit control + BOOL LimitText(int nMaxChars) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, CB_LIMITTEXT, nMaxChars, 0L); + } + + // for drop-down combo boxes + void ShowDropDown(BOOL bShowIt = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, CB_SHOWDROPDOWN, bShowIt, 0L); + } + + // manipulating listbox items + int AddString(LPCTSTR lpszString) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_ADDSTRING, 0, (LPARAM)lpszString); + } + + int DeleteString(UINT nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_DELETESTRING, nIndex, 0L); + } + + int InsertString(int nIndex, LPCTSTR lpszString) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_INSERTSTRING, nIndex, (LPARAM)lpszString); + } + +#ifndef _WIN32_WCE + int Dir(UINT attr, LPCTSTR lpszWildCard) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_DIR, attr, (LPARAM)lpszWildCard); + } +#endif // !_WIN32_WCE + + // selection helpers + int FindString(int nStartAfter, LPCTSTR lpszString) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_FINDSTRING, nStartAfter, (LPARAM)lpszString); + } + + int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_FINDSTRINGEXACT, nIndexStart, (LPARAM)lpszFind); + } + + int SelectString(int nStartAfter, LPCTSTR lpszString) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CB_SELECTSTRING, nStartAfter, (LPARAM)lpszString); + } + + // Clipboard operations + void Clear() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L); + } + + void Copy() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_COPY, 0, 0L); + } + + void Cut() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_CUT, 0, 0L); + } + + void Paste() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_PASTE, 0, 0L); + } +}; + +typedef CComboBoxT CComboBox; + +#endif // !WIN32_PLATFORM_WFSP + +/////////////////////////////////////////////////////////////////////////////// +// CEdit - client side for a Windows EDIT control + +template +class CEditT : public TBase +{ +public: +// Constructors + CEditT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CEditT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return _T("EDIT"); + } + + BOOL CanUndo() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_CANUNDO, 0, 0L); + } + + int GetLineCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_GETLINECOUNT, 0, 0L); + } + + BOOL GetModify() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_GETMODIFY, 0, 0L); + } + + void SetModify(BOOL bModified = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETMODIFY, bModified, 0L); + } + + void GetRect(LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_GETRECT, 0, (LPARAM)lpRect); + } + + DWORD GetSel() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, EM_GETSEL, 0, 0L); + } + + void GetSel(int& nStartChar, int& nEndChar) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar); + } + +#ifndef _WIN32_WCE + HLOCAL GetHandle() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HLOCAL)::SendMessage(m_hWnd, EM_GETHANDLE, 0, 0L); + } + + void SetHandle(HLOCAL hBuffer) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETHANDLE, (WPARAM)hBuffer, 0L); + } +#endif // !_WIN32_WCE + + DWORD GetMargins() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, EM_GETMARGINS, 0, 0L); + } + + void SetMargins(UINT nLeft, UINT nRight) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN, MAKELONG(nLeft, nRight)); + } + + UINT GetLimitText() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, EM_GETLIMITTEXT, 0, 0L); + } + + void SetLimitText(UINT nMax) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETLIMITTEXT, nMax, 0L); + } + + POINT PosFromChar(UINT nChar) const + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_POSFROMCHAR, nChar, 0); + POINT point = { GET_X_LPARAM(dwRet), GET_Y_LPARAM(dwRet) }; + return point; + } + + int CharFromPos(POINT pt, int* pLine = NULL) const + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y)); + if(pLine != NULL) + *pLine = (int)(short)HIWORD(dwRet); + return (int)(short)LOWORD(dwRet); + } + + // NOTE: first word in lpszBuffer must contain the size of the buffer! + int GetLine(int nIndex, LPTSTR lpszBuffer) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer); + } + + int GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const + { + ATLASSERT(::IsWindow(m_hWnd)); + *(LPWORD)lpszBuffer = (WORD)nMaxLength; + return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer); + } + + TCHAR GetPasswordChar() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (TCHAR)::SendMessage(m_hWnd, EM_GETPASSWORDCHAR, 0, 0L); + } + + void SetPasswordChar(TCHAR ch) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETPASSWORDCHAR, ch, 0L); + } + +#ifndef _WIN32_WCE + EDITWORDBREAKPROC GetWordBreakProc() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (EDITWORDBREAKPROC)::SendMessage(m_hWnd, EM_GETWORDBREAKPROC, 0, 0L); + } + + void SetWordBreakProc(EDITWORDBREAKPROC ewbprc) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETWORDBREAKPROC, 0, (LPARAM)ewbprc); + } +#endif // !_WIN32_WCE + + int GetFirstVisibleLine() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_GETFIRSTVISIBLELINE, 0, 0L); + } + +#ifndef _WIN32_WCE + int GetThumb() const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & ES_MULTILINE) != 0); + return (int)::SendMessage(m_hWnd, EM_GETTHUMB, 0, 0L); + } +#endif // !_WIN32_WCE + + BOOL SetReadOnly(BOOL bReadOnly = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_SETREADONLY, bReadOnly, 0L); + } + +#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) + UINT GetImeStatus(UINT uStatus) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, EM_GETIMESTATUS, uStatus, 0L); + } + + UINT SetImeStatus(UINT uStatus, UINT uData) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, EM_SETIMESTATUS, uStatus, uData); + } +#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) + +#if (_WIN32_WINNT >= 0x0501) + BOOL GetCueBannerText(LPCWSTR lpstrText, int cchText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_GETCUEBANNER, (WPARAM)lpstrText, cchText); + } + + // bKeepWithFocus - Vista only + BOOL SetCueBannerText(LPCWSTR lpstrText, BOOL bKeepWithFocus = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_SETCUEBANNER, (WPARAM)bKeepWithFocus, (LPARAM)(lpstrText)); + } +#endif // (_WIN32_WINNT >= 0x0501) + +// Operations + void EmptyUndoBuffer() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_EMPTYUNDOBUFFER, 0, 0L); + } + + BOOL FmtLines(BOOL bAddEOL) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_FMTLINES, bAddEOL, 0L); + } + + void LimitText(int nChars = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_LIMITTEXT, nChars, 0L); + } + + int LineFromChar(int nIndex = -1) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_LINEFROMCHAR, nIndex, 0L); + } + + int LineIndex(int nLine = -1) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_LINEINDEX, nLine, 0L); + } + + int LineLength(int nLine = -1) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_LINELENGTH, nLine, 0L); + } + + void LineScroll(int nLines, int nChars = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_LINESCROLL, nChars, nLines); + } + + void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText); + } + + void SetRect(LPCRECT lpRect) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETRECT, 0, (LPARAM)lpRect); + } + + void SetRectNP(LPCRECT lpRect) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETRECTNP, 0, (LPARAM)lpRect); + } + + void SetSel(DWORD dwSelection, BOOL bNoScroll = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETSEL, LOWORD(dwSelection), HIWORD(dwSelection)); + if(!bNoScroll) + ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L); + } + + void SetSel(int nStartChar, int nEndChar, BOOL bNoScroll = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETSEL, nStartChar, nEndChar); + if(!bNoScroll) + ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L); + } + + void SetSelAll(BOOL bNoScroll = FALSE) + { + SetSel(0, -1, bNoScroll); + } + + void SetSelNone(BOOL bNoScroll = FALSE) + { + SetSel(-1, 0, bNoScroll); + } + + BOOL SetTabStops(int nTabStops, LPINT rgTabStops) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops); + } + + BOOL SetTabStops() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 0, 0L); + } + + BOOL SetTabStops(const int& cxEachStop) // takes an 'int' + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop); + } + + void ScrollCaret() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L); + } + + int Scroll(int nScrollAction) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & ES_MULTILINE) != 0); + LRESULT lRet = ::SendMessage(m_hWnd, EM_SCROLL, nScrollAction, 0L); + if(!(BOOL)HIWORD(lRet)) + return -1; // failed + return (int)(short)LOWORD(lRet); + + } + + void InsertText(int nInsertAfterChar, LPCTSTR lpstrText, BOOL bNoScroll = FALSE, BOOL bCanUndo = FALSE) + { + SetSel(nInsertAfterChar, nInsertAfterChar, bNoScroll); + ReplaceSel(lpstrText, bCanUndo); + } + + void AppendText(LPCTSTR lpstrText, BOOL bNoScroll = FALSE, BOOL bCanUndo = FALSE) + { + InsertText(GetWindowTextLength(), lpstrText, bNoScroll, bCanUndo); + } + +#if (_WIN32_WINNT >= 0x0501) + BOOL ShowBalloonTip(PEDITBALLOONTIP pEditBaloonTip) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_SHOWBALLOONTIP, 0, (LPARAM)pEditBaloonTip); + } + + BOOL HideBalloonTip() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_HIDEBALLOONTIP, 0, 0L); + } +#endif // (_WIN32_WINNT >= 0x0501) + +#if (_WIN32_WINNT >= 0x0600) + DWORD GetHilite() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, EM_GETHILITE, 0, 0L); + } + + void GetHilite(int& nStartChar, int& nEndChar) const + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_GETHILITE, 0, 0L); + nStartChar = (int)(short)LOWORD(dwRet); + nEndChar = (int)(short)HIWORD(dwRet); + } + + void SetHilite(int nStartChar, int nEndChar) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETHILITE, nStartChar, nEndChar); + } +#endif // (_WIN32_WINNT >= 0x0600) + + // Clipboard operations + BOOL Undo() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_UNDO, 0, 0L); + } + + void Clear() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L); + } + + void Copy() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_COPY, 0, 0L); + } + + void Cut() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_CUT, 0, 0L); + } + + void Paste() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_PASTE, 0, 0L); + } + +#ifdef WIN32_PLATFORM_WFSP // SmartPhone only messages + DWORD GetExtendedStyle() + { + return SendMessage(EM_GETEXTENDEDSTYLE); + } + + DWORD SetExtendedStyle(DWORD dwMask, DWORD dwExStyle) + { + return SendMessage(EM_SETEXTENDEDSTYLE, (WPARAM)dwMask, (LPARAM)dwExStyle); + } + + DWORD GetInputMode(BOOL bCurrentMode = TRUE) + { + return SendMessage(EM_GETINPUTMODE, 0, (LPARAM)bCurrentMode); + } + + BOOL SetInputMode(DWORD dwMode) + { + return SendMessage(EM_SETINPUTMODE, 0, (LPARAM)dwMode); + } + + BOOL SetSymbols(LPCTSTR szSymbols) + { + return SendMessage(EM_SETSYMBOLS, 0, (LPARAM)szSymbols); + } + + BOOL ResetSymbols() + { + return SendMessage(EM_SETSYMBOLS); + } +#endif // WIN32_PLATFORM_WFSP +}; + +typedef CEditT CEdit; + + +/////////////////////////////////////////////////////////////////////////////// +// CEditCommands - message handlers for standard EDIT commands + +// Chain to CEditCommands message map. Your class must also derive from CEdit. +// Example: +// class CMyEdit : public CWindowImpl, +// public CEditCommands +// { +// public: +// BEGIN_MSG_MAP(CMyEdit) +// // your handlers... +// CHAIN_MSG_MAP_ALT(CEditCommands, 1) +// END_MSG_MAP() +// // other stuff... +// }; + +template +class CEditCommands +{ +public: + BEGIN_MSG_MAP(CEditCommands< T >) + ALT_MSG_MAP(1) + COMMAND_ID_HANDLER(ID_EDIT_CLEAR, OnEditClear) + COMMAND_ID_HANDLER(ID_EDIT_CLEAR_ALL, OnEditClearAll) + COMMAND_ID_HANDLER(ID_EDIT_COPY, OnEditCopy) + COMMAND_ID_HANDLER(ID_EDIT_CUT, OnEditCut) + COMMAND_ID_HANDLER(ID_EDIT_PASTE, OnEditPaste) + COMMAND_ID_HANDLER(ID_EDIT_SELECT_ALL, OnEditSelectAll) + COMMAND_ID_HANDLER(ID_EDIT_UNDO, OnEditUndo) + END_MSG_MAP() + + LRESULT OnEditClear(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->Clear(); + return 0; + } + + LRESULT OnEditClearAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->SetSel(0, -1); + pT->Clear(); + return 0; + } + + LRESULT OnEditCopy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->Copy(); + return 0; + } + + LRESULT OnEditCut(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->Cut(); + return 0; + } + + LRESULT OnEditPaste(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->Paste(); + return 0; + } + + LRESULT OnEditSelectAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->SetSel(0, -1); + return 0; + } + + LRESULT OnEditUndo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->Undo(); + return 0; + } + +// State (update UI) helpers + BOOL CanCut() const + { return HasSelection(); } + + BOOL CanCopy() const + { return HasSelection(); } + + BOOL CanClear() const + { return HasSelection(); } + + BOOL CanSelectAll() const + { return HasText(); } + + BOOL CanFind() const + { return HasText(); } + + BOOL CanRepeat() const + { return HasText(); } + + BOOL CanReplace() const + { return HasText(); } + + BOOL CanClearAll() const + { return HasText(); } + +// Implementation + BOOL HasSelection() const + { + const T* pT = static_cast(this); + int nMin, nMax; + ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nMin, (LPARAM)&nMax); + return (nMin != nMax); + } + + BOOL HasText() const + { + const T* pT = static_cast(this); + return (pT->GetWindowTextLength() > 0); + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CScrollBar - client side for a Windows SCROLLBAR control + +template +class CScrollBarT : public TBase +{ +public: +// Constructors + CScrollBarT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CScrollBarT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return _T("SCROLLBAR"); + } + +#ifndef _WIN32_WCE + int GetScrollPos() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetScrollPos(m_hWnd, SB_CTL); + } +#endif // !_WIN32_WCE + + int SetScrollPos(int nPos, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetScrollPos(m_hWnd, SB_CTL, nPos, bRedraw); + } + +#ifndef _WIN32_WCE + void GetScrollRange(LPINT lpMinPos, LPINT lpMaxPos) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::GetScrollRange(m_hWnd, SB_CTL, lpMinPos, lpMaxPos); + } +#endif // !_WIN32_WCE + + void SetScrollRange(int nMinPos, int nMaxPos, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SetScrollRange(m_hWnd, SB_CTL, nMinPos, nMaxPos, bRedraw); + } + + BOOL GetScrollInfo(LPSCROLLINFO lpScrollInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetScrollInfo(m_hWnd, SB_CTL, lpScrollInfo); + } + + int SetScrollInfo(LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetScrollInfo(m_hWnd, SB_CTL, lpScrollInfo, bRedraw); + } + +#ifndef _WIN32_WCE + int GetScrollLimit() const + { + int nMin = 0, nMax = 0; + ::GetScrollRange(m_hWnd, SB_CTL, &nMin, &nMax); + SCROLLINFO info = { 0 }; + info.cbSize = sizeof(SCROLLINFO); + info.fMask = SIF_PAGE; + if(::GetScrollInfo(m_hWnd, SB_CTL, &info)) + nMax -= ((info.nPage - 1) > 0) ? (info.nPage - 1) : 0; + + return nMax; + } + +#if (WINVER >= 0x0500) + BOOL GetScrollBarInfo(PSCROLLBARINFO pScrollBarInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); +#if (_WIN32_WINNT >= 0x0501) + return (BOOL)::SendMessage(m_hWnd, SBM_GETSCROLLBARINFO, 0, (LPARAM)pScrollBarInfo); +#else // !(_WIN32_WINNT >= 0x0501) + return ::GetScrollBarInfo(m_hWnd, OBJID_CLIENT, pScrollBarInfo); +#endif // !(_WIN32_WINNT >= 0x0501) + } +#endif // (WINVER >= 0x0500) + +// Operations + void ShowScrollBar(BOOL bShow = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::ShowScrollBar(m_hWnd, SB_CTL, bShow); + } + + BOOL EnableScrollBar(UINT nArrowFlags = ESB_ENABLE_BOTH) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::EnableScrollBar(m_hWnd, SB_CTL, nArrowFlags); + } +#endif // !_WIN32_WCE +}; + +typedef CScrollBarT CScrollBar; + + +// --- Windows Common Controls --- + +/////////////////////////////////////////////////////////////////////////////// +// CImageList + +class CImageList +{ +public: + HIMAGELIST m_hImageList; + +// Constructor + CImageList(HIMAGELIST hImageList = NULL) : m_hImageList(hImageList) + { } + +// Operators, etc. + CImageList& operator =(HIMAGELIST hImageList) + { + m_hImageList = hImageList; + return *this; + } + + operator HIMAGELIST() const { return m_hImageList; } + + void Attach(HIMAGELIST hImageList) + { + ATLASSERT(m_hImageList == NULL); + ATLASSERT(hImageList != NULL); + m_hImageList = hImageList; + } + + HIMAGELIST Detach() + { + HIMAGELIST hImageList = m_hImageList; + m_hImageList = NULL; + return hImageList; + } + + bool IsNull() const { return (m_hImageList == NULL); } + +// Attributes + int GetImageCount() const + { + ATLASSERT(m_hImageList != NULL); + return ImageList_GetImageCount(m_hImageList); + } + + COLORREF GetBkColor() const + { + ATLASSERT(m_hImageList != NULL); + return ImageList_GetBkColor(m_hImageList); + } + + COLORREF SetBkColor(COLORREF cr) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_SetBkColor(m_hImageList, cr); + } + + BOOL GetImageInfo(int nImage, IMAGEINFO* pImageInfo) const + { + ATLASSERT(m_hImageList != NULL); + return ImageList_GetImageInfo(m_hImageList, nImage, pImageInfo); + } + + HICON GetIcon(int nIndex, UINT uFlags = ILD_NORMAL) const + { + ATLASSERT(m_hImageList != NULL); + return ImageList_GetIcon(m_hImageList, nIndex, uFlags); + } + + BOOL GetIconSize(int& cx, int& cy) const + { + ATLASSERT(m_hImageList != NULL); + return ImageList_GetIconSize(m_hImageList, &cx, &cy); + } + + BOOL GetIconSize(SIZE& size) const + { + ATLASSERT(m_hImageList != NULL); + return ImageList_GetIconSize(m_hImageList, (int*)&size.cx, (int*)&size.cy); + } + + BOOL SetIconSize(int cx, int cy) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_SetIconSize(m_hImageList, cx, cy); + } + + BOOL SetIconSize(SIZE size) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_SetIconSize(m_hImageList, size.cx, size.cy); + } + + BOOL SetImageCount(UINT uNewCount) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_SetImageCount(m_hImageList, uNewCount); + } + + BOOL SetOverlayImage(int nImage, int nOverlay) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_SetOverlayImage(m_hImageList, nImage, nOverlay); + } + +// Operations + BOOL Create(int cx, int cy, UINT nFlags, int nInitial, int nGrow) + { + ATLASSERT(m_hImageList == NULL); + m_hImageList = ImageList_Create(cx, cy, nFlags, nInitial, nGrow); + return (m_hImageList != NULL) ? TRUE : FALSE; + } + + BOOL Create(ATL::_U_STRINGorID bitmap, int cx, int nGrow, COLORREF crMask) + { + ATLASSERT(m_hImageList == NULL); + m_hImageList = ImageList_LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr, cx, nGrow, crMask); + return (m_hImageList != NULL) ? TRUE : FALSE; + } + + BOOL CreateFromImage(ATL::_U_STRINGorID image, int cx, int nGrow, COLORREF crMask, UINT uType, UINT uFlags = LR_DEFAULTCOLOR | LR_DEFAULTSIZE) + { + ATLASSERT(m_hImageList == NULL); + m_hImageList = ImageList_LoadImage(ModuleHelper::GetResourceInstance(), image.m_lpstr, cx, nGrow, crMask, uType, uFlags); + return (m_hImageList != NULL) ? TRUE : FALSE; + } + + BOOL Merge(HIMAGELIST hImageList1, int nImage1, HIMAGELIST hImageList2, int nImage2, int dx, int dy) + { + ATLASSERT(m_hImageList == NULL); + m_hImageList = ImageList_Merge(hImageList1, nImage1, hImageList2, nImage2, dx, dy); + return (m_hImageList != NULL) ? TRUE : FALSE; + } + +#ifndef _WIN32_WCE +#ifdef __IStream_INTERFACE_DEFINED__ + BOOL CreateFromStream(LPSTREAM lpStream) + { + ATLASSERT(m_hImageList == NULL); + m_hImageList = ImageList_Read(lpStream); + return (m_hImageList != NULL) ? TRUE : FALSE; + } +#endif // __IStream_INTERFACE_DEFINED__ +#endif // !_WIN32_WCE + + BOOL Destroy() + { + if (m_hImageList == NULL) + return FALSE; + BOOL bRet = ImageList_Destroy(m_hImageList); + if(bRet) + m_hImageList = NULL; + return bRet; + } + + int Add(HBITMAP hBitmap, HBITMAP hBitmapMask = NULL) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_Add(m_hImageList, hBitmap, hBitmapMask); + } + + int Add(HBITMAP hBitmap, COLORREF crMask) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_AddMasked(m_hImageList, hBitmap, crMask); + } + + BOOL Remove(int nImage) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_Remove(m_hImageList, nImage); + } + + BOOL RemoveAll() + { + ATLASSERT(m_hImageList != NULL); + return ImageList_RemoveAll(m_hImageList); + } + + BOOL Replace(int nImage, HBITMAP hBitmap, HBITMAP hBitmapMask) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_Replace(m_hImageList, nImage, hBitmap, hBitmapMask); + } + + int AddIcon(HICON hIcon) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_AddIcon(m_hImageList, hIcon); + } + + int ReplaceIcon(int nImage, HICON hIcon) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_ReplaceIcon(m_hImageList, nImage, hIcon); + } + + HICON ExtractIcon(int nImage) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_ExtractIcon(NULL, m_hImageList, nImage); + } + + BOOL Draw(HDC hDC, int nImage, int x, int y, UINT nStyle) + { + ATLASSERT(m_hImageList != NULL); + ATLASSERT(hDC != NULL); + return ImageList_Draw(m_hImageList, nImage, hDC, x, y, nStyle); + } + + BOOL Draw(HDC hDC, int nImage, POINT pt, UINT nStyle) + { + ATLASSERT(m_hImageList != NULL); + ATLASSERT(hDC != NULL); + return ImageList_Draw(m_hImageList, nImage, hDC, pt.x, pt.y, nStyle); + } + + BOOL DrawEx(int nImage, HDC hDC, int x, int y, int dx, int dy, COLORREF rgbBk, COLORREF rgbFg, UINT fStyle) + { + ATLASSERT(m_hImageList != NULL); + ATLASSERT(hDC != NULL); + return ImageList_DrawEx(m_hImageList, nImage, hDC, x, y, dx, dy, rgbBk, rgbFg, fStyle); + } + + BOOL DrawEx(int nImage, HDC hDC, RECT& rect, COLORREF rgbBk, COLORREF rgbFg, UINT fStyle) + { + ATLASSERT(m_hImageList != NULL); + ATLASSERT(hDC != NULL); + return ImageList_DrawEx(m_hImageList, nImage, hDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, rgbBk, rgbFg, fStyle); + } + + static BOOL DrawIndirect(IMAGELISTDRAWPARAMS* pimldp) + { + return ImageList_DrawIndirect(pimldp); + } + + BOOL Copy(int nSrc, int nDst, UINT uFlags = ILCF_MOVE) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_Copy(m_hImageList, nDst, m_hImageList, nSrc, uFlags); + } + +#ifdef __IStream_INTERFACE_DEFINED__ +#ifndef _WIN32_WCE + static HIMAGELIST Read(LPSTREAM lpStream) + { + return ImageList_Read(lpStream); + } + + BOOL Write(LPSTREAM lpStream) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_Write(m_hImageList, lpStream); + } +#endif // !_WIN32_WCE + +#if (_WIN32_WINNT >= 0x0501) + static HRESULT ReadEx(DWORD dwFlags, LPSTREAM lpStream, REFIID riid, PVOID* ppv) + { + return ImageList_ReadEx(dwFlags, lpStream, riid, ppv); + } + + HRESULT WriteEx(DWORD dwFlags, LPSTREAM lpStream) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_WriteEx(m_hImageList, dwFlags, lpStream); + } +#endif // (_WIN32_WINNT >= 0x0501) +#endif // __IStream_INTERFACE_DEFINED__ + + // Drag operations + BOOL BeginDrag(int nImage, POINT ptHotSpot) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_BeginDrag(m_hImageList, nImage, ptHotSpot.x, ptHotSpot.y); + } + + BOOL BeginDrag(int nImage, int xHotSpot, int yHotSpot) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_BeginDrag(m_hImageList, nImage, xHotSpot, yHotSpot); + } + + static void EndDrag() + { + ImageList_EndDrag(); + } + + static BOOL DragMove(POINT pt) + { + return ImageList_DragMove(pt.x, pt.y); + } + + static BOOL DragMove(int x, int y) + { + return ImageList_DragMove(x, y); + } + + BOOL SetDragCursorImage(int nDrag, POINT ptHotSpot) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_SetDragCursorImage(m_hImageList, nDrag, ptHotSpot.x, ptHotSpot.y); + } + + BOOL SetDragCursorImage(int nDrag, int xHotSpot, int yHotSpot) + { + ATLASSERT(m_hImageList != NULL); + return ImageList_SetDragCursorImage(m_hImageList, nDrag, xHotSpot, yHotSpot); + } + + static BOOL DragShowNolock(BOOL bShow = TRUE) + { + return ImageList_DragShowNolock(bShow); + } + + static CImageList GetDragImage(LPPOINT lpPoint, LPPOINT lpPointHotSpot) + { + return CImageList(ImageList_GetDragImage(lpPoint, lpPointHotSpot)); + } + + static BOOL DragEnter(HWND hWnd, POINT point) + { + return ImageList_DragEnter(hWnd, point.x, point.y); + } + + static BOOL DragEnter(HWND hWnd, int x, int y) + { + return ImageList_DragEnter(hWnd, x, y); + } + + static BOOL DragLeave(HWND hWnd) + { + return ImageList_DragLeave(hWnd); + } + +#if (_WIN32_IE >= 0x0400) + CImageList Duplicate() const + { + ATLASSERT(m_hImageList != NULL); + return CImageList(ImageList_Duplicate(m_hImageList)); + } + + static CImageList Duplicate(HIMAGELIST hImageList) + { + ATLASSERT(hImageList != NULL); + return CImageList(ImageList_Duplicate(hImageList)); + } +#endif // (_WIN32_IE >= 0x0400) +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CToolTipCtrl + +#ifndef _WIN32_WCE + +class CToolInfo : public TOOLINFO +{ +public: + CToolInfo(UINT nFlags, HWND hWnd, UINT nIDTool = 0, LPRECT lpRect = NULL, LPTSTR lpstrText = LPSTR_TEXTCALLBACK, LPARAM lUserParam = NULL) + { + Init(nFlags, hWnd, nIDTool, lpRect, lpstrText, lUserParam); + } + + operator LPTOOLINFO() { return this; } + + operator LPARAM() { return (LPARAM)this; } + + void Init(UINT nFlags, HWND hWnd, UINT nIDTool = 0, LPRECT lpRect = NULL, LPTSTR lpstrText = LPSTR_TEXTCALLBACK, LPARAM lUserParam = NULL) + { + ATLASSERT(::IsWindow(hWnd)); + memset(this, 0, sizeof(TOOLINFO)); + cbSize = sizeof(TOOLINFO); + uFlags = nFlags; + if(nIDTool == 0) + { + hwnd = ::GetParent(hWnd); + uFlags |= TTF_IDISHWND; + uId = (UINT_PTR)hWnd; + } + else + { + hwnd = hWnd; + uId = nIDTool; + } + if(lpRect != NULL) + rect = *lpRect; + hinst = ModuleHelper::GetResourceInstance(); + lpszText = lpstrText; + lParam = lUserParam; + } +}; + +template +class CToolTipCtrlT : public TBase +{ +public: +// Constructors + CToolTipCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CToolTipCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return TOOLTIPS_CLASS; + } + + void GetText(LPTOOLINFO lpToolInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_GETTEXT, 0, (LPARAM)&lpToolInfo); + } + + void GetText(LPTSTR lpstrText, HWND hWnd, UINT nIDTool = 0) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(hWnd != NULL); + CToolInfo ti(0, hWnd, nIDTool, NULL, lpstrText); + ::SendMessage(m_hWnd, TTM_GETTEXT, 0, ti); + } + + BOOL GetToolInfo(LPTOOLINFO lpToolInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TTM_GETTOOLINFO, 0, (LPARAM)lpToolInfo); + } + + BOOL GetToolInfo(HWND hWnd, UINT nIDTool, UINT* puFlags, LPRECT lpRect, LPTSTR lpstrText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(hWnd != NULL); + ATLASSERT(puFlags != NULL); + ATLASSERT(lpRect != NULL); + CToolInfo ti(0, hWnd, nIDTool, NULL, lpstrText); + BOOL bRet = (BOOL)::SendMessage(m_hWnd, TTM_GETTOOLINFO, 0, ti); + if(bRet != FALSE) + { + *puFlags = ti.uFlags; + *lpRect = ti.rect; + } + return bRet; + } + + void SetToolInfo(LPTOOLINFO lpToolInfo) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_SETTOOLINFO, 0, (LPARAM)lpToolInfo); + } + + void SetToolRect(LPTOOLINFO lpToolInfo) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_NEWTOOLRECT, 0, (LPARAM)lpToolInfo); + } + + void SetToolRect(HWND hWnd, UINT nIDTool, LPCRECT lpRect) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(hWnd != NULL); + ATLASSERT(nIDTool != 0); + + CToolInfo ti(0, hWnd, nIDTool, (LPRECT)lpRect, NULL); + ::SendMessage(m_hWnd, TTM_NEWTOOLRECT, 0, ti); + } + + int GetToolCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TTM_GETTOOLCOUNT, 0, 0L); + } + + int GetDelayTime(DWORD dwType) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TTM_GETDELAYTIME, dwType, 0L); + } + + void SetDelayTime(DWORD dwType, int nTime) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_SETDELAYTIME, dwType, MAKELPARAM(nTime, 0)); + } + + void GetMargin(LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_GETMARGIN, 0, (LPARAM)lpRect); + } + + void SetMargin(LPRECT lpRect) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_SETMARGIN, 0, (LPARAM)lpRect); + } + + int GetMaxTipWidth() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TTM_GETMAXTIPWIDTH, 0, 0L); + } + + int SetMaxTipWidth(int nWidth) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TTM_SETMAXTIPWIDTH, 0, nWidth); + } + + COLORREF GetTipBkColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, TTM_GETTIPBKCOLOR, 0, 0L); + } + + void SetTipBkColor(COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_SETTIPBKCOLOR, (WPARAM)clr, 0L); + } + + COLORREF GetTipTextColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, TTM_GETTIPTEXTCOLOR, 0, 0L); + } + + void SetTipTextColor(COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_SETTIPTEXTCOLOR, (WPARAM)clr, 0L); + } + + BOOL GetCurrentTool(LPTOOLINFO lpToolInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TTM_GETCURRENTTOOL, 0, (LPARAM)lpToolInfo); + } + +#if (_WIN32_IE >= 0x0500) + SIZE GetBubbleSize(LPTOOLINFO lpToolInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TTM_GETBUBBLESIZE, 0, (LPARAM)lpToolInfo); + SIZE size = { GET_X_LPARAM(dwRet), GET_Y_LPARAM(dwRet) }; + return size; + } + + BOOL SetTitle(UINT uIcon, LPCTSTR lpstrTitle) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TTM_SETTITLE, uIcon, (LPARAM)lpstrTitle); + } +#endif // (_WIN32_IE >= 0x0500) + +#if (_WIN32_WINNT >= 0x0501) + void GetTitle(PTTGETTITLE pTTGetTitle) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_GETTITLE, 0, (LPARAM)pTTGetTitle); + } + + void SetWindowTheme(LPCWSTR lpstrTheme) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme); + } +#endif // (_WIN32_WINNT >= 0x0501) + +// Operations + void Activate(BOOL bActivate) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_ACTIVATE, bActivate, 0L); + } + + BOOL AddTool(LPTOOLINFO lpToolInfo) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TTM_ADDTOOL, 0, (LPARAM)lpToolInfo); + } + + BOOL AddTool(HWND hWnd, ATL::_U_STRINGorID text = LPSTR_TEXTCALLBACK, LPCRECT lpRectTool = NULL, UINT nIDTool = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(hWnd != NULL); + // the toolrect and toolid must both be zero or both valid + ATLASSERT((lpRectTool != NULL && nIDTool != 0) || (lpRectTool == NULL && nIDTool == 0)); + + CToolInfo ti(0, hWnd, nIDTool, (LPRECT)lpRectTool, (LPTSTR)text.m_lpstr); + return (BOOL)::SendMessage(m_hWnd, TTM_ADDTOOL, 0, ti); + } + + void DelTool(LPTOOLINFO lpToolInfo) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_DELTOOL, 0, (LPARAM)lpToolInfo); + } + + void DelTool(HWND hWnd, UINT nIDTool = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(hWnd != NULL); + + CToolInfo ti(0, hWnd, nIDTool, NULL, NULL); + ::SendMessage(m_hWnd, TTM_DELTOOL, 0, ti); + } + + BOOL HitTest(LPTTHITTESTINFO lpHitTestInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TTM_HITTEST, 0, (LPARAM)lpHitTestInfo); + } + + BOOL HitTest(HWND hWnd, POINT pt, LPTOOLINFO lpToolInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(hWnd != NULL); + ATLASSERT(lpToolInfo != NULL); + + TTHITTESTINFO hti = { 0 }; + hti.ti.cbSize = sizeof(TOOLINFO); + hti.hwnd = hWnd; + hti.pt.x = pt.x; + hti.pt.y = pt.y; + if((BOOL)::SendMessage(m_hWnd, TTM_HITTEST, 0, (LPARAM)&hti) != FALSE) + { + *lpToolInfo = hti.ti; + return TRUE; + } + return FALSE; + } + + void RelayEvent(LPMSG lpMsg) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_RELAYEVENT, 0, (LPARAM)lpMsg); + } + + void UpdateTipText(LPTOOLINFO lpToolInfo) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_UPDATETIPTEXT, 0, (LPARAM)lpToolInfo); + } + + void UpdateTipText(ATL::_U_STRINGorID text, HWND hWnd, UINT nIDTool = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(hWnd != NULL); + + CToolInfo ti(0, hWnd, nIDTool, NULL, (LPTSTR)text.m_lpstr); + ::SendMessage(m_hWnd, TTM_UPDATETIPTEXT, 0, ti); + } + + BOOL EnumTools(UINT nTool, LPTOOLINFO lpToolInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TTM_ENUMTOOLS, nTool, (LPARAM)lpToolInfo); + } + + void Pop() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_POP, 0, 0L); + } + + void TrackActivate(LPTOOLINFO lpToolInfo, BOOL bActivate) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_TRACKACTIVATE, bActivate, (LPARAM)lpToolInfo); + } + + void TrackPosition(int xPos, int yPos) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_TRACKPOSITION, 0, MAKELPARAM(xPos, yPos)); + } + +#if (_WIN32_IE >= 0x0400) + void Update() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_UPDATE, 0, 0L); + } +#endif // (_WIN32_IE >= 0x0400) + +#if (_WIN32_IE >= 0x0500) + BOOL AdjustRect(LPRECT lpRect, BOOL bLarger /*= TRUE*/) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TTM_ADJUSTRECT, bLarger, (LPARAM)lpRect); + } +#endif // (_WIN32_IE >= 0x0500) + +#if (_WIN32_WINNT >= 0x0501) + void Popup() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TTM_POPUP, 0, 0L); + } +#endif // (_WIN32_WINNT >= 0x0501) +}; + +typedef CToolTipCtrlT CToolTipCtrl; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CHeaderCtrl + +template +class CHeaderCtrlT : public TBase +{ +public: +// Constructors + CHeaderCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CHeaderCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return WC_HEADER; + } + + int GetItemCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, HDM_GETITEMCOUNT, 0, 0L); + } + + BOOL GetItem(int nIndex, LPHDITEM pHeaderItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, HDM_GETITEM, nIndex, (LPARAM)pHeaderItem); + } + + BOOL SetItem(int nIndex, LPHDITEM pHeaderItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, HDM_SETITEM, nIndex, (LPARAM)pHeaderItem); + } + + CImageList GetImageList() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_GETIMAGELIST, 0, 0L)); + } + + CImageList SetImageList(HIMAGELIST hImageList) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_SETIMAGELIST, 0, (LPARAM)hImageList)); + } + + BOOL GetOrderArray(int nSize, int* lpnArray) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, HDM_GETORDERARRAY, nSize, (LPARAM)lpnArray); + } + + BOOL SetOrderArray(int nSize, int* lpnArray) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, HDM_SETORDERARRAY, nSize, (LPARAM)lpnArray); + } + + BOOL GetItemRect(int nIndex, LPRECT lpItemRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, HDM_GETITEMRECT, nIndex, (LPARAM)lpItemRect); + } + + int SetHotDivider(BOOL bPos, DWORD dwInputValue) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, HDM_SETHOTDIVIDER, bPos, dwInputValue); + } + +#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + BOOL GetUnicodeFormat() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, HDM_GETUNICODEFORMAT, 0, 0L); + } + + BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, HDM_SETUNICODEFORMAT, bUnicode, 0L); + } +#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + int GetBitmapMargin() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, HDM_GETBITMAPMARGIN, 0, 0L); + } + + int SetBitmapMargin(int nWidth) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, HDM_SETBITMAPMARGIN, nWidth, 0L); + } + + int SetFilterChangeTimeout(DWORD dwTimeOut) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, HDM_SETFILTERCHANGETIMEOUT, 0, dwTimeOut); + } +#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + +#if (_WIN32_WINNT >= 0x0600) + BOOL GetItemDropDownRect(int nIndex, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, HDM_GETITEMDROPDOWNRECT, nIndex, (LPARAM)lpRect); + } + + BOOL GetOverflowRect(LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, HDM_GETOVERFLOWRECT, 0, (LPARAM)lpRect); + } + + int GetFocusedItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, HDM_GETFOCUSEDITEM, 0, 0L); + } + + BOOL SetFocusedItem(int nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, HDM_SETFOCUSEDITEM, 0, nIndex); + } +#endif // (_WIN32_WINNT >= 0x0600) + +// Operations + int InsertItem(int nIndex, LPHDITEM phdi) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, HDM_INSERTITEM, nIndex, (LPARAM)phdi); + } + + int AddItem(LPHDITEM phdi) + { + return InsertItem(GetItemCount(), phdi); + } + + BOOL DeleteItem(int nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, HDM_DELETEITEM, nIndex, 0L); + } + + BOOL Layout(HD_LAYOUT* pHeaderLayout) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, HDM_LAYOUT, 0, (LPARAM)pHeaderLayout); + } + + int HitTest(LPHDHITTESTINFO lpHitTestInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, HDM_HITTEST, 0, (LPARAM)lpHitTestInfo); + } + + int OrderToIndex(int nOrder) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, HDM_ORDERTOINDEX, nOrder, 0L); + } + + CImageList CreateDragImage(int nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_CREATEDRAGIMAGE, nIndex, 0L)); + } + +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + int EditFilter(int nColumn, BOOL bDiscardChanges) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, HDM_EDITFILTER, nColumn, MAKELPARAM(bDiscardChanges, 0)); + } + + int ClearFilter(int nColumn) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, HDM_CLEARFILTER, nColumn, 0L); + } + + int ClearAllFilters() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, HDM_CLEARFILTER, (WPARAM)-1, 0L); + } +#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) +}; + +typedef CHeaderCtrlT CHeaderCtrl; + + +/////////////////////////////////////////////////////////////////////////////// +// CListViewCtrl + +template +class CListViewCtrlT : public TBase +{ +public: +// Constructors + CListViewCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CListViewCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return WC_LISTVIEW; + } + + COLORREF GetBkColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, LVM_GETBKCOLOR, 0, 0L); + } + + BOOL SetBkColor(COLORREF cr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETBKCOLOR, 0, cr); + } + + CImageList GetImageList(int nImageListType) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_GETIMAGELIST, nImageListType, 0L)); + } + + CImageList SetImageList(HIMAGELIST hImageList, int nImageList) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_SETIMAGELIST, nImageList, (LPARAM)hImageList)); + } + + int GetItemCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_GETITEMCOUNT, 0, 0L); + } + + BOOL SetItemCount(int nItems) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMCOUNT, nItems, 0L); + } + + BOOL GetItem(LPLVITEM pItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)pItem); + } + + BOOL SetItem(const LVITEM* pItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETITEM, 0, (LPARAM)pItem); + } + + BOOL SetItem(int nItem, int nSubItem, UINT nMask, LPCTSTR lpszItem, + int nImage, UINT nState, UINT nStateMask, LPARAM lParam) + { + ATLASSERT(::IsWindow(m_hWnd)); + LVITEM lvi = { 0 }; + lvi.mask = nMask; + lvi.iItem = nItem; + lvi.iSubItem = nSubItem; + lvi.stateMask = nStateMask; + lvi.state = nState; + lvi.pszText = (LPTSTR) lpszItem; + lvi.iImage = nImage; + lvi.lParam = lParam; + return (BOOL)::SendMessage(m_hWnd, LVM_SETITEM, 0, (LPARAM)&lvi); + } + + UINT GetItemState(int nItem, UINT nMask) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, LVM_GETITEMSTATE, nItem, nMask); + } + + BOOL SetItemState(int nItem, UINT nState, UINT nStateMask) + { + ATLASSERT(::IsWindow(m_hWnd)); + LVITEM lvi = { 0 }; + lvi.state = nState; + lvi.stateMask = nStateMask; + return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMSTATE, nItem, (LPARAM)&lvi); + } + + BOOL SetItemState(int nItem, LPLVITEM pItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMSTATE, nItem, (LPARAM)pItem); + } + +#ifndef _ATL_NO_COM + BOOL GetItemText(int nItem, int nSubItem, BSTR& bstrText) const + { + USES_CONVERSION; + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(bstrText == NULL); + LVITEM lvi = { 0 }; + lvi.iSubItem = nSubItem; + + LPTSTR lpstrText = NULL; + int nRes = 0; + for(int nLen = 256; ; nLen *= 2) + { + ATLTRY(lpstrText = new TCHAR[nLen]); + if(lpstrText == NULL) + break; + lpstrText[0] = NULL; + lvi.cchTextMax = nLen; + lvi.pszText = lpstrText; + nRes = (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi); + if(nRes < nLen - 1) + break; + delete [] lpstrText; + lpstrText = NULL; + } + + if(lpstrText != NULL) + { + if(nRes != 0) + bstrText = ::SysAllocString(T2OLE(lpstrText)); + delete [] lpstrText; + } + + return (bstrText != NULL) ? TRUE : FALSE; + } +#endif // !_ATL_NO_COM + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + int GetItemText(int nItem, int nSubItem, _CSTRING_NS::CString& strText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + LVITEM lvi = { 0 }; + lvi.iSubItem = nSubItem; + + strText.Empty(); + int nRes = 0; + for(int nLen = 256; ; nLen *= 2) + { + lvi.cchTextMax = nLen; + lvi.pszText = strText.GetBufferSetLength(nLen); + if(lvi.pszText == NULL) + { + nRes = 0; + break; + } + nRes = (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi); + if(nRes < nLen - 1) + break; + } + strText.ReleaseBuffer(); + return nRes; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + + int GetItemText(int nItem, int nSubItem, LPTSTR lpszText, int nLen) const + { + ATLASSERT(::IsWindow(m_hWnd)); + LVITEM lvi = { 0 }; + lvi.iSubItem = nSubItem; + lvi.cchTextMax = nLen; + lvi.pszText = lpszText; + return (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi); + } + + BOOL SetItemText(int nItem, int nSubItem, LPCTSTR lpszText) + { + ATLASSERT(::IsWindow(m_hWnd)); + return SetItem(nItem, nSubItem, LVIF_TEXT, lpszText, 0, 0, 0, 0); + } + + DWORD_PTR GetItemData(int nItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + LVITEM lvi = { 0 }; + lvi.iItem = nItem; + lvi.mask = LVIF_PARAM; + BOOL bRet = (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)&lvi); + return (DWORD_PTR)(bRet ? lvi.lParam : NULL); + } + + BOOL SetItemData(int nItem, DWORD_PTR dwData) + { + ATLASSERT(::IsWindow(m_hWnd)); + return SetItem(nItem, 0, LVIF_PARAM, NULL, 0, 0, 0, (LPARAM)dwData); + } + + UINT GetCallbackMask() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, LVM_GETCALLBACKMASK, 0, 0L); + } + + BOOL SetCallbackMask(UINT nMask) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETCALLBACKMASK, nMask, 0L); + } + + BOOL GetItemPosition(int nItem, LPPOINT lpPoint) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMPOSITION, nItem, (LPARAM)lpPoint); + } + + BOOL SetItemPosition(int nItem, POINT pt) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(((GetStyle() & LVS_TYPEMASK) == LVS_ICON) || ((GetStyle() & LVS_TYPEMASK) == LVS_SMALLICON)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMPOSITION32, nItem, (LPARAM)&pt); + } + + BOOL SetItemPosition(int nItem, int x, int y) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(((GetStyle() & LVS_TYPEMASK) == LVS_ICON) || ((GetStyle() & LVS_TYPEMASK) == LVS_SMALLICON)); + POINT pt = { x, y }; + return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMPOSITION32, nItem, (LPARAM)&pt); + } + + int GetStringWidth(LPCTSTR lpsz) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_GETSTRINGWIDTH, 0, (LPARAM)lpsz); + } + + CEdit GetEditControl() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CEdit((HWND)::SendMessage(m_hWnd, LVM_GETEDITCONTROL, 0, 0L)); + } + + BOOL GetColumn(int nCol, LVCOLUMN* pColumn) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETCOLUMN, nCol, (LPARAM)pColumn); + } + + BOOL SetColumn(int nCol, const LVCOLUMN* pColumn) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMN, nCol, (LPARAM)pColumn); + } + + int GetColumnWidth(int nCol) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_GETCOLUMNWIDTH, nCol, 0L); + } + + BOOL SetColumnWidth(int nCol, int cx) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMNWIDTH, nCol, MAKELPARAM(cx, 0)); + } + + BOOL GetViewRect(LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETVIEWRECT, 0, (LPARAM)lpRect); + } + + COLORREF GetTextColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, LVM_GETTEXTCOLOR, 0, 0L); + } + + BOOL SetTextColor(COLORREF cr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETTEXTCOLOR, 0, cr); + } + + COLORREF GetTextBkColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, LVM_GETTEXTBKCOLOR, 0, 0L); + } + + BOOL SetTextBkColor(COLORREF cr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETTEXTBKCOLOR, 0, cr); + } + + int GetTopIndex() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_GETTOPINDEX, 0, 0L); + } + + int GetCountPerPage() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_GETCOUNTPERPAGE, 0, 0L); + } + + BOOL GetOrigin(LPPOINT lpPoint) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETORIGIN, 0, (LPARAM)lpPoint); + } + + UINT GetSelectedCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, LVM_GETSELECTEDCOUNT, 0, 0L); + } + + BOOL GetItemRect(int nItem, LPRECT lpRect, UINT nCode) const + { + ATLASSERT(::IsWindow(m_hWnd)); + lpRect->left = nCode; + return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMRECT, (WPARAM)nItem, (LPARAM)lpRect); + } + +#ifndef _WIN32_WCE + HCURSOR GetHotCursor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HCURSOR)::SendMessage(m_hWnd, LVM_GETHOTCURSOR, 0, 0L); + } + + HCURSOR SetHotCursor(HCURSOR hHotCursor) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HCURSOR)::SendMessage(m_hWnd, LVM_SETHOTCURSOR, 0, (LPARAM)hHotCursor); + } + + int GetHotItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_GETHOTITEM, 0, 0L); + } + + int SetHotItem(int nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_SETHOTITEM, nIndex, 0L); + } +#endif // !_WIN32_WCE + + BOOL GetColumnOrderArray(int nCount, int* lpnArray) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETCOLUMNORDERARRAY, nCount, (LPARAM)lpnArray); + } + + BOOL SetColumnOrderArray(int nCount, int* lpnArray) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMNORDERARRAY, nCount, (LPARAM)lpnArray); + } + + CHeaderCtrl GetHeader() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CHeaderCtrl((HWND)::SendMessage(m_hWnd, LVM_GETHEADER, 0, 0L)); + } + + BOOL GetSubItemRect(int nItem, int nSubItem, int nFlag, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & LVS_TYPEMASK) == LVS_REPORT); + ATLASSERT(lpRect != NULL); + lpRect->top = nSubItem; + lpRect->left = nFlag; + return (BOOL)::SendMessage(m_hWnd, LVM_GETSUBITEMRECT, nItem, (LPARAM)lpRect); + } + + DWORD SetIconSpacing(int cx, int cy) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & LVS_TYPEMASK) == LVS_ICON); + return (DWORD)::SendMessage(m_hWnd, LVM_SETICONSPACING, 0, MAKELPARAM(cx, cy)); + } + + int GetISearchString(LPTSTR lpstr) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_GETISEARCHSTRING, 0, (LPARAM)lpstr); + } + + void GetItemSpacing(SIZE& sizeSpacing, BOOL bSmallIconView = FALSE) const + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dwRet = (DWORD)::SendMessage(m_hWnd, LVM_GETITEMSPACING, bSmallIconView, 0L); + sizeSpacing.cx = GET_X_LPARAM(dwRet); + sizeSpacing.cy = GET_Y_LPARAM(dwRet); + } + +#if (_WIN32_WCE >= 410) + void SetItemSpacing(INT cySpacing) + { + ATLASSERT(::IsWindow(m_hWnd)); + ListView_SetItemSpacing(m_hWnd, cySpacing); + } +#endif // (_WIN32_WCE >= 410) + + // single-selection only + int GetSelectedIndex() const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & LVS_SINGLESEL) != 0); + return (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, (WPARAM)-1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0)); + } + + BOOL GetSelectedItem(LPLVITEM pItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & LVS_SINGLESEL) != 0); + ATLASSERT(pItem != NULL); + pItem->iItem = (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, (WPARAM)-1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0)); + if(pItem->iItem == -1) + return FALSE; + return (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)pItem); + } + + // extended list view styles + DWORD GetExtendedListViewStyle() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0L); + } + + // dwExMask = 0 means all styles + DWORD SetExtendedListViewStyle(DWORD dwExStyle, DWORD dwExMask = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, dwExMask, dwExStyle); + } + + // checkboxes only + BOOL GetCheckState(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetExtendedListViewStyle() & LVS_EX_CHECKBOXES) != 0); + UINT uRet = GetItemState(nIndex, LVIS_STATEIMAGEMASK); + return (uRet >> 12) - 1; + } + + BOOL SetCheckState(int nItem, BOOL bCheck) + { + int nCheck = bCheck ? 2 : 1; // one based index + return SetItemState(nItem, INDEXTOSTATEIMAGEMASK(nCheck), LVIS_STATEIMAGEMASK); + } + + // view type + DWORD GetViewType() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (GetStyle() & LVS_TYPEMASK); + } + + DWORD SetViewType(DWORD dwType) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(dwType == LVS_ICON || dwType == LVS_SMALLICON || dwType == LVS_LIST || dwType == LVS_REPORT); + DWORD dwOldType = GetViewType(); + if(dwType != dwOldType) + ModifyStyle(LVS_TYPEMASK, (dwType & LVS_TYPEMASK)); + return dwOldType; + } + +#if (_WIN32_IE >= 0x0400) +#ifndef _WIN32_WCE + BOOL GetBkImage(LPLVBKIMAGE plvbki) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETBKIMAGE, 0, (LPARAM)plvbki); + } + + BOOL SetBkImage(LPLVBKIMAGE plvbki) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETBKIMAGE, 0, (LPARAM)plvbki); + } +#endif // !_WIN32_WCE + + int GetSelectionMark() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_GETSELECTIONMARK, 0, 0L); + } + + int SetSelectionMark(int nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_SETSELECTIONMARK, 0, nIndex); + } + +#ifndef _WIN32_WCE + BOOL GetWorkAreas(int nWorkAreas, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETWORKAREAS, nWorkAreas, (LPARAM)lpRect); + } + + BOOL SetWorkAreas(int nWorkAreas, LPRECT lpRect) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETWORKAREAS, nWorkAreas, (LPARAM)lpRect); + } + + DWORD GetHoverTime() const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetExtendedListViewStyle() & (LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_TWOCLICKACTIVATE)) != 0); + return (DWORD)::SendMessage(m_hWnd, LVM_GETHOVERTIME, 0, 0L); + } + + DWORD SetHoverTime(DWORD dwHoverTime) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetExtendedListViewStyle() & (LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_TWOCLICKACTIVATE)) != 0); + return (DWORD)::SendMessage(m_hWnd, LVM_SETHOVERTIME, 0, dwHoverTime); + } + + BOOL GetNumberOfWorkAreas(int* pnWorkAreas) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETNUMBEROFWORKAREAS, 0, (LPARAM)pnWorkAreas); + } +#endif // !_WIN32_WCE + + BOOL SetItemCountEx(int nItems, DWORD dwFlags) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(((GetStyle() & LVS_OWNERDATA) != 0) && (((GetStyle() & LVS_TYPEMASK) == LVS_REPORT) || ((GetStyle() & LVS_TYPEMASK) == LVS_LIST))); + return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMCOUNT, nItems, dwFlags); + } + +#ifndef _WIN32_WCE + CToolTipCtrl GetToolTips() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CToolTipCtrl((HWND)::SendMessage(m_hWnd, LVM_GETTOOLTIPS, 0, 0L)); + } + + CToolTipCtrl SetToolTips(HWND hWndTT) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CToolTipCtrl((HWND)::SendMessage(m_hWnd, LVM_SETTOOLTIPS, (WPARAM)hWndTT, 0L)); + } + + BOOL GetUnicodeFormat() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETUNICODEFORMAT, 0, 0L); + } + + BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETUNICODEFORMAT, bUnicode, 0L); + } +#endif // !_WIN32_WCE +#endif // (_WIN32_IE >= 0x0400) + +#if (_WIN32_WINNT >= 0x0501) + int GetSelectedColumn() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_GETSELECTEDCOLUMN, 0, 0L); + } + + void SetSelectedColumn(int nColumn) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LVM_SETSELECTEDCOLUMN, nColumn, 0L); + } + + DWORD GetView() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, LVM_GETVIEW, 0, 0L); + } + + int SetView(DWORD dwView) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_SETVIEW, dwView, 0L); + } + + BOOL IsGroupViewEnabled() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_ISGROUPVIEWENABLED, 0, 0L); + } + + int GetGroupInfo(int nGroupID, PLVGROUP pGroup) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_GETGROUPINFO, nGroupID, (LPARAM)pGroup); + } + + int SetGroupInfo(int nGroupID, PLVGROUP pGroup) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_SETGROUPINFO, nGroupID, (LPARAM)pGroup); + } + + void GetGroupMetrics(PLVGROUPMETRICS pGroupMetrics) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LVM_GETGROUPMETRICS, 0, (LPARAM)pGroupMetrics); + } + + void SetGroupMetrics(PLVGROUPMETRICS pGroupMetrics) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LVM_SETGROUPMETRICS, 0, (LPARAM)pGroupMetrics); + } + + void GetTileViewInfo(PLVTILEVIEWINFO pTileViewInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LVM_GETTILEVIEWINFO, 0, (LPARAM)pTileViewInfo); + } + + BOOL SetTileViewInfo(PLVTILEVIEWINFO pTileViewInfo) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETTILEVIEWINFO, 0, (LPARAM)pTileViewInfo); + } + + void GetTileInfo(PLVTILEINFO pTileInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LVM_GETTILEINFO, 0, (LPARAM)pTileInfo); + } + + BOOL SetTileInfo(PLVTILEINFO pTileInfo) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETTILEINFO, 0, (LPARAM)pTileInfo); + } + + BOOL GetInsertMark(LPLVINSERTMARK pInsertMark) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETINSERTMARK, 0, (LPARAM)pInsertMark); + } + + BOOL SetInsertMark(LPLVINSERTMARK pInsertMark) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETINSERTMARK, 0, (LPARAM)pInsertMark); + } + + int GetInsertMarkRect(LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_GETINSERTMARKRECT, 0, (LPARAM)lpRect); + } + + COLORREF GetInsertMarkColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, LVM_GETINSERTMARKCOLOR, 0, 0L); + } + + COLORREF SetInsertMarkColor(COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, LVM_SETINSERTMARKCOLOR, 0, clr); + } + + COLORREF GetOutlineColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, LVM_GETOUTLINECOLOR, 0, 0L); + } + + COLORREF SetOutlineColor(COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, LVM_SETOUTLINECOLOR, 0, clr); + } +#endif // (_WIN32_WINNT >= 0x0501) + +#if (_WIN32_WINNT >= 0x0600) + int GetGroupCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_GETGROUPCOUNT, 0, 0L); + } + + BOOL GetGroupInfoByIndex(int nIndex, PLVGROUP pGroup) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETGROUPINFOBYINDEX, nIndex, (LPARAM)pGroup); + } + + BOOL GetGroupRect(int nGroupID, int nType, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(lpRect != NULL); + if(lpRect != NULL) + lpRect->top = nType; + return (BOOL)::SendMessage(m_hWnd, LVM_GETGROUPRECT, nGroupID, (LPARAM)lpRect); + } + + UINT GetGroupState(int nGroupID, UINT uMask) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, LVM_GETGROUPSTATE, nGroupID, (LPARAM)uMask); + } + + int GetFocusedGroup() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_GETFOCUSEDGROUP, 0, 0L); + } + + BOOL GetEmptyText(LPWSTR lpstrText, int cchText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETEMPTYTEXT, cchText, (LPARAM)lpstrText); + } + + BOOL GetFooterRect(LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERRECT, 0, (LPARAM)lpRect); + } + + BOOL GetFooterInfo(LPLVFOOTERINFO lpFooterInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERINFO, 0, (LPARAM)lpFooterInfo); + } + + BOOL GetFooterItemRect(int nItem, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERITEMRECT, nItem, (LPARAM)lpRect); + } + + BOOL GetFooterItem(int nItem, LPLVFOOTERITEM lpFooterItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERITEM, nItem, (LPARAM)lpFooterItem); + } + + BOOL GetItemIndexRect(PLVITEMINDEX pItemIndex, int nSubItem, int nType, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pItemIndex != NULL); + ATLASSERT(lpRect != NULL); + if(lpRect != NULL) + { + lpRect->top = nSubItem; + lpRect->left = nType; + } + return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMINDEXRECT, (WPARAM)pItemIndex, (LPARAM)lpRect); + } + + BOOL SetItemIndexState(PLVITEMINDEX pItemIndex, UINT uState, UINT dwMask) + { + ATLASSERT(::IsWindow(m_hWnd)); + LVITEM lvi = { 0 }; + lvi.state = uState; + lvi.stateMask = dwMask; + return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMINDEXSTATE, (WPARAM)pItemIndex, (LPARAM)&lvi); + } + + BOOL GetNextItemIndex(PLVITEMINDEX pItemIndex, WORD wFlags) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_GETNEXTITEMINDEX, (WPARAM)pItemIndex, MAKELPARAM(wFlags, 0)); + } +#endif // (_WIN32_WINNT >= 0x0600) + +// Operations + int InsertColumn(int nCol, const LVCOLUMN* pColumn) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_INSERTCOLUMN, nCol, (LPARAM)pColumn); + } + + int InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT, + int nWidth = -1, int nSubItem = -1, int iImage = -1, int iOrder = -1) + { + LVCOLUMN column = { 0 }; + column.mask = LVCF_TEXT|LVCF_FMT; + column.pszText = (LPTSTR)lpszColumnHeading; + column.fmt = nFormat; + if (nWidth != -1) + { + column.mask |= LVCF_WIDTH; + column.cx = nWidth; + } + if (nSubItem != -1) + { + column.mask |= LVCF_SUBITEM; + column.iSubItem = nSubItem; + } + if (iImage != -1) + { + column.mask |= LVCF_IMAGE; + column.iImage = iImage; + } + if (iOrder != -1) + { + column.mask |= LVCF_ORDER; + column.iOrder = iOrder; + } + return InsertColumn(nCol, &column); + } + + BOOL DeleteColumn(int nCol) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_DELETECOLUMN, nCol, 0L); + } + + int InsertItem(UINT nMask, int nItem, LPCTSTR lpszItem, UINT nState, UINT nStateMask, int nImage, LPARAM lParam) + { + ATLASSERT(::IsWindow(m_hWnd)); + LVITEM item = { 0 }; + item.mask = nMask; + item.iItem = nItem; + item.iSubItem = 0; + item.pszText = (LPTSTR)lpszItem; + item.state = nState; + item.stateMask = nStateMask; + item.iImage = nImage; + item.lParam = lParam; + return InsertItem(&item); + } + + int InsertItem(const LVITEM* pItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_INSERTITEM, 0, (LPARAM)pItem); + } + + int InsertItem(int nItem, LPCTSTR lpszItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return InsertItem(LVIF_TEXT, nItem, lpszItem, 0, 0, 0, 0); + } + + int InsertItem(int nItem, LPCTSTR lpszItem, int nImage) + { + ATLASSERT(::IsWindow(m_hWnd)); + return InsertItem(LVIF_TEXT|LVIF_IMAGE, nItem, lpszItem, 0, 0, nImage, 0); + } + + int GetNextItem(int nItem, int nFlags) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, nItem, MAKELPARAM(nFlags, 0)); + } + + BOOL DeleteItem(int nItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_DELETEITEM, nItem, 0L); + } + + BOOL DeleteAllItems() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_DELETEALLITEMS, 0, 0L); + } + + int FindItem(LVFINDINFO* pFindInfo, int nStart) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_FINDITEM, nStart, (LPARAM)pFindInfo); + } + + int HitTest(LVHITTESTINFO* pHitTestInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_HITTEST, 0, (LPARAM)pHitTestInfo); + } + + int HitTest(POINT pt, UINT* pFlags) const + { + ATLASSERT(::IsWindow(m_hWnd)); + LVHITTESTINFO hti = { 0 }; + hti.pt = pt; + int nRes = (int)::SendMessage(m_hWnd, LVM_HITTEST, 0, (LPARAM)&hti); + if (pFlags != NULL) + *pFlags = hti.flags; + return nRes; + } + + BOOL EnsureVisible(int nItem, BOOL bPartialOK) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_ENSUREVISIBLE, nItem, MAKELPARAM(bPartialOK, 0)); + } + + BOOL Scroll(SIZE size) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SCROLL, size.cx, size.cy); + } + + BOOL RedrawItems(int nFirst, int nLast) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_REDRAWITEMS, nFirst, nLast); + } + + BOOL Arrange(UINT nCode) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_ARRANGE, nCode, 0L); + } + + CEdit EditLabel(int nItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CEdit((HWND)::SendMessage(m_hWnd, LVM_EDITLABEL, nItem, 0L)); + } + + BOOL Update(int nItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_UPDATE, nItem, 0L); + } + + BOOL SortItems(PFNLVCOMPARE pfnCompare, LPARAM lParamSort) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SORTITEMS, (WPARAM)lParamSort, (LPARAM)pfnCompare); + } + + CImageList RemoveImageList(int nImageList) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_SETIMAGELIST, (WPARAM)nImageList, NULL)); + } + + CImageList CreateDragImage(int nItem, LPPOINT lpPoint) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_CREATEDRAGIMAGE, nItem, (LPARAM)lpPoint)); + } + + DWORD ApproximateViewRect(int cx = -1, int cy = -1, int nCount = -1) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, LVM_APPROXIMATEVIEWRECT, nCount, MAKELPARAM(cx, cy)); + } + + int SubItemHitTest(LPLVHITTESTINFO lpInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_SUBITEMHITTEST, 0, (LPARAM)lpInfo); + } + + int AddColumn(LPCTSTR strItem, int nItem, int nSubItem = -1, + int nMask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM, + int nFmt = LVCFMT_LEFT) + { + const int cxOffset = 15; + ATLASSERT(::IsWindow(m_hWnd)); + LVCOLUMN lvc = { 0 }; + lvc.mask = nMask; + lvc.fmt = nFmt; + lvc.pszText = (LPTSTR)strItem; + lvc.cx = GetStringWidth(lvc.pszText) + cxOffset; + if(nMask & LVCF_SUBITEM) + lvc.iSubItem = (nSubItem != -1) ? nSubItem : nItem; + return InsertColumn(nItem, &lvc); + } + + int AddItem(int nItem, int nSubItem, LPCTSTR strItem, int nImageIndex = -1) + { + ATLASSERT(::IsWindow(m_hWnd)); + LVITEM lvItem = { 0 }; + lvItem.mask = LVIF_TEXT; + lvItem.iItem = nItem; + lvItem.iSubItem = nSubItem; + lvItem.pszText = (LPTSTR)strItem; + if(nImageIndex != -1) + { + lvItem.mask |= LVIF_IMAGE; + lvItem.iImage = nImageIndex; + } + if(nSubItem == 0) + return InsertItem(&lvItem); + return SetItem(&lvItem) ? nItem : -1; + } + +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + BOOL SortItemsEx(PFNLVCOMPARE pfnCompare, LPARAM lParamSort) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SORTITEMSEX, (WPARAM)lParamSort, (LPARAM)pfnCompare); + } +#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + +#if (_WIN32_WINNT >= 0x0501) + int InsertGroup(int nItem, PLVGROUP pGroup) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_INSERTGROUP, nItem, (LPARAM)pGroup); + } + + int AddGroup(PLVGROUP pGroup) + { + return InsertGroup(-1, pGroup); + } + + int RemoveGroup(int nGroupID) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_REMOVEGROUP, nGroupID, 0L); + } + + void MoveGroup(int nGroupID, int nItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LVM_MOVEGROUP, nGroupID, nItem); + } + + void MoveItemToGroup(int nItem, int nGroupID) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LVM_MOVEITEMTOGROUP, nItem, nGroupID); + } + + int EnableGroupView(BOOL bEnable) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_ENABLEGROUPVIEW, bEnable, 0L); + } + + int SortGroups(PFNLVGROUPCOMPARE pCompareFunc, LPVOID lpVoid = NULL) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_SORTGROUPS, (WPARAM)pCompareFunc, (LPARAM)lpVoid); + } + + void InsertGroupSorted(PLVINSERTGROUPSORTED pInsertGroupSorted) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LVM_INSERTGROUPSORTED, (WPARAM)pInsertGroupSorted, 0L); + } + + void RemoveAllGroups() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LVM_REMOVEALLGROUPS, 0, 0L); + } + + BOOL HasGroup(int nGroupID) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_HASGROUP, nGroupID, 0L); + } + + BOOL InsertMarkHitTest(LPPOINT lpPoint, LPLVINSERTMARK pInsertMark) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_INSERTMARKHITTEST, (WPARAM)lpPoint, (LPARAM)pInsertMark); + } + + BOOL SetInfoTip(PLVSETINFOTIP pSetInfoTip) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LVM_SETINFOTIP, 0, (LPARAM)pSetInfoTip); + } + + void CancelEditLabel() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, LVM_CANCELEDITLABEL, 0, 0L); + } + + UINT MapIndexToID(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, LVM_MAPINDEXTOID, nIndex, 0L); + } + + int MapIDToIndex(UINT uID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_MAPIDTOINDEX, uID, 0L); + } +#endif // (_WIN32_WINNT >= 0x0501) + +#if (_WIN32_WINNT >= 0x0600) + int HitTestEx(LPLVHITTESTINFO lpHitTestInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_HITTEST, (WPARAM)-1, (LPARAM)lpHitTestInfo); + } + + int HitTestEx(POINT pt, UINT* pFlags) const + { + ATLASSERT(::IsWindow(m_hWnd)); + LVHITTESTINFO hti = { 0 }; + hti.pt = pt; + int nRes = (int)::SendMessage(m_hWnd, LVM_HITTEST, (WPARAM)-1, (LPARAM)&hti); + if (pFlags != NULL) + *pFlags = hti.flags; + return nRes; + } + + int SubItemHitTestEx(LPLVHITTESTINFO lpHitTestInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LVM_SUBITEMHITTEST, (WPARAM)-1, (LPARAM)lpHitTestInfo); + } +#endif // (_WIN32_WINNT >= 0x0600) + + // single-selection only + BOOL SelectItem(int nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & LVS_SINGLESEL) != 0); + + BOOL bRet = SetItemState(nIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); + if(bRet) + bRet = EnsureVisible(nIndex, FALSE); + return bRet; + } +}; + +typedef CListViewCtrlT CListViewCtrl; + + +/////////////////////////////////////////////////////////////////////////////// +// CTreeViewCtrl + +template +class CTreeViewCtrlT : public TBase +{ +public: +// Constructors + CTreeViewCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CTreeViewCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return WC_TREEVIEW; + } + + UINT GetCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, TVM_GETCOUNT, 0, 0L); + } + + UINT GetIndent() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, TVM_GETINDENT, 0, 0L); + } + + void SetIndent(UINT nIndent) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TVM_SETINDENT, nIndent, 0L); + } + + CImageList GetImageList(int nImageListType = TVSIL_NORMAL) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_GETIMAGELIST, (WPARAM)nImageListType, 0L)); + } + + CImageList SetImageList(HIMAGELIST hImageList, int nImageListType = TVSIL_NORMAL) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_SETIMAGELIST, (WPARAM)nImageListType, (LPARAM)hImageList)); + } + + BOOL GetItem(LPTVITEM pItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)pItem); + } + + BOOL SetItem(LPTVITEM pItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)pItem); + } + + BOOL SetItem(HTREEITEM hItem, UINT nMask, LPCTSTR lpszItem, int nImage, + int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam) + { + ATLASSERT(::IsWindow(m_hWnd)); + TVITEM item = { 0 }; + item.hItem = hItem; + item.mask = nMask; + item.pszText = (LPTSTR) lpszItem; + item.iImage = nImage; + item.iSelectedImage = nSelectedImage; + item.state = nState; + item.stateMask = nStateMask; + item.lParam = lParam; + return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)&item); + } + + BOOL GetItemText(HTREEITEM hItem, LPTSTR lpstrText, int nLen) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(lpstrText != NULL); + + TVITEM item = { 0 }; + item.hItem = hItem; + item.mask = TVIF_TEXT; + item.pszText = lpstrText; + item.cchTextMax = nLen; + + return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); + } + +#ifndef _ATL_NO_COM + BOOL GetItemText(HTREEITEM hItem, BSTR& bstrText) const + { + USES_CONVERSION; + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(bstrText == NULL); + TVITEM item = { 0 }; + item.hItem = hItem; + item.mask = TVIF_TEXT; + + LPTSTR lpstrText = NULL; + BOOL bRet = FALSE; + for(int nLen = 256; ; nLen *= 2) + { + ATLTRY(lpstrText = new TCHAR[nLen]); + if(lpstrText == NULL) + break; + lpstrText[0] = NULL; + item.pszText = lpstrText; + item.cchTextMax = nLen; + bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); + if(!bRet || (lstrlen(item.pszText) < nLen - 1)) + break; + delete [] lpstrText; + lpstrText = NULL; + } + + if(lpstrText != NULL) + { + if(bRet) + bstrText = ::SysAllocString(T2OLE(lpstrText)); + delete [] lpstrText; + } + + return (bstrText != NULL) ? TRUE : FALSE; + } +#endif // !_ATL_NO_COM + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + BOOL GetItemText(HTREEITEM hItem, _CSTRING_NS::CString& strText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + TVITEM item = { 0 }; + item.hItem = hItem; + item.mask = TVIF_TEXT; + + strText.Empty(); + BOOL bRet = FALSE; + for(int nLen = 256; ; nLen *= 2) + { + item.pszText = strText.GetBufferSetLength(nLen); + if(item.pszText == NULL) + { + bRet = FALSE; + break; + } + item.cchTextMax = nLen; + bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); + if(!bRet || (lstrlen(item.pszText) < nLen - 1)) + break; + } + strText.ReleaseBuffer(); + return bRet; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + + BOOL SetItemText(HTREEITEM hItem, LPCTSTR lpszItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return SetItem(hItem, TVIF_TEXT, lpszItem, 0, 0, 0, 0, NULL); + } + + BOOL GetItemImage(HTREEITEM hItem, int& nImage, int& nSelectedImage) const + { + ATLASSERT(::IsWindow(m_hWnd)); + TVITEM item = { 0 }; + item.hItem = hItem; + item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE; + BOOL bRes = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); + if (bRes) + { + nImage = item.iImage; + nSelectedImage = item.iSelectedImage; + } + return bRes; + } + + BOOL SetItemImage(HTREEITEM hItem, int nImage, int nSelectedImage) + { + ATLASSERT(::IsWindow(m_hWnd)); + return SetItem(hItem, TVIF_IMAGE|TVIF_SELECTEDIMAGE, NULL, nImage, nSelectedImage, 0, 0, NULL); + } + + UINT GetItemState(HTREEITEM hItem, UINT nStateMask) const + { + ATLASSERT(::IsWindow(m_hWnd)); +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + return (((UINT)::SendMessage(m_hWnd, TVM_GETITEMSTATE, (WPARAM)hItem, (LPARAM)nStateMask)) & nStateMask); +#else // !((_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)) + TVITEM item = { 0 }; + item.hItem = hItem; + item.mask = TVIF_STATE; + item.state = 0; + item.stateMask = nStateMask; + ::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); + return (item.state & nStateMask); +#endif // !((_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)) + } + + BOOL SetItemState(HTREEITEM hItem, UINT nState, UINT nStateMask) + { + ATLASSERT(::IsWindow(m_hWnd)); + return SetItem(hItem, TVIF_STATE, NULL, 0, 0, nState, nStateMask, NULL); + } + + DWORD_PTR GetItemData(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + TVITEM item = { 0 }; + item.hItem = hItem; + item.mask = TVIF_PARAM; + BOOL bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); + return (DWORD_PTR)(bRet ? item.lParam : NULL); + } + + BOOL SetItemData(HTREEITEM hItem, DWORD_PTR dwData) + { + ATLASSERT(::IsWindow(m_hWnd)); + return SetItem(hItem, TVIF_PARAM, NULL, 0, 0, 0, 0, (LPARAM)dwData); + } + + CEdit GetEditControl() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CEdit((HWND)::SendMessage(m_hWnd, TVM_GETEDITCONTROL, 0, 0L)); + } + + UINT GetVisibleCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, TVM_GETVISIBLECOUNT, 0, 0L); + } + + BOOL GetItemRect(HTREEITEM hItem, LPRECT lpRect, BOOL bTextOnly) const + { + ATLASSERT(::IsWindow(m_hWnd)); + *(HTREEITEM*)lpRect = hItem; + return (BOOL)::SendMessage(m_hWnd, TVM_GETITEMRECT, (WPARAM)bTextOnly, (LPARAM)lpRect); + } + + BOOL ItemHasChildren(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + TVITEM item = { 0 }; + item.hItem = hItem; + item.mask = TVIF_CHILDREN; + ::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); + return item.cChildren; + } + +#ifndef _WIN32_WCE + CToolTipCtrl GetToolTips() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TVM_GETTOOLTIPS, 0, 0L)); + } + + CToolTipCtrl SetToolTips(HWND hWndTT) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TVM_SETTOOLTIPS, (WPARAM)hWndTT, 0L)); + } +#endif // !_WIN32_WCE + + int GetISearchString(LPTSTR lpstr) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TVM_GETISEARCHSTRING, 0, (LPARAM)lpstr); + } + + // checkboxes only + BOOL GetCheckState(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & TVS_CHECKBOXES) != 0); + UINT uRet = GetItemState(hItem, TVIS_STATEIMAGEMASK); + return (uRet >> 12) - 1; + } + + BOOL SetCheckState(HTREEITEM hItem, BOOL bCheck) + { + int nCheck = bCheck ? 2 : 1; // one based index + return SetItemState(hItem, INDEXTOSTATEIMAGEMASK(nCheck), TVIS_STATEIMAGEMASK); + } + +#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + COLORREF GetBkColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, TVM_GETBKCOLOR, 0, 0L); + } + + COLORREF SetBkColor(COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, TVM_SETBKCOLOR, 0, (LPARAM)clr); + } + + COLORREF GetInsertMarkColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, TVM_GETINSERTMARKCOLOR, 0, 0L); + } + + COLORREF SetInsertMarkColor(COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, TVM_SETINSERTMARKCOLOR, 0, (LPARAM)clr); + } + + int GetItemHeight() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TVM_GETITEMHEIGHT, 0, 0L); + } + + int SetItemHeight(int cyHeight) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TVM_SETITEMHEIGHT, cyHeight, 0L); + } + + int GetScrollTime() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TVM_GETSCROLLTIME, 0, 0L); + } + + int SetScrollTime(int nScrollTime) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TVM_SETSCROLLTIME, nScrollTime, 0L); + } + + COLORREF GetTextColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, TVM_GETTEXTCOLOR, 0, 0L); + } + + COLORREF SetTextColor(COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, TVM_SETTEXTCOLOR, 0, (LPARAM)clr); + } + + BOOL GetUnicodeFormat() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_GETUNICODEFORMAT, 0, 0L); + } + + BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_SETUNICODEFORMAT, bUnicode, 0L); + } +#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + COLORREF GetLineColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, TVM_GETLINECOLOR, 0, 0L); + } + + COLORREF SetLineColor(COLORREF clrNew /*= CLR_DEFAULT*/) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, TVM_SETLINECOLOR, 0, (LPARAM)clrNew); + } +#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + +#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + BOOL GetItem(LPTVITEMEX pItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)pItem); + } + + BOOL SetItem(LPTVITEMEX pItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)pItem); + } +#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + + DWORD GetExtendedStyle() const + { +#ifndef TVM_GETEXTENDEDSTYLE + const UINT TVM_GETEXTENDEDSTYLE = (TV_FIRST + 45); +#endif + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, TVM_GETEXTENDEDSTYLE, 0, 0L); + } + + DWORD SetExtendedStyle(DWORD dwStyle, DWORD dwMask) + { +#ifndef TVM_SETEXTENDEDSTYLE + const UINT TVM_SETEXTENDEDSTYLE = (TV_FIRST + 44); +#endif + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, TVM_SETEXTENDEDSTYLE, dwMask, dwStyle); + } + +#if (_WIN32_WINNT >= 0x0600) + BOOL SetAutoScrollInfo(UINT uPixPerSec, UINT uUpdateTime) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_SETAUTOSCROLLINFO, (WPARAM)uPixPerSec, (LPARAM)uUpdateTime); + } + + DWORD GetSelectedCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, TVM_GETSELECTEDCOUNT, 0, 0L); + } + + BOOL GetItemPartRect(HTREEITEM hItem, TVITEMPART partID, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + TVGETITEMPARTRECTINFO gipri = { hItem, lpRect, partID }; + return (BOOL)::SendMessage(m_hWnd, TVM_GETITEMPARTRECT, 0, (LPARAM)&gipri); + } +#endif // (_WIN32_WINNT >= 0x0600) + +// Operations + HTREEITEM InsertItem(LPTVINSERTSTRUCT lpInsertStruct) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)lpInsertStruct); + } + + HTREEITEM InsertItem(LPCTSTR lpszItem, int nImage, + int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter) + { + ATLASSERT(::IsWindow(m_hWnd)); + return InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE, lpszItem, nImage, nSelectedImage, 0, 0, 0, hParent, hInsertAfter); + } + + HTREEITEM InsertItem(LPCTSTR lpszItem, HTREEITEM hParent, HTREEITEM hInsertAfter) + { + ATLASSERT(::IsWindow(m_hWnd)); + return InsertItem(TVIF_TEXT, lpszItem, 0, 0, 0, 0, 0, hParent, hInsertAfter); + } + + HTREEITEM InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage, + int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam, + HTREEITEM hParent, HTREEITEM hInsertAfter) + { + ATLASSERT(::IsWindow(m_hWnd)); + TVINSERTSTRUCT tvis = { 0 }; + tvis.hParent = hParent; + tvis.hInsertAfter = hInsertAfter; + tvis.item.mask = nMask; + tvis.item.pszText = (LPTSTR) lpszItem; + tvis.item.iImage = nImage; + tvis.item.iSelectedImage = nSelectedImage; + tvis.item.state = nState; + tvis.item.stateMask = nStateMask; + tvis.item.lParam = lParam; + return (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)&tvis); + } + + BOOL DeleteItem(HTREEITEM hItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_DELETEITEM, 0, (LPARAM)hItem); + } + + BOOL DeleteAllItems() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT); + } + + BOOL Expand(HTREEITEM hItem, UINT nCode = TVE_EXPAND) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_EXPAND, nCode, (LPARAM)hItem); + } + + HTREEITEM GetNextItem(HTREEITEM hItem, UINT nCode) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, nCode, (LPARAM)hItem); + } + + HTREEITEM GetChildItem(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem); + } + + HTREEITEM GetNextSiblingItem(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem); + } + + HTREEITEM GetPrevSiblingItem(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)hItem); + } + + HTREEITEM GetParentItem(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem); + } + + HTREEITEM GetFirstVisibleItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, 0L); + } + + HTREEITEM GetNextVisibleItem(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)hItem); + } + + HTREEITEM GetPrevVisibleItem(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItem); + } + + HTREEITEM GetSelectedItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CARET, 0L); + } + + HTREEITEM GetDropHilightItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0L); + } + + HTREEITEM GetRootItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0L); + } + +#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) + HTREEITEM GetLastVisibleItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0L); + } +#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) + +#if (_WIN32_IE >= 0x0600) + HTREEITEM GetNextSelectedItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTSELECTED, 0L); + } +#endif // (_WIN32_IE >= 0x0600) + + BOOL Select(HTREEITEM hItem, UINT nCode) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, nCode, (LPARAM)hItem); + } + + BOOL SelectItem(HTREEITEM hItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hItem); + } + + BOOL SelectDropTarget(HTREEITEM hItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_DROPHILITE, (LPARAM)hItem); + } + + BOOL SelectSetFirstVisible(HTREEITEM hItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_FIRSTVISIBLE, (LPARAM)hItem); + } + + CEdit EditLabel(HTREEITEM hItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CEdit((HWND)::SendMessage(m_hWnd, TVM_EDITLABEL, 0, (LPARAM)hItem)); + } + + BOOL EndEditLabelNow(BOOL bCancel) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_ENDEDITLABELNOW, bCancel, 0L); + } + + HTREEITEM HitTest(TVHITTESTINFO* pHitTestInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)pHitTestInfo); + } + + HTREEITEM HitTest(POINT pt, UINT* pFlags) const + { + ATLASSERT(::IsWindow(m_hWnd)); + TVHITTESTINFO hti = { 0 }; + hti.pt = pt; + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)&hti); + if (pFlags != NULL) + *pFlags = hti.flags; + return hTreeItem; + } + + BOOL SortChildren(HTREEITEM hItem, BOOL bRecurse = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_SORTCHILDREN, (WPARAM)bRecurse, (LPARAM)hItem); + } + + BOOL EnsureVisible(HTREEITEM hItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_ENSUREVISIBLE, 0, (LPARAM)hItem); + } + + BOOL SortChildrenCB(LPTVSORTCB pSort, BOOL bRecurse = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_SORTCHILDRENCB, (WPARAM)bRecurse, (LPARAM)pSort); + } + + CImageList RemoveImageList(int nImageList) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_SETIMAGELIST, (WPARAM)nImageList, NULL)); + } + + CImageList CreateDragImage(HTREEITEM hItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_CREATEDRAGIMAGE, 0, (LPARAM)hItem)); + } + +#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + BOOL SetInsertMark(HTREEITEM hTreeItem, BOOL bAfter) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_SETINSERTMARK, bAfter, (LPARAM)hTreeItem); + } + + BOOL RemoveInsertMark() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TVM_SETINSERTMARK, 0, 0L); + } +#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + +#if (_WIN32_WINNT >= 0x0501) + HTREEITEM MapAccIDToHTREEITEM(UINT uID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HTREEITEM)::SendMessage(m_hWnd, TVM_MAPACCIDTOHTREEITEM, uID, 0L); + } + + UINT MapHTREEITEMToAccID(HTREEITEM hTreeItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, TVM_MAPHTREEITEMTOACCID, (WPARAM)hTreeItem, 0L); + } +#endif // (_WIN32_WINNT >= 0x0501) + +#if (_WIN32_WINNT >= 0x0600) + void ShowInfoTip(HTREEITEM hItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TVM_SHOWINFOTIP, 0, (LPARAM)hItem); + } +#endif // (_WIN32_WINNT >= 0x0600) +}; + +typedef CTreeViewCtrlT CTreeViewCtrl; + + +/////////////////////////////////////////////////////////////////////////////// +// CTreeViewCtrlEx + +// forward declaration +template class CTreeViewCtrlExT; + +// Note: TBase here is for CTreeViewCtrlExT, and not for CTreeItemT itself +template +class CTreeItemT +{ +public: + HTREEITEM m_hTreeItem; + CTreeViewCtrlExT* m_pTreeView; + +// Construction + CTreeItemT(HTREEITEM hTreeItem = NULL, CTreeViewCtrlExT* pTreeView = NULL) : m_hTreeItem(hTreeItem), m_pTreeView(pTreeView) + { } + + CTreeItemT(const CTreeItemT& posSrc) + { + *this = posSrc; + } + + operator HTREEITEM() { return m_hTreeItem; } + + CTreeItemT& operator =(const CTreeItemT& itemSrc) + { + m_hTreeItem = itemSrc.m_hTreeItem; + m_pTreeView = itemSrc.m_pTreeView; + return *this; + } + +// Attributes + CTreeViewCtrlExT* GetTreeView() const { return m_pTreeView; } + + BOOL operator !() const { return m_hTreeItem == NULL; } + + BOOL IsNull() const { return m_hTreeItem == NULL; } + + BOOL GetRect(LPRECT lpRect, BOOL bTextOnly) const; + BOOL GetText(LPTSTR lpstrText, int nLen) const; +#ifndef _ATL_NO_COM + BOOL GetText(BSTR& bstrText) const; +#endif // !_ATL_NO_COM +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + BOOL GetText(_CSTRING_NS::CString& strText) const; +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + BOOL SetText(LPCTSTR lpszItem); + BOOL GetImage(int& nImage, int& nSelectedImage) const; + BOOL SetImage(int nImage, int nSelectedImage); + UINT GetState(UINT nStateMask) const; + BOOL SetState(UINT nState, UINT nStateMask); + DWORD_PTR GetData() const; + BOOL SetData(DWORD_PTR dwData); + BOOL SetItem(UINT nMask, LPCTSTR lpszItem, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam); + +// Operations + CTreeItemT InsertAfter(LPCTSTR lpstrItem, HTREEITEM hItemAfter, int nImageIndex) + { + return _Insert(lpstrItem, nImageIndex, hItemAfter); + } + + CTreeItemT AddHead(LPCTSTR lpstrItem, int nImageIndex) + { + return _Insert(lpstrItem, nImageIndex, TVI_FIRST); + } + + CTreeItemT AddTail(LPCTSTR lpstrItem, int nImageIndex) + { + return _Insert(lpstrItem, nImageIndex, TVI_LAST); + } + + CTreeItemT GetChild() const; + CTreeItemT GetNext(UINT nCode) const; + CTreeItemT GetNextSibling() const; + CTreeItemT GetPrevSibling() const; + CTreeItemT GetParent() const; + CTreeItemT GetFirstVisible() const; + CTreeItemT GetNextVisible() const; + CTreeItemT GetPrevVisible() const; + CTreeItemT GetSelected() const; + CTreeItemT GetDropHilight() const; + CTreeItemT GetRoot() const; +#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) + CTreeItemT GetLastVisible() const; +#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) +#if (_WIN32_IE >= 0x0600) + CTreeItemT GetNextSelected() const; +#endif // (_WIN32_IE >= 0x0600) + BOOL HasChildren() const; + BOOL Delete(); + BOOL Expand(UINT nCode = TVE_EXPAND); + BOOL Select(UINT nCode); + BOOL Select(); + BOOL SelectDropTarget(); + BOOL SelectSetFirstVisible(); + HWND EditLabel(); + HIMAGELIST CreateDragImage(); + BOOL SortChildren(BOOL bRecurse = FALSE); + BOOL EnsureVisible(); + CTreeItemT _Insert(LPCTSTR lpstrItem, int nImageIndex, HTREEITEM hItemAfter); + int GetImageIndex() const; +#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + BOOL SetInsertMark(BOOL bAfter); +#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) +#if (_WIN32_WINNT >= 0x0501) + UINT MapHTREEITEMToAccID() const; +#endif // (_WIN32_WINNT >= 0x0501) +#if (_WIN32_WINNT >= 0x0600) + void ShowInfoTip(); + BOOL GetPartRect(TVITEMPART partID, LPRECT lpRect) const; +#endif // (_WIN32_WINNT >= 0x0600) +}; + +typedef CTreeItemT CTreeItem; + + +template +class CTreeViewCtrlExT : public CTreeViewCtrlT< TBase > +{ +public: +// Constructors + CTreeViewCtrlExT(HWND hWnd = NULL) : CTreeViewCtrlT< TBase >(hWnd) + { } + + CTreeViewCtrlExT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + +// Operations (overides that return CTreeItem) + CTreeItemT InsertItem(LPTVINSERTSTRUCT lpInsertStruct) + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)lpInsertStruct); + return CTreeItemT(hTreeItem, this); + } + + CTreeItemT InsertItem(LPCTSTR lpszItem, int nImage, + int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter) + { + ATLASSERT(::IsWindow(m_hWnd)); + return InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE, lpszItem, nImage, nSelectedImage, 0, 0, 0, hParent, hInsertAfter); + } + + CTreeItemT InsertItem(LPCTSTR lpszItem, HTREEITEM hParent, HTREEITEM hInsertAfter) + { + ATLASSERT(::IsWindow(m_hWnd)); + return InsertItem(TVIF_TEXT, lpszItem, 0, 0, 0, 0, 0, hParent, hInsertAfter); + } + + CTreeItemT GetNextItem(HTREEITEM hItem, UINT nCode) const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, nCode, (LPARAM)hItem); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } + + CTreeItemT GetChildItem(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } + + CTreeItemT GetNextSiblingItem(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } + + CTreeItemT GetPrevSiblingItem(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)hItem); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } + + CTreeItemT GetParentItem(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } + + CTreeItemT GetFirstVisibleItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, 0L); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } + + CTreeItemT GetNextVisibleItem(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)hItem); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } + + CTreeItemT GetPrevVisibleItem(HTREEITEM hItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItem); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } + + CTreeItemT GetSelectedItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CARET, 0L); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } + + CTreeItemT GetDropHilightItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0L); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } + + CTreeItemT GetRootItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0L); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } + +#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) + CTreeItemT GetLastVisibleItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0L); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } +#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) + +#if (_WIN32_IE >= 0x0600) + CTreeItemT GetNextSelectedItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTSELECTED, 0L); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } +#endif // (_WIN32_IE >= 0x0600) + + CTreeItemT HitTest(TVHITTESTINFO* pHitTestInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)pHitTestInfo); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } + + CTreeItemT InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage, + int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam, + HTREEITEM hParent, HTREEITEM hInsertAfter) + { + ATLASSERT(::IsWindow(m_hWnd)); + TVINSERTSTRUCT tvis = { 0 }; + tvis.hParent = hParent; + tvis.hInsertAfter = hInsertAfter; + tvis.item.mask = nMask; + tvis.item.pszText = (LPTSTR) lpszItem; + tvis.item.iImage = nImage; + tvis.item.iSelectedImage = nSelectedImage; + tvis.item.state = nState; + tvis.item.stateMask = nStateMask; + tvis.item.lParam = lParam; + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)&tvis); + return CTreeItemT(hTreeItem, this); + } + + CTreeItemT HitTest(POINT pt, UINT* pFlags) const + { + ATLASSERT(::IsWindow(m_hWnd)); + TVHITTESTINFO hti = { 0 }; + hti.pt = pt; + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)&hti); + if (pFlags != NULL) + *pFlags = hti.flags; + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } + +#if (_WIN32_WINNT >= 0x0501) + CTreeItemT MapAccIDToHTREEITEM(UINT uID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_MAPACCIDTOHTREEITEM, uID, 0L); + return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); + } +#endif // (_WIN32_WINNT >= 0x0501) +}; + +typedef CTreeViewCtrlExT CTreeViewCtrlEx; + + +// CTreeItem inline methods +template +inline BOOL CTreeItemT::GetRect(LPRECT lpRect, BOOL bTextOnly) const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetItemRect(m_hTreeItem,lpRect,bTextOnly); +} + +template +inline CTreeItemT CTreeItemT::GetNext(UINT nCode) const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetNextItem(m_hTreeItem,nCode); +} + +template +inline CTreeItemT CTreeItemT::GetChild() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetChildItem(m_hTreeItem); +} + +template +inline CTreeItemT CTreeItemT::GetNextSibling() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetNextSiblingItem(m_hTreeItem); +} + +template +inline CTreeItemT CTreeItemT::GetPrevSibling() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetPrevSiblingItem(m_hTreeItem); +} + +template +inline CTreeItemT CTreeItemT::GetParent() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetParentItem(m_hTreeItem); +} + +template +inline CTreeItemT CTreeItemT::GetFirstVisible() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetFirstVisibleItem(); +} + +template +inline CTreeItemT CTreeItemT::GetNextVisible() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetNextVisibleItem(m_hTreeItem); +} + +template +inline CTreeItemT CTreeItemT::GetPrevVisible() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetPrevVisibleItem(m_hTreeItem); +} + +template +inline CTreeItemT CTreeItemT::GetSelected() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetSelectedItem(); +} + +template +inline CTreeItemT CTreeItemT::GetDropHilight() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetDropHilightItem(); +} + +template +inline CTreeItemT CTreeItemT::GetRoot() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetRootItem(); +} + +#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) +template +inline CTreeItemT CTreeItemT::GetLastVisible() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetLastVisibleItem(); +} +#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) + +#if (_WIN32_IE >= 0x0600) +template +inline CTreeItemT CTreeItemT::GetNextSelected() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetNextSelectedItem(); +} +#endif // (_WIN32_IE >= 0x0600) + +template +inline BOOL CTreeItemT::GetText(LPTSTR lpstrText, int nLen) const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetItemText(m_hTreeItem, lpstrText, nLen); +} + +#ifndef _ATL_NO_COM +#ifdef _OLEAUTO_H_ +template +inline BOOL CTreeItemT::GetText(BSTR& bstrText) const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetItemText(m_hTreeItem, bstrText); +} +#endif // _OLEAUTO_H_ +#endif // !_ATL_NO_COM + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) +template +inline BOOL CTreeItemT::GetText(_CSTRING_NS::CString& strText) const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetItemText(m_hTreeItem, strText); +} +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + +template +inline BOOL CTreeItemT::GetImage(int& nImage, int& nSelectedImage) const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetItemImage(m_hTreeItem,nImage,nSelectedImage); +} + +template +inline UINT CTreeItemT::GetState(UINT nStateMask) const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetItemState(m_hTreeItem,nStateMask); +} + +template +inline DWORD_PTR CTreeItemT::GetData() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetItemData(m_hTreeItem); +} + +template +inline BOOL CTreeItemT::SetItem(UINT nMask, LPCTSTR lpszItem, int nImage, + int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam) +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->SetItem(m_hTreeItem, nMask, lpszItem, nImage, nSelectedImage, nState, nStateMask, lParam); +} + +template +inline BOOL CTreeItemT::SetText(LPCTSTR lpszItem) +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->SetItemText(m_hTreeItem,lpszItem); +} + +template +inline BOOL CTreeItemT::SetImage(int nImage, int nSelectedImage) +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->SetItemImage(m_hTreeItem,nImage,nSelectedImage); +} + +template +inline BOOL CTreeItemT::SetState(UINT nState, UINT nStateMask) +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->SetItemState(m_hTreeItem,nState,nStateMask); +} + +template +inline BOOL CTreeItemT::SetData(DWORD_PTR dwData) +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->SetItemData(m_hTreeItem,dwData); +} + +template +inline BOOL CTreeItemT::HasChildren() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->ItemHasChildren(m_hTreeItem); +} + +template +inline BOOL CTreeItemT::Delete() +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->DeleteItem(m_hTreeItem); +} + +template +inline BOOL CTreeItemT::Expand(UINT nCode /*= TVE_EXPAND*/) +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->Expand(m_hTreeItem,nCode); +} + +template +inline BOOL CTreeItemT::Select(UINT nCode) +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->Select(m_hTreeItem,nCode); +} + +template +inline BOOL CTreeItemT::Select() +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->SelectItem(m_hTreeItem); +} + +template +inline BOOL CTreeItemT::SelectDropTarget() +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->SelectDropTarget(m_hTreeItem); +} + +template +inline BOOL CTreeItemT::SelectSetFirstVisible() +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->SelectSetFirstVisible(m_hTreeItem); +} + +template +inline HWND CTreeItemT::EditLabel() +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->EditLabel(m_hTreeItem); +} + +template +inline HIMAGELIST CTreeItemT::CreateDragImage() +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->CreateDragImage(m_hTreeItem); +} + +template +inline BOOL CTreeItemT::SortChildren(BOOL bRecurse /*= FALSE*/) +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->SortChildren(m_hTreeItem, bRecurse); +} + +template +inline BOOL CTreeItemT::EnsureVisible() +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->EnsureVisible(m_hTreeItem); +} + +template +inline CTreeItemT CTreeItemT::_Insert(LPCTSTR lpstrItem, int nImageIndex, HTREEITEM hItemAfter) +{ + ATLASSERT(m_pTreeView != NULL); + TVINSERTSTRUCT ins = { 0 }; + ins.hParent = m_hTreeItem; + ins.hInsertAfter = hItemAfter; + ins.item.mask = TVIF_TEXT; + ins.item.pszText = (LPTSTR)lpstrItem; + if(nImageIndex != -1) + { + ins.item.mask |= TVIF_IMAGE | TVIF_SELECTEDIMAGE; + ins.item.iImage = nImageIndex; + ins.item.iSelectedImage = nImageIndex; + } + return CTreeItemT(m_pTreeView->InsertItem(&ins), m_pTreeView); +} + +template +inline int CTreeItemT::GetImageIndex() const +{ + ATLASSERT(m_pTreeView != NULL); + TVITEM item = { 0 }; + item.mask = TVIF_HANDLE | TVIF_IMAGE; + item.hItem = m_hTreeItem; + m_pTreeView->GetItem(&item); + return item.iImage; +} + +#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) +template +inline BOOL CTreeItemT::SetInsertMark(BOOL bAfter) +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->SetInsertMark(m_hTreeItem, bAfter); +} +#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + +#if (_WIN32_WINNT >= 0x0501) +template +inline UINT CTreeItemT::MapHTREEITEMToAccID() const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->MapHTREEITEMToAccID(m_hTreeItem); +} +#endif // (_WIN32_WINNT >= 0x0501) + +#if (_WIN32_WINNT >= 0x0600) +template +inline void CTreeItemT::ShowInfoTip() +{ + ATLASSERT(m_pTreeView != NULL); + m_pTreeView->ShowInfoTip(m_hTreeItem); +} + +template +inline BOOL CTreeItemT::GetPartRect(TVITEMPART partID, LPRECT lpRect) const +{ + ATLASSERT(m_pTreeView != NULL); + return m_pTreeView->GetItemPartRect(m_hTreeItem, partID, lpRect); +} +#endif // (_WIN32_WINNT >= 0x0600) + + +/////////////////////////////////////////////////////////////////////////////// +// CToolBarCtrl + +template +class CToolBarCtrlT : public TBase +{ +public: +// Construction + CToolBarCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CToolBarCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return TOOLBARCLASSNAME; + } + + BOOL IsButtonEnabled(int nID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONENABLED, nID, 0L); + } + + BOOL IsButtonChecked(int nID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONCHECKED, nID, 0L); + } + + BOOL IsButtonPressed(int nID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONPRESSED, nID, 0L); + } + + BOOL IsButtonHidden(int nID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return(BOOL) ::SendMessage(m_hWnd, TB_ISBUTTONHIDDEN, nID, 0L); + } + + BOOL IsButtonIndeterminate(int nID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONINDETERMINATE, nID, 0L); + } + + int GetState(int nID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_GETSTATE, nID, 0L); + } + + BOOL SetState(int nID, UINT nState) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_SETSTATE, nID, MAKELPARAM(nState, 0)); + } + + BOOL GetButton(int nIndex, LPTBBUTTON lpButton) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_GETBUTTON, nIndex, (LPARAM)lpButton); + } + + int GetButtonCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_BUTTONCOUNT, 0, 0L); + } + + BOOL GetItemRect(int nIndex, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_GETITEMRECT, nIndex, (LPARAM)lpRect); + } + + void SetButtonStructSize(int nSize = sizeof(TBBUTTON)) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TB_BUTTONSTRUCTSIZE, nSize, 0L); + } + + BOOL SetButtonSize(SIZE size) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONSIZE, 0, MAKELPARAM(size.cx, size.cy)); + } + + BOOL SetButtonSize(int cx, int cy) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONSIZE, 0, MAKELPARAM(cx, cy)); + } + + BOOL SetBitmapSize(SIZE size) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_SETBITMAPSIZE, 0, MAKELPARAM(size.cx, size.cy)); + } + + BOOL SetBitmapSize(int cx, int cy) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_SETBITMAPSIZE, 0, MAKELPARAM(cx, cy)); + } + +#ifndef _WIN32_WCE + CToolTipCtrl GetToolTips() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TB_GETTOOLTIPS, 0, 0L)); + } + + void SetToolTips(HWND hWndToolTip) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TB_SETTOOLTIPS, (WPARAM)hWndToolTip, 0L); + } +#endif // !_WIN32_WCE + + void SetNotifyWnd(HWND hWnd) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TB_SETPARENT, (WPARAM)hWnd, 0L); + } + + int GetRows() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_GETROWS, 0, 0L); + } + + void SetRows(int nRows, BOOL bLarger, LPRECT lpRect) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TB_SETROWS, MAKELPARAM(nRows, bLarger), (LPARAM)lpRect); + } + + BOOL SetCmdID(int nIndex, UINT nID) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_SETCMDID, nIndex, nID); + } + + DWORD GetBitmapFlags() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, TB_GETBITMAPFLAGS, 0, 0L); + } + + int GetBitmap(int nID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_GETBITMAP, nID, 0L); + } + + int GetButtonText(int nID, LPTSTR lpstrText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_GETBUTTONTEXT, nID, (LPARAM)lpstrText); + } + + // nIndex - IE5 or higher only + CImageList GetImageList(int nIndex = 0) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETIMAGELIST, nIndex, 0L)); + } + + // nIndex - IE5 or higher only + CImageList SetImageList(HIMAGELIST hImageList, int nIndex = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETIMAGELIST, nIndex, (LPARAM)hImageList)); + } + + // nIndex - IE5 or higher only + CImageList GetDisabledImageList(int nIndex = 0) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETDISABLEDIMAGELIST, nIndex, 0L)); + } + + // nIndex - IE5 or higher only + CImageList SetDisabledImageList(HIMAGELIST hImageList, int nIndex = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETDISABLEDIMAGELIST, nIndex, (LPARAM)hImageList)); + } + +#ifndef _WIN32_WCE + // nIndex - IE5 or higher only + CImageList GetHotImageList(int nIndex = 0) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETHOTIMAGELIST, nIndex, 0L)); + } + + // nIndex - IE5 or higher only + CImageList SetHotImageList(HIMAGELIST hImageList, int nIndex = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETHOTIMAGELIST, nIndex, (LPARAM)hImageList)); + } +#endif // !_WIN32_WCE + + DWORD GetStyle() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, TB_GETSTYLE, 0, 0L); + } + + void SetStyle(DWORD dwStyle) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TB_SETSTYLE, 0, dwStyle); + } + + DWORD GetButtonSize() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, TB_GETBUTTONSIZE, 0, 0L); + } + + void GetButtonSize(SIZE& size) const + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TB_GETBUTTONSIZE, 0, 0L); + size.cx = LOWORD(dwRet); + size.cy = HIWORD(dwRet); + } + + BOOL GetRect(int nID, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_GETRECT, nID, (LPARAM)lpRect); + } + + int GetTextRows() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_GETTEXTROWS, 0, 0L); + } + + BOOL SetButtonWidth(int cxMin, int cxMax) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONWIDTH, 0, MAKELPARAM(cxMin, cxMax)); + } + + BOOL SetIndent(int nIndent) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_SETINDENT, nIndent, 0L); + } + + BOOL SetMaxTextRows(int nMaxTextRows) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_SETMAXTEXTROWS, nMaxTextRows, 0L); + } + +#if (_WIN32_IE >= 0x0400) +#ifndef _WIN32_WCE + BOOL GetAnchorHighlight() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_GETANCHORHIGHLIGHT, 0, 0L); + } + + BOOL SetAnchorHighlight(BOOL bEnable = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_SETANCHORHIGHLIGHT, bEnable, 0L); + } +#endif // !_WIN32_WCE + + int GetButtonInfo(int nID, LPTBBUTTONINFO lptbbi) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_GETBUTTONINFO, nID, (LPARAM)lptbbi); + } + + BOOL SetButtonInfo(int nID, LPTBBUTTONINFO lptbbi) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONINFO, nID, (LPARAM)lptbbi); + } + + BOOL SetButtonInfo(int nID, DWORD dwMask, BYTE Style, BYTE State, LPCTSTR lpszItem, + int iImage, WORD cx, int iCommand, DWORD_PTR lParam) + { + ATLASSERT(::IsWindow(m_hWnd)); + TBBUTTONINFO tbbi = { 0 }; + tbbi.cbSize = sizeof(TBBUTTONINFO); + tbbi.dwMask = dwMask; + tbbi.idCommand = iCommand; + tbbi.iImage = iImage; + tbbi.fsState = State; + tbbi.fsStyle = Style; + tbbi.cx = cx; + tbbi.pszText = (LPTSTR) lpszItem; + tbbi.lParam = lParam; + return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONINFO, nID, (LPARAM)&tbbi); + } + +#ifndef _WIN32_WCE + int GetHotItem() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_GETHOTITEM, 0, 0L); + } + + int SetHotItem(int nItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_SETHOTITEM, nItem, 0L); + } +#endif // !_WIN32_WCE + + BOOL IsButtonHighlighted(int nButtonID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONHIGHLIGHTED, nButtonID, 0L); + } + + DWORD SetDrawTextFlags(DWORD dwMask, DWORD dwFlags) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, TB_SETDRAWTEXTFLAGS, dwMask, dwFlags); + } + +#ifndef _WIN32_WCE + BOOL GetColorScheme(LPCOLORSCHEME lpcs) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_GETCOLORSCHEME, 0, (LPARAM)lpcs); + } + + void SetColorScheme(LPCOLORSCHEME lpcs) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TB_SETCOLORSCHEME, 0, (LPARAM)lpcs); + } + + DWORD GetExtendedStyle() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, TB_GETEXTENDEDSTYLE, 0, 0L); + } + + DWORD SetExtendedStyle(DWORD dwStyle) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, TB_SETEXTENDEDSTYLE, 0, dwStyle); + } + + void GetInsertMark(LPTBINSERTMARK lptbim) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TB_GETINSERTMARK, 0, (LPARAM)lptbim); + } + + void SetInsertMark(LPTBINSERTMARK lptbim) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TB_SETINSERTMARK, 0, (LPARAM)lptbim); + } + + COLORREF GetInsertMarkColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, TB_GETINSERTMARKCOLOR, 0, 0L); + } + + COLORREF SetInsertMarkColor(COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, TB_SETINSERTMARKCOLOR, 0, (LPARAM)clr); + } + + BOOL GetMaxSize(LPSIZE lpSize) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_GETMAXSIZE, 0, (LPARAM)lpSize); + } + + void GetPadding(LPSIZE lpSizePadding) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(lpSizePadding != NULL); + DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TB_GETPADDING, 0, 0L); + lpSizePadding->cx = GET_X_LPARAM(dwRet); + lpSizePadding->cy = GET_Y_LPARAM(dwRet); + } + + void SetPadding(int cx, int cy, LPSIZE lpSizePadding = NULL) + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TB_SETPADDING, 0, MAKELPARAM(cx, cy)); + if(lpSizePadding != NULL) + { + lpSizePadding->cx = GET_X_LPARAM(dwRet); + lpSizePadding->cy = GET_Y_LPARAM(dwRet); + } + } + + BOOL GetUnicodeFormat() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_GETUNICODEFORMAT, 0, 0L); + } + + BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_SETUNICODEFORMAT, bUnicode, 0L); + } +#endif // !_WIN32_WCE +#endif // (_WIN32_IE >= 0x0400) + +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + int GetString(int nString, LPTSTR lpstrString, int cchMaxLen) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(cchMaxLen, nString), (LPARAM)lpstrString); + } + + int GetStringBSTR(int nString, BSTR& bstrString) const + { + USES_CONVERSION; + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(bstrString == NULL); + int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(0, nString), NULL)); + if(nLength != -1) + { + CTempBuffer buff; + LPTSTR lpstrText = buff.Allocate(nLength + 1); + if(lpstrText != NULL) + { + nLength = (int)::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(nLength + 1, nString), (LPARAM)lpstrText); + if(nLength != -1) + bstrString = ::SysAllocString(T2OLE(lpstrText)); + } + else + { + nLength = -1; + } + } + + return nLength; + } + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + int GetString(int nString, _CSTRING_NS::CString& str) const + { + ATLASSERT(::IsWindow(m_hWnd)); + int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(0, nString), NULL)); + if(nLength != -1) + { + LPTSTR lpstr = str.GetBufferSetLength(nLength + 1); + if(lpstr != NULL) + nLength = (int)::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(nLength + 1, nString), (LPARAM)lpstr); + else + nLength = -1; + str.ReleaseBuffer(); + } + return nLength; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) +#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + +#if (_WIN32_WINNT >= 0x0501) + void GetMetrics(LPTBMETRICS lptbm) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TB_GETMETRICS, 0, (LPARAM)lptbm); + } + + void SetMetrics(LPTBMETRICS lptbm) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TB_SETMETRICS, 0, (LPARAM)lptbm); + } + + void SetWindowTheme(LPCWSTR lpstrTheme) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TB_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme); + } +#endif // (_WIN32_WINNT >= 0x0501) + +#if (_WIN32_WINNT >= 0x0600) + CImageList GetPressedImageList(int nIndex = 0) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETPRESSEDIMAGELIST, nIndex, 0L)); + } + + CImageList SetPressedImageList(HIMAGELIST hImageList, int nIndex = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETPRESSEDIMAGELIST, nIndex, (LPARAM)hImageList)); + } +#endif // (_WIN32_WINNT >= 0x0600) + +// Operations + BOOL EnableButton(int nID, BOOL bEnable = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_ENABLEBUTTON, nID, MAKELPARAM(bEnable, 0)); + } + + BOOL CheckButton(int nID, BOOL bCheck = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_CHECKBUTTON, nID, MAKELPARAM(bCheck, 0)); + } + + BOOL PressButton(int nID, BOOL bPress = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_PRESSBUTTON, nID, MAKELPARAM(bPress, 0)); + } + + BOOL HideButton(int nID, BOOL bHide = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_HIDEBUTTON, nID, MAKELPARAM(bHide, 0)); + } + + BOOL Indeterminate(int nID, BOOL bIndeterminate = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_INDETERMINATE, nID, MAKELPARAM(bIndeterminate, 0)); + } + + int AddBitmap(int nNumButtons, UINT nBitmapID) + { + ATLASSERT(::IsWindow(m_hWnd)); + TBADDBITMAP tbab = { 0 }; + tbab.hInst = ModuleHelper::GetResourceInstance(); + ATLASSERT(tbab.hInst != NULL); + tbab.nID = nBitmapID; + return (int)::SendMessage(m_hWnd, TB_ADDBITMAP, (WPARAM)nNumButtons, (LPARAM)&tbab); + } + + int AddBitmap(int nNumButtons, HBITMAP hBitmap) + { + ATLASSERT(::IsWindow(m_hWnd)); + TBADDBITMAP tbab = { 0 }; + tbab.hInst = NULL; + tbab.nID = (UINT_PTR)hBitmap; + return (int)::SendMessage(m_hWnd, TB_ADDBITMAP, (WPARAM)nNumButtons, (LPARAM)&tbab); + } + + BOOL AddButtons(int nNumButtons, LPTBBUTTON lpButtons) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_ADDBUTTONS, nNumButtons, (LPARAM)lpButtons); + } + + BOOL InsertButton(int nIndex, LPTBBUTTON lpButton) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_INSERTBUTTON, nIndex, (LPARAM)lpButton); + } + + BOOL InsertButton(int nIndex, int iCommand, BYTE Style, BYTE State, int iBitmap, + INT_PTR iString, DWORD_PTR lParam) + { + ATLASSERT(::IsWindow(m_hWnd)); + TBBUTTON tbb = { 0 }; + tbb.fsStyle = Style; + tbb.fsState = State; + tbb.idCommand = iCommand; + tbb.iBitmap = iBitmap; + tbb.iString = iString; + tbb.dwData = lParam; + return (BOOL)::SendMessage(m_hWnd, TB_INSERTBUTTON, nIndex, (LPARAM)&tbb); + } + + BOOL InsertButton(int nIndex, int iCommand, BYTE Style, BYTE State, int iBitmap, + LPCTSTR lpszItem, DWORD_PTR lParam) + { + return InsertButton(nIndex, iCommand, Style, State, iBitmap, (INT_PTR)lpszItem, lParam); + } + + BOOL AddButton(LPTBBUTTON lpButton) + { + return InsertButton(-1, lpButton); + } + + BOOL AddButton(int iCommand, BYTE Style, BYTE State, int iBitmap, INT_PTR iString, DWORD_PTR lParam) + { + return InsertButton(-1, iCommand, Style, State, iBitmap, iString, lParam); + } + + BOOL AddButton(int iCommand, BYTE Style, BYTE State, int iBitmap, LPCTSTR lpszItem, DWORD_PTR lParam) + { + return InsertButton(-1, iCommand, Style, State, iBitmap, lpszItem, lParam); + } + + BOOL DeleteButton(int nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_DELETEBUTTON, nIndex, 0L); + } + + UINT CommandToIndex(UINT nID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, TB_COMMANDTOINDEX, nID, 0L); + } + +#ifndef _WIN32_WCE + void SaveState(HKEY hKeyRoot, LPCTSTR lpszSubKey, LPCTSTR lpszValueName) + { + ATLASSERT(::IsWindow(m_hWnd)); + TBSAVEPARAMS tbs = { 0 }; + tbs.hkr = hKeyRoot; + tbs.pszSubKey = lpszSubKey; + tbs.pszValueName = lpszValueName; + ::SendMessage(m_hWnd, TB_SAVERESTORE, (WPARAM)TRUE, (LPARAM)&tbs); + } + + void RestoreState(HKEY hKeyRoot, LPCTSTR lpszSubKey, LPCTSTR lpszValueName) + { + ATLASSERT(::IsWindow(m_hWnd)); + TBSAVEPARAMS tbs = { 0 }; + tbs.hkr = hKeyRoot; + tbs.pszSubKey = lpszSubKey; + tbs.pszValueName = lpszValueName; + ::SendMessage(m_hWnd, TB_SAVERESTORE, (WPARAM)FALSE, (LPARAM)&tbs); + } + + void Customize() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TB_CUSTOMIZE, 0, 0L); + } +#endif // !_WIN32_WCE + + int AddString(UINT nStringID) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_ADDSTRING, (WPARAM)ModuleHelper::GetResourceInstance(), (LPARAM)nStringID); + } + + int AddStrings(LPCTSTR lpszStrings) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_ADDSTRING, 0, (LPARAM)lpszStrings); + } + + void AutoSize() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TB_AUTOSIZE, 0, 0L); + } + + BOOL ChangeBitmap(int nID, int nBitmap) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_CHANGEBITMAP, nID, MAKELPARAM(nBitmap, 0)); + } + + int LoadImages(int nBitmapID) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_LOADIMAGES, nBitmapID, (LPARAM)ModuleHelper::GetResourceInstance()); + } + + int LoadStdImages(int nBitmapID) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_LOADIMAGES, nBitmapID, (LPARAM)HINST_COMMCTRL); + } + + BOOL ReplaceBitmap(LPTBREPLACEBITMAP ptbrb) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_REPLACEBITMAP, 0, (LPARAM)ptbrb); + } + +#if (_WIN32_IE >= 0x0400) + int HitTest(LPPOINT lpPoint) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TB_HITTEST, 0, (LPARAM)lpPoint); + } + +#ifndef _WIN32_WCE + BOOL InsertMarkHitTest(LPPOINT lpPoint, LPTBINSERTMARK lptbim) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_INSERTMARKHITTEST, (WPARAM)lpPoint, (LPARAM)lptbim); + } + + BOOL InsertMarkHitTest(int x, int y, LPTBINSERTMARK lptbim) const + { + ATLASSERT(::IsWindow(m_hWnd)); + POINT pt = { x, y }; + return (BOOL)::SendMessage(m_hWnd, TB_INSERTMARKHITTEST, (WPARAM)&pt, (LPARAM)lptbim); + } + + BOOL MapAccelerator(TCHAR chAccel, int& nID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_MAPACCELERATOR, (WPARAM)chAccel, (LPARAM)&nID); + } + + BOOL MarkButton(int nID, BOOL bHighlight = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_MARKBUTTON, nID, MAKELPARAM(bHighlight, 0)); + } + + BOOL MoveButton(int nOldPos, int nNewPos) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TB_MOVEBUTTON, nOldPos, nNewPos); + } + + HRESULT GetObject(REFIID iid, LPVOID* ppvObject) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HRESULT)::SendMessage(m_hWnd, TB_GETOBJECT, (WPARAM)&iid, (LPARAM)ppvObject); + } +#endif // !_WIN32_WCE +#endif // (_WIN32_IE >= 0x0400) +}; + +typedef CToolBarCtrlT CToolBarCtrl; + + +/////////////////////////////////////////////////////////////////////////////// +// CStatusBarCtrl + +template +class CStatusBarCtrlT : public TBase +{ +public: +// Constructors + CStatusBarCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CStatusBarCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Methods + static LPCTSTR GetWndClassName() + { + return STATUSCLASSNAME; + } + + int GetParts(int nParts, int* pParts) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, SB_GETPARTS, nParts, (LPARAM)pParts); + } + + BOOL SetParts(int nParts, int* pWidths) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, SB_SETPARTS, nParts, (LPARAM)pWidths); + } + + int GetTextLength(int nPane, int* pType = NULL) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nPane < 256); + DWORD dwRet = (DWORD)::SendMessage(m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L); + if (pType != NULL) + *pType = (int)(short)HIWORD(dwRet); + return (int)(short)LOWORD(dwRet); + } + + int GetText(int nPane, LPTSTR lpszText, int* pType = NULL) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nPane < 256); + DWORD dwRet = (DWORD)::SendMessage(m_hWnd, SB_GETTEXT, (WPARAM)nPane, (LPARAM)lpszText); + if(pType != NULL) + *pType = (int)(short)HIWORD(dwRet); + return (int)(short)LOWORD(dwRet); + } + +#ifndef _ATL_NO_COM + BOOL GetTextBSTR(int nPane, BSTR& bstrText, int* pType = NULL) const + { + USES_CONVERSION; + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nPane < 256); + ATLASSERT(bstrText == NULL); + int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L)); + if(nLength == 0) + return FALSE; + + CTempBuffer buff; + LPTSTR lpstrText = buff.Allocate(nLength + 1); + if(lpstrText == NULL) + return FALSE; + + if(!GetText(nPane, lpstrText, pType)) + return FALSE; + + bstrText = ::SysAllocString(T2OLE(lpstrText)); + return (bstrText != NULL) ? TRUE : FALSE; + } +#endif // !_ATL_NO_COM + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + int GetText(int nPane, _CSTRING_NS::CString& strText, int* pType = NULL) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nPane < 256); + int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L)); + if(nLength == 0) + return 0; + + LPTSTR lpstr = strText.GetBufferSetLength(nLength); + if(lpstr == NULL) + return 0; + return GetText(nPane, lpstr, pType); + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + + BOOL SetText(int nPane, LPCTSTR lpszText, int nType = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nPane < 256); + return (BOOL)::SendMessage(m_hWnd, SB_SETTEXT, (nPane | nType), (LPARAM)lpszText); + } + + BOOL GetRect(int nPane, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nPane < 256); + return (BOOL)::SendMessage(m_hWnd, SB_GETRECT, nPane, (LPARAM)lpRect); + } + + BOOL GetBorders(int* pBorders) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, SB_GETBORDERS, 0, (LPARAM)pBorders); + } + + BOOL GetBorders(int& nHorz, int& nVert, int& nSpacing) const + { + ATLASSERT(::IsWindow(m_hWnd)); + int borders[3] = { 0, 0, 0 }; + BOOL bResult = (BOOL)::SendMessage(m_hWnd, SB_GETBORDERS, 0, (LPARAM)&borders); + if(bResult) + { + nHorz = borders[0]; + nVert = borders[1]; + nSpacing = borders[2]; + } + return bResult; + } + + void SetMinHeight(int nMin) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, SB_SETMINHEIGHT, nMin, 0L); + } + + BOOL SetSimple(BOOL bSimple = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, SB_SIMPLE, bSimple, 0L); + } + + BOOL IsSimple() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, SB_ISSIMPLE, 0, 0L); + } + +#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + BOOL GetUnicodeFormat() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, SB_GETUNICODEFORMAT, 0, 0L); + } + + BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, SB_SETUNICODEFORMAT, bUnicode, 0L); + } + + void GetTipText(int nPane, LPTSTR lpstrText, int nSize) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nPane < 256); + ::SendMessage(m_hWnd, SB_GETTIPTEXT, MAKEWPARAM(nPane, nSize), (LPARAM)lpstrText); + } + + void SetTipText(int nPane, LPCTSTR lpstrText) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nPane < 256); + ::SendMessage(m_hWnd, SB_SETTIPTEXT, nPane, (LPARAM)lpstrText); + } +#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + +#if ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500)) + COLORREF SetBkColor(COLORREF clrBk) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, SB_SETBKCOLOR, 0, (LPARAM)clrBk); + } + + HICON GetIcon(int nPane) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nPane < 256); + return (HICON)::SendMessage(m_hWnd, SB_GETICON, nPane, 0L); + } + + BOOL SetIcon(int nPane, HICON hIcon) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nPane < 256); + return (BOOL)::SendMessage(m_hWnd, SB_SETICON, nPane, (LPARAM)hIcon); + } +#endif // ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500)) +}; + +typedef CStatusBarCtrlT CStatusBarCtrl; + + +/////////////////////////////////////////////////////////////////////////////// +// CTabCtrl + +template +class CTabCtrlT : public TBase +{ +public: +// Constructors + CTabCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CTabCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return WC_TABCONTROL; + } + + CImageList GetImageList() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TCM_GETIMAGELIST, 0, 0L)); + } + + CImageList SetImageList(HIMAGELIST hImageList) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TCM_SETIMAGELIST, 0, (LPARAM)hImageList)); + } + + int GetItemCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TCM_GETITEMCOUNT, 0, 0L); + } + + BOOL GetItem(int nItem, LPTCITEM pTabCtrlItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TCM_GETITEM, nItem, (LPARAM)pTabCtrlItem); + } + + BOOL SetItem(int nItem, LPTCITEM pTabCtrlItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TCM_SETITEM, nItem, (LPARAM)pTabCtrlItem); + } + + int SetItem(int nItem, UINT mask, LPCTSTR lpszItem, DWORD dwState, DWORD dwStateMask, int iImage, LPARAM lParam) + { + ATLASSERT(::IsWindow(m_hWnd)); + TCITEM tci = { 0 }; + tci.mask = mask; + tci.pszText = (LPTSTR) lpszItem; + tci.dwState = dwState; + tci.dwStateMask = dwStateMask; + tci.iImage = iImage; + tci.lParam = lParam; + return (int)::SendMessage(m_hWnd, TCM_SETITEM, nItem, (LPARAM)&tci); + } + + BOOL GetItemRect(int nItem, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TCM_GETITEMRECT, nItem, (LPARAM)lpRect); + } + + int GetCurSel() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TCM_GETCURSEL, 0, 0L); + } + + int SetCurSel(int nItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TCM_SETCURSEL, nItem, 0L); + } + + SIZE SetItemSize(SIZE size) + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dwSize = (DWORD)::SendMessage(m_hWnd, TCM_SETITEMSIZE, 0, MAKELPARAM(size.cx, size.cy)); + SIZE sizeRet = { GET_X_LPARAM(dwSize), GET_Y_LPARAM(dwSize) }; + return sizeRet; + } + + void SetItemSize(int cx, int cy) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TCM_SETITEMSIZE, 0, MAKELPARAM(cx, cy)); + } + + void SetPadding(SIZE size) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TCM_SETPADDING, 0, MAKELPARAM(size.cx, size.cy)); + } + + int GetRowCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TCM_GETROWCOUNT, 0, 0L); + } + +#ifndef _WIN32_WCE + CToolTipCtrl GetTooltips() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TCM_GETTOOLTIPS, 0, 0L)); + } + + void SetTooltips(HWND hWndToolTip) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TCM_SETTOOLTIPS, (WPARAM)hWndToolTip, 0L); + } +#endif // !_WIN32_WCE + + int GetCurFocus() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TCM_GETCURFOCUS, 0, 0L); + } + + void SetCurFocus(int nItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TCM_SETCURFOCUS, nItem, 0L); + } + + BOOL SetItemExtra(int cbExtra) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetItemCount() == 0); // must be empty + return (BOOL)::SendMessage(m_hWnd, TCM_SETITEMEXTRA, cbExtra, 0L); + } + + int SetMinTabWidth(int nWidth = -1) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TCM_SETMINTABWIDTH, 0, nWidth); + } + +#if (_WIN32_IE >= 0x0400) + DWORD GetExtendedStyle() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, TCM_GETEXTENDEDSTYLE, 0, 0L); + } + + DWORD SetExtendedStyle(DWORD dwExMask, DWORD dwExStyle) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, TCM_SETEXTENDEDSTYLE, dwExMask, dwExStyle); + } + +#ifndef _WIN32_WCE + BOOL GetUnicodeFormat() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TCM_GETUNICODEFORMAT, 0, 0L); + } + + BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TCM_SETUNICODEFORMAT, bUnicode, 0L); + } +#endif // !_WIN32_WCE +#endif // (_WIN32_IE >= 0x0400) + +// Operations + int InsertItem(int nItem, LPTCITEM pTabCtrlItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)pTabCtrlItem); + } + + int InsertItem(int nItem, UINT mask, LPCTSTR lpszItem, int iImage, LPARAM lParam) + { + ATLASSERT(::IsWindow(m_hWnd)); + TCITEM tci = { 0 }; + tci.mask = mask; + tci.pszText = (LPTSTR) lpszItem; + tci.iImage = iImage; + tci.lParam = lParam; + return (int)::SendMessage(m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)&tci); + } + + int InsertItem(int nItem, LPCTSTR lpszItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + TCITEM tci = { 0 }; + tci.mask = TCIF_TEXT; + tci.pszText = (LPTSTR) lpszItem; + return (int)::SendMessage(m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)&tci); + } + + int AddItem(LPTCITEM pTabCtrlItem) + { + return InsertItem(GetItemCount(), pTabCtrlItem); + } + + int AddItem(UINT mask, LPCTSTR lpszItem, int iImage, LPARAM lParam) + { + return InsertItem(GetItemCount(), mask, lpszItem, iImage, lParam); + } + + int AddItem(LPCTSTR lpszItem) + { + return InsertItem(GetItemCount(), lpszItem); + } + + BOOL DeleteItem(int nItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TCM_DELETEITEM, nItem, 0L); + } + + BOOL DeleteAllItems() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TCM_DELETEALLITEMS, 0, 0L); + } + + void AdjustRect(BOOL bLarger, LPRECT lpRect) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TCM_ADJUSTRECT, bLarger, (LPARAM)lpRect); + } + + void RemoveImage(int nImage) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TCM_REMOVEIMAGE, nImage, 0L); + } + + int HitTest(TC_HITTESTINFO* pHitTestInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TCM_HITTEST, 0, (LPARAM)pHitTestInfo); + } + + void DeselectAll(BOOL bExcludeFocus = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TCM_DESELECTALL, bExcludeFocus, 0L); + } + +#if (_WIN32_IE >= 0x0400) + BOOL HighlightItem(int nIndex, BOOL bHighlight = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TCM_HIGHLIGHTITEM, nIndex, MAKELPARAM(bHighlight, 0)); + } +#endif // (_WIN32_IE >= 0x0400) +}; + +typedef CTabCtrlT CTabCtrl; + + +/////////////////////////////////////////////////////////////////////////////// +// CTrackBarCtrl + +template +class CTrackBarCtrlT : public TBase +{ +public: +// Constructors + CTrackBarCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CTrackBarCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return TRACKBAR_CLASS; + } + + int GetLineSize() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TBM_GETLINESIZE, 0, 0L); + } + + int SetLineSize(int nSize) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TBM_SETLINESIZE, 0, nSize); + } + + int GetPageSize() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TBM_GETPAGESIZE, 0, 0L); + } + + int SetPageSize(int nSize) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TBM_SETPAGESIZE, 0, nSize); + } + + int GetRangeMin() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TBM_GETRANGEMIN, 0, 0L); + } + + void SetRangeMin(int nMin, BOOL bRedraw = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TBM_SETRANGEMIN, bRedraw, nMin); + } + + int GetRangeMax() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TBM_GETRANGEMAX, 0, 0L); + } + + void SetRangeMax(int nMax, BOOL bRedraw = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TBM_SETRANGEMAX, bRedraw, nMax); + } + + void GetRange(int& nMin, int& nMax) const + { + nMin = GetRangeMin(); + nMax = GetRangeMax(); + } + + void SetRange(int nMin, int nMax, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TBM_SETRANGE, bRedraw, MAKELPARAM(nMin, nMax)); + } + + int GetSelStart() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TBM_GETSELSTART, 0, 0L); + } + + void SetSelStart(int nMin) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TBM_SETSELSTART, 0, (LPARAM)nMin); + } + + int GetSelEnd() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TBM_GETSELEND, 0, 0L); + } + + void SetSelEnd(int nMax) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TBM_SETSELEND, 0, (LPARAM)nMax); + } + + void GetSelection(int& nMin, int& nMax) const + { + nMin = GetSelStart(); + nMax = GetSelEnd(); + } + + void SetSelection(int nMin, int nMax) + { + SetSelStart(nMin); + SetSelEnd(nMax); + } + + void GetChannelRect(LPRECT lprc) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TBM_GETCHANNELRECT, 0, (LPARAM)lprc); + } + + void GetThumbRect(LPRECT lprc) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TBM_GETTHUMBRECT, 0, (LPARAM)lprc); + } + + int GetPos() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TBM_GETPOS, 0, 0L); + } + + void SetPos(int nPos) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TBM_SETPOS, TRUE, nPos); + } + + UINT GetNumTics() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, TBM_GETNUMTICS, 0, 0L); + } + + DWORD* GetTicArray() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD*)::SendMessage(m_hWnd, TBM_GETPTICS, 0, 0L); + } + + int GetTic(int nTic) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TBM_GETTIC, nTic, 0L); + } + + BOOL SetTic(int nTic) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TBM_SETTIC, 0, nTic); + } + + int GetTicPos(int nTic) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TBM_GETTICPOS, nTic, 0L); + } + + void SetTicFreq(int nFreq) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TBM_SETTICFREQ, nFreq, 0L); + } + + int GetThumbLength() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TBM_GETTHUMBLENGTH, 0, 0L); + } + + void SetThumbLength(int nLength) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TBM_SETTHUMBLENGTH, nLength, 0L); + } + + void SetSel(int nStart, int nEnd, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & TBS_ENABLESELRANGE) != 0); + ::SendMessage(m_hWnd, TBM_SETSEL, bRedraw, MAKELPARAM(nStart, nEnd)); + } + + ATL::CWindow GetBuddy(BOOL bLeft = TRUE) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ATL::CWindow((HWND)::SendMessage(m_hWnd, TBM_GETBUDDY, bLeft, 0L)); + } + + ATL::CWindow SetBuddy(HWND hWndBuddy, BOOL bLeft = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ATL::CWindow((HWND)::SendMessage(m_hWnd, TBM_SETBUDDY, bLeft, (LPARAM)hWndBuddy)); + } + +#ifndef _WIN32_WCE + CToolTipCtrl GetToolTips() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TBM_GETTOOLTIPS, 0, 0L)); + } + + void SetToolTips(HWND hWndTT) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TBM_SETTOOLTIPS, (WPARAM)hWndTT, 0L); + } + + int SetTipSide(int nSide) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, TBM_SETTIPSIDE, nSide, 0L); + } +#endif // !_WIN32_WCE + +#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + BOOL GetUnicodeFormat() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TBM_GETUNICODEFORMAT, 0, 0L); + } + + BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, TBM_SETUNICODEFORMAT, bUnicode, 0L); + } +#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + +// Operations + void ClearSel(BOOL bRedraw = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TBM_CLEARSEL, bRedraw, 0L); + } + + void VerifyPos() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TBM_SETPOS, FALSE, 0L); + } + + void ClearTics(BOOL bRedraw = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, TBM_CLEARTICS, bRedraw, 0L); + } +}; + +typedef CTrackBarCtrlT CTrackBarCtrl; + + +/////////////////////////////////////////////////////////////////////////////// +// CUpDownCtrl + +template +class CUpDownCtrlT : public TBase +{ +public: +// Constructors + CUpDownCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CUpDownCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return UPDOWN_CLASS; + } + + UINT GetAccel(int nAccel, UDACCEL* pAccel) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)LOWORD(::SendMessage(m_hWnd, UDM_GETACCEL, nAccel, (LPARAM)pAccel)); + } + + BOOL SetAccel(int nAccel, UDACCEL* pAccel) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)LOWORD(::SendMessage(m_hWnd, UDM_SETACCEL, nAccel, (LPARAM)pAccel)); + } + + UINT GetBase() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)LOWORD(::SendMessage(m_hWnd, UDM_GETBASE, 0, 0L)); + } + + int SetBase(int nBase) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, UDM_SETBASE, nBase, 0L); + } + + ATL::CWindow GetBuddy() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ATL::CWindow((HWND)::SendMessage(m_hWnd, UDM_GETBUDDY, 0, 0L)); + } + + ATL::CWindow SetBuddy(HWND hWndBuddy) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ATL::CWindow((HWND)::SendMessage(m_hWnd, UDM_SETBUDDY, (WPARAM)hWndBuddy, 0L)); + } + + int GetPos(LPBOOL lpbError = NULL) const + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dwRet = (DWORD)::SendMessage(m_hWnd, UDM_GETPOS, 0, 0L); + // Note: Seems that Windows always sets error to TRUE if + // UDS_SETBUDDYINT style is not used + if(lpbError != NULL) + *lpbError = (HIWORD(dwRet) != 0) ? TRUE : FALSE; + return (int)(short)LOWORD(dwRet); + } + + int SetPos(int nPos) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)(short)LOWORD(::SendMessage(m_hWnd, UDM_SETPOS, 0, MAKELPARAM(nPos, 0))); + } + + DWORD GetRange() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, UDM_GETRANGE, 0, 0L); + } + + void GetRange(int& nLower, int& nUpper) const + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dwRet = (DWORD)::SendMessage(m_hWnd, UDM_GETRANGE, 0, 0L); + nLower = (int)(short)HIWORD(dwRet); + nUpper = (int)(short)LOWORD(dwRet); + } + + void SetRange(int nLower, int nUpper) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, UDM_SETRANGE, 0, MAKELPARAM(nUpper, nLower)); + } + +#if (_WIN32_IE >= 0x0400) + void SetRange32(int nLower, int nUpper) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, UDM_SETRANGE32, nLower, nUpper); + } + + void GetRange32(int& nLower, int& nUpper) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, UDM_GETRANGE32, (WPARAM)&nLower, (LPARAM)&nUpper); + } + +#ifndef _WIN32_WCE + BOOL GetUnicodeFormat() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, UDM_GETUNICODEFORMAT, 0, 0L); + } + + BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, UDM_SETUNICODEFORMAT, bUnicode, 0L); + } +#endif // !_WIN32_WCE +#endif // (_WIN32_IE >= 0x0400) + +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + int GetPos32(LPBOOL lpbError = NULL) const + { + ATLASSERT(::IsWindow(m_hWnd)); + // Note: Seems that Windows always sets error to TRUE if + // UDS_SETBUDDYINT style is not used + return (int)::SendMessage(m_hWnd, UDM_GETPOS32, 0, (LPARAM)lpbError); + } + + int SetPos32(int nPos) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, UDM_SETPOS32, 0, (LPARAM)nPos); + } +#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) +}; + +typedef CUpDownCtrlT CUpDownCtrl; + + +/////////////////////////////////////////////////////////////////////////////// +// CProgressBarCtrl + +template +class CProgressBarCtrlT : public TBase +{ +public: +// Constructors + CProgressBarCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CProgressBarCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return PROGRESS_CLASS; + } + + DWORD SetRange(int nLower, int nUpper) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, PBM_SETRANGE, 0, MAKELPARAM(nLower, nUpper)); + } + + int SetPos(int nPos) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_SETPOS, nPos, 0L)); + } + + int OffsetPos(int nPos) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_DELTAPOS, nPos, 0L)); + } + + int SetStep(int nStep) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_SETSTEP, nStep, 0L)); + } + + UINT GetPos() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, PBM_GETPOS, 0, 0L); + } + + void GetRange(PPBRANGE pPBRange) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pPBRange != NULL); + ::SendMessage(m_hWnd, PBM_GETRANGE, TRUE, (LPARAM)pPBRange); + } + + void GetRange(int& nLower, int& nUpper) const + { + ATLASSERT(::IsWindow(m_hWnd)); + PBRANGE range = { 0 }; + ::SendMessage(m_hWnd, PBM_GETRANGE, TRUE, (LPARAM)&range); + nLower = range.iLow; + nUpper = range.iHigh; + } + + int GetRangeLimit(BOOL bLowLimit) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PBM_GETRANGE, bLowLimit, (LPARAM)NULL); + } + + DWORD SetRange32(int nMin, int nMax) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, PBM_SETRANGE32, nMin, nMax); + } + +#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + COLORREF SetBarColor(COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, PBM_SETBARCOLOR, 0, (LPARAM)clr); + } + + COLORREF SetBkColor(COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, PBM_SETBKCOLOR, 0, (LPARAM)clr); + } +#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + +#if (_WIN32_WINNT >= 0x0501) && defined(PBM_SETMARQUEE) + BOOL SetMarquee(BOOL bMarquee, UINT uUpdateTime = 0U) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, PBM_SETMARQUEE, (WPARAM)bMarquee, (LPARAM)uUpdateTime); + } +#endif // (_WIN32_WINNT >= 0x0501) && defined(PBM_SETMARQUEE) + +#if (_WIN32_WINNT >= 0x0600) + int GetStep() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PBM_GETSTEP, 0, 0L); + } + + COLORREF GetBkColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, PBM_GETBKCOLOR, 0, 0L); + } + + COLORREF GetBarColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, PBM_GETBARCOLOR, 0, 0L); + } + + int GetState() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PBM_GETSTATE, 0, 0L); + } + + int SetState(int nState) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PBM_SETSTATE, nState, 0L); + } +#endif // (_WIN32_WINNT >= 0x0600) + +// Operations + int StepIt() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_STEPIT, 0, 0L)); + } +}; + +typedef CProgressBarCtrlT CProgressBarCtrl; + + +/////////////////////////////////////////////////////////////////////////////// +// CHotKeyCtrl + +#ifndef _WIN32_WCE + +template +class CHotKeyCtrlT : public TBase +{ +public: +// Constructors + CHotKeyCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CHotKeyCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return HOTKEY_CLASS; + } + + DWORD GetHotKey() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, HKM_GETHOTKEY, 0, 0L); + } + + void GetHotKey(WORD &wVirtualKeyCode, WORD &wModifiers) const + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dw = (DWORD)::SendMessage(m_hWnd, HKM_GETHOTKEY, 0, 0L); + wVirtualKeyCode = LOBYTE(LOWORD(dw)); + wModifiers = HIBYTE(LOWORD(dw)); + } + + void SetHotKey(WORD wVirtualKeyCode, WORD wModifiers) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, HKM_SETHOTKEY, MAKEWORD(wVirtualKeyCode, wModifiers), 0L); + } + + void SetRules(WORD wInvalidComb, WORD wModifiers) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, HKM_SETRULES, wInvalidComb, MAKELPARAM(wModifiers, 0)); + } +}; + +typedef CHotKeyCtrlT CHotKeyCtrl; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CAnimateCtrl + +#ifndef _WIN32_WCE + +template +class CAnimateCtrlT : public TBase +{ +public: +// Constructors + CAnimateCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CAnimateCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return ANIMATE_CLASS; + } + +// Operations + BOOL Open(ATL::_U_STRINGorID FileName) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, ACM_OPEN, 0, (LPARAM)FileName.m_lpstr); + } + + BOOL Play(UINT nFrom, UINT nTo, UINT nRep) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, ACM_PLAY, nRep, MAKELPARAM(nFrom, nTo)); + } + + BOOL Stop() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, ACM_STOP, 0, 0L); + } + + BOOL Close() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, ACM_OPEN, 0, 0L); + } + + BOOL Seek(UINT nTo) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, ACM_PLAY, 0, MAKELPARAM(nTo, nTo)); + } + + // Vista only + BOOL IsPlaying() const + { +#ifndef ACM_ISPLAYING + const UINT ACM_ISPLAYING = (WM_USER+104); +#endif + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, ACM_ISPLAYING, 0, 0L); + } +}; + +typedef CAnimateCtrlT CAnimateCtrl; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CRichEditCtrl + +#ifndef _WIN32_WCE + +#ifdef _UNICODE +#if (_RICHEDIT_VER == 0x0100) +#undef RICHEDIT_CLASS +#define RICHEDIT_CLASS L"RICHEDIT" +#endif // (_RICHEDIT_VER == 0x0100) +#endif // _UNICODE + +template +class CRichEditCtrlT : public TBase +{ +public: +// Constructors + CRichEditCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CRichEditCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return RICHEDIT_CLASS; + } + + static LPCTSTR GetLibraryName() + { +#if (_RICHEDIT_VER >= 0x0200) + return _T("RICHED20.DLL"); +#else + return _T("RICHED32.DLL"); +#endif + } + + int GetLineCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_GETLINECOUNT, 0, 0L); + } + + BOOL GetModify() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_GETMODIFY, 0, 0L); + } + + void SetModify(BOOL bModified = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETMODIFY, bModified, 0L); + } + + void GetRect(LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_GETRECT, 0, (LPARAM)lpRect); + } + + DWORD GetOptions() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, EM_GETOPTIONS, 0, 0L); + } + + DWORD SetOptions(WORD wOperation, DWORD dwOptions) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, EM_SETOPTIONS, wOperation, dwOptions); + } + + // NOTE: first word in lpszBuffer must contain the size of the buffer! + int GetLine(int nIndex, LPTSTR lpszBuffer) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer); + } + + int GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const + { + ATLASSERT(::IsWindow(m_hWnd)); + *(LPWORD)lpszBuffer = (WORD)nMaxLength; + return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer); + } + + BOOL CanUndo() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_CANUNDO, 0, 0L); + } + + BOOL CanPaste(UINT nFormat = 0) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_CANPASTE, nFormat, 0L); + } + + void GetSel(LONG& nStartChar, LONG& nEndChar) const + { + ATLASSERT(::IsWindow(m_hWnd)); + CHARRANGE cr = { 0, 0 }; + ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr); + nStartChar = cr.cpMin; + nEndChar = cr.cpMax; + } + + void GetSel(CHARRANGE &cr) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr); + } + + int SetSel(LONG nStartChar, LONG nEndChar) + { + ATLASSERT(::IsWindow(m_hWnd)); + CHARRANGE cr = { nStartChar, nEndChar }; + return (int)::SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&cr); + } + + int SetSel(CHARRANGE &cr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&cr); + } + + int SetSelAll() + { + return SetSel(0, -1); + } + + int SetSelNone() + { + return SetSel(-1, 0); + } + + DWORD GetDefaultCharFormat(CHARFORMAT& cf) const + { + ATLASSERT(::IsWindow(m_hWnd)); + cf.cbSize = sizeof(CHARFORMAT); + return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 0, (LPARAM)&cf); + } + + DWORD GetSelectionCharFormat(CHARFORMAT& cf) const + { + ATLASSERT(::IsWindow(m_hWnd)); + cf.cbSize = sizeof(CHARFORMAT); + return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 1, (LPARAM)&cf); + } + + DWORD GetEventMask() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, EM_GETEVENTMASK, 0, 0L); + } + + LONG GetLimitText() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (LONG)::SendMessage(m_hWnd, EM_GETLIMITTEXT, 0, 0L); + } + + DWORD GetParaFormat(PARAFORMAT& pf) const + { + ATLASSERT(::IsWindow(m_hWnd)); + pf.cbSize = sizeof(PARAFORMAT); + return (DWORD)::SendMessage(m_hWnd, EM_GETPARAFORMAT, 0, (LPARAM)&pf); + } + +#if (_RICHEDIT_VER >= 0x0200) + LONG GetSelText(LPTSTR lpstrBuff) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrBuff); + } +#else // !(_RICHEDIT_VER >= 0x0200) + // RichEdit 1.0 EM_GETSELTEXT is ANSI only + LONG GetSelText(LPSTR lpstrBuff) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrBuff); + } +#endif // !(_RICHEDIT_VER >= 0x0200) + +#ifndef _ATL_NO_COM + BOOL GetSelTextBSTR(BSTR& bstrText) const + { + USES_CONVERSION; + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(bstrText == NULL); + + CHARRANGE cr = { 0, 0 }; + ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr); + +#if (_RICHEDIT_VER >= 0x0200) + CTempBuffer buff; + LPTSTR lpstrText = buff.Allocate(cr.cpMax - cr.cpMin + 1); + if(lpstrText == NULL) + return FALSE; + if(::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText) == 0) + return FALSE; + + bstrText = ::SysAllocString(T2W(lpstrText)); +#else // !(_RICHEDIT_VER >= 0x0200) + CTempBuffer buff; + LPSTR lpstrText = buff.Allocate(cr.cpMax - cr.cpMin + 1); + if(lpstrText == NULL) + return FALSE; + if(::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText) == 0) + return FALSE; + + bstrText = ::SysAllocString(A2W(lpstrText)); +#endif // !(_RICHEDIT_VER >= 0x0200) + + return (bstrText != NULL) ? TRUE : FALSE; + } +#endif // !_ATL_NO_COM + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + LONG GetSelText(_CSTRING_NS::CString& strText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + + CHARRANGE cr = { 0, 0 }; + ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr); + +#if (_RICHEDIT_VER >= 0x0200) + LONG lLen = 0; + LPTSTR lpstrText = strText.GetBufferSetLength(cr.cpMax - cr.cpMin); + if(lpstrText != NULL) + { + lLen = (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText); + strText.ReleaseBuffer(); + } +#else // !(_RICHEDIT_VER >= 0x0200) + CTempBuffer buff; + LPSTR lpstrText = buff.Allocate(cr.cpMax - cr.cpMin + 1); + if(lpstrText == NULL) + return 0; + LONG lLen = (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText); + if(lLen == 0) + return 0; + + USES_CONVERSION; + strText = A2T(lpstrText); +#endif // !(_RICHEDIT_VER >= 0x0200) + + return lLen; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + + WORD GetSelectionType() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (WORD)::SendMessage(m_hWnd, EM_SELECTIONTYPE, 0, 0L); + } + + COLORREF SetBackgroundColor(COLORREF cr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, EM_SETBKGNDCOLOR, 0, cr); + } + + COLORREF SetBackgroundColor() // sets to system background + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, EM_SETBKGNDCOLOR, 1, 0); + } + + BOOL SetCharFormat(CHARFORMAT& cf, WORD wFlags) + { + ATLASSERT(::IsWindow(m_hWnd)); + cf.cbSize = sizeof(CHARFORMAT); + return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, (WPARAM)wFlags, (LPARAM)&cf); + } + + BOOL SetDefaultCharFormat(CHARFORMAT& cf) + { + ATLASSERT(::IsWindow(m_hWnd)); + cf.cbSize = sizeof(CHARFORMAT); + return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, 0, (LPARAM)&cf); + } + + BOOL SetSelectionCharFormat(CHARFORMAT& cf) + { + ATLASSERT(::IsWindow(m_hWnd)); + cf.cbSize = sizeof(CHARFORMAT); + return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } + + BOOL SetWordCharFormat(CHARFORMAT& cf) + { + ATLASSERT(::IsWindow(m_hWnd)); + cf.cbSize = sizeof(CHARFORMAT); + return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION | SCF_WORD, (LPARAM)&cf); + } + + DWORD SetEventMask(DWORD dwEventMask) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, EM_SETEVENTMASK, 0, dwEventMask); + } + + BOOL SetParaFormat(PARAFORMAT& pf) + { + ATLASSERT(::IsWindow(m_hWnd)); + pf.cbSize = sizeof(PARAFORMAT); + return (BOOL)::SendMessage(m_hWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf); + } + + BOOL SetTargetDevice(HDC hDC, int cxLineWidth) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_SETTARGETDEVICE, (WPARAM)hDC, cxLineWidth); + } + + int GetTextLength() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, WM_GETTEXTLENGTH, 0, 0L); + } + + BOOL SetReadOnly(BOOL bReadOnly = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_SETREADONLY, bReadOnly, 0L); + } + + int GetFirstVisibleLine() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_GETFIRSTVISIBLELINE, 0, 0L); + } + + EDITWORDBREAKPROCEX GetWordBreakProcEx() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (EDITWORDBREAKPROCEX)::SendMessage(m_hWnd, EM_GETWORDBREAKPROCEX, 0, 0L); + } + + EDITWORDBREAKPROCEX SetWordBreakProcEx(EDITWORDBREAKPROCEX pfnEditWordBreakProcEx) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (EDITWORDBREAKPROCEX)::SendMessage(m_hWnd, EM_SETWORDBREAKPROCEX, 0, (LPARAM)pfnEditWordBreakProcEx); + } + + int GetTextRange(TEXTRANGE* pTextRange) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_GETTEXTRANGE, 0, (LPARAM)pTextRange); + } + +#if (_RICHEDIT_VER >= 0x0200) + int GetTextRange(LONG nStartChar, LONG nEndChar, LPTSTR lpstrText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + TEXTRANGE tr = { 0 }; + tr.chrg.cpMin = nStartChar; + tr.chrg.cpMax = nEndChar; + tr.lpstrText = lpstrText; + return (int)::SendMessage(m_hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr); + } +#else // !(_RICHEDIT_VER >= 0x0200) + + int GetTextRange(LONG nStartChar, LONG nEndChar, LPSTR lpstrText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + TEXTRANGE tr = { 0 }; + tr.chrg.cpMin = nStartChar; + tr.chrg.cpMax = nEndChar; + tr.lpstrText = lpstrText; + return (int)::SendMessage(m_hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr); + } +#endif // !(_RICHEDIT_VER >= 0x0200) + +#if (_RICHEDIT_VER >= 0x0200) + DWORD GetDefaultCharFormat(CHARFORMAT2& cf) const + { + ATLASSERT(::IsWindow(m_hWnd)); + cf.cbSize = sizeof(CHARFORMAT2); + return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 0, (LPARAM)&cf); + } + + BOOL SetCharFormat(CHARFORMAT2& cf, WORD wFlags) + { + ATLASSERT(::IsWindow(m_hWnd)); + cf.cbSize = sizeof(CHARFORMAT2); + return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, (WPARAM)wFlags, (LPARAM)&cf); + } + + BOOL SetDefaultCharFormat(CHARFORMAT2& cf) + { + ATLASSERT(::IsWindow(m_hWnd)); + cf.cbSize = sizeof(CHARFORMAT2); + return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, 0, (LPARAM)&cf); + } + + DWORD GetSelectionCharFormat(CHARFORMAT2& cf) const + { + ATLASSERT(::IsWindow(m_hWnd)); + cf.cbSize = sizeof(CHARFORMAT2); + return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 1, (LPARAM)&cf); + } + + BOOL SetSelectionCharFormat(CHARFORMAT2& cf) + { + ATLASSERT(::IsWindow(m_hWnd)); + cf.cbSize = sizeof(CHARFORMAT2); + return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } + + BOOL SetWordCharFormat(CHARFORMAT2& cf) + { + ATLASSERT(::IsWindow(m_hWnd)); + cf.cbSize = sizeof(CHARFORMAT2); + return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION | SCF_WORD, (LPARAM)&cf); + } + + DWORD GetParaFormat(PARAFORMAT2& pf) const + { + ATLASSERT(::IsWindow(m_hWnd)); + pf.cbSize = sizeof(PARAFORMAT2); + return (DWORD)::SendMessage(m_hWnd, EM_GETPARAFORMAT, 0, (LPARAM)&pf); + } + + BOOL SetParaFormat(PARAFORMAT2& pf) + { + ATLASSERT(::IsWindow(m_hWnd)); + pf.cbSize = sizeof(PARAFORMAT2); + return (BOOL)::SendMessage(m_hWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf); + } + + TEXTMODE GetTextMode() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (TEXTMODE)::SendMessage(m_hWnd, EM_GETTEXTMODE, 0, 0L); + } + + BOOL SetTextMode(TEXTMODE enumTextMode) + { + ATLASSERT(::IsWindow(m_hWnd)); + return !(BOOL)::SendMessage(m_hWnd, EM_SETTEXTMODE, enumTextMode, 0L); + } + + UNDONAMEID GetUndoName() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UNDONAMEID)::SendMessage(m_hWnd, EM_GETUNDONAME, 0, 0L); + } + + UNDONAMEID GetRedoName() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UNDONAMEID)::SendMessage(m_hWnd, EM_GETREDONAME, 0, 0L); + } + + BOOL CanRedo() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_CANREDO, 0, 0L); + } + + BOOL GetAutoURLDetect() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_GETAUTOURLDETECT, 0, 0L); + } + + BOOL SetAutoURLDetect(BOOL bAutoDetect = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return !(BOOL)::SendMessage(m_hWnd, EM_AUTOURLDETECT, bAutoDetect, 0L); + } + + // this method is deprecated, please use SetAutoURLDetect + BOOL EnableAutoURLDetect(BOOL bEnable = TRUE) { return SetAutoURLDetect(bEnable); } + + UINT SetUndoLimit(UINT uUndoLimit) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, EM_SETUNDOLIMIT, uUndoLimit, 0L); + } + + void SetPalette(HPALETTE hPalette) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETPALETTE, (WPARAM)hPalette, 0L); + } + + int GetTextEx(GETTEXTEX* pGetTextEx, LPTSTR lpstrText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_GETTEXTEX, (WPARAM)pGetTextEx, (LPARAM)lpstrText); + } + + int GetTextEx(LPTSTR lpstrText, int nTextLen, DWORD dwFlags = GT_DEFAULT, UINT uCodePage = CP_ACP, LPCSTR lpDefaultChar = NULL, LPBOOL lpUsedDefChar = NULL) const + { + ATLASSERT(::IsWindow(m_hWnd)); + GETTEXTEX gte = { 0 }; + gte.cb = nTextLen * sizeof(TCHAR); + gte.codepage = uCodePage; + gte.flags = dwFlags; + gte.lpDefaultChar = lpDefaultChar; + gte.lpUsedDefChar = lpUsedDefChar; + return (int)::SendMessage(m_hWnd, EM_GETTEXTEX, (WPARAM)>e, (LPARAM)lpstrText); + } + + int GetTextLengthEx(GETTEXTLENGTHEX* pGetTextLengthEx) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_GETTEXTLENGTHEX, (WPARAM)pGetTextLengthEx, 0L); + } + + int GetTextLengthEx(DWORD dwFlags = GTL_DEFAULT, UINT uCodePage = CP_ACP) const + { + ATLASSERT(::IsWindow(m_hWnd)); + GETTEXTLENGTHEX gtle = { 0 }; + gtle.codepage = uCodePage; + gtle.flags = dwFlags; + return (int)::SendMessage(m_hWnd, EM_GETTEXTLENGTHEX, (WPARAM)>le, 0L); + } +#endif // (_RICHEDIT_VER >= 0x0200) + +#if (_RICHEDIT_VER >= 0x0300) + int SetTextEx(SETTEXTEX* pSetTextEx, LPCTSTR lpstrText) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_SETTEXTEX, (WPARAM)pSetTextEx, (LPARAM)lpstrText); + } + + int SetTextEx(LPCTSTR lpstrText, DWORD dwFlags = ST_DEFAULT, UINT uCodePage = CP_ACP) + { + ATLASSERT(::IsWindow(m_hWnd)); + SETTEXTEX ste = { 0 }; + ste.flags = dwFlags; + ste.codepage = uCodePage; + return (int)::SendMessage(m_hWnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)lpstrText); + } + + int GetEditStyle() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_GETEDITSTYLE, 0, 0L); + } + + int SetEditStyle(int nStyle, int nMask = -1) + { + ATLASSERT(::IsWindow(m_hWnd)); + if(nMask == -1) + nMask = nStyle; // set everything specified + return (int)::SendMessage(m_hWnd, EM_SETEDITSTYLE, nStyle, nMask); + } + + BOOL SetFontSize(int nFontSizeDelta) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nFontSizeDelta >= -1637 && nFontSizeDelta <= 1638); + return (BOOL)::SendMessage(m_hWnd, EM_SETFONTSIZE, nFontSizeDelta, 0L); + } + + void GetScrollPos(LPPOINT lpPoint) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(lpPoint != NULL); + ::SendMessage(m_hWnd, EM_GETSCROLLPOS, 0, (LPARAM)lpPoint); + } + + void SetScrollPos(LPPOINT lpPoint) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(lpPoint != NULL); + ::SendMessage(m_hWnd, EM_SETSCROLLPOS, 0, (LPARAM)lpPoint); + } + + BOOL GetZoom(int& nNum, int& nDen) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_GETZOOM, (WPARAM)&nNum, (LPARAM)&nDen); + } + + BOOL SetZoom(int nNum, int nDen) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nNum >= 0 && nNum <= 64); + ATLASSERT(nDen >= 0 && nDen <= 64); + return (BOOL)::SendMessage(m_hWnd, EM_SETZOOM, nNum, nDen); + } + + BOOL SetZoomOff() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_SETZOOM, 0, 0L); + } +#endif // (_RICHEDIT_VER >= 0x0300) + +// Operations + void LimitText(LONG nChars = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_EXLIMITTEXT, 0, nChars); + } + + int LineFromChar(LONG nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_EXLINEFROMCHAR, 0, nIndex); + } + + POINT PosFromChar(LONG nChar) const + { + ATLASSERT(::IsWindow(m_hWnd)); + POINT point = { 0, 0 }; + ::SendMessage(m_hWnd, EM_POSFROMCHAR, (WPARAM)&point, nChar); + return point; + } + + int CharFromPos(POINT pt) const + { + ATLASSERT(::IsWindow(m_hWnd)); + POINTL ptl = { pt.x, pt.y }; + return (int)::SendMessage(m_hWnd, EM_CHARFROMPOS, 0, (LPARAM)&ptl); + } + + void EmptyUndoBuffer() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_EMPTYUNDOBUFFER, 0, 0L); + } + + int LineIndex(int nLine = -1) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_LINEINDEX, nLine, 0L); + } + + int LineLength(int nLine = -1) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, EM_LINELENGTH, nLine, 0L); + } + + BOOL LineScroll(int nLines, int nChars = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_LINESCROLL, nChars, nLines); + } + + void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText); + } + + void SetRect(LPCRECT lpRect) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETRECT, 0, (LPARAM)lpRect); + } + + BOOL DisplayBand(LPRECT pDisplayRect) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_DISPLAYBAND, 0, (LPARAM)pDisplayRect); + } + + LONG FindText(DWORD dwFlags, FINDTEXT& ft) const + { + ATLASSERT(::IsWindow(m_hWnd)); +#if (_RICHEDIT_VER >= 0x0200) && defined(_UNICODE) + return (LONG)::SendMessage(m_hWnd, EM_FINDTEXTW, dwFlags, (LPARAM)&ft); +#else + return (LONG)::SendMessage(m_hWnd, EM_FINDTEXT, dwFlags, (LPARAM)&ft); +#endif + } + + LONG FindText(DWORD dwFlags, FINDTEXTEX& ft) const + { + ATLASSERT(::IsWindow(m_hWnd)); +#if (_RICHEDIT_VER >= 0x0200) && defined(_UNICODE) + return (LONG)::SendMessage(m_hWnd, EM_FINDTEXTEXW, dwFlags, (LPARAM)&ft); +#else + return (LONG)::SendMessage(m_hWnd, EM_FINDTEXTEX, dwFlags, (LPARAM)&ft); +#endif + } + + LONG FormatRange(FORMATRANGE& fr, BOOL bDisplay = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (LONG)::SendMessage(m_hWnd, EM_FORMATRANGE, bDisplay, (LPARAM)&fr); + } + + LONG FormatRange(FORMATRANGE* pFormatRange, BOOL bDisplay = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (LONG)::SendMessage(m_hWnd, EM_FORMATRANGE, bDisplay, (LPARAM)pFormatRange); + } + + void HideSelection(BOOL bHide = TRUE, BOOL bChangeStyle = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_HIDESELECTION, bHide, bChangeStyle); + } + + void PasteSpecial(UINT uClipFormat, DWORD dwAspect = 0, HMETAFILE hMF = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + REPASTESPECIAL reps = { dwAspect, (DWORD_PTR)hMF }; + ::SendMessage(m_hWnd, EM_PASTESPECIAL, uClipFormat, (LPARAM)&reps); + } + + void RequestResize() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_REQUESTRESIZE, 0, 0L); + } + + LONG StreamIn(UINT uFormat, EDITSTREAM& es) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (LONG)::SendMessage(m_hWnd, EM_STREAMIN, uFormat, (LPARAM)&es); + } + + LONG StreamOut(UINT uFormat, EDITSTREAM& es) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (LONG)::SendMessage(m_hWnd, EM_STREAMOUT, uFormat, (LPARAM)&es); + } + + DWORD FindWordBreak(int nCode, LONG nStartChar) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, EM_FINDWORDBREAK, nCode, nStartChar); + } + + // Additional operations + void ScrollCaret() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L); + } + + int InsertText(long nInsertAfterChar, LPCTSTR lpstrText, BOOL bCanUndo = FALSE) + { + int nRet = SetSel(nInsertAfterChar, nInsertAfterChar); + ReplaceSel(lpstrText, bCanUndo); + return nRet; + } + + int AppendText(LPCTSTR lpstrText, BOOL bCanUndo = FALSE) + { + return InsertText(GetWindowTextLength(), lpstrText, bCanUndo); + } + + // Clipboard operations + BOOL Undo() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_UNDO, 0, 0L); + } + + void Clear() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L); + } + + void Copy() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_COPY, 0, 0L); + } + + void Cut() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_CUT, 0, 0L); + } + + void Paste() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_PASTE, 0, 0L); + } + + // OLE support + IRichEditOle* GetOleInterface() const + { + ATLASSERT(::IsWindow(m_hWnd)); + IRichEditOle *pRichEditOle = NULL; + ::SendMessage(m_hWnd, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle); + return pRichEditOle; + } + + BOOL SetOleCallback(IRichEditOleCallback* pCallback) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_SETOLECALLBACK, 0, (LPARAM)pCallback); + } + +#if (_RICHEDIT_VER >= 0x0200) + BOOL Redo() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_REDO, 0, 0L); + } + + void StopGroupTyping() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_STOPGROUPTYPING, 0, 0L); + } + + void ShowScrollBar(int nBarType, BOOL bVisible = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SHOWSCROLLBAR, nBarType, bVisible); + } +#endif // (_RICHEDIT_VER >= 0x0200) + +#if (_RICHEDIT_VER >= 0x0300) + BOOL SetTabStops(int nTabStops, LPINT rgTabStops) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops); + } + + BOOL SetTabStops() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 0, 0L); + } + + BOOL SetTabStops(const int& cxEachStop) // takes an 'int' + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop); + } +#endif // (_RICHEDIT_VER >= 0x0300) +}; + +typedef CRichEditCtrlT CRichEditCtrl; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CRichEditCommands - message handlers for standard EDIT commands + +#ifndef _WIN32_WCE + +// Chain to CRichEditCommands message map. Your class must also derive from CRichEditCtrl. +// Example: +// class CMyRichEdit : public CWindowImpl, +// public CRichEditCommands +// { +// public: +// BEGIN_MSG_MAP(CMyRichEdit) +// // your handlers... +// CHAIN_MSG_MAP_ALT(CRichEditCommands, 1) +// END_MSG_MAP() +// // other stuff... +// }; + +template +class CRichEditCommands : public CEditCommands< T > +{ +public: + BEGIN_MSG_MAP(CRichEditCommands< T >) + ALT_MSG_MAP(1) + COMMAND_ID_HANDLER(ID_EDIT_CLEAR, CEditCommands< T >::OnEditClear) + COMMAND_ID_HANDLER(ID_EDIT_CLEAR_ALL, CEditCommands< T >::OnEditClearAll) + COMMAND_ID_HANDLER(ID_EDIT_COPY, CEditCommands< T >::OnEditCopy) + COMMAND_ID_HANDLER(ID_EDIT_CUT, CEditCommands< T >::OnEditCut) + COMMAND_ID_HANDLER(ID_EDIT_PASTE, CEditCommands< T >::OnEditPaste) + COMMAND_ID_HANDLER(ID_EDIT_SELECT_ALL, CEditCommands< T >::OnEditSelectAll) + COMMAND_ID_HANDLER(ID_EDIT_UNDO, CEditCommands< T >::OnEditUndo) +#if (_RICHEDIT_VER >= 0x0200) + COMMAND_ID_HANDLER(ID_EDIT_REDO, OnEditRedo) +#endif // (_RICHEDIT_VER >= 0x0200) + END_MSG_MAP() + +#if (_RICHEDIT_VER >= 0x0200) + LRESULT OnEditRedo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->Redo(); + return 0; + } +#endif // (_RICHEDIT_VER >= 0x0200) + +// State (update UI) helpers + BOOL CanCut() const + { return HasSelection(); } + + BOOL CanCopy() const + { return HasSelection(); } + + BOOL CanClear() const + { return HasSelection(); } + +// Implementation + BOOL HasSelection() const + { + const T* pT = static_cast(this); + return (pT->GetSelectionType() != SEL_EMPTY); + } +}; + +#endif // _WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CDragListBox + +#ifndef _WIN32_WCE + +template +class CDragListBoxT : public CListBoxT< TBase > +{ +public: +// Constructors + CDragListBoxT(HWND hWnd = NULL) : CListBoxT< TBase >(hWnd) + { } + + CDragListBoxT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + if(hWnd != NULL) + MakeDragList(); + return hWnd; + } + +// Operations + BOOL MakeDragList() + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0); + return ::MakeDragList(m_hWnd); + } + + int LBItemFromPt(POINT pt, BOOL bAutoScroll = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::LBItemFromPt(m_hWnd, pt, bAutoScroll); + } + + void DrawInsert(int nItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::DrawInsert(GetParent(), m_hWnd, nItem); + } + + static UINT GetDragListMessage() + { + static UINT uDragListMessage = 0; + if(uDragListMessage == 0) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CDragListBox::GetDragListMessage.\n")); + ATLASSERT(FALSE); + return 0; + } + + if(uDragListMessage == 0) + uDragListMessage = ::RegisterWindowMessage(DRAGLISTMSGSTRING); + + lock.Unlock(); + } + ATLASSERT(uDragListMessage != 0); + return uDragListMessage; + } +}; + +typedef CDragListBoxT CDragListBox; + +template +class CDragListNotifyImpl +{ +public: + BEGIN_MSG_MAP(CDragListNotifyImpl< T >) + MESSAGE_HANDLER(CDragListBox::GetDragListMessage(), OnDragListNotify) + END_MSG_MAP() + + LRESULT OnDragListNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + uMsg; // avoid level 4 warning + ATLASSERT(uMsg == CDragListBox::GetDragListMessage()); + T* pT = static_cast(this); + LPDRAGLISTINFO lpDragListInfo = (LPDRAGLISTINFO)lParam; + LRESULT lRet = 0; + switch(lpDragListInfo->uNotification) + { + case DL_BEGINDRAG: + lRet = (LPARAM)pT->OnBeginDrag((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor); + break; + case DL_CANCELDRAG: + pT->OnCancelDrag((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor); + break; + case DL_DRAGGING: + lRet = (LPARAM)pT->OnDragging((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor); + break; + case DL_DROPPED: + pT->OnDropped((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor); + break; + default: + ATLTRACE2(atlTraceUI, 0, _T("Unknown DragListBox notification\n")); + bHandled = FALSE; // don't handle it + break; + } + return lRet; + } + +// Overrideables + BOOL OnBeginDrag(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/) + { + return TRUE; // allow dragging + } + + void OnCancelDrag(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/) + { + // nothing to do + } + + int OnDragging(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/) + { + return 0; // don't change cursor + } + + void OnDropped(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/) + { + // nothing to do + } +}; + +#endif // _WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CReBarCtrl + +template +class CReBarCtrlT : public TBase +{ +public: +// Constructors + CReBarCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CReBarCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return REBARCLASSNAME; + } + + UINT GetBandCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, RB_GETBANDCOUNT, 0, 0L); + } + + BOOL GetBandInfo(int nBand, LPREBARBANDINFO lprbbi) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, RB_GETBANDINFO, nBand, (LPARAM)lprbbi); + } + + BOOL SetBandInfo(int nBand, LPREBARBANDINFO lprbbi) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, RB_SETBANDINFO, nBand, (LPARAM)lprbbi); + } + + BOOL GetBarInfo(LPREBARINFO lprbi) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, RB_GETBARINFO, 0, (LPARAM)lprbi); + } + + BOOL SetBarInfo(LPREBARINFO lprbi) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, RB_SETBARINFO, 0, (LPARAM)lprbi); + } + + CImageList GetImageList() const + { + ATLASSERT(::IsWindow(m_hWnd)); + REBARINFO rbi = { 0 }; + rbi.cbSize = sizeof(REBARINFO); + rbi.fMask = RBIM_IMAGELIST; + if( (BOOL)::SendMessage(m_hWnd, RB_GETBARINFO, 0, (LPARAM)&rbi) == FALSE ) return CImageList(); + return CImageList(rbi.himl); + } + + BOOL SetImageList(HIMAGELIST hImageList) + { + ATLASSERT(::IsWindow(m_hWnd)); + REBARINFO rbi = { 0 }; + rbi.cbSize = sizeof(REBARINFO); + rbi.fMask = RBIM_IMAGELIST; + rbi.himl = hImageList; + return (BOOL)::SendMessage(m_hWnd, RB_SETBARINFO, 0, (LPARAM)&rbi); + } + + UINT GetRowCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, RB_GETROWCOUNT, 0, 0L); + } + + UINT GetRowHeight(int nBand) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, RB_GETROWHEIGHT, nBand, 0L); + } + +#if (_WIN32_IE >= 0x0400) + COLORREF GetTextColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, RB_GETTEXTCOLOR, 0, 0L); + } + + COLORREF SetTextColor(COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, RB_SETTEXTCOLOR, 0, (LPARAM)clr); + } + + COLORREF GetBkColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, RB_GETBKCOLOR, 0, 0L); + } + + COLORREF SetBkColor(COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, RB_SETBKCOLOR, 0, (LPARAM)clr); + } + + UINT GetBarHeight() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, RB_GETBARHEIGHT, 0, 0L); + } + + BOOL GetRect(int nBand, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, RB_GETRECT, nBand, (LPARAM)lpRect); + } + +#ifndef _WIN32_WCE + CToolTipCtrl GetToolTips() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CToolTipCtrl((HWND)::SendMessage(m_hWnd, RB_GETTOOLTIPS, 0, 0L)); + } + + void SetToolTips(HWND hwndToolTip) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, RB_SETTOOLTIPS, (WPARAM)hwndToolTip, 0L); + } +#endif // !_WIN32_WCE + + void GetBandBorders(int nBand, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(lpRect != NULL); + ::SendMessage(m_hWnd, RB_GETBANDBORDERS, nBand, (LPARAM)lpRect); + } + +#ifndef _WIN32_WCE + BOOL GetColorScheme(LPCOLORSCHEME lpColorScheme) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(lpColorScheme != NULL); + return (BOOL)::SendMessage(m_hWnd, RB_GETCOLORSCHEME, 0, (LPARAM)lpColorScheme); + } + + void SetColorScheme(LPCOLORSCHEME lpColorScheme) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(lpColorScheme != NULL); + ::SendMessage(m_hWnd, RB_SETCOLORSCHEME, 0, (LPARAM)lpColorScheme); + } + + HPALETTE GetPalette() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HPALETTE)::SendMessage(m_hWnd, RB_GETPALETTE, 0, 0L); + } + + HPALETTE SetPalette(HPALETTE hPalette) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HPALETTE)::SendMessage(m_hWnd, RB_SETPALETTE, 0, (LPARAM)hPalette); + } + + BOOL GetUnicodeFormat() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, RB_GETUNICODEFORMAT, 0, 0L); + } + + BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, RB_SETUNICODEFORMAT, bUnicode, 0L); + } +#endif // !_WIN32_WCE +#endif // (_WIN32_IE >= 0x0400) + +#if (_WIN32_WINNT >= 0x0501) + // requires uxtheme.h to be included to use MARGINS struct +#ifndef _UXTHEME_H_ + typedef struct _MARGINS* PMARGINS; +#endif // !_UXTHEME_H_ + void GetBandMargins(PMARGINS pMargins) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, RB_GETBANDMARGINS, 0, (LPARAM)pMargins); + } + + void SetWindowTheme(LPCWSTR lpstrTheme) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, RB_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme); + } +#endif // (_WIN32_WINNT >= 0x0501) + +#if (_WIN32_IE >= 0x0600) + DWORD GetExtendedStyle() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, RB_GETEXTENDEDSTYLE, 0, 0L); + } + + DWORD SetExtendedStyle(DWORD dwStyle, DWORD dwMask) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, RB_SETEXTENDEDSTYLE, dwMask, dwStyle); + } +#endif // (_WIN32_IE >= 0x0600) + +// Operations + BOOL InsertBand(int nBand, LPREBARBANDINFO lprbbi) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, RB_INSERTBAND, nBand, (LPARAM)lprbbi); + } + + BOOL AddBand(LPREBARBANDINFO lprbbi) + { + return InsertBand(-1, lprbbi); + } + + BOOL DeleteBand(int nBand) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, RB_DELETEBAND, nBand, 0L); + } + + ATL::CWindow SetNotifyWnd(HWND hWnd) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ATL::CWindow((HWND)::SendMessage(m_hWnd, RB_SETPARENT, (WPARAM)hWnd, 0L)); + } + +#if (_WIN32_IE >= 0x0400) + void BeginDrag(int nBand, DWORD dwPos) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, RB_BEGINDRAG, nBand, dwPos); + } + + void BeginDrag(int nBand, int xPos, int yPos) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, RB_BEGINDRAG, nBand, MAKELPARAM(xPos, yPos)); + } + + void EndDrag() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, RB_ENDDRAG, 0, 0L); + } + + void DragMove(DWORD dwPos) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, RB_DRAGMOVE, 0, dwPos); + } + + void DragMove(int xPos, int yPos) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, RB_DRAGMOVE, 0, MAKELPARAM(xPos, yPos)); + } + +#ifndef _WIN32_WCE + void GetDropTarget(IDropTarget** ppDropTarget) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, RB_GETDROPTARGET, 0, (LPARAM)ppDropTarget); + } +#endif // !_WIN32_WCE + + void MaximizeBand(int nBand, BOOL bIdeal = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, RB_MAXIMIZEBAND, nBand, bIdeal); + } + + void MinimizeBand(int nBand) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, RB_MINIMIZEBAND, nBand, 0L); + } + + BOOL SizeToRect(LPRECT lpRect) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, RB_SIZETORECT, 0, (LPARAM)lpRect); + } + + int IdToIndex(UINT uBandID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, RB_IDTOINDEX, uBandID, 0L); + } + + int HitTest(LPRBHITTESTINFO lprbht) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, RB_HITTEST, 0, (LPARAM)lprbht); + } + + BOOL ShowBand(int nBand, BOOL bShow) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, RB_SHOWBAND, nBand, bShow); + } + +#ifndef _WIN32_WCE + BOOL MoveBand(int nBand, int nNewPos) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nNewPos >= 0 && nNewPos <= ((int)GetBandCount() - 1)); + return (BOOL)::SendMessage(m_hWnd, RB_MOVEBAND, nBand, nNewPos); + } +#endif // !_WIN32_WCE +#endif // (_WIN32_IE >= 0x0400) + +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + void PushChevron(int nBand, LPARAM lAppValue) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, RB_PUSHCHEVRON, nBand, lAppValue); + } +#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + +// Extra operations +#if (_WIN32_IE >= 0x0400) + void LockBands(bool bLock) + { + int nBandCount = GetBandCount(); + for(int i =0; i < nBandCount; i++) + { + REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() }; + rbbi.fMask = RBBIM_STYLE; + BOOL bRet = GetBandInfo(i, &rbbi); + ATLASSERT(bRet); + + if((rbbi.fStyle & RBBS_GRIPPERALWAYS) == 0) + { + rbbi.fStyle |= RBBS_GRIPPERALWAYS; + bRet = SetBandInfo(i, &rbbi); + ATLASSERT(bRet); + rbbi.fStyle &= ~RBBS_GRIPPERALWAYS; + } + + if(bLock) + rbbi.fStyle |= RBBS_NOGRIPPER; + else + rbbi.fStyle &= ~RBBS_NOGRIPPER; + + bRet = SetBandInfo(i, &rbbi); + ATLASSERT(bRet); + } + } +#endif // (_WIN32_IE >= 0x0400) + +#if (_WIN32_WINNT >= 0x0600) + BOOL SetBandWidth(int nBand, int cxWidth) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, RB_SETBANDWIDTH, nBand, cxWidth); + } +#endif // (_WIN32_WINNT >= 0x0600) +}; + +typedef CReBarCtrlT CReBarCtrl; + + +/////////////////////////////////////////////////////////////////////////////// +// CComboBoxEx + +#ifndef _WIN32_WCE + +template +class CComboBoxExT : public CComboBoxT< TBase > +{ +public: +// Constructors + CComboBoxExT(HWND hWnd = NULL) : CComboBoxT< TBase >(hWnd) + { } + + CComboBoxExT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return WC_COMBOBOXEX; + } + + CImageList GetImageList() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, CBEM_GETIMAGELIST, 0, 0L)); + } + + CImageList SetImageList(HIMAGELIST hImageList) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CImageList((HIMAGELIST)::SendMessage(m_hWnd, CBEM_SETIMAGELIST, 0, (LPARAM)hImageList)); + } + +#if (_WIN32_IE >= 0x0400) + DWORD GetExtendedStyle() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, CBEM_GETEXTENDEDSTYLE, 0, 0L); + } + + DWORD SetExtendedStyle(DWORD dwExMask, DWORD dwExStyle) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, CBEM_SETEXTENDEDSTYLE, dwExMask, dwExStyle); + } + + BOOL GetUnicodeFormat() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, CBEM_GETUNICODEFORMAT, 0, 0L); + } + + BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, CBEM_SETUNICODEFORMAT, bUnicode, 0L); + } +#endif // (_WIN32_IE >= 0x0400) + +#if (_WIN32_WINNT >= 0x0501) + void SetWindowTheme(LPCWSTR lpstrTheme) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, CBEM_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme); + } +#endif // (_WIN32_WINNT >= 0x0501) + +// Operations + int InsertItem(const COMBOBOXEXITEM* lpcCBItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)lpcCBItem); + } + + int InsertItem(UINT nMask, int nIndex, LPCTSTR lpszItem, int nImage, int nSelImage, + int iIndent, int iOverlay, LPARAM lParam) + { + ATLASSERT(::IsWindow(m_hWnd)); + COMBOBOXEXITEM cbex = { 0 }; + cbex.mask = nMask; + cbex.iItem = nIndex; + cbex.pszText = (LPTSTR) lpszItem; + cbex.iImage = nImage; + cbex.iSelectedImage = nSelImage; + cbex.iIndent = iIndent; + cbex.iOverlay = iOverlay; + cbex.lParam = lParam; + return (int)::SendMessage(m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)&cbex); + } + + int InsertItem(int nIndex, LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, LPARAM lParam = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + COMBOBOXEXITEM cbex = { 0 }; + cbex.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_INDENT | CBEIF_LPARAM; + cbex.iItem = nIndex; + cbex.pszText = (LPTSTR) lpszItem; + cbex.iImage = nImage; + cbex.iSelectedImage = nSelImage; + cbex.iIndent = iIndent; + cbex.lParam = lParam; + return (int)::SendMessage(m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)&cbex); + } + + int AddItem(UINT nMask, LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, int iOverlay, LPARAM lParam) + { + return InsertItem(nMask, -1, lpszItem, nImage, nSelImage, iIndent, iOverlay, lParam); + } + + int AddItem(LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, LPARAM lParam = 0) + { + return InsertItem(-1, lpszItem, nImage, nSelImage, iIndent, lParam); + } + + int DeleteItem(int nIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, CBEM_DELETEITEM, nIndex, 0L); + } + + BOOL GetItem(PCOMBOBOXEXITEM pCBItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)pCBItem); + } + + BOOL SetItem(const COMBOBOXEXITEM* lpcCBItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, CBEM_SETITEM, 0, (LPARAM)lpcCBItem); + } + + int SetItem(int nIndex, UINT nMask, LPCTSTR lpszItem, int nImage, int nSelImage, + int iIndent, int iOverlay, LPARAM lParam) + { + ATLASSERT(::IsWindow(m_hWnd)); + COMBOBOXEXITEM cbex = { 0 }; + cbex.mask = nMask; + cbex.iItem = nIndex; + cbex.pszText = (LPTSTR) lpszItem; + cbex.iImage = nImage; + cbex.iSelectedImage = nSelImage; + cbex.iIndent = iIndent; + cbex.iOverlay = iOverlay; + cbex.lParam = lParam; + return (int)::SendMessage(m_hWnd, CBEM_SETITEM, 0, (LPARAM)&cbex); + } + + BOOL GetItemText(int nIndex, LPTSTR lpszItem, int nLen) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(lpszItem != NULL); + + COMBOBOXEXITEM cbex = { 0 }; + cbex.mask = CBEIF_TEXT; + cbex.iItem = nIndex; + cbex.pszText = lpszItem; + cbex.cchTextMax = nLen; + + return (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex); + } + +#ifndef _ATL_NO_COM + BOOL GetItemText(int nIndex, BSTR& bstrText) const + { + USES_CONVERSION; + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(bstrText == NULL); + + COMBOBOXEXITEM cbex = { 0 }; + cbex.mask = CBEIF_TEXT; + cbex.iItem = nIndex; + + LPTSTR lpstrText = NULL; + BOOL bRet = FALSE; + for(int nLen = 256; ; nLen *= 2) + { + ATLTRY(lpstrText = new TCHAR[nLen]); + if(lpstrText == NULL) + break; + lpstrText[0] = NULL; + cbex.pszText = lpstrText; + cbex.cchTextMax = nLen; + bRet = (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex); + if(!bRet || (lstrlen(cbex.pszText) < nLen - 1)) + break; + delete [] lpstrText; + lpstrText = NULL; + } + + if(lpstrText != NULL) + { + if(bRet) + bstrText = ::SysAllocString(T2OLE(lpstrText)); + delete [] lpstrText; + } + + return (bstrText != NULL) ? TRUE : FALSE; + } +#endif // !_ATL_NO_COM + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + BOOL GetItemText(int nIndex, _CSTRING_NS::CString& strText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + + COMBOBOXEXITEM cbex = { 0 }; + cbex.mask = CBEIF_TEXT; + cbex.iItem = nIndex; + + strText.Empty(); + BOOL bRet = FALSE; + for(int nLen = 256; ; nLen *= 2) + { + cbex.pszText = strText.GetBufferSetLength(nLen); + if(cbex.pszText == NULL) + { + bRet = FALSE; + break; + } + cbex.cchTextMax = nLen; + bRet = (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex); + if(!bRet || (lstrlen(cbex.pszText) < nLen - 1)) + break; + } + strText.ReleaseBuffer(); + return bRet; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + + BOOL SetItemText(int nIndex, LPCTSTR lpszItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return SetItem(nIndex, CBEIF_TEXT, lpszItem, 0, 0, 0, 0, 0); + } + + CComboBox GetComboCtrl() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CComboBox((HWND)::SendMessage(m_hWnd, CBEM_GETCOMBOCONTROL, 0, 0L)); + } + + CEdit GetEditCtrl() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CEdit((HWND)::SendMessage(m_hWnd, CBEM_GETEDITCONTROL, 0, 0L)); + } + + BOOL HasEditChanged() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, CBEM_HASEDITCHANGED, 0, 0L); + } + +// Non-functional + int AddString(LPCTSTR /*lpszItem*/) + { + ATLASSERT(FALSE); // Not available in CComboBoxEx; use InsertItem + return 0; + } + + int InsertString(int /*nIndex*/, LPCTSTR /*lpszString*/) + { + ATLASSERT(FALSE); // Not available in CComboBoxEx; use InsertItem + return 0; + } + + int Dir(UINT /*attr*/, LPCTSTR /*lpszWildCard*/) + { + ATLASSERT(FALSE); // Not available in CComboBoxEx + return 0; + } + + int FindString(int /*nStartAfter*/, LPCTSTR /*lpszString*/) const + { + ATLASSERT(FALSE); // Not available in CComboBoxEx; try FindStringExact + return 0; + } +}; + +typedef CComboBoxExT CComboBoxEx; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CMonthCalendarCtrl + +template +class CMonthCalendarCtrlT : public TBase +{ +public: +// Constructors + CMonthCalendarCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CMonthCalendarCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return MONTHCAL_CLASS; + } + + COLORREF GetColor(int nColorType) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, MCM_GETCOLOR, nColorType, 0L); + } + + COLORREF SetColor(int nColorType, COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, MCM_SETCOLOR, nColorType, clr); + } + + BOOL GetCurSel(LPSYSTEMTIME lpSysTime) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, MCM_GETCURSEL, 0, (LPARAM)lpSysTime); + } + + BOOL SetCurSel(LPSYSTEMTIME lpSysTime) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, MCM_SETCURSEL, 0, (LPARAM)lpSysTime); + } + + int GetFirstDayOfWeek(BOOL* pbLocaleVal = NULL) const + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dwRet = (DWORD)::SendMessage(m_hWnd, MCM_GETFIRSTDAYOFWEEK, 0, 0L); + if(pbLocaleVal != NULL) + *pbLocaleVal = (BOOL)HIWORD(dwRet); + return (int)(short)LOWORD(dwRet); + } + + int SetFirstDayOfWeek(int nDay, BOOL* pbLocaleVal = NULL) + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD dwRet = (DWORD)::SendMessage(m_hWnd, MCM_SETFIRSTDAYOFWEEK, 0, nDay); + if(pbLocaleVal != NULL) + *pbLocaleVal = (BOOL)HIWORD(dwRet); + return (int)(short)LOWORD(dwRet); + } + + int GetMaxSelCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, MCM_GETMAXSELCOUNT, 0, 0L); + } + + BOOL SetMaxSelCount(int nMax) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, MCM_SETMAXSELCOUNT, nMax, 0L); + } + + int GetMonthDelta() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, MCM_GETMONTHDELTA, 0, 0L); + } + + int SetMonthDelta(int nDelta) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, MCM_SETMONTHDELTA, nDelta, 0L); + } + + DWORD GetRange(LPSYSTEMTIME lprgSysTimeArray) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, MCM_GETRANGE, 0, (LPARAM)lprgSysTimeArray); + } + + BOOL SetRange(DWORD dwFlags, LPSYSTEMTIME lprgSysTimeArray) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, MCM_SETRANGE, dwFlags, (LPARAM)lprgSysTimeArray); + } + + BOOL GetSelRange(LPSYSTEMTIME lprgSysTimeArray) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, MCM_GETSELRANGE, 0, (LPARAM)lprgSysTimeArray); + } + + BOOL SetSelRange(LPSYSTEMTIME lprgSysTimeArray) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, MCM_SETSELRANGE, 0, (LPARAM)lprgSysTimeArray); + } + + BOOL GetToday(LPSYSTEMTIME lpSysTime) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, MCM_GETTODAY, 0, (LPARAM)lpSysTime); + } + + void SetToday(LPSYSTEMTIME lpSysTime) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, MCM_SETTODAY, 0, (LPARAM)lpSysTime); + } + + BOOL GetMinReqRect(LPRECT lpRectInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, MCM_GETMINREQRECT, 0, (LPARAM)lpRectInfo); + } + + int GetMaxTodayWidth() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, MCM_GETMAXTODAYWIDTH, 0, 0L); + } + +#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + BOOL GetUnicodeFormat() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, MCM_GETUNICODEFORMAT, 0, 0L); + } + + BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, MCM_SETUNICODEFORMAT, bUnicode, 0L); + } +#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + +#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) + DWORD GetCurrentView() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, MCM_GETCURRENTVIEW, 0, 0L); + } + + BOOL SetCurrentView(DWORD dwView) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, MCM_SETCURRENTVIEW, 0, dwView); + } + + DWORD GetCalendarCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, MCM_GETCALENDARCOUNT, 0, 0L); + } + + BOOL GetCalendarGridInfo(PMCGRIDINFO pGridInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, MCM_GETCALENDARGRIDINFO, 0, (LPARAM)pGridInfo); + } + + CALID GetCALID() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (CALID)::SendMessage(m_hWnd, MCM_GETCALID, 0, 0L); + } + + void SetCALID(CALID calid) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, MCM_SETCALID, (LPARAM)calid, 0L); + } + + int GetCalendarBorder() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, MCM_GETCALENDARBORDER, 0, 0L); + } + + void SetCalendarBorder(int cxyBorder, BOOL bSet = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, MCM_SETCALENDARBORDER, (WPARAM)bSet, (LPARAM)cxyBorder); + } +#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) + +// Operations + int GetMonthRange(DWORD dwFlags, LPSYSTEMTIME lprgSysTimeArray) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, MCM_GETMONTHRANGE, dwFlags, (LPARAM)lprgSysTimeArray); + } + + BOOL SetDayState(int nMonths, LPMONTHDAYSTATE lpDayStateArray) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, MCM_SETDAYSTATE, nMonths, (LPARAM)lpDayStateArray); + } + + DWORD HitTest(PMCHITTESTINFO pMCHitTest) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, MCM_HITTEST, 0, (LPARAM)pMCHitTest); + } + +#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) + void SizeRectToMin(LPRECT lpRect) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, MCM_SIZERECTTOMIN, 0, (LPARAM)lpRect); + } +#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) +}; + +typedef CMonthCalendarCtrlT CMonthCalendarCtrl; + + +/////////////////////////////////////////////////////////////////////////////// +// CDateTimePickerCtrl + +template +class CDateTimePickerCtrlT : public TBase +{ +public: +// Constructors + CDateTimePickerCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CDateTimePickerCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Operations + static LPCTSTR GetWndClassName() + { + return DATETIMEPICK_CLASS; + } + + BOOL SetFormat(LPCTSTR lpszFormat) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, DTM_SETFORMAT, 0, (LPARAM)lpszFormat); + } + + COLORREF GetMonthCalColor(int nColorType) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, DTM_GETMCCOLOR, nColorType, 0L); + } + + COLORREF SetMonthCalColor(int nColorType, COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, DTM_SETMCCOLOR, nColorType, clr); + } + + DWORD GetRange(LPSYSTEMTIME lpSysTimeArray) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, DTM_GETRANGE, 0, (LPARAM)lpSysTimeArray); + } + + BOOL SetRange(DWORD dwFlags, LPSYSTEMTIME lpSysTimeArray) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, DTM_SETRANGE, dwFlags, (LPARAM)lpSysTimeArray); + } + + DWORD GetSystemTime(LPSYSTEMTIME lpSysTime) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)lpSysTime); + } + + BOOL SetSystemTime(DWORD dwFlags, LPSYSTEMTIME lpSysTime) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, DTM_SETSYSTEMTIME, dwFlags, (LPARAM)lpSysTime); + } + + CMonthCalendarCtrl GetMonthCal() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CMonthCalendarCtrl((HWND)::SendMessage(m_hWnd, DTM_GETMONTHCAL, 0, 0L)); + } + +#if (_WIN32_IE >= 0x0400) + CFontHandle GetMonthCalFont() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CFontHandle((HFONT)::SendMessage(m_hWnd, DTM_GETMCFONT, 0, 0L)); + } + + void SetMonthCalFont(HFONT hFont, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_SETMCFONT, (WPARAM)hFont, MAKELPARAM(bRedraw, 0)); + } +#endif // (_WIN32_IE >= 0x0400) + +#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) + DWORD GetMonthCalStyle() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, DTM_GETMCSTYLE, 0, 0L); + } + + DWORD SetMonthCalStyle(DWORD dwStyle) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, DTM_SETMCSTYLE, 0, (LPARAM)dwStyle); + } + + void GetDateTimePickerInfo(LPDATETIMEPICKERINFO lpPickerInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_GETDATETIMEPICKERINFO, 0, (LPARAM)lpPickerInfo); + } + + BOOL GetIdealSize(LPSIZE lpSize) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, DTM_GETIDEALSIZE, 0, (LPARAM)lpSize); + } + + void CloseMonthCal() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_CLOSEMONTHCAL, 0, 0L); + } +#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) +}; + +typedef CDateTimePickerCtrlT CDateTimePickerCtrl; + + +/////////////////////////////////////////////////////////////////////////////// +// CFlatScrollBarImpl - support for flat scroll bars + +#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + +template +class CFlatScrollBarImpl +{ +public: +// Initialization + BOOL FlatSB_Initialize() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::InitializeFlatSB(pT->m_hWnd); + } + + HRESULT FlatSB_Uninitialize() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::UninitializeFlatSB(pT->m_hWnd); + } + +// Flat scroll bar properties + BOOL FlatSB_GetScrollProp(UINT uIndex, LPINT lpnValue) const + { + const T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::FlatSB_GetScrollProp(pT->m_hWnd, uIndex, lpnValue); + } + + BOOL FlatSB_SetScrollProp(UINT uIndex, int nValue, BOOL bRedraw = TRUE) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::FlatSB_SetScrollProp(pT->m_hWnd, uIndex, nValue, bRedraw); + } + +// Attributes + int FlatSB_GetScrollPos(int nBar) const + { + const T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::FlatSB_GetScrollPos(pT->m_hWnd, nBar); + } + + int FlatSB_SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::FlatSB_SetScrollPos(pT->m_hWnd, nBar, nPos, bRedraw); + } + + BOOL FlatSB_GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const + { + const T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::FlatSB_GetScrollRange(pT->m_hWnd, nBar, lpMinPos, lpMaxPos); + } + + BOOL FlatSB_SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::FlatSB_SetScrollRange(pT->m_hWnd, nBar, nMinPos, nMaxPos, bRedraw); + } + + BOOL FlatSB_GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo) const + { + const T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::FlatSB_GetScrollInfo(pT->m_hWnd, nBar, lpScrollInfo); + } + + int FlatSB_SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::FlatSB_SetScrollInfo(pT->m_hWnd, nBar, lpScrollInfo, bRedraw); + } + +// Operations + BOOL FlatSB_ShowScrollBar(UINT nBar, BOOL bShow = TRUE) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::FlatSB_ShowScrollBar(pT->m_hWnd, nBar, bShow); + } + + BOOL FlatSB_EnableScrollBar(UINT uSBFlags, UINT uArrowFlags = ESB_ENABLE_BOTH) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::FlatSB_EnableScrollBar(pT->m_hWnd, uSBFlags, uArrowFlags); + } +}; + +template +class CFlatScrollBarT : public TBase, public CFlatScrollBarImpl > +{ +public: + CFlatScrollBarT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CFlatScrollBarT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } +}; + +typedef CFlatScrollBarT CFlatScrollBar; + +#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + + +/////////////////////////////////////////////////////////////////////////////// +// CIPAddressCtrl + +#if (_WIN32_IE >= 0x0400) + +template +class CIPAddressCtrlT : public TBase +{ +public: +// Constructors + CIPAddressCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CIPAddressCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Atteributes + static LPCTSTR GetWndClassName() + { + return WC_IPADDRESS; + } + + BOOL IsBlank() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, IPM_ISBLANK, 0, 0L); + } + + int GetAddress(LPDWORD lpdwAddress) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, IPM_GETADDRESS, 0, (LPARAM)lpdwAddress); + } + + void SetAddress(DWORD dwAddress) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, IPM_SETADDRESS, 0, dwAddress); + } + + void ClearAddress() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, IPM_CLEARADDRESS, 0, 0L); + } + + void SetRange(int nField, WORD wRange) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, IPM_SETRANGE, nField, wRange); + } + + void SetRange(int nField, BYTE nMin, BYTE nMax) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, IPM_SETRANGE, nField, MAKEIPRANGE(nMin, nMax)); + } + + void SetFocus(int nField) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, IPM_SETFOCUS, nField, 0L); + } +}; + +typedef CIPAddressCtrlT CIPAddressCtrl; + +#endif // (_WIN32_IE >= 0x0400) + + +/////////////////////////////////////////////////////////////////////////////// +// CPagerCtrl + +#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + +template +class CPagerCtrlT : public TBase +{ +public: +// Constructors + CPagerCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CPagerCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return WC_PAGESCROLLER; + } + + int GetButtonSize() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PGM_GETBUTTONSIZE, 0, 0L); + } + + int SetButtonSize(int nButtonSize) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PGM_SETBUTTONSIZE, 0, nButtonSize); + } + + DWORD GetButtonState(int nButton) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nButton == PGB_TOPORLEFT || nButton == PGB_BOTTOMORRIGHT); + return (DWORD)::SendMessage(m_hWnd, PGM_GETBUTTONSTATE, 0, nButton); + } + + COLORREF GetBkColor() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, PGM_GETBKCOLOR, 0, 0L); + } + + COLORREF SetBkColor(COLORREF clrBk) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (COLORREF)::SendMessage(m_hWnd, PGM_SETBKCOLOR, 0, (LPARAM)clrBk); + } + + int GetBorder() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PGM_GETBORDER, 0, 0L); + } + + int SetBorder(int nBorderSize) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PGM_SETBORDER, 0, nBorderSize); + } + + int GetPos() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PGM_GETPOS, 0, 0L); + } + + int SetPos(int nPos) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PGM_SETPOS, 0, nPos); + } + +// Operations + void SetChild(HWND hWndChild) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, PGM_SETCHILD, 0, (LPARAM)hWndChild); + } + + void ForwardMouse(BOOL bForward = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, PGM_FORWARDMOUSE, bForward, 0L); + } + + void RecalcSize() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, PGM_RECALCSIZE, 0, 0L); + } + + void GetDropTarget(IDropTarget** ppDropTarget) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(ppDropTarget != NULL); + ::SendMessage(m_hWnd, PGM_GETDROPTARGET, 0, (LPARAM)ppDropTarget); + } +}; + +typedef CPagerCtrlT CPagerCtrl; + +#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + + +/////////////////////////////////////////////////////////////////////////////// +// CLinkCtrl - Windows SYSLINK control + +#if (_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE) + +template +class CLinkCtrlT : public TBase +{ +public: +// Constructors + CLinkCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CLinkCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + } + +// Attributes + static LPCTSTR GetWndClassName() + { +#ifdef _UNICODE + return WC_LINK; +#else // !_UNICODE + return "SysLink"; +#endif // !_UNICODE + } + + int GetIdealHeight(int cxMaxWidth = 0) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LM_GETIDEALHEIGHT, cxMaxWidth, 0L); + } + + BOOL GetItem(PLITEM pLItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LM_GETITEM, 0, (LPARAM)pLItem); + } + + BOOL SetItem(PLITEM pLItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LM_SETITEM, 0, (LPARAM)pLItem); + } + + // Vista only + int GetIdealSize(SIZE& size, int cxMaxWidth = 0) const + { +#ifndef LM_GETIDEALSIZE + const UINT LM_GETIDEALSIZE = LM_GETIDEALHEIGHT; +#endif + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, LM_GETIDEALSIZE, cxMaxWidth, (LPARAM)&size); + } + +// Operations + BOOL HitTest(PLHITTESTINFO pLHitTestInfo) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, LM_HITTEST, 0, (LPARAM)pLHitTestInfo); + } +}; + +typedef CLinkCtrlT CLinkCtrl; + +#endif // (_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE) + + +/////////////////////////////////////////////////////////////////////////////// +// CCustomDraw - MI class for custom-draw support + +template +class CCustomDraw +{ +public: +#if (_ATL_VER < 0x0700) + BOOL m_bHandledCD; + + BOOL IsMsgHandled() const + { + return m_bHandledCD; + } + + void SetMsgHandled(BOOL bHandled) + { + m_bHandledCD = bHandled; + } +#endif // !(_ATL_VER < 0x0700) + +// Message map and handlers + BEGIN_MSG_MAP(CCustomDraw< T >) + NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw) + ALT_MSG_MAP(1) + REFLECTED_NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw) + END_MSG_MAP() + +// message handler + LRESULT OnCustomDraw(int idCtrl, LPNMHDR pnmh, BOOL& bHandled) + { + T* pT = static_cast(this); + pT->SetMsgHandled(TRUE); + LPNMCUSTOMDRAW lpNMCustomDraw = (LPNMCUSTOMDRAW)pnmh; + DWORD dwRet = 0; + switch(lpNMCustomDraw->dwDrawStage) + { + case CDDS_PREPAINT: + dwRet = pT->OnPrePaint(idCtrl, lpNMCustomDraw); + break; + case CDDS_POSTPAINT: + dwRet = pT->OnPostPaint(idCtrl, lpNMCustomDraw); + break; + case CDDS_PREERASE: + dwRet = pT->OnPreErase(idCtrl, lpNMCustomDraw); + break; + case CDDS_POSTERASE: + dwRet = pT->OnPostErase(idCtrl, lpNMCustomDraw); + break; + case CDDS_ITEMPREPAINT: + dwRet = pT->OnItemPrePaint(idCtrl, lpNMCustomDraw); + break; + case CDDS_ITEMPOSTPAINT: + dwRet = pT->OnItemPostPaint(idCtrl, lpNMCustomDraw); + break; + case CDDS_ITEMPREERASE: + dwRet = pT->OnItemPreErase(idCtrl, lpNMCustomDraw); + break; + case CDDS_ITEMPOSTERASE: + dwRet = pT->OnItemPostErase(idCtrl, lpNMCustomDraw); + break; +#if (_WIN32_IE >= 0x0400) + case (CDDS_ITEMPREPAINT | CDDS_SUBITEM): + dwRet = pT->OnSubItemPrePaint(idCtrl, lpNMCustomDraw); + break; +#endif // (_WIN32_IE >= 0x0400) + default: + pT->SetMsgHandled(FALSE); + break; + } + bHandled = pT->IsMsgHandled(); + return dwRet; + } + +// Overrideables + DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) + { + return CDRF_DODEFAULT; + } + + DWORD OnPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) + { + return CDRF_DODEFAULT; + } + + DWORD OnPreErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) + { + return CDRF_DODEFAULT; + } + + DWORD OnPostErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) + { + return CDRF_DODEFAULT; + } + + DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) + { + return CDRF_DODEFAULT; + } + + DWORD OnItemPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) + { + return CDRF_DODEFAULT; + } + + DWORD OnItemPreErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) + { + return CDRF_DODEFAULT; + } + + DWORD OnItemPostErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) + { + return CDRF_DODEFAULT; + } + +#if (_WIN32_IE >= 0x0400) + DWORD OnSubItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) + { + return CDRF_DODEFAULT; + } +#endif // (_WIN32_IE >= 0x0400) +}; + + +// --- Windows CE common controls --- + +#ifdef _WIN32_WCE + +/////////////////////////////////////////////////////////////////////////////// +// CCECommandBarCtrl + +template +class CCECommandBarCtrlT : public TBase +{ +public: +// Constructors + CCECommandBarCtrlT(HWND hWnd = NULL) : TBase(hWnd) { } + + CCECommandBarCtrlT< TBase >& operator=(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + +// Attributes + BOOL IsVisible() const + { + return IsWindowVisible(); + } + + int GetHeight() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CommandBar_Height(m_hWnd); + } + + HMENU GetMenu(WORD wButton) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CommandBar_GetMenu(m_hWnd, wButton); + } + +// Operations + HWND Create(HWND hWndParent, int nCmdBarID) + { + m_hWnd = ::CommandBar_Create(ModuleHelper::GetModuleInstance(), hWndParent, nCmdBarID); + ATLASSERT(::IsWindow(m_hWnd)); + return m_hWnd; + } + + void Destroy() + { + DestroyWindow(); + } + + BOOL Show(BOOL bShow = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CommandBar_Show(m_hWnd, bShow); + } + + BOOL DrawMenuBar(WORD wButton) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CommandBar_DrawMenuBar(m_hWnd, wButton); + } + + BOOL AddAdornments(DWORD dwFlags = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CommandBar_AddAdornments(m_hWnd, dwFlags, 0); + } + + int AddBitmap(int nBitmapID, int nNumImages) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CommandBar_AddBitmap(m_hWnd, ModuleHelper::GetResourceInstance(), nBitmapID, nNumImages, 16, 16); + } + + BOOL AddButtons(UINT uNumButtons, LPTBBUTTON lpButtons) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CommandBar_AddButtons(m_hWnd, uNumButtons, lpButtons); + } + + BOOL AddToolTips(UINT uNumToolTips, LPTSTR lpToolTips) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CommandBar_AddToolTips(m_hWnd, uNumToolTips, lpToolTips); + } + + BOOL InsertButton(int nButton, LPTBBUTTON lpButton) + { + ATLASSERT(::IsWindow(m_hWnd)); + return CommandBar_InsertButton(m_hWnd, nButton, lpButton); + } + + HWND InsertComboBox(int nWidth, UINT dwStyle, WORD wComboBoxID, WORD wButton) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CommandBar_InsertComboBox(m_hWnd, ModuleHelper::GetModuleInstance(), nWidth, dwStyle, wComboBoxID, wButton); + } + + BOOL InsertMenubar(WORD wMenuID, WORD wButton) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CommandBar_InsertMenubar(m_hWnd, ModuleHelper::GetResourceInstance(), wMenuID, wButton); + } + + BOOL InsertMenubarEx(ATL::_U_STRINGorID menu, WORD wButton) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CommandBar_InsertMenubarEx(m_hWnd, ModuleHelper::GetResourceInstance(), (LPTSTR)menu.m_lpstr, wButton); + } + + BOOL IsCommandBarMessage(LPMSG lpMsg) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::IsCommandBarMessage(m_hWnd, lpMsg); + } +}; + +#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC MenuBar + typedef CCECommandBarCtrlT CMenuBarCtrl; +#else + typedef CCECommandBarCtrlT CCECommandBarCtrl; +#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) + +/////////////////////////////////////////////////////////////////////////////// +// CCECommandBandsCtrl + +template +class CCECommandBandsCtrlT : public TBase +{ +public: +// Constructors + CCECommandBandsCtrlT(HWND hWnd = NULL) : TBase(hWnd) { } + + CCECommandBandsCtrlT< TBase >& operator=(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + +// Attributes + BOOL IsVisible() const + { + return IsWindowVisible(); + } + +#if (_WIN32_IE >= 0x0400) + UINT GetHeight() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CommandBands_Height(m_hWnd); + } +#endif // (_WIN32_IE >= 0x0400) + + HWND GetCommandBar(UINT uBand) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CommandBands_GetCommandBar(m_hWnd, uBand); + } + + BOOL GetRestoreInformation(UINT uBand, LPCOMMANDBANDSRESTOREINFO pcbr) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CommandBands_GetRestoreInformation(m_hWnd, uBand, pcbr); + } + +// Operations + HWND Create(HWND hWndParent, UINT wID, DWORD dwStyles, HIMAGELIST hImageList = NULL) + { + m_hWnd = ::CommandBands_Create(ModuleHelper::GetModuleInstance(), hWndParent, wID, dwStyles, hImageList); + ATLASSERT(::IsWindow(m_hWnd)); + return m_hWnd; + } + + BOOL AddAdornments(DWORD dwFlags = 0, LPREBARBANDINFO prbbi = NULL) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CommandBands_AddAdornments(m_hWnd, ModuleHelper::GetModuleInstance(), dwFlags, prbbi); + } + + BOOL AddBands(UINT uBandCount, LPREBARBANDINFO prbbi) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CommandBands_AddBands(m_hWnd, ModuleHelper::GetModuleInstance(), uBandCount, prbbi); + } + + BOOL Show(BOOL bShow = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CommandBands_Show(m_hWnd, bShow); + } +}; + +typedef CCECommandBandsCtrlT CCECommandBandsCtrl; + +#endif // _WIN32_WCE + +}; // namespace WTL + +#endif // __ATLCTRLS_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlctrlw.h b/Client/Client/GUI/BKWin/wtl/atlctrlw.h new file mode 100644 index 00000000..194d80f9 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlctrlw.h @@ -0,0 +1,4158 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLCTRLW_H__ +#define __ATLCTRLW_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifdef _WIN32_WCE + #error atlctrlw.h is not supported on Windows CE +#endif + +#ifndef __ATLAPP_H__ + #error atlctrlw.h requires atlapp.h to be included first +#endif + +#ifndef __ATLCTRLS_H__ + #error atlctrlw.h requires atlctrls.h to be included first +#endif + +#if (_WIN32_IE < 0x0400) + #error atlctrlw.h requires _WIN32_IE >= 0x0400 +#endif + +// Define _WTL_CMDBAR_VISTA_MENUS as 0 to exclude Vista menus support +#if !defined(_WTL_CMDBAR_VISTA_MENUS) && (WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501) + #define _WTL_CMDBAR_VISTA_MENUS 1 +#endif + +#if _WTL_CMDBAR_VISTA_MENUS + #if !((_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501)) + #error _WTL_CMDBAR_VISTA_MENUS requires (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501) + #endif +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CCommandBarCtrlImpl +// CCommandBarCtrl +// CMDICommandBarCtrlImpl +// CMDICommandBarCtrl + + +namespace WTL +{ + +/////////////////////////////////////////////////////////////////////////////// +// Command Bars + +// Window Styles: +#define CBRWS_TOP CCS_TOP +#define CBRWS_BOTTOM CCS_BOTTOM +#define CBRWS_NORESIZE CCS_NORESIZE +#define CBRWS_NOPARENTALIGN CCS_NOPARENTALIGN +#define CBRWS_NODIVIDER CCS_NODIVIDER + +// Extended styles +#define CBR_EX_TRANSPARENT 0x00000001L +#define CBR_EX_SHAREMENU 0x00000002L +#define CBR_EX_ALTFOCUSMODE 0x00000004L +#define CBR_EX_TRACKALWAYS 0x00000008L +#define CBR_EX_NOVISTAMENUS 0x00000010L + +// standard command bar styles +#define ATL_SIMPLE_CMDBAR_PANE_STYLE \ + (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CBRWS_NODIVIDER | CBRWS_NORESIZE | CBRWS_NOPARENTALIGN) + +// Messages - support chevrons for frame windows +#define CBRM_GETCMDBAR (WM_USER + 301) // returns command bar HWND +#define CBRM_GETMENU (WM_USER + 302) // returns loaded or attached menu +#define CBRM_TRACKPOPUPMENU (WM_USER + 303) // displays a popup menu + +typedef struct tagCBRPOPUPMENU +{ + int cbSize; + HMENU hMenu; // popup menu do display + UINT uFlags; // TPM_* flags for ::TrackPopupMenuEx + int x; + int y; + LPTPMPARAMS lptpm; // ptr to TPMPARAMS for ::TrackPopupMenuEx +} CBRPOPUPMENU, *LPCBRPOPUPMENU; + +// helper class +template +class CSimpleStack : public ATL::CSimpleArray< T > +{ +public: + BOOL Push(T t) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - STACK-PUSH (%8.8X) size = %i\n"), t, GetSize()); +#endif + return Add(t); + } + + T Pop() + { + int nLast = GetSize() - 1; + if(nLast < 0) + return NULL; // must be able to convert to NULL + T t = m_aT[nLast]; +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - STACK-POP (%8.8X) size = %i\n"), t, GetSize()); +#endif + if(!RemoveAt(nLast)) + return NULL; + return t; + } + + T GetCurrent() + { + int nLast = GetSize() - 1; + if(nLast < 0) + return NULL; // must be able to convert to NULL + return m_aT[nLast]; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CCommandBarCtrlBase - base class for the Command Bar implementation + +class CCommandBarCtrlBase : public CToolBarCtrl +{ +public: + struct _MsgHookData + { + HHOOK hMsgHook; + DWORD dwUsage; + + _MsgHookData() : hMsgHook(NULL), dwUsage(0) + { } + }; + + typedef ATL::CSimpleMap CMsgHookMap; + static CMsgHookMap* s_pmapMsgHook; + + static HHOOK s_hCreateHook; + static bool s_bW2K; // For animation flag + static CCommandBarCtrlBase* s_pCurrentBar; + static bool s_bStaticInit; + + CSimpleStack m_stackMenuWnd; + CSimpleStack m_stackMenuHandle; + + HWND m_hWndHook; + DWORD m_dwMagic; + + + CCommandBarCtrlBase() : m_hWndHook(NULL), m_dwMagic(1314) + { + // init static variables + if(!s_bStaticInit) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlBase::CCommandBarCtrlBase.\n")); + ATLASSERT(FALSE); + return; + } + + if(!s_bStaticInit) + { + // Just in case... + AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES); + // Animation on Win2000 only + s_bW2K = !AtlIsOldWindows(); + // done + s_bStaticInit = true; + } + + lock.Unlock(); + } + } + + bool IsCommandBarBase() const { return m_dwMagic == 1314; } +}; + +__declspec(selectany) CCommandBarCtrlBase::CMsgHookMap* CCommandBarCtrlBase::s_pmapMsgHook = NULL; +__declspec(selectany) HHOOK CCommandBarCtrlBase::s_hCreateHook = NULL; +__declspec(selectany) CCommandBarCtrlBase* CCommandBarCtrlBase::s_pCurrentBar = NULL; +__declspec(selectany) bool CCommandBarCtrlBase::s_bW2K = false; +__declspec(selectany) bool CCommandBarCtrlBase::s_bStaticInit = false; + + +/////////////////////////////////////////////////////////////////////////////// +// CCommandBarCtrl - ATL implementation of Command Bars + +template +class ATL_NO_VTABLE CCommandBarCtrlImpl : public ATL::CWindowImpl< T, TBase, TWinTraits > +{ +public: + DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName()) + +// Declarations + struct _MenuItemData // menu item data + { + DWORD dwMagic; + LPTSTR lpstrText; + UINT fType; + UINT fState; + int iButton; + + _MenuItemData() { dwMagic = 0x1313; } + bool IsCmdBarMenuItem() { return (dwMagic == 0x1313); } + }; + + struct _ToolBarData // toolbar resource data + { + WORD wVersion; + WORD wWidth; + WORD wHeight; + WORD wItemCount; + //WORD aItems[wItemCount] + + WORD* items() + { return (WORD*)(this+1); } + }; + +// Constants + enum _CmdBarDrawConstants + { + s_kcxGap = 1, + s_kcxTextMargin = 2, + s_kcxButtonMargin = 3, + s_kcyButtonMargin = 3 + }; + + enum + { + _nMaxMenuItemTextLength = 100, + _chChevronShortcut = _T('/') + }; + +#ifndef DT_HIDEPREFIX + enum { DT_HIDEPREFIX = 0x00100000 }; +#endif // !DT_HIDEPREFIX + +// Data members + HMENU m_hMenu; + HIMAGELIST m_hImageList; + ATL::CSimpleValArray m_arrCommand; + + DWORD m_dwExtendedStyle; // Command Bar specific extended styles + + ATL::CContainedWindow m_wndParent; + + bool m_bMenuActive:1; + bool m_bAttachedMenu:1; + bool m_bImagesVisible:1; + bool m_bPopupItem:1; + bool m_bContextMenu:1; + bool m_bEscapePressed:1; + bool m_bSkipMsg:1; + bool m_bParentActive:1; + bool m_bFlatMenus:1; + bool m_bUseKeyboardCues:1; + bool m_bShowKeyboardCues:1; + bool m_bAllowKeyboardCues:1; + bool m_bKeyboardInput:1; + bool m_bAlphaImages:1; + bool m_bLayoutRTL:1; + bool m_bSkipPostDown:1; + bool m_bVistaMenus:1; + + int m_nPopBtn; + int m_nNextPopBtn; + + SIZE m_szBitmap; + SIZE m_szButton; + + COLORREF m_clrMask; + CFont m_fontMenu; // used internally, only to measure text + + UINT m_uSysKey; + + HWND m_hWndFocus; // Alternate focus mode + + int m_cxExtraSpacing; + +#if _WTL_CMDBAR_VISTA_MENUS + ATL::CSimpleValArray m_arrVistaBitmap; // Bitmaps for Vista menus +#endif // _WTL_CMDBAR_VISTA_MENUS + +// Constructor/destructor + CCommandBarCtrlImpl() : + m_hMenu(NULL), + m_hImageList(NULL), + m_wndParent(this, 1), + m_bMenuActive(false), + m_bAttachedMenu(false), + m_nPopBtn(-1), + m_nNextPopBtn(-1), + m_bPopupItem(false), + m_bImagesVisible(true), + m_bSkipMsg(false), + m_uSysKey(0), + m_hWndFocus(NULL), + m_bContextMenu(false), + m_bEscapePressed(false), + m_clrMask(RGB(192, 192, 192)), + m_dwExtendedStyle(CBR_EX_TRANSPARENT | CBR_EX_SHAREMENU | CBR_EX_TRACKALWAYS), + m_bParentActive(true), + m_bFlatMenus(false), + m_bUseKeyboardCues(false), + m_bShowKeyboardCues(false), + m_bAllowKeyboardCues(true), + m_bKeyboardInput(false), + m_cxExtraSpacing(0), + m_bAlphaImages(false), + m_bLayoutRTL(false), + m_bSkipPostDown(false), + m_bVistaMenus(false) + { + SetImageSize(16, 15); // default + } + + ~CCommandBarCtrlImpl() + { + if(m_wndParent.IsWindow()) +/*scary!*/ m_wndParent.UnsubclassWindow(); + + if(m_hMenu != NULL && (m_dwExtendedStyle & CBR_EX_SHAREMENU) == 0) + ::DestroyMenu(m_hMenu); + + if(m_hImageList != NULL) + ::ImageList_Destroy(m_hImageList); + } + +// Attributes + DWORD GetCommandBarExtendedStyle() const + { + return m_dwExtendedStyle; + } + + DWORD SetCommandBarExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) + { + DWORD dwPrevStyle = m_dwExtendedStyle; + if(dwMask == 0) + m_dwExtendedStyle = dwExtendedStyle; + else + m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); + return dwPrevStyle; + } + + CMenuHandle GetMenu() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return m_hMenu; + } + + COLORREF GetImageMaskColor() const + { + return m_clrMask; + } + + COLORREF SetImageMaskColor(COLORREF clrMask) + { + COLORREF clrOld = m_clrMask; + m_clrMask = clrMask; + return clrOld; + } + + bool GetImagesVisible() const + { + return m_bImagesVisible; + } + + bool SetImagesVisible(bool bVisible) + { + bool bOld = m_bImagesVisible; + m_bImagesVisible = bVisible; + return bOld; + } + + void GetImageSize(SIZE& size) const + { + size = m_szBitmap; + } + + bool SetImageSize(SIZE& size) + { + return SetImageSize(size.cx, size.cy); + } + + bool SetImageSize(int cx, int cy) + { + if(m_hImageList != NULL) + { + if(::ImageList_GetImageCount(m_hImageList) == 0) // empty + { + ::ImageList_Destroy(m_hImageList); + m_hImageList = NULL; + } + else + { + return false; // can't set, image list exists + } + } + + if(cx == 0 || cy == 0) + return false; + + m_szBitmap.cx = cx; + m_szBitmap.cy = cy; + m_szButton.cx = m_szBitmap.cx + 2 * s_kcxButtonMargin; + m_szButton.cy = m_szBitmap.cy + 2 * s_kcyButtonMargin; + + return true; + } + + bool GetAlphaImages() const + { + return m_bAlphaImages; + } + + bool SetAlphaImages(bool bAlphaImages) + { + if(m_hImageList != NULL) + { + if(::ImageList_GetImageCount(m_hImageList) == 0) // empty + { + ::ImageList_Destroy(m_hImageList); + m_hImageList = NULL; + } + else + { + return false; // can't set, image list exists + } + } + + m_bAlphaImages = bAlphaImages; + return true; + } + + HWND GetCmdBar() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HWND)::SendMessage(m_hWnd, CBRM_GETCMDBAR, 0, 0L); + } + +// Methods + HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + UINT nID = 0, LPVOID lpCreateParam = NULL) + { + // These styles are required for command bars + dwStyle |= TBSTYLE_LIST | TBSTYLE_FLAT; +#if (_MSC_VER >= 1300) + return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam); +#else // !(_MSC_VER >= 1300) + typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass; + return _baseClass::Create(hWndParent, rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam); +#endif // !(_MSC_VER >= 1300) + } + + BOOL AttachToWindow(HWND hWnd) + { + ATLASSERT(m_hWnd == NULL); + ATLASSERT(::IsWindow(hWnd)); + BOOL bRet = SubclassWindow(hWnd); + if(bRet) + { + m_bAttachedMenu = true; + T* pT = static_cast(this); + pT->GetSystemSettings(); + } + return bRet; + } + + BOOL LoadMenu(ATL::_U_STRINGorID menu) + { + ATLASSERT(::IsWindow(m_hWnd)); + + if(m_bAttachedMenu) // doesn't work in this mode + return FALSE; + if(menu.m_lpstr == NULL) + return FALSE; + + HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), menu.m_lpstr); + if(hMenu == NULL) + return FALSE; + + return AttachMenu(hMenu); + } + + BOOL AttachMenu(HMENU hMenu) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(hMenu == NULL || ::IsMenu(hMenu)); + if(hMenu != NULL && !::IsMenu(hMenu)) + return FALSE; + +#if _WTL_CMDBAR_VISTA_MENUS + // remove Vista bitmaps if used + if(m_bVistaMenus && (m_hMenu != NULL)) + { + T* pT = static_cast(this); + pT->_RemoveVistaBitmapsFromMenu(); + } +#endif // _WTL_CMDBAR_VISTA_MENUS + + // destroy old menu, if needed, and set new one + if(m_hMenu != NULL && (m_dwExtendedStyle & CBR_EX_SHAREMENU) == 0) + ::DestroyMenu(m_hMenu); + + m_hMenu = hMenu; + + if(m_bAttachedMenu) // Nothing else in this mode + return TRUE; + + // Build buttons according to menu + SetRedraw(FALSE); + + // Clear all buttons + int nCount = GetButtonCount(); + for(int i = 0; i < nCount; i++) + ATLVERIFY(DeleteButton(0) != FALSE); + + // Add buttons for each menu item + if(m_hMenu != NULL) + { + int nItems = ::GetMenuItemCount(m_hMenu); + + T* pT = static_cast(this); + pT; // avoid level 4 warning + TCHAR szString[pT->_nMaxMenuItemTextLength]; + for(int i = 0; i < nItems; i++) + { + CMenuItemInfo mii; + mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU; + mii.fType = MFT_STRING; + mii.dwTypeData = szString; + mii.cch = pT->_nMaxMenuItemTextLength; + BOOL bRet = ::GetMenuItemInfo(m_hMenu, i, TRUE, &mii); + ATLASSERT(bRet); + // If we have more than the buffer, we assume we have bitmaps bits + if(lstrlen(szString) > pT->_nMaxMenuItemTextLength - 1) + { + mii.fType = MFT_BITMAP; + ::SetMenuItemInfo(m_hMenu, i, TRUE, &mii); + szString[0] = 0; + } + + // NOTE: Command Bar currently supports only drop-down menu items + ATLASSERT(mii.hSubMenu != NULL); + + TBBUTTON btn = { 0 }; + btn.iBitmap = 0; + btn.idCommand = i; + btn.fsState = (BYTE)(((mii.fState & MFS_DISABLED) == 0) ? TBSTATE_ENABLED : 0); + btn.fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE | TBSTYLE_DROPDOWN; + btn.dwData = 0; + btn.iString = 0; + + bRet = InsertButton(-1, &btn); + ATLASSERT(bRet); + + TBBUTTONINFO bi = { 0 }; + bi.cbSize = sizeof(TBBUTTONINFO); + bi.dwMask = TBIF_TEXT; + bi.pszText = szString; + + bRet = SetButtonInfo(i, &bi); + ATLASSERT(bRet); + } + } + + SetRedraw(TRUE); + Invalidate(); + UpdateWindow(); + + return TRUE; + } + + BOOL LoadImages(ATL::_U_STRINGorID image) + { + return _LoadImagesHelper(image, false); + } + + BOOL LoadMappedImages(UINT nIDImage, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0) + { + return _LoadImagesHelper(nIDImage, true, nFlags , lpColorMap, nMapSize); + } + + BOOL _LoadImagesHelper(ATL::_U_STRINGorID image, bool bMapped, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + HINSTANCE hInstance = ModuleHelper::GetResourceInstance(); + + HRSRC hRsrc = ::FindResource(hInstance, image.m_lpstr, (LPTSTR)RT_TOOLBAR); + if(hRsrc == NULL) + return FALSE; + + HGLOBAL hGlobal = ::LoadResource(hInstance, hRsrc); + if(hGlobal == NULL) + return FALSE; + + _ToolBarData* pData = (_ToolBarData*)::LockResource(hGlobal); + if(pData == NULL) + return FALSE; + ATLASSERT(pData->wVersion == 1); + + WORD* pItems = pData->items(); + int nItems = pData->wItemCount; + + // Set internal data + SetImageSize(pData->wWidth, pData->wHeight); + + // Create image list if needed + if(m_hImageList == NULL) + { + // Check if the bitmap is 32-bit (alpha channel) bitmap (valid for Windows XP only) + T* pT = static_cast(this); + m_bAlphaImages = AtlIsAlphaBitmapResource(image); + + if(!pT->CreateInternalImageList(pData->wItemCount)) + return FALSE; + } + +#if _WTL_CMDBAR_VISTA_MENUS + int nOldImageCount = ::ImageList_GetImageCount(m_hImageList); +#endif // _WTL_CMDBAR_VISTA_MENUS + + // Add bitmap to our image list + CBitmap bmp; + if(bMapped) + { + ATLASSERT(HIWORD(PtrToUlong(image.m_lpstr)) == 0); // if mapped, must be a numeric ID + int nIDImage = (int)(short)LOWORD(PtrToUlong(image.m_lpstr)); + bmp.LoadMappedBitmap(nIDImage, (WORD)nFlags, lpColorMap, nMapSize); + } + else + { + if(m_bAlphaImages) + bmp = (HBITMAP)::LoadImage(ModuleHelper::GetResourceInstance(), image.m_lpstr, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE); + else + bmp.LoadBitmap(image.m_lpstr); + } + ATLASSERT(bmp.m_hBitmap != NULL); + if(bmp.m_hBitmap == NULL) + return FALSE; + if(::ImageList_AddMasked(m_hImageList, bmp, m_clrMask) == -1) + return FALSE; + + // Fill the array with command IDs + for(int i = 0; i < nItems; i++) + { + if(pItems[i] != 0) + m_arrCommand.Add(pItems[i]); + } + + int nImageCount = ::ImageList_GetImageCount(m_hImageList); + ATLASSERT(nImageCount == m_arrCommand.GetSize()); + if(nImageCount != m_arrCommand.GetSize()) + return FALSE; + +#if _WTL_CMDBAR_VISTA_MENUS + if(RunTimeHelper::IsVista()) + { + T* pT = static_cast(this); + pT->_AddVistaBitmapsFromImageList(nOldImageCount, nImageCount - nOldImageCount); + ATLASSERT(nImageCount == m_arrVistaBitmap.GetSize()); + } +#endif // _WTL_CMDBAR_VISTA_MENUS + + return TRUE; + } + + BOOL AddBitmap(ATL::_U_STRINGorID bitmap, int nCommandID) + { + ATLASSERT(::IsWindow(m_hWnd)); + CBitmap bmp; + bmp.LoadBitmap(bitmap.m_lpstr); + if(bmp.m_hBitmap == NULL) + return FALSE; + return AddBitmap(bmp, nCommandID); + } + + BOOL AddBitmap(HBITMAP hBitmap, UINT nCommandID) + { + ATLASSERT(::IsWindow(m_hWnd)); + T* pT = static_cast(this); + // Create image list if it doesn't exist + if(m_hImageList == NULL) + { + if(!pT->CreateInternalImageList(1)) + return FALSE; + } + // check bitmap size + CBitmapHandle bmp = hBitmap; + SIZE size = { 0, 0 }; + bmp.GetSize(size); + if(size.cx != m_szBitmap.cx || size.cy != m_szBitmap.cy) + { + ATLASSERT(FALSE); // must match size! + return FALSE; + } + // add bitmap + int nRet = ::ImageList_AddMasked(m_hImageList, hBitmap, m_clrMask); + if(nRet == -1) + return FALSE; + BOOL bRet = m_arrCommand.Add((WORD)nCommandID); + ATLASSERT(::ImageList_GetImageCount(m_hImageList) == m_arrCommand.GetSize()); +#if _WTL_CMDBAR_VISTA_MENUS + if(RunTimeHelper::IsVista()) + { + pT->_AddVistaBitmapFromImageList(m_arrCommand.GetSize() - 1); + ATLASSERT(m_arrVistaBitmap.GetSize() == m_arrCommand.GetSize()); + } +#endif // _WTL_CMDBAR_VISTA_MENUS + return bRet; + } + + BOOL AddIcon(ATL::_U_STRINGorID icon, UINT nCommandID) + { + ATLASSERT(::IsWindow(m_hWnd)); + HICON hIcon = ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr); + if(hIcon == NULL) + return FALSE; + return AddIcon(hIcon, nCommandID); + } + + BOOL AddIcon(HICON hIcon, UINT nCommandID) + { + ATLASSERT(::IsWindow(m_hWnd)); + T* pT = static_cast(this); + // create image list if it doesn't exist + if(m_hImageList == NULL) + { + if(!pT->CreateInternalImageList(1)) + return FALSE; + } + + int nRet = ::ImageList_AddIcon(m_hImageList, hIcon); + if(nRet == -1) + return FALSE; + BOOL bRet = m_arrCommand.Add((WORD)nCommandID); + ATLASSERT(::ImageList_GetImageCount(m_hImageList) == m_arrCommand.GetSize()); +#if _WTL_CMDBAR_VISTA_MENUS + if(RunTimeHelper::IsVista()) + { + pT->_AddVistaBitmapFromImageList(m_arrCommand.GetSize() - 1); + ATLASSERT(m_arrVistaBitmap.GetSize() == m_arrCommand.GetSize()); + } +#endif // _WTL_CMDBAR_VISTA_MENUS + return bRet; + } + + BOOL ReplaceBitmap(ATL::_U_STRINGorID bitmap, int nCommandID) + { + ATLASSERT(::IsWindow(m_hWnd)); + CBitmap bmp; + bmp.LoadBitmap(bitmap.m_lpstr); + if(bmp.m_hBitmap == NULL) + return FALSE; + return ReplaceBitmap(bmp, nCommandID); + } + + BOOL ReplaceBitmap(HBITMAP hBitmap, UINT nCommandID) + { + ATLASSERT(::IsWindow(m_hWnd)); + BOOL bRet = FALSE; + for(int i = 0; i < m_arrCommand.GetSize(); i++) + { + if(m_arrCommand[i] == nCommandID) + { + bRet = ::ImageList_Remove(m_hImageList, i); + if(bRet) + { + m_arrCommand.RemoveAt(i); +#if _WTL_CMDBAR_VISTA_MENUS + if(RunTimeHelper::IsVista()) + { + if(m_arrVistaBitmap[i] != NULL) + ::DeleteObject(m_arrVistaBitmap[i]); + m_arrVistaBitmap.RemoveAt(i); + } +#endif // _WTL_CMDBAR_VISTA_MENUS + } + break; + } + } + if(bRet) + bRet = AddBitmap(hBitmap, nCommandID); + return bRet; + } + + BOOL ReplaceIcon(ATL::_U_STRINGorID icon, UINT nCommandID) + { + ATLASSERT(::IsWindow(m_hWnd)); + HICON hIcon = ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr); + if(hIcon == NULL) + return FALSE; + return ReplaceIcon(hIcon, nCommandID); + } + + BOOL ReplaceIcon(HICON hIcon, UINT nCommandID) + { + ATLASSERT(::IsWindow(m_hWnd)); + BOOL bRet = FALSE; + for(int i = 0; i < m_arrCommand.GetSize(); i++) + { + if(m_arrCommand[i] == nCommandID) + { + bRet = (::ImageList_ReplaceIcon(m_hImageList, i, hIcon) != -1); +#if _WTL_CMDBAR_VISTA_MENUS + if(RunTimeHelper::IsVista() && bRet != FALSE) + { + T* pT = static_cast(this); + pT->_ReplaceVistaBitmapFromImageList(i); + } +#endif // _WTL_CMDBAR_VISTA_MENUS + break; + } + } + return bRet; + } + + BOOL RemoveImage(int nCommandID) + { + ATLASSERT(::IsWindow(m_hWnd)); + + BOOL bRet = FALSE; + for(int i = 0; i < m_arrCommand.GetSize(); i++) + { + if(m_arrCommand[i] == nCommandID) + { + bRet = ::ImageList_Remove(m_hImageList, i); + if(bRet) + { + m_arrCommand.RemoveAt(i); +#if _WTL_CMDBAR_VISTA_MENUS + if(RunTimeHelper::IsVista()) + { + if(m_arrVistaBitmap[i] != NULL) + ::DeleteObject(m_arrVistaBitmap[i]); + m_arrVistaBitmap.RemoveAt(i); + } +#endif // _WTL_CMDBAR_VISTA_MENUS + } + break; + } + } + return bRet; + } + + BOOL RemoveAllImages() + { + ATLASSERT(::IsWindow(m_hWnd)); + + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Removing all images\n")); + BOOL bRet = ::ImageList_RemoveAll(m_hImageList); + if(bRet) + { + m_arrCommand.RemoveAll(); +#if _WTL_CMDBAR_VISTA_MENUS + for(int i = 0; i < m_arrVistaBitmap.GetSize(); i++) + { + if(m_arrVistaBitmap[i] != NULL) + ::DeleteObject(m_arrVistaBitmap[i]); + } + m_arrVistaBitmap.RemoveAll(); +#endif // _WTL_CMDBAR_VISTA_MENUS + } + return bRet; + } + + BOOL TrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, LPTPMPARAMS lpParams = NULL) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(::IsMenu(hMenu)); + if(!::IsMenu(hMenu)) + return FALSE; + m_bContextMenu = true; + if(m_bUseKeyboardCues) + m_bShowKeyboardCues = m_bKeyboardInput; + T* pT = static_cast(this); + return pT->DoTrackPopupMenu(hMenu, uFlags, x, y, lpParams); + } + + BOOL SetMDIClient(HWND /*hWndMDIClient*/) + { + // Use CMDICommandBarCtrl for MDI support + ATLASSERT(FALSE); + return FALSE; + } + +// Message map and handlers + BEGIN_MSG_MAP(CCommandBarCtrlImpl) + MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) + MESSAGE_HANDLER(WM_INITMENU, OnInitMenu) + MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup) + MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect) + MESSAGE_HANDLER(GetAutoPopupMessage(), OnInternalAutoPopup) + MESSAGE_HANDLER(GetGetBarMessage(), OnInternalGetBar) + MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) + MESSAGE_HANDLER(WM_MENUCHAR, OnMenuChar) + + MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown) + MESSAGE_HANDLER(WM_KEYUP, OnKeyUp) + MESSAGE_HANDLER(WM_CHAR, OnChar) + MESSAGE_HANDLER(WM_SYSKEYDOWN, OnSysKeyDown) + MESSAGE_HANDLER(WM_SYSKEYUP, OnSysKeyUp) + MESSAGE_HANDLER(WM_SYSCHAR, OnSysChar) +// public API handlers - these stay to support chevrons in atlframe.h + MESSAGE_HANDLER(CBRM_GETMENU, OnAPIGetMenu) + MESSAGE_HANDLER(CBRM_TRACKPOPUPMENU, OnAPITrackPopupMenu) + MESSAGE_HANDLER(CBRM_GETCMDBAR, OnAPIGetCmdBar) + + MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem) + MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem) + + MESSAGE_HANDLER(WM_FORWARDMSG, OnForwardMsg) + ALT_MSG_MAP(1) // Parent window messages + NOTIFY_CODE_HANDLER(TBN_HOTITEMCHANGE, OnParentHotItemChange) + NOTIFY_CODE_HANDLER(TBN_DROPDOWN, OnParentDropDown) + MESSAGE_HANDLER(WM_INITMENUPOPUP, OnParentInitMenuPopup) + MESSAGE_HANDLER(GetGetBarMessage(), OnParentInternalGetBar) + MESSAGE_HANDLER(WM_SYSCOMMAND, OnParentSysCommand) + MESSAGE_HANDLER(CBRM_GETMENU, OnParentAPIGetMenu) + MESSAGE_HANDLER(WM_MENUCHAR, OnParentMenuChar) + MESSAGE_HANDLER(CBRM_TRACKPOPUPMENU, OnParentAPITrackPopupMenu) + MESSAGE_HANDLER(CBRM_GETCMDBAR, OnParentAPIGetCmdBar) + MESSAGE_HANDLER(WM_SETTINGCHANGE, OnParentSettingChange) + + MESSAGE_HANDLER(WM_DRAWITEM, OnParentDrawItem) + MESSAGE_HANDLER(WM_MEASUREITEM, OnParentMeasureItem) + + MESSAGE_HANDLER(WM_ACTIVATE, OnParentActivate) + NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnParentCustomDraw) + ALT_MSG_MAP(2) // MDI client window messages + // Use CMDICommandBarCtrl for MDI support + ALT_MSG_MAP(3) // Message hook messages + MESSAGE_HANDLER(WM_MOUSEMOVE, OnHookMouseMove) + MESSAGE_HANDLER(WM_SYSKEYDOWN, OnHookSysKeyDown) + MESSAGE_HANDLER(WM_SYSKEYUP, OnHookSysKeyUp) + MESSAGE_HANDLER(WM_SYSCHAR, OnHookSysChar) + MESSAGE_HANDLER(WM_KEYDOWN, OnHookKeyDown) + MESSAGE_HANDLER(WM_NEXTMENU, OnHookNextMenu) + MESSAGE_HANDLER(WM_CHAR, OnHookChar) + END_MSG_MAP() + + LRESULT OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) + { + LPMSG pMsg = (LPMSG)lParam; + if(pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST) + m_bKeyboardInput = false; + else if(pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) + m_bKeyboardInput = true; + LRESULT lRet = 0; + ProcessWindowMessage(pMsg->hwnd, pMsg->message, pMsg->wParam, pMsg->lParam, lRet, 3); + return lRet; + } + + LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + // Let the toolbar initialize itself + LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); + // get and use system settings + T* pT = static_cast(this); + pT->GetSystemSettings(); + // Parent init + ATL::CWindow wndParent = GetParent(); + ATL::CWindow wndTopLevelParent = wndParent.GetTopLevelParent(); + m_wndParent.SubclassWindow(wndTopLevelParent); + // Toolbar Init + SetButtonStructSize(); + SetImageList(NULL); + + // Create message hook if needed + CWindowCreateCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::OnCreate.\n")); + ATLASSERT(FALSE); + return -1; + } + + if(s_pmapMsgHook == NULL) + { + ATLTRY(s_pmapMsgHook = new CMsgHookMap); + ATLASSERT(s_pmapMsgHook != NULL); + } + + if(s_pmapMsgHook != NULL) + { + DWORD dwThreadID = ::GetCurrentThreadId(); + _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID); + if(pData == NULL) + { + ATLTRY(pData = new _MsgHookData); + ATLASSERT(pData != NULL); + HHOOK hMsgHook = ::SetWindowsHookEx(WH_GETMESSAGE, MessageHookProc, ModuleHelper::GetModuleInstance(), dwThreadID); + ATLASSERT(hMsgHook != NULL); + if(pData != NULL && hMsgHook != NULL) + { + pData->hMsgHook = hMsgHook; + pData->dwUsage = 1; + BOOL bRet = s_pmapMsgHook->Add(dwThreadID, pData); + bRet; + ATLASSERT(bRet); + } + } + else + { + (pData->dwUsage)++; + } + } + lock.Unlock(); + + // Get layout +#if (WINVER >= 0x0500) + m_bLayoutRTL = ((GetExStyle() & WS_EX_LAYOUTRTL) != 0); +#endif // (WINVER >= 0x0500) + + return lRet; + } + + LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); + +#if _WTL_CMDBAR_VISTA_MENUS + if(m_bVistaMenus && (m_hMenu != NULL)) + { + T* pT = static_cast(this); + pT->_RemoveVistaBitmapsFromMenu(); + } + + for(int i = 0; i < m_arrVistaBitmap.GetSize(); i++) + { + if(m_arrVistaBitmap[i] != NULL) + ::DeleteObject(m_arrVistaBitmap[i]); + } +#endif // _WTL_CMDBAR_VISTA_MENUS + + if(m_bAttachedMenu) // nothing to do in this mode + return lRet; + + CWindowCreateCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::OnDestroy.\n")); + ATLASSERT(FALSE); + return lRet; + } + + if(s_pmapMsgHook != NULL) + { + DWORD dwThreadID = ::GetCurrentThreadId(); + _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID); + if(pData != NULL) + { + (pData->dwUsage)--; + if(pData->dwUsage == 0) + { + BOOL bRet = ::UnhookWindowsHookEx(pData->hMsgHook); + ATLASSERT(bRet); + bRet = s_pmapMsgHook->Remove(dwThreadID); + ATLASSERT(bRet); + if(bRet) + delete pData; + } + + if(s_pmapMsgHook->GetSize() == 0) + { + delete s_pmapMsgHook; + s_pmapMsgHook = NULL; + } + } + } + + lock.Unlock(); + + return lRet; + } + + LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnKeyDown\n")); +#endif + bHandled = FALSE; + // Simulate Alt+Space for the parent + if(wParam == VK_SPACE) + { + m_wndParent.PostMessage(WM_SYSKEYDOWN, wParam, lParam | (1 << 29)); + bHandled = TRUE; + } +#if (_WIN32_IE >= 0x0500) + else if(wParam == VK_LEFT || wParam == VK_RIGHT) + { + WPARAM wpNext = m_bLayoutRTL ? VK_LEFT : VK_RIGHT; + + if(!m_bMenuActive) + { + T* pT = static_cast(this); + int nBtn = GetHotItem(); + int nNextBtn = (wParam == wpNext) ? pT->GetNextMenuItem(nBtn) : pT->GetPreviousMenuItem(nBtn); + if(nNextBtn == -2) + { + SetHotItem(-1); + if(pT->DisplayChevronMenu()) + bHandled = TRUE; + } + } + } +#endif // (_WIN32_IE >= 0x0500) + return 0; + } + + LRESULT OnKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnKeyUp\n")); +#endif + if(wParam != VK_SPACE) + bHandled = FALSE; + return 0; + } + + LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnChar\n")); +#endif + if(wParam != VK_SPACE) + bHandled = FALSE; + else + return 0; + // Security + if(!m_wndParent.IsWindowEnabled() || ::GetFocus() != m_hWnd) + return 0; + + // Handle mnemonic press when we have focus + int nBtn = 0; + if(wParam != VK_RETURN && !MapAccelerator((TCHAR)LOWORD(wParam), nBtn)) + { +#if (_WIN32_IE >= 0x0500) + if((TCHAR)LOWORD(wParam) != _chChevronShortcut) +#endif // (_WIN32_IE >= 0x0500) + ::MessageBeep(0); + } + else + { +#if (_WIN32_IE >= 0x0500) + RECT rcClient = { 0 }; + GetClientRect(&rcClient); + RECT rcBtn = { 0 }; + GetItemRect(nBtn, &rcBtn); + TBBUTTON tbb = { 0 }; + GetButton(nBtn, &tbb); + if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0 && rcBtn.right <= rcClient.right) + { +#endif // (_WIN32_IE >= 0x0500) + PostMessage(WM_KEYDOWN, VK_DOWN, 0L); + if(wParam != VK_RETURN) + SetHotItem(nBtn); +#if (_WIN32_IE >= 0x0500) + } + else + { + ::MessageBeep(0); + bHandled = TRUE; + } +#endif // (_WIN32_IE >= 0x0500) + } + return 0; + } + + LRESULT OnSysKeyDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysKeyDown\n")); +#endif + bHandled = FALSE; + return 0; + } + + LRESULT OnSysKeyUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysKeyUp\n")); +#endif + bHandled = FALSE; + return 0; + } + + LRESULT OnSysChar(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysChar\n")); +#endif + bHandled = FALSE; + return 0; + } + + LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + if(m_bAttachedMenu || (m_dwExtendedStyle & CBR_EX_TRANSPARENT)) + { + bHandled = FALSE; + return 0; + } + + CDCHandle dc = (HDC)wParam; + RECT rect = { 0 }; + GetClientRect(&rect); + dc.FillRect(&rect, COLOR_MENU); + + return 1; // don't do the default erase + } + + LRESULT OnInitMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + int nIndex = GetHotItem(); + SendMessage(WM_MENUSELECT, MAKEWPARAM(nIndex, MF_POPUP|MF_HILITE), (LPARAM)m_hMenu); + bHandled = FALSE; + return 1; + } + + LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + if((BOOL)HIWORD(lParam)) // System menu, do nothing + { + bHandled = FALSE; + return 1; + } + + if(!(m_bAttachedMenu || m_bMenuActive)) // Not attached or ours, do nothing + { + bHandled = FALSE; + return 1; + } + +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnInitMenuPopup\n")); +#endif + // forward to the parent or subclassed window, so it can handle update UI + LRESULT lRet = 0; + if(m_bAttachedMenu) + lRet = DefWindowProc(uMsg, wParam, (lParam || m_bContextMenu) ? lParam : GetHotItem()); + else + lRet = m_wndParent.DefWindowProc(uMsg, wParam, (lParam || m_bContextMenu) ? lParam : GetHotItem()); + +#if _WTL_CMDBAR_VISTA_MENUS + // If Vista menus are active, just set bitmaps and return + if(m_bVistaMenus) + { + CMenuHandle menu = (HMENU)wParam; + ATLASSERT(menu.m_hMenu != NULL); + + for(int i = 0; i < menu.GetMenuItemCount(); i++) + { + WORD nID = (WORD)menu.GetMenuItemID(i); + int nIndex = m_arrCommand.Find(nID); + + CMenuItemInfo mii; + mii.fMask = MIIM_BITMAP; + mii.hbmpItem = (m_bImagesVisible && (nIndex != -1)) ? m_arrVistaBitmap[nIndex] : NULL; + menu.SetMenuItemInfo(i, TRUE, &mii); + } + + return lRet; + } +#endif // _WTL_CMDBAR_VISTA_MENUS + + // Convert menu items to ownerdraw, add our data + if(m_bImagesVisible) + { + CMenuHandle menuPopup = (HMENU)wParam; + ATLASSERT(menuPopup.m_hMenu != NULL); + + T* pT = static_cast(this); + pT; // avoid level 4 warning + TCHAR szString[pT->_nMaxMenuItemTextLength]; + BOOL bRet = FALSE; + for(int i = 0; i < menuPopup.GetMenuItemCount(); i++) + { + CMenuItemInfo mii; + mii.cch = pT->_nMaxMenuItemTextLength; + mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE; + mii.dwTypeData = szString; + bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii); + ATLASSERT(bRet); + + if(!(mii.fType & MFT_OWNERDRAW)) // Not already an ownerdraw item + { + mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE; + _MenuItemData* pMI = NULL; + ATLTRY(pMI = new _MenuItemData); + ATLASSERT(pMI != NULL); + if(pMI != NULL) + { + pMI->fType = mii.fType; + pMI->fState = mii.fState; + mii.fType |= MFT_OWNERDRAW; + pMI->iButton = -1; + for(int j = 0; j < m_arrCommand.GetSize(); j++) + { + if(m_arrCommand[j] == mii.wID) + { + pMI->iButton = j; + break; + } + } + int cchLen = lstrlen(szString) + 1; + pMI->lpstrText = NULL; + ATLTRY(pMI->lpstrText = new TCHAR[cchLen]); + ATLASSERT(pMI->lpstrText != NULL); + if(pMI->lpstrText != NULL) + SecureHelper::strcpy_x(pMI->lpstrText, cchLen, szString); + mii.dwItemData = (ULONG_PTR)pMI; + bRet = menuPopup.SetMenuItemInfo(i, TRUE, &mii); + ATLASSERT(bRet); + } + } + } + + // Add it to the list + m_stackMenuHandle.Push(menuPopup.m_hMenu); + } + + return lRet; + } + + LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + if(!m_bAttachedMenu) // Not attached, do nothing, forward to parent + { + m_bPopupItem = (lParam != NULL) && ((HMENU)lParam != m_hMenu) && (HIWORD(wParam) & MF_POPUP); + if(m_wndParent.IsWindow()) + m_wndParent.SendMessage(uMsg, wParam, lParam); + bHandled = FALSE; + return 1; + } + + // Check if a menu is closing, do a cleanup + if(HIWORD(wParam) == 0xFFFF && lParam == NULL) // Menu closing + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnMenuSelect - CLOSING!!!!\n")); +#endif + ATLASSERT(m_stackMenuWnd.GetSize() == 0); + // Restore the menu items to the previous state for all menus that were converted + if(m_bImagesVisible) + { + HMENU hMenu = NULL; + while((hMenu = m_stackMenuHandle.Pop()) != NULL) + { + CMenuHandle menuPopup = hMenu; + ATLASSERT(menuPopup.m_hMenu != NULL); + // Restore state and delete menu item data + BOOL bRet = FALSE; + for(int i = 0; i < menuPopup.GetMenuItemCount(); i++) + { + CMenuItemInfo mii; + mii.fMask = MIIM_DATA | MIIM_TYPE; + bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii); + ATLASSERT(bRet); + + _MenuItemData* pMI = (_MenuItemData*)mii.dwItemData; + if(pMI != NULL && pMI->IsCmdBarMenuItem()) + { + mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE; + mii.fType = pMI->fType; + mii.dwTypeData = pMI->lpstrText; + mii.cch = lstrlen(pMI->lpstrText); + mii.dwItemData = NULL; + + bRet = menuPopup.SetMenuItemInfo(i, TRUE, &mii); + ATLASSERT(bRet); + + delete [] pMI->lpstrText; + pMI->dwMagic = 0x6666; + delete pMI; + } + } + } + } + } + + bHandled = FALSE; + return 1; + } + + LRESULT OnInternalAutoPopup(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + int nIndex = (int)wParam; + T* pT = static_cast(this); + pT->DoPopupMenu(nIndex, false); + return 0; + } + + LRESULT OnInternalGetBar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + // Let's make sure we're not embedded in another process + if((LPVOID)wParam != NULL) + *((DWORD*)wParam) = GetCurrentProcessId(); + if(IsWindowVisible()) + return (LRESULT)static_cast(this); + else + return NULL; + } + + LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { +#ifndef SPI_GETKEYBOARDCUES + const UINT SPI_SETKEYBOARDCUES = 0x100B; +#endif // !SPI_GETKEYBOARDCUES +#ifndef SPI_GETFLATMENU + const UINT SPI_SETFLATMENU = 0x1023; +#endif // !SPI_GETFLATMENU + + if(wParam == SPI_SETNONCLIENTMETRICS || wParam == SPI_SETKEYBOARDCUES || wParam == SPI_SETFLATMENU) + { + T* pT = static_cast(this); + pT->GetSystemSettings(); + } + + return 0; + } + + LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); + + LPWINDOWPOS lpWP = (LPWINDOWPOS)lParam; + int cyMin = ::GetSystemMetrics(SM_CYMENU); + if(lpWP->cy < cyMin) + lpWP->cy = cyMin; + + return lRet; + } + + LRESULT OnMenuChar(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnMenuChar\n")); +#endif + bHandled = TRUE; + T* pT = static_cast(this); + + LRESULT lRet; + if(m_bMenuActive && LOWORD(wParam) != 0x0D) + lRet = 0; + else + lRet = MAKELRESULT(1, 1); + + if(m_bMenuActive && HIWORD(wParam) == MF_POPUP) + { + // Convert character to lower/uppercase and possibly Unicode, using current keyboard layout + TCHAR ch = (TCHAR)LOWORD(wParam); + CMenuHandle menu = (HMENU)lParam; + int nCount = ::GetMenuItemCount(menu); + int nRetCode = MNC_EXECUTE; + BOOL bRet = FALSE; + TCHAR szString[pT->_nMaxMenuItemTextLength]; + WORD wMnem = 0; + bool bFound = false; + for(int i = 0; i < nCount; i++) + { + CMenuItemInfo mii; + mii.cch = pT->_nMaxMenuItemTextLength; + mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE; + mii.dwTypeData = szString; + bRet = menu.GetMenuItemInfo(i, TRUE, &mii); + if(!bRet || (mii.fType & MFT_SEPARATOR)) + continue; + _MenuItemData* pmd = (_MenuItemData*)mii.dwItemData; + if(pmd != NULL && pmd->IsCmdBarMenuItem()) + { + LPTSTR p = pmd->lpstrText; + + if(p != NULL) + { + while(*p && *p != _T('&')) + p = ::CharNext(p); + if(p != NULL && *p) + { + DWORD dwP = MAKELONG(*(++p), 0); + DWORD dwC = MAKELONG(ch, 0); + if(::CharLower((LPTSTR)ULongToPtr(dwP)) == ::CharLower((LPTSTR)ULongToPtr(dwC))) + { + if(!bFound) + { + wMnem = (WORD)i; + bFound = true; + } + else + { + nRetCode = MNC_SELECT; + break; + } + } + } + } + } + } + if(bFound) + { + if(nRetCode == MNC_EXECUTE) + { + PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L); + pT->GiveFocusBack(); + } + bHandled = TRUE; + lRet = MAKELRESULT(wMnem, nRetCode); + } + } + else if(!m_bMenuActive) + { + int nBtn = 0; + if(!MapAccelerator((TCHAR)LOWORD(wParam), nBtn)) + { + bHandled = FALSE; + PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L); + pT->GiveFocusBack(); + +#if (_WIN32_IE >= 0x0500) + // check if we should display chevron menu + if((TCHAR)LOWORD(wParam) == pT->_chChevronShortcut) + { + if(pT->DisplayChevronMenu()) + bHandled = TRUE; + } +#endif // (_WIN32_IE >= 0x0500) + } + else if(m_wndParent.IsWindowEnabled()) + { +#if (_WIN32_IE >= 0x0500) + RECT rcClient = { 0 }; + GetClientRect(&rcClient); + RECT rcBtn = { 0 }; + GetItemRect(nBtn, &rcBtn); + TBBUTTON tbb = { 0 }; + GetButton(nBtn, &tbb); + if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0 && rcBtn.right <= rcClient.right) + { +#endif // (_WIN32_IE >= 0x0500) + if(m_bUseKeyboardCues && !m_bShowKeyboardCues) + { + m_bAllowKeyboardCues = true; + ShowKeyboardCues(true); + } + pT->TakeFocus(); + PostMessage(WM_KEYDOWN, VK_DOWN, 0L); + SetHotItem(nBtn); +#if (_WIN32_IE >= 0x0500) + } + else + { + ::MessageBeep(0); + } +#endif // (_WIN32_IE >= 0x0500) + } + } + + return lRet; + } + + LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + LPDRAWITEMSTRUCT lpDrawItemStruct = (LPDRAWITEMSTRUCT)lParam; + _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData; + if(lpDrawItemStruct->CtlType == ODT_MENU && pmd != NULL && pmd->IsCmdBarMenuItem()) + { + T* pT = static_cast(this); + pT->DrawItem(lpDrawItemStruct); + } + else + { + bHandled = FALSE; + } + return (LRESULT)TRUE; + } + + LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + LPMEASUREITEMSTRUCT lpMeasureItemStruct = (LPMEASUREITEMSTRUCT)lParam; + _MenuItemData* pmd = (_MenuItemData*)lpMeasureItemStruct->itemData; + if(lpMeasureItemStruct->CtlType == ODT_MENU && pmd != NULL && pmd->IsCmdBarMenuItem()) + { + T* pT = static_cast(this); + pT->MeasureItem(lpMeasureItemStruct); + } + else + { + bHandled = FALSE; + } + return (LRESULT)TRUE; + } + +// API message handlers + LRESULT OnAPIGetMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return (LRESULT)m_hMenu; + } + + LRESULT OnAPITrackPopupMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) + { + if(lParam == NULL) + return FALSE; + LPCBRPOPUPMENU lpCBRPopupMenu = (LPCBRPOPUPMENU)lParam; + if(lpCBRPopupMenu->cbSize != sizeof(CBRPOPUPMENU)) + return FALSE; + + T* pT = static_cast(this); + return pT->TrackPopupMenu(lpCBRPopupMenu->hMenu, lpCBRPopupMenu->uFlags, lpCBRPopupMenu->x, lpCBRPopupMenu->y, lpCBRPopupMenu->lptpm); + } + + LRESULT OnAPIGetCmdBar(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return (LRESULT)m_hWnd; + } + +// Parent window message handlers + LRESULT OnParentHotItemChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) + { + LPNMTBHOTITEM lpNMHT = (LPNMTBHOTITEM)pnmh; + + // Check if this comes from us + if(pnmh->hwndFrom != m_hWnd) + { + bHandled = FALSE; + return 0; + } + + bool bBlockTracking = false; + if((m_dwExtendedStyle & CBR_EX_TRACKALWAYS) == 0) + { + DWORD dwProcessID; + ::GetWindowThreadProcessId(::GetActiveWindow(), &dwProcessID); + bBlockTracking = (::GetCurrentProcessId() != dwProcessID); + } + + if((!m_wndParent.IsWindowEnabled() || bBlockTracking) && (lpNMHT->dwFlags & HICF_MOUSE)) + { + return 1; + } + else + { +#ifndef HICF_LMOUSE + const DWORD HICF_LMOUSE = 0x00000080; // left mouse button selected +#endif + bHandled = FALSE; + + // Send WM_MENUSELECT to the app if it needs to display a status text + if(!(lpNMHT->dwFlags & HICF_MOUSE) + && !(lpNMHT->dwFlags & HICF_ACCELERATOR) + && !(lpNMHT->dwFlags & HICF_LMOUSE)) + { + if(lpNMHT->dwFlags & HICF_ENTERING) + m_wndParent.SendMessage(WM_MENUSELECT, 0, (LPARAM)m_hMenu); + if(lpNMHT->dwFlags & HICF_LEAVING) + m_wndParent.SendMessage(WM_MENUSELECT, MAKEWPARAM(0, 0xFFFF), NULL); + } + + return 0; + } + } + + LRESULT OnParentDropDown(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) + { + // Check if this comes from us + if(pnmh->hwndFrom != m_hWnd) + { + bHandled = FALSE; + return 1; + } + + T* pT = static_cast(this); + if(::GetFocus() != m_hWnd) + pT->TakeFocus(); + LPNMTOOLBAR pNMToolBar = (LPNMTOOLBAR)pnmh; + int nIndex = CommandToIndex(pNMToolBar->iItem); + m_bContextMenu = false; + m_bEscapePressed = false; + pT->DoPopupMenu(nIndex, true); + + return TBDDRET_DEFAULT; + } + + LRESULT OnParentInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + return OnInitMenuPopup(uMsg, wParam, lParam, bHandled); + } + + LRESULT OnParentInternalGetBar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + return OnInternalGetBar(uMsg, wParam, lParam, bHandled); + } + + LRESULT OnParentSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + bHandled = FALSE; + if((m_uSysKey == VK_MENU + || (m_uSysKey == VK_F10 && !(::GetKeyState(VK_SHIFT) & 0x80)) + || m_uSysKey == VK_SPACE) + && wParam == SC_KEYMENU) + { + T* pT = static_cast(this); + if(::GetFocus() == m_hWnd) + { + pT->GiveFocusBack(); // exit menu "loop" + PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L); + } + else if(m_uSysKey != VK_SPACE && !m_bSkipMsg) + { + if(m_bUseKeyboardCues && !m_bShowKeyboardCues && m_bAllowKeyboardCues) + ShowKeyboardCues(true); + + pT->TakeFocus(); // enter menu "loop" + bHandled = TRUE; + } + else if(m_uSysKey != VK_SPACE) + { + bHandled = TRUE; + } + } + m_bSkipMsg = false; + return 0; + } + + LRESULT OnParentAPIGetMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + return OnAPIGetMenu(uMsg, wParam, lParam, bHandled); + } + + LRESULT OnParentMenuChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + return OnMenuChar(uMsg, wParam, lParam, bHandled); + } + + LRESULT OnParentAPITrackPopupMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + return OnAPITrackPopupMenu(uMsg, wParam, lParam, bHandled); + } + + LRESULT OnParentAPIGetCmdBar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + return OnAPIGetCmdBar(uMsg, wParam, lParam, bHandled); + } + + LRESULT OnParentSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + OnSettingChange(uMsg, wParam, lParam, bHandled); + bHandled = FALSE; + return 1; + } + + LRESULT OnParentDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + return OnDrawItem(uMsg, wParam, lParam, bHandled); + } + + LRESULT OnParentMeasureItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + return OnMeasureItem(uMsg, wParam, lParam, bHandled); + } + + LRESULT OnParentActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + m_bParentActive = (LOWORD(wParam) != WA_INACTIVE); + if(!m_bParentActive && m_bUseKeyboardCues && m_bShowKeyboardCues) + { + ShowKeyboardCues(false); // this will repaint our window + } + else + { + Invalidate(); + UpdateWindow(); + } + bHandled = FALSE; + return 1; + } + + LRESULT OnParentCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) + { + LRESULT lRet = CDRF_DODEFAULT; + bHandled = FALSE; + if(pnmh->hwndFrom == m_hWnd) + { + LPNMTBCUSTOMDRAW lpTBCustomDraw = (LPNMTBCUSTOMDRAW)pnmh; + if(lpTBCustomDraw->nmcd.dwDrawStage == CDDS_PREPAINT) + { + lRet = CDRF_NOTIFYITEMDRAW; + bHandled = TRUE; + } + else if(lpTBCustomDraw->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) + { + if(m_bFlatMenus) + { +#ifndef COLOR_MENUHILIGHT + const int COLOR_MENUHILIGHT = 29; +#endif // !COLOR_MENUHILIGHT + bool bDisabled = ((lpTBCustomDraw->nmcd.uItemState & CDIS_DISABLED) == CDIS_DISABLED); + if(!bDisabled && ((lpTBCustomDraw->nmcd.uItemState & CDIS_HOT) == CDIS_HOT || + (lpTBCustomDraw->nmcd.uItemState & CDIS_SELECTED) == CDIS_SELECTED)) + { + ::FillRect(lpTBCustomDraw->nmcd.hdc, &lpTBCustomDraw->nmcd.rc, ::GetSysColorBrush(COLOR_MENUHILIGHT)); + ::FrameRect(lpTBCustomDraw->nmcd.hdc, &lpTBCustomDraw->nmcd.rc, ::GetSysColorBrush(COLOR_HIGHLIGHT)); + lpTBCustomDraw->clrText = ::GetSysColor(m_bParentActive ? COLOR_HIGHLIGHTTEXT : COLOR_GRAYTEXT); + } + else if(bDisabled || !m_bParentActive) + { + lpTBCustomDraw->clrText = ::GetSysColor(COLOR_GRAYTEXT); + } + CDCHandle dc = lpTBCustomDraw->nmcd.hdc; + dc.SetTextColor(lpTBCustomDraw->clrText); + dc.SetBkMode(lpTBCustomDraw->nStringBkMode); + HFONT hFont = GetFont(); + HFONT hFontOld = NULL; + if(hFont != NULL) + hFontOld = dc.SelectFont(hFont); + const int cchText = 200; + TCHAR szText[cchText] = { 0 }; + TBBUTTONINFO tbbi = { 0 }; + tbbi.cbSize = sizeof(TBBUTTONINFO); + tbbi.dwMask = TBIF_TEXT; + tbbi.pszText = szText; + tbbi.cchText = cchText; + GetButtonInfo((int)lpTBCustomDraw->nmcd.dwItemSpec, &tbbi); + dc.DrawText(szText, -1, &lpTBCustomDraw->nmcd.rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER | (m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX)); + if(hFont != NULL) + dc.SelectFont(hFontOld); + lRet = CDRF_SKIPDEFAULT; + bHandled = TRUE; + } + else if(!m_bParentActive) + { + lpTBCustomDraw->clrText = ::GetSysColor(COLOR_GRAYTEXT); + bHandled = TRUE; + } + } + } + return lRet; + } + +// Message hook handlers + LRESULT OnHookMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + static POINT s_point = { -1, -1 }; + DWORD dwPoint = ::GetMessagePos(); + POINT point = { GET_X_LPARAM(dwPoint), GET_Y_LPARAM(dwPoint) }; + + bHandled = FALSE; + if(m_bMenuActive) + { + if(::WindowFromPoint(point) == m_hWnd) + { + ScreenToClient(&point); + int nHit = HitTest(&point); + + if((point.x != s_point.x || point.y != s_point.y) && nHit >= 0 && nHit < ::GetMenuItemCount(m_hMenu) && nHit != m_nPopBtn && m_nPopBtn != -1) + { + TBBUTTON tbb = { 0 }; + GetButton(nHit, &tbb); + if((tbb.fsState & TBSTATE_ENABLED) != 0) + { + m_nNextPopBtn = nHit | 0xFFFF0000; + HWND hWndMenu = m_stackMenuWnd.GetCurrent(); + ATLASSERT(hWndMenu != NULL); + + // this one is needed to close a menu if mouse button was down + ::PostMessage(hWndMenu, WM_LBUTTONUP, 0, MAKELPARAM(point.x, point.y)); + // this one closes a popup menu + ::PostMessage(hWndMenu, WM_KEYDOWN, VK_ESCAPE, 0L); + + bHandled = TRUE; + } + } + } + } + else + { + ScreenToClient(&point); + } + + s_point = point; + return 0; + } + + LRESULT OnHookSysKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + bHandled = FALSE; +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSKEYDOWN (0x%2.2X)\n"), wParam); +#endif + + if(wParam == VK_MENU && m_bParentActive && m_bUseKeyboardCues && !m_bShowKeyboardCues && m_bAllowKeyboardCues) + ShowKeyboardCues(true); + + if(wParam != VK_SPACE && !m_bMenuActive && ::GetFocus() == m_hWnd) + { + m_bAllowKeyboardCues = false; + PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L); + T* pT = static_cast(this); + pT->GiveFocusBack(); + m_bSkipMsg = true; + } + else + { + if(wParam == VK_SPACE && m_bUseKeyboardCues && m_bShowKeyboardCues) + { + m_bAllowKeyboardCues = true; + ShowKeyboardCues(false); + } + m_uSysKey = (UINT)wParam; + } + return 0; + } + + LRESULT OnHookSysKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + if(!m_bAllowKeyboardCues) + m_bAllowKeyboardCues = true; + bHandled = FALSE; + wParam; +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSKEYUP (0x%2.2X)\n"), wParam); +#endif + return 0; + } + + LRESULT OnHookSysChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + bHandled = FALSE; +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSCHAR (0x%2.2X)\n"), wParam); +#endif + + if(!m_bMenuActive && m_hWndHook != m_hWnd && wParam != VK_SPACE) + bHandled = TRUE; + return 0; + } + + LRESULT OnHookKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_KEYDOWN (0x%2.2X)\n"), wParam); +#endif + bHandled = FALSE; + T* pT = static_cast(this); + + if(wParam == VK_ESCAPE && m_stackMenuWnd.GetSize() <= 1) + { + if(m_bMenuActive && !m_bContextMenu) + { + int nHot = GetHotItem(); + if(nHot == -1) + nHot = m_nPopBtn; + if(nHot == -1) + nHot = 0; + SetHotItem(nHot); + bHandled = TRUE; + pT->TakeFocus(); + m_bEscapePressed = true; // To keep focus + m_bSkipPostDown = false; + } + else if(::GetFocus() == m_hWnd && m_wndParent.IsWindow()) + { + SetHotItem(-1); + pT->GiveFocusBack(); + bHandled = TRUE; + } + } + else if(wParam == VK_RETURN || wParam == VK_UP || wParam == VK_DOWN) + { + if(!m_bMenuActive && ::GetFocus() == m_hWnd && m_wndParent.IsWindow()) + { + int nHot = GetHotItem(); + if(nHot != -1) + { + if(wParam != VK_RETURN) + { + if(!m_bSkipPostDown) + { +// IE4 only: WM_KEYDOWN doesn't generate TBN_DROPDOWN, we need to simulate a mouse click +#if (_WIN32_IE < 0x0500) + DWORD dwMajor = 0, dwMinor = 0; + ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor); + if(dwMajor <= 4 || (dwMajor == 5 && dwMinor < 80)) + { + RECT rect; + GetItemRect(nHot, &rect); + PostMessage(WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(rect.left, rect.top)); + } +#endif // (_WIN32_IE < 0x0500) + PostMessage(WM_KEYDOWN, VK_DOWN, 0L); + m_bSkipPostDown = true; + } + else + { + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - skipping posting another VK_DOWN\n")); + m_bSkipPostDown = false; + } + } + } + else + { + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Can't find hot button\n")); + } + } + if(wParam == VK_RETURN && m_bMenuActive) + { + PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L); + m_nNextPopBtn = -1; + pT->GiveFocusBack(); + } + } + else if(wParam == VK_LEFT || wParam == VK_RIGHT) + { + WPARAM wpNext = m_bLayoutRTL ? VK_LEFT : VK_RIGHT; + WPARAM wpPrev = m_bLayoutRTL ? VK_RIGHT : VK_LEFT; + + if(m_bMenuActive && !m_bContextMenu && !(wParam == wpNext && m_bPopupItem)) + { + bool bAction = false; + if(wParam == wpPrev && s_pCurrentBar->m_stackMenuWnd.GetSize() == 1) + { + m_nNextPopBtn = pT->GetPreviousMenuItem(m_nPopBtn); + if(m_nNextPopBtn != -1) + bAction = true; + } + else if(wParam == wpNext) + { + m_nNextPopBtn = pT->GetNextMenuItem(m_nPopBtn); + if(m_nNextPopBtn != -1) + bAction = true; + } + HWND hWndMenu = m_stackMenuWnd.GetCurrent(); + ATLASSERT(hWndMenu != NULL); + + // Close the popup menu + if(bAction) + { + ::PostMessage(hWndMenu, WM_KEYDOWN, VK_ESCAPE, 0L); + if(wParam == wpNext) + { + int cItem = m_stackMenuWnd.GetSize() - 1; + while(cItem >= 0) + { + hWndMenu = m_stackMenuWnd[cItem]; + if(hWndMenu != NULL) + ::PostMessage(hWndMenu, WM_KEYDOWN, VK_ESCAPE, 0L); + cItem--; + } + } +#if (_WIN32_IE >= 0x0500) + if(m_nNextPopBtn == -2) + { + m_nNextPopBtn = -1; + pT->DisplayChevronMenu(); + } +#endif // (_WIN32_IE >= 0x0500) + bHandled = TRUE; + } + } + } + return 0; + } + + LRESULT OnHookNextMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_NEXTMENU\n")); +#endif + bHandled = FALSE; + return 1; + } + + LRESULT OnHookChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_CHAR (0x%2.2X)\n"), wParam); +#endif + bHandled = (wParam == VK_ESCAPE); + return 0; + } + +// Implementation - ownerdraw overrideables and helpers + void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) + { + T* pT = static_cast(this); + if(m_bFlatMenus) + pT->DrawItemFlat(lpDrawItemStruct); + else + pT->DrawItem3D(lpDrawItemStruct); + + } + + void DrawItem3D(LPDRAWITEMSTRUCT lpDrawItemStruct) + { + _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData; + CDCHandle dc = lpDrawItemStruct->hDC; + const RECT& rcItem = lpDrawItemStruct->rcItem; + T* pT = static_cast(this); + + if(pmd->fType & MFT_SEPARATOR) + { + // draw separator + RECT rc = rcItem; + rc.top += (rc.bottom - rc.top) / 2; // vertical center + dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP); // draw separator line + } + else // not a separator + { + BOOL bDisabled = lpDrawItemStruct->itemState & ODS_GRAYED; + BOOL bSelected = lpDrawItemStruct->itemState & ODS_SELECTED; + BOOL bChecked = lpDrawItemStruct->itemState & ODS_CHECKED; + BOOL bHasImage = FALSE; + + if(LOWORD(lpDrawItemStruct->itemID) == (WORD)-1) + bSelected = FALSE; + RECT rcButn = { rcItem.left, rcItem.top, rcItem.left + m_szButton.cx, rcItem.top + m_szButton.cy }; // button rect + ::OffsetRect(&rcButn, 0, ((rcItem.bottom - rcItem.top) - (rcButn.bottom - rcButn.top)) / 2); // center vertically + + int iButton = pmd->iButton; + if(iButton >= 0) + { + bHasImage = TRUE; + + // calc drawing point + SIZE sz = { rcButn.right - rcButn.left - m_szBitmap.cx, rcButn.bottom - rcButn.top - m_szBitmap.cy }; + sz.cx /= 2; + sz.cy /= 2; + POINT point = { rcButn.left + sz.cx, rcButn.top + sz.cy }; + + // fill background depending on state + if(!bChecked || (bSelected && !bDisabled)) + { + if(!bDisabled) + dc.FillRect(&rcButn, (bChecked && !bSelected) ? COLOR_3DLIGHT : COLOR_MENU); + else + dc.FillRect(&rcButn, COLOR_MENU); + } + else + { + COLORREF crTxt = dc.SetTextColor(::GetSysColor(COLOR_BTNFACE)); + COLORREF crBk = dc.SetBkColor(::GetSysColor(COLOR_BTNHILIGHT)); + CBrush hbr(CDCHandle::GetHalftoneBrush()); + dc.SetBrushOrg(rcButn.left, rcButn.top); + dc.FillRect(&rcButn, hbr); + dc.SetTextColor(crTxt); + dc.SetBkColor(crBk); + } + + // draw disabled or normal + if(!bDisabled) + { + // draw pushed-in or popped-out edge + if(bSelected || bChecked) + { + RECT rc2 = rcButn; + dc.DrawEdge(&rc2, bChecked ? BDR_SUNKENOUTER : BDR_RAISEDINNER, BF_RECT); + } + // draw the image + ::ImageList_Draw(m_hImageList, iButton, dc, point.x, point.y, ILD_TRANSPARENT); + } + else + { + HBRUSH hBrushBackground = bChecked ? NULL : ::GetSysColorBrush(COLOR_MENU); + pT->DrawBitmapDisabled(dc, iButton, point, hBrushBackground); + } + } + else + { + // no image - look for custom checked/unchecked bitmaps + CMenuItemInfo info; + info.fMask = MIIM_CHECKMARKS | MIIM_TYPE; + ::GetMenuItemInfo((HMENU)lpDrawItemStruct->hwndItem, lpDrawItemStruct->itemID, MF_BYCOMMAND, &info); + if(bChecked || info.hbmpUnchecked != NULL) + { + BOOL bRadio = ((info.fType & MFT_RADIOCHECK) != 0); + bHasImage = pT->DrawCheckmark(dc, rcButn, bSelected, bDisabled, bRadio, bChecked ? info.hbmpChecked : info.hbmpUnchecked); + } + } + + // draw item text + int cxButn = m_szButton.cx; + COLORREF colorBG = ::GetSysColor(bSelected ? COLOR_HIGHLIGHT : COLOR_MENU); + if(bSelected || lpDrawItemStruct->itemAction == ODA_SELECT) + { + RECT rcBG = rcItem; + if(bHasImage) + rcBG.left += cxButn + s_kcxGap; + dc.FillRect(&rcBG, bSelected ? COLOR_HIGHLIGHT : COLOR_MENU); + } + + // calc text rectangle and colors + RECT rcText = rcItem; + rcText.left += cxButn + s_kcxGap + s_kcxTextMargin; + rcText.right -= cxButn; + dc.SetBkMode(TRANSPARENT); + COLORREF colorText = ::GetSysColor(bDisabled ? (bSelected ? COLOR_GRAYTEXT : COLOR_3DSHADOW) : (bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT)); + + // font already selected by Windows + if(bDisabled && (!bSelected || colorText == colorBG)) + { + // disabled - draw shadow text shifted down and right 1 pixel (unles selected) + RECT rcDisabled = rcText; + ::OffsetRect(&rcDisabled, 1, 1); + pT->DrawMenuText(dc, rcDisabled, pmd->lpstrText, ::GetSysColor(COLOR_3DHILIGHT)); + } + pT->DrawMenuText(dc, rcText, pmd->lpstrText, colorText); // finally! + } + } + + void DrawItemFlat(LPDRAWITEMSTRUCT lpDrawItemStruct) + { + _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData; + CDCHandle dc = lpDrawItemStruct->hDC; + const RECT& rcItem = lpDrawItemStruct->rcItem; + T* pT = static_cast(this); + +#ifndef COLOR_MENUHILIGHT + const int COLOR_MENUHILIGHT = 29; +#endif // !COLOR_MENUHILIGHT + + BOOL bDisabled = lpDrawItemStruct->itemState & ODS_GRAYED; + BOOL bSelected = lpDrawItemStruct->itemState & ODS_SELECTED; + BOOL bChecked = lpDrawItemStruct->itemState & ODS_CHECKED; + + // paint background + if(bSelected || lpDrawItemStruct->itemAction == ODA_SELECT) + { + if(bSelected) + { + dc.FillRect(&rcItem, ::GetSysColorBrush(COLOR_MENUHILIGHT)); + dc.FrameRect(&rcItem, ::GetSysColorBrush(COLOR_HIGHLIGHT)); + } + else + { + dc.FillRect(&rcItem, ::GetSysColorBrush(COLOR_MENU)); + } + } + + if(pmd->fType & MFT_SEPARATOR) + { + // draw separator + RECT rc = rcItem; + rc.top += (rc.bottom - rc.top) / 2; // vertical center + dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP); // draw separator line + } + else // not a separator + { + if(LOWORD(lpDrawItemStruct->itemID) == (WORD)-1) + bSelected = FALSE; + RECT rcButn = { rcItem.left, rcItem.top, rcItem.left + m_szButton.cx, rcItem.top + m_szButton.cy }; // button rect + ::OffsetRect(&rcButn, 0, ((rcItem.bottom - rcItem.top) - (rcButn.bottom - rcButn.top)) / 2); // center vertically + + // draw background and border for checked items + if(bChecked) + { + RECT rcCheck = rcButn; + ::InflateRect(&rcCheck, -1, -1); + if(bSelected) + dc.FillRect(&rcCheck, ::GetSysColorBrush(COLOR_MENU)); + dc.FrameRect(&rcCheck, ::GetSysColorBrush(COLOR_HIGHLIGHT)); + } + + int iButton = pmd->iButton; + if(iButton >= 0) + { + // calc drawing point + SIZE sz = { rcButn.right - rcButn.left - m_szBitmap.cx, rcButn.bottom - rcButn.top - m_szBitmap.cy }; + sz.cx /= 2; + sz.cy /= 2; + POINT point = { rcButn.left + sz.cx, rcButn.top + sz.cy }; + + // draw disabled or normal + if(!bDisabled) + { + ::ImageList_Draw(m_hImageList, iButton, dc, point.x, point.y, ILD_TRANSPARENT); + } + else + { + HBRUSH hBrushBackground = ::GetSysColorBrush((bSelected && !(bDisabled && bChecked)) ? COLOR_MENUHILIGHT : COLOR_MENU); + HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW); + pT->DrawBitmapDisabled(dc, iButton, point, hBrushBackground, hBrushBackground, hBrushDisabledImage); + } + } + else + { + // no image - look for custom checked/unchecked bitmaps + CMenuItemInfo info; + info.fMask = MIIM_CHECKMARKS | MIIM_TYPE; + ::GetMenuItemInfo((HMENU)lpDrawItemStruct->hwndItem, lpDrawItemStruct->itemID, MF_BYCOMMAND, &info); + if(bChecked || info.hbmpUnchecked != NULL) + { + BOOL bRadio = ((info.fType & MFT_RADIOCHECK) != 0); + pT->DrawCheckmark(dc, rcButn, bSelected, bDisabled, bRadio, bChecked ? info.hbmpChecked : info.hbmpUnchecked); + } + } + + // draw item text + int cxButn = m_szButton.cx; + // calc text rectangle and colors + RECT rcText = rcItem; + rcText.left += cxButn + s_kcxGap + s_kcxTextMargin; + rcText.right -= cxButn; + dc.SetBkMode(TRANSPARENT); + COLORREF colorText = ::GetSysColor(bDisabled ? (bSelected ? COLOR_GRAYTEXT : COLOR_3DSHADOW) : (bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT)); + + pT->DrawMenuText(dc, rcText, pmd->lpstrText, colorText); // finally! + } + } + + void DrawMenuText(CDCHandle& dc, RECT& rc, LPCTSTR lpstrText, COLORREF color) + { + int nTab = -1; + for(int i = 0; i < lstrlen(lpstrText); i++) + { + if(lpstrText[i] == _T('\t')) + { + nTab = i; + break; + } + } + dc.SetTextColor(color); + dc.DrawText(lpstrText, nTab, &rc, DT_SINGLELINE | DT_LEFT | DT_VCENTER | (m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX)); + if(nTab != -1) + dc.DrawText(&lpstrText[nTab + 1], -1, &rc, DT_SINGLELINE | DT_RIGHT | DT_VCENTER | (m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX)); + } + + void DrawBitmapDisabled(CDCHandle& dc, int nImage, POINT point, + HBRUSH hBrushBackground = ::GetSysColorBrush(COLOR_3DFACE), + HBRUSH hBrush3DEffect = ::GetSysColorBrush(COLOR_3DHILIGHT), + HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW)) + { +#if (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501) + if(m_bAlphaImages) + { + IMAGELISTDRAWPARAMS ildp = { 0 }; + ildp.cbSize = sizeof(IMAGELISTDRAWPARAMS); + ildp.himl = m_hImageList; + ildp.i = nImage; + ildp.hdcDst = dc; + ildp.x = point.x; + ildp.y = point.y; + ildp.cx = 0; + ildp.cy = 0; + ildp.xBitmap = 0; + ildp.yBitmap = 0; + ildp.fStyle = ILD_TRANSPARENT; + ildp.fState = ILS_SATURATE; + ildp.Frame = 0; + ::ImageList_DrawIndirect(&ildp); + } + else +#endif // (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501) + { + // create memory DC + CDC dcMem; + dcMem.CreateCompatibleDC(dc); + // create mono or color bitmap + CBitmap bmp; + bmp.CreateCompatibleBitmap(dc, m_szBitmap.cx, m_szBitmap.cy); + ATLASSERT(bmp.m_hBitmap != NULL); + // draw image into memory DC--fill BG white first + HBITMAP hBmpOld = dcMem.SelectBitmap(bmp); + dcMem.PatBlt(0, 0, m_szBitmap.cx, m_szBitmap.cy, WHITENESS); + // If white is the text color, we can't use the normal painting since + // it would blend with the WHITENESS, but the mask is OK + UINT uDrawStyle = (::GetSysColor(COLOR_BTNTEXT) == RGB(255, 255, 255)) ? ILD_MASK : ILD_NORMAL; + ::ImageList_Draw(m_hImageList, nImage, dcMem, 0, 0, uDrawStyle); + dc.DitherBlt(point.x, point.y, m_szBitmap.cx, m_szBitmap.cy, dcMem, NULL, 0, 0, hBrushBackground, hBrush3DEffect, hBrushDisabledImage); + dcMem.SelectBitmap(hBmpOld); // restore + } + } + + // old name + BOOL Draw3DCheckmark(CDCHandle& dc, const RECT& rc, BOOL bSelected, BOOL bDisabled, BOOL bRadio, HBITMAP hBmpCheck) + { + return DrawCheckmark(dc, rc, bSelected, bDisabled, bRadio, hBmpCheck); + } + + BOOL DrawCheckmark(CDCHandle& dc, const RECT& rc, BOOL bSelected, BOOL bDisabled, BOOL bRadio, HBITMAP hBmpCheck) + { + // get checkmark bitmap, if none, use Windows standard + SIZE size = { 0, 0 }; + CBitmapHandle bmp = hBmpCheck; + if(hBmpCheck != NULL) + { + bmp.GetSize(size); + } + else + { + size.cx = ::GetSystemMetrics(SM_CXMENUCHECK); + size.cy = ::GetSystemMetrics(SM_CYMENUCHECK); + bmp.CreateCompatibleBitmap(dc, size.cx, size.cy); + ATLASSERT(bmp.m_hBitmap != NULL); + } + // center bitmap in caller's rectangle + RECT rcDest = rc; + if((rc.right - rc.left) > size.cx) + { + rcDest.left = rc.left + (rc.right - rc.left - size.cx) / 2; + rcDest.right = rcDest.left + size.cx; + } + if((rc.bottom - rc.top) > size.cy) + { + rcDest.top = rc.top + (rc.bottom - rc.top - size.cy) / 2; + rcDest.bottom = rcDest.top + size.cy; + } + // paint background + if(!m_bFlatMenus) + { + if(bSelected && !bDisabled) + { + dc.FillRect(&rcDest, COLOR_MENU); + } + else + { + COLORREF clrTextOld = dc.SetTextColor(::GetSysColor(COLOR_BTNFACE)); + COLORREF clrBkOld = dc.SetBkColor(::GetSysColor(COLOR_BTNHILIGHT)); + CBrush hbr(CDCHandle::GetHalftoneBrush()); + dc.SetBrushOrg(rcDest.left, rcDest.top); + dc.FillRect(&rcDest, hbr); + dc.SetTextColor(clrTextOld); + dc.SetBkColor(clrBkOld); + } + } + + // create source image + CDC dcSource; + dcSource.CreateCompatibleDC(dc); + HBITMAP hBmpOld = dcSource.SelectBitmap(bmp); + // set colors + const COLORREF clrBlack = RGB(0, 0, 0); + const COLORREF clrWhite = RGB(255, 255, 255); + COLORREF clrTextOld = dc.SetTextColor(clrBlack); + COLORREF clrBkOld = dc.SetBkColor(clrWhite); + // create mask + CDC dcMask; + dcMask.CreateCompatibleDC(dc); + CBitmap bmpMask; + bmpMask.CreateBitmap(size.cx, size.cy, 1, 1, NULL); + HBITMAP hBmpOld1 = dcMask.SelectBitmap(bmpMask); + + // draw the checkmark transparently + int cx = rcDest.right - rcDest.left; + int cy = rcDest.bottom - rcDest.top; + if(hBmpCheck != NULL) + { + // build mask based on transparent color + dcSource.SetBkColor(m_clrMask); + dcMask.SetBkColor(clrBlack); + dcMask.SetTextColor(clrWhite); + dcMask.BitBlt(0, 0, size.cx, size.cy, dcSource, 0, 0, SRCCOPY); + // draw bitmap using the mask + dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, SRCINVERT); + dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMask, 0, 0, SRCAND); + dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, SRCINVERT); + } + else + { + const DWORD ROP_DSno = 0x00BB0226L; + const DWORD ROP_DSa = 0x008800C6L; + const DWORD ROP_DSo = 0x00EE0086L; + const DWORD ROP_DSna = 0x00220326L; + + // draw mask + RECT rcSource = { 0, 0, min(size.cx, rc.right - rc.left), min(size.cy, rc.bottom - rc.top) }; + dcMask.DrawFrameControl(&rcSource, DFC_MENU, bRadio ? DFCS_MENUBULLET : DFCS_MENUCHECK); + + // draw shadow if disabled + if(!m_bFlatMenus && bDisabled) + { + // offset by one pixel + int x = rcDest.left + 1; + int y = rcDest.top + 1; + // paint source bitmap + const int nColor = COLOR_3DHILIGHT; + dcSource.FillRect(&rcSource, nColor); + // draw checkmark - special case black and white colors + COLORREF clrCheck = ::GetSysColor(nColor); + if(clrCheck == clrWhite) + { + dc.BitBlt(x, y, cx, cy, dcMask, 0, 0, ROP_DSno); + dc.BitBlt(x, y, cx, cy, dcSource, 0, 0, ROP_DSa); + } + else + { + if(clrCheck != clrBlack) + { + ATLASSERT(dcSource.GetTextColor() == clrBlack); + ATLASSERT(dcSource.GetBkColor() == clrWhite); + dcSource.BitBlt(0, 0, size.cx, size.cy, dcMask, 0, 0, ROP_DSna); + } + dc.BitBlt(x, y, cx, cy, dcMask, 0, 0, ROP_DSa); + dc.BitBlt(x, y, cx, cy, dcSource, 0, 0, ROP_DSo); + } + } + + // paint source bitmap + const int nColor = bDisabled ? COLOR_BTNSHADOW : COLOR_MENUTEXT; + dcSource.FillRect(&rcSource, nColor); + // draw checkmark - special case black and white colors + COLORREF clrCheck = ::GetSysColor(nColor); + if(clrCheck == clrWhite) + { + dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMask, 0, 0, ROP_DSno); + dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, ROP_DSa); + } + else + { + if(clrCheck != clrBlack) + { + ATLASSERT(dcSource.GetTextColor() == clrBlack); + ATLASSERT(dcSource.GetBkColor() == clrWhite); + dcSource.BitBlt(0, 0, size.cx, size.cy, dcMask, 0, 0, ROP_DSna); + } + dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMask, 0, 0, ROP_DSa); + dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, ROP_DSo); + } + } + // restore all + dc.SetTextColor(clrTextOld); + dc.SetBkColor(clrBkOld); + dcSource.SelectBitmap(hBmpOld); + dcMask.SelectBitmap(hBmpOld1); + if(hBmpCheck == NULL) + bmp.DeleteObject(); + // draw pushed-in hilight + if(!m_bFlatMenus && !bDisabled) + { + if(rc.right - rc.left > size.cx) + ::InflateRect(&rcDest, 1,1); // inflate checkmark by one pixel all around + dc.DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT); + } + + return TRUE; + } + + void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) + { + _MenuItemData* pmd = (_MenuItemData*)lpMeasureItemStruct->itemData; + + if(pmd->fType & MFT_SEPARATOR) // separator - use half system height and zero width + { + lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_CYMENU) / 2; + lpMeasureItemStruct->itemWidth = 0; + } + else + { + // compute size of text - use DrawText with DT_CALCRECT + CWindowDC dc(NULL); + CFont fontBold; + HFONT hOldFont = NULL; + if(pmd->fState & MFS_DEFAULT) + { + // need bold version of font + LOGFONT lf = { 0 }; + m_fontMenu.GetLogFont(lf); + lf.lfWeight += 200; + fontBold.CreateFontIndirect(&lf); + ATLASSERT(fontBold.m_hFont != NULL); + hOldFont = dc.SelectFont(fontBold); + } + else + { + hOldFont = dc.SelectFont(m_fontMenu); + } + + RECT rcText = { 0, 0, 0, 0 }; + dc.DrawText(pmd->lpstrText, -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT); + int cx = rcText.right - rcText.left; + dc.SelectFont(hOldFont); + + LOGFONT lf = { 0 }; + m_fontMenu.GetLogFont(lf); + int cy = lf.lfHeight; + if(cy < 0) + cy = -cy; + const int cyMargin = 8; + cy += cyMargin; + + // height of item is the bigger of these two + lpMeasureItemStruct->itemHeight = max(cy, (int)m_szButton.cy); + + // width is width of text plus a bunch of stuff + cx += 2 * s_kcxTextMargin; // L/R margin for readability + cx += s_kcxGap; // space between button and menu text + cx += 2 * m_szButton.cx; // button width (L=button; R=empty margin) + cx += m_cxExtraSpacing; // extra between item text and accelerator keys + + // Windows adds 1 to returned value + cx -= ::GetSystemMetrics(SM_CXMENUCHECK) - 1; + lpMeasureItemStruct->itemWidth = cx; // done deal + } + } + +// Implementation - Hook procs + static LRESULT CALLBACK CreateHookProc(int nCode, WPARAM wParam, LPARAM lParam) + { + const int cchClassName = 7; + TCHAR szClassName[cchClassName] = { 0 }; + + if(nCode == HCBT_CREATEWND) + { + HWND hWndMenu = (HWND)wParam; +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - HCBT_CREATEWND (HWND = %8.8X)\n"), hWndMenu); +#endif + + ::GetClassName(hWndMenu, szClassName, cchClassName); + if(!lstrcmp(_T("#32768"), szClassName)) + s_pCurrentBar->m_stackMenuWnd.Push(hWndMenu); + } + else if(nCode == HCBT_DESTROYWND) + { + HWND hWndMenu = (HWND)wParam; +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - HCBT_DESTROYWND (HWND = %8.8X)\n"), hWndMenu); +#endif + + ::GetClassName(hWndMenu, szClassName, cchClassName); + if(!lstrcmp(_T("#32768"), szClassName)) + { + ATLASSERT(hWndMenu == s_pCurrentBar->m_stackMenuWnd.GetCurrent()); + s_pCurrentBar->m_stackMenuWnd.Pop(); + } + } + + return ::CallNextHookEx(s_hCreateHook, nCode, wParam, lParam); + } + + static LRESULT CALLBACK MessageHookProc(int nCode, WPARAM wParam, LPARAM lParam) + { + LPMSG pMsg = (LPMSG)lParam; + + if(nCode == HC_ACTION && wParam == PM_REMOVE && pMsg->message != GetGetBarMessage() && pMsg->message != WM_FORWARDMSG) + { + CCommandBarCtrlBase* pCmdBar = NULL; + HWND hWnd = pMsg->hwnd; + DWORD dwPID = 0; + while(pCmdBar == NULL && hWnd != NULL) + { + pCmdBar = (CCommandBarCtrlBase*)::SendMessage(hWnd, GetGetBarMessage(), (WPARAM)&dwPID, 0L); + hWnd = ::GetParent(hWnd); + } + + if(pCmdBar != NULL && dwPID == GetCurrentProcessId()) + { + pCmdBar->m_hWndHook = pMsg->hwnd; + ATLASSERT(pCmdBar->IsCommandBarBase()); + + if(::IsWindow(pCmdBar->m_hWnd)) + pCmdBar->SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg); + else + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook skipping message, can't find command bar!\n")); + } + } + + LRESULT lRet = 0; + ATLASSERT(s_pmapMsgHook != NULL); + if(s_pmapMsgHook != NULL) + { + DWORD dwThreadID = ::GetCurrentThreadId(); + _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID); + if(pData != NULL) + { + lRet = ::CallNextHookEx(pData->hMsgHook, nCode, wParam, lParam); + } + } + return lRet; + } + +// Implementation + void DoPopupMenu(int nIndex, bool bAnimate) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - DoPopupMenu, bAnimate = %s\n"), bAnimate ? "true" : "false"); +#endif + + // Menu animation flags +#ifndef TPM_VERPOSANIMATION + const UINT TPM_VERPOSANIMATION = 0x1000L; +#endif +#ifndef TPM_NOANIMATION + const UINT TPM_NOANIMATION = 0x4000L; +#endif + T* pT = static_cast(this); + + // get popup menu and it's position + RECT rect = { 0 }; + GetItemRect(nIndex, &rect); + POINT pt = { rect.left, rect.bottom }; + MapWindowPoints(NULL, &pt, 1); + MapWindowPoints(NULL, &rect); + TPMPARAMS TPMParams = { 0 }; + TPMParams.cbSize = sizeof(TPMPARAMS); + TPMParams.rcExclude = rect; + HMENU hMenuPopup = ::GetSubMenu(m_hMenu, nIndex); + ATLASSERT(hMenuPopup != NULL); + + // get button ID + TBBUTTON tbb = { 0 }; + GetButton(nIndex, &tbb); + int nCmdID = tbb.idCommand; + + m_nPopBtn = nIndex; // remember current button's index + + // press button and display popup menu + PressButton(nCmdID, TRUE); + SetHotItem(nCmdID); + pT->DoTrackPopupMenu(hMenuPopup, TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | + (s_bW2K ? (bAnimate ? TPM_VERPOSANIMATION : TPM_NOANIMATION) : 0), pt.x, pt.y, &TPMParams); + PressButton(nCmdID, FALSE); + if(::GetFocus() != m_hWnd) + SetHotItem(-1); + + m_nPopBtn = -1; // restore + + // eat next message if click is on the same button + MSG msg = { 0 }; + if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rect, msg.pt)) + ::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE); + + // check if another popup menu should be displayed + if(m_nNextPopBtn != -1) + { + PostMessage(GetAutoPopupMessage(), m_nNextPopBtn & 0xFFFF); + if(!(m_nNextPopBtn & 0xFFFF0000) && !m_bPopupItem) + PostMessage(WM_KEYDOWN, VK_DOWN, 0); + m_nNextPopBtn = -1; + } + else + { + m_bContextMenu = false; + // If user didn't hit escape, give focus back + if(!m_bEscapePressed) + { + if(m_bUseKeyboardCues && m_bShowKeyboardCues) + m_bAllowKeyboardCues = false; + pT->GiveFocusBack(); + } + else + { + SetHotItem(nCmdID); + SetAnchorHighlight(TRUE); + } + } + } + + BOOL DoTrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, LPTPMPARAMS lpParams = NULL) + { + CMenuHandle menuPopup = hMenu; + + CWindowCreateCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::DoTrackPopupMenu.\n")); + ATLASSERT(FALSE); + return FALSE; + } + + ATLASSERT(s_hCreateHook == NULL); + + s_pCurrentBar = static_cast(this); + + s_hCreateHook = ::SetWindowsHookEx(WH_CBT, CreateHookProc, ModuleHelper::GetModuleInstance(), GetCurrentThreadId()); + ATLASSERT(s_hCreateHook != NULL); + + m_bPopupItem = false; + m_bMenuActive = true; + + BOOL bTrackRet = menuPopup.TrackPopupMenuEx(uFlags, x, y, m_hWnd, lpParams); + m_bMenuActive = false; + + ::UnhookWindowsHookEx(s_hCreateHook); + + s_hCreateHook = NULL; + s_pCurrentBar = NULL; + + lock.Unlock(); + + // cleanup - convert menus back to original state +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - TrackPopupMenu - cleanup\n")); +#endif + + ATLASSERT(m_stackMenuWnd.GetSize() == 0); + + UpdateWindow(); + ATL::CWindow wndTL = GetTopLevelParent(); + wndTL.UpdateWindow(); + + // restore the menu items to the previous state for all menus that were converted + if(m_bImagesVisible) + { + HMENU hMenuSav = NULL; + while((hMenuSav = m_stackMenuHandle.Pop()) != NULL) + { + menuPopup = hMenuSav; + BOOL bRet = FALSE; + // restore state and delete menu item data + for(int i = 0; i < menuPopup.GetMenuItemCount(); i++) + { + CMenuItemInfo mii; + mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID; + bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii); + ATLASSERT(bRet); + + _MenuItemData* pMI = (_MenuItemData*)mii.dwItemData; + if(pMI != NULL && pMI->IsCmdBarMenuItem()) + { + mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE; + mii.fType = pMI->fType; + mii.fState = pMI->fState; + mii.dwTypeData = pMI->lpstrText; + mii.cch = lstrlen(pMI->lpstrText); + mii.dwItemData = NULL; + + bRet = menuPopup.SetMenuItemInfo(i, TRUE, &mii); + // this one triggers WM_MEASUREITEM + menuPopup.ModifyMenu(i, MF_BYPOSITION | mii.fType | mii.fState, mii.wID, pMI->lpstrText); + ATLASSERT(bRet); + + delete [] pMI->lpstrText; + delete pMI; + } + } + } + } + return bTrackRet; + } + + int GetPreviousMenuItem(int nBtn) const + { + if(nBtn == -1) + return -1; +#if (_WIN32_IE >= 0x0500) + RECT rcClient; + GetClientRect(&rcClient); +#endif // (_WIN32_IE >= 0x0500) + int nNextBtn; + for(nNextBtn = nBtn - 1; nNextBtn != nBtn; nNextBtn--) + { + if(nNextBtn < 0) + nNextBtn = ::GetMenuItemCount(m_hMenu) - 1; + TBBUTTON tbb = { 0 }; + GetButton(nNextBtn, &tbb); +#if (_WIN32_IE >= 0x0500) + RECT rcBtn; + GetItemRect(nNextBtn, &rcBtn); + if(rcBtn.right > rcClient.right) + { + nNextBtn = -2; // chevron + break; + } +#endif // (_WIN32_IE >= 0x0500) + if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0) + break; + } + return (nNextBtn != nBtn) ? nNextBtn : -1; + } + + int GetNextMenuItem(int nBtn) const + { + if(nBtn == -1) + return -1; +#if (_WIN32_IE >= 0x0500) + RECT rcClient = { 0 }; + GetClientRect(&rcClient); +#endif // (_WIN32_IE >= 0x0500) + int nNextBtn = 0; + int nCount = ::GetMenuItemCount(m_hMenu); + for(nNextBtn = nBtn + 1; nNextBtn != nBtn; nNextBtn++) + { + if(nNextBtn >= nCount) + nNextBtn = 0; + TBBUTTON tbb = { 0 }; + GetButton(nNextBtn, &tbb); +#if (_WIN32_IE >= 0x0500) + RECT rcBtn = { 0 }; + GetItemRect(nNextBtn, &rcBtn); + if(rcBtn.right > rcClient.right) + { + nNextBtn = -2; // chevron + break; + } +#endif // (_WIN32_IE >= 0x0500) + if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0) + break; + } + return (nNextBtn != nBtn) ? nNextBtn : -1; + } + +#if (_WIN32_IE >= 0x0500) + bool DisplayChevronMenu() + { + // assume we are in a rebar + HWND hWndReBar = GetParent(); + int nCount = (int)::SendMessage(hWndReBar, RB_GETBANDCOUNT, 0, 0L); + bool bRet = false; + for(int i = 0; i < nCount; i++) + { + REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_STYLE }; + BOOL bRetBandInfo = (BOOL)::SendMessage(hWndReBar, RB_GETBANDINFO, i, (LPARAM)&rbbi); + if(bRetBandInfo && rbbi.hwndChild == m_hWnd) + { + if((rbbi.fStyle & RBBS_USECHEVRON) != 0) + { + ::PostMessage(hWndReBar, RB_PUSHCHEVRON, i, 0L); + PostMessage(WM_KEYDOWN, VK_DOWN, 0L); + bRet = true; + } + break; + } + } + return bRet; + } +#endif // (_WIN32_IE >= 0x0500) + + void GetSystemSettings() + { + // refresh our font + NONCLIENTMETRICS info = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; + BOOL bRet = ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0); + ATLASSERT(bRet); + if(bRet) + { + LOGFONT logfont = { 0 }; + if(m_fontMenu.m_hFont != NULL) + m_fontMenu.GetLogFont(logfont); + if(logfont.lfHeight != info.lfMenuFont.lfHeight || + logfont.lfWidth != info.lfMenuFont.lfWidth || + logfont.lfEscapement != info.lfMenuFont.lfEscapement || + logfont.lfOrientation != info.lfMenuFont.lfOrientation || + logfont.lfWeight != info.lfMenuFont.lfWeight || + logfont.lfItalic != info.lfMenuFont.lfItalic || + logfont.lfUnderline != info.lfMenuFont.lfUnderline || + logfont.lfStrikeOut != info.lfMenuFont.lfStrikeOut || + logfont.lfCharSet != info.lfMenuFont.lfCharSet || + logfont.lfOutPrecision != info.lfMenuFont.lfOutPrecision || + logfont.lfClipPrecision != info.lfMenuFont.lfClipPrecision || + logfont.lfQuality != info.lfMenuFont.lfQuality || + logfont.lfPitchAndFamily != info.lfMenuFont.lfPitchAndFamily || + lstrcmp(logfont.lfFaceName, info.lfMenuFont.lfFaceName) != 0) + { + HFONT hFontMenu = ::CreateFontIndirect(&info.lfMenuFont); + ATLASSERT(hFontMenu != NULL); + if(hFontMenu != NULL) + { + if(m_fontMenu.m_hFont != NULL) + m_fontMenu.DeleteObject(); + m_fontMenu.Attach(hFontMenu); + SetFont(m_fontMenu); + AddStrings(_T("NS\0")); // for proper item height + AutoSize(); + } + } + } + + // check if we need extra spacing for menu item text + CWindowDC dc(m_hWnd); + HFONT hFontOld = dc.SelectFont(m_fontMenu); + RECT rcText = { 0, 0, 0, 0 }; + dc.DrawText(_T("\t"), -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT); + if((rcText.right - rcText.left) < 4) + { + ::SetRectEmpty(&rcText); + dc.DrawText(_T("x"), -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT); + m_cxExtraSpacing = rcText.right - rcText.left; + } + else + { + m_cxExtraSpacing = 0; + } + dc.SelectFont(hFontOld); + + // get Windows version + OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) }; + ::GetVersionEx(&ovi); + + // query keyboard cues mode (Windows 2000 or later) + if(ovi.dwMajorVersion >= 5) + { +#ifndef SPI_GETKEYBOARDCUES + const UINT SPI_GETKEYBOARDCUES = 0x100A; +#endif // !SPI_GETKEYBOARDCUES + BOOL bRetVal = TRUE; + bRet = ::SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &bRetVal, 0); + m_bUseKeyboardCues = (bRet && !bRetVal); + m_bAllowKeyboardCues = true; + ShowKeyboardCues(!m_bUseKeyboardCues); + } + + // query flat menu mode (Windows XP or later) + if((ovi.dwMajorVersion == 5 && ovi.dwMinorVersion >= 1) || (ovi.dwMajorVersion > 5)) + { +#ifndef SPI_GETFLATMENU + const UINT SPI_GETFLATMENU = 0x1022; +#endif // !SPI_GETFLATMENU + BOOL bRetVal = FALSE; + bRet = ::SystemParametersInfo(SPI_GETFLATMENU, 0, &bRetVal, 0); + m_bFlatMenus = (bRet && bRetVal); + } + +#if _WTL_CMDBAR_VISTA_MENUS + // check if we should use Vista menus + bool bVistaMenus = (RunTimeHelper::IsVista() && RunTimeHelper::IsCommCtrl6() && ((m_dwExtendedStyle & CBR_EX_NOVISTAMENUS) == 0)); + + if(bVistaMenus) + { + HMODULE hThemeDLL = ::LoadLibrary(_T("uxtheme.dll")); + if(hThemeDLL != NULL) + { + typedef BOOL (STDAPICALLTYPE *PFN_IsThemeActive)(); + PFN_IsThemeActive pfnIsThemeActive = (PFN_IsThemeActive)::GetProcAddress(hThemeDLL, "IsThemeActive"); + ATLASSERT(pfnIsThemeActive != NULL); + bVistaMenus = bVistaMenus && (pfnIsThemeActive != NULL) && (pfnIsThemeActive() != FALSE); + + typedef BOOL (STDAPICALLTYPE *PFN_IsAppThemed)(); + PFN_IsAppThemed pfnIsAppThemed = (PFN_IsAppThemed)::GetProcAddress(hThemeDLL, "IsAppThemed"); + ATLASSERT(pfnIsAppThemed != NULL); + bVistaMenus = bVistaMenus && (pfnIsAppThemed != NULL) && (pfnIsAppThemed() != FALSE); + + ::FreeLibrary(hThemeDLL); + } + } + + if(!bVistaMenus && m_bVistaMenus && (m_hMenu != NULL) && (m_arrCommand.GetSize() > 0)) + { + T* pT = static_cast(this); + pT->_RemoveVistaBitmapsFromMenu(); + } + + m_bVistaMenus = bVistaMenus; +#endif // _WTL_CMDBAR_VISTA_MENUS + +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("CmdBar - GetSystemSettings:\n m_bFlatMenus = %s\n m_bUseKeyboardCues = %s m_bVistaMenus = %s\n"), + m_bFlatMenus ? "true" : "false", m_bUseKeyboardCues ? "true" : "false", m_bVistaMenus ? "true" : "false"); +#endif + } + +// Implementation - alternate focus mode support + void TakeFocus() + { + if((m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && m_hWndFocus == NULL) + m_hWndFocus = ::GetFocus(); + SetFocus(); + } + + void GiveFocusBack() + { + if(m_bParentActive) + { + if((m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && ::IsWindow(m_hWndFocus)) + ::SetFocus(m_hWndFocus); + else if(!(m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && m_wndParent.IsWindow()) + m_wndParent.SetFocus(); + } + m_hWndFocus = NULL; + SetAnchorHighlight(FALSE); + if(m_bUseKeyboardCues && m_bShowKeyboardCues) + ShowKeyboardCues(false); + m_bSkipPostDown = false; + } + + void ShowKeyboardCues(bool bShow) + { + m_bShowKeyboardCues = bShow; + SetDrawTextFlags(DT_HIDEPREFIX, m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX); + Invalidate(); + UpdateWindow(); + } + +// Implementation - internal message helpers + static UINT GetAutoPopupMessage() + { + static UINT uAutoPopupMessage = 0; + if(uAutoPopupMessage == 0) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::GetAutoPopupMessage.\n")); + ATLASSERT(FALSE); + return 0; + } + + if(uAutoPopupMessage == 0) + uAutoPopupMessage = ::RegisterWindowMessage(_T("WTL_CmdBar_InternalAutoPopupMsg")); + + lock.Unlock(); + } + ATLASSERT(uAutoPopupMessage != 0); + return uAutoPopupMessage; + } + + static UINT GetGetBarMessage() + { + static UINT uGetBarMessage = 0; + if(uGetBarMessage == 0) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::GetGetBarMessage.\n")); + ATLASSERT(FALSE); + return 0; + } + + if(uGetBarMessage == 0) + uGetBarMessage = ::RegisterWindowMessage(_T("WTL_CmdBar_InternalGetBarMsg")); + + lock.Unlock(); + } + ATLASSERT(uGetBarMessage != 0); + return uGetBarMessage; + } + +// Implementation + bool CreateInternalImageList(int cImages) + { + UINT uFlags = (m_bAlphaImages ? ILC_COLOR32 : ILC_COLOR24) | ILC_MASK; + m_hImageList = ::ImageList_Create(m_szBitmap.cx, m_szBitmap.cy, uFlags, cImages, 1); + ATLASSERT(m_hImageList != NULL); + return (m_hImageList != NULL); + } + +// Implementation - support for Vista menus +#if _WTL_CMDBAR_VISTA_MENUS + void _AddVistaBitmapsFromImageList(int nStartIndex, int nCount) + { + // Create display compatible memory DC + HDC hDC = ::GetDC(NULL); + CDC dcMem; + dcMem.CreateCompatibleDC(hDC); + HBITMAP hBitmapSave = dcMem.GetCurrentBitmap(); + + T* pT = static_cast(this); + // Create bitmaps for all menu items + for(int i = 0; i < nCount; i++) + { + HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nStartIndex + i, hDC, dcMem); + dcMem.SelectBitmap(hBitmapSave); + m_arrVistaBitmap.Add(hBitmap); + } + } + + void _AddVistaBitmapFromImageList(int nIndex) + { + // Create display compatible memory DC + HDC hDC = ::GetDC(NULL); + CDC dcMem; + dcMem.CreateCompatibleDC(hDC); + HBITMAP hBitmapSave = dcMem.GetCurrentBitmap(); + + // Create bitmap for menu item + T* pT = static_cast(this); + HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nIndex, hDC, dcMem); + + // Select saved bitmap back and add bitmap to the array + dcMem.SelectBitmap(hBitmapSave); + m_arrVistaBitmap.Add(hBitmap); + } + + void _ReplaceVistaBitmapFromImageList(int nIndex) + { + // Delete existing bitmap + if(m_arrVistaBitmap[nIndex] != NULL) + ::DeleteObject(m_arrVistaBitmap[nIndex]); + + // Create display compatible memory DC + HDC hDC = ::GetDC(NULL); + CDC dcMem; + dcMem.CreateCompatibleDC(hDC); + HBITMAP hBitmapSave = dcMem.GetCurrentBitmap(); + + // Create bitmap for menu item + T* pT = static_cast(this); + HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nIndex, hDC, dcMem); + + // Select saved bitmap back and replace bitmap in the array + dcMem.SelectBitmap(hBitmapSave); + m_arrVistaBitmap.SetAtIndex(nIndex, hBitmap); + } + + HBITMAP _CreateVistaBitmapHelper(int nIndex, HDC hDCSource, HDC hDCTarget) + { + // Create 32-bit bitmap + BITMAPINFO bi = { 0 }; + bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth = m_szBitmap.cx; + bi.bmiHeader.biHeight = m_szBitmap.cy; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 32; + bi.bmiHeader.biCompression = BI_RGB; + bi.bmiHeader.biSizeImage = 0; + bi.bmiHeader.biXPelsPerMeter = 0; + bi.bmiHeader.biYPelsPerMeter = 0; + bi.bmiHeader.biClrUsed = 0; + bi.bmiHeader.biClrImportant = 0; + HBITMAP hBitmap = ::CreateDIBSection(hDCSource, &bi, DIB_RGB_COLORS, NULL, NULL, 0); + ATLASSERT(hBitmap != NULL); + + // Select bitmap into target DC and draw from image list to it + if(hBitmap != NULL) + { + ::SelectObject(hDCTarget, hBitmap); + + IMAGELISTDRAWPARAMS ildp = { 0 }; + ildp.cbSize = sizeof(IMAGELISTDRAWPARAMS); + ildp.himl = m_hImageList; + ildp.i = nIndex; + ildp.hdcDst = hDCTarget; + ildp.x = 0; + ildp.y = 0; + ildp.cx = 0; + ildp.cy = 0; + ildp.xBitmap = 0; + ildp.yBitmap = 0; + ildp.fStyle = ILD_TRANSPARENT; + ildp.fState = ILS_ALPHA; + ildp.Frame = 255; + ::ImageList_DrawIndirect(&ildp); + } + + return hBitmap; + } + + void _RemoveVistaBitmapsFromMenu() + { + CMenuHandle menu = m_hMenu; + for(int i = 0; i < m_arrCommand.GetSize(); i++) + { + CMenuItemInfo mii; + mii.fMask = MIIM_BITMAP; + mii.hbmpItem = NULL; + menu.SetMenuItemInfo(m_arrCommand[i], FALSE, &mii); + } + } +#endif // _WTL_CMDBAR_VISTA_MENUS +}; + + +class CCommandBarCtrl : public CCommandBarCtrlImpl +{ +public: + DECLARE_WND_SUPERCLASS(_T("WTL_CommandBar"), GetWndClassName()) +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CMDICommandBarCtrl - ATL implementation of Command Bars for MDI apps + +template +class ATL_NO_VTABLE CMDICommandBarCtrlImpl : public CCommandBarCtrlImpl< T, TBase, TWinTraits> +{ +public: +// Data members + ATL::CContainedWindow m_wndMDIClient; + bool m_bChildMaximized; + HWND m_hWndChildMaximized; + HICON m_hIconChildMaximized; + int m_nBtnPressed; + int m_nBtnWasPressed; + + int m_cxyOffset; // offset between nonclient elements + int m_cxIconWidth; // small icon width + int m_cyIconHeight; // small icon height + int m_cxBtnWidth; // nonclient button width + int m_cyBtnHeight; // nonclient button height + int m_cxLeft; // left nonclient area width + int m_cxRight; // right nonclient area width + +// Theme declarations and data members +#ifndef _WTL_NO_AUTO_THEME +#ifndef _UXTHEME_H_ + typedef HANDLE HTHEME; +#endif // !_UXTHEME_H_ + typedef HTHEME (STDAPICALLTYPE *PFN_OpenThemeData)(HWND hwnd, LPCWSTR pszClassList); + typedef HRESULT (STDAPICALLTYPE *PFN_CloseThemeData)(HTHEME hTheme); + typedef HRESULT (STDAPICALLTYPE *PFN_DrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); + typedef HRESULT (STDAPICALLTYPE *PFN_DrawThemeParentBackground)(HWND hwnd, HDC hdc, OPTIONAL RECT* prc); + + HMODULE m_hThemeDLL; + HTHEME m_hTheme; + PFN_DrawThemeBackground m_pfnDrawThemeBackground; + PFN_DrawThemeParentBackground m_pfnDrawThemeParentBackground; +#endif // !_WTL_NO_AUTO_THEME + +// Constructor/destructor + CMDICommandBarCtrlImpl() : + m_wndMDIClient(this, 2), m_bChildMaximized(false), + m_hWndChildMaximized(NULL), m_hIconChildMaximized(NULL), + m_nBtnPressed(-1), m_nBtnWasPressed(-1), +#ifndef _WTL_NO_AUTO_THEME + m_hThemeDLL(NULL), m_hTheme(NULL), m_pfnDrawThemeBackground(NULL), m_pfnDrawThemeParentBackground(NULL), +#endif // !_WTL_NO_AUTO_THEME + m_cxyOffset(2), + m_cxIconWidth(16), m_cyIconHeight(16), + m_cxBtnWidth(16), m_cyBtnHeight(14), + m_cxLeft(20), m_cxRight(55) + { } + + ~CMDICommandBarCtrlImpl() + { + if(m_wndMDIClient.IsWindow()) +/*scary!*/ m_wndMDIClient.UnsubclassWindow(); + } + +// Operations + BOOL SetMDIClient(HWND hWndMDIClient) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(::IsWindow(hWndMDIClient)); + if(!::IsWindow(hWndMDIClient)) + return FALSE; + +#ifdef _DEBUG + // BLOCK: Test if the passed window is MDICLIENT + { + LPCTSTR lpszMDIClientClass = _T("MDICLIENT"); + const int nNameLen = 9 + 1; // "MDICLIENT" + NULL + TCHAR szClassName[nNameLen] = { 0 }; + ::GetClassName(hWndMDIClient, szClassName, nNameLen); + ATLASSERT(lstrcmpi(szClassName, lpszMDIClientClass) == 0); + } +#endif // _DEBUG + + if(m_wndMDIClient.IsWindow()) +/*scary!*/ m_wndMDIClient.UnsubclassWindow(); + + return m_wndMDIClient.SubclassWindow(hWndMDIClient); + } + +// Message maps + typedef CCommandBarCtrlImpl< T, TBase, TWinTraits > _baseClass; + BEGIN_MSG_MAP(CMDICommandBarCtrlImpl) + MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) +#ifndef _WTL_NO_AUTO_THEME + MESSAGE_HANDLER(_GetThemeChangedMsg(), OnThemeChanged) +#endif // !_WTL_NO_AUTO_THEME + MESSAGE_HANDLER(WM_SIZE, OnSize) + MESSAGE_HANDLER(WM_NCCALCSIZE, OnNcCalcSize) + MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint) + MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest) + MESSAGE_HANDLER(WM_NCLBUTTONDOWN, OnNcLButtonDown) + MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) + MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) + MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnNcLButtonDblClk) + MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged) + CHAIN_MSG_MAP(_baseClass) + ALT_MSG_MAP(1) // Parent window messages + MESSAGE_HANDLER(WM_ACTIVATE, OnParentActivate) + CHAIN_MSG_MAP_ALT(_baseClass, 1) + ALT_MSG_MAP(2) // MDI client window messages + MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu) + // no chaining needed since this was moved from the base class here + ALT_MSG_MAP(3) // Message hook messages + MESSAGE_RANGE_HANDLER(0, 0xFFFF, OnAllHookMessages) + CHAIN_MSG_MAP_ALT(_baseClass, 3) + END_MSG_MAP() + +// Additional MDI message handlers + LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + LRESULT lRet = _baseClass::OnCreate(uMsg, wParam, lParam, bHandled); + if(lRet == (LRESULT)-1) + return lRet; + +#ifndef _WTL_NO_AUTO_THEME + // this will fail if theming is not supported + m_hThemeDLL = ::LoadLibrary(_T("uxtheme.dll")); + if(m_hThemeDLL != NULL) + { + m_pfnDrawThemeBackground = (PFN_DrawThemeBackground)::GetProcAddress(m_hThemeDLL, "DrawThemeBackground"); + ATLASSERT(m_pfnDrawThemeBackground != NULL); + if(m_pfnDrawThemeBackground != NULL) + { + T* pT = static_cast(this); + pT->_OpenThemeData(); + } + else + { + ::FreeLibrary(m_hThemeDLL); + m_hThemeDLL = NULL; + } + m_pfnDrawThemeParentBackground = (PFN_DrawThemeParentBackground)::GetProcAddress(m_hThemeDLL, "DrawThemeParentBackground"); + ATLASSERT(m_pfnDrawThemeParentBackground != NULL); + } +#endif // !_WTL_NO_AUTO_THEME + + return lRet; + } + + LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + LRESULT lRet = _baseClass::OnDestroy(uMsg, wParam, lParam, bHandled); + +#ifndef _WTL_NO_AUTO_THEME + if(m_hThemeDLL != NULL) + { + T* pT = static_cast(this); + pT->_CloseThemeData(); + ::FreeLibrary(m_hThemeDLL); + m_hThemeDLL = NULL; + } +#endif // !_WTL_NO_AUTO_THEME + + return lRet; + } + +#ifndef _WTL_NO_AUTO_THEME + LRESULT OnThemeChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + if(m_hThemeDLL != NULL) + { + T* pT = static_cast(this); + pT->_CloseThemeData(); + pT->_OpenThemeData(); + } + return 0; + } +#endif // !_WTL_NO_AUTO_THEME + + LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); + T* pT = static_cast(this); + pT->_AdjustBtnSize(GET_Y_LPARAM(lParam)); + return lRet; + } + + LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); + + if(m_bChildMaximized && (BOOL)wParam) + { + LPNCCALCSIZE_PARAMS lpParams = (LPNCCALCSIZE_PARAMS)lParam; + if(m_bLayoutRTL) + { + lpParams->rgrc[0].left += m_cxRight; + lpParams->rgrc[0].right -= m_cxLeft; + } + else + { + lpParams->rgrc[0].left += m_cxLeft; + lpParams->rgrc[0].right -= m_cxRight; + } + } + + return lRet; + } + + LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); + + if(!m_bChildMaximized) + return lRet; + + ATLASSERT(m_hWndChildMaximized != NULL && m_hIconChildMaximized != NULL); + + // get DC and window rectangle + CWindowDC dc(m_hWnd); + RECT rect; + GetWindowRect(&rect); + int cxWidth = rect.right - rect.left; + int cyHeight = rect.bottom - rect.top; + + // paint left side nonclient background and draw icon + ::SetRect(&rect, 0, 0, m_cxLeft, cyHeight); +#ifndef _WTL_NO_AUTO_THEME + if(m_hTheme != NULL) + { + if(m_pfnDrawThemeParentBackground != NULL) + m_pfnDrawThemeParentBackground(m_hWnd, dc, &rect); + else + dc.FillRect(&rect, COLOR_WINDOW); + } + else +#endif // !_WTL_NO_AUTO_THEME + { + if((m_dwExtendedStyle & CBR_EX_TRANSPARENT) != 0) + dc.FillRect(&rect, COLOR_3DFACE); + else + dc.FillRect(&rect, COLOR_MENU); + } + + RECT rcIcon = { 0 }; + T* pT = static_cast(this); + pT->_CalcIconRect(cxWidth, cyHeight, rcIcon); + dc.DrawIconEx(rcIcon.left, rcIcon.top, m_hIconChildMaximized, m_cxIconWidth, m_cyIconHeight); + + // paint right side nonclient background + ::SetRect(&rect, cxWidth - m_cxRight, 0, cxWidth, cyHeight); +#ifndef _WTL_NO_AUTO_THEME + if(m_hTheme != NULL) + { + if(m_pfnDrawThemeParentBackground != NULL) + { + // this is to account for the left non-client area + POINT ptOrg = { 0, 0 }; + dc.GetViewportOrg(&ptOrg); + dc.SetViewportOrg(ptOrg.x + m_cxLeft, ptOrg.y); + ::OffsetRect(&rect, -m_cxLeft, 0); + + m_pfnDrawThemeParentBackground(m_hWnd, dc, &rect); + + // restore + dc.SetViewportOrg(ptOrg); + ::OffsetRect(&rect, m_cxLeft, 0); + } + else + { + dc.FillRect(&rect, COLOR_3DFACE); + } + } + else +#endif // !_WTL_NO_AUTO_THEME + { + if((m_dwExtendedStyle & CBR_EX_TRANSPARENT) != 0) + dc.FillRect(&rect, COLOR_3DFACE); + else + dc.FillRect(&rect, COLOR_MENU); + } + + // draw buttons + RECT arrRect[3] = { 0 }; + pT->_CalcBtnRects(cxWidth, cyHeight, arrRect); + pT->_DrawMDIButton(dc, arrRect, -1); // draw all buttons + + return lRet; + } + + LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); + if(m_bChildMaximized) + { + RECT rect = { 0 }; + GetWindowRect(&rect); + POINT pt = { GET_X_LPARAM(lParam) - rect.left, GET_Y_LPARAM(lParam) - rect.top }; + if(m_bLayoutRTL) + { + if((pt.x < m_cxRight) || (pt.x > ((rect.right - rect.left) - m_cxLeft))) + lRet = HTBORDER; + } + else + { + if((pt.x < m_cxLeft) || (pt.x > ((rect.right - rect.left) - m_cxRight))) + lRet = HTBORDER; + } + } + return lRet; + } + + LRESULT OnNcLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + if(!m_bChildMaximized) + { + bHandled = FALSE; + return 1; + } + + ATLASSERT(_DebugCheckChild()); + + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + RECT rect = { 0 }; + GetWindowRect(&rect); + pt.x -= rect.left; + pt.y -= rect.top; + + RECT rcIcon = { 0 }; + T* pT = static_cast(this); + pT->_CalcIconRect(rect.right - rect.left, rect.bottom - rect.top, rcIcon, m_bLayoutRTL); + RECT arrRect[3] = { 0 }; + pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL); + + if(::PtInRect(&rcIcon, pt)) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: icon\n")); +#endif +#ifndef TPM_VERPOSANIMATION + const UINT TPM_VERPOSANIMATION = 0x1000L; // Menu animation flag +#endif + CMenuHandle menu = ::GetSystemMenu(m_hWndChildMaximized, FALSE); + UINT uRet = (UINT)menu.TrackPopupMenu(TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | + (s_bW2K ? TPM_VERPOSANIMATION : 0), m_bLayoutRTL ? rect.right : rect.left, rect.bottom, m_hWndChildMaximized); + + // eat next message if click is on the same button + ::OffsetRect(&rcIcon, rect.left, rect.top); + MSG msg = { 0 }; + if(::PeekMessage(&msg, m_hWnd, WM_NCLBUTTONDOWN, WM_NCLBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rcIcon, msg.pt)) + ::PeekMessage(&msg, m_hWnd, WM_NCLBUTTONDOWN, WM_NCLBUTTONDOWN, PM_REMOVE); + + if(uRet != 0) + ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, uRet, 0L); + } + else if(::PtInRect(&arrRect[0], pt)) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: close button\n")); +#endif + m_nBtnWasPressed = m_nBtnPressed = 0; + } + else if(::PtInRect(&arrRect[1], pt)) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: restore button\n")); +#endif + m_nBtnWasPressed = m_nBtnPressed = 1; + } + else if(::PtInRect(&arrRect[2], pt)) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: minimize button\n")); +#endif + m_nBtnWasPressed = m_nBtnPressed = 2; + } + else + { + bHandled = FALSE; + } + + // draw the button state if it was pressed + if(m_nBtnPressed != -1) + { + SetCapture(); + CWindowDC dc(m_hWnd); + pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect); + pT->_DrawMDIButton(dc, arrRect, m_nBtnPressed); + } + + return 0; + } + + LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + if(!m_bChildMaximized || ::GetCapture() != m_hWnd || m_nBtnWasPressed == -1) + { + bHandled = FALSE; + return 1; + } + + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + ClientToScreen(&pt); + RECT rect = { 0 }; + GetWindowRect(&rect); + pt.x -= rect.left; + pt.y -= rect.top; + RECT arrRect[3] = { 0 }; + T* pT = static_cast(this); + pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL); + int nOldBtnPressed = m_nBtnPressed; + m_nBtnPressed = ::PtInRect(&arrRect[m_nBtnWasPressed], pt) ? m_nBtnWasPressed : -1; + if(nOldBtnPressed != m_nBtnPressed) + { + CWindowDC dc(m_hWnd); + pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect); + pT->_DrawMDIButton(dc, arrRect, (m_nBtnPressed != -1) ? m_nBtnPressed : nOldBtnPressed); + } + + return 0; + } + + LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + if(!m_bChildMaximized || ::GetCapture() != m_hWnd || m_nBtnWasPressed == -1) + { + bHandled = FALSE; + return 1; + } + + ATLASSERT(_DebugCheckChild()); + + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + ClientToScreen(&pt); + RECT rect = { 0 }; + GetWindowRect(&rect); + pt.x -= rect.left; + pt.y -= rect.top; + + int nBtn = m_nBtnWasPressed; + ReleaseCapture(); + + RECT arrRect[3] = { 0 }; + T* pT = static_cast(this); + pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL); + if(::PtInRect(&arrRect[nBtn], pt)) + { + switch(nBtn) + { + case 0: // close +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonUp: close button\n")); +#endif + ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, SC_CLOSE, 0L); + break; + case 1: // restore +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonUp: restore button\n")); +#endif + ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, SC_RESTORE, 0L); + break; + case 2: // minimize +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonUp: minimize button\n")); +#endif + ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, SC_MINIMIZE, 0L); + break; + default: + break; + } + } + + return 0; + } + + LRESULT OnNcLButtonDblClk(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + if(!m_bChildMaximized || m_nBtnWasPressed != -1) + { + bHandled = FALSE; + return 1; + } + + ATLASSERT(_DebugCheckChild()); + + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + RECT rect = { 0 }; + GetWindowRect(&rect); + pt.x -= rect.left; + pt.y -= rect.top; + + RECT rcIcon = { 0 }; + T* pT = static_cast(this); + pT->_CalcIconRect(rect.right - rect.left, rect.bottom - rect.top, rcIcon, m_bLayoutRTL); + RECT arrRect[3] = { 0 }; + pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL); + + if(::PtInRect(&rcIcon, pt)) + { + CMenuHandle menu = ::GetSystemMenu(m_hWndChildMaximized, FALSE); + UINT uDefID = menu.GetMenuDefaultItem(); + if(uDefID == (UINT)-1) + uDefID = SC_CLOSE; + ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, uDefID, 0L); + } + + return 0; + } + + LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + if(m_bChildMaximized) + { + if(m_nBtnPressed != -1) + { + ATLASSERT(m_nBtnPressed == m_nBtnWasPressed); // must be + m_nBtnPressed = -1; + RECT rect = { 0 }; + GetWindowRect(&rect); + RECT arrRect[3] = { 0 }; + T* pT = static_cast(this); + pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect); + CWindowDC dc(m_hWnd); + pT->_DrawMDIButton(dc, arrRect, m_nBtnWasPressed); + } + m_nBtnWasPressed = -1; + } + else + { + bHandled = FALSE; + } + return 0; + } + +// Parent window message handlers + LRESULT OnParentActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + m_bParentActive = (LOWORD(wParam) != WA_INACTIVE); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW); + bHandled = FALSE; + return 1; + } + +// MDI client window message handlers + LRESULT OnMDISetMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + m_wndMDIClient.DefWindowProc(uMsg, NULL, lParam); + HMENU hOldMenu = GetMenu(); + BOOL bRet = AttachMenu((HMENU)wParam); + bRet; // avoid level 4 warning + ATLASSERT(bRet); + +#if (_WIN32_IE >= 0x0400) + T* pT = static_cast(this); + pT->UpdateRebarBandIdealSize(); +#endif // (_WIN32_IE >= 0x0400) + + return (LRESULT)hOldMenu; + } + +// All messages from the message hook + LRESULT OnAllHookMessages(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + T* pT = static_cast(this); + pT->_ProcessAllHookMessages(uMsg, wParam, lParam); + + bHandled = FALSE; + return 1; + } + +// Overrideables + // override this to provide different ideal size + void UpdateRebarBandIdealSize() + { + // assuming we are in a rebar, change ideal size to our size + // we hope that if we are not in a rebar, nCount will be 0 + int nCount = (int)::SendMessage(GetParent(), RB_GETBANDCOUNT, 0, 0L); + for(int i = 0; i < nCount; i++) + { + REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE }; + ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi); + if(rbi.hwndChild == m_hWnd) + { + rbi.fMask = RBBIM_IDEALSIZE; + rbi.cxIdeal = m_bChildMaximized ? m_cxLeft + m_cxRight : 0; + int nBtnCount = GetButtonCount(); + if(nBtnCount > 0) + { + RECT rect = { 0 }; + GetItemRect(nBtnCount - 1, &rect); + rbi.cxIdeal += rect.right; + } + ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi); + break; + } + } + } + + // all hook messages - check for the maximized MDI child window change + void _ProcessAllHookMessages(UINT uMsg, WPARAM /*wParam*/, LPARAM /*lParam*/) + { + if(uMsg == WM_MDIGETACTIVE || uMsg == WM_MDISETMENU) + return; + + BOOL bMaximized = FALSE; + HWND hWndChild = (HWND)::SendMessage(m_wndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized); + bool bMaxOld = m_bChildMaximized; + m_bChildMaximized = (hWndChild != NULL && bMaximized); + HICON hIconOld = m_hIconChildMaximized; + + if(m_bChildMaximized) + { + if(m_hWndChildMaximized != hWndChild) + { + ATL::CWindow wnd = m_hWndChildMaximized = hWndChild; + m_hIconChildMaximized = wnd.GetIcon(FALSE); + if(m_hIconChildMaximized == NULL) + { + m_hIconChildMaximized = wnd.GetIcon(TRUE); + if(m_hIconChildMaximized == NULL) + { + // no icon set with WM_SETICON, get the class one +// need conditional code because types don't match in winuser.h +#ifdef _WIN64 + m_hIconChildMaximized = (HICON)::GetClassLongPtr(wnd, GCLP_HICONSM); +#else + m_hIconChildMaximized = (HICON)LongToHandle(::GetClassLongPtr(wnd, GCLP_HICONSM)); +#endif + } + } + } + } + else + { + m_hWndChildMaximized = NULL; + m_hIconChildMaximized = NULL; + } + + if(bMaxOld != m_bChildMaximized) + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - All messages hook change: m_bChildMaximized = %s\n"), m_bChildMaximized ? "true" : "false"); +#endif + // assuming we are in a rebar, change our size to accomodate new state + // we hope that if we are not in a rebar, nCount will be 0 + int nCount = (int)::SendMessage(GetParent(), RB_GETBANDCOUNT, 0, 0L); + int cxDiff = (m_bChildMaximized ? 1 : -1) * (m_cxLeft + m_cxRight); + for(int i = 0; i < nCount; i++) + { +#if (_WIN32_IE >= 0x0500) + REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_STYLE }; + ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi); + if(rbi.hwndChild == m_hWnd) + { + if((rbi.fStyle & RBBS_USECHEVRON) != 0) + { + rbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE; + rbi.cxMinChild += cxDiff; + rbi.cxIdeal += cxDiff; + ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi); + } + break; + } +#elif (_WIN32_IE >= 0x0400) + REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE }; + ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi); + if(rbi.hwndChild == m_hWnd) + { + rbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE; + rbi.cxMinChild += cxDiff; + rbi.cxIdeal += cxDiff; + ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi); + break; + } +#else // (_WIN32_IE < 0x0400) + REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE }; + ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi); + if(rbi.hwndChild == m_hWnd) + { + rbi.fMask = RBBIM_CHILDSIZE; + rbi.cxMinChild += cxDiff; + ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi); + break; + } +#endif // (_WIN32_IE < 0x0400) + } + } + + if(bMaxOld != m_bChildMaximized || hIconOld != m_hIconChildMaximized) + { + // force size change and redraw everything + RECT rect = { 0 }; + GetWindowRect(&rect); + ::MapWindowPoints(NULL, GetParent(), (LPPOINT)&rect, 2); + SetRedraw(FALSE); + SetWindowPos(NULL, 0, 0, 1, 1, SWP_NOZORDER | SWP_NOMOVE); + SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE); + SetRedraw(TRUE); + RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW); + } + } + +// Implementation + void GetSystemSettings() + { +#ifdef _CMDBAR_EXTRA_TRACE + ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - GetSystemSettings\n")); +#endif + _baseClass::GetSystemSettings(); + + NONCLIENTMETRICS info = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; + BOOL bRet = ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0); + ATLASSERT(bRet); + if(bRet) + { + m_cxIconWidth = ::GetSystemMetrics(SM_CXSMICON); + m_cyIconHeight = ::GetSystemMetrics(SM_CYSMICON); + m_cxLeft = m_cxIconWidth; + +#ifndef _WTL_NO_AUTO_THEME + if(m_hTheme != NULL) + { + m_cxBtnWidth = info.iCaptionWidth - 2 * m_cxyOffset; + m_cyBtnHeight = info.iCaptionHeight - 2 * m_cxyOffset; + m_cxRight = 3 * m_cxBtnWidth; + } + else +#endif // !_WTL_NO_AUTO_THEME + { + m_cxBtnWidth = info.iCaptionWidth - m_cxyOffset; + m_cyBtnHeight = info.iCaptionHeight - 2 * m_cxyOffset; + m_cxRight = 3 * m_cxBtnWidth + m_cxyOffset; + } + } + + RECT rect = { 0 }; + GetClientRect(&rect); + T* pT = static_cast(this); + pT->_AdjustBtnSize(rect.bottom); + } + + void _AdjustBtnSize(int cyHeight) + { + if(cyHeight > 1 && m_cyBtnHeight > cyHeight) + { +#ifndef _WTL_NO_AUTO_THEME + if(m_hTheme != NULL) + { + m_cyBtnHeight = cyHeight; + m_cxBtnWidth = cyHeight; + m_cxRight = 3 * m_cxBtnWidth; + } + else +#endif // !_WTL_NO_AUTO_THEME + { + m_cyBtnHeight = cyHeight; + m_cxBtnWidth = cyHeight + m_cxyOffset; + m_cxRight = 3 * m_cxBtnWidth + m_cxyOffset; + } + } + } + + void _CalcIconRect(int cxWidth, int cyHeight, RECT& rect, bool bInvertX = false) const + { + int xStart = (m_cxLeft - m_cxIconWidth) / 2; + if(xStart < 0) + xStart = 0; + int yStart = (cyHeight - m_cyIconHeight) / 2; + if(yStart < 0) + yStart = 0; + + if(bInvertX) + ::SetRect(&rect, cxWidth - (xStart + m_cxBtnWidth), yStart, cxWidth - xStart, yStart + m_cyBtnHeight); + else + ::SetRect(&rect, xStart, yStart, xStart + m_cxBtnWidth, yStart + m_cyBtnHeight); + } + + void _CalcBtnRects(int cxWidth, int cyHeight, RECT arrRect[3], bool bInvertX = false) const + { + int yStart = (cyHeight - m_cyBtnHeight) / 2; + if(yStart < 0) + yStart = 0; + + RECT rcBtn = { cxWidth - m_cxBtnWidth, yStart, cxWidth, yStart + m_cyBtnHeight }; + int nDirection = -1; + if(bInvertX) + { + ::SetRect(&rcBtn, 0, yStart, m_cxBtnWidth, yStart + m_cyBtnHeight); + nDirection = 1; + } + + arrRect[0] = rcBtn; +#ifndef _WTL_NO_AUTO_THEME + if(m_hTheme != NULL) + ::OffsetRect(&rcBtn, nDirection * m_cxBtnWidth, 0); + else +#endif // !_WTL_NO_AUTO_THEME + ::OffsetRect(&rcBtn, nDirection * (m_cxBtnWidth + m_cxyOffset), 0); + arrRect[1] = rcBtn; + ::OffsetRect(&rcBtn, nDirection * m_cxBtnWidth, 0); + arrRect[2] = rcBtn; + } + + void _DrawMDIButton(CWindowDC& dc, LPRECT pRects, int nBtn) + { +#ifndef _WTL_NO_AUTO_THEME + if(m_hTheme != NULL) + { +#ifndef TMSCHEMA_H + const int WP_MDICLOSEBUTTON = 20; + const int CBS_NORMAL = 1; + const int CBS_PUSHED = 3; + const int CBS_DISABLED = 4; + const int WP_MDIRESTOREBUTTON = 22; + const int RBS_NORMAL = 1; + const int RBS_PUSHED = 3; + const int RBS_DISABLED = 4; + const int WP_MDIMINBUTTON = 16; + const int MINBS_NORMAL = 1; + const int MINBS_PUSHED = 3; + const int MINBS_DISABLED = 4; +#endif // TMSCHEMA_H + if(nBtn == -1 || nBtn == 0) + m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDICLOSEBUTTON, m_bParentActive ? ((m_nBtnPressed == 0) ? CBS_PUSHED : CBS_NORMAL) : CBS_DISABLED, &pRects[0], NULL); + if(nBtn == -1 || nBtn == 1) + m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDIRESTOREBUTTON, m_bParentActive ? ((m_nBtnPressed == 1) ? RBS_PUSHED : RBS_NORMAL) : RBS_DISABLED, &pRects[1], NULL); + if(nBtn == -1 || nBtn == 2) + m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDIMINBUTTON, m_bParentActive ? ((m_nBtnPressed == 2) ? MINBS_PUSHED : MINBS_NORMAL) : MINBS_DISABLED, &pRects[2], NULL); + } + else +#endif // !_WTL_NO_AUTO_THEME + { + if(nBtn == -1 || nBtn == 0) + dc.DrawFrameControl(&pRects[0], DFC_CAPTION, DFCS_CAPTIONCLOSE | ((m_nBtnPressed == 0) ? DFCS_PUSHED : 0)); + if(nBtn == -1 || nBtn == 1) + dc.DrawFrameControl(&pRects[1], DFC_CAPTION, DFCS_CAPTIONRESTORE | ((m_nBtnPressed == 1) ? DFCS_PUSHED : 0)); + if(nBtn == -1 || nBtn == 2) + dc.DrawFrameControl(&pRects[2], DFC_CAPTION, DFCS_CAPTIONMIN | ((m_nBtnPressed == 2) ? DFCS_PUSHED : 0)); + } + } + +#ifndef _WTL_NO_AUTO_THEME + static UINT _GetThemeChangedMsg() + { +#ifndef WM_THEMECHANGED + static const UINT WM_THEMECHANGED = 0x031A; +#endif // !WM_THEMECHANGED + return WM_THEMECHANGED; + } + + void _OpenThemeData() + { + ATLASSERT(m_hThemeDLL != NULL); + + PFN_OpenThemeData pfnOpenThemeData = (PFN_OpenThemeData)::GetProcAddress(m_hThemeDLL, "OpenThemeData"); + ATLASSERT(pfnOpenThemeData != NULL); + if(pfnOpenThemeData != NULL) + m_hTheme = pfnOpenThemeData(m_hWnd, L"Window"); + } + + void _CloseThemeData() + { + ATLASSERT(m_hThemeDLL != NULL); + + if(m_hTheme == NULL) + return; // nothing to do + + PFN_CloseThemeData pfnCloseThemeData = (PFN_CloseThemeData)::GetProcAddress(m_hThemeDLL, "CloseThemeData"); + ATLASSERT(pfnCloseThemeData != NULL); + if(pfnCloseThemeData != NULL) + { + pfnCloseThemeData(m_hTheme); + m_hTheme = NULL; + } + } +#endif // !_WTL_NO_AUTO_THEME + + bool _DebugCheckChild() + { +#ifdef _DEBUG + BOOL bMaximized = FALSE; + HWND hWndChild = (HWND)::SendMessage(m_wndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized); + return (bMaximized && hWndChild == m_hWndChildMaximized); +#else // !_DEBUG + return true; +#endif // !_DEBUG + } +}; + +class CMDICommandBarCtrl : public CMDICommandBarCtrlImpl +{ +public: + DECLARE_WND_SUPERCLASS(_T("WTL_MDICommandBar"), GetWndClassName()) +}; + +}; // namespace WTL + +#endif // __ATLCTRLW_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlctrlx.h b/Client/Client/GUI/BKWin/wtl/atlctrlx.h new file mode 100644 index 00000000..1bea3c35 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlctrlx.h @@ -0,0 +1,4824 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLCTRLX_H__ +#define __ATLCTRLX_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifndef __ATLAPP_H__ + #error atlctrlx.h requires atlapp.h to be included first +#endif + +#ifndef __ATLCTRLS_H__ + #error atlctrlx.h requires atlctrls.h to be included first +#endif + +#ifndef WM_UPDATEUISTATE + #define WM_UPDATEUISTATE 0x0128 +#endif // !WM_UPDATEUISTATE + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CBitmapButtonImpl +// CBitmapButton +// CCheckListViewCtrlImpl +// CCheckListViewCtrl +// CHyperLinkImpl +// CHyperLink +// CWaitCursor +// CCustomWaitCursor +// CMultiPaneStatusBarCtrlImpl +// CMultiPaneStatusBarCtrl +// CPaneContainerImpl +// CPaneContainer +// CSortListViewImpl +// CSortListViewCtrlImpl +// CSortListViewCtrl +// CTabViewImpl +// CTabView + +namespace WTL +{ + +/////////////////////////////////////////////////////////////////////////////// +// CBitmapButton - bitmap button implementation + +#ifndef _WIN32_WCE + +// bitmap button extended styles +#define BMPBTN_HOVER 0x00000001 +#define BMPBTN_AUTO3D_SINGLE 0x00000002 +#define BMPBTN_AUTO3D_DOUBLE 0x00000004 +#define BMPBTN_AUTOSIZE 0x00000008 +#define BMPBTN_SHAREIMAGELISTS 0x00000010 +#define BMPBTN_AUTOFIRE 0x00000020 + +template +class ATL_NO_VTABLE CBitmapButtonImpl : public ATL::CWindowImpl< T, TBase, TWinTraits> +{ +public: + DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName()) + + enum + { + _nImageNormal = 0, + _nImagePushed, + _nImageFocusOrHover, + _nImageDisabled, + + _nImageCount = 4, + }; + + enum + { + ID_TIMER_FIRST = 1000, + ID_TIMER_REPEAT = 1001 + }; + + // Bitmap button specific extended styles + DWORD m_dwExtendedStyle; + + CImageList m_ImageList; + int m_nImage[_nImageCount]; + + CToolTipCtrl m_tip; + LPTSTR m_lpstrToolTipText; + + // Internal states + unsigned m_fMouseOver:1; + unsigned m_fFocus:1; + unsigned m_fPressed:1; + + +// Constructor/Destructor + CBitmapButtonImpl(DWORD dwExtendedStyle = BMPBTN_AUTOSIZE, HIMAGELIST hImageList = NULL) : + m_ImageList(hImageList), m_dwExtendedStyle(dwExtendedStyle), + m_lpstrToolTipText(NULL), + m_fMouseOver(0), m_fFocus(0), m_fPressed(0) + { + m_nImage[_nImageNormal] = -1; + m_nImage[_nImagePushed] = -1; + m_nImage[_nImageFocusOrHover] = -1; + m_nImage[_nImageDisabled] = -1; + } + + ~CBitmapButtonImpl() + { + if((m_dwExtendedStyle & BMPBTN_SHAREIMAGELISTS) == 0) + m_ImageList.Destroy(); + delete [] m_lpstrToolTipText; + } + + // overridden to provide proper initialization + BOOL SubclassWindow(HWND hWnd) + { +#if (_MSC_VER >= 1300) + BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits>::SubclassWindow(hWnd); +#else // !(_MSC_VER >= 1300) + typedef ATL::CWindowImpl< T, TBase, TWinTraits> _baseClass; + BOOL bRet = _baseClass::SubclassWindow(hWnd); +#endif // !(_MSC_VER >= 1300) + if(bRet) + Init(); + return bRet; + } + +// Attributes + DWORD GetBitmapButtonExtendedStyle() const + { + return m_dwExtendedStyle; + } + + DWORD SetBitmapButtonExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) + { + DWORD dwPrevStyle = m_dwExtendedStyle; + if(dwMask == 0) + m_dwExtendedStyle = dwExtendedStyle; + else + m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); + return dwPrevStyle; + } + + HIMAGELIST GetImageList() const + { + return m_ImageList; + } + + HIMAGELIST SetImageList(HIMAGELIST hImageList) + { + HIMAGELIST hImageListPrev = m_ImageList; + m_ImageList = hImageList; + if((m_dwExtendedStyle & BMPBTN_AUTOSIZE) != 0 && ::IsWindow(m_hWnd)) + SizeToImage(); + return hImageListPrev; + } + + int GetToolTipTextLength() const + { + return (m_lpstrToolTipText == NULL) ? -1 : lstrlen(m_lpstrToolTipText); + } + + bool GetToolTipText(LPTSTR lpstrText, int nLength) const + { + ATLASSERT(lpstrText != NULL); + if(m_lpstrToolTipText == NULL) + return false; + + errno_t nRet = SecureHelper::strncpy_x(lpstrText, nLength, m_lpstrToolTipText, _TRUNCATE); + + return (nRet == 0 || nRet == STRUNCATE); + } + + bool SetToolTipText(LPCTSTR lpstrText) + { + if(m_lpstrToolTipText != NULL) + { + delete [] m_lpstrToolTipText; + m_lpstrToolTipText = NULL; + } + + if(lpstrText == NULL) + { + if(m_tip.IsWindow()) + m_tip.Activate(FALSE); + return true; + } + + int cchLen = lstrlen(lpstrText) + 1; + ATLTRY(m_lpstrToolTipText = new TCHAR[cchLen]); + if(m_lpstrToolTipText == NULL) + return false; + + SecureHelper::strcpy_x(m_lpstrToolTipText, cchLen, lpstrText); + if(m_tip.IsWindow()) + { + m_tip.Activate(TRUE); + m_tip.AddTool(m_hWnd, m_lpstrToolTipText); + } + + return true; + } + +// Operations + void SetImages(int nNormal, int nPushed = -1, int nFocusOrHover = -1, int nDisabled = -1) + { + if(nNormal != -1) + m_nImage[_nImageNormal] = nNormal; + if(nPushed != -1) + m_nImage[_nImagePushed] = nPushed; + if(nFocusOrHover != -1) + m_nImage[_nImageFocusOrHover] = nFocusOrHover; + if(nDisabled != -1) + m_nImage[_nImageDisabled] = nDisabled; + } + + BOOL SizeToImage() + { + ATLASSERT(::IsWindow(m_hWnd) && m_ImageList.m_hImageList != NULL); + int cx = 0; + int cy = 0; + if(!m_ImageList.GetIconSize(cx, cy)) + return FALSE; + return ResizeClient(cx, cy); + } + +// Overrideables + void DoPaint(CDCHandle dc) + { + ATLASSERT(m_ImageList.m_hImageList != NULL); // image list must be set + ATLASSERT(m_nImage[0] != -1); // main bitmap must be set + + // set bitmap according to the current button state + int nImage = -1; + bool bHover = IsHoverMode(); + if(!IsWindowEnabled()) + nImage = m_nImage[_nImageDisabled]; + else if(m_fPressed == 1) + nImage = m_nImage[_nImagePushed]; + else if((!bHover && m_fFocus == 1) || (bHover && m_fMouseOver == 1)) + nImage = m_nImage[_nImageFocusOrHover]; + if(nImage == -1) // not there, use default one + nImage = m_nImage[_nImageNormal]; + + // draw the button image + int xyPos = 0; + if((m_fPressed == 1) && ((m_dwExtendedStyle & (BMPBTN_AUTO3D_SINGLE | BMPBTN_AUTO3D_DOUBLE)) != 0) && (m_nImage[_nImagePushed] == -1)) + xyPos = 1; + m_ImageList.Draw(dc, nImage, xyPos, xyPos, ILD_NORMAL); + + // draw 3D border if required + if((m_dwExtendedStyle & (BMPBTN_AUTO3D_SINGLE | BMPBTN_AUTO3D_DOUBLE)) != 0) + { + RECT rect; + GetClientRect(&rect); + + if(m_fPressed == 1) + dc.DrawEdge(&rect, ((m_dwExtendedStyle & BMPBTN_AUTO3D_SINGLE) != 0) ? BDR_SUNKENOUTER : EDGE_SUNKEN, BF_RECT); + else if(!bHover || m_fMouseOver == 1) + dc.DrawEdge(&rect, ((m_dwExtendedStyle & BMPBTN_AUTO3D_SINGLE) != 0) ? BDR_RAISEDINNER : EDGE_RAISED, BF_RECT); + + if(!bHover && m_fFocus == 1) + { + ::InflateRect(&rect, -2 * ::GetSystemMetrics(SM_CXEDGE), -2 * ::GetSystemMetrics(SM_CYEDGE)); + dc.DrawFocusRect(&rect); + } + } + } + +// Message map and handlers + BEGIN_MSG_MAP(CBitmapButtonImpl) + MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) + MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) + MESSAGE_HANDLER(WM_PAINT, OnPaint) + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) + MESSAGE_HANDLER(WM_SETFOCUS, OnFocus) + MESSAGE_HANDLER(WM_KILLFOCUS, OnFocus) + MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) + MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDblClk) + MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) + MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged) + MESSAGE_HANDLER(WM_ENABLE, OnEnable) + MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) + MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave) + MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown) + MESSAGE_HANDLER(WM_KEYUP, OnKeyUp) + MESSAGE_HANDLER(WM_TIMER, OnTimer) + MESSAGE_HANDLER(WM_UPDATEUISTATE, OnUpdateUiState) + END_MSG_MAP() + + LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + Init(); + bHandled = FALSE; + return 1; + } + + LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + if(m_tip.IsWindow()) + { + m_tip.DestroyWindow(); + m_tip.m_hWnd = NULL; + } + bHandled = FALSE; + return 1; + } + + LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + MSG msg = { m_hWnd, uMsg, wParam, lParam }; + if(m_tip.IsWindow()) + m_tip.RelayEvent(&msg); + bHandled = FALSE; + return 1; + } + + LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return 1; // no background needed + } + + LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + if(wParam != NULL) + { + pT->DoPaint((HDC)wParam); + } + else + { + CPaintDC dc(m_hWnd); + pT->DoPaint(dc.m_hDC); + } + return 0; + } + + LRESULT OnFocus(UINT uMsg, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + m_fFocus = (uMsg == WM_SETFOCUS) ? 1 : 0; + Invalidate(); + UpdateWindow(); + bHandled = FALSE; + return 1; + } + + LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + LRESULT lRet = 0; + if(IsHoverMode()) + SetCapture(); + else + lRet = DefWindowProc(uMsg, wParam, lParam); + if(::GetCapture() == m_hWnd) + { + m_fPressed = 1; + Invalidate(); + UpdateWindow(); + } + if((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0) + { + int nElapse = 250; + int nDelay = 0; + if(::SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &nDelay, 0)) + nElapse += nDelay * 250; // all milli-seconds + SetTimer(ID_TIMER_FIRST, nElapse); + } + return lRet; + } + + LRESULT OnLButtonDblClk(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + LRESULT lRet = 0; + if(!IsHoverMode()) + lRet = DefWindowProc(uMsg, wParam, lParam); + if(::GetCapture() != m_hWnd) + SetCapture(); + if(m_fPressed == 0) + { + m_fPressed = 1; + Invalidate(); + UpdateWindow(); + } + return lRet; + } + + LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + LRESULT lRet = 0; + bool bHover = IsHoverMode(); + if(!bHover) + lRet = DefWindowProc(uMsg, wParam, lParam); + if(::GetCapture() == m_hWnd) + { + if(bHover && m_fPressed == 1) + ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd); + ::ReleaseCapture(); + } + return lRet; + } + + LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + if(m_fPressed == 1) + { + m_fPressed = 0; + Invalidate(); + UpdateWindow(); + } + bHandled = FALSE; + return 1; + } + + LRESULT OnEnable(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + Invalidate(); + UpdateWindow(); + bHandled = FALSE; + return 1; + } + + LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + if(::GetCapture() == m_hWnd) + { + POINT ptCursor = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + ClientToScreen(&ptCursor); + RECT rect = { 0 }; + GetWindowRect(&rect); + unsigned int uPressed = ::PtInRect(&rect, ptCursor) ? 1 : 0; + if(m_fPressed != uPressed) + { + m_fPressed = uPressed; + Invalidate(); + UpdateWindow(); + } + } + else if(IsHoverMode() && m_fMouseOver == 0) + { + m_fMouseOver = 1; + Invalidate(); + UpdateWindow(); + StartTrackMouseLeave(); + } + bHandled = FALSE; + return 1; + } + + LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + if(m_fMouseOver == 1) + { + m_fMouseOver = 0; + Invalidate(); + UpdateWindow(); + } + return 0; + } + + LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + if(wParam == VK_SPACE && IsHoverMode()) + return 0; // ignore if in hover mode + if(wParam == VK_SPACE && m_fPressed == 0) + { + m_fPressed = 1; + Invalidate(); + UpdateWindow(); + } + bHandled = FALSE; + return 1; + } + + LRESULT OnKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + if(wParam == VK_SPACE && IsHoverMode()) + return 0; // ignore if in hover mode + if(wParam == VK_SPACE && m_fPressed == 1) + { + m_fPressed = 0; + Invalidate(); + UpdateWindow(); + } + bHandled = FALSE; + return 1; + } + + LRESULT OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + ATLASSERT((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0); + switch(wParam) // timer ID + { + case ID_TIMER_FIRST: + KillTimer(ID_TIMER_FIRST); + if(m_fPressed == 1) + { + ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd); + int nElapse = 250; + int nRepeat = 40; + if(::SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &nRepeat, 0)) + nElapse = 10000 / (10 * nRepeat + 25); // milli-seconds, approximated + SetTimer(ID_TIMER_REPEAT, nElapse); + } + break; + case ID_TIMER_REPEAT: + if(m_fPressed == 1) + ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd); + else if(::GetCapture() != m_hWnd) + KillTimer(ID_TIMER_REPEAT); + break; + default: // not our timer + break; + } + return 0; + } + + LRESULT OnUpdateUiState(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + // If the control is subclassed or superclassed, this message can cause + // repainting without WM_PAINT. We don't use this state, so just do nothing. + return 0; + } + +// Implementation + void Init() + { + // We need this style to prevent Windows from painting the button + ModifyStyle(0, BS_OWNERDRAW); + + // create a tool tip + m_tip.Create(m_hWnd); + ATLASSERT(m_tip.IsWindow()); + if(m_tip.IsWindow() && m_lpstrToolTipText != NULL) + { + m_tip.Activate(TRUE); + m_tip.AddTool(m_hWnd, m_lpstrToolTipText); + } + + if(m_ImageList.m_hImageList != NULL && (m_dwExtendedStyle & BMPBTN_AUTOSIZE) != 0) + SizeToImage(); + } + + BOOL StartTrackMouseLeave() + { + TRACKMOUSEEVENT tme = { 0 }; + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = m_hWnd; + return _TrackMouseEvent(&tme); + } + + bool IsHoverMode() const + { + return ((m_dwExtendedStyle & BMPBTN_HOVER) != 0); + } +}; + + +class CBitmapButton : public CBitmapButtonImpl +{ +public: + DECLARE_WND_SUPERCLASS(_T("WTL_BitmapButton"), GetWndClassName()) + + CBitmapButton(DWORD dwExtendedStyle = BMPBTN_AUTOSIZE, HIMAGELIST hImageList = NULL) : + CBitmapButtonImpl(dwExtendedStyle, hImageList) + { } +}; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CCheckListCtrlView - list view control with check boxes + +template +class CCheckListViewCtrlImplTraits +{ +public: + static DWORD GetWndStyle(DWORD dwStyle) + { + return (dwStyle == 0) ? t_dwStyle : dwStyle; + } + + static DWORD GetWndExStyle(DWORD dwExStyle) + { + return (dwExStyle == 0) ? t_dwExStyle : dwExStyle; + } + + static DWORD GetExtendedLVStyle() + { + return t_dwExListViewStyle; + } +}; + +typedef CCheckListViewCtrlImplTraits CCheckListViewCtrlTraits; + +template +class ATL_NO_VTABLE CCheckListViewCtrlImpl : public ATL::CWindowImpl +{ +public: + DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName()) + +// Attributes + static DWORD GetExtendedLVStyle() + { + return TWinTraits::GetExtendedLVStyle(); + } + +// Operations + BOOL SubclassWindow(HWND hWnd) + { +#if (_MSC_VER >= 1300) + BOOL bRet = ATL::CWindowImplBaseT< TBase, TWinTraits>::SubclassWindow(hWnd); +#else // !(_MSC_VER >= 1300) + typedef ATL::CWindowImplBaseT< TBase, TWinTraits> _baseClass; + BOOL bRet = _baseClass::SubclassWindow(hWnd); +#endif // !(_MSC_VER >= 1300) + if(bRet) + { + T* pT = static_cast(this); + pT; + ATLASSERT((pT->GetExtendedLVStyle() & LVS_EX_CHECKBOXES) != 0); + SetExtendedListViewStyle(pT->GetExtendedLVStyle()); + } + return bRet; + } + + void CheckSelectedItems(int nCurrItem) + { + // first check if this item is selected + LVITEM lvi = { 0 }; + lvi.iItem = nCurrItem; + lvi.iSubItem = 0; + lvi.mask = LVIF_STATE; + lvi.stateMask = LVIS_SELECTED; + GetItem(&lvi); + // if item is not selected, don't do anything + if(!(lvi.state & LVIS_SELECTED)) + return; + // new check state will be reverse of the current state, + BOOL bCheck = !GetCheckState(nCurrItem); + int nItem = -1; + int nOldItem = -1; + while((nItem = GetNextItem(nOldItem, LVNI_SELECTED)) != -1) + { + if(nItem != nCurrItem) + SetCheckState(nItem, bCheck); + nOldItem = nItem; + } + } + +// Implementation + BEGIN_MSG_MAP(CCheckListViewCtrlImpl) + MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) + MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDown) + MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown) + END_MSG_MAP() + + LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + // first let list view control initialize everything + LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); + T* pT = static_cast(this); + pT; + ATLASSERT((pT->GetExtendedLVStyle() & LVS_EX_CHECKBOXES) != 0); + SetExtendedListViewStyle(pT->GetExtendedLVStyle()); + return lRet; + } + + LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + POINT ptMsg = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + LVHITTESTINFO lvh = { 0 }; + lvh.pt = ptMsg; + if(HitTest(&lvh) != -1 && lvh.flags == LVHT_ONITEMSTATEICON && ::GetKeyState(VK_CONTROL) >= 0) + { + T* pT = static_cast(this); + pT->CheckSelectedItems(lvh.iItem); + } + bHandled = FALSE; + return 1; + } + + LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + if(wParam == VK_SPACE) + { + int nCurrItem = GetNextItem(-1, LVNI_FOCUSED); + if(nCurrItem != -1 && ::GetKeyState(VK_CONTROL) >= 0) + { + T* pT = static_cast(this); + pT->CheckSelectedItems(nCurrItem); + } + } + bHandled = FALSE; + return 1; + } +}; + +class CCheckListViewCtrl : public CCheckListViewCtrlImpl +{ +public: + DECLARE_WND_SUPERCLASS(_T("WTL_CheckListView"), GetWndClassName()) +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CHyperLink - hyper link control implementation + +#if (WINVER < 0x0500) && !defined(_WIN32_WCE) +__declspec(selectany) struct +{ + enum { cxWidth = 32, cyHeight = 32 }; + int xHotSpot; + int yHotSpot; + unsigned char arrANDPlane[cxWidth * cyHeight / 8]; + unsigned char arrXORPlane[cxWidth * cyHeight / 8]; +} _AtlHyperLink_CursorData = +{ + 5, 0, + { + 0xF9, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, + 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, + 0xF0, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, + 0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, + 0xE0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, + 0xF8, 0x01, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }, + { + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0xC0, 0x00, 0x00, 0x06, 0xD8, 0x00, 0x00, + 0x06, 0xDA, 0x00, 0x00, 0x06, 0xDB, 0x00, 0x00, 0x67, 0xFB, 0x00, 0x00, 0x77, 0xFF, 0x00, 0x00, + 0x37, 0xFF, 0x00, 0x00, 0x17, 0xFF, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, + 0x0F, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, + 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + } +}; +#endif // (WINVER < 0x0500) && !defined(_WIN32_WCE) + +#define HLINK_UNDERLINED 0x00000000 +#define HLINK_NOTUNDERLINED 0x00000001 +#define HLINK_UNDERLINEHOVER 0x00000002 +#define HLINK_COMMANDBUTTON 0x00000004 +#define HLINK_NOTIFYBUTTON 0x0000000C +#define HLINK_USETAGS 0x00000010 +#define HLINK_USETAGSBOLD 0x00000030 +#define HLINK_NOTOOLTIP 0x00000040 + +// Notes: +// - HLINK_USETAGS and HLINK_USETAGSBOLD are always left-aligned +// - When HLINK_USETAGSBOLD is used, the underlined styles will be ignored + +template +class ATL_NO_VTABLE CHyperLinkImpl : public ATL::CWindowImpl< T, TBase, TWinTraits > +{ +public: + LPTSTR m_lpstrLabel; + LPTSTR m_lpstrHyperLink; + + HCURSOR m_hCursor; + HFONT m_hFont; + HFONT m_hFontNormal; + + RECT m_rcLink; +#ifndef _WIN32_WCE + CToolTipCtrl m_tip; +#endif // !_WIN32_WCE + + COLORREF m_clrLink; + COLORREF m_clrVisited; + + DWORD m_dwExtendedStyle; // Hyper Link specific extended styles + + bool m_bPaintLabel:1; + bool m_bVisited:1; + bool m_bHover:1; + bool m_bInternalLinkFont:1; + + +// Constructor/Destructor + CHyperLinkImpl(DWORD dwExtendedStyle = HLINK_UNDERLINED) : + m_lpstrLabel(NULL), m_lpstrHyperLink(NULL), + m_hCursor(NULL), m_hFont(NULL), m_hFontNormal(NULL), + m_clrLink(RGB(0, 0, 255)), m_clrVisited(RGB(128, 0, 128)), + m_dwExtendedStyle(dwExtendedStyle), + m_bPaintLabel(true), m_bVisited(false), + m_bHover(false), m_bInternalLinkFont(false) + { + ::SetRectEmpty(&m_rcLink); + } + + ~CHyperLinkImpl() + { + delete [] m_lpstrLabel; + delete [] m_lpstrHyperLink; + if(m_bInternalLinkFont && m_hFont != NULL) + ::DeleteObject(m_hFont); +#if (WINVER < 0x0500) && !defined(_WIN32_WCE) + // It was created, not loaded, so we have to destroy it + if(m_hCursor != NULL) + ::DestroyCursor(m_hCursor); +#endif // (WINVER < 0x0500) && !defined(_WIN32_WCE) + } + +// Attributes + DWORD GetHyperLinkExtendedStyle() const + { + return m_dwExtendedStyle; + } + + DWORD SetHyperLinkExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) + { + DWORD dwPrevStyle = m_dwExtendedStyle; + if(dwMask == 0) + m_dwExtendedStyle = dwExtendedStyle; + else + m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); + return dwPrevStyle; + } + + bool GetLabel(LPTSTR lpstrBuffer, int nLength) const + { + if(m_lpstrLabel == NULL) + return false; + ATLASSERT(lpstrBuffer != NULL); + if(nLength <= lstrlen(m_lpstrLabel)) + return false; + + SecureHelper::strcpy_x(lpstrBuffer, nLength, m_lpstrLabel); + + return true; + } + + bool SetLabel(LPCTSTR lpstrLabel) + { + delete [] m_lpstrLabel; + m_lpstrLabel = NULL; + int cchLen = lstrlen(lpstrLabel) + 1; + ATLTRY(m_lpstrLabel = new TCHAR[cchLen]); + if(m_lpstrLabel == NULL) + return false; + + SecureHelper::strcpy_x(m_lpstrLabel, cchLen, lpstrLabel); + T* pT = static_cast(this); + pT->CalcLabelRect(); + + if(m_hWnd != NULL) + SetWindowText(lpstrLabel); // Set this for accessibility + + return true; + } + + bool GetHyperLink(LPTSTR lpstrBuffer, int nLength) const + { + if(m_lpstrHyperLink == NULL) + return false; + ATLASSERT(lpstrBuffer != NULL); + if(nLength <= lstrlen(m_lpstrHyperLink)) + return false; + + SecureHelper::strcpy_x(lpstrBuffer, nLength, m_lpstrHyperLink); + + return true; + } + + bool SetHyperLink(LPCTSTR lpstrLink) + { + delete [] m_lpstrHyperLink; + m_lpstrHyperLink = NULL; + int cchLen = lstrlen(lpstrLink) + 1; + ATLTRY(m_lpstrHyperLink = new TCHAR[cchLen]); + if(m_lpstrHyperLink == NULL) + return false; + + SecureHelper::strcpy_x(m_lpstrHyperLink, cchLen, lpstrLink); + if(m_lpstrLabel == NULL) + { + T* pT = static_cast(this); + pT->CalcLabelRect(); + } +#ifndef _WIN32_WCE + if(m_tip.IsWindow()) + { + m_tip.Activate(TRUE); + m_tip.AddTool(m_hWnd, m_lpstrHyperLink, &m_rcLink, 1); + } +#endif // !_WIN32_WCE + return true; + } + + HFONT GetLinkFont() const + { + return m_hFont; + } + + void SetLinkFont(HFONT hFont) + { + if(m_bInternalLinkFont && m_hFont != NULL) + { + ::DeleteObject(m_hFont); + m_bInternalLinkFont = false; + } + m_hFont = hFont; + } + + int GetIdealHeight() const + { + ATLASSERT(::IsWindow(m_hWnd)); + if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL) + return -1; + if(!m_bPaintLabel) + return -1; + + CClientDC dc(m_hWnd); + RECT rect = { 0 }; + GetClientRect(&rect); + HFONT hFontOld = dc.SelectFont(m_hFontNormal); + RECT rcText = rect; + dc.DrawText(_T("NS"), -1, &rcText, DT_LEFT | DT_WORDBREAK | DT_CALCRECT); + dc.SelectFont(m_hFont); + RECT rcLink = rect; + dc.DrawText(_T("NS"), -1, &rcLink, DT_LEFT | DT_WORDBREAK | DT_CALCRECT); + dc.SelectFont(hFontOld); + return max(rcText.bottom - rcText.top, rcLink.bottom - rcLink.top); + } + + bool GetIdealSize(SIZE& size) const + { + int cx = 0, cy = 0; + bool bRet = GetIdealSize(cx, cy); + if(bRet) + { + size.cx = cx; + size.cy = cy; + } + return bRet; + } + + bool GetIdealSize(int& cx, int& cy) const + { + ATLASSERT(::IsWindow(m_hWnd)); + if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL) + return false; + if(!m_bPaintLabel) + return false; + + CClientDC dc(m_hWnd); + RECT rcClient = { 0 }; + GetClientRect(&rcClient); + RECT rcAll = rcClient; + + if(IsUsingTags()) + { + // find tags and label parts + LPTSTR lpstrLeft = NULL; + int cchLeft = 0; + LPTSTR lpstrLink = NULL; + int cchLink = 0; + LPTSTR lpstrRight = NULL; + int cchRight = 0; + + const T* pT = static_cast(this); + pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight); + + // get label part rects + HFONT hFontOld = dc.SelectFont(m_hFontNormal); + RECT rcLeft = rcClient; + dc.DrawText(lpstrLeft, cchLeft, &rcLeft, DT_LEFT | DT_WORDBREAK | DT_CALCRECT); + + dc.SelectFont(m_hFont); + RECT rcLink = { rcLeft.right, rcLeft.top, rcClient.right, rcClient.bottom }; + dc.DrawText(lpstrLink, cchLink, &rcLink, DT_LEFT | DT_WORDBREAK | DT_CALCRECT); + + dc.SelectFont(m_hFontNormal); + RECT rcRight = { rcLink.right, rcLink.top, rcClient.right, rcClient.bottom }; + dc.DrawText(lpstrRight, cchRight, &rcRight, DT_LEFT | DT_WORDBREAK | DT_CALCRECT); + + dc.SelectFont(hFontOld); + + int cyMax = max(rcLeft.bottom, max(rcLink.bottom, rcRight.bottom)); + ::SetRect(&rcAll, rcLeft.left, rcLeft.top, rcRight.right, cyMax); + } + else + { + HFONT hOldFont = NULL; + if(m_hFont != NULL) + hOldFont = dc.SelectFont(m_hFont); + LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink; + DWORD dwStyle = GetStyle(); + int nDrawStyle = DT_LEFT; + if (dwStyle & SS_CENTER) + nDrawStyle = DT_CENTER; + else if (dwStyle & SS_RIGHT) + nDrawStyle = DT_RIGHT; + dc.DrawText(lpstrText, -1, &rcAll, nDrawStyle | DT_WORDBREAK | DT_CALCRECT); + if(m_hFont != NULL) + dc.SelectFont(hOldFont); + if (dwStyle & SS_CENTER) + { + int dx = (rcClient.right - rcAll.right) / 2; + ::OffsetRect(&rcAll, dx, 0); + } + else if (dwStyle & SS_RIGHT) + { + int dx = rcClient.right - rcAll.right; + ::OffsetRect(&rcAll, dx, 0); + } + } + + cx = rcAll.right - rcAll.left; + cy = rcAll.bottom - rcAll.top; + + return true; + } + + // for command buttons only + bool GetToolTipText(LPTSTR lpstrBuffer, int nLength) const + { + ATLASSERT(IsCommandButton()); + return GetHyperLink(lpstrBuffer, nLength); + } + + bool SetToolTipText(LPCTSTR lpstrToolTipText) + { + ATLASSERT(IsCommandButton()); + return SetHyperLink(lpstrToolTipText); + } + +// Operations + BOOL SubclassWindow(HWND hWnd) + { + ATLASSERT(m_hWnd == NULL); + ATLASSERT(::IsWindow(hWnd)); +#if (_MSC_VER >= 1300) + BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits>::SubclassWindow(hWnd); +#else // !(_MSC_VER >= 1300) + typedef ATL::CWindowImpl< T, TBase, TWinTraits> _baseClass; + BOOL bRet = _baseClass::SubclassWindow(hWnd); +#endif // !(_MSC_VER >= 1300) + if(bRet) + { + T* pT = static_cast(this); + pT->Init(); + } + return bRet; + } + + bool Navigate() + { + ATLASSERT(::IsWindow(m_hWnd)); + bool bRet = true; + if(IsNotifyButton()) + { + NMHDR nmhdr = { m_hWnd, GetDlgCtrlID(), NM_CLICK }; + ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmhdr); + } + else if(IsCommandButton()) + { + ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd); + } + else + { + ATLASSERT(m_lpstrHyperLink != NULL); +#ifndef _WIN32_WCE + DWORD_PTR dwRet = (DWORD_PTR)::ShellExecute(0, _T("open"), m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL); + bRet = (dwRet > 32); +#else // CE specific + SHELLEXECUTEINFO shExeInfo = { sizeof(SHELLEXECUTEINFO), 0, 0, L"open", m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL, 0, 0, 0, 0, 0, 0, 0 }; + ::ShellExecuteEx(&shExeInfo); + DWORD_PTR dwRet = (DWORD_PTR)shExeInfo.hInstApp; + bRet = (dwRet == 0) || (dwRet > 32); +#endif // _WIN32_WCE + ATLASSERT(bRet); + if(bRet) + { + m_bVisited = true; + Invalidate(); + } + } + return bRet; + } + +// Message map and handlers + BEGIN_MSG_MAP(CHyperLinkImpl) + MESSAGE_HANDLER(WM_CREATE, OnCreate) +#ifndef _WIN32_WCE + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) + MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage) +#endif // !_WIN32_WCE + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) + MESSAGE_HANDLER(WM_PAINT, OnPaint) +#ifndef _WIN32_WCE + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) +#endif // !_WIN32_WCE + MESSAGE_HANDLER(WM_SETFOCUS, OnFocus) + MESSAGE_HANDLER(WM_KILLFOCUS, OnFocus) + MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) +#ifndef _WIN32_WCE + MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave) +#endif // !_WIN32_WCE + MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) + MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) + MESSAGE_HANDLER(WM_CHAR, OnChar) + MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode) + MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor) + MESSAGE_HANDLER(WM_ENABLE, OnEnable) + MESSAGE_HANDLER(WM_GETFONT, OnGetFont) + MESSAGE_HANDLER(WM_SETFONT, OnSetFont) + MESSAGE_HANDLER(WM_UPDATEUISTATE, OnUpdateUiState) + MESSAGE_HANDLER(WM_SIZE, OnSize) + END_MSG_MAP() + + LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->Init(); + return 0; + } + +#ifndef _WIN32_WCE + LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + if(m_tip.IsWindow()) + { + m_tip.DestroyWindow(); + m_tip.m_hWnd = NULL; + } + bHandled = FALSE; + return 1; + } + + LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + MSG msg = { m_hWnd, uMsg, wParam, lParam }; + if(m_tip.IsWindow() && IsUsingToolTip()) + m_tip.RelayEvent(&msg); + bHandled = FALSE; + return 1; + } +#endif // !_WIN32_WCE + + LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return 1; // no background painting needed (we do it all during WM_PAINT) + } + + LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + if(!m_bPaintLabel) + { + bHandled = FALSE; + return 1; + } + + T* pT = static_cast(this); + if(wParam != NULL) + { + pT->DoEraseBackground((HDC)wParam); + pT->DoPaint((HDC)wParam); + } + else + { + CPaintDC dc(m_hWnd); + pT->DoEraseBackground(dc.m_hDC); + pT->DoPaint(dc.m_hDC); + } + + return 0; + } + + LRESULT OnFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + if(m_bPaintLabel) + Invalidate(); + else + bHandled = FALSE; + return 0; + } + + LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + if((m_lpstrHyperLink != NULL || IsCommandButton()) && ::PtInRect(&m_rcLink, pt)) + { + ::SetCursor(m_hCursor); + if(IsUnderlineHover()) + { + if(!m_bHover) + { + m_bHover = true; + InvalidateRect(&m_rcLink); + UpdateWindow(); +#ifndef _WIN32_WCE + StartTrackMouseLeave(); +#endif // !_WIN32_WCE + } + } + } + else + { + if(IsUnderlineHover()) + { + if(m_bHover) + { + m_bHover = false; + InvalidateRect(&m_rcLink); + UpdateWindow(); + } + } + bHandled = FALSE; + } + return 0; + } + +#ifndef _WIN32_WCE + LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + if(IsUnderlineHover() && m_bHover) + { + m_bHover = false; + InvalidateRect(&m_rcLink); + UpdateWindow(); + } + return 0; + } +#endif // !_WIN32_WCE + + LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) + { + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + if(::PtInRect(&m_rcLink, pt)) + { + SetFocus(); + SetCapture(); + } + return 0; + } + + LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) + { + if(GetCapture() == m_hWnd) + { + ReleaseCapture(); + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + if(::PtInRect(&m_rcLink, pt)) + { + T* pT = static_cast(this); + pT->Navigate(); + } + } + return 0; + } + + LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + if(wParam == VK_RETURN || wParam == VK_SPACE) + { + T* pT = static_cast(this); + pT->Navigate(); + } + return 0; + } + + LRESULT OnGetDlgCode(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return DLGC_WANTCHARS; + } + + LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + POINT pt = { 0, 0 }; + GetCursorPos(&pt); + ScreenToClient(&pt); + if((m_lpstrHyperLink != NULL || IsCommandButton()) && ::PtInRect(&m_rcLink, pt)) + { + return TRUE; + } + bHandled = FALSE; + return FALSE; + } + + LRESULT OnEnable(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + Invalidate(); + UpdateWindow(); + return 0; + } + + LRESULT OnGetFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return (LRESULT)m_hFontNormal; + } + + LRESULT OnSetFont(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + m_hFontNormal = (HFONT)wParam; + if((BOOL)lParam) + { + Invalidate(); + UpdateWindow(); + } + return 0; + } + + LRESULT OnUpdateUiState(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + // If the control is subclassed or superclassed, this message can cause + // repainting without WM_PAINT. We don't use this state, so just do nothing. + return 0; + } + + LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->CalcLabelRect(); + pT->Invalidate(); + return 0; + } + +// Implementation + void Init() + { + ATLASSERT(::IsWindow(m_hWnd)); + + // Check if we should paint a label + const int cchBuff = 8; + TCHAR szBuffer[cchBuff] = { 0 }; + if(::GetClassName(m_hWnd, szBuffer, cchBuff)) + { + if(lstrcmpi(szBuffer, _T("static")) == 0) + { + ModifyStyle(0, SS_NOTIFY); // we need this + DWORD dwStyle = GetStyle() & 0x000000FF; +#ifndef _WIN32_WCE + if(dwStyle == SS_ICON || dwStyle == SS_BLACKRECT || dwStyle == SS_GRAYRECT || + dwStyle == SS_WHITERECT || dwStyle == SS_BLACKFRAME || dwStyle == SS_GRAYFRAME || + dwStyle == SS_WHITEFRAME || dwStyle == SS_OWNERDRAW || + dwStyle == SS_BITMAP || dwStyle == SS_ENHMETAFILE) +#else // CE specific + if(dwStyle == SS_ICON || dwStyle == SS_BITMAP) +#endif // _WIN32_WCE + m_bPaintLabel = false; + } + } + + // create or load a cursor +#if (WINVER >= 0x0500) || defined(_WIN32_WCE) + m_hCursor = ::LoadCursor(NULL, IDC_HAND); +#else + m_hCursor = ::CreateCursor(ModuleHelper::GetModuleInstance(), _AtlHyperLink_CursorData.xHotSpot, _AtlHyperLink_CursorData.yHotSpot, _AtlHyperLink_CursorData.cxWidth, _AtlHyperLink_CursorData.cyHeight, _AtlHyperLink_CursorData.arrANDPlane, _AtlHyperLink_CursorData.arrXORPlane); +#endif + ATLASSERT(m_hCursor != NULL); + + // set font + if(m_bPaintLabel) + { + ATL::CWindow wnd = GetParent(); + m_hFontNormal = wnd.GetFont(); + if(m_hFontNormal == NULL) + m_hFontNormal = (HFONT)::GetStockObject(SYSTEM_FONT); + if(m_hFontNormal != NULL && m_hFont == NULL) + { + LOGFONT lf = { 0 }; + CFontHandle font = m_hFontNormal; + font.GetLogFont(&lf); + if(IsUsingTagsBold()) + lf.lfWeight = FW_BOLD; + else if(!IsNotUnderlined()) + lf.lfUnderline = TRUE; + m_hFont = ::CreateFontIndirect(&lf); + m_bInternalLinkFont = true; + ATLASSERT(m_hFont != NULL); + } + } + +#ifndef _WIN32_WCE + // create a tool tip + m_tip.Create(m_hWnd); + ATLASSERT(m_tip.IsWindow()); +#endif // !_WIN32_WCE + + // set label (defaults to window text) + if(m_lpstrLabel == NULL) + { + int nLen = GetWindowTextLength(); + if(nLen > 0) + { + CTempBuffer buff; + LPTSTR lpstrText = buff.Allocate(nLen + 1); + ATLASSERT(lpstrText != NULL); + if((lpstrText != NULL) && (GetWindowText(lpstrText, nLen + 1) > 0)) + SetLabel(lpstrText); + } + } + + T* pT = static_cast(this); + pT->CalcLabelRect(); + + // set hyperlink (defaults to label), or just activate tool tip if already set + if(m_lpstrHyperLink == NULL && !IsCommandButton()) + { + if(m_lpstrLabel != NULL) + SetHyperLink(m_lpstrLabel); + } +#ifndef _WIN32_WCE + else + { + m_tip.Activate(TRUE); + m_tip.AddTool(m_hWnd, m_lpstrHyperLink, &m_rcLink, 1); + } +#endif // !_WIN32_WCE + + // set link colors + if(m_bPaintLabel) + { + ATL::CRegKey rk; + LONG lRet = rk.Open(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Internet Explorer\\Settings")); + if(lRet == 0) + { + const int cchValue = 12; + TCHAR szValue[cchValue] = { 0 }; +#if (_ATL_VER >= 0x0700) + ULONG ulCount = cchValue; + lRet = rk.QueryStringValue(_T("Anchor Color"), szValue, &ulCount); +#else + DWORD dwCount = cchValue * sizeof(TCHAR); + lRet = rk.QueryValue(szValue, _T("Anchor Color"), &dwCount); +#endif + if(lRet == 0) + { + COLORREF clr = pT->_ParseColorString(szValue); + ATLASSERT(clr != CLR_INVALID); + if(clr != CLR_INVALID) + m_clrLink = clr; + } + +#if (_ATL_VER >= 0x0700) + ulCount = cchValue; + lRet = rk.QueryStringValue(_T("Anchor Color Visited"), szValue, &ulCount); +#else + dwCount = cchValue * sizeof(TCHAR); + lRet = rk.QueryValue(szValue, _T("Anchor Color Visited"), &dwCount); +#endif + if(lRet == 0) + { + COLORREF clr = pT->_ParseColorString(szValue); + ATLASSERT(clr != CLR_INVALID); + if(clr != CLR_INVALID) + m_clrVisited = clr; + } + } + } + } + + static COLORREF _ParseColorString(LPTSTR lpstr) + { + int c[3] = { -1, -1, -1 }; + LPTSTR p = NULL; + for(int i = 0; i < 2; i++) + { + for(p = lpstr; *p != _T('\0'); p = ::CharNext(p)) + { + if(*p == _T(',')) + { + *p = _T('\0'); + c[i] = T::_xttoi(lpstr); + lpstr = &p[1]; + break; + } + } + if(c[i] == -1) + return CLR_INVALID; + } + if(*lpstr == _T('\0')) + return CLR_INVALID; + c[2] = T::_xttoi(lpstr); + + return RGB(c[0], c[1], c[2]); + } + + bool CalcLabelRect() + { + if(!::IsWindow(m_hWnd)) + return false; + if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL) + return false; + + CClientDC dc(m_hWnd); + RECT rcClient = { 0 }; + GetClientRect(&rcClient); + m_rcLink = rcClient; + if(!m_bPaintLabel) + return true; + + if(IsUsingTags()) + { + // find tags and label parts + LPTSTR lpstrLeft = NULL; + int cchLeft = 0; + LPTSTR lpstrLink = NULL; + int cchLink = 0; + LPTSTR lpstrRight = NULL; + int cchRight = 0; + + T* pT = static_cast(this); + pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight); + ATLASSERT(lpstrLink != NULL); + ATLASSERT(cchLink > 0); + + // get label part rects + HFONT hFontOld = dc.SelectFont(m_hFontNormal); + + RECT rcLeft = rcClient; + if(lpstrLeft != NULL) + dc.DrawText(lpstrLeft, cchLeft, &rcLeft, DT_LEFT | DT_WORDBREAK | DT_CALCRECT); + + dc.SelectFont(m_hFont); + RECT rcLink = rcClient; + if(lpstrLeft != NULL) + rcLink.left = rcLeft.right; + dc.DrawText(lpstrLink, cchLink, &rcLink, DT_LEFT | DT_WORDBREAK | DT_CALCRECT); + + dc.SelectFont(hFontOld); + + m_rcLink = rcLink; + } + else + { + HFONT hOldFont = NULL; + if(m_hFont != NULL) + hOldFont = dc.SelectFont(m_hFont); + LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink; + DWORD dwStyle = GetStyle(); + int nDrawStyle = DT_LEFT; + if (dwStyle & SS_CENTER) + nDrawStyle = DT_CENTER; + else if (dwStyle & SS_RIGHT) + nDrawStyle = DT_RIGHT; + dc.DrawText(lpstrText, -1, &m_rcLink, nDrawStyle | DT_WORDBREAK | DT_CALCRECT); + if(m_hFont != NULL) + dc.SelectFont(hOldFont); + if (dwStyle & SS_CENTER) + { + int dx = (rcClient.right - m_rcLink.right) / 2; + ::OffsetRect(&m_rcLink, dx, 0); + } + else if (dwStyle & SS_RIGHT) + { + int dx = rcClient.right - m_rcLink.right; + ::OffsetRect(&m_rcLink, dx, 0); + } + } + + return true; + } + + void CalcLabelParts(LPTSTR& lpstrLeft, int& cchLeft, LPTSTR& lpstrLink, int& cchLink, LPTSTR& lpstrRight, int& cchRight) const + { + lpstrLeft = NULL; + cchLeft = 0; + lpstrLink = NULL; + cchLink = 0; + lpstrRight = NULL; + cchRight = 0; + + LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink; + int cchText = lstrlen(lpstrText); + bool bOutsideLink = true; + for(int i = 0; i < cchText; i++) + { + if(lpstrText[i] != _T('<')) + continue; + + if(bOutsideLink) + { + if(::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, &lpstrText[i], 3, _T(""), 3) == CSTR_EQUAL) + { + if(i > 0) + { + lpstrLeft = lpstrText; + cchLeft = i; + } + lpstrLink = &lpstrText[i + 3]; + bOutsideLink = false; + } + } + else + { + if(::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, &lpstrText[i], 4, _T(""), 4) == CSTR_EQUAL) + { + cchLink = i - 3 - cchLeft; + if(lpstrText[i + 4] != 0) + { + lpstrRight = &lpstrText[i + 4]; + cchRight = cchText - (i + 4); + break; + } + } + } + } + + } + + void DoEraseBackground(CDCHandle dc) + { + HBRUSH hBrush = (HBRUSH)::SendMessage(GetParent(), WM_CTLCOLORSTATIC, (WPARAM)dc.m_hDC, (LPARAM)m_hWnd); + if(hBrush != NULL) + { + RECT rect = { 0 }; + GetClientRect(&rect); + dc.FillRect(&rect, hBrush); + } + } + + void DoPaint(CDCHandle dc) + { + if(IsUsingTags()) + { + // find tags and label parts + LPTSTR lpstrLeft = NULL; + int cchLeft = 0; + LPTSTR lpstrLink = NULL; + int cchLink = 0; + LPTSTR lpstrRight = NULL; + int cchRight = 0; + + T* pT = static_cast(this); + pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight); + + // get label part rects + RECT rcClient = { 0 }; + GetClientRect(&rcClient); + + dc.SetBkMode(TRANSPARENT); + HFONT hFontOld = dc.SelectFont(m_hFontNormal); + + if(lpstrLeft != NULL) + dc.DrawText(lpstrLeft, cchLeft, &rcClient, DT_LEFT | DT_WORDBREAK); + + COLORREF clrOld = dc.SetTextColor(IsWindowEnabled() ? (m_bVisited ? m_clrVisited : m_clrLink) : (::GetSysColor(COLOR_GRAYTEXT))); + if(m_hFont != NULL && (!IsUnderlineHover() || (IsUnderlineHover() && m_bHover))) + dc.SelectFont(m_hFont); + else + dc.SelectFont(m_hFontNormal); + + dc.DrawText(lpstrLink, cchLink, &m_rcLink, DT_LEFT | DT_WORDBREAK); + + dc.SetTextColor(clrOld); + dc.SelectFont(m_hFontNormal); + if(lpstrRight != NULL) + { + RECT rcRight = { m_rcLink.right, m_rcLink.top, rcClient.right, rcClient.bottom }; + dc.DrawText(lpstrRight, cchRight, &rcRight, DT_LEFT | DT_WORDBREAK); + } + + if(GetFocus() == m_hWnd) + dc.DrawFocusRect(&m_rcLink); + + dc.SelectFont(hFontOld); + } + else + { + dc.SetBkMode(TRANSPARENT); + COLORREF clrOld = dc.SetTextColor(IsWindowEnabled() ? (m_bVisited ? m_clrVisited : m_clrLink) : (::GetSysColor(COLOR_GRAYTEXT))); + + HFONT hFontOld = NULL; + if(m_hFont != NULL && (!IsUnderlineHover() || (IsUnderlineHover() && m_bHover))) + hFontOld = dc.SelectFont(m_hFont); + else + hFontOld = dc.SelectFont(m_hFontNormal); + + LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink; + + DWORD dwStyle = GetStyle(); + int nDrawStyle = DT_LEFT; + if (dwStyle & SS_CENTER) + nDrawStyle = DT_CENTER; + else if (dwStyle & SS_RIGHT) + nDrawStyle = DT_RIGHT; + + dc.DrawText(lpstrText, -1, &m_rcLink, nDrawStyle | DT_WORDBREAK); + + if(GetFocus() == m_hWnd) + dc.DrawFocusRect(&m_rcLink); + + dc.SetTextColor(clrOld); + dc.SelectFont(hFontOld); + } + } + +#ifndef _WIN32_WCE + BOOL StartTrackMouseLeave() + { + TRACKMOUSEEVENT tme = { 0 }; + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = m_hWnd; + return _TrackMouseEvent(&tme); + } +#endif // !_WIN32_WCE + +// Implementation helpers + bool IsUnderlined() const + { + return ((m_dwExtendedStyle & (HLINK_NOTUNDERLINED | HLINK_UNDERLINEHOVER)) == 0); + } + + bool IsNotUnderlined() const + { + return ((m_dwExtendedStyle & HLINK_NOTUNDERLINED) != 0); + } + + bool IsUnderlineHover() const + { + return ((m_dwExtendedStyle & HLINK_UNDERLINEHOVER) != 0); + } + + bool IsCommandButton() const + { + return ((m_dwExtendedStyle & HLINK_COMMANDBUTTON) != 0); + } + + bool IsNotifyButton() const + { + return ((m_dwExtendedStyle & HLINK_NOTIFYBUTTON) == HLINK_NOTIFYBUTTON); + } + + bool IsUsingTags() const + { + return ((m_dwExtendedStyle & HLINK_USETAGS) != 0); + } + + bool IsUsingTagsBold() const + { + return ((m_dwExtendedStyle & HLINK_USETAGSBOLD) == HLINK_USETAGSBOLD); + } + + bool IsUsingToolTip() const + { + return ((m_dwExtendedStyle & HLINK_NOTOOLTIP) == 0); + } + + static int _xttoi(const TCHAR* nptr) + { +#ifndef _ATL_MIN_CRT + return _ttoi(nptr); +#else // _ATL_MIN_CRT + while(*nptr == _T(' ')) // skip spaces + ++nptr; + + int c = (int)(_TUCHAR)*nptr++; + int sign = c; // save sign indication + if (c == _T('-') || c == _T('+')) + c = (int)(_TUCHAR)*nptr++; // skip sign + + int total = 0; + while((TCHAR)c >= _T('0') && (TCHAR)c <= _T('9')) + { + total = 10 * total + ((TCHAR)c - _T('0')); // accumulate digit + c = (int)(_TUCHAR)*nptr++; // get next char + } + + // return result, negated if necessary + return ((TCHAR)sign != _T('-')) ? total : -total; +#endif // _ATL_MIN_CRT + } +}; + + +class CHyperLink : public CHyperLinkImpl +{ +public: + DECLARE_WND_CLASS(_T("WTL_HyperLink")) +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CWaitCursor - displays a wait cursor + +class CWaitCursor +{ +public: +// Data + HCURSOR m_hWaitCursor; + HCURSOR m_hOldCursor; + bool m_bInUse; + +// Constructor/destructor + CWaitCursor(bool bSet = true, LPCTSTR lpstrCursor = IDC_WAIT, bool bSys = true) : m_hOldCursor(NULL), m_bInUse(false) + { + HINSTANCE hInstance = bSys ? NULL : ModuleHelper::GetResourceInstance(); + m_hWaitCursor = ::LoadCursor(hInstance, lpstrCursor); + ATLASSERT(m_hWaitCursor != NULL); + + if(bSet) + Set(); + } + + ~CWaitCursor() + { + Restore(); + } + +// Methods + bool Set() + { + if(m_bInUse) + return false; + m_hOldCursor = ::SetCursor(m_hWaitCursor); + m_bInUse = true; + return true; + } + + bool Restore() + { + if(!m_bInUse) + return false; + ::SetCursor(m_hOldCursor); + m_bInUse = false; + return true; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CCustomWaitCursor - for custom and animated cursors + +class CCustomWaitCursor : public CWaitCursor +{ +public: +// Constructor/destructor + CCustomWaitCursor(ATL::_U_STRINGorID cursor, bool bSet = true, HINSTANCE hInstance = NULL) : + CWaitCursor(false, IDC_WAIT, true) + { + if(hInstance == NULL) + hInstance = ModuleHelper::GetResourceInstance(); + m_hWaitCursor = (HCURSOR)::LoadImage(hInstance, cursor.m_lpstr, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE); + + if(bSet) + Set(); + } + + ~CCustomWaitCursor() + { + Restore(); +#if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))) + ::DestroyCursor(m_hWaitCursor); +#endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))) + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CMultiPaneStatusBarCtrl - Status Bar with multiple panes + +template +class ATL_NO_VTABLE CMultiPaneStatusBarCtrlImpl : public ATL::CWindowImpl< T, TBase > +{ +public: + DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName()) + +// Data + enum { m_cxPaneMargin = 3 }; + + int m_nPanes; + int* m_pPane; + +// Constructor/destructor + CMultiPaneStatusBarCtrlImpl() : m_nPanes(0), m_pPane(NULL) + { } + + ~CMultiPaneStatusBarCtrlImpl() + { + delete [] m_pPane; + } + +// Methods + HWND Create(HWND hWndParent, LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR) + { +#if (_MSC_VER >= 1300) + return ATL::CWindowImpl< T, TBase >::Create(hWndParent, rcDefault, lpstrText, dwStyle, 0, nID); +#else // !(_MSC_VER >= 1300) + typedef ATL::CWindowImpl< T, TBase > _baseClass; + return _baseClass::Create(hWndParent, rcDefault, lpstrText, dwStyle, 0, nID); +#endif // !(_MSC_VER >= 1300) + } + + HWND Create(HWND hWndParent, UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR) + { + const int cchMax = 128; // max text length is 127 for status bars (+1 for null) + TCHAR szText[cchMax]; + szText[0] = 0; + ::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szText, cchMax); + return Create(hWndParent, szText, dwStyle, nID); + } + + BOOL SetPanes(int* pPanes, int nPanes, bool bSetText = true) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nPanes > 0); + + m_nPanes = nPanes; + delete [] m_pPane; + m_pPane = NULL; + + ATLTRY(m_pPane = new int[nPanes]); + ATLASSERT(m_pPane != NULL); + if(m_pPane == NULL) + return FALSE; + + CTempBuffer buff; + int* pPanesPos = buff.Allocate(nPanes); + ATLASSERT(pPanesPos != NULL); + if(pPanesPos == NULL) + return FALSE; + + SecureHelper::memcpy_x(m_pPane, nPanes * sizeof(int), pPanes, nPanes * sizeof(int)); + + // get status bar DC and set font + CClientDC dc(m_hWnd); + HFONT hOldFont = dc.SelectFont(GetFont()); + + // get status bar borders + int arrBorders[3] = { 0 }; + GetBorders(arrBorders); + + const int cchBuff = 128; + TCHAR szBuff[cchBuff] = { 0 }; + SIZE size = { 0, 0 }; + int cxLeft = arrBorders[0]; + + // calculate right edge of each part + for(int i = 0; i < nPanes; i++) + { + if(pPanes[i] == ID_DEFAULT_PANE) + { + // make very large, will be resized later + pPanesPos[i] = INT_MAX / 2; + } + else + { + ::LoadString(ModuleHelper::GetResourceInstance(), pPanes[i], szBuff, cchBuff); + dc.GetTextExtent(szBuff, lstrlen(szBuff), &size); + T* pT = static_cast(this); + pT; + pPanesPos[i] = cxLeft + size.cx + arrBorders[2] + 2 * pT->m_cxPaneMargin; + } + cxLeft = pPanesPos[i]; + } + + BOOL bRet = SetParts(nPanes, pPanesPos); + + if(bRet && bSetText) + { + for(int i = 0; i < nPanes; i++) + { + if(pPanes[i] != ID_DEFAULT_PANE) + { + ::LoadString(ModuleHelper::GetResourceInstance(), pPanes[i], szBuff, cchBuff); + SetPaneText(m_pPane[i], szBuff); + } + } + } + + dc.SelectFont(hOldFont); + return bRet; + } + + bool GetPaneTextLength(int nPaneID, int* pcchLength = NULL, int* pnType = NULL) const + { + ATLASSERT(::IsWindow(m_hWnd)); + int nIndex = GetPaneIndexFromID(nPaneID); + if(nIndex == -1) + return false; + + int nLength = GetTextLength(nIndex, pnType); + if(pcchLength != NULL) + *pcchLength = nLength; + + return true; + } + + BOOL GetPaneText(int nPaneID, LPTSTR lpstrText, int* pcchLength = NULL, int* pnType = NULL) const + { + ATLASSERT(::IsWindow(m_hWnd)); + int nIndex = GetPaneIndexFromID(nPaneID); + if(nIndex == -1) + return FALSE; + + int nLength = GetText(nIndex, lpstrText, pnType); + if(pcchLength != NULL) + *pcchLength = nLength; + + return TRUE; + } + + BOOL SetPaneText(int nPaneID, LPCTSTR lpstrText, int nType = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + int nIndex = GetPaneIndexFromID(nPaneID); + if(nIndex == -1) + return FALSE; + + return SetText(nIndex, lpstrText, nType); + } + + BOOL GetPaneRect(int nPaneID, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + int nIndex = GetPaneIndexFromID(nPaneID); + if(nIndex == -1) + return FALSE; + + return GetRect(nIndex, lpRect); + } + + BOOL SetPaneWidth(int nPaneID, int cxWidth) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nPaneID != ID_DEFAULT_PANE); // Can't resize this one + int nIndex = GetPaneIndexFromID(nPaneID); + if(nIndex == -1) + return FALSE; + + // get pane positions + CTempBuffer buff; + int* pPanesPos = buff.Allocate(m_nPanes); + if(pPanesPos == NULL) + return FALSE; + GetParts(m_nPanes, pPanesPos); + // calculate offset + int cxPaneWidth = pPanesPos[nIndex] - ((nIndex == 0) ? 0 : pPanesPos[nIndex - 1]); + int cxOff = cxWidth - cxPaneWidth; + // find variable width pane + int nDef = m_nPanes; + for(int i = 0; i < m_nPanes; i++) + { + if(m_pPane[i] == ID_DEFAULT_PANE) + { + nDef = i; + break; + } + } + // resize + if(nIndex < nDef) // before default pane + { + for(int i = nIndex; i < nDef; i++) + pPanesPos[i] += cxOff; + + } + else // after default one + { + for(int i = nDef; i < nIndex; i++) + pPanesPos[i] -= cxOff; + } + // set pane postions + return SetParts(m_nPanes, pPanesPos); + } + +#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + BOOL GetPaneTipText(int nPaneID, LPTSTR lpstrText, int nSize) const + { + ATLASSERT(::IsWindow(m_hWnd)); + int nIndex = GetPaneIndexFromID(nPaneID); + if(nIndex == -1) + return FALSE; + + GetTipText(nIndex, lpstrText, nSize); + return TRUE; + } + + BOOL SetPaneTipText(int nPaneID, LPCTSTR lpstrText) + { + ATLASSERT(::IsWindow(m_hWnd)); + int nIndex = GetPaneIndexFromID(nPaneID); + if(nIndex == -1) + return FALSE; + + SetTipText(nIndex, lpstrText); + return TRUE; + } +#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + +#if ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500)) + BOOL GetPaneIcon(int nPaneID, HICON& hIcon) const + { + ATLASSERT(::IsWindow(m_hWnd)); + int nIndex = GetPaneIndexFromID(nPaneID); + if(nIndex == -1) + return FALSE; + + hIcon = GetIcon(nIndex); + return TRUE; + } + + BOOL SetPaneIcon(int nPaneID, HICON hIcon) + { + ATLASSERT(::IsWindow(m_hWnd)); + int nIndex = GetPaneIndexFromID(nPaneID); + if(nIndex == -1) + return FALSE; + + return SetIcon(nIndex, hIcon); + } +#endif // ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500)) + +// Message map and handlers + BEGIN_MSG_MAP(CMultiPaneStatusBarCtrlImpl< T >) + MESSAGE_HANDLER(WM_SIZE, OnSize) + END_MSG_MAP() + + LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); + if(wParam != SIZE_MINIMIZED && m_nPanes > 0) + { + T* pT = static_cast(this); + pT->UpdatePanesLayout(); + } + return lRet; + } + +// Implementation + BOOL UpdatePanesLayout() + { + // get pane positions + CTempBuffer buff; + int* pPanesPos = buff.Allocate(m_nPanes); + ATLASSERT(pPanesPos != NULL); + if(pPanesPos == NULL) + return FALSE; + int nRet = GetParts(m_nPanes, pPanesPos); + ATLASSERT(nRet == m_nPanes); + if(nRet != m_nPanes) + return FALSE; + // calculate offset + RECT rcClient = { 0 }; + GetClientRect(&rcClient); + int cxOff = rcClient.right - pPanesPos[m_nPanes - 1]; +#ifndef _WIN32_WCE + // Move panes left if size grip box is present + if((GetStyle() & SBARS_SIZEGRIP) != 0) + cxOff -= ::GetSystemMetrics(SM_CXVSCROLL) + ::GetSystemMetrics(SM_CXEDGE); +#endif // !_WIN32_WCE + // find variable width pane + int i; + for(i = 0; i < m_nPanes; i++) + { + if(m_pPane[i] == ID_DEFAULT_PANE) + break; + } + // resize all panes from the variable one to the right + if((i < m_nPanes) && (pPanesPos[i] + cxOff) > ((i == 0) ? 0 : pPanesPos[i - 1])) + { + for(; i < m_nPanes; i++) + pPanesPos[i] += cxOff; + } + // set pane postions + return SetParts(m_nPanes, pPanesPos); + } + + int GetPaneIndexFromID(int nPaneID) const + { + for(int i = 0; i < m_nPanes; i++) + { + if(m_pPane[i] == nPaneID) + return i; + } + + return -1; // not found + } +}; + +class CMultiPaneStatusBarCtrl : public CMultiPaneStatusBarCtrlImpl +{ +public: + DECLARE_WND_SUPERCLASS(_T("WTL_MultiPaneStatusBar"), GetWndClassName()) +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CPaneContainer - provides header with title and close button for panes + +// pane container extended styles +#define PANECNT_NOCLOSEBUTTON 0x00000001 +#define PANECNT_VERTICAL 0x00000002 +#define PANECNT_FLATBORDER 0x00000004 +#define PANECNT_NOBORDER 0x00000008 + +template +class ATL_NO_VTABLE CPaneContainerImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CCustomDraw< T > +{ +public: + DECLARE_WND_CLASS_EX(NULL, 0, -1) + +// Constants + enum + { + m_cxyBorder = 2, + m_cxyTextOffset = 4, + m_cxyBtnOffset = 1, + + m_cchTitle = 80, + + m_cxImageTB = 13, + m_cyImageTB = 11, + m_cxyBtnAddTB = 7, + + m_cxToolBar = m_cxImageTB + m_cxyBtnAddTB + m_cxyBorder + m_cxyBtnOffset, + + m_xBtnImageLeft = 6, + m_yBtnImageTop = 5, + m_xBtnImageRight = 12, + m_yBtnImageBottom = 11, + + m_nCloseBtnID = ID_PANE_CLOSE + }; + +// Data members + CToolBarCtrl m_tb; + ATL::CWindow m_wndClient; + int m_cxyHeader; + TCHAR m_szTitle[m_cchTitle]; + DWORD m_dwExtendedStyle; // Pane container specific extended styles + + +// Constructor + CPaneContainerImpl() : m_cxyHeader(0), m_dwExtendedStyle(0) + { + m_szTitle[0] = 0; + } + +// Attributes + DWORD GetPaneContainerExtendedStyle() const + { + return m_dwExtendedStyle; + } + + DWORD SetPaneContainerExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) + { + DWORD dwPrevStyle = m_dwExtendedStyle; + if(dwMask == 0) + m_dwExtendedStyle = dwExtendedStyle; + else + m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); + if(m_hWnd != NULL) + { + T* pT = static_cast(this); + bool bUpdate = false; + + if(((dwPrevStyle & PANECNT_NOCLOSEBUTTON) != 0) && ((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) == 0)) // add close button + { + pT->CreateCloseButton(); + bUpdate = true; + } + else if(((dwPrevStyle & PANECNT_NOCLOSEBUTTON) == 0) && ((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) != 0)) // remove close button + { + pT->DestroyCloseButton(); + bUpdate = true; + } + + if((dwPrevStyle & PANECNT_VERTICAL) != (m_dwExtendedStyle & PANECNT_VERTICAL)) // change orientation + { + pT->CalcSize(); + bUpdate = true; + } + + if((dwPrevStyle & (PANECNT_FLATBORDER | PANECNT_NOBORDER)) != + (m_dwExtendedStyle & (PANECNT_FLATBORDER | PANECNT_NOBORDER))) // change border + { + bUpdate = true; + } + + if(bUpdate) + pT->UpdateLayout(); + } + return dwPrevStyle; + } + + HWND GetClient() const + { + return m_wndClient; + } + + HWND SetClient(HWND hWndClient) + { + HWND hWndOldClient = m_wndClient; + m_wndClient = hWndClient; + if(m_hWnd != NULL) + { + T* pT = static_cast(this); + pT->UpdateLayout(); + } + return hWndOldClient; + } + + BOOL GetTitle(LPTSTR lpstrTitle, int cchLength) const + { + ATLASSERT(lpstrTitle != NULL); + + errno_t nRet = SecureHelper::strncpy_x(lpstrTitle, cchLength, m_szTitle, _TRUNCATE); + + return (nRet == 0 || nRet == STRUNCATE); + } + + BOOL SetTitle(LPCTSTR lpstrTitle) + { + ATLASSERT(lpstrTitle != NULL); + + errno_t nRet = SecureHelper::strncpy_x(m_szTitle, m_cchTitle, lpstrTitle, _TRUNCATE); + bool bRet = (nRet == 0 || nRet == STRUNCATE); + if(bRet && m_hWnd != NULL) + { + T* pT = static_cast(this); + pT->UpdateLayout(); + } + + return bRet; + } + + int GetTitleLength() const + { + return lstrlen(m_szTitle); + } + +// Methods + HWND Create(HWND hWndParent, LPCTSTR lpstrTitle = NULL, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, + DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL) + { + if(lpstrTitle != NULL) + SecureHelper::strncpy_x(m_szTitle, m_cchTitle, lpstrTitle, _TRUNCATE); +#if (_MSC_VER >= 1300) + return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam); +#else // !(_MSC_VER >= 1300) + typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass; + return _baseClass::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam); +#endif // !(_MSC_VER >= 1300) + } + + HWND Create(HWND hWndParent, UINT uTitleID, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, + DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL) + { + if(uTitleID != 0U) + ::LoadString(ModuleHelper::GetResourceInstance(), uTitleID, m_szTitle, m_cchTitle); +#if (_MSC_VER >= 1300) + return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam); +#else // !(_MSC_VER >= 1300) + typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass; + return _baseClass::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam); +#endif // !(_MSC_VER >= 1300) + } + + BOOL EnableCloseButton(BOOL bEnable) + { + ATLASSERT(::IsWindow(m_hWnd)); + T* pT = static_cast(this); + pT; // avoid level 4 warning + return (m_tb.m_hWnd != NULL) ? m_tb.EnableButton(pT->m_nCloseBtnID, bEnable) : FALSE; + } + + void UpdateLayout() + { + RECT rcClient = { 0 }; + GetClientRect(&rcClient); + T* pT = static_cast(this); + pT->UpdateLayout(rcClient.right, rcClient.bottom); + } + +// Message map and handlers + BEGIN_MSG_MAP(CPaneContainerImpl) + MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_SIZE, OnSize) + MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) + MESSAGE_HANDLER(WM_PAINT, OnPaint) +#ifndef _WIN32_WCE + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) +#endif // !_WIN32_WCE + MESSAGE_HANDLER(WM_NOTIFY, OnNotify) + MESSAGE_HANDLER(WM_COMMAND, OnCommand) + FORWARD_NOTIFICATIONS() + END_MSG_MAP() + + LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->CalcSize(); + + if((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) == 0) + pT->CreateCloseButton(); + + return 0; + } + + LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->UpdateLayout(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + return 0; + } + + LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + if(m_wndClient.m_hWnd != NULL) + m_wndClient.SetFocus(); + return 0; + } + + LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return 1; // no background needed + } + + LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + if(wParam != NULL) + { + pT->DrawPaneTitle((HDC)wParam); + + if(m_wndClient.m_hWnd == NULL) // no client window + pT->DrawPane((HDC)wParam); + } + else + { + CPaintDC dc(m_hWnd); + pT->DrawPaneTitle(dc.m_hDC); + + if(m_wndClient.m_hWnd == NULL) // no client window + pT->DrawPane(dc.m_hDC); + } + + return 0; + } + + LRESULT OnNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + if(m_tb.m_hWnd == NULL) + { + bHandled = FALSE; + return 1; + } + + T* pT = static_cast(this); + pT; + LPNMHDR lpnmh = (LPNMHDR)lParam; + LRESULT lRet = 0; + + // pass toolbar custom draw notifications to the base class + if(lpnmh->code == NM_CUSTOMDRAW && lpnmh->hwndFrom == m_tb.m_hWnd) + lRet = CCustomDraw< T >::OnCustomDraw(0, lpnmh, bHandled); +#ifndef _WIN32_WCE + // tooltip notifications come with the tooltip window handle and button ID, + // pass them to the parent if we don't handle them + else if(lpnmh->code == TTN_GETDISPINFO && lpnmh->idFrom == pT->m_nCloseBtnID) + bHandled = pT->GetToolTipText(lpnmh); +#endif // !_WIN32_WCE + // only let notifications not from the toolbar go to the parent + else if(lpnmh->hwndFrom != m_tb.m_hWnd && lpnmh->idFrom != pT->m_nCloseBtnID) + bHandled = FALSE; + + return lRet; + } + + LRESULT OnCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + // if command comes from the close button, substitute HWND of the pane container instead + if(m_tb.m_hWnd != NULL && (HWND)lParam == m_tb.m_hWnd) + return ::SendMessage(GetParent(), WM_COMMAND, wParam, (LPARAM)m_hWnd); + + bHandled = FALSE; + return 1; + } + +// Custom draw overrides + DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) + { + return CDRF_NOTIFYITEMDRAW; // we need per-item notifications + } + + DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw) + { + CDCHandle dc = lpNMCustomDraw->hdc; +#if (_WIN32_IE >= 0x0400) + RECT& rc = lpNMCustomDraw->rc; +#else // !(_WIN32_IE >= 0x0400) + RECT rc; + m_tb.GetItemRect(0, &rc); +#endif // !(_WIN32_IE >= 0x0400) + + dc.FillRect(&rc, COLOR_3DFACE); + + return CDRF_NOTIFYPOSTPAINT; + } + + DWORD OnItemPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw) + { + CDCHandle dc = lpNMCustomDraw->hdc; +#if (_WIN32_IE >= 0x0400) + RECT& rc = lpNMCustomDraw->rc; +#else // !(_WIN32_IE >= 0x0400) + RECT rc = { 0 }; + m_tb.GetItemRect(0, &rc); +#endif // !(_WIN32_IE >= 0x0400) + + RECT rcImage = { m_xBtnImageLeft, m_yBtnImageTop, m_xBtnImageRight + 1, m_yBtnImageBottom + 1 }; + ::OffsetRect(&rcImage, rc.left, rc.top); + T* pT = static_cast(this); + + if((lpNMCustomDraw->uItemState & CDIS_DISABLED) != 0) + { + RECT rcShadow = rcImage; + ::OffsetRect(&rcShadow, 1, 1); + CPen pen1; + pen1.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_3DHILIGHT)); + pT->DrawButtonImage(dc, rcShadow, pen1); + CPen pen2; + pen2.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_3DSHADOW)); + pT->DrawButtonImage(dc, rcImage, pen2); + } + else + { + if((lpNMCustomDraw->uItemState & CDIS_SELECTED) != 0) + ::OffsetRect(&rcImage, 1, 1); + CPen pen; + pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNTEXT)); + pT->DrawButtonImage(dc, rcImage, pen); + } + + return CDRF_DODEFAULT; // continue with the default item painting + } + +// Implementation - overrideable methods + void UpdateLayout(int cxWidth, int cyHeight) + { + ATLASSERT(::IsWindow(m_hWnd)); + RECT rect = { 0 }; + + if(IsVertical()) + { + ::SetRect(&rect, 0, 0, m_cxyHeader, cyHeight); + if(m_tb.m_hWnd != NULL) + m_tb.SetWindowPos(NULL, m_cxyBorder, m_cxyBorder + m_cxyBtnOffset, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); + + if(m_wndClient.m_hWnd != NULL) + m_wndClient.SetWindowPos(NULL, m_cxyHeader, 0, cxWidth - m_cxyHeader, cyHeight, SWP_NOZORDER); + else + rect.right = cxWidth; + } + else + { + ::SetRect(&rect, 0, 0, cxWidth, m_cxyHeader); + if(m_tb.m_hWnd != NULL) + m_tb.SetWindowPos(NULL, rect.right - m_cxToolBar, m_cxyBorder + m_cxyBtnOffset, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); + + if(m_wndClient.m_hWnd != NULL) + m_wndClient.SetWindowPos(NULL, 0, m_cxyHeader, cxWidth, cyHeight - m_cxyHeader, SWP_NOZORDER); + else + rect.bottom = cyHeight; + } + + InvalidateRect(&rect); + } + + void CreateCloseButton() + { + ATLASSERT(m_tb.m_hWnd == NULL); + // create toolbar for the "x" button + m_tb.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | CCS_NOMOVEY | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT, 0); + ATLASSERT(m_tb.IsWindow()); + + if(m_tb.m_hWnd != NULL) + { + T* pT = static_cast(this); + pT; // avoid level 4 warning + + m_tb.SetButtonStructSize(); + + TBBUTTON tbbtn = { 0 }; + tbbtn.idCommand = pT->m_nCloseBtnID; + tbbtn.fsState = TBSTATE_ENABLED; + tbbtn.fsStyle = TBSTYLE_BUTTON; + m_tb.AddButtons(1, &tbbtn); + + m_tb.SetBitmapSize(m_cxImageTB, m_cyImageTB); + m_tb.SetButtonSize(m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB); + + if(IsVertical()) + m_tb.SetWindowPos(NULL, m_cxyBorder + m_cxyBtnOffset, m_cxyBorder + m_cxyBtnOffset, m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB, SWP_NOZORDER | SWP_NOACTIVATE); + else + m_tb.SetWindowPos(NULL, 0, 0, m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); + } + } + + void DestroyCloseButton() + { + if(m_tb.m_hWnd != NULL) + m_tb.DestroyWindow(); + } + + void CalcSize() + { + T* pT = static_cast(this); + CFontHandle font = pT->GetTitleFont(); + LOGFONT lf = { 0 }; + font.GetLogFont(lf); + if(IsVertical()) + { + m_cxyHeader = m_cxImageTB + m_cxyBtnAddTB + m_cxyBorder; + } + else + { + int cyFont = abs(lf.lfHeight) + m_cxyBorder + 2 * m_cxyTextOffset; + int cyBtn = m_cyImageTB + m_cxyBtnAddTB + m_cxyBorder + 2 * m_cxyBtnOffset; + m_cxyHeader = max(cyFont, cyBtn); + } + } + + HFONT GetTitleFont() const + { + return AtlGetDefaultGuiFont(); + } + +#ifndef _WIN32_WCE + BOOL GetToolTipText(LPNMHDR /*lpnmh*/) + { + return FALSE; + } +#endif // !_WIN32_WCE + + void DrawPaneTitle(CDCHandle dc) + { + RECT rect = { 0 }; + GetClientRect(&rect); + + UINT uBorder = BF_LEFT | BF_TOP | BF_ADJUST; + if(IsVertical()) + { + rect.right = rect.left + m_cxyHeader; + uBorder |= BF_BOTTOM; + } + else + { + rect.bottom = rect.top + m_cxyHeader; + uBorder |= BF_RIGHT; + } + + if((m_dwExtendedStyle & PANECNT_NOBORDER) == 0) + { + if((m_dwExtendedStyle & PANECNT_FLATBORDER) != 0) + uBorder |= BF_FLAT; + dc.DrawEdge(&rect, EDGE_ETCHED, uBorder); + } + dc.FillRect(&rect, COLOR_3DFACE); + + if(!IsVertical()) // draw title only for horizontal pane container + { + dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT)); + dc.SetBkMode(TRANSPARENT); + T* pT = static_cast(this); + HFONT hFontOld = dc.SelectFont(pT->GetTitleFont()); + rect.left += m_cxyTextOffset; + rect.right -= m_cxyTextOffset; + if(m_tb.m_hWnd != NULL) + rect.right -= m_cxToolBar;; +#ifndef _WIN32_WCE + dc.DrawText(m_szTitle, -1, &rect, DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS); +#else // CE specific + dc.DrawText(m_szTitle, -1, &rect, DT_LEFT | DT_SINGLELINE | DT_VCENTER); +#endif // _WIN32_WCE + dc.SelectFont(hFontOld); + } + } + + // called only if pane is empty + void DrawPane(CDCHandle dc) + { + RECT rect = { 0 }; + GetClientRect(&rect); + if(IsVertical()) + rect.left += m_cxyHeader; + else + rect.top += m_cxyHeader; + if((GetExStyle() & WS_EX_CLIENTEDGE) == 0) + dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); + dc.FillRect(&rect, COLOR_APPWORKSPACE); + } + + // drawing helper - draws "x" button image + void DrawButtonImage(CDCHandle dc, RECT& rcImage, HPEN hPen) + { +#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) + HPEN hPenOld = dc.SelectPen(hPen); + + dc.MoveTo(rcImage.left, rcImage.top); + dc.LineTo(rcImage.right, rcImage.bottom); + dc.MoveTo(rcImage.left + 1, rcImage.top); + dc.LineTo(rcImage.right + 1, rcImage.bottom); + + dc.MoveTo(rcImage.left, rcImage.bottom - 1); + dc.LineTo(rcImage.right, rcImage.top - 1); + dc.MoveTo(rcImage.left + 1, rcImage.bottom - 1); + dc.LineTo(rcImage.right + 1, rcImage.top - 1); + + dc.SelectPen(hPenOld); +#else // (_WIN32_WCE < 400) + rcImage; + hPen; + // no support for the "x" button image +#endif // (_WIN32_WCE < 400) + } + + bool IsVertical() const + { + return ((m_dwExtendedStyle & PANECNT_VERTICAL) != 0); + } +}; + +class CPaneContainer : public CPaneContainerImpl +{ +public: + DECLARE_WND_CLASS_EX(_T("WTL_PaneContainer"), 0, -1) +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CSortListViewCtrl - implements sorting for a listview control + +// sort listview extended styles +#define SORTLV_USESHELLBITMAPS 0x00000001 + +// Notification sent to parent when sort column is changed by user clicking header. +#define SLVN_SORTCHANGED LVN_LAST + +// A LPNMSORTLISTVIEW is sent with the SLVN_SORTCHANGED notification +typedef struct tagNMSORTLISTVIEW +{ + NMHDR hdr; + int iNewSortColumn; + int iOldSortColumn; +} NMSORTLISTVIEW, *LPNMSORTLISTVIEW; + +// Column sort types. Can be set on a per-column basis with the SetColumnSortType method. +enum +{ + LVCOLSORT_NONE, + LVCOLSORT_TEXT, // default + LVCOLSORT_TEXTNOCASE, + LVCOLSORT_LONG, + LVCOLSORT_DOUBLE, + LVCOLSORT_DECIMAL, + LVCOLSORT_DATETIME, + LVCOLSORT_DATE, + LVCOLSORT_TIME, + LVCOLSORT_CUSTOM, + LVCOLSORT_LAST = LVCOLSORT_CUSTOM +}; + + +template +class CSortListViewImpl +{ +public: + enum + { + m_cchCmpTextMax = 32, // overrideable + m_cxSortImage = 16, + m_cySortImage = 15, + m_cxSortArrow = 11, + m_cySortArrow = 6, + m_iSortUp = 0, // index of sort bitmaps + m_iSortDown = 1, + m_nShellSortUpID = 133 + }; + + // passed to LVCompare functions as lParam1 and lParam2 + struct LVCompareParam + { + int iItem; + DWORD_PTR dwItemData; + union + { + long lValue; + double dblValue; + DECIMAL decValue; + LPCTSTR pszValue; + }; + }; + + // passed to LVCompare functions as the lParamSort parameter + struct LVSortInfo + { + T* pT; + int iSortCol; + bool bDescending; + }; + + bool m_bSortDescending; + bool m_bCommCtrl6; + int m_iSortColumn; + CBitmap m_bmSort[2]; + int m_fmtOldSortCol; + HBITMAP m_hbmOldSortCol; + DWORD m_dwSortLVExtendedStyle; + ATL::CSimpleArray m_arrColSortType; + bool m_bUseWaitCursor; + + CSortListViewImpl() : + m_bSortDescending(false), + m_bCommCtrl6(false), + m_iSortColumn(-1), + m_fmtOldSortCol(0), + m_hbmOldSortCol(NULL), + m_dwSortLVExtendedStyle(SORTLV_USESHELLBITMAPS), + m_bUseWaitCursor(true) + { +#ifndef _WIN32_WCE + DWORD dwMajor = 0; + DWORD dwMinor = 0; + HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor); + m_bCommCtrl6 = SUCCEEDED(hRet) && dwMajor >= 6; +#endif // !_WIN32_WCE + } + +// Attributes + void SetSortColumn(int iCol) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + CHeaderCtrl header = pT->GetHeader(); + ATLASSERT(header.m_hWnd != NULL); + ATLASSERT(iCol >= -1 && iCol < m_arrColSortType.GetSize()); + + int iOldSortCol = m_iSortColumn; + m_iSortColumn = iCol; + if(m_bCommCtrl6) + { +#ifndef HDF_SORTUP + const int HDF_SORTUP = 0x0400; +#endif // HDF_SORTUP +#ifndef HDF_SORTDOWN + const int HDF_SORTDOWN = 0x0200; +#endif // HDF_SORTDOWN + const int nMask = HDF_SORTUP | HDF_SORTDOWN; + HDITEM hditem = { HDI_FORMAT }; + if(iOldSortCol != iCol && iOldSortCol >= 0 && header.GetItem(iOldSortCol, &hditem)) + { + hditem.fmt &= ~nMask; + header.SetItem(iOldSortCol, &hditem); + } + if(iCol >= 0 && header.GetItem(iCol, &hditem)) + { + hditem.fmt &= ~nMask; + hditem.fmt |= m_bSortDescending ? HDF_SORTDOWN : HDF_SORTUP; + header.SetItem(iCol, &hditem); + } + return; + } + + if(m_bmSort[m_iSortUp].IsNull()) + pT->CreateSortBitmaps(); + + // restore previous sort column's bitmap, if any, and format + HDITEM hditem = { HDI_BITMAP | HDI_FORMAT }; + if(iOldSortCol != iCol && iOldSortCol >= 0) + { + hditem.hbm = m_hbmOldSortCol; + hditem.fmt = m_fmtOldSortCol; + header.SetItem(iOldSortCol, &hditem); + } + + // save new sort column's bitmap and format, and add our sort bitmap + if(iCol >= 0 && header.GetItem(iCol, &hditem)) + { + if(iOldSortCol != iCol) + { + m_fmtOldSortCol = hditem.fmt; + m_hbmOldSortCol = hditem.hbm; + } + hditem.fmt &= ~HDF_IMAGE; + hditem.fmt |= HDF_BITMAP | HDF_BITMAP_ON_RIGHT; + int i = m_bSortDescending ? m_iSortDown : m_iSortUp; + hditem.hbm = m_bmSort[i]; + header.SetItem(iCol, &hditem); + } + } + + int GetSortColumn() const + { + return m_iSortColumn; + } + + void SetColumnSortType(int iCol, WORD wType) + { + ATLASSERT(iCol >= 0 && iCol < m_arrColSortType.GetSize()); + ATLASSERT(wType >= LVCOLSORT_NONE && wType <= LVCOLSORT_LAST); + m_arrColSortType[iCol] = wType; + } + + WORD GetColumnSortType(int iCol) const + { + ATLASSERT((iCol >= 0) && iCol < m_arrColSortType.GetSize()); + return m_arrColSortType[iCol]; + } + + int GetColumnCount() const + { + const T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + CHeaderCtrl header = pT->GetHeader(); + return header.m_hWnd != NULL ? header.GetItemCount() : 0; + } + + bool IsSortDescending() const + { + return m_bSortDescending; + } + + DWORD GetSortListViewExtendedStyle() const + { + return m_dwSortLVExtendedStyle; + } + + DWORD SetSortListViewExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) + { + DWORD dwPrevStyle = m_dwSortLVExtendedStyle; + if(dwMask == 0) + m_dwSortLVExtendedStyle = dwExtendedStyle; + else + m_dwSortLVExtendedStyle = (m_dwSortLVExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); + return dwPrevStyle; + } + +// Operations + bool DoSortItems(int iCol, bool bDescending = false) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + ATLASSERT(iCol >= 0 && iCol < m_arrColSortType.GetSize()); + + WORD wType = m_arrColSortType[iCol]; + if(wType == LVCOLSORT_NONE) + return false; + + int nCount = pT->GetItemCount(); + if(nCount < 2) + { + m_bSortDescending = bDescending; + SetSortColumn(iCol); + return true; + } + + CWaitCursor waitCursor(false); + if(m_bUseWaitCursor) + waitCursor.Set(); + + LVCompareParam* pParam = NULL; + ATLTRY(pParam = new LVCompareParam[nCount]); + PFNLVCOMPARE pFunc = NULL; + TCHAR pszTemp[pT->m_cchCmpTextMax]; + bool bStrValue = false; + + switch(wType) + { + case LVCOLSORT_TEXT: + pFunc = (PFNLVCOMPARE)pT->LVCompareText; + case LVCOLSORT_TEXTNOCASE: + if(pFunc == NULL) + pFunc = (PFNLVCOMPARE)pT->LVCompareTextNoCase; + case LVCOLSORT_CUSTOM: + { + if(pFunc == NULL) + pFunc = (PFNLVCOMPARE)pT->LVCompareCustom; + + for(int i = 0; i < nCount; i++) + { + pParam[i].iItem = i; + pParam[i].dwItemData = pT->GetItemData(i); + pParam[i].pszValue = new TCHAR[pT->m_cchCmpTextMax]; + pT->GetItemText(i, iCol, (LPTSTR)pParam[i].pszValue, pT->m_cchCmpTextMax); + pT->SetItemData(i, (DWORD_PTR)&pParam[i]); + } + bStrValue = true; + } + break; + case LVCOLSORT_LONG: + { + pFunc = (PFNLVCOMPARE)pT->LVCompareLong; + for(int i = 0; i < nCount; i++) + { + pParam[i].iItem = i; + pParam[i].dwItemData = pT->GetItemData(i); + pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax); + pParam[i].lValue = pT->StrToLong(pszTemp); + pT->SetItemData(i, (DWORD_PTR)&pParam[i]); + } + } + break; + case LVCOLSORT_DOUBLE: + { + pFunc = (PFNLVCOMPARE)pT->LVCompareDouble; + for(int i = 0; i < nCount; i++) + { + pParam[i].iItem = i; + pParam[i].dwItemData = pT->GetItemData(i); + pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax); + pParam[i].dblValue = pT->StrToDouble(pszTemp); + pT->SetItemData(i, (DWORD_PTR)&pParam[i]); + } + } + break; + case LVCOLSORT_DECIMAL: + { + pFunc = (PFNLVCOMPARE)pT->LVCompareDecimal; + for(int i = 0; i < nCount; i++) + { + pParam[i].iItem = i; + pParam[i].dwItemData = pT->GetItemData(i); + pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax); + pT->StrToDecimal(pszTemp, &pParam[i].decValue); + pT->SetItemData(i, (DWORD_PTR)&pParam[i]); + } + } + break; + case LVCOLSORT_DATETIME: + case LVCOLSORT_DATE: + case LVCOLSORT_TIME: + { + pFunc = (PFNLVCOMPARE)pT->LVCompareDouble; + DWORD dwFlags = LOCALE_NOUSEROVERRIDE; + if(wType == LVCOLSORT_DATE) + dwFlags |= VAR_DATEVALUEONLY; + else if(wType == LVCOLSORT_TIME) + dwFlags |= VAR_TIMEVALUEONLY; + for(int i = 0; i < nCount; i++) + { + pParam[i].iItem = i; + pParam[i].dwItemData = pT->GetItemData(i); + pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax); + pParam[i].dblValue = pT->DateStrToDouble(pszTemp, dwFlags); + pT->SetItemData(i, (DWORD_PTR)&pParam[i]); + } + } + break; + default: + ATLTRACE2(atlTraceUI, 0, _T("Unknown value for sort type in CSortListViewImpl::DoSortItems()\n")); + break; + } // switch(wType) + + ATLASSERT(pFunc != NULL); + LVSortInfo lvsi = { pT, iCol, bDescending }; + bool bRet = ((BOOL)pT->DefWindowProc(LVM_SORTITEMS, (WPARAM)&lvsi, (LPARAM)pFunc) != FALSE); + for(int i = 0; i < nCount; i++) + { + DWORD_PTR dwItemData = pT->GetItemData(i); + LVCompareParam* p = (LVCompareParam*)dwItemData; + ATLASSERT(p != NULL); + if(bStrValue) + delete [] (TCHAR*)p->pszValue; + pT->SetItemData(i, p->dwItemData); + } + delete [] pParam; + + if(bRet) + { + m_bSortDescending = bDescending; + SetSortColumn(iCol); + } + + if(m_bUseWaitCursor) + waitCursor.Restore(); + + return bRet; + } + + void CreateSortBitmaps() + { + if((m_dwSortLVExtendedStyle & SORTLV_USESHELLBITMAPS) != 0) + { + bool bFree = false; + LPCTSTR pszModule = _T("shell32.dll"); + HINSTANCE hShell = ::GetModuleHandle(pszModule); + + if (hShell == NULL) + { + hShell = ::LoadLibrary(pszModule); + bFree = true; + } + + if (hShell != NULL) + { + bool bSuccess = true; + for(int i = m_iSortUp; i <= m_iSortDown; i++) + { + if(!m_bmSort[i].IsNull()) + m_bmSort[i].DeleteObject(); + m_bmSort[i] = (HBITMAP)::LoadImage(hShell, MAKEINTRESOURCE(m_nShellSortUpID + i), +#ifndef _WIN32_WCE + IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); +#else // CE specific + IMAGE_BITMAP, 0, 0, 0); +#endif // _WIN32_WCE + if(m_bmSort[i].IsNull()) + { + bSuccess = false; + break; + } + } + if(bFree) + ::FreeLibrary(hShell); + if(bSuccess) + return; + } + } + + T* pT = static_cast(this); + for(int i = m_iSortUp; i <= m_iSortDown; i++) + { + if(!m_bmSort[i].IsNull()) + m_bmSort[i].DeleteObject(); + + CDC dcMem; + CClientDC dc(::GetDesktopWindow()); + dcMem.CreateCompatibleDC(dc.m_hDC); + m_bmSort[i].CreateCompatibleBitmap(dc.m_hDC, m_cxSortImage, m_cySortImage); + HBITMAP hbmOld = dcMem.SelectBitmap(m_bmSort[i]); + RECT rc = {0,0,m_cxSortImage, m_cySortImage}; + pT->DrawSortBitmap(dcMem.m_hDC, i, &rc); + dcMem.SelectBitmap(hbmOld); + dcMem.DeleteDC(); + } + } + + void NotifyParentSortChanged(int iNewSortCol, int iOldSortCol) + { + T* pT = static_cast(this); + int nID = pT->GetDlgCtrlID(); + NMSORTLISTVIEW nm = { { pT->m_hWnd, nID, SLVN_SORTCHANGED }, iNewSortCol, iOldSortCol }; + ::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nID, (LPARAM)&nm); + } + +// Overrideables + int CompareItemsCustom(LVCompareParam* /*pItem1*/, LVCompareParam* /*pItem2*/, int /*iSortCol*/) + { + // pItem1 and pItem2 contain valid iItem, dwItemData, and pszValue members. + // If item1 > item2 return 1, if item1 < item2 return -1, else return 0. + return 0; + } + + void DrawSortBitmap(CDCHandle dc, int iBitmap, LPRECT prc) + { + dc.FillRect(prc, ::GetSysColorBrush(COLOR_BTNFACE)); + HBRUSH hbrOld = dc.SelectBrush(::GetSysColorBrush(COLOR_BTNSHADOW)); + CPen pen; + pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNSHADOW)); + HPEN hpenOld = dc.SelectPen(pen); + POINT ptOrg = { (m_cxSortImage - m_cxSortArrow) / 2, (m_cySortImage - m_cySortArrow) / 2 }; + if(iBitmap == m_iSortUp) + { + POINT pts[3] = + { + { ptOrg.x + m_cxSortArrow / 2, ptOrg.y }, + { ptOrg.x, ptOrg.y + m_cySortArrow - 1 }, + { ptOrg.x + m_cxSortArrow - 1, ptOrg.y + m_cySortArrow - 1 } + }; + dc.Polygon(pts, 3); + } + else + { + POINT pts[3] = + { + { ptOrg.x, ptOrg.y }, + { ptOrg.x + m_cxSortArrow / 2, ptOrg.y + m_cySortArrow - 1 }, + { ptOrg.x + m_cxSortArrow - 1, ptOrg.y } + }; + dc.Polygon(pts, 3); + } + dc.SelectBrush(hbrOld); + dc.SelectPen(hpenOld); + } + + double DateStrToDouble(LPCTSTR lpstr, DWORD dwFlags) + { + ATLASSERT(lpstr != NULL); + if(lpstr == NULL || lpstr[0] == _T('\0')) + return 0; + + USES_CONVERSION; + HRESULT hRet = E_FAIL; + DATE dRet = 0; + if (FAILED(hRet = ::VarDateFromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, dwFlags, &dRet))) + { + ATLTRACE2(atlTraceUI, 0, _T("VarDateFromStr failed with result of 0x%8.8X\n"), hRet); + dRet = 0; + } + return dRet; + } + + long StrToLong(LPCTSTR lpstr) + { + ATLASSERT(lpstr != NULL); + if(lpstr == NULL || lpstr[0] == _T('\0')) + return 0; + + USES_CONVERSION; + HRESULT hRet = E_FAIL; + long lRet = 0; + if (FAILED(hRet = ::VarI4FromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, &lRet))) + { + ATLTRACE2(atlTraceUI, 0, _T("VarI4FromStr failed with result of 0x%8.8X\n"), hRet); + lRet = 0; + } + return lRet; + } + + double StrToDouble(LPCTSTR lpstr) + { + ATLASSERT(lpstr != NULL); + if(lpstr == NULL || lpstr[0] == _T('\0')) + return 0; + + USES_CONVERSION; + HRESULT hRet = E_FAIL; + double dblRet = 0; + if (FAILED(hRet = ::VarR8FromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, &dblRet))) + { + ATLTRACE2(atlTraceUI, 0, _T("VarR8FromStr failed with result of 0x%8.8X\n"), hRet); + dblRet = 0; + } + return dblRet; + } + + bool StrToDecimal(LPCTSTR lpstr, DECIMAL* pDecimal) + { + ATLASSERT(lpstr != NULL); + ATLASSERT(pDecimal != NULL); + if(lpstr == NULL || pDecimal == NULL) + return false; + + USES_CONVERSION; + HRESULT hRet = E_FAIL; + if (FAILED(hRet = ::VarDecFromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, pDecimal))) + { + ATLTRACE2(atlTraceUI, 0, _T("VarDecFromStr failed with result of 0x%8.8X\n"), hRet); + pDecimal->Lo64 = 0; + pDecimal->Hi32 = 0; + pDecimal->signscale = 0; + return false; + } + return true; + } + +// Overrideable PFNLVCOMPARE functions + static int CALLBACK LVCompareText(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) + { + ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL); + + LVCompareParam* pParam1 = (LVCompareParam*)lParam1; + LVCompareParam* pParam2 = (LVCompareParam*)lParam2; + LVSortInfo* pInfo = (LVSortInfo*)lParamSort; + + int nRet = lstrcmp(pParam1->pszValue, pParam2->pszValue); + return pInfo->bDescending ? -nRet : nRet; + } + + static int CALLBACK LVCompareTextNoCase(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) + { + ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL); + + LVCompareParam* pParam1 = (LVCompareParam*)lParam1; + LVCompareParam* pParam2 = (LVCompareParam*)lParam2; + LVSortInfo* pInfo = (LVSortInfo*)lParamSort; + + int nRet = lstrcmpi(pParam1->pszValue, pParam2->pszValue); + return pInfo->bDescending ? -nRet : nRet; + } + + static int CALLBACK LVCompareLong(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) + { + ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL); + + LVCompareParam* pParam1 = (LVCompareParam*)lParam1; + LVCompareParam* pParam2 = (LVCompareParam*)lParam2; + LVSortInfo* pInfo = (LVSortInfo*)lParamSort; + + int nRet = 0; + if(pParam1->lValue > pParam2->lValue) + nRet = 1; + else if(pParam1->lValue < pParam2->lValue) + nRet = -1; + return pInfo->bDescending ? -nRet : nRet; + } + + static int CALLBACK LVCompareDouble(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) + { + ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL); + + LVCompareParam* pParam1 = (LVCompareParam*)lParam1; + LVCompareParam* pParam2 = (LVCompareParam*)lParam2; + LVSortInfo* pInfo = (LVSortInfo*)lParamSort; + + int nRet = 0; + if(pParam1->dblValue > pParam2->dblValue) + nRet = 1; + else if(pParam1->dblValue < pParam2->dblValue) + nRet = -1; + return pInfo->bDescending ? -nRet : nRet; + } + + static int CALLBACK LVCompareCustom(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) + { + ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL); + + LVCompareParam* pParam1 = (LVCompareParam*)lParam1; + LVCompareParam* pParam2 = (LVCompareParam*)lParam2; + LVSortInfo* pInfo = (LVSortInfo*)lParamSort; + + int nRet = pInfo->pT->CompareItemsCustom(pParam1, pParam2, pInfo->iSortCol); + return pInfo->bDescending ? -nRet : nRet; + } + +#ifndef _WIN32_WCE + static int CALLBACK LVCompareDecimal(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) + { + ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL); + + LVCompareParam* pParam1 = (LVCompareParam*)lParam1; + LVCompareParam* pParam2 = (LVCompareParam*)lParam2; + LVSortInfo* pInfo = (LVSortInfo*)lParamSort; + + int nRet = (int)::VarDecCmp(&pParam1->decValue, &pParam2->decValue); + nRet--; + return pInfo->bDescending ? -nRet : nRet; + } +#else + // Compare mantissas, ignore sign and scale + static int CompareMantissas(const DECIMAL& decLeft, const DECIMAL& decRight) + { + if (decLeft.Hi32 < decRight.Hi32) + { + return -1; + } + if (decLeft.Hi32 > decRight.Hi32) + { + return 1; + } + // Here, decLeft.Hi32 == decRight.Hi32 + if (decLeft.Lo64 < decRight.Lo64) + { + return -1; + } + if (decLeft.Lo64 > decRight.Lo64) + { + return 1; + } + return 0; + } + + // return values: VARCMP_LT, VARCMP_EQ, VARCMP_GT, VARCMP_NULL + static HRESULT VarDecCmp(const DECIMAL* pdecLeft, const DECIMAL* pdecRight) + { + static const ULONG powersOfTen[] = + { + 10ul, + 100ul, + 1000ul, + 10000ul, + 100000ul, + 1000000ul, + 10000000ul, + 100000000ul, + 1000000000ul + }; + static const int largestPower = sizeof(powersOfTen) / sizeof(powersOfTen[0]); + if (!pdecLeft || !pdecRight) + { + return VARCMP_NULL; + } + + // Degenerate case - at least one comparand is of the form + // [+-]0*10^N (denormalized zero) + bool bLeftZero = (!pdecLeft->Lo64 && !pdecLeft->Hi32); + bool bRightZero = (!pdecRight->Lo64 && !pdecRight->Hi32); + if (bLeftZero && bRightZero) + { + return VARCMP_EQ; + } + bool bLeftNeg = ((pdecLeft->sign & DECIMAL_NEG) != 0); + bool bRightNeg = ((pdecRight->sign & DECIMAL_NEG) != 0); + if (bLeftZero) + { + return (bRightNeg ? VARCMP_GT : VARCMP_LT); + } + // This also covers the case where the comparands have different signs + if (bRightZero || bLeftNeg != bRightNeg) + { + return (bLeftNeg ? VARCMP_LT : VARCMP_GT); + } + + // Here both comparands have the same sign and need to be compared + // on mantissa and scale. The result is obvious when + // 1. Scales are equal (then compare mantissas) + // 2. A number with smaller scale is also the one with larger mantissa + // (then this number is obviously larger) + // In the remaining case, we would multiply the number with smaller + // scale by 10 and simultaneously increment its scale (which amounts to + // adding trailing zeros after decimal point), until the numbers fall under + // one of the two cases above + DECIMAL temp; + bool bInvert = bLeftNeg; // the final result needs to be inverted + if (pdecLeft->scale < pdecRight->scale) + { + temp = *pdecLeft; + } + else + { + temp = *pdecRight; + pdecRight = pdecLeft; + bInvert = !bInvert; + } + + // Now temp is the number with smaller (or equal) scale, and + // we can modify it freely without touching original parameters + int comp; + while ((comp = CompareMantissas(temp, *pdecRight)) < 0 && + temp.scale < pdecRight->scale) + { + // Multiply by an appropriate power of 10 + int scaleDiff = pdecRight->scale - temp.scale; + if (scaleDiff > largestPower) + { + // Keep the multiplier representable in 32bit + scaleDiff = largestPower; + } + DWORDLONG power = powersOfTen[scaleDiff - 1]; + // Multiply temp's mantissa by power + DWORDLONG product = temp.Lo32 * power; + ULONG carry = static_cast(product >> 32); + temp.Lo32 = static_cast(product); + product = temp.Mid32 * power + carry; + carry = static_cast(product >> 32); + temp.Mid32 = static_cast(product); + product = temp.Hi32 * power + carry; + if (static_cast(product >> 32)) + { + // Multiplication overflowed - pdecLeft is clearly larger + break; + } + temp.Hi32 = static_cast(product); + temp.scale = (BYTE)(temp.scale + scaleDiff); + } + if (temp.scale < pdecRight->scale) + { + comp = 1; + } + if (bInvert) + { + comp = -comp; + } + return (comp > 0 ? VARCMP_GT : comp < 0 ? VARCMP_LT : VARCMP_EQ); + } + + static int CALLBACK LVCompareDecimal(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) + { + ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL); + + LVCompareParam* pParam1 = (LVCompareParam*)lParam1; + LVCompareParam* pParam2 = (LVCompareParam*)lParam2; + LVSortInfo* pInfo = (LVSortInfo*)lParamSort; + + int nRet = (int)VarDecCmp(&pParam1->decValue, &pParam2->decValue); + nRet--; + return pInfo->bDescending ? -nRet : nRet; + } +#endif // !_WIN32_WCE + + BEGIN_MSG_MAP(CSortListViewImpl) + MESSAGE_HANDLER(LVM_INSERTCOLUMN, OnInsertColumn) + MESSAGE_HANDLER(LVM_DELETECOLUMN, OnDeleteColumn) + NOTIFY_CODE_HANDLER(HDN_ITEMCLICKA, OnHeaderItemClick) + NOTIFY_CODE_HANDLER(HDN_ITEMCLICKW, OnHeaderItemClick) + MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) + END_MSG_MAP() + + LRESULT OnInsertColumn(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam); + if(lRet == -1) + return -1; + + WORD wType = 0; + m_arrColSortType.Add(wType); + int nCount = m_arrColSortType.GetSize(); + ATLASSERT(nCount == GetColumnCount()); + + for(int i = nCount - 1; i > lRet; i--) + m_arrColSortType[i] = m_arrColSortType[i - 1]; + m_arrColSortType[(int)lRet] = LVCOLSORT_TEXT; + + if(lRet <= m_iSortColumn) + m_iSortColumn++; + + return lRet; + } + + LRESULT OnDeleteColumn(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam); + if(lRet == 0) + return 0; + + int iCol = (int)wParam; + if(m_iSortColumn == iCol) + m_iSortColumn = -1; + else if(m_iSortColumn > iCol) + m_iSortColumn--; + m_arrColSortType.RemoveAt(iCol); + + return lRet; + } + + LRESULT OnHeaderItemClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) + { + LPNMHEADER p = (LPNMHEADER)pnmh; + if(p->iButton == 0) + { + int iOld = m_iSortColumn; + bool bDescending = (m_iSortColumn == p->iItem) ? !m_bSortDescending : false; + if(DoSortItems(p->iItem, bDescending)) + NotifyParentSortChanged(p->iItem, iOld); + } + bHandled = FALSE; + return 0; + } + + LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { +#ifndef _WIN32_WCE + if(wParam == SPI_SETNONCLIENTMETRICS) + GetSystemSettings(); +#else // CE specific + wParam; // avoid level 4 warning + GetSystemSettings(); +#endif // _WIN32_WCE + bHandled = FALSE; + return 0; + } + + void GetSystemSettings() + { + if(!m_bCommCtrl6 && !m_bmSort[m_iSortUp].IsNull()) + { + T* pT = static_cast(this); + pT->CreateSortBitmaps(); + if(m_iSortColumn != -1) + SetSortColumn(m_iSortColumn); + } + } + +}; + + +typedef ATL::CWinTraits CSortListViewCtrlTraits; + +template +class ATL_NO_VTABLE CSortListViewCtrlImpl: public ATL::CWindowImpl, public CSortListViewImpl +{ +public: + DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName()) + + bool SortItems(int iCol, bool bDescending = false) + { + return DoSortItems(iCol, bDescending); + } + + BEGIN_MSG_MAP(CSortListViewCtrlImpl) + MESSAGE_HANDLER(LVM_INSERTCOLUMN, CSortListViewImpl::OnInsertColumn) + MESSAGE_HANDLER(LVM_DELETECOLUMN, CSortListViewImpl::OnDeleteColumn) + NOTIFY_CODE_HANDLER(HDN_ITEMCLICKA, CSortListViewImpl::OnHeaderItemClick) + NOTIFY_CODE_HANDLER(HDN_ITEMCLICKW, CSortListViewImpl::OnHeaderItemClick) + MESSAGE_HANDLER(WM_SETTINGCHANGE, CSortListViewImpl::OnSettingChange) + END_MSG_MAP() +}; + +class CSortListViewCtrl : public CSortListViewCtrlImpl +{ +public: + DECLARE_WND_SUPERCLASS(_T("WTL_SortListViewCtrl"), GetWndClassName()) +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CTabView - implements tab view window + +// TabView Notifications +#define TBVN_PAGEACTIVATED (0U-741) +#define TBVN_CONTEXTMENU (0U-742) + +// Notification data for TBVN_CONTEXTMENU +struct TBVCONTEXTMENUINFO +{ + NMHDR hdr; + POINT pt; +}; + +typedef TBVCONTEXTMENUINFO* LPTBVCONTEXTMENUINFO; + + +template +class ATL_NO_VTABLE CTabViewImpl : public ATL::CWindowImpl +{ +public: + DECLARE_WND_CLASS_EX(NULL, 0, COLOR_APPWORKSPACE) + +// Declarations and enums + struct TABVIEWPAGE + { + HWND hWnd; + LPTSTR lpstrTitle; + LPVOID pData; + }; + + struct TCITEMEXTRA + { + TCITEMHEADER tciheader; + TABVIEWPAGE tvpage; + + operator LPTCITEM() { return (LPTCITEM)this; } + }; + + enum + { + m_nTabID = 1313, + m_cxMoveMark = 6, + m_cyMoveMark = 3, + m_nMenuItemsMax = (ID_WINDOW_TABLAST - ID_WINDOW_TABFIRST + 1) + }; + +// Data members + ATL::CContainedWindowT m_tab; + int m_cyTabHeight; + + int m_nActivePage; + + int m_nInsertItem; + POINT m_ptStartDrag; + + CMenuHandle m_menu; + + int m_cchTabTextLength; + + int m_nMenuItemsCount; + + ATL::CWindow m_wndTitleBar; + LPTSTR m_lpstrTitleBarBase; + int m_cchTitleBarLength; + + CImageList m_ilDrag; + + bool m_bDestroyPageOnRemove:1; + bool m_bDestroyImageList:1; + bool m_bActivePageMenuItem:1; + bool m_bActiveAsDefaultMenuItem:1; + bool m_bEmptyMenuItem:1; + bool m_bWindowsMenuItem:1; + // internal + bool m_bTabCapture:1; + bool m_bTabDrag:1; + +// Constructor/destructor + CTabViewImpl() : + m_nActivePage(-1), + m_cyTabHeight(0), + m_tab(this, 1), + m_nInsertItem(-1), + m_cchTabTextLength(30), + m_nMenuItemsCount(10), + m_lpstrTitleBarBase(NULL), + m_cchTitleBarLength(100), + m_bDestroyPageOnRemove(true), + m_bDestroyImageList(true), + m_bActivePageMenuItem(true), + m_bActiveAsDefaultMenuItem(false), + m_bEmptyMenuItem(false), + m_bWindowsMenuItem(false), + m_bTabCapture(false), + m_bTabDrag(false) + { + m_ptStartDrag.x = 0; + m_ptStartDrag.y = 0; + } + + ~CTabViewImpl() + { + delete [] m_lpstrTitleBarBase; + } + +// Message filter function - to be called from PreTranslateMessage of the main window + BOOL PreTranslateMessage(MSG* pMsg) + { + if(IsWindow() == FALSE) + return FALSE; + + BOOL bRet = FALSE; + + // Check for TabView built-in accelerators (Ctrl+Tab/Ctrl+Shift+Tab - next/previous page) + int nCount = GetPageCount(); + if(nCount > 0) + { + bool bControl = (::GetKeyState(VK_CONTROL) < 0); + if((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_TAB) && bControl) + { + if(nCount > 1) + { + int nPage = m_nActivePage; + bool bShift = (::GetKeyState(VK_SHIFT) < 0); + if(bShift) + nPage = (nPage > 0) ? (nPage - 1) : (nCount - 1); + else + nPage = ((nPage >= 0) && (nPage < (nCount - 1))) ? (nPage + 1) : 0; + + SetActivePage(nPage); + T* pT = static_cast(this); + pT->OnPageActivated(m_nActivePage); + } + + bRet = TRUE; + } + } + + // If we are doing drag-drop, check for Escape key that cancels it + if(bRet == FALSE) + { + if(m_bTabCapture && pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) + { + ::ReleaseCapture(); + bRet = TRUE; + } + } + + // Pass the message to the active page + if(bRet == FALSE) + { + if(m_nActivePage != -1) + bRet = (BOOL)::SendMessage(GetPageHWND(m_nActivePage), WM_FORWARDMSG, 0, (LPARAM)pMsg); + } + + return bRet; + } + +// Attributes + int GetPageCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return m_tab.GetItemCount(); + } + + int GetActivePage() const + { + return m_nActivePage; + } + + void SetActivePage(int nPage) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(IsValidPageIndex(nPage)); + + T* pT = static_cast(this); + + SetRedraw(FALSE); + + if(m_nActivePage != -1) + ::ShowWindow(GetPageHWND(m_nActivePage), FALSE); + m_nActivePage = nPage; + m_tab.SetCurSel(m_nActivePage); + ::ShowWindow(GetPageHWND(m_nActivePage), TRUE); + + pT->UpdateLayout(); + + SetRedraw(TRUE); + RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); + + if(::GetFocus() != m_tab.m_hWnd) + ::SetFocus(GetPageHWND(m_nActivePage)); + + pT->UpdateTitleBar(); + pT->UpdateMenu(); + } + + HIMAGELIST GetImageList() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return m_tab.GetImageList(); + } + + HIMAGELIST SetImageList(HIMAGELIST hImageList) + { + ATLASSERT(::IsWindow(m_hWnd)); + return m_tab.SetImageList(hImageList); + } + + void SetWindowMenu(HMENU hMenu) + { + ATLASSERT(::IsWindow(m_hWnd)); + + m_menu = hMenu; + + T* pT = static_cast(this); + pT->UpdateMenu(); + } + + void SetTitleBarWindow(HWND hWnd) + { + ATLASSERT(::IsWindow(m_hWnd)); + + delete [] m_lpstrTitleBarBase; + m_lpstrTitleBarBase = NULL; + + m_wndTitleBar = hWnd; + if(hWnd == NULL) + return; + + int cchLen = m_wndTitleBar.GetWindowTextLength() + 1; + ATLTRY(m_lpstrTitleBarBase = new TCHAR[cchLen]); + if(m_lpstrTitleBarBase != NULL) + { + m_wndTitleBar.GetWindowText(m_lpstrTitleBarBase, cchLen); + T* pT = static_cast(this); + pT->UpdateTitleBar(); + } + } + +// Page attributes + HWND GetPageHWND(int nPage) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(IsValidPageIndex(nPage)); + + TCITEMEXTRA tcix = { 0 }; + tcix.tciheader.mask = TCIF_PARAM; + m_tab.GetItem(nPage, tcix); + + return tcix.tvpage.hWnd; + } + + LPCTSTR GetPageTitle(int nPage) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(IsValidPageIndex(nPage)); + + TCITEMEXTRA tcix = { 0 }; + tcix.tciheader.mask = TCIF_PARAM; + if(m_tab.GetItem(nPage, tcix) == FALSE) + return NULL; + + return tcix.tvpage.lpstrTitle; + } + + bool SetPageTitle(int nPage, LPCTSTR lpstrTitle) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(IsValidPageIndex(nPage)); + + T* pT = static_cast(this); + + int cchBuff = lstrlen(lpstrTitle) + 1; + LPTSTR lpstrBuff = NULL; + ATLTRY(lpstrBuff = new TCHAR[cchBuff]); + if(lpstrBuff == NULL) + return false; + + SecureHelper::strcpy_x(lpstrBuff, cchBuff, lpstrTitle); + TCITEMEXTRA tcix = { 0 }; + tcix.tciheader.mask = TCIF_PARAM; + if(m_tab.GetItem(nPage, tcix) == FALSE) + return false; + + CTempBuffer buff; + LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1); + if(lpstrTabText == NULL) + return false; + + delete [] tcix.tvpage.lpstrTitle; + + pT->ShortenTitle(lpstrTitle, lpstrTabText, m_cchTabTextLength + 1); + + tcix.tciheader.mask = TCIF_TEXT | TCIF_PARAM; + tcix.tciheader.pszText = lpstrTabText; + tcix.tvpage.lpstrTitle = lpstrBuff; + if(m_tab.SetItem(nPage, tcix) == FALSE) + return false; + + pT->UpdateTitleBar(); + pT->UpdateMenu(); + + return true; + } + + LPVOID GetPageData(int nPage) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(IsValidPageIndex(nPage)); + + TCITEMEXTRA tcix = { 0 }; + tcix.tciheader.mask = TCIF_PARAM; + m_tab.GetItem(nPage, tcix); + + return tcix.tvpage.pData; + } + + LPVOID SetPageData(int nPage, LPVOID pData) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(IsValidPageIndex(nPage)); + + TCITEMEXTRA tcix = { 0 }; + tcix.tciheader.mask = TCIF_PARAM; + m_tab.GetItem(nPage, tcix); + LPVOID pDataOld = tcix.tvpage.pData; + + tcix.tvpage.pData = pData; + m_tab.SetItem(nPage, tcix); + + return pDataOld; + } + + int GetPageImage(int nPage) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(IsValidPageIndex(nPage)); + + TCITEMEXTRA tcix = { 0 }; + tcix.tciheader.mask = TCIF_IMAGE; + m_tab.GetItem(nPage, tcix); + + return tcix.tciheader.iImage; + } + + int SetPageImage(int nPage, int nImage) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(IsValidPageIndex(nPage)); + + TCITEMEXTRA tcix = { 0 }; + tcix.tciheader.mask = TCIF_IMAGE; + m_tab.GetItem(nPage, tcix); + int nImageOld = tcix.tciheader.iImage; + + tcix.tciheader.iImage = nImage; + m_tab.SetItem(nPage, tcix); + + return nImageOld; + } + +// Operations + bool AddPage(HWND hWndView, LPCTSTR lpstrTitle, int nImage = -1, LPVOID pData = NULL) + { + return InsertPage(GetPageCount(), hWndView, lpstrTitle, nImage, pData); + } + + bool InsertPage(int nPage, HWND hWndView, LPCTSTR lpstrTitle, int nImage = -1, LPVOID pData = NULL) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(nPage == GetPageCount() || IsValidPageIndex(nPage)); + + T* pT = static_cast(this); + + int cchBuff = lstrlen(lpstrTitle) + 1; + LPTSTR lpstrBuff = NULL; + ATLTRY(lpstrBuff = new TCHAR[cchBuff]); + if(lpstrBuff == NULL) + return false; + + SecureHelper::strcpy_x(lpstrBuff, cchBuff, lpstrTitle); + + CTempBuffer buff; + LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1); + if(lpstrTabText == NULL) + return false; + + pT->ShortenTitle(lpstrTitle, lpstrTabText, m_cchTabTextLength + 1); + + SetRedraw(FALSE); + + TCITEMEXTRA tcix = { 0 }; + tcix.tciheader.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM; + tcix.tciheader.pszText = lpstrTabText; + tcix.tciheader.iImage = nImage; + tcix.tvpage.hWnd = hWndView; + tcix.tvpage.lpstrTitle = lpstrBuff; + tcix.tvpage.pData = pData; + int nItem = m_tab.InsertItem(nPage, tcix); + if(nItem == -1) + { + delete [] lpstrBuff; + SetRedraw(TRUE); + return false; + } + + SetActivePage(nItem); + pT->OnPageActivated(m_nActivePage); + + if(GetPageCount() == 1) + pT->ShowTabControl(true); + + pT->UpdateLayout(); + + SetRedraw(TRUE); + RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); + + return true; + } + + void RemovePage(int nPage) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(IsValidPageIndex(nPage)); + + T* pT = static_cast(this); + + SetRedraw(FALSE); + + if(GetPageCount() == 1) + pT->ShowTabControl(false); + + if(m_bDestroyPageOnRemove) + ::DestroyWindow(GetPageHWND(nPage)); + else + ::ShowWindow(GetPageHWND(nPage), FALSE); + LPTSTR lpstrTitle = (LPTSTR)GetPageTitle(nPage); + delete [] lpstrTitle; + + ATLVERIFY(m_tab.DeleteItem(nPage) != FALSE); + + if(m_nActivePage == nPage) + { + m_nActivePage = -1; + + if(nPage > 0) + { + SetActivePage(nPage - 1); + } + else if(GetPageCount() > 0) + { + SetActivePage(nPage); + } + else + { + SetRedraw(TRUE); + Invalidate(); + UpdateWindow(); + pT->UpdateTitleBar(); + pT->UpdateMenu(); + } + } + else + { + nPage = (nPage < m_nActivePage) ? (m_nActivePage - 1) : m_nActivePage; + m_nActivePage = -1; + SetActivePage(nPage); + } + + pT->OnPageActivated(m_nActivePage); + } + + void RemoveAllPages() + { + ATLASSERT(::IsWindow(m_hWnd)); + + if(GetPageCount() == 0) + return; + + T* pT = static_cast(this); + + SetRedraw(FALSE); + + pT->ShowTabControl(false); + + for(int i = 0; i < GetPageCount(); i++) + { + if(m_bDestroyPageOnRemove) + ::DestroyWindow(GetPageHWND(i)); + else + ::ShowWindow(GetPageHWND(i), FALSE); + LPTSTR lpstrTitle = (LPTSTR)GetPageTitle(i); + delete [] lpstrTitle; + } + m_tab.DeleteAllItems(); + + m_nActivePage = -1; + pT->OnPageActivated(m_nActivePage); + + SetRedraw(TRUE); + Invalidate(); + UpdateWindow(); + + pT->UpdateTitleBar(); + pT->UpdateMenu(); + } + + int PageIndexFromHwnd(HWND hWnd) const + { + int nIndex = -1; + + for(int i = 0; i < GetPageCount(); i++) + { + if(GetPageHWND(i) == hWnd) + { + nIndex = i; + break; + } + } + + return nIndex; + } + + void BuildWindowMenu(HMENU hMenu, int nMenuItemsCount = 10, bool bEmptyMenuItem = true, bool bWindowsMenuItem = true, bool bActivePageMenuItem = true, bool bActiveAsDefaultMenuItem = false) + { + ATLASSERT(::IsWindow(m_hWnd)); + + CMenuHandle menu = hMenu; + T* pT = static_cast(this); + pT; // avoid level 4 warning + int nFirstPos = 0; + + // Find first menu item in our range +#ifndef _WIN32_WCE + for(nFirstPos = 0; nFirstPos < menu.GetMenuItemCount(); nFirstPos++) + { + UINT nID = menu.GetMenuItemID(nFirstPos); + if((nID >= ID_WINDOW_TABFIRST && nID <= ID_WINDOW_TABLAST) || nID == ID_WINDOW_SHOWTABLIST) + break; + } +#else // CE specific + for(nFirstPos = 0; ; nFirstPos++) + { + CMenuItemInfo mii; + mii.fMask = MIIM_ID; + BOOL bRet = menu.GetMenuItemInfo(nFirstPos, TRUE, &mii); + if(bRet == FALSE) + break; + if((mii.wID >= ID_WINDOW_TABFIRST && mii.wID <= ID_WINDOW_TABLAST) || mii.wID == ID_WINDOW_SHOWTABLIST) + break; + } +#endif // _WIN32_WCE + + // Remove all menu items for tab pages + BOOL bRet = TRUE; + while(bRet != FALSE) + bRet = menu.DeleteMenu(nFirstPos, MF_BYPOSITION); + + // Add separator if it's not already there + int nPageCount = GetPageCount(); + if((bWindowsMenuItem || (nPageCount > 0)) && (nFirstPos > 0)) + { + CMenuItemInfo mii; + mii.fMask = MIIM_TYPE; + menu.GetMenuItemInfo(nFirstPos - 1, TRUE, &mii); + if((nFirstPos <= 0) || ((mii.fType & MFT_SEPARATOR) == 0)) + { + menu.AppendMenu(MF_SEPARATOR); + nFirstPos++; + } + } + + // Add menu items for all pages + if(nPageCount > 0) + { + // Append menu items for all pages + const int cchPrefix = 3; // 2 digits + space + nMenuItemsCount = min(min(nPageCount, nMenuItemsCount), (int)m_nMenuItemsMax); + ATLASSERT(nMenuItemsCount < 100); // 2 digits only + if(nMenuItemsCount >= 100) + nMenuItemsCount = 99; + + for(int i = 0; i < nMenuItemsCount; i++) + { + LPCTSTR lpstrTitle = GetPageTitle(i); + int nLen = lstrlen(lpstrTitle); + CTempBuffer buff; + LPTSTR lpstrText = buff.Allocate(cchPrefix + nLen + 1); + ATLASSERT(lpstrText != NULL); + if(lpstrText != NULL) + { + LPCTSTR lpstrFormat = (i < 9) ? _T("&%i %s") : _T("%i %s"); + SecureHelper::wsprintf_x(lpstrText, cchPrefix + nLen + 1, lpstrFormat, i + 1, lpstrTitle); + menu.AppendMenu(MF_STRING, ID_WINDOW_TABFIRST + i, lpstrText); + } + } + + // Mark active page + if(bActivePageMenuItem && (m_nActivePage != -1)) + { +#ifndef _WIN32_WCE + if(bActiveAsDefaultMenuItem) + { + menu.SetMenuDefaultItem((UINT)-1, TRUE); + menu.SetMenuDefaultItem(nFirstPos + m_nActivePage, TRUE); + } + else +#else // CE specific + bActiveAsDefaultMenuItem; // avoid level 4 warning +#endif // _WIN32_WCE + { + menu.CheckMenuRadioItem(nFirstPos, nFirstPos + nMenuItemsCount, nFirstPos + m_nActivePage, MF_BYPOSITION); + } + } + } + else + { + if(bEmptyMenuItem) + { + menu.AppendMenu(MF_BYPOSITION | MF_STRING, ID_WINDOW_TABFIRST, pT->GetEmptyListText()); + menu.EnableMenuItem(ID_WINDOW_TABFIRST, MF_GRAYED); + } + + // Remove separator if nothing else is there + if(!bEmptyMenuItem && !bWindowsMenuItem && (nFirstPos > 0)) + { + CMenuItemInfo mii; + mii.fMask = MIIM_TYPE; + menu.GetMenuItemInfo(nFirstPos - 1, TRUE, &mii); + if((mii.fType & MFT_SEPARATOR) != 0) + menu.DeleteMenu(nFirstPos - 1, MF_BYPOSITION); + } + } + + // Add "Windows..." menu item + if(bWindowsMenuItem) + menu.AppendMenu(MF_BYPOSITION | MF_STRING, ID_WINDOW_SHOWTABLIST, pT->GetWindowsMenuItemText()); + } + +// Message map and handlers + BEGIN_MSG_MAP(CTabViewImpl) + MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) + MESSAGE_HANDLER(WM_SIZE, OnSize) + MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) + NOTIFY_HANDLER(m_nTabID, TCN_SELCHANGE, OnTabChanged) + NOTIFY_ID_HANDLER(m_nTabID, OnTabNotification) +#ifndef _WIN32_WCE + NOTIFY_CODE_HANDLER(TTN_GETDISPINFO, OnTabGetDispInfo) +#endif // !_WIN32_WCE + FORWARD_NOTIFICATIONS() + ALT_MSG_MAP(1) // tab control + MESSAGE_HANDLER(WM_LBUTTONDOWN, OnTabLButtonDown) + MESSAGE_HANDLER(WM_LBUTTONUP, OnTabLButtonUp) + MESSAGE_HANDLER(WM_CAPTURECHANGED, OnTabCaptureChanged) + MESSAGE_HANDLER(WM_MOUSEMOVE, OnTabMouseMove) + MESSAGE_HANDLER(WM_RBUTTONUP, OnTabRButtonUp) + MESSAGE_HANDLER(WM_SYSKEYDOWN, OnTabSysKeyDown) + END_MSG_MAP() + + LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->CreateTabControl(); + + return 0; + } + + LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + RemoveAllPages(); + + if(m_bDestroyImageList) + { + CImageList il = m_tab.SetImageList(NULL); + if(il.m_hImageList != NULL) + il.Destroy(); + } + + return 0; + } + + LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->UpdateLayout(); + return 0; + } + + LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + if(m_nActivePage != -1) + ::SetFocus(GetPageHWND(m_nActivePage)); + return 0; + } + + LRESULT OnTabChanged(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) + { + SetActivePage(m_tab.GetCurSel()); + T* pT = static_cast(this); + pT->OnPageActivated(m_nActivePage); + + return 0; + } + + LRESULT OnTabNotification(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) + { + // nothing to do - this just blocks all tab control + // notifications from being propagated further + return 0; + } + +#ifndef _WIN32_WCE + LRESULT OnTabGetDispInfo(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) + { + LPNMTTDISPINFO pTTDI = (LPNMTTDISPINFO)pnmh; + if(pTTDI->hdr.hwndFrom == m_tab.GetTooltips()) + { + T* pT = static_cast(this); + pT->UpdateTooltipText(pTTDI); + } + else + { + bHandled = FALSE; + } + + return 0; + } +#endif // !_WIN32_WCE + +// Tab control message handlers + LRESULT OnTabLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + if(m_tab.GetItemCount() > 1) + { + m_bTabCapture = true; + m_tab.SetCapture(); + + m_ptStartDrag.x = GET_X_LPARAM(lParam); + m_ptStartDrag.y = GET_Y_LPARAM(lParam); + } + + bHandled = FALSE; + return 0; + } + + LRESULT OnTabLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + if(m_bTabCapture) + { + if(m_bTabDrag) + { + TCHITTESTINFO hti = { 0 }; + hti.pt.x = GET_X_LPARAM(lParam); + hti.pt.y = GET_Y_LPARAM(lParam); + int nItem = m_tab.HitTest(&hti); + if(nItem != -1) + MovePage(m_nActivePage, nItem); + } + + ::ReleaseCapture(); + } + + bHandled = FALSE; + return 0; + } + + LRESULT OnTabCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + if(m_bTabCapture) + { + m_bTabCapture = false; + + if(m_bTabDrag) + { + m_bTabDrag = false; + T* pT = static_cast(this); + pT->DrawMoveMark(-1); + +#ifndef _WIN32_WCE + m_ilDrag.DragLeave(GetDesktopWindow()); +#endif // !_WIN32_WCE + m_ilDrag.EndDrag(); + + m_ilDrag.Destroy(); + m_ilDrag.m_hImageList = NULL; + } + } + + bHandled = FALSE; + return 0; + } + + LRESULT OnTabMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + bHandled = FALSE; + + if(m_bTabCapture) + { + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + + if(!m_bTabDrag) + { +#ifndef _WIN32_WCE + if(abs(m_ptStartDrag.x - GET_X_LPARAM(lParam)) >= ::GetSystemMetrics(SM_CXDRAG) || + abs(m_ptStartDrag.y - GET_Y_LPARAM(lParam)) >= ::GetSystemMetrics(SM_CYDRAG)) +#else // CE specific + if(abs(m_ptStartDrag.x - GET_X_LPARAM(lParam)) >= 4 || + abs(m_ptStartDrag.y - GET_Y_LPARAM(lParam)) >= 4) +#endif // _WIN32_WCE + { + T* pT = static_cast(this); + pT->GenerateDragImage(m_nActivePage); + + int cxCursor = ::GetSystemMetrics(SM_CXCURSOR); + int cyCursor = ::GetSystemMetrics(SM_CYCURSOR); + m_ilDrag.BeginDrag(0, -(cxCursor / 2), -(cyCursor / 2)); +#ifndef _WIN32_WCE + POINT ptEnter = m_ptStartDrag; + m_tab.ClientToScreen(&ptEnter); + m_ilDrag.DragEnter(GetDesktopWindow(), ptEnter); +#endif // !_WIN32_WCE + + m_bTabDrag = true; + } + } + + if(m_bTabDrag) + { + TCHITTESTINFO hti = { 0 }; + hti.pt = pt; + int nItem = m_tab.HitTest(&hti); + + T* pT = static_cast(this); + pT->SetMoveCursor(nItem != -1); + + if(m_nInsertItem != nItem) + pT->DrawMoveMark(nItem); + + m_ilDrag.DragShowNolock((nItem != -1) ? TRUE : FALSE); + m_tab.ClientToScreen(&pt); + m_ilDrag.DragMove(pt); + + bHandled = TRUE; + } + } + + return 0; + } + + LRESULT OnTabRButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) + { + TCHITTESTINFO hti = { 0 }; + hti.pt.x = GET_X_LPARAM(lParam); + hti.pt.y = GET_Y_LPARAM(lParam); + int nItem = m_tab.HitTest(&hti); + if(nItem != -1) + { + T* pT = static_cast(this); + pT->OnContextMenu(nItem, hti.pt); + } + + return 0; + } + + LRESULT OnTabSysKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + bool bShift = (::GetKeyState(VK_SHIFT) < 0); + if(wParam == VK_F10 && bShift) + { + if(m_nActivePage != -1) + { + RECT rect = { 0 }; + m_tab.GetItemRect(m_nActivePage, &rect); + POINT pt = { rect.left, rect.bottom }; + T* pT = static_cast(this); + pT->OnContextMenu(m_nActivePage, pt); + } + } + else + { + bHandled = FALSE; + } + + return 0; + } + +// Implementation helpers + bool IsValidPageIndex(int nPage) const + { + return (nPage >= 0 && nPage < GetPageCount()); + } + + bool MovePage(int nMovePage, int nInsertBeforePage) + { + ATLASSERT(IsValidPageIndex(nMovePage)); + ATLASSERT(IsValidPageIndex(nInsertBeforePage)); + + if(!IsValidPageIndex(nMovePage) || !IsValidPageIndex(nInsertBeforePage)) + return false; + + if(nMovePage == nInsertBeforePage) + return true; // nothing to do + + CTempBuffer buff; + LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1); + if(lpstrTabText == NULL) + return false; + TCITEMEXTRA tcix = { 0 }; + tcix.tciheader.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM; + tcix.tciheader.pszText = lpstrTabText; + tcix.tciheader.cchTextMax = m_cchTabTextLength + 1; + BOOL bRet = m_tab.GetItem(nMovePage, tcix); + ATLASSERT(bRet != FALSE); + if(bRet == FALSE) + return false; + + int nInsertItem = (nInsertBeforePage > nMovePage) ? nInsertBeforePage + 1 : nInsertBeforePage; + int nNewItem = m_tab.InsertItem(nInsertItem, tcix); + ATLASSERT(nNewItem == nInsertItem); + if(nNewItem != nInsertItem) + { + ATLVERIFY(m_tab.DeleteItem(nNewItem)); + return false; + } + + if(nMovePage > nInsertBeforePage) + ATLVERIFY(m_tab.DeleteItem(nMovePage + 1) != FALSE); + else if(nMovePage < nInsertBeforePage) + ATLVERIFY(m_tab.DeleteItem(nMovePage) != FALSE); + + SetActivePage(nInsertBeforePage); + T* pT = static_cast(this); + pT->OnPageActivated(m_nActivePage); + + return true; + } + +// Implementation overrideables + bool CreateTabControl() + { +#ifndef _WIN32_WCE + m_tab.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_TOOLTIPS, 0, m_nTabID); +#else // CE specific + m_tab.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, m_nTabID); +#endif // _WIN32_WCE + ATLASSERT(m_tab.m_hWnd != NULL); + if(m_tab.m_hWnd == NULL) + return false; + + m_tab.SetFont(AtlGetDefaultGuiFont()); + + m_tab.SetItemExtra(sizeof(TABVIEWPAGE)); + + T* pT = static_cast(this); + m_cyTabHeight = pT->CalcTabHeight(); + + return true; + } + + int CalcTabHeight() + { + int nCount = m_tab.GetItemCount(); + TCITEMEXTRA tcix = { 0 }; + tcix.tciheader.mask = TCIF_TEXT; + tcix.tciheader.pszText = _T("NS"); + int nIndex = m_tab.InsertItem(nCount, tcix); + + RECT rect = { 0, 0, 1000, 1000 }; + m_tab.AdjustRect(FALSE, &rect); + + RECT rcWnd = { 0, 0, 1000, rect.top }; + ::AdjustWindowRectEx(&rcWnd, m_tab.GetStyle(), FALSE, m_tab.GetExStyle()); + + int nHeight = rcWnd.bottom - rcWnd.top; + + m_tab.DeleteItem(nIndex); + + return nHeight; + } + + void ShowTabControl(bool bShow) + { + m_tab.ShowWindow(bShow ? SW_SHOWNOACTIVATE : SW_HIDE); + } + + void UpdateLayout() + { + RECT rect; + GetClientRect(&rect); + + if(m_tab.IsWindow() && ((m_tab.GetStyle() & WS_VISIBLE) != 0)) + m_tab.SetWindowPos(NULL, 0, 0, rect.right - rect.left, m_cyTabHeight, SWP_NOZORDER); + + if(m_nActivePage != -1) + ::SetWindowPos(GetPageHWND(m_nActivePage), NULL, 0, m_cyTabHeight, rect.right - rect.left, rect.bottom - rect.top - m_cyTabHeight, SWP_NOZORDER); + } + + void UpdateMenu() + { + if(m_menu.m_hMenu != NULL) + BuildWindowMenu(m_menu, m_nMenuItemsCount, m_bEmptyMenuItem, m_bWindowsMenuItem, m_bActivePageMenuItem, m_bActiveAsDefaultMenuItem); + } + + void UpdateTitleBar() + { + if(!m_wndTitleBar.IsWindow() || m_lpstrTitleBarBase == NULL) + return; // nothing to do + + if(m_nActivePage != -1) + { + T* pT = static_cast(this); + LPCTSTR lpstrTitle = pT->GetPageTitle(m_nActivePage); + LPCTSTR lpstrDivider = pT->GetTitleDividerText(); + int cchBuffer = m_cchTitleBarLength + lstrlen(lpstrDivider) + lstrlen(m_lpstrTitleBarBase) + 1; + CTempBuffer buff; + LPTSTR lpstrPageTitle = buff.Allocate(cchBuffer); + ATLASSERT(lpstrPageTitle != NULL); + if(lpstrPageTitle != NULL) + { + pT->ShortenTitle(lpstrTitle, lpstrPageTitle, m_cchTitleBarLength + 1); + SecureHelper::strcat_x(lpstrPageTitle, cchBuffer, lpstrDivider); + SecureHelper::strcat_x(lpstrPageTitle, cchBuffer, m_lpstrTitleBarBase); + } + else + { + lpstrPageTitle = m_lpstrTitleBarBase; + } + + m_wndTitleBar.SetWindowText(lpstrPageTitle); + } + else + { + m_wndTitleBar.SetWindowText(m_lpstrTitleBarBase); + } + } + + void DrawMoveMark(int nItem) + { + T* pT = static_cast(this); + + if(m_nInsertItem != -1) + { + RECT rect = { 0 }; + pT->GetMoveMarkRect(rect); + m_tab.InvalidateRect(&rect); + } + + m_nInsertItem = nItem; + + if(m_nInsertItem != -1) + { + CClientDC dc(m_tab.m_hWnd); + + RECT rect = { 0 }; + pT->GetMoveMarkRect(rect); + + CPen pen; + pen.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_WINDOWTEXT)); + CBrush brush; + brush.CreateSolidBrush(::GetSysColor(COLOR_WINDOWTEXT)); + + HPEN hPenOld = dc.SelectPen(pen); + HBRUSH hBrushOld = dc.SelectBrush(brush); + + int x = rect.left; + int y = rect.top; + POINT ptsTop[3] = { { x, y }, { x + m_cxMoveMark, y }, { x + (m_cxMoveMark / 2), y + m_cyMoveMark } }; + dc.Polygon(ptsTop, 3); + + y = rect.bottom - 1; + POINT ptsBottom[3] = { { x, y }, { x + m_cxMoveMark, y }, { x + (m_cxMoveMark / 2), y - m_cyMoveMark } }; + dc.Polygon(ptsBottom, 3); + + dc.SelectPen(hPenOld); + dc.SelectBrush(hBrushOld); + } + } + + void GetMoveMarkRect(RECT& rect) const + { + m_tab.GetClientRect(&rect); + + RECT rcItem = { 0 }; + m_tab.GetItemRect(m_nInsertItem, &rcItem); + + if(m_nInsertItem <= m_nActivePage) + { + rect.left = rcItem.left - m_cxMoveMark / 2 - 1; + rect.right = rcItem.left + m_cxMoveMark / 2; + } + else + { + rect.left = rcItem.right - m_cxMoveMark / 2 - 1; + rect.right = rcItem.right + m_cxMoveMark / 2; + } + } + + void SetMoveCursor(bool bCanMove) + { + ::SetCursor(::LoadCursor(NULL, bCanMove ? IDC_ARROW : IDC_NO)); + } + + void GenerateDragImage(int nItem) + { + ATLASSERT(IsValidPageIndex(nItem)); + +#ifndef _WIN32_WCE + RECT rcItem = { 0 }; + m_tab.GetItemRect(nItem, &rcItem); + ::InflateRect(&rcItem, 2, 2); // make bigger to cover selected item +#else // CE specific + nItem; // avoid level 4 warning + RECT rcItem = { 0, 0, 40, 20 }; +#endif // _WIN32_WCE + + ATLASSERT(m_ilDrag.m_hImageList == NULL); + m_ilDrag.Create(rcItem.right - rcItem.left, rcItem.bottom - rcItem.top, ILC_COLORDDB | ILC_MASK, 1, 1); + + CClientDC dc(m_hWnd); + CDC dcMem; + dcMem.CreateCompatibleDC(dc); + ATLASSERT(dcMem.m_hDC != NULL); + dcMem.SetViewportOrg(-rcItem.left, -rcItem.top); + + CBitmap bmp; + bmp.CreateCompatibleBitmap(dc, rcItem.right - rcItem.left, rcItem.bottom - rcItem.top); + ATLASSERT(bmp.m_hBitmap != NULL); + + HBITMAP hBmpOld = dcMem.SelectBitmap(bmp); +#ifndef _WIN32_WCE + m_tab.SendMessage(WM_PRINTCLIENT, (WPARAM)dcMem.m_hDC); +#else // CE specific + dcMem.Rectangle(&rcItem); +#endif // _WIN32_WCE + dcMem.SelectBitmap(hBmpOld); + + ATLVERIFY(m_ilDrag.Add(bmp.m_hBitmap, RGB(255, 0, 255)) != -1); + } + + void ShortenTitle(LPCTSTR lpstrTitle, LPTSTR lpstrShortTitle, int cchShortTitle) + { + if(lstrlen(lpstrTitle) >= cchShortTitle) + { + LPCTSTR lpstrEllipsis = _T("..."); + int cchEllipsis = lstrlen(lpstrEllipsis); + SecureHelper::strncpy_x(lpstrShortTitle, cchShortTitle, lpstrTitle, cchShortTitle - cchEllipsis - 1); + SecureHelper::strcat_x(lpstrShortTitle, cchShortTitle, lpstrEllipsis); + } + else + { + SecureHelper::strcpy_x(lpstrShortTitle, cchShortTitle, lpstrTitle); + } + } + +#ifndef _WIN32_WCE + void UpdateTooltipText(LPNMTTDISPINFO pTTDI) + { + ATLASSERT(pTTDI != NULL); + pTTDI->lpszText = (LPTSTR)GetPageTitle((int)pTTDI->hdr.idFrom); + } +#endif // !_WIN32_WCE + +// Text for menu items and title bar - override to provide different strings + static LPCTSTR GetEmptyListText() + { + return _T("(Empty)"); + } + + static LPCTSTR GetWindowsMenuItemText() + { + return _T("&Windows..."); + } + + static LPCTSTR GetTitleDividerText() + { + return _T(" - "); + } + +// Notifications - override to provide different behavior + void OnPageActivated(int nPage) + { + NMHDR nmhdr = { 0 }; + nmhdr.hwndFrom = m_hWnd; + nmhdr.idFrom = nPage; + nmhdr.code = TBVN_PAGEACTIVATED; + ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmhdr); + } + + void OnContextMenu(int nPage, POINT pt) + { + m_tab.ClientToScreen(&pt); + + TBVCONTEXTMENUINFO cmi = { 0 }; + cmi.hdr.hwndFrom = m_hWnd; + cmi.hdr.idFrom = nPage; + cmi.hdr.code = TBVN_CONTEXTMENU; + cmi.pt = pt; + ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&cmi); + } +}; + + +class CTabView : public CTabViewImpl +{ +public: + DECLARE_WND_CLASS_EX(_T("WTL_TabView"), 0, COLOR_APPWORKSPACE) +}; + +}; // namespace WTL + +#endif // __ATLCTRLX_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlddx.h b/Client/Client/GUI/BKWin/wtl/atlddx.h new file mode 100644 index 00000000..dc0f31f2 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlddx.h @@ -0,0 +1,621 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLDDX_H__ +#define __ATLDDX_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifndef __ATLAPP_H__ + #error atlddx.h requires atlapp.h to be included first +#endif + +#if defined(_ATL_USE_DDX_FLOAT) && defined(_ATL_MIN_CRT) + #error Cannot use floating point DDX with _ATL_MIN_CRT defined +#endif // defined(_ATL_USE_DDX_FLOAT) && defined(_ATL_MIN_CRT) + +#ifdef _ATL_USE_DDX_FLOAT + #include +#endif // _ATL_USE_DDX_FLOAT + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CWinDataExchange + + +namespace WTL +{ + +// Constants +#define DDX_LOAD FALSE +#define DDX_SAVE TRUE + +// DDX map macros +#define BEGIN_DDX_MAP(thisClass) \ + BOOL DoDataExchange(BOOL bSaveAndValidate = FALSE, UINT nCtlID = (UINT)-1) \ + { \ + bSaveAndValidate; \ + nCtlID; + +#define DDX_TEXT(nID, var) \ + if(nCtlID == (UINT)-1 || nCtlID == nID) \ + { \ + if(!DDX_Text(nID, var, sizeof(var), bSaveAndValidate)) \ + return FALSE; \ + } + +#define DDX_TEXT_LEN(nID, var, len) \ + if(nCtlID == (UINT)-1 || nCtlID == nID) \ + { \ + if(!DDX_Text(nID, var, sizeof(var), bSaveAndValidate, TRUE, len)) \ + return FALSE; \ + } + +#define DDX_INT(nID, var) \ + if(nCtlID == (UINT)-1 || nCtlID == nID) \ + { \ + if(!DDX_Int(nID, var, TRUE, bSaveAndValidate)) \ + return FALSE; \ + } + +#define DDX_INT_RANGE(nID, var, min, max) \ + if(nCtlID == (UINT)-1 || nCtlID == nID) \ + { \ + if(!DDX_Int(nID, var, TRUE, bSaveAndValidate, TRUE, min, max)) \ + return FALSE; \ + } + +#define DDX_UINT(nID, var) \ + if(nCtlID == (UINT)-1 || nCtlID == nID) \ + { \ + if(!DDX_Int(nID, var, FALSE, bSaveAndValidate)) \ + return FALSE; \ + } + +#define DDX_UINT_RANGE(nID, var, min, max) \ + if(nCtlID == (UINT)-1 || nCtlID == nID) \ + { \ + if(!DDX_Int(nID, var, FALSE, bSaveAndValidate, TRUE, min, max)) \ + return FALSE; \ + } + +#ifdef _ATL_USE_DDX_FLOAT +#define DDX_FLOAT(nID, var) \ + if(nCtlID == (UINT)-1 || nCtlID == nID) \ + { \ + if(!DDX_Float(nID, var, bSaveAndValidate)) \ + return FALSE; \ + } + +#define DDX_FLOAT_RANGE(nID, var, min, max) \ + if(nCtlID == (UINT)-1 || nCtlID == nID) \ + { \ + if(!DDX_Float(nID, var, bSaveAndValidate, TRUE, min, max)) \ + return FALSE; \ + } +#define DDX_FLOAT_P(nID, var, precision) \ + if(nCtlID == (UINT)-1 || nCtlID == nID) \ + { \ + if(!DDX_Float(nID, var, bSaveAndValidate, FALSE, 0, 0, precision)) \ + return FALSE; \ + } + +#define DDX_FLOAT_P_RANGE(nID, var, min, max, precision) \ + if(nCtlID == (UINT)-1 || nCtlID == nID) \ + { \ + if(!DDX_Float(nID, var, bSaveAndValidate, TRUE, min, max, precision)) \ + return FALSE; \ + } +#endif // _ATL_USE_DDX_FLOAT + +#define DDX_CONTROL(nID, obj) \ + if(nCtlID == (UINT)-1 || nCtlID == nID) \ + DDX_Control(nID, obj, bSaveAndValidate); + +#define DDX_CONTROL_HANDLE(nID, obj) \ + if(nCtlID == (UINT)-1 || nCtlID == nID) \ + DDX_Control_Handle(nID, obj, bSaveAndValidate); + +#define DDX_CHECK(nID, var) \ + if(nCtlID == (UINT)-1 || nCtlID == nID) \ + DDX_Check(nID, var, bSaveAndValidate); + +#define DDX_RADIO(nID, var) \ + if(nCtlID == (UINT)-1 || nCtlID == nID) \ + DDX_Radio(nID, var, bSaveAndValidate); + +#define END_DDX_MAP() \ + return TRUE; \ + } + + +/////////////////////////////////////////////////////////////////////////////// +// CWinDataExchange - provides support for DDX + +template +class CWinDataExchange +{ +public: +// Data exchange method - override in your derived class + BOOL DoDataExchange(BOOL /*bSaveAndValidate*/ = FALSE, UINT /*nCtlID*/ = (UINT)-1) + { + // this one should never be called, override it in + // your derived class by implementing DDX map + ATLASSERT(FALSE); + return FALSE; + } + +// Helpers for validation error reporting + enum _XDataType + { + ddxDataNull = 0, + ddxDataText = 1, + ddxDataInt = 2, + ddxDataFloat = 3, + ddxDataDouble = 4 + }; + + struct _XTextData + { + int nLength; + int nMaxLength; + }; + + struct _XIntData + { + long nVal; + long nMin; + long nMax; + }; + + struct _XFloatData + { + double nVal; + double nMin; + double nMax; + }; + + struct _XData + { + _XDataType nDataType; + union + { + _XTextData textData; + _XIntData intData; + _XFloatData floatData; + }; + }; + +// Text exchange + BOOL DDX_Text(UINT nID, LPTSTR lpstrText, int cbSize, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0) + { + T* pT = static_cast(this); + BOOL bSuccess = TRUE; + + if(bSave) + { + HWND hWndCtrl = pT->GetDlgItem(nID); + int nRetLen = ::GetWindowText(hWndCtrl, lpstrText, cbSize / sizeof(TCHAR)); + if(nRetLen < ::GetWindowTextLength(hWndCtrl)) + bSuccess = FALSE; + } + else + { + ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength); + bSuccess = pT->SetDlgItemText(nID, lpstrText); + } + + if(!bSuccess) + { + pT->OnDataExchangeError(nID, bSave); + } + else if(bSave && bValidate) // validation + { + ATLASSERT(nLength > 0); + if(lstrlen(lpstrText) > nLength) + { + _XData data = { ddxDataText }; + data.textData.nLength = lstrlen(lpstrText); + data.textData.nMaxLength = nLength; + pT->OnDataValidateError(nID, bSave, data); + bSuccess = FALSE; + } + } + return bSuccess; + } + + BOOL DDX_Text(UINT nID, BSTR& bstrText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0) + { + T* pT = static_cast(this); + BOOL bSuccess = TRUE; + + if(bSave) + { + bSuccess = pT->GetDlgItemText(nID, bstrText); + } + else + { + USES_CONVERSION; + LPTSTR lpstrText = OLE2T(bstrText); + ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength); + bSuccess = pT->SetDlgItemText(nID, lpstrText); + } + + if(!bSuccess) + { + pT->OnDataExchangeError(nID, bSave); + } + else if(bSave && bValidate) // validation + { + ATLASSERT(nLength > 0); + if((int)::SysStringLen(bstrText) > nLength) + { + _XData data = { ddxDataText }; + data.textData.nLength = (int)::SysStringLen(bstrText); + data.textData.nMaxLength = nLength; + pT->OnDataValidateError(nID, bSave, data); + bSuccess = FALSE; + } + } + return bSuccess; + } + + BOOL DDX_Text(UINT nID, ATL::CComBSTR& bstrText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0) + { + T* pT = static_cast(this); + BOOL bSuccess = TRUE; + + if(bSave) + { + bSuccess = pT->GetDlgItemText(nID, (BSTR&)bstrText); + } + else + { + USES_CONVERSION; + LPTSTR lpstrText = OLE2T(bstrText); + ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength); + bSuccess = pT->SetDlgItemText(nID, lpstrText); + } + + if(!bSuccess) + { + pT->OnDataExchangeError(nID, bSave); + } + else if(bSave && bValidate) // validation + { + ATLASSERT(nLength > 0); + if((int)bstrText.Length() > nLength) + { + _XData data = { ddxDataText }; + data.textData.nLength = (int)bstrText.Length(); + data.textData.nMaxLength = nLength; + pT->OnDataValidateError(nID, bSave, data); + bSuccess = FALSE; + } + } + return bSuccess; + } + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + BOOL DDX_Text(UINT nID, _CSTRING_NS::CString& strText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0) + { + T* pT = static_cast(this); + BOOL bSuccess = TRUE; + + if(bSave) + { + HWND hWndCtrl = pT->GetDlgItem(nID); + int nLen = ::GetWindowTextLength(hWndCtrl); + int nRetLen = -1; + LPTSTR lpstr = strText.GetBufferSetLength(nLen); + if(lpstr != NULL) + { + nRetLen = ::GetWindowText(hWndCtrl, lpstr, nLen + 1); + strText.ReleaseBuffer(); + } + if(nRetLen < nLen) + bSuccess = FALSE; + } + else + { + bSuccess = pT->SetDlgItemText(nID, strText); + } + + if(!bSuccess) + { + pT->OnDataExchangeError(nID, bSave); + } + else if(bSave && bValidate) // validation + { + ATLASSERT(nLength > 0); + if(strText.GetLength() > nLength) + { + _XData data = { ddxDataText }; + data.textData.nLength = strText.GetLength(); + data.textData.nMaxLength = nLength; + pT->OnDataValidateError(nID, bSave, data); + bSuccess = FALSE; + } + } + return bSuccess; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + +// Numeric exchange + template + BOOL DDX_Int(UINT nID, Type& nVal, BOOL bSigned, BOOL bSave, BOOL bValidate = FALSE, Type nMin = 0, Type nMax = 0) + { + T* pT = static_cast(this); + BOOL bSuccess = TRUE; + + if(bSave) + { + nVal = (Type)pT->GetDlgItemInt(nID, &bSuccess, bSigned); + } + else + { + ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax); + bSuccess = pT->SetDlgItemInt(nID, nVal, bSigned); + } + + if(!bSuccess) + { + pT->OnDataExchangeError(nID, bSave); + } + else if(bSave && bValidate) // validation + { + ATLASSERT(nMin != nMax); + if(nVal < nMin || nVal > nMax) + { + _XData data = { ddxDataInt }; + data.intData.nVal = (long)nVal; + data.intData.nMin = (long)nMin; + data.intData.nMax = (long)nMax; + pT->OnDataValidateError(nID, bSave, data); + bSuccess = FALSE; + } + } + return bSuccess; + } + +// Float exchange +#ifdef _ATL_USE_DDX_FLOAT + static BOOL _AtlSimpleFloatParse(LPCTSTR lpszText, double& d) + { + ATLASSERT(lpszText != NULL); + while (*lpszText == _T(' ') || *lpszText == _T('\t')) + lpszText++; + + TCHAR chFirst = lpszText[0]; + d = _tcstod(lpszText, (LPTSTR*)&lpszText); + if (d == 0.0 && chFirst != _T('0')) + return FALSE; // could not convert + while (*lpszText == _T(' ') || *lpszText == _T('\t')) + lpszText++; + + if (*lpszText != _T('\0')) + return FALSE; // not terminated properly + + return TRUE; + } + + BOOL DDX_Float(UINT nID, float& nVal, BOOL bSave, BOOL bValidate = FALSE, float nMin = 0.F, float nMax = 0.F, int nPrecision = FLT_DIG) + { + T* pT = static_cast(this); + BOOL bSuccess = TRUE; + const int cchBuff = 32; + TCHAR szBuff[cchBuff] = { 0 }; + + if(bSave) + { + pT->GetDlgItemText(nID, szBuff, cchBuff); + double d = 0; + if(_AtlSimpleFloatParse(szBuff, d)) + nVal = (float)d; + else + bSuccess = FALSE; + } + else + { + ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax); + SecureHelper::sprintf_x(szBuff, cchBuff, _T("%.*g"), nPrecision, nVal); + bSuccess = pT->SetDlgItemText(nID, szBuff); + } + + if(!bSuccess) + { + pT->OnDataExchangeError(nID, bSave); + } + else if(bSave && bValidate) // validation + { + ATLASSERT(nMin != nMax); + if(nVal < nMin || nVal > nMax) + { + _XData data = { ddxDataFloat }; + data.floatData.nVal = (double)nVal; + data.floatData.nMin = (double)nMin; + data.floatData.nMax = (double)nMax; + pT->OnDataValidateError(nID, bSave, data); + bSuccess = FALSE; + } + } + return bSuccess; + } + + BOOL DDX_Float(UINT nID, double& nVal, BOOL bSave, BOOL bValidate = FALSE, double nMin = 0., double nMax = 0., int nPrecision = DBL_DIG) + { + T* pT = static_cast(this); + BOOL bSuccess = TRUE; + const int cchBuff = 32; + TCHAR szBuff[cchBuff] = { 0 }; + + if(bSave) + { + pT->GetDlgItemText(nID, szBuff, cchBuff); + double d = 0; + if(_AtlSimpleFloatParse(szBuff, d)) + nVal = d; + else + bSuccess = FALSE; + } + else + { + ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax); + SecureHelper::sprintf_x(szBuff, cchBuff, _T("%.*g"), nPrecision, nVal); + bSuccess = pT->SetDlgItemText(nID, szBuff); + } + + if(!bSuccess) + { + pT->OnDataExchangeError(nID, bSave); + } + else if(bSave && bValidate) // validation + { + ATLASSERT(nMin != nMax); + if(nVal < nMin || nVal > nMax) + { + _XData data = { ddxDataFloat }; + data.floatData.nVal = nVal; + data.floatData.nMin = nMin; + data.floatData.nMax = nMax; + pT->OnDataValidateError(nID, bSave, data); + bSuccess = FALSE; + } + } + return bSuccess; + } +#endif // _ATL_USE_DDX_FLOAT + +// Full control subclassing (for CWindowImpl derived controls) + template + void DDX_Control(UINT nID, TControl& ctrl, BOOL bSave) + { + if(!bSave && ctrl.m_hWnd == NULL) + { + T* pT = static_cast(this); + ctrl.SubclassWindow(pT->GetDlgItem(nID)); + } + } + +// Simple control attaching (for HWND wrapper controls) + template + void DDX_Control_Handle(UINT nID, TControl& ctrl, BOOL bSave) + { + if(!bSave && ctrl.m_hWnd == NULL) + { + T* pT = static_cast(this); + ctrl = pT->GetDlgItem(nID); + } + } + +// Control state + void DDX_Check(UINT nID, int& nValue, BOOL bSave) + { + T* pT = static_cast(this); + HWND hWndCtrl = pT->GetDlgItem(nID); + if(bSave) + { + nValue = (int)::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L); + ATLASSERT(nValue >= 0 && nValue <= 2); + } + else + { + if(nValue < 0 || nValue > 2) + { + ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - dialog data checkbox value (%d) out of range.\n"), nValue); + nValue = 0; // default to off + } + ::SendMessage(hWndCtrl, BM_SETCHECK, nValue, 0L); + } + } + + // variant that supports bool (checked/not-checked, no intermediate state) + void DDX_Check(UINT nID, bool& bCheck, BOOL bSave) + { + int nValue = bCheck ? 1 : 0; + DDX_Check(nID, nValue, bSave); + + if(bSave) + { + if(nValue == 2) + ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - checkbox state (%d) out of supported range.\n"), nValue); + bCheck = (nValue == 1); + } + } + + void DDX_Radio(UINT nID, int& nValue, BOOL bSave) + { + T* pT = static_cast(this); + HWND hWndCtrl = pT->GetDlgItem(nID); + ATLASSERT(hWndCtrl != NULL); + + // must be first in a group of auto radio buttons + ATLASSERT(::GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP); + ATLASSERT(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON); + + if(bSave) + nValue = -1; // value if none found + + // walk all children in group + int nButton = 0; + do + { + if(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON) + { + // control in group is a radio button + if(bSave) + { + if(::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L) != 0) + { + ATLASSERT(nValue == -1); // only set once + nValue = nButton; + } + } + else + { + // select button + ::SendMessage(hWndCtrl, BM_SETCHECK, (nButton == nValue), 0L); + } + nButton++; + } + else + { + ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - skipping non-radio button in group.\n")); + } + hWndCtrl = ::GetWindow(hWndCtrl, GW_HWNDNEXT); + } + while (hWndCtrl != NULL && !(GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP)); + } + +// Overrideables + void OnDataExchangeError(UINT nCtrlID, BOOL /*bSave*/) + { + // Override to display an error message + ::MessageBeep((UINT)-1); + T* pT = static_cast(this); + ::SetFocus(pT->GetDlgItem(nCtrlID)); + } + + void OnDataValidateError(UINT nCtrlID, BOOL /*bSave*/, _XData& /*data*/) + { + // Override to display an error message + ::MessageBeep((UINT)-1); + T* pT = static_cast(this); + ::SetFocus(pT->GetDlgItem(nCtrlID)); + } +}; + +}; // namespace WTL + +#endif // __ATLDDX_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atldlgs.h b/Client/Client/GUI/BKWin/wtl/atldlgs.h new file mode 100644 index 00000000..62db9178 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atldlgs.h @@ -0,0 +1,6209 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLDLGS_H__ +#define __ATLDLGS_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifndef __ATLAPP_H__ + #error atldlgs.h requires atlapp.h to be included first +#endif + +#ifndef __ATLWIN_H__ + #error atldlgs.h requires atlwin.h to be included first +#endif + +#include +#include + +#if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE) + #include +#endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE) + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CFileDialogImpl +// CFileDialog +// CFileDialogEx +// CMultiFileDialogImpl +// CMultiFileDialog +// CShellFileDialogImpl +// CShellFileOpenDialogImpl +// CShellFileOpenDialog +// CShellFileSaveDialogImpl +// CShellFileSaveDialog +// CFolderDialogImpl +// CFolderDialog +// CFontDialogImpl +// CFontDialog +// CRichEditFontDialogImpl +// CRichEditFontDialog +// CColorDialogImpl +// CColorDialog +// CPrintDialogImpl +// CPrintDialog +// CPrintDialogExImpl +// CPrintDialogEx +// CPageSetupDialogImpl +// CPageSetupDialog +// CFindReplaceDialogImpl +// CFindReplaceDialog +// +// CMemDlgTemplate +// CIndirectDialogImpl +// +// CPropertySheetWindow +// CPropertySheetImpl +// CPropertySheet +// CPropertyPageWindow +// CPropertyPageImpl +// CPropertyPage +// CAxPropertyPageImpl +// CAxPropertyPage +// +// CWizard97SheetWindow +// CWizard97SheetImpl +// CWizard97Sheet +// CWizard97PageWindow +// CWizard97PageImpl +// CWizard97ExteriorPageImpl +// CWizard97InteriorPageImpl +// +// CAeroWizardFrameWindow +// CAeroWizardFrameImpl +// CAeroWizardFrame +// CAeroWizardPageWindow +// CAeroWizardPageImpl +// CAeroWizardPage +// CAeroWizardAxPageImpl +// CAeroWizardAxPage +// +// CTaskDialogConfig +// CTaskDialogImpl +// CTaskDialog +// +// Global functions: +// AtlTaskDialog() + + +namespace WTL +{ + +/////////////////////////////////////////////////////////////////////////////// +// CFileDialogImpl - used for File Open or File Save As + +// compatibility with the old (vc6.0) headers +#if (_WIN32_WINNT >= 0x0500) && !defined(OPENFILENAME_SIZE_VERSION_400) + #ifndef CDSIZEOF_STRUCT + #define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member)) + #endif + #define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName) + #define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName) + #ifdef UNICODE + #define OPENFILENAME_SIZE_VERSION_400 OPENFILENAME_SIZE_VERSION_400W + #else + #define OPENFILENAME_SIZE_VERSION_400 OPENFILENAME_SIZE_VERSION_400A + #endif // !UNICODE +#endif // (_WIN32_WINNT >= 0x0500) && !defined(OPENFILENAME_SIZE_VERSION_400) + +#if !defined(_WIN32_WCE) && !defined(CDN_INCLUDEITEM) + #define CDN_INCLUDEITEM (CDN_FIRST - 0x0007) +#endif + +template +class ATL_NO_VTABLE CFileDialogImpl : public ATL::CDialogImplBase +{ +public: +#if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501) + OPENFILENAMEEX m_ofn; +#else + OPENFILENAME m_ofn; +#endif + BOOL m_bOpenFileDialog; // TRUE for file open, FALSE for file save + TCHAR m_szFileTitle[_MAX_FNAME]; // contains file title after return + TCHAR m_szFileName[_MAX_PATH]; // contains full path name after return + + CFileDialogImpl(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs + LPCTSTR lpszDefExt = NULL, + LPCTSTR lpszFileName = NULL, + DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + LPCTSTR lpszFilter = NULL, + HWND hWndParent = NULL) + { + memset(&m_ofn, 0, sizeof(m_ofn)); // initialize structure to 0/NULL + m_szFileName[0] = _T('\0'); + m_szFileTitle[0] = _T('\0'); + + m_bOpenFileDialog = bOpenFileDialog; + + m_ofn.lStructSize = sizeof(m_ofn); +#if (_WIN32_WINNT >= 0x0500) + // adjust struct size if running on older version of Windows + if(AtlIsOldWindows()) + { + ATLASSERT(sizeof(m_ofn) > OPENFILENAME_SIZE_VERSION_400); // must be + m_ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + } +#endif // (_WIN32_WINNT >= 0x0500) + m_ofn.lpstrFile = m_szFileName; + m_ofn.nMaxFile = _MAX_PATH; + m_ofn.lpstrDefExt = lpszDefExt; + m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle; + m_ofn.nMaxFileTitle = _MAX_FNAME; +#ifndef _WIN32_WCE + m_ofn.Flags = dwFlags | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLESIZING; +#else // CE specific + m_ofn.Flags = dwFlags | OFN_EXPLORER | OFN_ENABLEHOOK; +#endif // !_WIN32_WCE + m_ofn.lpstrFilter = lpszFilter; + m_ofn.hInstance = ModuleHelper::GetResourceInstance(); + m_ofn.lpfnHook = (LPOFNHOOKPROC)T::StartDialogProc; + m_ofn.hwndOwner = hWndParent; + + // setup initial file name + if(lpszFileName != NULL) + SecureHelper::strncpy_x(m_szFileName, _countof(m_szFileName), lpszFileName, _TRUNCATE); + } + + INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) + { + ATLASSERT((m_ofn.Flags & OFN_ENABLEHOOK) != 0); + ATLASSERT(m_ofn.lpfnHook != NULL); // can still be a user hook + + ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); + + if(m_ofn.hwndOwner == NULL) // set only if not specified before + m_ofn.hwndOwner = hWndParent; + + ATLASSERT(m_hWnd == NULL); + ModuleHelper::AddCreateWndData(&m_thunk.cd, (ATL::CDialogImplBase*)this); + + BOOL bRet; + if(m_bOpenFileDialog) +#if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501) + bRet = ::GetOpenFileNameEx(&m_ofn); + else + bRet = ::GetSaveFileName((LPOPENFILENAME)&m_ofn); +#else + bRet = ::GetOpenFileName(&m_ofn); + else + bRet = ::GetSaveFileName(&m_ofn); +#endif + + m_hWnd = NULL; + + return bRet ? IDOK : IDCANCEL; + } + +// Attributes + ATL::CWindow GetFileDialogWindow() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ATL::CWindow(GetParent()); + } + + int GetFilePath(LPTSTR lpstrFilePath, int nLength) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); + + return (int)GetFileDialogWindow().SendMessage(CDM_GETFILEPATH, nLength, (LPARAM)lpstrFilePath); + } + + int GetFolderIDList(LPVOID lpBuff, int nLength) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); + + return (int)GetFileDialogWindow().SendMessage(CDM_GETFOLDERIDLIST, nLength, (LPARAM)lpBuff); + } + + int GetFolderPath(LPTSTR lpstrFolderPath, int nLength) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); + + return (int)GetFileDialogWindow().SendMessage(CDM_GETFOLDERPATH, nLength, (LPARAM)lpstrFolderPath); + } + + int GetSpec(LPTSTR lpstrSpec, int nLength) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); + + return (int)GetFileDialogWindow().SendMessage(CDM_GETSPEC, nLength, (LPARAM)lpstrSpec); + } + + void SetControlText(int nCtrlID, LPCTSTR lpstrText) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); + + GetFileDialogWindow().SendMessage(CDM_SETCONTROLTEXT, nCtrlID, (LPARAM)lpstrText); + } + + void SetDefExt(LPCTSTR lpstrExt) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); + + GetFileDialogWindow().SendMessage(CDM_SETDEFEXT, 0, (LPARAM)lpstrExt); + } + + BOOL GetReadOnlyPref() const // return TRUE if readonly checked + { + return ((m_ofn.Flags & OFN_READONLY) != 0) ? TRUE : FALSE; + } + +// Operations + void HideControl(int nCtrlID) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); + + GetFileDialogWindow().SendMessage(CDM_HIDECONTROL, nCtrlID); + } + +// Special override for common dialogs + BOOL EndDialog(INT_PTR /*nRetCode*/ = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + GetFileDialogWindow().SendMessage(WM_COMMAND, MAKEWPARAM(IDCANCEL, 0)); + return TRUE; + } + +// Message map and handlers + BEGIN_MSG_MAP(CFileDialogImpl) + NOTIFY_CODE_HANDLER(CDN_FILEOK, _OnFileOK) + NOTIFY_CODE_HANDLER(CDN_FOLDERCHANGE, _OnFolderChange) + NOTIFY_CODE_HANDLER(CDN_HELP, _OnHelp) + NOTIFY_CODE_HANDLER(CDN_INITDONE, _OnInitDone) + NOTIFY_CODE_HANDLER(CDN_SELCHANGE, _OnSelChange) + NOTIFY_CODE_HANDLER(CDN_SHAREVIOLATION, _OnShareViolation) + NOTIFY_CODE_HANDLER(CDN_TYPECHANGE, _OnTypeChange) +#ifndef _WIN32_WCE + NOTIFY_CODE_HANDLER(CDN_INCLUDEITEM, _OnIncludeItem) +#endif // !_WIN32_WCE + END_MSG_MAP() + + LRESULT _OnFileOK(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) + { + ATLASSERT(::IsWindow(m_hWnd)); + T* pT = static_cast(this); + return !pT->OnFileOK((LPOFNOTIFY)pnmh); + } + + LRESULT _OnFolderChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) + { + ATLASSERT(::IsWindow(m_hWnd)); + T* pT = static_cast(this); + pT->OnFolderChange((LPOFNOTIFY)pnmh); + return 0; + } + + LRESULT _OnHelp(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) + { + ATLASSERT(::IsWindow(m_hWnd)); + T* pT = static_cast(this); + pT->OnHelp((LPOFNOTIFY)pnmh); + return 0; + } + + LRESULT _OnInitDone(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) + { + ATLASSERT(::IsWindow(m_hWnd)); + T* pT = static_cast(this); + pT->OnInitDone((LPOFNOTIFY)pnmh); + return 0; + } + + LRESULT _OnSelChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) + { + ATLASSERT(::IsWindow(m_hWnd)); + T* pT = static_cast(this); + pT->OnSelChange((LPOFNOTIFY)pnmh); + return 0; + } + + LRESULT _OnShareViolation(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) + { + ATLASSERT(::IsWindow(m_hWnd)); + T* pT = static_cast(this); + return pT->OnShareViolation((LPOFNOTIFY)pnmh); + } + + LRESULT _OnTypeChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) + { + ATLASSERT(::IsWindow(m_hWnd)); + T* pT = static_cast(this); + pT->OnTypeChange((LPOFNOTIFY)pnmh); + return 0; + } + +#ifndef _WIN32_WCE + LRESULT _OnIncludeItem(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) + { + ATLASSERT(::IsWindow(m_hWnd)); + T* pT = static_cast(this); + return pT->OnIncludeItem((LPOFNOTIFYEX)pnmh); + } +#endif // !_WIN32_WCE + +// Overrideables + BOOL OnFileOK(LPOFNOTIFY /*lpon*/) + { + return TRUE; + } + + void OnFolderChange(LPOFNOTIFY /*lpon*/) + { + } + + void OnHelp(LPOFNOTIFY /*lpon*/) + { + } + + void OnInitDone(LPOFNOTIFY /*lpon*/) + { + } + + void OnSelChange(LPOFNOTIFY /*lpon*/) + { + } + + int OnShareViolation(LPOFNOTIFY /*lpon*/) + { + return 0; + } + + void OnTypeChange(LPOFNOTIFY /*lpon*/) + { + } + +#ifndef _WIN32_WCE + BOOL OnIncludeItem(LPOFNOTIFYEX /*lponex*/) + { + return TRUE; // include item + } +#endif // !_WIN32_WCE +}; + +class CFileDialog : public CFileDialogImpl +{ +public: + CFileDialog(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs + LPCTSTR lpszDefExt = NULL, + LPCTSTR lpszFileName = NULL, + DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + LPCTSTR lpszFilter = NULL, + HWND hWndParent = NULL) + : CFileDialogImpl(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent) + { } + + // override base class map and references to handlers + DECLARE_EMPTY_MSG_MAP() +}; + +#if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501) +class CFileDialogEx : public CFileDialogImpl +{ +public: + CFileDialogEx( // Supports only FileOpen + LPCTSTR lpszDefExt = NULL, + LPCTSTR lpszFileName = NULL, + DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + OFN_EXFLAG ExFlags = OFN_EXFLAG_THUMBNAILVIEW, + OFN_SORTORDER dwSortOrder = OFN_SORTORDER_AUTO, + LPCTSTR lpszFilter = NULL, + HWND hWndParent = NULL) + : CFileDialogImpl(TRUE, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent) + { + m_ofn.ExFlags = ExFlags; + m_ofn.dwSortOrder = dwSortOrder; + } + + // override base class map and references to handlers + DECLARE_EMPTY_MSG_MAP() +}; +#endif // defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501) + + +/////////////////////////////////////////////////////////////////////////////// +// Multi File Dialog - Multi-select File Open dialog + +#ifndef _WIN32_WCE + +// The class dynamically resizes the buffer as the file selection changes +// (as described in Knowledge Base article 131462). It also expands selected +// shortcut files to take into account the full path of the target file. +// Note that this doesn't work on Win9x for the old style dialogs, as well as +// on NT for non-Unicode builds. + +#ifndef _WTL_FIXED_OFN_BUFFER_LENGTH + #define _WTL_FIXED_OFN_BUFFER_LENGTH 0x10000 +#endif + +template +class ATL_NO_VTABLE CMultiFileDialogImpl : public CFileDialogImpl< T > +{ +public: + mutable LPCTSTR m_pNextFile; +#ifndef _UNICODE + bool m_bIsNT; +#endif + + CMultiFileDialogImpl( + LPCTSTR lpszDefExt = NULL, + LPCTSTR lpszFileName = NULL, + DWORD dwFlags = OFN_HIDEREADONLY, + LPCTSTR lpszFilter = NULL, + HWND hWndParent = NULL) + : CFileDialogImpl(TRUE, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent), + m_pNextFile(NULL) + { + m_ofn.Flags |= OFN_ALLOWMULTISELECT; // Force multiple selection mode + +#ifndef _UNICODE + OSVERSIONINFO ovi = { sizeof(ovi) }; + ::GetVersionEx(&ovi); + m_bIsNT = (ovi.dwPlatformId == VER_PLATFORM_WIN32_NT); + if (m_bIsNT) + { + // On NT platforms, GetOpenFileNameA thunks to GetOpenFileNameW and there + // is absolutely nothing we can do except to start off with a large buffer. + ATLVERIFY(ResizeFilenameBuffer(_WTL_FIXED_OFN_BUFFER_LENGTH)); + } +#endif + } + + ~CMultiFileDialogImpl() + { + if (m_ofn.lpstrFile != m_szFileName) // Free the buffer if we allocated it + delete[] m_ofn.lpstrFile; + } + +// Operations + // Get the directory that the files were chosen from. + // The function returns the number of characters copied, not including the terminating zero. + // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero. + // If the function fails, the return value is zero. + int GetDirectory(LPTSTR pBuffer, int nBufLen) const + { + if (m_ofn.lpstrFile == NULL) + return 0; + + LPCTSTR pStr = m_ofn.lpstrFile; + int nLength = lstrlen(pStr); + if (pStr[nLength + 1] == 0) + { + // The OFN buffer contains a single item so extract its path. + LPCTSTR pSep = _strrchr(pStr, _T('\\')); + if (pSep != NULL) + nLength = (int)(DWORD_PTR)(pSep - pStr); + } + + int nRet = 0; + if (pBuffer == NULL) // If the buffer is NULL, return the required length + { + nRet = nLength + 1; + } + else if (nBufLen > nLength) + { + SecureHelper::strncpy_x(pBuffer, nBufLen, pStr, nLength); + nRet = nLength; + } + + return nRet; + } + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + bool GetDirectory(_CSTRING_NS::CString& strDir) const + { + bool bRet = false; + + int nLength = GetDirectory(NULL, 0); + if (nLength > 0) + { + bRet = (GetDirectory(strDir.GetBuffer(nLength), nLength) > 0); + strDir.ReleaseBuffer(nLength - 1); + } + + return bRet; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + + // Get the first filename as a pointer into the buffer. + LPCTSTR GetFirstFileName() const + { + if (m_ofn.lpstrFile == NULL) + return NULL; + + m_pNextFile = NULL; // Reset internal buffer pointer + + LPCTSTR pStr = m_ofn.lpstrFile; + int nLength = lstrlen(pStr); + if (pStr[nLength + 1] != 0) + { + // Multiple items were selected. The first string is the directory, + // so skip forwards to the second string. + pStr += nLength + 1; + + // Set up m_pNext so it points to the second item (or null). + m_pNextFile = pStr; + GetNextFileName(); + } + else + { + // A single item was selected. Skip forward past the path. + LPCTSTR pSep = _strrchr(pStr, _T('\\')); + if (pSep != NULL) + pStr = pSep + 1; + } + + return pStr; + } + + // Get the next filename as a pointer into the buffer. + LPCTSTR GetNextFileName() const + { + if (m_pNextFile == NULL) + return NULL; + + LPCTSTR pStr = m_pNextFile; + // Set "m_pNextFile" to point to the next file name, or null if we + // have reached the last file in the list. + int nLength = lstrlen(pStr); + m_pNextFile = (pStr[nLength + 1] != 0) ? &pStr[nLength + 1] : NULL; + + return pStr; + } + + // Get the first filename as a full path. + // The function returns the number of characters copied, not including the terminating zero. + // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero. + // If the function fails, the return value is zero. + int GetFirstPathName(LPTSTR pBuffer, int nBufLen) const + { + LPCTSTR pStr = GetFirstFileName(); + int nLengthDir = GetDirectory(NULL, 0); + if((pStr == NULL) || (nLengthDir == 0)) + return 0; + + // Figure out the required length. + int nLengthTotal = nLengthDir + lstrlen(pStr); + + int nRet = 0; + if(pBuffer == NULL) // If the buffer is NULL, return the required length + { + nRet = nLengthTotal + 1; + } + else if (nBufLen > nLengthTotal) // If the buffer is big enough, go ahead and construct the path + { + GetDirectory(pBuffer, nBufLen); + SecureHelper::strcat_x(pBuffer, nBufLen, _T("\\")); + SecureHelper::strcat_x(pBuffer, nBufLen, pStr); + nRet = nLengthTotal; + } + + return nRet; + } + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + bool GetFirstPathName(_CSTRING_NS::CString& strPath) const + { + bool bRet = false; + + int nLength = GetFirstPathName(NULL, 0); + if (nLength > 0) + { + bRet = (GetFirstPathName(strPath.GetBuffer(nLength), nLength) > 0); + strPath.ReleaseBuffer(nLength - 1); + } + + return bRet; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + + // Get the next filename as a full path. + // The function returns the number of characters copied, not including the terminating zero. + // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero. + // If the function fails, the return value is zero. + // The internal position marker is moved forward only if the function succeeds and the buffer was large enough. + int GetNextPathName(LPTSTR pBuffer, int nBufLen) const + { + if (m_pNextFile == NULL) + return 0; + + int nRet = 0; + LPCTSTR pStr = m_pNextFile; + // Does the filename contain a backslash? + if (_strrchr(pStr, _T('\\')) != NULL) + { + // Yes, so we'll assume it's a full path. + int nLength = lstrlen(pStr); + + if (pBuffer == NULL) // If the buffer is NULL, return the required length + { + nRet = nLength + 1; + } + else if (nBufLen > nLength) // The buffer is big enough, so go ahead and copy the filename + { + SecureHelper::strcpy_x(pBuffer, nBufLen, GetNextFileName()); + nRet = nBufLen; + } + } + else + { + // The filename is relative, so construct the full path. + int nLengthDir = GetDirectory(NULL, 0); + if (nLengthDir > 0) + { + // Calculate the required space. + int nLengthTotal = nLengthDir + lstrlen(pStr); + + if(pBuffer == NULL) // If the buffer is NULL, return the required length + { + nRet = nLengthTotal + 1; + } + else if (nBufLen > nLengthTotal) // If the buffer is big enough, go ahead and construct the path + { + GetDirectory(pBuffer, nBufLen); + SecureHelper::strcat_x(pBuffer, nBufLen, _T("\\")); + SecureHelper::strcat_x(pBuffer, nBufLen, GetNextFileName()); + nRet = nLengthTotal; + } + } + } + + return nRet; + } + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + bool GetNextPathName(_CSTRING_NS::CString& strPath) const + { + bool bRet = false; + + int nLength = GetNextPathName(NULL, 0); + if (nLength > 0) + { + bRet = (GetNextPathName(strPath.GetBuffer(nLength), nLength) > 0); + strPath.ReleaseBuffer(nLength - 1); + } + + return bRet; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + +// Implementation + bool ResizeFilenameBuffer(DWORD dwLength) + { + if (dwLength > m_ofn.nMaxFile) + { + // Free the old buffer. + if (m_ofn.lpstrFile != m_szFileName) + { + delete[] m_ofn.lpstrFile; + m_ofn.lpstrFile = NULL; + m_ofn.nMaxFile = 0; + } + + // Allocate the new buffer. + LPTSTR lpstrBuff = NULL; + ATLTRY(lpstrBuff = new TCHAR[dwLength]); + if (lpstrBuff != NULL) + { + m_ofn.lpstrFile = lpstrBuff; + m_ofn.lpstrFile[0] = 0; + m_ofn.nMaxFile = dwLength; + } + } + + return (m_ofn.lpstrFile != NULL); + } + + void OnSelChange(LPOFNOTIFY /*lpon*/) + { +#ifndef _UNICODE + // There is no point resizing the buffer in ANSI builds running on NT. + if (m_bIsNT) + return; +#endif + + // Get the buffer length required to hold the spec. + int nLength = GetSpec(NULL, 0); + if (nLength <= 1) + return; // no files are selected, presumably + + // Add room for the directory, and an extra terminating zero. + nLength += GetFolderPath(NULL, 0) + 1; + + if (!ResizeFilenameBuffer(nLength)) + { + ATLASSERT(FALSE); + return; + } + + // If we are not following links then our work is done. + if ((m_ofn.Flags & OFN_NODEREFERENCELINKS) != 0) + return; + + // Get the file spec, which is the text in the edit control. + if (GetSpec(m_ofn.lpstrFile, m_ofn.nMaxFile) <= 0) + return; + + // Get the ID-list of the current folder. + int nBytes = GetFolderIDList(NULL, 0); + CTempBuffer idlist; + idlist.AllocateBytes(nBytes); + if ((nBytes <= 0) || (GetFolderIDList(idlist, nBytes) <= 0)) + return; + + // First bind to the desktop folder, then to the current folder. + ATL::CComPtr pDesktop, pFolder; + if (FAILED(::SHGetDesktopFolder(&pDesktop))) + return; + if (FAILED(pDesktop->BindToObject(idlist, NULL, IID_IShellFolder, (void**)&pFolder))) + return; + + // Work through the file spec, looking for quoted filenames. If we find a shortcut file, then + // we need to add enough extra buffer space to hold its target path. + DWORD nExtraChars = 0; + bool bInsideQuotes = false; + LPCTSTR pAnchor = m_ofn.lpstrFile; + LPCTSTR pChar = m_ofn.lpstrFile; + for ( ; *pChar; ++pChar) + { + // Look for quotation marks. + if (*pChar == _T('\"')) + { + // We are either entering or leaving a passage of quoted text. + bInsideQuotes = !bInsideQuotes; + + // Is it an opening or closing quote? + if (bInsideQuotes) + { + // We found an opening quote, so set "pAnchor" to the following character. + pAnchor = pChar + 1; + } + else // closing quote + { + // Each quoted entity should be shorter than MAX_PATH. + if (pChar - pAnchor >= MAX_PATH) + return; + + // Get the ID-list and attributes of the file. + USES_CONVERSION; + int nFileNameLength = (int)(DWORD_PTR)(pChar - pAnchor); + TCHAR szFileName[MAX_PATH]; + SecureHelper::strncpy_x(szFileName, MAX_PATH, pAnchor, nFileNameLength); + LPITEMIDLIST pidl = NULL; + DWORD dwAttrib = SFGAO_LINK; + if (SUCCEEDED(pFolder->ParseDisplayName(NULL, NULL, T2W(szFileName), NULL, &pidl, &dwAttrib))) + { + // Is it a shortcut file? + if (dwAttrib & SFGAO_LINK) + { + // Bind to its IShellLink interface. + ATL::CComPtr pLink; + if (SUCCEEDED(pFolder->BindToObject(pidl, NULL, IID_IShellLink, (void**)&pLink))) + { + // Get the shortcut's target path. + TCHAR szPath[MAX_PATH]; + if (SUCCEEDED(pLink->GetPath(szPath, MAX_PATH, NULL, 0))) + { + // If the target path is longer than the shortcut name, then add on the number + // of extra characters that are required. + int nNewLength = lstrlen(szPath); + if (nNewLength > nFileNameLength) + nExtraChars += nNewLength - nFileNameLength; + } + } + } + + // Free the ID-list returned by ParseDisplayName. + ::CoTaskMemFree(pidl); + } + } + } + } + + // If we need more space for shortcut targets, then reallocate. + if (nExtraChars > 0) + ATLVERIFY(ResizeFilenameBuffer(m_ofn.nMaxFile + nExtraChars)); + } + + // Helper for _ATM_MIN_CRT + static const TCHAR* _strrchr(const TCHAR* p, TCHAR ch) + { +#ifndef _ATL_MIN_CRT + return _tcsrchr(p, ch); +#else // _ATL_MIN_CRT + const TCHAR* lpsz = NULL; + while (*p != 0) + { + if (*p == ch) + lpsz = p; + p = ::CharNext(p); + } + return lpsz; +#endif // _ATL_MIN_CRT + } +}; + +class CMultiFileDialog : public CMultiFileDialogImpl +{ +public: + CMultiFileDialog( + LPCTSTR lpszDefExt = NULL, + LPCTSTR lpszFileName = NULL, + DWORD dwFlags = OFN_HIDEREADONLY, + LPCTSTR lpszFilter = NULL, + HWND hWndParent = NULL) + : CMultiFileDialogImpl(lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent) + { } + + BEGIN_MSG_MAP(CMultiFileDialog) + CHAIN_MSG_MAP(CMultiFileDialogImpl) + END_MSG_MAP() +}; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// Shell File Dialog - new Shell File Open and Save dialogs in Vista + +// Note: Use GetPtr() to access dialog interface methods. +// Example: +// CShellFileOpenDialog dlg; +// dlg.GetPtr()->SetTitle(L"MyFileOpenDialog"); + +#if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE) + +/////////////////////////////////////////////////////////////////////////////// +// CShellFileDialogImpl - base class for CShellFileOpenDialogImpl and CShellFileSaveDialogImpl + +template +class ATL_NO_VTABLE CShellFileDialogImpl : public IFileDialogEvents +{ +public: +// Operations + INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) + { + INT_PTR nRet = -1; + + T* pT = static_cast(this); + if(pT->m_spFileDlg == NULL) + { + ATLASSERT(FALSE); + return nRet; + } + + DWORD dwCookie = 0; + pT->_Advise(dwCookie); + + HRESULT hRet = pT->m_spFileDlg->Show(hWndParent); + if(SUCCEEDED(hRet)) + nRet = IDOK; + else if(hRet == HRESULT_FROM_WIN32(ERROR_CANCELLED)) + nRet = IDCANCEL; + else + ATLASSERT(FALSE); // error + + pT->_Unadvise(dwCookie); + + return nRet; + } + + bool IsNull() const + { + const T* pT = static_cast(this); + return (pT->m_spFileDlg == NULL); + } + +// Operations - get file path after dialog returns + HRESULT GetFilePath(LPWSTR lpstrFilePath, int cchLength) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_spFileDlg != NULL); + + ATL::CComPtr spItem; + HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem); + + if(SUCCEEDED(hRet)) + hRet = GetFileNameFromShellItem(spItem, SIGDN_FILESYSPATH, lpstrFilePath, cchLength); + + return hRet; + } + + HRESULT GetFileTitle(LPWSTR lpstrFileTitle, int cchLength) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_spFileDlg != NULL); + + ATL::CComPtr spItem; + HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem); + + if(SUCCEEDED(hRet)) + hRet = GetFileNameFromShellItem(spItem, SIGDN_NORMALDISPLAY, lpstrFileTitle, cchLength); + + return hRet; + } + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + HRESULT GetFilePath(_CSTRING_NS::CString& strFilePath) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_spFileDlg != NULL); + + ATL::CComPtr spItem; + HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem); + + if(SUCCEEDED(hRet)) + hRet = GetFileNameFromShellItem(spItem, SIGDN_FILESYSPATH, strFilePath); + + return hRet; + } + + HRESULT GetFileTitle(_CSTRING_NS::CString& strFileTitle) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_spFileDlg != NULL); + + ATL::CComPtr spItem; + HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem); + + if(SUCCEEDED(hRet)) + hRet = GetFileNameFromShellItem(spItem, SIGDN_NORMALDISPLAY, strFileTitle); + + return hRet; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + +// Helpers for IShellItem + static HRESULT GetFileNameFromShellItem(IShellItem* pShellItem, SIGDN type, LPWSTR lpstr, int cchLength) + { + ATLASSERT(pShellItem != NULL); + + LPWSTR lpstrName = NULL; + HRESULT hRet = pShellItem->GetDisplayName(type, &lpstrName); + + if(SUCCEEDED(hRet)) + { + if(lstrlenW(lpstrName) < cchLength) + { + SecureHelper::strcpyW_x(lpstr, cchLength, lpstrName); + } + else + { + ATLASSERT(FALSE); + hRet = DISP_E_BUFFERTOOSMALL; + } + + ::CoTaskMemFree(lpstrName); + } + + return hRet; + } + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + static HRESULT GetFileNameFromShellItem(IShellItem* pShellItem, SIGDN type, _CSTRING_NS::CString& str) + { + ATLASSERT(pShellItem != NULL); + + LPWSTR lpstrName = NULL; + HRESULT hRet = pShellItem->GetDisplayName(type, &lpstrName); + + if(SUCCEEDED(hRet)) + { + str = lpstrName; + ::CoTaskMemFree(lpstrName); + } + + return hRet; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + +// Implementation + void _Advise(DWORD& dwCookie) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_spFileDlg != NULL); + HRESULT hRet = pT->m_spFileDlg->Advise((IFileDialogEvents*)this, &dwCookie); + ATLVERIFY(SUCCEEDED(hRet)); + } + + void _Unadvise(DWORD dwCookie) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_spFileDlg != NULL); + HRESULT hRet = pT->m_spFileDlg->Unadvise(dwCookie); + ATLVERIFY(SUCCEEDED(hRet)); + } + + void _Init(LPCWSTR lpszFileName, DWORD dwOptions, LPCWSTR lpszDefExt, const COMDLG_FILTERSPEC* arrFilterSpec, UINT uFilterSpecCount) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_spFileDlg != NULL); + + HRESULT hRet = E_FAIL; + + if(lpszFileName != NULL) + { + hRet = pT->m_spFileDlg->SetFileName(lpszFileName); + ATLASSERT(SUCCEEDED(hRet)); + } + + hRet = pT->m_spFileDlg->SetOptions(dwOptions); + ATLASSERT(SUCCEEDED(hRet)); + + if(lpszDefExt != NULL) + { + hRet = pT->m_spFileDlg->SetDefaultExtension(lpszDefExt); + ATLASSERT(SUCCEEDED(hRet)); + } + + if(arrFilterSpec != NULL && uFilterSpecCount != 0U) + { + hRet = pT->m_spFileDlg->SetFileTypes(uFilterSpecCount, arrFilterSpec); + ATLASSERT(SUCCEEDED(hRet)); + } + } + +// Implementation - IUnknown interface + STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) + { + if(ppvObject == NULL) + return E_POINTER; + + T* pT = static_cast(this); + if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IFileDialogEvents)) + { + *ppvObject = (IFileDialogEvents*)pT; + // AddRef() not needed + return S_OK; + } + + return E_NOINTERFACE; + } + + virtual ULONG STDMETHODCALLTYPE AddRef() + { + return 1; + } + + virtual ULONG STDMETHODCALLTYPE Release() + { + return 1; + } + +// Implementation - IFileDialogEvents interface + virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFileOk(IFileDialog* pfd) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd)); + pfd; // avoid level 4 warning + return pT->OnFileOk(); + } + + virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFolderChanging(IFileDialog* pfd, IShellItem* psiFolder) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd)); + pfd; // avoid level 4 warning + return pT->OnFolderChanging(psiFolder); + } + + virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFolderChange(IFileDialog* pfd) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd)); + pfd; // avoid level 4 warning + return pT->OnFolderChange(); + } + + virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnSelectionChange(IFileDialog* pfd) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd)); + pfd; // avoid level 4 warning + return pT->OnSelectionChange(); + } + + virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnShareViolation(IFileDialog* pfd, IShellItem* psi, FDE_SHAREVIOLATION_RESPONSE* pResponse) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd)); + pfd; // avoid level 4 warning + return pT->OnShareViolation(psi, pResponse); + } + + virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnTypeChange(IFileDialog* pfd) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd)); + pfd; // avoid level 4 warning + return pT->OnTypeChange(); + } + + virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnOverwrite(IFileDialog* pfd, IShellItem* psi, FDE_OVERWRITE_RESPONSE* pResponse) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd)); + pfd; // avoid level 4 warning + return pT->OnOverwrite(psi, pResponse); + } + +// Overrideables - Event handlers + HRESULT OnFileOk() + { + return E_NOTIMPL; + } + + HRESULT OnFolderChanging(IShellItem* /*psiFolder*/) + { + return E_NOTIMPL; + } + + HRESULT OnFolderChange() + { + return E_NOTIMPL; + } + + HRESULT OnSelectionChange() + { + return E_NOTIMPL; + } + + HRESULT OnShareViolation(IShellItem* /*psi*/, FDE_SHAREVIOLATION_RESPONSE* /*pResponse*/) + { + return E_NOTIMPL; + } + + HRESULT OnTypeChange() + { + return E_NOTIMPL; + } + + HRESULT OnOverwrite(IShellItem* /*psi*/, FDE_OVERWRITE_RESPONSE* /*pResponse*/) + { + return E_NOTIMPL; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CShellFileOpenDialogImpl - implements new Shell File Open dialog + +template +class ATL_NO_VTABLE CShellFileOpenDialogImpl : public CShellFileDialogImpl< T > +{ +public: + ATL::CComPtr m_spFileDlg; + + CShellFileOpenDialogImpl(LPCWSTR lpszFileName = NULL, + DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST, + LPCWSTR lpszDefExt = NULL, + const COMDLG_FILTERSPEC* arrFilterSpec = NULL, + UINT uFilterSpecCount = 0U) + { + HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileOpenDialog); + + if(SUCCEEDED(hRet)) + _Init(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount); + } + + IFileOpenDialog* GetPtr() + { + return m_spFileDlg; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CShellFileOpenDialog - new Shell File Open dialog without events + +class CShellFileOpenDialog : public CShellFileOpenDialogImpl +{ +public: + CShellFileOpenDialog(LPCWSTR lpszFileName = NULL, + DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST, + LPCWSTR lpszDefExt = NULL, + const COMDLG_FILTERSPEC* arrFilterSpec = NULL, + UINT uFilterSpecCount = 0U) : CShellFileOpenDialogImpl(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount) + { } + +// Implementation (remove _Advise/_Unadvise code using template magic) + void _Advise(DWORD& /*dwCookie*/) + { } + + void _Unadvise(DWORD /*dwCookie*/) + { } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CShellFileSaveDialogImpl - implements new Shell File Save dialog + +template +class ATL_NO_VTABLE CShellFileSaveDialogImpl : public CShellFileDialogImpl< T > +{ +public: + ATL::CComPtr m_spFileDlg; + + CShellFileSaveDialogImpl(LPCWSTR lpszFileName = NULL, + DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT, + LPCWSTR lpszDefExt = NULL, + const COMDLG_FILTERSPEC* arrFilterSpec = NULL, + UINT uFilterSpecCount = 0U) + { + HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileSaveDialog); + + if(SUCCEEDED(hRet)) + _Init(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount); + } + + IFileSaveDialog* GetPtr() + { + return m_spFileDlg; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CShellFileSaveDialog - new Shell File Save dialog without events + +class CShellFileSaveDialog : public CShellFileSaveDialogImpl +{ +public: + CShellFileSaveDialog(LPCWSTR lpszFileName = NULL, + DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT, + LPCWSTR lpszDefExt = NULL, + const COMDLG_FILTERSPEC* arrFilterSpec = NULL, + UINT uFilterSpecCount = 0U) : CShellFileSaveDialogImpl(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount) + { } + +// Implementation (remove _Advise/_Unadvise code using template magic) + void _Advise(DWORD& /*dwCookie*/) + { } + + void _Unadvise(DWORD /*dwCookie*/) + { } +}; + +#endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE) + + +/////////////////////////////////////////////////////////////////////////////// +// CFolderDialogImpl - used for browsing for a folder + +#ifndef _WIN32_WCE + +template +class ATL_NO_VTABLE CFolderDialogImpl +{ +public: + BROWSEINFO m_bi; + LPCTSTR m_lpstrInitialFolder; + LPCITEMIDLIST m_pidlInitialSelection; + bool m_bExpandInitialSelection; + TCHAR m_szFolderDisplayName[MAX_PATH]; + TCHAR m_szFolderPath[MAX_PATH]; + LPITEMIDLIST m_pidlSelected; + HWND m_hWnd; // used only in the callback function + +// Constructor + CFolderDialogImpl(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_RETURNONLYFSDIRS) : + m_lpstrInitialFolder(NULL), m_pidlInitialSelection(NULL), m_bExpandInitialSelection(false), m_pidlSelected(NULL), m_hWnd(NULL) + { + memset(&m_bi, 0, sizeof(m_bi)); // initialize structure to 0/NULL + + m_bi.hwndOwner = hWndParent; + m_bi.pidlRoot = NULL; + m_bi.pszDisplayName = m_szFolderDisplayName; + m_bi.lpszTitle = lpstrTitle; + m_bi.ulFlags = uFlags; + m_bi.lpfn = BrowseCallbackProc; + m_bi.lParam = (LPARAM)static_cast(this); + + m_szFolderPath[0] = 0; + m_szFolderDisplayName[0] = 0; + } + + ~CFolderDialogImpl() + { + ::CoTaskMemFree(m_pidlSelected); + } + +// Operations + INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) + { + if(m_bi.hwndOwner == NULL) // set only if not specified before + m_bi.hwndOwner = hWndParent; + + // Clear out any previous results + m_szFolderPath[0] = 0; + m_szFolderDisplayName[0] = 0; + ::CoTaskMemFree(m_pidlSelected); + + INT_PTR nRet = IDCANCEL; + m_pidlSelected = ::SHBrowseForFolder(&m_bi); + + if(m_pidlSelected != NULL) + { + nRet = IDOK; + + // If BIF_RETURNONLYFSDIRS is set, we try to get the filesystem path. + // Otherwise, the caller must handle the ID-list directly. + if((m_bi.ulFlags & BIF_RETURNONLYFSDIRS) != 0) + { + if(::SHGetPathFromIDList(m_pidlSelected, m_szFolderPath) == FALSE) + nRet = IDCANCEL; + } + } + + return nRet; + } + + // Methods to call before DoModal + void SetInitialFolder(LPCTSTR lpstrInitialFolder, bool bExpand = true) + { + // lpstrInitialFolder may be a file if BIF_BROWSEINCLUDEFILES is specified + m_lpstrInitialFolder = lpstrInitialFolder; + m_bExpandInitialSelection = bExpand; + } + + void SetInitialSelection(LPCITEMIDLIST pidl, bool bExpand = true) + { + m_pidlInitialSelection = pidl; + m_bExpandInitialSelection = bExpand; + } + + // Methods to call after DoModal + LPITEMIDLIST GetSelectedItem(bool bDetach = false) + { + LPITEMIDLIST pidl = m_pidlSelected; + if(bDetach) + m_pidlSelected = NULL; + + return pidl; + } + + LPCTSTR GetFolderPath() const + { + return m_szFolderPath; + } + + LPCTSTR GetFolderDisplayName() const + { + return m_szFolderDisplayName; + } + + int GetFolderImageIndex() const + { + return m_bi.iImage; + } + +// Callback function and overrideables + static int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData) + { +#ifndef BFFM_VALIDATEFAILED + #ifdef UNICODE + const int BFFM_VALIDATEFAILED = 4; + #else + const int BFFM_VALIDATEFAILED = 3; + #endif +#endif // !BFFM_VALIDATEFAILED +#ifndef BFFM_IUNKNOWN + const int BFFM_IUNKNOWN = 5; +#endif // !BFFM_IUNKNOWN +#ifndef BIF_NEWDIALOGSTYLE + const UINT BIF_NEWDIALOGSTYLE = 0x0040; +#endif // !BIF_NEWDIALOGSTYLE + + int nRet = 0; + T* pT = (T*)lpData; + bool bClear = false; + if(pT->m_hWnd == NULL) + { + pT->m_hWnd = hWnd; + bClear = true; + } + else + { + ATLASSERT(pT->m_hWnd == hWnd); + } + + switch(uMsg) + { + case BFFM_INITIALIZED: + // Set initial selection + // Note that m_pidlInitialSelection, if set, takes precedence over m_lpstrInitialFolder + if(pT->m_pidlInitialSelection != NULL) + pT->SetSelection(pT->m_pidlInitialSelection); + else if(pT->m_lpstrInitialFolder != NULL) + pT->SetSelection(pT->m_lpstrInitialFolder); + + // Expand initial selection if appropriate + if(pT->m_bExpandInitialSelection && ((pT->m_bi.ulFlags & BIF_NEWDIALOGSTYLE) != 0)) + { + if(pT->m_pidlInitialSelection != NULL) + pT->SetExpanded(pT->m_pidlInitialSelection); + else if(pT->m_lpstrInitialFolder != NULL) + pT->SetExpanded(pT->m_lpstrInitialFolder); + } + pT->OnInitialized(); + break; + case BFFM_SELCHANGED: + pT->OnSelChanged((LPITEMIDLIST)lParam); + break; + case BFFM_VALIDATEFAILED: + nRet = pT->OnValidateFailed((LPCTSTR)lParam); + break; + case BFFM_IUNKNOWN: + pT->OnIUnknown((IUnknown*)lParam); + break; + default: + ATLTRACE2(atlTraceUI, 0, _T("Unknown message received in CFolderDialogImpl::BrowseCallbackProc\n")); + break; + } + + if(bClear) + pT->m_hWnd = NULL; + return nRet; + } + + void OnInitialized() + { + } + + void OnSelChanged(LPITEMIDLIST /*pItemIDList*/) + { + } + + int OnValidateFailed(LPCTSTR /*lpstrFolderPath*/) + { + return 1; // 1=continue, 0=EndDialog + } + + void OnIUnknown(IUnknown* /*pUnknown*/) + { + } + + // Commands - valid to call only from handlers + void EnableOK(BOOL bEnable) + { + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, BFFM_ENABLEOK, 0, bEnable); + } + + void SetSelection(LPCITEMIDLIST pItemIDList) + { + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, BFFM_SETSELECTION, FALSE, (LPARAM)pItemIDList); + } + + void SetSelection(LPCTSTR lpstrFolderPath) + { + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, BFFM_SETSELECTION, TRUE, (LPARAM)lpstrFolderPath); + } + + void SetStatusText(LPCTSTR lpstrText) + { + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)lpstrText); + } + + void SetOKText(LPCTSTR lpstrOKText) + { +#ifndef BFFM_SETOKTEXT + const UINT BFFM_SETOKTEXT = WM_USER + 105; +#endif + ATLASSERT(m_hWnd != NULL); + USES_CONVERSION; + LPCWSTR lpstr = T2CW(lpstrOKText); + ::SendMessage(m_hWnd, BFFM_SETOKTEXT, (WPARAM)lpstr, 0L); + } + + void SetExpanded(LPCITEMIDLIST pItemIDList) + { +#ifndef BFFM_SETEXPANDED + const UINT BFFM_SETEXPANDED = WM_USER + 106; +#endif + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, BFFM_SETEXPANDED, FALSE, (LPARAM)pItemIDList); + } + + void SetExpanded(LPCTSTR lpstrFolderPath) + { +#ifndef BFFM_SETEXPANDED + const UINT BFFM_SETEXPANDED = WM_USER + 106; +#endif + ATLASSERT(m_hWnd != NULL); + USES_CONVERSION; + LPCWSTR lpstr = T2CW(lpstrFolderPath); + ::SendMessage(m_hWnd, BFFM_SETEXPANDED, TRUE, (LPARAM)lpstr); + } +}; + +class CFolderDialog : public CFolderDialogImpl +{ +public: + CFolderDialog(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_RETURNONLYFSDIRS) + : CFolderDialogImpl(hWndParent, lpstrTitle, uFlags) + { } +}; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CCommonDialogImplBase - base class for common dialog classes + +class ATL_NO_VTABLE CCommonDialogImplBase : public ATL::CWindowImplBase +{ +public: + static UINT_PTR APIENTRY HookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + if(uMsg != WM_INITDIALOG) + return 0; + CCommonDialogImplBase* pT = (CCommonDialogImplBase*)ModuleHelper::ExtractCreateWndData(); + ATLASSERT(pT != NULL); + ATLASSERT(pT->m_hWnd == NULL); + ATLASSERT(::IsWindow(hWnd)); + // subclass dialog's window + if(!pT->SubclassWindow(hWnd)) + { + ATLTRACE2(atlTraceUI, 0, _T("Subclassing a common dialog failed\n")); + return 0; + } + // check message map for WM_INITDIALOG handler + LRESULT lRes = 0; + if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0) == FALSE) + return 0; + return lRes; + } + +// Special override for common dialogs + BOOL EndDialog(INT_PTR /*nRetCode*/ = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + SendMessage(WM_COMMAND, MAKEWPARAM(IDABORT, 0)); + return TRUE; + } + +// Implementation - try to override these, to prevent errors + HWND Create(HWND, ATL::_U_RECT, LPCTSTR, DWORD, DWORD, ATL::_U_MENUorID, ATOM, LPVOID) + { + ATLASSERT(FALSE); // should not be called + return NULL; + } + + static LRESULT CALLBACK StartWindowProc(HWND /*hWnd*/, UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/) + { + ATLASSERT(FALSE); // should not be called + return 0; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CFontDialogImpl - font selection dialog + +#ifndef _WIN32_WCE + +template +class ATL_NO_VTABLE CFontDialogImpl : public CCommonDialogImplBase +{ +public: + enum { _cchStyleName = 64 }; + + CHOOSEFONT m_cf; + TCHAR m_szStyleName[_cchStyleName]; // contains style name after return + LOGFONT m_lf; // default LOGFONT to store the info + +// Constructors + CFontDialogImpl(LPLOGFONT lplfInitial = NULL, + DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS, + HDC hDCPrinter = NULL, + HWND hWndParent = NULL) + { + memset(&m_cf, 0, sizeof(m_cf)); + memset(&m_lf, 0, sizeof(m_lf)); + memset(&m_szStyleName, 0, sizeof(m_szStyleName)); + + m_cf.lStructSize = sizeof(m_cf); + m_cf.hwndOwner = hWndParent; + m_cf.rgbColors = RGB(0, 0, 0); + m_cf.lpszStyle = (LPTSTR)&m_szStyleName; + m_cf.Flags = dwFlags | CF_ENABLEHOOK; + m_cf.lpfnHook = (LPCFHOOKPROC)T::HookProc; + + if(lplfInitial != NULL) + { + m_cf.lpLogFont = lplfInitial; + m_cf.Flags |= CF_INITTOLOGFONTSTRUCT; + m_lf = *lplfInitial; + } + else + { + m_cf.lpLogFont = &m_lf; + } + + if(hDCPrinter != NULL) + { + m_cf.hDC = hDCPrinter; + m_cf.Flags |= CF_PRINTERFONTS; + } + } + +// Operations + INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) + { + ATLASSERT((m_cf.Flags & CF_ENABLEHOOK) != 0); + ATLASSERT(m_cf.lpfnHook != NULL); // can still be a user hook + + if(m_cf.hwndOwner == NULL) // set only if not specified before + m_cf.hwndOwner = hWndParent; + + ATLASSERT(m_hWnd == NULL); + ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this); + + BOOL bRet = ::ChooseFont(&m_cf); + + m_hWnd = NULL; + + if(bRet) // copy logical font from user's initialization buffer (if needed) + SecureHelper::memcpy_x(&m_lf, sizeof(m_lf), m_cf.lpLogFont, sizeof(m_lf)); + + return bRet ? IDOK : IDCANCEL; + } + + // works only when the dialog is dislayed or after + void GetCurrentFont(LPLOGFONT lplf) const + { + ATLASSERT(lplf != NULL); + + if(m_hWnd != NULL) + ::SendMessage(m_hWnd, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM)lplf); + else + *lplf = m_lf; + } + + // works only when the dialog is dislayed or before +#ifndef _WIN32_WCE + void SetLogFont(LPLOGFONT lplf) + { + ATLASSERT(lplf != NULL); +#ifndef WM_CHOOSEFONT_SETLOGFONT + const UINT WM_CHOOSEFONT_SETLOGFONT = (WM_USER + 101); +#endif + if(m_hWnd != NULL) + { + ::SendMessage(m_hWnd, WM_CHOOSEFONT_SETLOGFONT, 0, (LPARAM)lplf); + } + else + { + m_lf = *lplf; + m_cf.Flags |= CF_INITTOLOGFONTSTRUCT; + } + } + + void SetFlags(DWORD dwFlags) + { +#ifndef WM_CHOOSEFONT_SETFLAGS + const UINT WM_CHOOSEFONT_SETFLAGS = (WM_USER + 102); +#endif + if(m_hWnd != NULL) + { + CHOOSEFONT cf = { sizeof(CHOOSEFONT) }; + cf.Flags = dwFlags; + ::SendMessage(m_hWnd, WM_CHOOSEFONT_SETFLAGS, 0, (LPARAM)&cf); + } + else + { + m_cf.Flags = dwFlags; + } + } +#endif // !_WIN32_WCE + + // Helpers for parsing information after successful return + LPCTSTR GetFaceName() const // return the face name of the font + { + return (LPCTSTR)m_cf.lpLogFont->lfFaceName; + } + + LPCTSTR GetStyleName() const // return the style name of the font + { + return m_cf.lpszStyle; + } + + int GetSize() const // return the pt size of the font + { + return m_cf.iPointSize; + } + + COLORREF GetColor() const // return the color of the font + { + return m_cf.rgbColors; + } + + int GetWeight() const // return the chosen font weight + { + return (int)m_cf.lpLogFont->lfWeight; + } + + BOOL IsStrikeOut() const // return TRUE if strikeout + { + return (m_cf.lpLogFont->lfStrikeOut) ? TRUE : FALSE; + } + + BOOL IsUnderline() const // return TRUE if underline + { + return (m_cf.lpLogFont->lfUnderline) ? TRUE : FALSE; + } + + BOOL IsBold() const // return TRUE if bold font + { + return (m_cf.lpLogFont->lfWeight == FW_BOLD) ? TRUE : FALSE; + } + + BOOL IsItalic() const // return TRUE if italic font + { + return m_cf.lpLogFont->lfItalic ? TRUE : FALSE; + } +}; + +class CFontDialog : public CFontDialogImpl +{ +public: + CFontDialog(LPLOGFONT lplfInitial = NULL, + DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS, + HDC hDCPrinter = NULL, + HWND hWndParent = NULL) + : CFontDialogImpl(lplfInitial, dwFlags, hDCPrinter, hWndParent) + { } + + DECLARE_EMPTY_MSG_MAP() +}; + +#endif // _WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CRichEditFontDialogImpl - font selection for the Rich Edit ctrl + +#if defined(_RICHEDIT_) && !defined(_WIN32_WCE) + +template +class ATL_NO_VTABLE CRichEditFontDialogImpl : public CFontDialogImpl< T > +{ +public: + CRichEditFontDialogImpl(const CHARFORMAT& charformat, + DWORD dwFlags = CF_SCREENFONTS, + HDC hDCPrinter = NULL, + HWND hWndParent = NULL) + : CFontDialogImpl< T >(NULL, dwFlags, hDCPrinter, hWndParent) + { + m_cf.Flags |= CF_INITTOLOGFONTSTRUCT; + m_cf.Flags |= FillInLogFont(charformat); + m_cf.lpLogFont = &m_lf; + + if((charformat.dwMask & CFM_COLOR) != 0) + m_cf.rgbColors = charformat.crTextColor; + } + + void GetCharFormat(CHARFORMAT& cf) const + { + USES_CONVERSION; + cf.dwEffects = 0; + cf.dwMask = 0; + if((m_cf.Flags & CF_NOSTYLESEL) == 0) + { + cf.dwMask |= CFM_BOLD | CFM_ITALIC; + cf.dwEffects |= IsBold() ? CFE_BOLD : 0; + cf.dwEffects |= IsItalic() ? CFE_ITALIC : 0; + } + if((m_cf.Flags & CF_NOSIZESEL) == 0) + { + cf.dwMask |= CFM_SIZE; + // GetSize() returns in tenths of points so mulitply by 2 to get twips + cf.yHeight = GetSize() * 2; + } + + if((m_cf.Flags & CF_NOFACESEL) == 0) + { + cf.dwMask |= CFM_FACE; + cf.bPitchAndFamily = m_cf.lpLogFont->lfPitchAndFamily; +#if (_RICHEDIT_VER >= 0x0200) + SecureHelper::strcpy_x(cf.szFaceName, _countof(cf.szFaceName), GetFaceName()); +#else // !(_RICHEDIT_VER >= 0x0200) + SecureHelper::strcpyA_x(cf.szFaceName, _countof(cf.szFaceName), T2A((LPTSTR)(LPCTSTR)GetFaceName())); +#endif // !(_RICHEDIT_VER >= 0x0200) + } + + if((m_cf.Flags & CF_EFFECTS) != 0) + { + cf.dwMask |= CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR; + cf.dwEffects |= IsUnderline() ? CFE_UNDERLINE : 0; + cf.dwEffects |= IsStrikeOut() ? CFE_STRIKEOUT : 0; + cf.crTextColor = GetColor(); + } + if((m_cf.Flags & CF_NOSCRIPTSEL) == 0) + { + cf.bCharSet = m_cf.lpLogFont->lfCharSet; + cf.dwMask |= CFM_CHARSET; + } + cf.yOffset = 0; + } + + DWORD FillInLogFont(const CHARFORMAT& cf) + { + USES_CONVERSION; + DWORD dwFlags = 0; + if((cf.dwMask & CFM_SIZE) != 0) + { + HDC hDC = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL); + LONG yPerInch = ::GetDeviceCaps(hDC, LOGPIXELSY); + m_lf.lfHeight = -(int)((cf.yHeight * yPerInch) / 1440); + } + else + m_lf.lfHeight = 0; + + m_lf.lfWidth = 0; + m_lf.lfEscapement = 0; + m_lf.lfOrientation = 0; + + if((cf.dwMask & (CFM_ITALIC | CFM_BOLD)) == (CFM_ITALIC | CFM_BOLD)) + { + m_lf.lfWeight = ((cf.dwEffects & CFE_BOLD) != 0) ? FW_BOLD : FW_NORMAL; + m_lf.lfItalic = (BYTE)(((cf.dwEffects & CFE_ITALIC) != 0) ? TRUE : FALSE); + } + else + { + dwFlags |= CF_NOSTYLESEL; + m_lf.lfWeight = FW_DONTCARE; + m_lf.lfItalic = FALSE; + } + + if((cf.dwMask & (CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR)) == (CFM_UNDERLINE|CFM_STRIKEOUT|CFM_COLOR)) + { + dwFlags |= CF_EFFECTS; + m_lf.lfUnderline = (BYTE)(((cf.dwEffects & CFE_UNDERLINE) != 0) ? TRUE : FALSE); + m_lf.lfStrikeOut = (BYTE)(((cf.dwEffects & CFE_STRIKEOUT) != 0) ? TRUE : FALSE); + } + else + { + m_lf.lfUnderline = (BYTE)FALSE; + m_lf.lfStrikeOut = (BYTE)FALSE; + } + + if((cf.dwMask & CFM_CHARSET) != 0) + m_lf.lfCharSet = cf.bCharSet; + else + dwFlags |= CF_NOSCRIPTSEL; + m_lf.lfOutPrecision = OUT_DEFAULT_PRECIS; + m_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + m_lf.lfQuality = DEFAULT_QUALITY; + if((cf.dwMask & CFM_FACE) != 0) + { + m_lf.lfPitchAndFamily = cf.bPitchAndFamily; +#if (_RICHEDIT_VER >= 0x0200) + SecureHelper::strcpy_x(m_lf.lfFaceName, _countof(m_lf.lfFaceName), cf.szFaceName); +#else // !(_RICHEDIT_VER >= 0x0200) + SecureHelper::strcpy_x(m_lf.lfFaceName, _countof(m_lf.lfFaceName), A2T((LPSTR)cf.szFaceName)); +#endif // !(_RICHEDIT_VER >= 0x0200) + } + else + { + m_lf.lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE; + m_lf.lfFaceName[0] = (TCHAR)0; + } + return dwFlags; + } +}; + +class CRichEditFontDialog : public CRichEditFontDialogImpl +{ +public: + CRichEditFontDialog(const CHARFORMAT& charformat, + DWORD dwFlags = CF_SCREENFONTS, + HDC hDCPrinter = NULL, + HWND hWndParent = NULL) + : CRichEditFontDialogImpl(charformat, dwFlags, hDCPrinter, hWndParent) + { } + + DECLARE_EMPTY_MSG_MAP() +}; + +#endif // defined(_RICHEDIT_) && !defined(_WIN32_WCE) + + +/////////////////////////////////////////////////////////////////////////////// +// CColorDialogImpl - color selection + +#if !defined(_WIN32_WCE) || ((_WIN32_WCE > 420) && !(defined(WIN32_PLATFORM_WFSP) && (_WIN32_WCE > 0x0500))) + +#ifdef _WIN32_WCE + #pragma comment(lib, "commdlg.lib") + + #ifndef SETRGBSTRING + #define SETRGBSTRING _T("commdlg_SetRGBColor") + #endif + + #ifndef COLOROKSTRING + #define COLOROKSTRING _T("commdlg_ColorOK") + #endif +#endif + +template +class ATL_NO_VTABLE CColorDialogImpl : public CCommonDialogImplBase +{ +public: + CHOOSECOLOR m_cc; + +// Constructor + CColorDialogImpl(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL) + { + memset(&m_cc, 0, sizeof(m_cc)); + + m_cc.lStructSize = sizeof(m_cc); + m_cc.lpCustColors = GetCustomColors(); + m_cc.hwndOwner = hWndParent; + m_cc.Flags = dwFlags | CC_ENABLEHOOK; + m_cc.lpfnHook = (LPCCHOOKPROC)T::HookProc; + + if(clrInit != 0) + { + m_cc.rgbResult = clrInit; + m_cc.Flags |= CC_RGBINIT; + } + } + +// Operations + INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) + { + ATLASSERT((m_cc.Flags & CC_ENABLEHOOK) != 0); + ATLASSERT(m_cc.lpfnHook != NULL); // can still be a user hook + + if(m_cc.hwndOwner == NULL) // set only if not specified before + m_cc.hwndOwner = hWndParent; + + ATLASSERT(m_hWnd == NULL); + ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this); + + BOOL bRet = ::ChooseColor(&m_cc); + + m_hWnd = NULL; + + return bRet ? IDOK : IDCANCEL; + } + + // Set the current color while dialog is displayed + void SetCurrentColor(COLORREF clr) + { + ATLASSERT(::IsWindow(m_hWnd)); + SendMessage(_GetSetRGBMessage(), 0, (LPARAM)clr); + } + + // Get the selected color after DoModal returns, or in OnColorOK + COLORREF GetColor() const + { + return m_cc.rgbResult; + } + +// Special override for the color dialog + static UINT_PTR APIENTRY HookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + if(uMsg != WM_INITDIALOG && uMsg != _GetColorOKMessage()) + return 0; + + LPCHOOSECOLOR lpCC = (LPCHOOSECOLOR)lParam; + CCommonDialogImplBase* pT = NULL; + + if(uMsg == WM_INITDIALOG) + { + pT = (CCommonDialogImplBase*)ModuleHelper::ExtractCreateWndData(); + lpCC->lCustData = (LPARAM)pT; + ATLASSERT(pT != NULL); + ATLASSERT(pT->m_hWnd == NULL); + ATLASSERT(::IsWindow(hWnd)); + // subclass dialog's window + if(!pT->SubclassWindow(hWnd)) + { + ATLTRACE2(atlTraceUI, 0, _T("Subclassing a Color common dialog failed\n")); + return 0; + } + } + else if(uMsg == _GetColorOKMessage()) + { + pT = (CCommonDialogImplBase*)lpCC->lCustData; + ATLASSERT(pT != NULL); + ATLASSERT(::IsWindow(pT->m_hWnd)); + } + + // pass to the message map + LRESULT lRes; + if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0) == FALSE) + return 0; + return lRes; + } + +// Helpers + static COLORREF* GetCustomColors() + { + static COLORREF rgbCustomColors[16] = + { + RGB(255, 255, 255), RGB(255, 255, 255), + RGB(255, 255, 255), RGB(255, 255, 255), + RGB(255, 255, 255), RGB(255, 255, 255), + RGB(255, 255, 255), RGB(255, 255, 255), + RGB(255, 255, 255), RGB(255, 255, 255), + RGB(255, 255, 255), RGB(255, 255, 255), + RGB(255, 255, 255), RGB(255, 255, 255), + RGB(255, 255, 255), RGB(255, 255, 255), + }; + + return rgbCustomColors; + } + + static UINT _GetSetRGBMessage() + { + static UINT uSetRGBMessage = 0; + if(uSetRGBMessage == 0) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CColorDialogImpl::_GetSetRGBMessage.\n")); + ATLASSERT(FALSE); + return 0; + } + + if(uSetRGBMessage == 0) + uSetRGBMessage = ::RegisterWindowMessage(SETRGBSTRING); + + lock.Unlock(); + } + ATLASSERT(uSetRGBMessage != 0); + return uSetRGBMessage; + } + + static UINT _GetColorOKMessage() + { + static UINT uColorOKMessage = 0; + if(uColorOKMessage == 0) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CColorDialogImpl::_GetColorOKMessage.\n")); + ATLASSERT(FALSE); + return 0; + } + + if(uColorOKMessage == 0) + uColorOKMessage = ::RegisterWindowMessage(COLOROKSTRING); + + lock.Unlock(); + } + ATLASSERT(uColorOKMessage != 0); + return uColorOKMessage; + } + +// Message map and handlers + BEGIN_MSG_MAP(CColorDialogImpl) + MESSAGE_HANDLER(_GetColorOKMessage(), _OnColorOK) + END_MSG_MAP() + + LRESULT _OnColorOK(UINT, WPARAM, LPARAM, BOOL&) + { + T* pT = static_cast(this); + return pT->OnColorOK(); + } + +// Overrideable + BOOL OnColorOK() // validate color + { + return FALSE; + } +}; + +class CColorDialog : public CColorDialogImpl +{ +public: + CColorDialog(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL) + : CColorDialogImpl(clrInit, dwFlags, hWndParent) + { } + + // override base class map and references to handlers + DECLARE_EMPTY_MSG_MAP() +}; + +#endif // !defined(_WIN32_WCE) || ((_WIN32_WCE > 420) && !(defined(WIN32_PLATFORM_WFSP) && (_WIN32_WCE > 0x0500))) + + +/////////////////////////////////////////////////////////////////////////////// +// CPrintDialogImpl - used for Print... and PrintSetup... + +#ifndef _WIN32_WCE + +// global helper +static HDC _AtlCreateDC(HGLOBAL hDevNames, HGLOBAL hDevMode) +{ + if(hDevNames == NULL) + return NULL; + + LPDEVNAMES lpDevNames = (LPDEVNAMES)::GlobalLock(hDevNames); + LPDEVMODE lpDevMode = (hDevMode != NULL) ? (LPDEVMODE)::GlobalLock(hDevMode) : NULL; + + if(lpDevNames == NULL) + return NULL; + + HDC hDC = ::CreateDC((LPCTSTR)lpDevNames + lpDevNames->wDriverOffset, + (LPCTSTR)lpDevNames + lpDevNames->wDeviceOffset, + (LPCTSTR)lpDevNames + lpDevNames->wOutputOffset, + lpDevMode); + + ::GlobalUnlock(hDevNames); + if(hDevMode != NULL) + ::GlobalUnlock(hDevMode); + return hDC; +} + +template +class ATL_NO_VTABLE CPrintDialogImpl : public CCommonDialogImplBase +{ +public: + // print dialog parameter block (note this is a reference) + PRINTDLG& m_pd; + +// Constructors + CPrintDialogImpl(BOOL bPrintSetupOnly = FALSE, // TRUE for Print Setup, FALSE for Print Dialog + DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION, + HWND hWndParent = NULL) + : m_pd(m_pdActual) + { + memset(&m_pdActual, 0, sizeof(m_pdActual)); + + m_pd.lStructSize = sizeof(m_pdActual); + m_pd.hwndOwner = hWndParent; + m_pd.Flags = (dwFlags | PD_ENABLEPRINTHOOK | PD_ENABLESETUPHOOK); + m_pd.lpfnPrintHook = (LPPRINTHOOKPROC)T::HookProc; + m_pd.lpfnSetupHook = (LPSETUPHOOKPROC)T::HookProc; + + if(bPrintSetupOnly) + m_pd.Flags |= PD_PRINTSETUP; + else + m_pd.Flags |= PD_RETURNDC; + + m_pd.Flags &= ~PD_RETURNIC; // do not support information context + } + +// Operations + INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) + { + ATLASSERT((m_pd.Flags & PD_ENABLEPRINTHOOK) != 0); + ATLASSERT((m_pd.Flags & PD_ENABLESETUPHOOK) != 0); + ATLASSERT(m_pd.lpfnPrintHook != NULL); // can still be a user hook + ATLASSERT(m_pd.lpfnSetupHook != NULL); // can still be a user hook + ATLASSERT((m_pd.Flags & PD_RETURNDEFAULT) == 0); // use GetDefaults for this + + if(m_pd.hwndOwner == NULL) // set only if not specified before + m_pd.hwndOwner = hWndParent; + + ATLASSERT(m_hWnd == NULL); + ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this); + + BOOL bRet = ::PrintDlg(&m_pd); + + m_hWnd = NULL; + + return bRet ? IDOK : IDCANCEL; + } + + // GetDefaults will not display a dialog but will get device defaults + BOOL GetDefaults() + { + m_pd.Flags |= PD_RETURNDEFAULT; + ATLASSERT(m_pd.hDevMode == NULL); // must be NULL + ATLASSERT(m_pd.hDevNames == NULL); // must be NULL + + return ::PrintDlg(&m_pd); + } + + // Helpers for parsing information after successful return num. copies requested + int GetCopies() const + { + if((m_pd.Flags & PD_USEDEVMODECOPIES) != 0) + { + LPDEVMODE lpDevMode = GetDevMode(); + return (lpDevMode != NULL) ? lpDevMode->dmCopies : -1; + } + + return m_pd.nCopies; + } + + BOOL PrintCollate() const // TRUE if collate checked + { + return ((m_pd.Flags & PD_COLLATE) != 0) ? TRUE : FALSE; + } + + BOOL PrintSelection() const // TRUE if printing selection + { + return ((m_pd.Flags & PD_SELECTION) != 0) ? TRUE : FALSE; + } + + BOOL PrintAll() const // TRUE if printing all pages + { + return (!PrintRange() && !PrintSelection()) ? TRUE : FALSE; + } + + BOOL PrintRange() const // TRUE if printing page range + { + return ((m_pd.Flags & PD_PAGENUMS) != 0) ? TRUE : FALSE; + } + + BOOL PrintToFile() const // TRUE if printing to a file + { + return ((m_pd.Flags & PD_PRINTTOFILE) != 0) ? TRUE : FALSE; + } + + int GetFromPage() const // starting page if valid + { + return PrintRange() ? m_pd.nFromPage : -1; + } + + int GetToPage() const // ending page if valid + { + return PrintRange() ? m_pd.nToPage : -1; + } + + LPDEVMODE GetDevMode() const // return DEVMODE + { + if(m_pd.hDevMode == NULL) + return NULL; + + return (LPDEVMODE)::GlobalLock(m_pd.hDevMode); + } + + LPCTSTR GetDriverName() const // return driver name + { + if(m_pd.hDevNames == NULL) + return NULL; + + LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames); + if(lpDev == NULL) + return NULL; + + return (LPCTSTR)lpDev + lpDev->wDriverOffset; + } + + LPCTSTR GetDeviceName() const // return device name + { + if(m_pd.hDevNames == NULL) + return NULL; + + LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames); + if(lpDev == NULL) + return NULL; + + return (LPCTSTR)lpDev + lpDev->wDeviceOffset; + } + + LPCTSTR GetPortName() const // return output port name + { + if(m_pd.hDevNames == NULL) + return NULL; + + LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames); + if(lpDev == NULL) + return NULL; + + return (LPCTSTR)lpDev + lpDev->wOutputOffset; + } + + HDC GetPrinterDC() const // return HDC (caller must delete) + { + ATLASSERT((m_pd.Flags & PD_RETURNDC) != 0); + return m_pd.hDC; + } + + // This helper creates a DC based on the DEVNAMES and DEVMODE structures. + // This DC is returned, but also stored in m_pd.hDC as though it had been + // returned by CommDlg. It is assumed that any previously obtained DC + // has been/will be deleted by the user. This may be + // used without ever invoking the print/print setup dialogs. + HDC CreatePrinterDC() + { + m_pd.hDC = _AtlCreateDC(m_pd.hDevNames, m_pd.hDevMode); + return m_pd.hDC; + } + +// Implementation + PRINTDLG m_pdActual; // the Print/Print Setup need to share this + + // The following handle the case of print setup... from the print dialog + CPrintDialogImpl(PRINTDLG& pdInit) : m_pd(pdInit) + { } + + BEGIN_MSG_MAP(CPrintDialogImpl) +#ifdef psh1 + COMMAND_ID_HANDLER(psh1, OnPrintSetup) // print setup button when print is displayed +#else // !psh1 + COMMAND_ID_HANDLER(0x0400, OnPrintSetup) // value from dlgs.h +#endif // !psh1 + END_MSG_MAP() + + LRESULT OnPrintSetup(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& /*bHandled*/) + { + T dlgSetup(m_pd); + ModuleHelper::AddCreateWndData(&dlgSetup.m_thunk.cd, (CCommonDialogImplBase*)&dlgSetup); + return DefWindowProc(WM_COMMAND, MAKEWPARAM(wID, wNotifyCode), (LPARAM)hWndCtl); + } +}; + +class CPrintDialog : public CPrintDialogImpl +{ +public: + CPrintDialog(BOOL bPrintSetupOnly = FALSE, + DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION, + HWND hWndParent = NULL) + : CPrintDialogImpl(bPrintSetupOnly, dwFlags, hWndParent) + { } + + CPrintDialog(PRINTDLG& pdInit) : CPrintDialogImpl(pdInit) + { } +}; + +#endif // _WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CPrintDialogExImpl - new print dialog for Windows 2000 + +#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) + +}; // namespace WTL + +#include + +extern "C" const __declspec(selectany) IID IID_IPrintDialogCallback = {0x5852a2c3, 0x6530, 0x11d1, {0xb6, 0xa3, 0x0, 0x0, 0xf8, 0x75, 0x7b, 0xf9}}; +extern "C" const __declspec(selectany) IID IID_IPrintDialogServices = {0x509aaeda, 0x5639, 0x11d1, {0xb6, 0xa1, 0x0, 0x0, 0xf8, 0x75, 0x7b, 0xf9}}; + +namespace WTL +{ + +template +class ATL_NO_VTABLE CPrintDialogExImpl : + public ATL::CWindow, + public ATL::CMessageMap, + public IPrintDialogCallback, + public ATL::IObjectWithSiteImpl< T > +{ +public: + PRINTDLGEX m_pdex; + +// Constructor + CPrintDialogExImpl(DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE, + HWND hWndParent = NULL) + { + memset(&m_pdex, 0, sizeof(m_pdex)); + + m_pdex.lStructSize = sizeof(PRINTDLGEX); + m_pdex.hwndOwner = hWndParent; + m_pdex.Flags = dwFlags; + m_pdex.nStartPage = START_PAGE_GENERAL; + // callback object will be set in DoModal + + m_pdex.Flags &= ~PD_RETURNIC; // do not support information context + } + +// Operations + HRESULT DoModal(HWND hWndParent = ::GetActiveWindow()) + { + ATLASSERT(m_hWnd == NULL); + ATLASSERT((m_pdex.Flags & PD_RETURNDEFAULT) == 0); // use GetDefaults for this + + if(m_pdex.hwndOwner == NULL) // set only if not specified before + m_pdex.hwndOwner = hWndParent; + + T* pT = static_cast(this); + m_pdex.lpCallback = (IUnknown*)(IPrintDialogCallback*)pT; + + HRESULT hResult = ::PrintDlgEx(&m_pdex); + + m_hWnd = NULL; + + return hResult; + } + + BOOL EndDialog(INT_PTR /*nRetCode*/ = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + SendMessage(WM_COMMAND, MAKEWPARAM(IDABORT, 0)); + return TRUE; + } + + // GetDefaults will not display a dialog but will get device defaults + HRESULT GetDefaults() + { + m_pdex.Flags |= PD_RETURNDEFAULT; + ATLASSERT(m_pdex.hDevMode == NULL); // must be NULL + ATLASSERT(m_pdex.hDevNames == NULL); // must be NULL + + return ::PrintDlgEx(&m_pdex); + } + + // Helpers for parsing information after successful return num. copies requested + int GetCopies() const + { + if((m_pdex.Flags & PD_USEDEVMODECOPIES) != 0) + { + LPDEVMODE lpDevMode = GetDevMode(); + return (lpDevMode != NULL) ? lpDevMode->dmCopies : -1; + } + + return m_pdex.nCopies; + } + + BOOL PrintCollate() const // TRUE if collate checked + { + return ((m_pdex.Flags & PD_COLLATE) != 0) ? TRUE : FALSE; + } + + BOOL PrintSelection() const // TRUE if printing selection + { + return ((m_pdex.Flags & PD_SELECTION) != 0) ? TRUE : FALSE; + } + + BOOL PrintAll() const // TRUE if printing all pages + { + return (!PrintRange() && !PrintSelection()) ? TRUE : FALSE; + } + + BOOL PrintRange() const // TRUE if printing page range + { + return ((m_pdex.Flags & PD_PAGENUMS) != 0) ? TRUE : FALSE; + } + + BOOL PrintToFile() const // TRUE if printing to a file + { + return ((m_pdex.Flags & PD_PRINTTOFILE) != 0) ? TRUE : FALSE; + } + + LPDEVMODE GetDevMode() const // return DEVMODE + { + if(m_pdex.hDevMode == NULL) + return NULL; + + return (LPDEVMODE)::GlobalLock(m_pdex.hDevMode); + } + + LPCTSTR GetDriverName() const // return driver name + { + if(m_pdex.hDevNames == NULL) + return NULL; + + LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames); + if(lpDev == NULL) + return NULL; + + return (LPCTSTR)lpDev + lpDev->wDriverOffset; + } + + LPCTSTR GetDeviceName() const // return device name + { + if(m_pdex.hDevNames == NULL) + return NULL; + + LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames); + if(lpDev == NULL) + return NULL; + + return (LPCTSTR)lpDev + lpDev->wDeviceOffset; + } + + LPCTSTR GetPortName() const // return output port name + { + if(m_pdex.hDevNames == NULL) + return NULL; + + LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames); + if(lpDev == NULL) + return NULL; + + return (LPCTSTR)lpDev + lpDev->wOutputOffset; + } + + HDC GetPrinterDC() const // return HDC (caller must delete) + { + ATLASSERT((m_pdex.Flags & PD_RETURNDC) != 0); + return m_pdex.hDC; + } + + // This helper creates a DC based on the DEVNAMES and DEVMODE structures. + // This DC is returned, but also stored in m_pdex.hDC as though it had been + // returned by CommDlg. It is assumed that any previously obtained DC + // has been/will be deleted by the user. This may be + // used without ever invoking the print/print setup dialogs. + HDC CreatePrinterDC() + { + m_pdex.hDC = _AtlCreateDC(m_pdex.hDevNames, m_pdex.hDevMode); + return m_pdex.hDC; + } + +// Implementation - interfaces + +// IUnknown + STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) + { + if(ppvObject == NULL) + return E_POINTER; + + T* pT = static_cast(this); + if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IPrintDialogCallback)) + { + *ppvObject = (IPrintDialogCallback*)pT; + // AddRef() not needed + return S_OK; + } + else if(IsEqualGUID(riid, IID_IObjectWithSite)) + { + *ppvObject = (IObjectWithSite*)pT; + // AddRef() not needed + return S_OK; + } + + return E_NOINTERFACE; + } + + virtual ULONG STDMETHODCALLTYPE AddRef() + { + return 1; + } + + virtual ULONG STDMETHODCALLTYPE Release() + { + return 1; + } + +// IPrintDialogCallback + STDMETHOD(InitDone)() + { + return S_FALSE; + } + + STDMETHOD(SelectionChange)() + { + return S_FALSE; + } + + STDMETHOD(HandleMessage)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plResult) + { + // set up m_hWnd the first time + if(m_hWnd == NULL) + Attach(hWnd); + + // call message map + HRESULT hRet = ProcessWindowMessage(hWnd, uMsg, wParam, lParam, *plResult, 0) ? S_OK : S_FALSE; + if(hRet == S_OK && uMsg == WM_NOTIFY) // return in DWLP_MSGRESULT + ::SetWindowLongPtr(GetParent(), DWLP_MSGRESULT, (LONG_PTR)*plResult); + + if(uMsg == WM_INITDIALOG && hRet == S_OK && (BOOL)*plResult != FALSE) + hRet = S_FALSE; + + return hRet; + } +}; + +class CPrintDialogEx : public CPrintDialogExImpl +{ +public: + CPrintDialogEx( + DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE, + HWND hWndParent = NULL) + : CPrintDialogExImpl(dwFlags, hWndParent) + { } + + DECLARE_EMPTY_MSG_MAP() +}; + +#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) + + +/////////////////////////////////////////////////////////////////////////////// +// CPageSetupDialogImpl - Page Setup dialog + +#ifndef _WIN32_WCE + +template +class ATL_NO_VTABLE CPageSetupDialogImpl : public CCommonDialogImplBase +{ +public: + PAGESETUPDLG m_psd; + ATL::CWndProcThunk m_thunkPaint; + +// Constructors + CPageSetupDialogImpl(DWORD dwFlags = PSD_MARGINS | PSD_INWININIINTLMEASURE, HWND hWndParent = NULL) + { + memset(&m_psd, 0, sizeof(m_psd)); + + m_psd.lStructSize = sizeof(m_psd); + m_psd.hwndOwner = hWndParent; + m_psd.Flags = (dwFlags | PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGEPAINTHOOK); + m_psd.lpfnPageSetupHook = (LPPAGESETUPHOOK)T::HookProc; + m_thunkPaint.Init((WNDPROC)T::PaintHookProc, this); +#if (_ATL_VER >= 0x0700) + m_psd.lpfnPagePaintHook = (LPPAGEPAINTHOOK)m_thunkPaint.GetWNDPROC(); +#else + m_psd.lpfnPagePaintHook = (LPPAGEPAINTHOOK)&(m_thunkPaint.thunk); +#endif + } + + DECLARE_EMPTY_MSG_MAP() + +// Attributes + LPDEVMODE GetDevMode() const // return DEVMODE + { + if(m_psd.hDevMode == NULL) + return NULL; + + return (LPDEVMODE)::GlobalLock(m_psd.hDevMode); + } + + LPCTSTR GetDriverName() const // return driver name + { + if(m_psd.hDevNames == NULL) + return NULL; + + LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames); + return (LPCTSTR)lpDev + lpDev->wDriverOffset; + } + + LPCTSTR GetDeviceName() const // return device name + { + if(m_psd.hDevNames == NULL) + return NULL; + + LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames); + return (LPCTSTR)lpDev + lpDev->wDeviceOffset; + } + + LPCTSTR GetPortName() const // return output port name + { + if(m_psd.hDevNames == NULL) + return NULL; + + LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames); + return (LPCTSTR)lpDev + lpDev->wOutputOffset; + } + + HDC CreatePrinterDC() + { + return _AtlCreateDC(m_psd.hDevNames, m_psd.hDevMode); + } + + SIZE GetPaperSize() const + { + SIZE size; + size.cx = m_psd.ptPaperSize.x; + size.cy = m_psd.ptPaperSize.y; + return size; + } + + void GetMargins(LPRECT lpRectMargins, LPRECT lpRectMinMargins) const + { + if(lpRectMargins != NULL) + *lpRectMargins = m_psd.rtMargin; + if(lpRectMinMargins != NULL) + *lpRectMinMargins = m_psd.rtMinMargin; + } + +// Operations + INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) + { + ATLASSERT((m_psd.Flags & PSD_ENABLEPAGESETUPHOOK) != 0); + ATLASSERT((m_psd.Flags & PSD_ENABLEPAGEPAINTHOOK) != 0); + ATLASSERT(m_psd.lpfnPageSetupHook != NULL); // can still be a user hook + ATLASSERT(m_psd.lpfnPagePaintHook != NULL); // can still be a user hook + + if(m_psd.hwndOwner == NULL) // set only if not specified before + m_psd.hwndOwner = hWndParent; + + ATLASSERT(m_hWnd == NULL); + ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this); + + BOOL bRet = ::PageSetupDlg(&m_psd); + + m_hWnd = NULL; + + return bRet ? IDOK : IDCANCEL; + } + +// Implementation + static UINT_PTR CALLBACK PaintHookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + T* pT = (T*)hWnd; + UINT_PTR uRet = 0; + switch(uMsg) + { + case WM_PSD_PAGESETUPDLG: + uRet = pT->PreDrawPage(LOWORD(wParam), HIWORD(wParam), (LPPAGESETUPDLG)lParam); + break; + case WM_PSD_FULLPAGERECT: + case WM_PSD_MINMARGINRECT: + case WM_PSD_MARGINRECT: + case WM_PSD_GREEKTEXTRECT: + case WM_PSD_ENVSTAMPRECT: + case WM_PSD_YAFULLPAGERECT: + uRet = pT->OnDrawPage(uMsg, (HDC)wParam, (LPRECT)lParam); + break; + default: + ATLTRACE2(atlTraceUI, 0, _T("CPageSetupDialogImpl::PaintHookProc - unknown message received\n")); + break; + } + return uRet; + } + +// Overridables + UINT_PTR PreDrawPage(WORD /*wPaper*/, WORD /*wFlags*/, LPPAGESETUPDLG /*pPSD*/) + { + // return 1 to prevent any more drawing + return 0; + } + + UINT_PTR OnDrawPage(UINT /*uMsg*/, HDC /*hDC*/, LPRECT /*lpRect*/) + { + return 0; // do the default + } +}; + +class CPageSetupDialog : public CPageSetupDialogImpl +{ +public: + CPageSetupDialog(DWORD dwFlags = PSD_MARGINS | PSD_INWININIINTLMEASURE, HWND hWndParent = NULL) + : CPageSetupDialogImpl(dwFlags, hWndParent) + { } + + // override PaintHookProc and references to handlers + static UINT_PTR CALLBACK PaintHookProc(HWND, UINT, WPARAM, LPARAM) + { + return 0; + } +}; + +#endif // _WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CFindReplaceDialogImpl - Find/FindReplace modeless dialogs + +#ifndef _WIN32_WCE + +template +class ATL_NO_VTABLE CFindReplaceDialogImpl : public CCommonDialogImplBase +{ +public: + enum { _cchFindReplaceBuffer = 128 }; + + FINDREPLACE m_fr; + TCHAR m_szFindWhat[_cchFindReplaceBuffer]; + TCHAR m_szReplaceWith[_cchFindReplaceBuffer]; + +// Constructors + CFindReplaceDialogImpl() + { + memset(&m_fr, 0, sizeof(m_fr)); + m_szFindWhat[0] = _T('\0'); + m_szReplaceWith[0] = _T('\0'); + + m_fr.lStructSize = sizeof(m_fr); + m_fr.Flags = FR_ENABLEHOOK; + m_fr.lpfnHook = (LPFRHOOKPROC)T::HookProc; + m_fr.lpstrFindWhat = (LPTSTR)m_szFindWhat; + m_fr.wFindWhatLen = _cchFindReplaceBuffer; + m_fr.lpstrReplaceWith = (LPTSTR)m_szReplaceWith; + m_fr.wReplaceWithLen = _cchFindReplaceBuffer; + } + + // Note: You must allocate the object on the heap. + // If you do not, you must override OnFinalMessage() + virtual void OnFinalMessage(HWND /*hWnd*/) + { + delete this; + } + + HWND Create(BOOL bFindDialogOnly, // TRUE for Find, FALSE for FindReplace + LPCTSTR lpszFindWhat, + LPCTSTR lpszReplaceWith = NULL, + DWORD dwFlags = FR_DOWN, + HWND hWndParent = NULL) + { + ATLASSERT((m_fr.Flags & FR_ENABLEHOOK) != 0); + ATLASSERT(m_fr.lpfnHook != NULL); + + m_fr.Flags |= dwFlags; + + if(hWndParent == NULL) + m_fr.hwndOwner = ::GetActiveWindow(); + else + m_fr.hwndOwner = hWndParent; + ATLASSERT(m_fr.hwndOwner != NULL); // must have an owner for modeless dialog + + if(lpszFindWhat != NULL) + SecureHelper::strncpy_x(m_szFindWhat, _countof(m_szFindWhat), lpszFindWhat, _TRUNCATE); + + if(lpszReplaceWith != NULL) + SecureHelper::strncpy_x(m_szReplaceWith, _countof(m_szReplaceWith), lpszReplaceWith, _TRUNCATE); + + ATLASSERT(m_hWnd == NULL); + ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this); + + HWND hWnd = NULL; + if(bFindDialogOnly) + hWnd = ::FindText(&m_fr); + else + hWnd = ::ReplaceText(&m_fr); + + ATLASSERT(m_hWnd == hWnd); + return hWnd; + } + + static const UINT GetFindReplaceMsg() + { + static const UINT nMsgFindReplace = ::RegisterWindowMessage(FINDMSGSTRING); + return nMsgFindReplace; + } + // call while handling FINDMSGSTRING registered message + // to retreive the object + static T* PASCAL GetNotifier(LPARAM lParam) + { + ATLASSERT(lParam != NULL); + T* pDlg = (T*)(lParam - offsetof(T, m_fr)); + return pDlg; + } + +// Operations + // Helpers for parsing information after successful return + LPCTSTR GetFindString() const // get find string + { + return (LPCTSTR)m_fr.lpstrFindWhat; + } + + LPCTSTR GetReplaceString() const // get replacement string + { + return (LPCTSTR)m_fr.lpstrReplaceWith; + } + + BOOL SearchDown() const // TRUE if search down, FALSE is up + { + return ((m_fr.Flags & FR_DOWN) != 0) ? TRUE : FALSE; + } + + BOOL FindNext() const // TRUE if command is find next + { + return ((m_fr.Flags & FR_FINDNEXT) != 0) ? TRUE : FALSE; + } + + BOOL MatchCase() const // TRUE if matching case + { + return ((m_fr.Flags & FR_MATCHCASE) != 0) ? TRUE : FALSE; + } + + BOOL MatchWholeWord() const // TRUE if matching whole words only + { + return ((m_fr.Flags & FR_WHOLEWORD) != 0) ? TRUE : FALSE; + } + + BOOL ReplaceCurrent() const // TRUE if replacing current string + { + return ((m_fr. Flags & FR_REPLACE) != 0) ? TRUE : FALSE; + } + + BOOL ReplaceAll() const // TRUE if replacing all occurrences + { + return ((m_fr.Flags & FR_REPLACEALL) != 0) ? TRUE : FALSE; + } + + BOOL IsTerminating() const // TRUE if terminating dialog + { + return ((m_fr.Flags & FR_DIALOGTERM) != 0) ? TRUE : FALSE ; + } +}; + +class CFindReplaceDialog : public CFindReplaceDialogImpl +{ +public: + DECLARE_EMPTY_MSG_MAP() +}; + +#endif // !_WIN32_WCE + + +#if (_ATL_VER >= 0x800) +typedef ATL::_DialogSplitHelper::DLGTEMPLATEEX DLGTEMPLATEEX; +typedef ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX DLGITEMTEMPLATEEX; +#else // (_ATL_VER >= 0x800) +typedef ATL::_DialogSizeHelper::_ATL_DLGTEMPLATEEX DLGTEMPLATEEX; +#pragma pack(push, 4) +struct DLGITEMTEMPLATEEX +{ + DWORD helpID; + DWORD exStyle; + DWORD style; + short x; + short y; + short cx; + short cy; + WORD id; +}; +#pragma pack(pop) +#endif // (_ATL_VER >= 0x800) + + +/////////////////////////////////////////////////////////////////////////////// +// CMemDlgTemplate - in-memory dialog template - DLGTEMPLATE or DLGTEMPLATEEX + +class CMemDlgTemplate +{ +public: + enum StdCtrlType + { + CTRL_BUTTON = 0x0080, + CTRL_EDIT = 0x0081, + CTRL_STATIC = 0x0082, + CTRL_LISTBOX = 0x0083, + CTRL_SCROLLBAR = 0x0084, + CTRL_COMBOBOX = 0x0085 + }; + + CMemDlgTemplate() : m_pData(NULL), m_pPtr(NULL), m_cAllocated(0) + { } + + ~CMemDlgTemplate() + { + Reset(); + } + + bool IsValid() const + { + return (m_pData != NULL); + } + + bool IsTemplateEx() const + { + return (IsValid() && ((DLGTEMPLATEEX*)m_pData)->signature == 0xFFFF); + } + + LPDLGTEMPLATE GetTemplatePtr() + { + return reinterpret_cast(m_pData); + } + + DLGTEMPLATEEX* GetTemplateExPtr() + { + return reinterpret_cast(m_pData); + } + + void Reset() + { + if (IsValid()) + ATLVERIFY(::GlobalFree(m_pData) == NULL); + + m_pData = NULL; + m_pPtr = NULL; + m_cAllocated = 0; + } + + void Create(bool bDlgEx, LPCTSTR lpszCaption, short nX, short nY, short nWidth, short nHeight, DWORD dwStyle = 0, DWORD dwExStyle = 0, + LPCTSTR lpstrFontName = NULL, WORD wFontSize = 0, WORD wWeight = 0, BYTE bItalic = 0, BYTE bCharset = 0, DWORD dwHelpID = 0, + ATL::_U_STRINGorID ClassName = 0U, ATL::_U_STRINGorID Menu = 0U) + { + // Should have DS_SETFONT style to set the dialog font name and size + if (lpstrFontName != NULL) + { + dwStyle |= DS_SETFONT; + } + else + { + dwStyle &= ~DS_SETFONT; + } + + if (bDlgEx) + { + DLGTEMPLATEEX dlg = {1, 0xFFFF, dwHelpID, dwExStyle, dwStyle, 0, nX, nY, nWidth, nHeight}; + AddData(&dlg, sizeof(dlg)); + } + else + { + DLGTEMPLATE dlg = {dwStyle, dwExStyle, 0, nX, nY, nWidth, nHeight}; + AddData(&dlg, sizeof(dlg)); + } + +#ifndef _WIN32_WCE + if (Menu.m_lpstr == NULL) + { + WORD menuData = 0; + AddData(&menuData, sizeof(WORD)); + } + else if (IS_INTRESOURCE(Menu.m_lpstr)) + { + WORD menuData[] = {0xFFFF, (WORD)Menu.m_lpstr}; + AddData(menuData, sizeof(menuData)); + } + else + { + AddString(Menu.m_lpstr); + } +#else // _WIN32_WCE + // Windows CE doesn't support the addition of menus to a dialog box + ATLASSERT(Menu.m_lpstr == NULL); + Menu.m_lpstr; // avoid level 4 warning + WORD menuData = 0; + AddData(&menuData, sizeof(WORD)); +#endif // _WIN32_WCE + + if (ClassName.m_lpstr == NULL) + { + WORD classData = 0; + AddData(&classData, sizeof(WORD)); + } + else if (IS_INTRESOURCE(ClassName.m_lpstr)) + { + WORD classData[] = {0xFFFF, (WORD)ClassName.m_lpstr}; + AddData(classData, sizeof(classData)); + } + else + { + AddString(ClassName.m_lpstr); + } + + // Set dialog caption + AddString(lpszCaption); + + if (lpstrFontName != NULL) + { + AddData(&wFontSize, sizeof(wFontSize)); + + if (bDlgEx) + { + AddData(&wWeight, sizeof(wWeight)); + AddData(&bItalic, sizeof(bItalic)); + AddData(&bCharset, sizeof(bCharset)); + } + + AddString(lpstrFontName); + } + } + + void AddControl(ATL::_U_STRINGorID ClassName, WORD wId, short nX, short nY, short nWidth, short nHeight, DWORD dwStyle, DWORD dwExStyle, + ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0) + { + ATLASSERT(IsValid()); + + // DWORD align data + m_pPtr = (LPBYTE)(DWORD_PTR)((DWORD)(DWORD_PTR)(m_pPtr + 3) & (~3)); + + if (IsTemplateEx()) + { + DLGTEMPLATEEX* dlg = (DLGTEMPLATEEX*)m_pData; + dlg->cDlgItems++; + + DLGITEMTEMPLATEEX item = {dwHelpID, ATL::CControlWinTraits::GetWndExStyle(0) | dwExStyle, ATL::CControlWinTraits::GetWndStyle(0) | dwStyle, nX, nY, nWidth, nHeight, wId}; + AddData(&item, sizeof(item)); + } + else + { + LPDLGTEMPLATE dlg = (LPDLGTEMPLATE)m_pData; + dlg->cdit++; + + DLGITEMTEMPLATE item = {ATL::CControlWinTraits::GetWndStyle(0) | dwStyle, ATL::CControlWinTraits::GetWndExStyle(0) | dwExStyle, nX, nY, nWidth, nHeight, wId}; + AddData(&item, sizeof(item)); + } + + ATLASSERT(ClassName.m_lpstr != NULL); + if (IS_INTRESOURCE(ClassName.m_lpstr)) + { + WORD wData[] = {0xFFFF, (WORD)ClassName.m_lpstr}; + AddData(wData, sizeof(wData)); + } + else + { + AddString(ClassName.m_lpstr); + } + + if (Text.m_lpstr == NULL) + { + WORD classData = 0; + AddData(&classData, sizeof(WORD)); + } + else if (IS_INTRESOURCE(Text.m_lpstr)) + { + WORD wData[] = {0xFFFF, (WORD)Text.m_lpstr}; + AddData(wData, sizeof(wData)); + } + else + { + AddString(Text.m_lpstr); + } + + AddData(&nCreationData, sizeof(nCreationData)); + + if ((nCreationData != 0)) + { + ATLASSERT(pCreationData != NULL); + AddData(pCreationData, nCreationData * sizeof(WORD)); + } + } + + void AddStdControl(StdCtrlType CtrlType, WORD wId, short nX, short nY, short nWidth, short nHeight, + DWORD dwStyle, DWORD dwExStyle, ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0) + { + AddControl(CtrlType, wId, nX, nY, nWidth, nHeight, dwStyle, dwExStyle, Text, pCreationData, nCreationData, dwHelpID); + } + +protected: + void AddData(LPCVOID pData, size_t nData) + { + ATLASSERT(pData != NULL); + + const size_t ALLOCATION_INCREMENT = 1024; + + if (m_pData == NULL) + { + m_cAllocated = ((nData / ALLOCATION_INCREMENT) + 1) * ALLOCATION_INCREMENT; + m_pPtr = m_pData = static_cast(::GlobalAlloc(GPTR, m_cAllocated)); + ATLASSERT(m_pData != NULL); + } + else if (((m_pPtr - m_pData) + nData) > m_cAllocated) + { + size_t ptrPos = (m_pPtr - m_pData); + m_cAllocated += ((nData / ALLOCATION_INCREMENT) + 1) * ALLOCATION_INCREMENT; + m_pData = static_cast(::GlobalReAlloc(m_pData, m_cAllocated, 0)); + ATLASSERT(m_pData != NULL); + m_pPtr = m_pData + ptrPos; + } + + SecureHelper::memcpy_x(m_pPtr, m_cAllocated - (m_pPtr - m_pData), pData, nData); + + m_pPtr += nData; + } + + void AddString(LPCTSTR lpszStr) + { + if (lpszStr == NULL) + { + WCHAR szEmpty = 0; + AddData(&szEmpty, sizeof(szEmpty)); + } + else + { + USES_CONVERSION; + LPCWSTR lpstr = T2CW(lpszStr); + int nSize = lstrlenW(lpstr) + 1; + AddData(lpstr, nSize * sizeof(WCHAR)); + } + } + + LPBYTE m_pData; + LPBYTE m_pPtr; + SIZE_T m_cAllocated; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Dialog and control macros for indirect dialogs + +// for DLGTEMPLATE +#define BEGIN_DIALOG(x, y, width, height) \ + void DoInitTemplate() \ + { \ + bool bExTemplate = false; \ + short nX = x, nY = y, nWidth = width, nHeight = height; \ + LPCTSTR szCaption = NULL; \ + DWORD dwStyle = WS_POPUP | WS_BORDER | WS_SYSMENU; \ + DWORD dwExStyle = 0; \ + LPCTSTR szFontName = NULL; \ + WORD wFontSize = 0; \ + WORD wWeight = 0; \ + BYTE bItalic = 0; \ + BYTE bCharset = 0; \ + DWORD dwHelpID = 0; \ + ATL::_U_STRINGorID Menu = 0U; \ + ATL::_U_STRINGorID ClassName = 0U; + +// for DLGTEMPLATEEX +#define BEGIN_DIALOG_EX(x, y, width, height, helpID) \ + void DoInitTemplate() \ + { \ + bool bExTemplate = true; \ + short nX = x, nY = y, nWidth = width, nHeight = height; \ + LPCTSTR szCaption = NULL; \ + DWORD dwStyle = WS_POPUP | WS_BORDER | WS_SYSMENU; \ + DWORD dwExStyle = 0; \ + LPCTSTR szFontName = NULL; \ + WORD wFontSize = 0; \ + WORD wWeight = 0; \ + BYTE bItalic = 0; \ + BYTE bCharset = 0; \ + DWORD dwHelpID = helpID; \ + ATL::_U_STRINGorID Menu = 0U; \ + ATL::_U_STRINGorID ClassName = 0U; + +#define END_DIALOG() \ + m_Template.Create(bExTemplate, szCaption, nX, nY, nWidth, nHeight, dwStyle, dwExStyle, szFontName, wFontSize, wWeight, bItalic, bCharset, dwHelpID, ClassName, Menu); \ + }; + +#define DIALOG_CAPTION(caption) \ + szCaption = caption; +#define DIALOG_STYLE(style) \ + dwStyle = style; +#define DIALOG_EXSTYLE(exStyle) \ + dwExStyle = exStyle; +#define DIALOG_FONT(pointSize, typeFace) \ + wFontSize = pointSize; \ + szFontName = typeFace; +#define DIALOG_FONT_EX(pointsize, typeface, weight, italic, charset) \ + ATLASSERT(bExTemplate); \ + wFontSize = pointsize; \ + szFontName = typeface; \ + wWeight = weight; \ + bItalic = italic; \ + bCharset = charset; +#define DIALOG_MENU(menuName) \ + Menu = menuName; +#define DIALOG_CLASS(className) \ + ClassName = className; + +#define BEGIN_CONTROLS_MAP() \ + void DoInitControls() \ + { + +#define END_CONTROLS_MAP() \ + }; + + +#define CONTROL_LTEXT(text, id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_LEFT | WS_GROUP, exStyle, text, NULL, 0); +#define CONTROL_CTEXT(text, id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_CENTER | WS_GROUP, exStyle, text, NULL, 0); +#define CONTROL_RTEXT(text, id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_RIGHT | WS_GROUP, exStyle, text, NULL, 0); +#define CONTROL_PUSHBUTTON(text, id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_PUSHBUTTON | WS_TABSTOP, exStyle, text, NULL, 0); +#define CONTROL_DEFPUSHBUTTON(text, id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_DEFPUSHBUTTON | WS_TABSTOP, exStyle, text, NULL, 0); +#ifndef _WIN32_WCE +#define CONTROL_PUSHBOX(text, id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_PUSHBOX | WS_TABSTOP, exStyle, text, NULL, 0); +#endif // !_WIN32_WCE +#define CONTROL_STATE3(text, id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_3STATE | WS_TABSTOP, exStyle, text, NULL, 0); +#define CONTROL_AUTO3STATE(text, id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTO3STATE | WS_TABSTOP, exStyle, text, NULL, 0); +#define CONTROL_CHECKBOX(text, id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_CHECKBOX | WS_TABSTOP, exStyle, text, NULL, 0); +#define CONTROL_AUTOCHECKBOX(text, id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTOCHECKBOX | WS_TABSTOP, exStyle, text, NULL, 0); +#define CONTROL_RADIOBUTTON(text, id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_RADIOBUTTON | WS_TABSTOP, exStyle, text, NULL, 0); +#define CONTROL_AUTORADIOBUTTON(text, id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTORADIOBUTTON | WS_TABSTOP, exStyle, text, NULL, 0); +#define CONTROL_COMBOBOX(id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_COMBOBOX, (WORD)id, x, y, width, height, style | CBS_DROPDOWN | WS_TABSTOP, exStyle, (LPCTSTR)NULL, NULL, 0); +#define CONTROL_EDITTEXT(id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_EDIT, (WORD)id, x, y, width, height, style | ES_LEFT | WS_BORDER | WS_TABSTOP, exStyle, (LPCTSTR)NULL, NULL, 0); +#define CONTROL_GROUPBOX(text, id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_GROUPBOX, exStyle, text, NULL, 0); +#define CONTROL_LISTBOX(id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_LISTBOX, (WORD)id, x, y, width, height, style | LBS_NOTIFY | WS_BORDER, exStyle, (LPCTSTR)NULL, NULL, 0); +#define CONTROL_SCROLLBAR(id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_SCROLLBAR, (WORD)id, x, y, width, height, style | SBS_HORZ, exStyle, (LPCTSTR)NULL, NULL, 0); +#define CONTROL_ICON(text, id, x, y, width, height, style, exStyle) \ + m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_ICON, exStyle, text, NULL, 0); +#define CONTROL_CONTROL(text, id, className, style, x, y, width, height, exStyle) \ + m_Template.AddControl(className, (WORD)id, x, y, width, height, style, exStyle, text, NULL, 0); + + +/////////////////////////////////////////////////////////////////////////////// +// CIndirectDialogImpl - dialogs with template in memory + +template > +class ATL_NO_VTABLE CIndirectDialogImpl : public TBase +{ +public: + enum { IDD = 0 }; // no dialog template resource + + TDlgTemplate m_Template; + + void CreateTemplate() + { + T* pT = static_cast(this); + pT->DoInitTemplate(); + pT->DoInitControls(); + } + + INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_hWnd == NULL); + + if (!m_Template.IsValid()) + CreateTemplate(); + +#if (_ATL_VER >= 0x0800) + // Allocate the thunk structure here, where we can fail gracefully. + BOOL result = m_thunk.Init(NULL, NULL); + if (result == FALSE) + { + SetLastError(ERROR_OUTOFMEMORY); + return -1; + } +#endif // (_ATL_VER >= 0x0800) + + ModuleHelper::AddCreateWndData(&m_thunk.cd, pT); + +#ifdef _DEBUG + m_bModal = true; +#endif // _DEBUG + + return ::DialogBoxIndirectParam(ModuleHelper::GetResourceInstance(), m_Template.GetTemplatePtr(), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam); + } + + HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL) + { + T* pT = static_cast(this); + ATLASSERT(pT->m_hWnd == NULL); + + if (!m_Template.IsValid()) + CreateTemplate(); + +#if (_ATL_VER >= 0x0800) + // Allocate the thunk structure here, where we can fail gracefully. + BOOL result = m_thunk.Init(NULL, NULL); + if (result == FALSE) + { + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } +#endif // (_ATL_VER >= 0x0800) + + ModuleHelper::AddCreateWndData(&m_thunk.cd, pT); + +#ifdef _DEBUG + m_bModal = false; +#endif // _DEBUG + + HWND hWnd = ::CreateDialogIndirectParam(ModuleHelper::GetResourceInstance(), (LPCDLGTEMPLATE)m_Template.GetTemplatePtr(), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam); + ATLASSERT(m_hWnd == hWnd); + + return hWnd; + } + + // for CComControl + HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL) + { + return Create(hWndParent, dwInitParam); + } + + void DoInitTemplate() + { + ATLASSERT(FALSE); // MUST be defined in derived class + } + + void DoInitControls() + { + ATLASSERT(FALSE); // MUST be defined in derived class + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// CPropertySheetWindow - client side for a property sheet + +class CPropertySheetWindow : public ATL::CWindow +{ +public: +// Constructors + CPropertySheetWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd) + { } + + CPropertySheetWindow& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + +// Attributes + int GetPageCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + HWND hWndTabCtrl = GetTabControl(); + ATLASSERT(hWndTabCtrl != NULL); + return (int)::SendMessage(hWndTabCtrl, TCM_GETITEMCOUNT, 0, 0L); + } + + HWND GetActivePage() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HWND)::SendMessage(m_hWnd, PSM_GETCURRENTPAGEHWND, 0, 0L); + } + + int GetActiveIndex() const + { + ATLASSERT(::IsWindow(m_hWnd)); + HWND hWndTabCtrl = GetTabControl(); + ATLASSERT(hWndTabCtrl != NULL); + return (int)::SendMessage(hWndTabCtrl, TCM_GETCURSEL, 0, 0L); + } + + BOOL SetActivePage(int nPageIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, nPageIndex, 0L); + } + + BOOL SetActivePage(HPROPSHEETPAGE hPage) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(hPage != NULL); + return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, 0, (LPARAM)hPage); + } + + BOOL SetActivePageByID(int nPageID) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSELID, 0, nPageID); + } + + void SetTitle(LPCTSTR lpszText, UINT nStyle = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid + ATLASSERT(lpszText != NULL); + ::SendMessage(m_hWnd, PSM_SETTITLE, nStyle, (LPARAM)lpszText); + } + + HWND GetTabControl() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HWND)::SendMessage(m_hWnd, PSM_GETTABCONTROL, 0, 0L); + } + + void SetFinishText(LPCTSTR lpszText) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, PSM_SETFINISHTEXT, 0, (LPARAM)lpszText); + } + + void SetWizardButtons(DWORD dwFlags) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::PostMessage(m_hWnd, PSM_SETWIZBUTTONS, 0, dwFlags); + } + +// Operations + BOOL AddPage(HPROPSHEETPAGE hPage) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(hPage != NULL); + return (BOOL)::SendMessage(m_hWnd, PSM_ADDPAGE, 0, (LPARAM)hPage); + } + + BOOL AddPage(LPCPROPSHEETPAGE pPage) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pPage != NULL); + HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage); + if(hPage == NULL) + return FALSE; + return (BOOL)::SendMessage(m_hWnd, PSM_ADDPAGE, 0, (LPARAM)hPage); + } + +#ifndef _WIN32_WCE + BOOL InsertPage(int nNewPageIndex, HPROPSHEETPAGE hPage) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(hPage != NULL); + return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, nNewPageIndex, (LPARAM)hPage); + } + + BOOL InsertPage(int nNewPageIndex, LPCPROPSHEETPAGE pPage) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pPage != NULL); + HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage); + if(hPage == NULL) + return FALSE; + return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, nNewPageIndex, (LPARAM)hPage); + } + + BOOL InsertPage(HPROPSHEETPAGE hPageInsertAfter, HPROPSHEETPAGE hPage) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(hPage != NULL); + return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, (WPARAM)hPageInsertAfter, (LPARAM)hPage); + } + + BOOL InsertPage(HPROPSHEETPAGE hPageInsertAfter, LPCPROPSHEETPAGE pPage) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pPage != NULL); + HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage); + if(hPage == NULL) + return FALSE; + return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, (WPARAM)hPageInsertAfter, (LPARAM)hPage); + } +#endif // !_WIN32_WCE + + void RemovePage(int nPageIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, PSM_REMOVEPAGE, nPageIndex, 0L); + } + + void RemovePage(HPROPSHEETPAGE hPage) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(hPage != NULL); + ::SendMessage(m_hWnd, PSM_REMOVEPAGE, 0, (LPARAM)hPage); + } + + BOOL PressButton(int nButton) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, PSM_PRESSBUTTON, nButton, 0L); + } + + BOOL Apply() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, PSM_APPLY, 0, 0L); + } + + void CancelToClose() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, PSM_CANCELTOCLOSE, 0, 0L); + } + + void SetModified(HWND hWndPage, BOOL bChanged = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(::IsWindow(hWndPage)); + UINT uMsg = bChanged ? PSM_CHANGED : PSM_UNCHANGED; + ::SendMessage(m_hWnd, uMsg, (WPARAM)hWndPage, 0L); + } + + LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SendMessage(m_hWnd, PSM_QUERYSIBLINGS, wParam, lParam); + } + + void RebootSystem() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, PSM_REBOOTSYSTEM, 0, 0L); + } + + void RestartWindows() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, PSM_RESTARTWINDOWS, 0, 0L); + } + + BOOL IsDialogMessage(LPMSG lpMsg) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, PSM_ISDIALOGMESSAGE, 0, (LPARAM)lpMsg); + } + +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + int HwndToIndex(HWND hWnd) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PSM_HWNDTOINDEX, (WPARAM)hWnd, 0L); + } + + HWND IndexToHwnd(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HWND)::SendMessage(m_hWnd, PSM_INDEXTOHWND, nIndex, 0L); + } + + int PageToIndex(HPROPSHEETPAGE hPage) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PSM_PAGETOINDEX, 0, (LPARAM)hPage); + } + + HPROPSHEETPAGE IndexToPage(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HPROPSHEETPAGE)::SendMessage(m_hWnd, PSM_INDEXTOPAGE, nIndex, 0L); + } + + int IdToIndex(int nID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PSM_IDTOINDEX, 0, nID); + } + + int IndexToId(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PSM_INDEXTOID, nIndex, 0L); + } + + int GetResult() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, PSM_GETRESULT, 0, 0L); + } + + BOOL RecalcPageSizes() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, PSM_RECALCPAGESIZES, 0, 0L); + } + + void SetHeaderTitle(int nIndex, LPCTSTR lpstrHeaderTitle) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, PSM_SETHEADERTITLE, nIndex, (LPARAM)lpstrHeaderTitle); + } + + void SetHeaderSubTitle(int nIndex, LPCTSTR lpstrHeaderSubTitle) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, PSM_SETHEADERSUBTITLE, nIndex, (LPARAM)lpstrHeaderSubTitle); + } +#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + +// Implementation - override to prevent usage + HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL) + { + ATLASSERT(FALSE); + return NULL; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// CPropertySheetImpl - implements a property sheet + +template +class ATL_NO_VTABLE CPropertySheetImpl : public ATL::CWindowImplBaseT< TBase > +{ +public: + PROPSHEETHEADER m_psh; + ATL::CSimpleArray m_arrPages; + +#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific + #ifndef PROPSHEET_LINK_SIZE + #define PROPSHEET_LINK_SIZE 128 + #endif // PROPSHEET_LINK_SIZE + TCHAR m_szLink[PROPSHEET_LINK_SIZE]; + static LPCTSTR m_pszTitle; + static LPCTSTR m_pszLink; +#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) + +// Construction/Destruction + CPropertySheetImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL) + { + memset(&m_psh, 0, sizeof(PROPSHEETHEADER)); + m_psh.dwSize = sizeof(PROPSHEETHEADER); + m_psh.dwFlags = PSH_USECALLBACK; + m_psh.hInstance = ModuleHelper::GetResourceInstance(); + m_psh.phpage = NULL; // will be set later + m_psh.nPages = 0; // will be set later + m_psh.pszCaption = title.m_lpstr; + m_psh.nStartPage = uStartPage; + m_psh.hwndParent = hWndParent; // if NULL, will be set in DoModal/Create + m_psh.pfnCallback = T::PropSheetCallback; + +#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific + m_psh.dwFlags |= PSH_MAXIMIZE; + m_szLink[0] = 0; +#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) + } + + ~CPropertySheetImpl() + { + if(m_arrPages.GetSize() > 0) // sheet never created, destroy all pages + { + for(int i = 0; i < m_arrPages.GetSize(); i++) + ::DestroyPropertySheetPage((HPROPSHEETPAGE)m_arrPages[i]); + } + } + +// Callback function and overrideables + static int CALLBACK PropSheetCallback(HWND hWnd, UINT uMsg, LPARAM lParam) + { + lParam; // avoid level 4 warning + int nRet = 0; + + if(uMsg == PSCB_INITIALIZED) + { + ATLASSERT(hWnd != NULL); + T* pT = (T*)ModuleHelper::ExtractCreateWndData(); + // subclass the sheet window + pT->SubclassWindow(hWnd); + // remove page handles array + pT->_CleanUpPages(); + +#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific + m_pszTitle = pT->m_psh.pszCaption; + if(*pT->m_szLink != 0) + m_pszLink = pT->m_szLink; +#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific + + pT->OnSheetInitialized(); + } +#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific uMsg + else + { + switch(uMsg) + { + case PSCB_GETVERSION : + nRet = COMCTL32_VERSION; + break; + case PSCB_GETTITLE : + if(m_pszTitle != NULL) + { + lstrcpy((LPTSTR)lParam, m_pszTitle); + m_pszTitle = NULL; + } + break; + case PSCB_GETLINKTEXT: + if(m_pszLink != NULL) + { + lstrcpy((LPTSTR)lParam, m_pszLink); + m_pszLink = NULL; + } + break; + default: + break; + } + } +#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) + + return nRet; + } + + void OnSheetInitialized() + { + } + +// Create method + HWND Create(HWND hWndParent = NULL) + { + ATLASSERT(m_hWnd == NULL); + + m_psh.dwFlags |= PSH_MODELESS; + if(m_psh.hwndParent == NULL) + m_psh.hwndParent = hWndParent; + m_psh.phpage = (HPROPSHEETPAGE*)m_arrPages.GetData(); + m_psh.nPages = m_arrPages.GetSize(); + + T* pT = static_cast(this); + ModuleHelper::AddCreateWndData(&pT->m_thunk.cd, pT); + + HWND hWnd = (HWND)::PropertySheet(&m_psh); + _CleanUpPages(); // ensure clean-up, required if call failed + + ATLASSERT(m_hWnd == hWnd); + + return hWnd; + } + + INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) + { + ATLASSERT(m_hWnd == NULL); + + m_psh.dwFlags &= ~PSH_MODELESS; + if(m_psh.hwndParent == NULL) + m_psh.hwndParent = hWndParent; + m_psh.phpage = (HPROPSHEETPAGE*)m_arrPages.GetData(); + m_psh.nPages = m_arrPages.GetSize(); + + T* pT = static_cast(this); + ModuleHelper::AddCreateWndData(&pT->m_thunk.cd, pT); + + INT_PTR nRet = ::PropertySheet(&m_psh); + _CleanUpPages(); // ensure clean-up, required if call failed + + return nRet; + } + + // implementation helper - clean up pages array + void _CleanUpPages() + { + m_psh.nPages = 0; + m_psh.phpage = NULL; + m_arrPages.RemoveAll(); + } + +// Attributes (extended overrides of client class methods) +// These now can be called before the sheet is created +// Note: Calling these after the sheet is created gives unpredictable results + int GetPageCount() const + { + if(m_hWnd == NULL) // not created yet + return m_arrPages.GetSize(); + return TBase::GetPageCount(); + } + + int GetActiveIndex() const + { + if(m_hWnd == NULL) // not created yet + return m_psh.nStartPage; + return TBase::GetActiveIndex(); + } + + HPROPSHEETPAGE GetPage(int nPageIndex) const + { + ATLASSERT(m_hWnd == NULL); // can't do this after it's created + return (HPROPSHEETPAGE)m_arrPages[nPageIndex]; + } + + int GetPageIndex(HPROPSHEETPAGE hPage) const + { + ATLASSERT(m_hWnd == NULL); // can't do this after it's created + return m_arrPages.Find((HPROPSHEETPAGE&)hPage); + } + + BOOL SetActivePage(int nPageIndex) + { + if(m_hWnd == NULL) // not created yet + { + ATLASSERT(nPageIndex >= 0 && nPageIndex < m_arrPages.GetSize()); + m_psh.nStartPage = nPageIndex; + return TRUE; + } + return TBase::SetActivePage(nPageIndex); + } + + BOOL SetActivePage(HPROPSHEETPAGE hPage) + { + ATLASSERT(hPage != NULL); + if (m_hWnd == NULL) // not created yet + { + int nPageIndex = GetPageIndex(hPage); + if(nPageIndex == -1) + return FALSE; + + return SetActivePage(nPageIndex); + } + return TBase::SetActivePage(hPage); + + } + + void SetTitle(LPCTSTR lpszText, UINT nStyle = 0) + { + ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid + ATLASSERT(lpszText != NULL); + + if(m_hWnd == NULL) + { + // set internal state + m_psh.pszCaption = lpszText; // must exist until sheet is created + m_psh.dwFlags &= ~PSH_PROPTITLE; + m_psh.dwFlags |= nStyle; + } + else + { + // set external state + TBase::SetTitle(lpszText, nStyle); + } + } + +#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific Link field + void SetLinkText(LPCTSTR lpszText) + { + ATLASSERT(lpszText != NULL); + ATLASSERT(lstrlen(lpszText) < PROPSHEET_LINK_SIZE); + lstrcpy(m_szLink, lpszText); + } +#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) + + void SetWizardMode() + { + m_psh.dwFlags |= PSH_WIZARD; + } + + void EnableHelp() + { + m_psh.dwFlags |= PSH_HASHELP; + } + +// Operations + BOOL AddPage(HPROPSHEETPAGE hPage) + { + ATLASSERT(hPage != NULL); + BOOL bRet = FALSE; + if(m_hWnd != NULL) + bRet = TBase::AddPage(hPage); + else // sheet not created yet, use internal data + bRet = m_arrPages.Add((HPROPSHEETPAGE&)hPage); + return bRet; + } + + BOOL AddPage(LPCPROPSHEETPAGE pPage) + { + ATLASSERT(pPage != NULL); + HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage); + if(hPage == NULL) + return FALSE; + BOOL bRet = AddPage(hPage); + if(!bRet) + ::DestroyPropertySheetPage(hPage); + return bRet; + } + + BOOL RemovePage(HPROPSHEETPAGE hPage) + { + ATLASSERT(hPage != NULL); + if (m_hWnd == NULL) // not created yet + { + int nPage = GetPageIndex(hPage); + if(nPage == -1) + return FALSE; + return RemovePage(nPage); + } + TBase::RemovePage(hPage); + return TRUE; + + } + + BOOL RemovePage(int nPageIndex) + { + BOOL bRet = TRUE; + if(m_hWnd != NULL) + TBase::RemovePage(nPageIndex); + else // sheet not created yet, use internal data + bRet = m_arrPages.RemoveAt(nPageIndex); + return bRet; + } + +#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + void SetHeader(LPCTSTR szbmHeader) + { + ATLASSERT(m_hWnd == NULL); // can't do this after it's created + + m_psh.dwFlags &= ~PSH_WIZARD; + m_psh.dwFlags |= (PSH_HEADER | PSH_WIZARD97); + m_psh.pszbmHeader = szbmHeader; + } + + void SetHeader(HBITMAP hbmHeader) + { + ATLASSERT(m_hWnd == NULL); // can't do this after it's created + + m_psh.dwFlags &= ~PSH_WIZARD; + m_psh.dwFlags |= (PSH_HEADER | PSH_USEHBMHEADER | PSH_WIZARD97); + m_psh.hbmHeader = hbmHeader; + } + + void SetWatermark(LPCTSTR szbmWatermark, HPALETTE hplWatermark = NULL) + { + ATLASSERT(m_hWnd == NULL); // can't do this after it's created + + m_psh.dwFlags &= ~PSH_WIZARD; + m_psh.dwFlags |= PSH_WATERMARK | PSH_WIZARD97; + m_psh.pszbmWatermark = szbmWatermark; + + if (hplWatermark != NULL) + { + m_psh.dwFlags |= PSH_USEHPLWATERMARK; + m_psh.hplWatermark = hplWatermark; + } + } + + void SetWatermark(HBITMAP hbmWatermark, HPALETTE hplWatermark = NULL) + { + ATLASSERT(m_hWnd == NULL); // can't do this after it's created + + m_psh.dwFlags &= ~PSH_WIZARD; + m_psh.dwFlags |= (PSH_WATERMARK | PSH_USEHBMWATERMARK | PSH_WIZARD97); + m_psh.hbmWatermark = hbmWatermark; + + if (hplWatermark != NULL) + { + m_psh.dwFlags |= PSH_USEHPLWATERMARK; + m_psh.hplWatermark = hplWatermark; + } + } + + void StretchWatermark(bool bStretchWatermark) + { + ATLASSERT(m_hWnd == NULL); // can't do this after it's created + if (bStretchWatermark) + m_psh.dwFlags |= PSH_STRETCHWATERMARK; + else + m_psh.dwFlags &= ~PSH_STRETCHWATERMARK; + } +#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + +// Message map and handlers + BEGIN_MSG_MAP(CPropertySheetImpl) + MESSAGE_HANDLER(WM_COMMAND, OnCommand) + MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand) + END_MSG_MAP() + + LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); + if(HIWORD(wParam) == BN_CLICKED && (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) && + ((m_psh.dwFlags & PSH_MODELESS) != 0) && (GetActivePage() == NULL)) + DestroyWindow(); + return lRet; + } + + LRESULT OnSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + if(((m_psh.dwFlags & PSH_MODELESS) == PSH_MODELESS) && ((wParam & 0xFFF0) == SC_CLOSE)) + SendMessage(WM_CLOSE); + else + bHandled = FALSE; + return 0; + } +}; + +#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC static pointers +template < class T, class TBase > +LPCWSTR CPropertySheetImpl::m_pszTitle = NULL; +template < class T, class TBase> +LPCWSTR CPropertySheetImpl::m_pszLink = NULL; +#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) + +// for non-customized sheets +class CPropertySheet : public CPropertySheetImpl +{ +public: + CPropertySheet(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL) + : CPropertySheetImpl(title, uStartPage, hWndParent) + { } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CPropertyPageWindow - client side for a property page + +class CPropertyPageWindow : public ATL::CWindow +{ +public: +// Constructors + CPropertyPageWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd) + { } + + CPropertyPageWindow& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + +// Attributes + CPropertySheetWindow GetPropertySheet() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CPropertySheetWindow(GetParent()); + } + +// Operations + BOOL Apply() + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetParent() != NULL); + return GetPropertySheet().Apply(); + } + + void CancelToClose() + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetParent() != NULL); + GetPropertySheet().CancelToClose(); + } + + void SetModified(BOOL bChanged = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetParent() != NULL); + GetPropertySheet().SetModified(m_hWnd, bChanged); + } + + LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetParent() != NULL); + return GetPropertySheet().QuerySiblings(wParam, lParam); + } + + void RebootSystem() + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetParent() != NULL); + GetPropertySheet().RebootSystem(); + } + + void RestartWindows() + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetParent() != NULL); + GetPropertySheet().RestartWindows(); + } + + void SetWizardButtons(DWORD dwFlags) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetParent() != NULL); + GetPropertySheet().SetWizardButtons(dwFlags); + } + +// Implementation - overrides to prevent usage + HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL) + { + ATLASSERT(FALSE); + return NULL; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// CPropertyPageImpl - implements a property page + +template +class ATL_NO_VTABLE CPropertyPageImpl : public ATL::CDialogImplBaseT< TBase > +{ +public: + PROPSHEETPAGE m_psp; + + operator PROPSHEETPAGE*() { return &m_psp; } + +// Construction + CPropertyPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) + { + // initialize PROPSHEETPAGE struct + memset(&m_psp, 0, sizeof(PROPSHEETPAGE)); + m_psp.dwSize = sizeof(PROPSHEETPAGE); + m_psp.dwFlags = PSP_USECALLBACK; + m_psp.hInstance = ModuleHelper::GetResourceInstance(); + T* pT = static_cast(this); + m_psp.pszTemplate = MAKEINTRESOURCE(pT->IDD); + m_psp.pfnDlgProc = (DLGPROC)T::StartDialogProc; + m_psp.pfnCallback = T::PropPageCallback; + m_psp.lParam = (LPARAM)pT; + + if(title.m_lpstr != NULL) + SetTitle(title); + } + +// Callback function and overrideables + static UINT CALLBACK PropPageCallback(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp) + { + hWnd; // avoid level 4 warning + ATLASSERT(hWnd == NULL); + T* pT = (T*)ppsp->lParam; + UINT uRet = 0; + + switch(uMsg) + { + case PSPCB_CREATE: + { + ATL::CDialogImplBaseT< TBase >* pPage = (ATL::CDialogImplBaseT< TBase >*)pT; + ModuleHelper::AddCreateWndData(&pPage->m_thunk.cd, pPage); + uRet = pT->OnPageCreate() ? 1 : 0; + } + break; +#if (_WIN32_IE >= 0x0500) + case PSPCB_ADDREF: + pT->OnPageAddRef(); + break; +#endif // (_WIN32_IE >= 0x0500) + case PSPCB_RELEASE: + pT->OnPageRelease(); + break; + default: + break; + } + + return uRet; + } + + bool OnPageCreate() + { + return true; // true - allow page to be created, false - prevent creation + } + +#if (_WIN32_IE >= 0x0500) + void OnPageAddRef() + { + } +#endif // (_WIN32_IE >= 0x0500) + + void OnPageRelease() + { + } + +// Create method + HPROPSHEETPAGE Create() + { + return ::CreatePropertySheetPage(&m_psp); + } + +// Attributes + void SetTitle(ATL::_U_STRINGorID title) + { + m_psp.pszTitle = title.m_lpstr; + m_psp.dwFlags |= PSP_USETITLE; + } + +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + void SetHeaderTitle(LPCTSTR lpstrHeaderTitle) + { + ATLASSERT(m_hWnd == NULL); // can't do this after it's created + m_psp.dwFlags |= PSP_USEHEADERTITLE; + m_psp.pszHeaderTitle = lpstrHeaderTitle; + } + + void SetHeaderSubTitle(LPCTSTR lpstrHeaderSubTitle) + { + ATLASSERT(m_hWnd == NULL); // can't do this after it's created + m_psp.dwFlags |= PSP_USEHEADERSUBTITLE; + m_psp.pszHeaderSubTitle = lpstrHeaderSubTitle; + } +#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + +// Operations + void EnableHelp() + { + m_psp.dwFlags |= PSP_HASHELP; + } + +// Message map and handlers + BEGIN_MSG_MAP(CPropertyPageImpl) + MESSAGE_HANDLER(WM_NOTIFY, OnNotify) + END_MSG_MAP() + + // NOTE: Define _WTL_NEW_PAGE_NOTIFY_HANDLERS to use new notification + // handlers that return direct values without any restrictions + LRESULT OnNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { +#ifndef _WIN32_WCE + // This notification is sometimes received on Windows CE after the window is already destroyed + ATLASSERT(::IsWindow(m_hWnd)); +#endif + NMHDR* pNMHDR = (NMHDR*)lParam; + + // don't handle messages not from the page/sheet itself + if(pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd)) + { + bHandled = FALSE; + return 1; + } +#ifdef _WIN32_WCE + ATLASSERT(::IsWindow(m_hWnd)); +#endif + + T* pT = static_cast(this); + LRESULT lResult = 0; + switch(pNMHDR->code) + { +#ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS + case PSN_SETACTIVE: + lResult = pT->OnSetActive(); + break; + case PSN_KILLACTIVE: + lResult = pT->OnKillActive(); + break; + case PSN_APPLY: + lResult = pT->OnApply(); + break; + case PSN_RESET: + pT->OnReset(); + break; + case PSN_QUERYCANCEL: + lResult = pT->OnQueryCancel(); + break; + case PSN_WIZNEXT: + lResult = pT->OnWizardNext(); + break; + case PSN_WIZBACK: + lResult = pT->OnWizardBack(); + break; + case PSN_WIZFINISH: + lResult = pT->OnWizardFinish(); + break; + case PSN_HELP: + pT->OnHelp(); + break; +#ifndef _WIN32_WCE +#if (_WIN32_IE >= 0x0400) + case PSN_GETOBJECT: + if(!pT->OnGetObject((LPNMOBJECTNOTIFY)lParam)) + bHandled = FALSE; + break; +#endif // (_WIN32_IE >= 0x0400) +#if (_WIN32_IE >= 0x0500) + case PSN_TRANSLATEACCELERATOR: + { + LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam; + lResult = pT->OnTranslateAccelerator((LPMSG)lpPSHNotify->lParam); + } + break; + case PSN_QUERYINITIALFOCUS: + { + LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam; + lResult = (LRESULT)pT->OnQueryInitialFocus((HWND)lpPSHNotify->lParam); + } + break; +#endif // (_WIN32_IE >= 0x0500) +#endif // !_WIN32_WCE + +#else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS + case PSN_SETACTIVE: + lResult = pT->OnSetActive() ? 0 : -1; + break; + case PSN_KILLACTIVE: + lResult = !pT->OnKillActive(); + break; + case PSN_APPLY: + lResult = pT->OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE; + break; + case PSN_RESET: + pT->OnReset(); + break; + case PSN_QUERYCANCEL: + lResult = !pT->OnQueryCancel(); + break; + case PSN_WIZNEXT: + lResult = pT->OnWizardNext(); + break; + case PSN_WIZBACK: + lResult = pT->OnWizardBack(); + break; + case PSN_WIZFINISH: + lResult = !pT->OnWizardFinish(); + break; + case PSN_HELP: + pT->OnHelp(); + break; +#ifndef _WIN32_WCE +#if (_WIN32_IE >= 0x0400) + case PSN_GETOBJECT: + if(!pT->OnGetObject((LPNMOBJECTNOTIFY)lParam)) + bHandled = FALSE; + break; +#endif // (_WIN32_IE >= 0x0400) +#if (_WIN32_IE >= 0x0500) + case PSN_TRANSLATEACCELERATOR: + { + LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam; + lResult = pT->OnTranslateAccelerator((LPMSG)lpPSHNotify->lParam) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR; + } + break; + case PSN_QUERYINITIALFOCUS: + { + LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam; + lResult = (LRESULT)pT->OnQueryInitialFocus((HWND)lpPSHNotify->lParam); + } + break; +#endif // (_WIN32_IE >= 0x0500) +#endif // !_WIN32_WCE + +#endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS + default: + bHandled = FALSE; // not handled + } + + return lResult; + } + +// Overridables + // NOTE: Define _WTL_NEW_PAGE_NOTIFY_HANDLERS to use new notification + // handlers that return direct values without any restrictions +#ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS + int OnSetActive() + { + // 0 = allow activate + // -1 = go back that was active + // page ID = jump to page + return 0; + } + + BOOL OnKillActive() + { + // FALSE = allow deactivate + // TRUE = prevent deactivation + return FALSE; + } + + int OnApply() + { + // PSNRET_NOERROR = apply OK + // PSNRET_INVALID = apply not OK, return to this page + // PSNRET_INVALID_NOCHANGEPAGE = apply not OK, don't change focus + return PSNRET_NOERROR; + } + + void OnReset() + { + } + + BOOL OnQueryCancel() + { + // FALSE = allow cancel + // TRUE = prevent cancel + return FALSE; + } + + int OnWizardBack() + { + // 0 = goto previous page + // -1 = prevent page change + // >0 = jump to page by dlg ID + return 0; + } + + int OnWizardNext() + { + // 0 = goto next page + // -1 = prevent page change + // >0 = jump to page by dlg ID + return 0; + } + + INT_PTR OnWizardFinish() + { + // FALSE = allow finish + // TRUE = prevent finish + // HWND = prevent finish and set focus to HWND (CommCtrl 5.80 only) + return FALSE; + } + + void OnHelp() + { + } + +#ifndef _WIN32_WCE +#if (_WIN32_IE >= 0x0400) + BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/) + { + return FALSE; // not processed + } +#endif // (_WIN32_IE >= 0x0400) + +#if (_WIN32_IE >= 0x0500) + int OnTranslateAccelerator(LPMSG /*lpMsg*/) + { + // PSNRET_NOERROR - message not handled + // PSNRET_MESSAGEHANDLED - message handled + return PSNRET_NOERROR; + } + + HWND OnQueryInitialFocus(HWND /*hWndFocus*/) + { + // NULL = set focus to default control + // HWND = set focus to HWND + return NULL; + } +#endif // (_WIN32_IE >= 0x0500) +#endif // !_WIN32_WCE + +#else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS + BOOL OnSetActive() + { + return TRUE; + } + + BOOL OnKillActive() + { + return TRUE; + } + + BOOL OnApply() + { + return TRUE; + } + + void OnReset() + { + } + + BOOL OnQueryCancel() + { + return TRUE; // ok to cancel + } + + int OnWizardBack() + { + // 0 = goto previous page + // -1 = prevent page change + // >0 = jump to page by dlg ID + return 0; + } + + int OnWizardNext() + { + // 0 = goto next page + // -1 = prevent page change + // >0 = jump to page by dlg ID + return 0; + } + + BOOL OnWizardFinish() + { + return TRUE; + } + + void OnHelp() + { + } + +#ifndef _WIN32_WCE +#if (_WIN32_IE >= 0x0400) + BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/) + { + return FALSE; // not processed + } +#endif // (_WIN32_IE >= 0x0400) + +#if (_WIN32_IE >= 0x0500) + BOOL OnTranslateAccelerator(LPMSG /*lpMsg*/) + { + return FALSE; // not translated + } + + HWND OnQueryInitialFocus(HWND /*hWndFocus*/) + { + return NULL; // default + } +#endif // (_WIN32_IE >= 0x0500) +#endif // !_WIN32_WCE + +#endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS +}; + +// for non-customized pages +template +class CPropertyPage : public CPropertyPageImpl > +{ +public: + enum { IDD = t_wDlgTemplateID }; + + CPropertyPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CPropertyPageImpl(title) + { } + + DECLARE_EMPTY_MSG_MAP() +}; + +/////////////////////////////////////////////////////////////////////////////// +// CAxPropertyPageImpl - property page that hosts ActiveX controls + +#ifndef _ATL_NO_HOSTING + +// Note: You must #include to use these classes + +template +class ATL_NO_VTABLE CAxPropertyPageImpl : public CPropertyPageImpl< T, TBase > +{ +public: +// Data members + HGLOBAL m_hInitData; + HGLOBAL m_hDlgRes; + HGLOBAL m_hDlgResSplit; + +// Constructor/destructor + CAxPropertyPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : + CPropertyPageImpl< T, TBase >(title), + m_hInitData(NULL), m_hDlgRes(NULL), m_hDlgResSplit(NULL) + { + T* pT = static_cast(this); + pT; // avoid level 4 warning + + // initialize ActiveX hosting and modify dialog template + ATL::AtlAxWinInit(); + + HINSTANCE hInstance = ModuleHelper::GetResourceInstance(); + LPCTSTR lpTemplateName = MAKEINTRESOURCE(pT->IDD); + HRSRC hDlg = ::FindResource(hInstance, lpTemplateName, (LPTSTR)RT_DIALOG); + if(hDlg != NULL) + { + HRSRC hDlgInit = ::FindResource(hInstance, lpTemplateName, (LPTSTR)_ATL_RT_DLGINIT); + + BYTE* pInitData = NULL; + if(hDlgInit != NULL) + { + m_hInitData = ::LoadResource(hInstance, hDlgInit); + pInitData = (BYTE*)::LockResource(m_hInitData); + } + + m_hDlgRes = ::LoadResource(hInstance, hDlg); + DLGTEMPLATE* pDlg = (DLGTEMPLATE*)::LockResource(m_hDlgRes); + LPCDLGTEMPLATE lpDialogTemplate = ATL::_DialogSplitHelper::SplitDialogTemplate(pDlg, pInitData); + if(lpDialogTemplate != pDlg) + m_hDlgResSplit = GlobalHandle(lpDialogTemplate); + + // set up property page to use in-memory dialog template + if(lpDialogTemplate != NULL) + { + m_psp.dwFlags |= PSP_DLGINDIRECT; + m_psp.pResource = lpDialogTemplate; + } + else + { + ATLASSERT(FALSE && _T("CAxPropertyPageImpl - ActiveX initializtion failed!")); + } + } + else + { + ATLASSERT(FALSE && _T("CAxPropertyPageImpl - Cannot find dialog template!")); + } + } + + ~CAxPropertyPageImpl() + { + if(m_hInitData != NULL) + { + UnlockResource(m_hInitData); + FreeResource(m_hInitData); + } + if(m_hDlgRes != NULL) + { + UnlockResource(m_hDlgRes); + FreeResource(m_hDlgRes); + } + if(m_hDlgResSplit != NULL) + { + ::GlobalFree(m_hDlgResSplit); + } + } + +// Methods + // call this one to handle keyboard message for ActiveX controls + BOOL PreTranslateMessage(LPMSG pMsg) + { + if ((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) && + (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST)) + return FALSE; + // find a direct child of the dialog from the window that has focus + HWND hWndCtl = ::GetFocus(); + if (IsChild(hWndCtl) && ::GetParent(hWndCtl) != m_hWnd) + { + do + { + hWndCtl = ::GetParent(hWndCtl); + } + while (::GetParent(hWndCtl) != m_hWnd); + } + // give controls a chance to translate this message + return (BOOL)::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg); + } + +// Overridables +#if (_WIN32_IE >= 0x0500) + // new default implementation for ActiveX hosting pages +#ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS + int OnTranslateAccelerator(LPMSG lpMsg) + { + T* pT = static_cast(this); + return (pT->PreTranslateMessage(lpMsg) != FALSE) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR; + } +#else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS + BOOL OnTranslateAccelerator(LPMSG lpMsg) + { + T* pT = static_cast(this); + return pT->PreTranslateMessage(lpMsg); + } +#endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS +#endif // (_WIN32_IE >= 0x0500) + +// Support for new stuff in ATL7 +#if (_ATL_VER >= 0x0700) + int GetIDD() + { + return( static_cast(this)->IDD ); + } + + virtual DLGPROC GetDialogProc() + { + return DialogProc; + } + + static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + CAxPropertyPageImpl< T, TBase >* pThis = (CAxPropertyPageImpl< T, TBase >*)hWnd; + if (uMsg == WM_INITDIALOG) + { + HRESULT hr; + if (FAILED(hr = pThis->CreateActiveXControls(pThis->GetIDD()))) + { + ATLASSERT(FALSE); + return FALSE; + } + } + return CPropertyPageImpl< T, TBase >::DialogProc(hWnd, uMsg, wParam, lParam); + } + +// ActiveX controls creation + virtual HRESULT CreateActiveXControls(UINT nID) + { + // Load dialog template and InitData + HRSRC hDlgInit = ::FindResource(ATL::_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)_ATL_RT_DLGINIT); + BYTE* pInitData = NULL; + HGLOBAL hData = NULL; + HRESULT hr = S_OK; + if (hDlgInit != NULL) + { + hData = ::LoadResource(ATL::_AtlBaseModule.GetResourceInstance(), hDlgInit); + if (hData != NULL) + pInitData = (BYTE*) ::LockResource(hData); + } + + HRSRC hDlg = ::FindResource(ATL::_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)RT_DIALOG); + if (hDlg != NULL) + { + HGLOBAL hResource = ::LoadResource(ATL::_AtlBaseModule.GetResourceInstance(), hDlg); + DLGTEMPLATE* pDlg = NULL; + if (hResource != NULL) + { + pDlg = (DLGTEMPLATE*) ::LockResource(hResource); + if (pDlg != NULL) + { + // Get first control on the template + BOOL bDialogEx = ATL::_DialogSplitHelper::IsDialogEx(pDlg); + WORD nItems = ATL::_DialogSplitHelper::DlgTemplateItemCount(pDlg); + + // Get first control on the dialog + DLGITEMTEMPLATE* pItem = ATL::_DialogSplitHelper::FindFirstDlgItem(pDlg); + HWND hWndPrev = GetWindow(GW_CHILD); + + // Create all ActiveX cotnrols in the dialog template and place them in the correct tab order (z-order) + for (WORD nItem = 0; nItem < nItems; nItem++) + { + DWORD wID = bDialogEx ? ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id : pItem->id; + if (ATL::_DialogSplitHelper::IsActiveXControl(pItem, bDialogEx)) + { + BYTE* pData = NULL; + DWORD dwLen = ATL::_DialogSplitHelper::FindCreateData(wID, pInitData, &pData); + ATL::CComPtr spStream; + if (dwLen != 0) + { + HGLOBAL h = GlobalAlloc(GHND, dwLen); + if (h != NULL) + { + BYTE* pBytes = (BYTE*) GlobalLock(h); + BYTE* pSource = pData; + SecureHelper::memcpy_x(pBytes, dwLen, pSource, dwLen); + GlobalUnlock(h); + CreateStreamOnHGlobal(h, TRUE, &spStream); + } + else + { + hr = E_OUTOFMEMORY; + break; + } + } + + ATL::CComBSTR bstrLicKey; + hr = ATL::_DialogSplitHelper::ParseInitData(spStream, &bstrLicKey.m_str); + if (SUCCEEDED(hr)) + { + ATL::CAxWindow2 wnd; + // Get control caption. + LPWSTR pszClassName = + bDialogEx ? + (LPWSTR)(((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem) + 1) : + (LPWSTR)(pItem + 1); + // Get control rect. + RECT rect; + rect.left = + bDialogEx ? + ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->x : + pItem->x; + rect.top = + bDialogEx ? + ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->y : + pItem->y; + rect.right = rect.left + + (bDialogEx ? + ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cx : + pItem->cx); + rect.bottom = rect.top + + (bDialogEx ? + ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cy : + pItem->cy); + + // Convert from dialog units to screen units + MapDialogRect(&rect); + + // Create AxWindow with a NULL caption. + wnd.Create(m_hWnd, + &rect, + NULL, + (bDialogEx ? + ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->style : + pItem->style) | WS_TABSTOP, + bDialogEx ? + ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->exStyle : + 0, + bDialogEx ? + ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id : + pItem->id, + NULL); + + if (wnd != NULL) + { +#ifndef _WIN32_WCE + // Set the Help ID + if (bDialogEx && ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID != 0) + wnd.SetWindowContextHelpId(((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID); +#endif // !_WIN32_WCE + // Try to create the ActiveX control. + hr = wnd.CreateControlLic(pszClassName, spStream, NULL, bstrLicKey); + if (FAILED(hr)) + break; + // Set the correct tab position. + if (nItem == 0) + hWndPrev = HWND_TOP; + wnd.SetWindowPos(hWndPrev, 0,0,0,0,SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); + hWndPrev = wnd; + } + else + { + hr = ATL::AtlHresultFromLastError(); + } + } + } + else + { + if (nItem != 0) + hWndPrev = ::GetWindow(hWndPrev, GW_HWNDNEXT); + } + pItem = ATL::_DialogSplitHelper::FindNextDlgItem(pItem, bDialogEx); + } + } + else + hr = ATL::AtlHresultFromLastError(); + } + else + hr = ATL::AtlHresultFromLastError(); + } + return hr; + } + +// Event handling support + HRESULT AdviseSinkMap(bool bAdvise) + { + if(!bAdvise && m_hWnd == NULL) + { + // window is gone, controls are already unadvised + ATLTRACE2(atlTraceUI, 0, _T("CAxPropertyPageImpl::AdviseSinkMap called after the window was destroyed\n")); + return S_OK; + } + HRESULT hRet = E_NOTIMPL; + __if_exists(T::_GetSinkMapFinder) + { + T* pT = static_cast(this); + hRet = AtlAdviseSinkMap(pT, bAdvise); + } + return hRet; + } + +// Message map and handlers + typedef CPropertyPageImpl< T, TBase> _baseClass; + BEGIN_MSG_MAP(CAxPropertyPageImpl) + MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) + CHAIN_MSG_MAP(_baseClass) + END_MSG_MAP() + + LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + // initialize controls in dialog with DLGINIT resource section + ExecuteDlgInit(static_cast(this)->IDD); + AdviseSinkMap(true); + bHandled = FALSE; + return 1; + } + + LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + AdviseSinkMap(false); + bHandled = FALSE; + return 1; + } +#endif // (_ATL_VER >= 0x0700) +}; + +// for non-customized pages +template +class CAxPropertyPage : public CAxPropertyPageImpl > +{ +public: + enum { IDD = t_wDlgTemplateID }; + + CAxPropertyPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAxPropertyPageImpl(title) + { } + +#if (_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700) + // not empty so we handle accelerators/create controls + BEGIN_MSG_MAP(CAxPropertyPage) + CHAIN_MSG_MAP(CAxPropertyPageImpl >) + END_MSG_MAP() +#else // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)) + DECLARE_EMPTY_MSG_MAP() +#endif // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)) +}; + +#endif // _ATL_NO_HOSTING + + +/////////////////////////////////////////////////////////////////////////////// +// Wizard97 Support + +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + +// Sample wizard dialog resources: +// +// IDD_WIZ97_INTERIOR_BLANK DIALOG 0, 0, 317, 143 +// STYLE DS_SETFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +// CAPTION "Wizard97 Property Page - Interior" +// FONT 8, "MS Shell Dlg" +// BEGIN +// END +// +// IDD_WIZ97_EXTERIOR_BLANK DIALOGEX 0, 0, 317, 193 +// STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION +// CAPTION "Wizard97 Property Page - Welcome/Complete" +// FONT 8, "MS Shell Dlg", 0, 0, 0x0 +// BEGIN +// LTEXT "Welcome to the X Wizard",IDC_WIZ97_EXTERIOR_TITLE,115,8, +// 195,24 +// LTEXT "Wizard Explanation\r\n(The height of the static text should be in multiples of 8 dlus)", +// IDC_STATIC,115,40,195,16 +// LTEXT "h",IDC_WIZ97_BULLET1,118,64,8,8 +// LTEXT "List Item 1 (the h is turned into a bullet)",IDC_STATIC, +// 127,63,122,8 +// LTEXT "h",IDC_WIZ97_BULLET2,118,79,8,8 +// LTEXT "List Item 2. Keep 7 dlus between paragraphs",IDC_STATIC, +// 127,78,33,8 +// CONTROL "&Do not show this Welcome page again", +// IDC_WIZ97_WELCOME_NOTAGAIN,"Button",BS_AUTOCHECKBOX | +// WS_TABSTOP,115,169,138,10 +// END +// +// GUIDELINES DESIGNINFO +// BEGIN +// IDD_WIZ97_INTERIOR_BLANK, DIALOG +// BEGIN +// LEFTMARGIN, 7 +// RIGHTMARGIN, 310 +// VERTGUIDE, 21 +// VERTGUIDE, 31 +// VERTGUIDE, 286 +// VERTGUIDE, 296 +// TOPMARGIN, 7 +// BOTTOMMARGIN, 136 +// HORZGUIDE, 8 +// END +// +// IDD_WIZ97_EXTERIOR_BLANK, DIALOG +// BEGIN +// RIGHTMARGIN, 310 +// VERTGUIDE, 115 +// VERTGUIDE, 118 +// VERTGUIDE, 127 +// TOPMARGIN, 7 +// BOTTOMMARGIN, 186 +// HORZGUIDE, 8 +// HORZGUIDE, 32 +// HORZGUIDE, 40 +// HORZGUIDE, 169 +// END +// END + +/////////////////////////////////////////////////////////////////////////////// +// CWizard97SheetWindow - client side for a Wizard 97 style wizard sheet + +class CWizard97SheetWindow : public CPropertySheetWindow +{ +public: +// Constructors + CWizard97SheetWindow(HWND hWnd = NULL) : CPropertySheetWindow(hWnd) + { } + + CWizard97SheetWindow& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + +// Operations + HFONT GetExteriorPageTitleFont(void) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HFONT)::SendMessage(m_hWnd, GetMessage_GetExteriorPageTitleFont(), 0, 0L); + } + + HFONT GetBulletFont(void) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HFONT)::SendMessage(m_hWnd, GetMessage_GetBulletFont(), 0, 0L); + } + +// Helpers + static UINT GetMessage_GetExteriorPageTitleFont() + { + static UINT uGetExteriorPageTitleFont = 0; + if(uGetExteriorPageTitleFont == 0) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CWizard97SheetWindow::GetMessage_GetExteriorPageTitleFont().\n")); + ATLASSERT(FALSE); + return 0; + } + + if(uGetExteriorPageTitleFont == 0) + uGetExteriorPageTitleFont = ::RegisterWindowMessage(_T("GetExteriorPageTitleFont_531AF056-B8BE-4c4c-B786-AC608DF0DF12")); + + lock.Unlock(); + } + ATLASSERT(uGetExteriorPageTitleFont != 0); + return uGetExteriorPageTitleFont; + } + + static UINT GetMessage_GetBulletFont() + { + static UINT uGetBulletFont = 0; + if(uGetBulletFont == 0) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CWizard97SheetWindow::GetMessage_GetBulletFont().\n")); + ATLASSERT(FALSE); + return 0; + } + + if(uGetBulletFont == 0) + uGetBulletFont = ::RegisterWindowMessage(_T("GetBulletFont_AD347D08-8F65-45ef-982E-6352E8218AD5")); + + lock.Unlock(); + } + ATLASSERT(uGetBulletFont != 0); + return uGetBulletFont; + } + +// Implementation - override to prevent usage + HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL) + { + ATLASSERT(FALSE); + return NULL; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CWizard97SheetImpl - implements a Wizard 97 style wizard sheet + +template +class ATL_NO_VTABLE CWizard97SheetImpl : public CPropertySheetImpl< T, TBase > +{ +protected: +// Typedefs + typedef CWizard97SheetImpl< T, TBase > thisClass; + typedef CPropertySheetImpl< T, TBase > baseClass; + +// Member variables + CFont m_fontExteriorPageTitle; // Welcome and Completion page title font + CFont m_fontBullet; // Bullet font (used on static text 'h' to produce a small bullet) + bool m_bReceivedFirstSizeMessage; + +public: + CWizard97SheetImpl(ATL::_U_STRINGorID title, ATL::_U_STRINGorID headerBitmap, ATL::_U_STRINGorID watermarkBitmap, UINT uStartPage = 0, HWND hWndParent = NULL) : + baseClass(title, uStartPage, hWndParent), + m_bReceivedFirstSizeMessage(false) + { + m_psh.dwFlags &= ~(PSH_NOCONTEXTHELP); + m_psh.dwFlags &= ~(PSH_WIZARD | PSH_WIZARD_LITE); + + m_psh.dwFlags |= (PSH_HASHELP | PSH_WIZARDCONTEXTHELP); + m_psh.dwFlags |= PSH_WIZARD97; + + baseClass::SetHeader(headerBitmap.m_lpstr); + baseClass::SetWatermark(watermarkBitmap.m_lpstr); + } + +// Overrides from base class + void OnSheetInitialized() + { + T* pT = static_cast(this); + pT->_InitializeFonts(); + + // We'd like to center the wizard here, but its too early. + // Instead, we'll do CenterWindow upon our first WM_SIZE message + } + +// Initialization + void _InitializeFonts() + { + // Setup the Title and Bullet Font + // (Property pages can send the "get external page title font" and "get bullet font" messages) + // The derived class needs to do the actual SetFont for the dialog items) + + CFontHandle fontThisDialog = this->GetFont(); + CClientDC dcScreen(NULL); + + LOGFONT titleLogFont = {0}; + LOGFONT bulletLogFont = {0}; + fontThisDialog.GetLogFont(&titleLogFont); + fontThisDialog.GetLogFont(&bulletLogFont); + + // The Wizard 97 Spec recommends to do the Title Font + // as Verdana Bold, 12pt. + titleLogFont.lfCharSet = DEFAULT_CHARSET; + titleLogFont.lfWeight = FW_BOLD; + SecureHelper::strcpy_x(titleLogFont.lfFaceName, _countof(titleLogFont.lfFaceName), _T("Verdana Bold")); + INT titleFontPointSize = 12; + titleLogFont.lfHeight = -::MulDiv(titleFontPointSize, dcScreen.GetDeviceCaps(LOGPIXELSY), 72); + m_fontExteriorPageTitle.CreateFontIndirect(&titleLogFont); + + // The Wizard 97 Spec recommends to do Bullets by having + // static text of "h" in the Marlett font. + bulletLogFont.lfCharSet = DEFAULT_CHARSET; + bulletLogFont.lfWeight = FW_NORMAL; + SecureHelper::strcpy_x(bulletLogFont.lfFaceName, _countof(bulletLogFont.lfFaceName), _T("Marlett")); + INT bulletFontSize = 8; + bulletLogFont.lfHeight = -::MulDiv(bulletFontSize, dcScreen.GetDeviceCaps(LOGPIXELSY), 72); + m_fontBullet.CreateFontIndirect(&bulletLogFont); + } + +// Message Handling + BEGIN_MSG_MAP(thisClass) + MESSAGE_HANDLER(CWizard97SheetWindow::GetMessage_GetExteriorPageTitleFont(), OnGetExteriorPageTitleFont) + MESSAGE_HANDLER(CWizard97SheetWindow::GetMessage_GetBulletFont(), OnGetBulletFont) + MESSAGE_HANDLER(WM_SIZE, OnSize) + CHAIN_MSG_MAP(baseClass) + END_MSG_MAP() + + LRESULT OnGetExteriorPageTitleFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return (LRESULT)(HFONT)m_fontExteriorPageTitle; + } + + LRESULT OnGetBulletFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return (LRESULT)(HFONT)m_fontBullet; + } + + LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + if(!m_bReceivedFirstSizeMessage) + { + m_bReceivedFirstSizeMessage = true; + this->CenterWindow(); + } + + bHandled = FALSE; + return 0; + } +}; + +// for non-customized sheets +class CWizard97Sheet : public CWizard97SheetImpl +{ +protected: +// Typedefs + typedef CWizard97Sheet thisClass; + typedef CWizard97SheetImpl baseClass; + +public: + CWizard97Sheet(ATL::_U_STRINGorID title, ATL::_U_STRINGorID headerBitmap, ATL::_U_STRINGorID watermarkBitmap, UINT uStartPage = 0, HWND hWndParent = NULL) : + baseClass(title, headerBitmap, watermarkBitmap, uStartPage, hWndParent) + { } + + BEGIN_MSG_MAP(thisClass) + CHAIN_MSG_MAP(baseClass) + END_MSG_MAP() +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CWizard97PageWindow - client side for a Wizard 97 style wizard page + +#define WIZARD97_EXTERIOR_CXDLG 317 +#define WIZARD97_EXTERIOR_CYDLG 193 + +#define WIZARD97_INTERIOR_CXDLG 317 +#define WIZARD97_INTERIOR_CYDLG 143 + +class CWizard97PageWindow : public CPropertyPageWindow +{ +public: +// Constructors + CWizard97PageWindow(HWND hWnd = NULL) : CPropertyPageWindow(hWnd) + { } + + CWizard97PageWindow& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + +// Attributes + CWizard97SheetWindow GetPropertySheet() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CWizard97SheetWindow(GetParent()); + } + +// Operations + HFONT GetExteriorPageTitleFont(void) + { + ATLASSERT(::IsWindow(m_hWnd)); + return GetPropertySheet().GetExteriorPageTitleFont(); + } + + HFONT GetBulletFont(void) + { + ATLASSERT(::IsWindow(m_hWnd)); + return GetPropertySheet().GetBulletFont(); + } + +// Implementation - overrides to prevent usage + HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL) + { + ATLASSERT(FALSE); + return NULL; + } + +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CWizard97PageImpl - implements a Wizard 97 style wizard page + +template +class ATL_NO_VTABLE CWizard97PageImpl : public CPropertyPageImpl< T, TBase > +{ +protected: +// Typedefs + typedef CWizard97PageImpl< T, TBase > thisClass; + typedef CPropertyPageImpl< T, TBase > baseClass; + +public: + CWizard97PageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title) + { } + +// Message Handling + BEGIN_MSG_MAP(thisClass) + CHAIN_MSG_MAP(baseClass) + END_MSG_MAP() +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CWizard97ExteriorPageImpl - implements a Wizard 97 style exterior wizard page + +template +class ATL_NO_VTABLE CWizard97ExteriorPageImpl : public CPropertyPageImpl< T, TBase > +{ +protected: +// Typedefs + typedef CWizard97ExteriorPageImpl< T, TBase > thisClass; + typedef CPropertyPageImpl< T, TBase > baseClass; + +public: +// Constructors + CWizard97ExteriorPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title) + { + m_psp.dwFlags |= PSP_HASHELP; + m_psp.dwFlags |= PSP_HIDEHEADER; + } + +// Message Handling + BEGIN_MSG_MAP(thisClass) + CHAIN_MSG_MAP(baseClass) + END_MSG_MAP() +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CWizard97InteriorPageImpl - implements a Wizard 97 style interior wizard page + +template +class ATL_NO_VTABLE CWizard97InteriorPageImpl : public CPropertyPageImpl< T, TBase > +{ +protected: +// Typedefs + typedef CWizard97InteriorPageImpl< T, TBase > thisClass; + typedef CPropertyPageImpl< T, TBase > baseClass; + +public: +// Constructors + CWizard97InteriorPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title) + { + m_psp.dwFlags |= PSP_HASHELP; + m_psp.dwFlags &= ~PSP_HIDEHEADER; + m_psp.dwFlags |= PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; + + // Be sure to have the derived class define this in the constructor. + // We'll default it to something obvious in case its forgotten. + baseClass::SetHeaderTitle(_T("Call SetHeaderTitle in Derived Class")); + baseClass::SetHeaderSubTitle(_T("Call SetHeaderSubTitle in the constructor of the Derived Class.")); + } + +// Message Handling + BEGIN_MSG_MAP(thisClass) + CHAIN_MSG_MAP(baseClass) + END_MSG_MAP() +}; + +#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + + +/////////////////////////////////////////////////////////////////////////////// +// Aero Wizard support + +#if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE) + +/////////////////////////////////////////////////////////////////////////////// +// CAeroWizardFrameWindow - client side for an Aero Wizard frame window + +class CAeroWizardFrameWindow : public CPropertySheetWindow +{ +public: +// Constructors + CAeroWizardFrameWindow(HWND hWnd = NULL) : CPropertySheetWindow(hWnd) + { } + + CAeroWizardFrameWindow& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + +// Operations - new, Aero Wizard only + void SetNextText(LPCWSTR lpszText) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, PSM_SETNEXTTEXT, 0, (LPARAM)lpszText); + } + + void ShowWizardButtons(DWORD dwButtons, DWORD dwStates) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::PostMessage(m_hWnd, PSM_SHOWWIZBUTTONS, (WPARAM)dwStates, (LPARAM)dwButtons); + } + + void EnableWizardButtons(DWORD dwButtons, DWORD dwStates) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::PostMessage(m_hWnd, PSM_ENABLEWIZBUTTONS, (WPARAM)dwStates, (LPARAM)dwButtons); + } + + void SetButtonText(DWORD dwButton, LPCWSTR lpszText) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, PSM_SETBUTTONTEXT, (WPARAM)dwButton, (LPARAM)lpszText); + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CAeroWizardFrameImpl - implements an Aero Wizard frame + +template +class ATL_NO_VTABLE CAeroWizardFrameImpl : public CPropertySheetImpl +{ +public: +// Constructor + CAeroWizardFrameImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL) : + CPropertySheetImpl(title, uStartPage, hWndParent) + { + m_psh.dwFlags |= PSH_WIZARD | PSH_AEROWIZARD; + } + +// Operations + void EnableResizing() + { + ATLASSERT(m_hWnd == NULL); // can't do this after it's created + m_psh.dwFlags |= PSH_RESIZABLE; + } + + void UseHeaderBitmap() + { + ATLASSERT(m_hWnd == NULL); // can't do this after it's created + m_psh.dwFlags |= PSH_HEADERBITMAP; + } + + void SetNoMargin() + { + ATLASSERT(m_hWnd == NULL); // can't do this after it's created + m_psh.dwFlags |= PSH_NOMARGIN; + } + +// Override to prevent use + HWND Create(HWND /*hWndParent*/ = NULL) + { + ATLASSERT(FALSE); // not supported for Aero Wizard + return NULL; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CAeroWizardFrame - for non-customized frames + +class CAeroWizardFrame : public CAeroWizardFrameImpl +{ +public: + CAeroWizardFrame(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL) + : CAeroWizardFrameImpl(title, uStartPage, hWndParent) + { } + + BEGIN_MSG_MAP(CAeroWizardFrame) + MESSAGE_HANDLER(WM_COMMAND, CAeroWizardFrameImpl::OnCommand) + END_MSG_MAP() +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CAeroWizardPageWindow - client side for an Aero Wizard page + +class CAeroWizardPageWindow : public CPropertyPageWindow +{ +public: +// Constructors + CAeroWizardPageWindow(HWND hWnd = NULL) : CPropertyPageWindow(hWnd) + { } + + CAeroWizardPageWindow& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + +// Attributes + CAeroWizardFrameWindow GetAeroWizardFrame() const + { + ATLASSERT(::IsWindow(m_hWnd)); + // This is not really top-level frame window, but it processes all frame messages + return CAeroWizardFrameWindow(GetParent()); + } + +// Operations - new, Aero Wizard only + void SetNextText(LPCWSTR lpszText) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetParent() != NULL); + GetAeroWizardFrame().SetNextText(lpszText); + } + + void ShowWizardButtons(DWORD dwButtons, DWORD dwStates) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetParent() != NULL); + GetAeroWizardFrame().ShowWizardButtons(dwButtons, dwStates); + } + + void EnableWizardButtons(DWORD dwButtons, DWORD dwStates) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetParent() != NULL); + GetAeroWizardFrame().EnableWizardButtons(dwButtons, dwStates); + } + + void SetButtonText(DWORD dwButton, LPCWSTR lpszText) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetParent() != NULL); + GetAeroWizardFrame().SetButtonText(dwButton, lpszText); + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CAeroWizardPageImpl - implements an Aero Wizard page + +template +class ATL_NO_VTABLE CAeroWizardPageImpl : public CPropertyPageImpl +{ +public: + CAeroWizardPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CPropertyPageImpl(title) + { } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CAeroWizardPage - for non-customized pages + +template +class CAeroWizardPage : public CAeroWizardPageImpl > +{ +public: + enum { IDD = t_wDlgTemplateID }; + + CAeroWizardPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAeroWizardPageImpl(title) + { } + + DECLARE_EMPTY_MSG_MAP() +}; + + +#ifndef _ATL_NO_HOSTING + +// Note: You must #include to use these classes + +/////////////////////////////////////////////////////////////////////////////// +// CAeroWizardAxPageImpl - Aero Wizard page that hosts ActiveX controls + +template +class ATL_NO_VTABLE CAeroWizardAxPageImpl : public CAxPropertyPageImpl< T, TBase > +{ +public: + CAeroWizardAxPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAxPropertyPageImpl< T, TBase >(title) + { } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CAeroWizardAxPage - for non-customized pages + +template +class CAeroWizardAxPage : public CAeroWizardAxPageImpl > +{ +public: + enum { IDD = t_wDlgTemplateID }; + + CAeroWizardAxPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAeroWizardAxPageImpl(title) + { } + +#if (_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700) + // not empty so we handle accelerators/create controls + BEGIN_MSG_MAP(CAeroWizardAxPage) + CHAIN_MSG_MAP(CAeroWizardAxPageImpl >) + END_MSG_MAP() +#else // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)) + DECLARE_EMPTY_MSG_MAP() +#endif // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)) +}; + +#endif // _ATL_NO_HOSTING + +#endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE) + + +/////////////////////////////////////////////////////////////////////////////// +// TaskDialog support + +#if ((_WIN32_WINNT >= 0x0600) || defined(_WTL_TASKDIALOG)) && !defined(_WIN32_WCE) + +/////////////////////////////////////////////////////////////////////////////// +// AtlTaskDialog - support for TaskDialog() function + +inline int AtlTaskDialog(HWND hWndParent, + ATL::_U_STRINGorID WindowTitle, ATL::_U_STRINGorID MainInstructionText, ATL::_U_STRINGorID ContentText, + TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons = 0U, ATL::_U_STRINGorID Icon = (LPCTSTR)NULL) +{ + int nRet = -1; + +#ifdef _WTL_TASKDIALOG_DIRECT + USES_CONVERSION; + HRESULT hRet = ::TaskDialog(hWndParent, ModuleHelper::GetResourceInstance(), T2CW(WindowTitle.m_lpstr), T2CW(MainInstructionText.m_lpstr), T2CW(ContentText.m_lpstr), dwCommonButtons, T2CW(Icon.m_lpstr), &nRet); + ATLVERIFY(SUCCEEDED(hRet)); +#else + // This allows apps to run on older versions of Windows + typedef HRESULT (STDAPICALLTYPE *PFN_TaskDialog)(HWND hwndParent, HINSTANCE hInstance, PCWSTR pszWindowTitle, PCWSTR pszMainInstruction, PCWSTR pszContent, TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons, PCWSTR pszIcon, int* pnButton); + + HMODULE m_hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll")); + if(m_hCommCtrlDLL != NULL) + { + PFN_TaskDialog pfnTaskDialog = (PFN_TaskDialog)::GetProcAddress(m_hCommCtrlDLL, "TaskDialog"); + if(pfnTaskDialog != NULL) + { + USES_CONVERSION; + HRESULT hRet = pfnTaskDialog(hWndParent, ModuleHelper::GetResourceInstance(), T2CW(WindowTitle.m_lpstr), T2CW(MainInstructionText.m_lpstr), T2CW(ContentText.m_lpstr), dwCommonButtons, T2CW(Icon.m_lpstr), &nRet); + ATLVERIFY(SUCCEEDED(hRet)); + } + + ::FreeLibrary(m_hCommCtrlDLL); + } +#endif + + return nRet; +} + + +/////////////////////////////////////////////////////////////////////////////// +// CTaskDialogConfig - TASKDIALOGCONFIG wrapper + +class CTaskDialogConfig : public TASKDIALOGCONFIG +{ +public: +// Constructor + CTaskDialogConfig() + { + Init(); + } + + void Init() + { + memset(this, 0, sizeof(TASKDIALOGCONFIG)); // initialize structure to 0/NULL + this->cbSize = sizeof(TASKDIALOGCONFIG); + this->hInstance = ModuleHelper::GetResourceInstance(); + } + +// Operations - setting values + // common buttons + void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons) + { + this->dwCommonButtons = dwCommonButtons; + } + + // window title text + void SetWindowTitle(UINT nID) + { + this->pszWindowTitle = MAKEINTRESOURCEW(nID); + } + + void SetWindowTitle(LPCWSTR lpstrWindowTitle) + { + this->pszWindowTitle = lpstrWindowTitle; + } + + // main icon + void SetMainIcon(HICON hIcon) + { + this->dwFlags |= TDF_USE_HICON_MAIN; + this->hMainIcon = hIcon; + } + + void SetMainIcon(UINT nID) + { + this->dwFlags &= ~TDF_USE_HICON_MAIN; + this->pszMainIcon = MAKEINTRESOURCEW(nID); + } + + void SetMainIcon(LPCWSTR lpstrMainIcon) + { + this->dwFlags &= ~TDF_USE_HICON_MAIN; + this->pszMainIcon = lpstrMainIcon; + } + + // main instruction text + void SetMainInstructionText(UINT nID) + { + this->pszMainInstruction = MAKEINTRESOURCEW(nID); + } + + void SetMainInstructionText(LPCWSTR lpstrMainInstruction) + { + this->pszMainInstruction = lpstrMainInstruction; + } + + // content text + void SetContentText(UINT nID) + { + this->pszContent = MAKEINTRESOURCEW(nID); + } + + void SetContentText(LPCWSTR lpstrContent) + { + this->pszContent = lpstrContent; + } + + // buttons + void SetButtons(const TASKDIALOG_BUTTON* pButtons, UINT cButtons, int nDefaultButton = 0) + { + this->pButtons = pButtons; + this->cButtons = cButtons; + if(nDefaultButton != 0) + this->nDefaultButton = nDefaultButton; + } + + void SetDefaultButton(int nDefaultButton) + { + this->nDefaultButton = nDefaultButton; + } + + // radio buttons + void SetRadioButtons(const TASKDIALOG_BUTTON* pRadioButtons, UINT cRadioButtons, int nDefaultRadioButton = 0) + { + this->pRadioButtons = pRadioButtons; + this->cRadioButtons = cRadioButtons; + if(nDefaultRadioButton != 0) + this->nDefaultRadioButton = nDefaultRadioButton; + } + + void SetDefaultRadioButton(int nDefaultRadioButton) + { + this->nDefaultRadioButton = nDefaultRadioButton; + } + + // verification text + void SetVerificationText(UINT nID) + { + this->pszVerificationText = MAKEINTRESOURCEW(nID); + } + + void SetVerificationText(LPCWSTR lpstrVerificationText) + { + this->pszVerificationText = lpstrVerificationText; + } + + // expanded information text + void SetExpandedInformationText(UINT nID) + { + this->pszExpandedInformation = MAKEINTRESOURCEW(nID); + } + + void SetExpandedInformationText(LPCWSTR lpstrExpandedInformation) + { + this->pszExpandedInformation = lpstrExpandedInformation; + } + + // expanded control text + void SetExpandedControlText(UINT nID) + { + this->pszExpandedControlText = MAKEINTRESOURCEW(nID); + } + + void SetExpandedControlText(LPCWSTR lpstrExpandedControlText) + { + this->pszExpandedControlText = lpstrExpandedControlText; + } + + // collapsed control text + void SetCollapsedControlText(UINT nID) + { + this->pszCollapsedControlText = MAKEINTRESOURCEW(nID); + } + + void SetCollapsedControlText(LPCWSTR lpstrCollapsedControlText) + { + this->pszCollapsedControlText = lpstrCollapsedControlText; + } + + // footer icon + void SetFooterIcon(HICON hIcon) + { + this->dwFlags |= TDF_USE_HICON_FOOTER; + this->hFooterIcon = hIcon; + } + + void SetFooterIcon(UINT nID) + { + this->dwFlags &= ~TDF_USE_HICON_FOOTER; + this->pszFooterIcon = MAKEINTRESOURCEW(nID); + } + + void SetFooterIcon(LPCWSTR lpstrFooterIcon) + { + this->dwFlags &= ~TDF_USE_HICON_FOOTER; + this->pszFooterIcon = lpstrFooterIcon; + } + + // footer text + void SetFooterText(UINT nID) + { + this->pszFooter = MAKEINTRESOURCEW(nID); + } + + void SetFooterText(LPCWSTR lpstrFooterText) + { + this->pszFooter = lpstrFooterText; + } + + // width (in DLUs) + void SetWidth(UINT cxWidth) + { + this->cxWidth = cxWidth; + } + + // modify flags + void ModifyFlags(DWORD dwRemove, DWORD dwAdd) + { + this->dwFlags = (this->dwFlags & ~dwRemove) | dwAdd; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CTaskDialogImpl - implements a Task Dialog + +template +class ATL_NO_VTABLE CTaskDialogImpl +{ +public: + CTaskDialogConfig m_tdc; + HWND m_hWnd; // used only in callback functions + +// Constructor + CTaskDialogImpl(HWND hWndParent = NULL) : m_hWnd(NULL) + { + m_tdc.hwndParent = hWndParent; + m_tdc.pfCallback = T::TaskDialogCallback; + m_tdc.lpCallbackData = (LONG_PTR)static_cast(this); + } + +// Operations + HRESULT DoModal(HWND hWndParent = ::GetActiveWindow(), int* pnButton = NULL, int* pnRadioButton = NULL, BOOL* pfVerificationFlagChecked = NULL) + { + if(m_tdc.hwndParent == NULL) + m_tdc.hwndParent = hWndParent; + +#ifdef _WTL_TASKDIALOG_DIRECT + return ::TaskDialogIndirect(&m_tdc, pnButton, pnRadioButton, pfVerificationFlagChecked); +#else + + // This allows apps to run on older versions of Windows + typedef HRESULT (STDAPICALLTYPE *PFN_TaskDialogIndirect)(const TASKDIALOGCONFIG* pTaskConfig, int* pnButton, int* pnRadioButton, BOOL* pfVerificationFlagChecked); + + HRESULT hRet = E_UNEXPECTED; + HMODULE m_hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll")); + if(m_hCommCtrlDLL != NULL) + { + PFN_TaskDialogIndirect pfnTaskDialogIndirect = (PFN_TaskDialogIndirect)::GetProcAddress(m_hCommCtrlDLL, "TaskDialogIndirect"); + if(pfnTaskDialogIndirect != NULL) + hRet = pfnTaskDialogIndirect(&m_tdc, pnButton, pnRadioButton, pfVerificationFlagChecked); + + ::FreeLibrary(m_hCommCtrlDLL); + } + + return hRet; +#endif + } + +// Operations - setting values of TASKDIALOGCONFIG + // common buttons + void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons) + { m_tdc.SetCommonButtons(dwCommonButtons); } + // window title text + void SetWindowTitle(UINT nID) + { m_tdc.SetWindowTitle(nID); } + void SetWindowTitle(LPCWSTR lpstrWindowTitle) + { m_tdc.SetWindowTitle(lpstrWindowTitle); } + // main icon + void SetMainIcon(HICON hIcon) + { m_tdc.SetMainIcon(hIcon); } + void SetMainIcon(UINT nID) + { m_tdc.SetMainIcon(nID); } + void SetMainIcon(LPCWSTR lpstrMainIcon) + { m_tdc.SetMainIcon(lpstrMainIcon); } + // main instruction text + void SetMainInstructionText(UINT nID) + { m_tdc.SetMainInstructionText(nID); } + void SetMainInstructionText(LPCWSTR lpstrMainInstruction) + { m_tdc.SetMainInstructionText(lpstrMainInstruction); } + // content text + void SetContentText(UINT nID) + { m_tdc.SetContentText(nID); } + void SetContentText(LPCWSTR lpstrContent) + { m_tdc.SetContentText(lpstrContent); } + // buttons + void SetButtons(const TASKDIALOG_BUTTON* pButtons, UINT cButtons, int nDefaultButton = 0) + { m_tdc.SetButtons(pButtons, cButtons, nDefaultButton); } + void SetDefaultButton(int nDefaultButton) + { m_tdc.SetDefaultButton(nDefaultButton); } + // radio buttons + void SetRadioButtons(const TASKDIALOG_BUTTON* pRadioButtons, UINT cRadioButtons, int nDefaultRadioButton = 0) + { m_tdc.SetRadioButtons(pRadioButtons, cRadioButtons, nDefaultRadioButton); } + void SetDefaultRadioButton(int nDefaultRadioButton) + { m_tdc.SetDefaultRadioButton(nDefaultRadioButton); } + // verification text + void SetVerificationText(UINT nID) + { m_tdc.SetVerificationText(nID); } + void SetVerificationText(LPCWSTR lpstrVerificationText) + { m_tdc.SetVerificationText(lpstrVerificationText); } + // expanded information text + void SetExpandedInformationText(UINT nID) + { m_tdc.SetExpandedInformationText(nID); } + void SetExpandedInformationText(LPCWSTR lpstrExpandedInformation) + { m_tdc.SetExpandedInformationText(lpstrExpandedInformation); } + // expanded control text + void SetExpandedControlText(UINT nID) + { m_tdc.SetExpandedControlText(nID); } + void SetExpandedControlText(LPCWSTR lpstrExpandedControlText) + { m_tdc.SetExpandedControlText(lpstrExpandedControlText); } + // collapsed control text + void SetCollapsedControlText(UINT nID) + { m_tdc.SetCollapsedControlText(nID); } + void SetCollapsedControlText(LPCWSTR lpstrCollapsedControlText) + { m_tdc.SetCollapsedControlText(lpstrCollapsedControlText); } + // footer icon + void SetFooterIcon(HICON hIcon) + { m_tdc.SetFooterIcon(hIcon); } + void SetFooterIcon(UINT nID) + { m_tdc.SetFooterIcon(nID); } + void SetFooterIcon(LPCWSTR lpstrFooterIcon) + { m_tdc.SetFooterIcon(lpstrFooterIcon); } + // footer text + void SetFooterText(UINT nID) + { m_tdc.SetFooterText(nID); } + void SetFooterText(LPCWSTR lpstrFooterText) + { m_tdc.SetFooterText(lpstrFooterText); } + // width (in DLUs) + void SetWidth(UINT cxWidth) + { m_tdc.SetWidth(cxWidth); } + // modify flags + void ModifyFlags(DWORD dwRemove, DWORD dwAdd) + { m_tdc.ModifyFlags(dwRemove, dwAdd); } + +// Implementation + static HRESULT CALLBACK TaskDialogCallback(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LONG_PTR lpRefData) + { + T* pT = (T*)lpRefData; + ATLASSERT(pT->m_hWnd == NULL || pT->m_hWnd == hWnd); + + BOOL bRet = FALSE; + switch(uMsg) + { + case TDN_DIALOG_CONSTRUCTED: + pT->m_hWnd = hWnd; + pT->OnDialogConstructed(); + break; + case TDN_CREATED: + pT->OnCreated(); + break; + case TDN_BUTTON_CLICKED: + bRet = pT->OnButtonClicked((int)wParam); + break; + case TDN_RADIO_BUTTON_CLICKED: + pT->OnRadioButtonClicked((int)wParam); + break; + case TDN_HYPERLINK_CLICKED: + pT->OnHyperlinkClicked((LPCWSTR)lParam); + break; + case TDN_EXPANDO_BUTTON_CLICKED: + pT->OnExpandoButtonClicked((wParam != 0)); + break; + case TDN_VERIFICATION_CLICKED: + pT->OnVerificationClicked((wParam != 0)); + break; + case TDN_HELP: + pT->OnHelp(); + break; + case TDN_TIMER: + bRet = pT->OnTimer((DWORD)wParam); + break; + case TDN_NAVIGATED: + pT->OnNavigated(); + break; + case TDN_DESTROYED: + pT->OnDestroyed(); + pT->m_hWnd = NULL; + break; + default: + ATLTRACE2(atlTraceUI, 0, _T("Unknown notification received in CTaskDialogImpl::TaskDialogCallback\n")); + break; + } + + return (HRESULT)bRet; + } + +// Overrideables - notification handlers + void OnDialogConstructed() + { + } + + void OnCreated() + { + } + + BOOL OnButtonClicked(int /*nButton*/) + { + return FALSE; // don't prevent dialog to close + } + + void OnRadioButtonClicked(int /*nRadioButton*/) + { + } + + void OnHyperlinkClicked(LPCWSTR /*pszHREF*/) + { + } + + void OnExpandoButtonClicked(bool /*bExpanded*/) + { + } + + void OnVerificationClicked(bool /*bChecked*/) + { + } + + void OnHelp() + { + } + + BOOL OnTimer(DWORD /*dwTickCount*/) + { + return FALSE; // don't reset counter + } + + void OnNavigated() + { + } + + void OnDestroyed() + { + } + +// Commands - valid to call only from handlers + void NavigatePage(TASKDIALOGCONFIG& tdc) + { + ATLASSERT(m_hWnd != NULL); + + tdc.cbSize = sizeof(TASKDIALOGCONFIG); + if(tdc.hwndParent == NULL) + tdc.hwndParent = m_tdc.hwndParent; + tdc.pfCallback = m_tdc.pfCallback; + tdc.lpCallbackData = m_tdc.lpCallbackData; + (TASKDIALOGCONFIG)m_tdc = tdc; + + ::SendMessage(m_hWnd, TDM_NAVIGATE_PAGE, 0, (LPARAM)&tdc); + } + + // modify TASKDIALOGCONFIG values, then call this to update task dialog + void NavigatePage() + { + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, TDM_NAVIGATE_PAGE, 0, (LPARAM)&m_tdc); + } + + void ClickButton(int nButton) + { + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, TDM_CLICK_BUTTON, nButton, 0L); + } + + void SetMarqueeProgressBar(BOOL bMarquee) + { + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, TDM_SET_MARQUEE_PROGRESS_BAR, bMarquee, 0L); + } + + BOOL SetProgressBarState(int nNewState) + { + ATLASSERT(m_hWnd != NULL); + return (BOOL)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_STATE, nNewState, 0L); + } + + DWORD SetProgressBarRange(int nMinRange, int nMaxRange) + { + ATLASSERT(m_hWnd != NULL); + return (DWORD)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_RANGE, 0, MAKELPARAM(nMinRange, nMaxRange)); + } + + int SetProgressBarPos(int nNewPos) + { + ATLASSERT(m_hWnd != NULL); + return (int)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_POS, nNewPos, 0L); + } + + BOOL SetProgressBarMarquee(BOOL bMarquee, UINT uSpeed) + { + ATLASSERT(m_hWnd != NULL); + return (BOOL)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_MARQUEE, bMarquee, uSpeed); + } + + void SetElementText(TASKDIALOG_ELEMENTS element, LPCWSTR lpstrText) + { + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, TDM_SET_ELEMENT_TEXT, element, (LPARAM)lpstrText); + } + + void ClickRadioButton(int nRadioButton) + { + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, TDM_CLICK_RADIO_BUTTON, nRadioButton, 0L); + } + + void EnableButton(int nButton, BOOL bEnable) + { + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, TDM_ENABLE_BUTTON, nButton, bEnable); + } + + void EnableRadioButton(int nButton, BOOL bEnable) + { + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, TDM_ENABLE_RADIO_BUTTON, nButton, bEnable); + } + + void ClickVerification(BOOL bCheck, BOOL bFocus) + { + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, TDM_CLICK_VERIFICATION, bCheck, bFocus); + } + + void UpdateElementText(TASKDIALOG_ELEMENTS element, LPCWSTR lpstrText) + { + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, TDM_UPDATE_ELEMENT_TEXT, element, (LPARAM)lpstrText); + } + + void SetButtonElevationRequiredState(int nButton, BOOL bElevation) + { + ATLASSERT(m_hWnd != NULL); + ::SendMessage(m_hWnd, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, nButton, bElevation); + } + + void UpdateIcon(TASKDIALOG_ICON_ELEMENTS element, HICON hIcon) + { + ATLASSERT(m_hWnd != NULL); +#ifdef _DEBUG + if(element == TDIE_ICON_MAIN) + ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_MAIN) != 0); + else if(element == TDIE_ICON_FOOTER) + ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_FOOTER) != 0); +#endif // _DEBUG + ::SendMessage(m_hWnd, TDM_UPDATE_ICON, element, (LPARAM)hIcon); + } + + void UpdateIcon(TASKDIALOG_ICON_ELEMENTS element, LPCWSTR lpstrIcon) + { + ATLASSERT(m_hWnd != NULL); +#ifdef _DEBUG + if(element == TDIE_ICON_MAIN) + ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_MAIN) == 0); + else if(element == TDIE_ICON_FOOTER) + ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_FOOTER) == 0); +#endif // _DEBUG + ::SendMessage(m_hWnd, TDM_UPDATE_ICON, element, (LPARAM)lpstrIcon); + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CTaskDialog - for non-customized task dialogs + +class CTaskDialog : public CTaskDialogImpl +{ +public: + CTaskDialog(HWND hWndParent = NULL) : CTaskDialogImpl(hWndParent) + { + m_tdc.pfCallback = NULL; + } +}; + +#endif // ((_WIN32_WINNT >= 0x0600) || defined(_WTL_TASKDIALOG)) && !defined(_WIN32_WCE) + +}; // namespace WTL + +#endif // __ATLDLGS_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlfind.h b/Client/Client/GUI/BKWin/wtl/atlfind.h new file mode 100644 index 00000000..b243e038 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlfind.h @@ -0,0 +1,1033 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLFIND_H__ +#define __ATLFIND_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifdef _WIN32_WCE + #error atlfind.h is not supported on Windows CE +#endif + +#ifndef __ATLCTRLS_H__ + #error atlfind.h requires atlctrls.h to be included first +#endif + +#ifndef __ATLDLGS_H__ + #error atlfind.h requires atldlgs.h to be included first +#endif + +#if !((defined(__ATLMISC_H__) && defined(_WTL_USE_CSTRING)) || defined(__ATLSTR_H__)) + #error atlfind.h requires CString (either from ATL's atlstr.h or WTL's atlmisc.h with _WTL_USE_CSTRING) +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CEditFindReplaceImplBase +// CEditFindReplaceImpl +// CRichEditFindReplaceImpl + + +namespace WTL +{ + +/////////////////////////////////////////////////////////////////////////////// +// CEditFindReplaceImplBase - Base class for mixin classes that +// help implement Find/Replace for CEdit or CRichEditCtrl based window classes. + +template +class CEditFindReplaceImplBase +{ +protected: +// Typedefs + typedef CEditFindReplaceImplBase thisClass; + +// Data members + TFindReplaceDialog* m_pFindReplaceDialog; + _CSTRING_NS::CString m_sFindNext, m_sReplaceWith; + BOOL m_bFindOnly, m_bFirstSearch, m_bMatchCase, m_bWholeWord, m_bFindDown; + LONG m_nInitialSearchPos; + HCURSOR m_hOldCursor; + +// Enumerations + enum TranslationTextItem + { + eText_OnReplaceAllMessage = 0, + eText_OnReplaceAllTitle = 1, + eText_OnTextNotFoundMessage = 2, + eText_OnTextNotFoundTitle = 3 + }; + +public: +// Constructors + CEditFindReplaceImplBase() : + m_pFindReplaceDialog(NULL), + m_bFindOnly(TRUE), + m_bFirstSearch(TRUE), + m_bMatchCase(FALSE), + m_bWholeWord(FALSE), + m_bFindDown(TRUE), + m_nInitialSearchPos(0), + m_hOldCursor(NULL) + { + } + +// Message Handlers + BEGIN_MSG_MAP(thisClass) + ALT_MSG_MAP(1) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) + MESSAGE_HANDLER(TFindReplaceDialog::GetFindReplaceMsg(), OnFindReplaceCmd) + COMMAND_ID_HANDLER(ID_EDIT_FIND, OnEditFind) + COMMAND_ID_HANDLER(ID_EDIT_REPEAT, OnEditRepeat) + COMMAND_ID_HANDLER(ID_EDIT_REPLACE, OnEditReplace) + END_MSG_MAP() + + LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + if(m_pFindReplaceDialog != NULL) + { + m_pFindReplaceDialog->SendMessage(WM_CLOSE); + ATLASSERT(m_pFindReplaceDialog == NULL); + } + + bHandled = FALSE; + return 0; + } + + LRESULT OnFindReplaceCmd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + + TFindReplaceDialog* pDialog = TFindReplaceDialog::GetNotifier(lParam); + if(pDialog == NULL) + { + ATLASSERT(FALSE); + ::MessageBeep(MB_ICONERROR); + return 1; + } + ATLASSERT(pDialog == m_pFindReplaceDialog); + + LPFINDREPLACE findReplace = (LPFINDREPLACE)lParam; + if((m_pFindReplaceDialog != NULL) && (findReplace != NULL)) + { + if(pDialog->FindNext()) + { + pT->OnFindNext(pDialog->GetFindString(), pDialog->SearchDown(), + pDialog->MatchCase(), pDialog->MatchWholeWord()); + } + else if(pDialog->ReplaceCurrent()) + { + pT->OnReplaceSel(pDialog->GetFindString(), + pDialog->SearchDown(), pDialog->MatchCase(), pDialog->MatchWholeWord(), + pDialog->GetReplaceString()); + } + else if(pDialog->ReplaceAll()) + { + pT->OnReplaceAll(pDialog->GetFindString(), pDialog->GetReplaceString(), + pDialog->MatchCase(), pDialog->MatchWholeWord()); + } + else if(pDialog->IsTerminating()) + { + // Dialog is going away (but hasn't gone away yet) + // OnFinalMessage will "delete this" + pT->OnTerminatingFindReplaceDialog(m_pFindReplaceDialog); + m_pFindReplaceDialog = NULL; + } + } + + return 0; + } + + LRESULT OnEditFind(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->FindReplace(TRUE); + + return 0; + } + + LRESULT OnEditRepeat(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + + // If the user is holding down SHIFT when hitting F3, we'll + // search in reverse. Otherwise, we'll search forward. + // (be sure to have an accelerator mapped to ID_EDIT_REPEAT + // for both F3 and Shift+F3) + m_bFindDown = !((::GetKeyState(VK_SHIFT) & 0x8000) == 0x8000); + + if(m_sFindNext.IsEmpty()) + { + pT->FindReplace(TRUE); + } + else + { + if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)) + pT->TextNotFound(m_sFindNext); + } + + return 0; + } + + LRESULT OnEditReplace(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& bHandled) + { + T* pT = static_cast(this); + + DWORD style = pT->GetStyle(); + if((style & ES_READONLY) != ES_READONLY) + { + pT->FindReplace(FALSE); + } + else + { + // Don't allow replace when the edit control is read only + bHandled = FALSE; + } + + return 0; + } + +// Operations (overrideable) + TFindReplaceDialog* CreateFindReplaceDialog(BOOL bFindOnly, // TRUE for Find, FALSE for FindReplace + LPCTSTR lpszFindWhat, + LPCTSTR lpszReplaceWith = NULL, + DWORD dwFlags = FR_DOWN, + HWND hWndParent = NULL) + { + // You can override all of this in a derived class + + TFindReplaceDialog* findReplaceDialog = new TFindReplaceDialog(); + if(findReplaceDialog == NULL) + { + ::MessageBeep(MB_ICONHAND); + } + else + { + HWND hWndFindReplace = findReplaceDialog->Create(bFindOnly, + lpszFindWhat, lpszReplaceWith, dwFlags, hWndParent); + if(hWndFindReplace == NULL) + { + delete findReplaceDialog; + findReplaceDialog = NULL; + } + else + { + findReplaceDialog->SetActiveWindow(); + findReplaceDialog->ShowWindow(SW_SHOW); + } + } + + return findReplaceDialog; + } + + void AdjustDialogPosition(HWND hWndDialog) + { + ATLASSERT((hWndDialog != NULL) && ::IsWindow(hWndDialog)); + + T* pT = static_cast(this); + LONG nStartChar = 0, nEndChar = 0; + // Send EM_GETSEL so we can use both Edit and RichEdit + // (CEdit::GetSel uses int&, and CRichEditCtrlT::GetSel uses LONG&) + ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar); + POINT point = pT->PosFromChar(nStartChar); + ::ClientToScreen(pT->GetParent(), &point); + CRect rect; + ::GetWindowRect(hWndDialog, &rect); + if(rect.PtInRect(point)) + { + if(point.y > rect.Height()) + { + rect.OffsetRect(0, point.y - rect.bottom - 20); + } + else + { + int nVertExt = GetSystemMetrics(SM_CYSCREEN); + if(point.y + rect.Height() < nVertExt) + rect.OffsetRect(0, 40 + point.y - rect.top); + } + + ::MoveWindow(hWndDialog, rect.left, rect.top, rect.Width(), rect.Height(), TRUE); + } + } + + DWORD GetFindReplaceDialogFlags(void) const + { + DWORD dwFlags = 0; + + if(m_bFindDown) + dwFlags |= FR_DOWN; + if(m_bMatchCase) + dwFlags |= FR_MATCHCASE; + if(m_bWholeWord) + dwFlags |= FR_WHOLEWORD; + + return dwFlags; + } + + void FindReplace(BOOL bFindOnly) + { + T* pT = static_cast(this); + m_bFirstSearch = TRUE; + if(m_pFindReplaceDialog != NULL) + { + if(m_bFindOnly == bFindOnly) + { + m_pFindReplaceDialog->SetActiveWindow(); + m_pFindReplaceDialog->ShowWindow(SW_SHOW); + return; + } + else + { + m_pFindReplaceDialog->SendMessage(WM_CLOSE); + ATLASSERT(m_pFindReplaceDialog == NULL); + } + } + + ATLASSERT(m_pFindReplaceDialog == NULL); + + _CSTRING_NS::CString findNext; + pT->GetSelText(findNext); + // if selection is empty or spans multiple lines use old find text + if(findNext.IsEmpty() || (findNext.FindOneOf(_T("\n\r")) != -1)) + findNext = m_sFindNext; + _CSTRING_NS::CString replaceWith = m_sReplaceWith; + DWORD dwFlags = pT->GetFindReplaceDialogFlags(); + + m_pFindReplaceDialog = pT->CreateFindReplaceDialog(bFindOnly, + findNext, replaceWith, dwFlags, pT->operator HWND()); + ATLASSERT(m_pFindReplaceDialog != NULL); + if(m_pFindReplaceDialog != NULL) + m_bFindOnly = bFindOnly; + } + + BOOL SameAsSelected(LPCTSTR lpszCompare, BOOL bMatchCase, BOOL /*bWholeWord*/) + { + T* pT = static_cast(this); + + // check length first + size_t nLen = lstrlen(lpszCompare); + LONG nStartChar = 0, nEndChar = 0; + // Send EM_GETSEL so we can use both Edit and RichEdit + // (CEdit::GetSel uses int&, and CRichEditCtrlT::GetSel uses LONG&) + ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar); + if(nLen != (size_t)(nEndChar - nStartChar)) + return FALSE; + + // length is the same, check contents + _CSTRING_NS::CString selectedText; + pT->GetSelText(selectedText); + + return (bMatchCase && selectedText.Compare(lpszCompare) == 0) || + (!bMatchCase && selectedText.CompareNoCase(lpszCompare) == 0); + } + + void TextNotFound(LPCTSTR lpszFind) + { + T* pT = static_cast(this); + m_bFirstSearch = TRUE; + pT->OnTextNotFound(lpszFind); + } + + _CSTRING_NS::CString GetTranslationText(enum TranslationTextItem eItem) const + { + _CSTRING_NS::CString text; + switch(eItem) + { + case eText_OnReplaceAllMessage: + text = _T("Replaced %d occurances of \"%s\" with \"%s\""); + break; + case eText_OnReplaceAllTitle: + text = _T("Replace All"); + break; + case eText_OnTextNotFoundMessage: + text = _T("Unable to find the text \"%s\""); + break; + case eText_OnTextNotFoundTitle: + text = _T("Text not found"); + break; + } + + return text; + } + +// Overrideable Handlers + void OnFindNext(LPCTSTR lpszFind, BOOL bFindDown, BOOL bMatchCase, BOOL bWholeWord) + { + T* pT = static_cast(this); + + m_sFindNext = lpszFind; + m_bMatchCase = bMatchCase; + m_bWholeWord = bWholeWord; + m_bFindDown = bFindDown; + + if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)) + pT->TextNotFound(m_sFindNext); + else + pT->AdjustDialogPosition(m_pFindReplaceDialog->operator HWND()); + } + + void OnReplaceSel(LPCTSTR lpszFind, BOOL bFindDown, BOOL bMatchCase, BOOL bWholeWord, LPCTSTR lpszReplace) + { + T* pT = static_cast(this); + + m_sFindNext = lpszFind; + m_sReplaceWith = lpszReplace; + m_bMatchCase = bMatchCase; + m_bWholeWord = bWholeWord; + m_bFindDown = bFindDown; + + if(pT->SameAsSelected(m_sFindNext, m_bMatchCase, m_bWholeWord)) + pT->ReplaceSel(m_sReplaceWith); + + if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)) + pT->TextNotFound(m_sFindNext); + else + pT->AdjustDialogPosition(m_pFindReplaceDialog->operator HWND()); + } + + void OnReplaceAll(LPCTSTR lpszFind, LPCTSTR lpszReplace, BOOL bMatchCase, BOOL bWholeWord) + { + T* pT = static_cast(this); + + m_sFindNext = lpszFind; + m_sReplaceWith = lpszReplace; + m_bMatchCase = bMatchCase; + m_bWholeWord = bWholeWord; + m_bFindDown = TRUE; + + // no selection or different than what looking for + if(!pT->SameAsSelected(m_sFindNext, m_bMatchCase, m_bWholeWord)) + { + if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)) + { + pT->TextNotFound(m_sFindNext); + return; + } + } + + pT->OnReplaceAllCoreBegin(); + + int replaceCount=0; + do + { + ++replaceCount; + pT->ReplaceSel(m_sReplaceWith); + } while(pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)); + + pT->OnReplaceAllCoreEnd(replaceCount); + } + + void OnReplaceAllCoreBegin() + { + T* pT = static_cast(this); + + m_hOldCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT)); + + pT->HideSelection(TRUE, FALSE); + + } + + void OnReplaceAllCoreEnd(int replaceCount) + { + T* pT = static_cast(this); + pT->HideSelection(FALSE, FALSE); + + ::SetCursor(m_hOldCursor); + + _CSTRING_NS::CString message = pT->GetTranslationText(eText_OnReplaceAllMessage); + if(message.GetLength() > 0) + { + _CSTRING_NS::CString formattedMessage; + formattedMessage.Format(message, + replaceCount, m_sFindNext, m_sReplaceWith); + if(m_pFindReplaceDialog != NULL) + { + m_pFindReplaceDialog->MessageBox(formattedMessage, + pT->GetTranslationText(eText_OnReplaceAllTitle), + MB_OK | MB_ICONINFORMATION | MB_APPLMODAL); + } + else + { + pT->MessageBox(formattedMessage, + pT->GetTranslationText(eText_OnReplaceAllTitle), + MB_OK | MB_ICONINFORMATION | MB_APPLMODAL); + } + } + } + + void OnTextNotFound(LPCTSTR lpszFind) + { + T* pT = static_cast(this); + _CSTRING_NS::CString message = pT->GetTranslationText(eText_OnTextNotFoundMessage); + if(message.GetLength() > 0) + { + _CSTRING_NS::CString formattedMessage; + formattedMessage.Format(message, lpszFind); + if(m_pFindReplaceDialog != NULL) + { + m_pFindReplaceDialog->MessageBox(formattedMessage, + pT->GetTranslationText(eText_OnTextNotFoundTitle), + MB_OK | MB_ICONINFORMATION | MB_APPLMODAL); + } + else + { + pT->MessageBox(formattedMessage, + pT->GetTranslationText(eText_OnTextNotFoundTitle), + MB_OK | MB_ICONINFORMATION | MB_APPLMODAL); + } + } + else + { + ::MessageBeep(MB_ICONHAND); + } + } + + void OnTerminatingFindReplaceDialog(TFindReplaceDialog*& /*findReplaceDialog*/) + { + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CEditFindReplaceImpl - Mixin class for implementing Find/Replace for CEdit +// based window classes. + +// Chain to CEditFindReplaceImpl message map. Your class must also derive from CEdit. +// Example: +// class CMyEdit : public CWindowImpl, +// public CEditFindReplaceImpl +// { +// public: +// BEGIN_MSG_MAP(CMyEdit) +// // your handlers... +// CHAIN_MSG_MAP_ALT(CEditFindReplaceImpl, 1) +// END_MSG_MAP() +// // other stuff... +// }; + +template +class CEditFindReplaceImpl : public CEditFindReplaceImplBase +{ +protected: + typedef CEditFindReplaceImpl thisClass; + typedef CEditFindReplaceImplBase baseClass; + +// Data members + LPTSTR m_pShadowBuffer; // Special shadow buffer only used in some cases. + UINT m_nShadowSize; + int m_bShadowBufferNeeded; // TRUE, FALSE, < 0 => Need to check + +public: +// Constructors + CEditFindReplaceImpl() : + m_pShadowBuffer(NULL), + m_nShadowSize(0), + m_bShadowBufferNeeded(-1) + { + } + + virtual ~CEditFindReplaceImpl() + { + if(m_pShadowBuffer != NULL) + { + delete [] m_pShadowBuffer; + m_pShadowBuffer = NULL; + } + } + +// Message Handlers + BEGIN_MSG_MAP(thisClass) + ALT_MSG_MAP(1) + CHAIN_MSG_MAP_ALT(baseClass, 1) + END_MSG_MAP() + +// Operations + // Supported only for RichEdit, so this does nothing for Edit + void HideSelection(BOOL /*bHide*/ = TRUE, BOOL /*bChangeStyle*/ = FALSE) + { + } + +// Operations (overrideable) + BOOL FindTextSimple(LPCTSTR lpszFind, BOOL bMatchCase, BOOL bWholeWord, BOOL bFindDown = TRUE) + { + T* pT = static_cast(this); + + ATLASSERT(lpszFind != NULL); + ATLASSERT(*lpszFind != _T('\0')); + + UINT nLen = pT->GetBufferLength(); + int nStartChar = 0, nEndChar = 0; + pT->GetSel(nStartChar, nEndChar); + UINT nStart = nStartChar; + int iDir = bFindDown ? +1 : -1; + + // can't find a match before the first character + if(nStart == 0 && iDir < 0) + return FALSE; + + LPCTSTR lpszText = pT->LockBuffer(); + + bool isDBCS = false; +#ifdef _MBCS + CPINFO info = { 0 }; + ::GetCPInfo(::GetOEMCP(), &info); + isDBCS = (info.MaxCharSize > 1); +#endif + + if(iDir < 0) + { + // always go back one for search backwards + nStart -= int((lpszText + nStart) - ::CharPrev(lpszText, lpszText + nStart)); + } + else if(nStartChar != nEndChar && pT->SameAsSelected(lpszFind, bMatchCase, bWholeWord)) + { + // easy to go backward/forward with SBCS +#ifndef _UNICODE + if(::IsDBCSLeadByte(lpszText[nStart])) + nStart++; +#endif + nStart += iDir; + } + + // handle search with nStart past end of buffer + UINT nLenFind = ::lstrlen(lpszFind); + if(nStart + nLenFind - 1 >= nLen) + { + if(iDir < 0 && nLen >= nLenFind) + { + if(isDBCS) + { + // walk back to previous character n times + nStart = nLen; + int n = nLenFind; + while(n--) + { + nStart -= int((lpszText + nStart) - ::CharPrev(lpszText, lpszText + nStart)); + } + } + else + { + // single-byte character set is easy and fast + nStart = nLen - nLenFind; + } + ATLASSERT(nStart + nLenFind - 1 <= nLen); + } + else + { + pT->UnlockBuffer(); + return FALSE; + } + } + + // start the search at nStart + LPCTSTR lpsz = lpszText + nStart; + typedef int (WINAPI* CompareProc)(LPCTSTR str1, LPCTSTR str2); + CompareProc pfnCompare = bMatchCase ? lstrcmp : lstrcmpi; + + if(isDBCS) + { + // double-byte string search + LPCTSTR lpszStop = NULL; + if(iDir > 0) + { + // start at current and find _first_ occurrance + lpszStop = lpszText + nLen - nLenFind + 1; + } + else + { + // start at top and find _last_ occurrance + lpszStop = lpsz; + lpsz = lpszText; + } + + LPCTSTR lpszFound = NULL; + while(lpsz <= lpszStop) + { +#ifndef _UNICODE + if(!bMatchCase || (*lpsz == *lpszFind && (!::IsDBCSLeadByte(*lpsz) || lpsz[1] == lpszFind[1]))) +#else + if(!bMatchCase || (*lpsz == *lpszFind && lpsz[1] == lpszFind[1])) +#endif + { + LPTSTR lpch = (LPTSTR)(lpsz + nLenFind); + TCHAR chSave = *lpch; + *lpch = _T('\0'); + int nResult = (*pfnCompare)(lpsz, lpszFind); + *lpch = chSave; + if(nResult == 0) + { + lpszFound = lpsz; + if(iDir > 0) + break; + } + } + lpsz = ::CharNext(lpsz); + } + pT->UnlockBuffer(); + + if(lpszFound != NULL) + { + int n = (int)(lpszFound - lpszText); + pT->SetSel(n, n + nLenFind); + return TRUE; + } + } + else + { + // single-byte string search + UINT nCompare; + if(iDir < 0) + nCompare = (UINT)(lpsz - lpszText) + 1; + else + nCompare = nLen - (UINT)(lpsz - lpszText) - nLenFind + 1; + + while(nCompare > 0) + { + ATLASSERT(lpsz >= lpszText); + ATLASSERT(lpsz + nLenFind - 1 <= lpszText + nLen - 1); + + LPSTR lpch = (LPSTR)(lpsz + nLenFind); + char chSave = *lpch; + *lpch = '\0'; + int nResult = (*pfnCompare)(lpsz, lpszFind); + *lpch = chSave; + if(nResult == 0) + { + pT->UnlockBuffer(); + int n = (int)(lpsz - lpszText); + pT->SetSel(n, n + nLenFind); + return TRUE; + } + + // restore character at end of search + *lpch = chSave; + + // move on to next substring + nCompare--; + lpsz += iDir; + } + pT->UnlockBuffer(); + } + + return FALSE; + } + + LPCTSTR LockBuffer() const + { + const T* pT = static_cast(this); + + ATLASSERT(pT->m_hWnd != NULL); + + BOOL useShadowBuffer = pT->UseShadowBuffer(); + if(useShadowBuffer) + { + if(m_pShadowBuffer == NULL || pT->GetModify()) + { + ATLASSERT(m_pShadowBuffer != NULL || m_nShadowSize == 0); + UINT nSize = pT->GetWindowTextLength() + 1; + if(nSize > m_nShadowSize) + { + // need more room for shadow buffer + T* pThisNoConst = const_cast(pT); + delete[] m_pShadowBuffer; + pThisNoConst->m_pShadowBuffer = NULL; + pThisNoConst->m_nShadowSize = 0; + pThisNoConst->m_pShadowBuffer = new TCHAR[nSize]; + pThisNoConst->m_nShadowSize = nSize; + } + + // update the shadow buffer with GetWindowText + ATLASSERT(m_nShadowSize >= nSize); + ATLASSERT(m_pShadowBuffer != NULL); + pT->GetWindowText(m_pShadowBuffer, nSize); + } + + return m_pShadowBuffer; + } + + HLOCAL hLocal = pT->GetHandle(); + ATLASSERT(hLocal != NULL); + LPCTSTR lpszText = (LPCTSTR)::LocalLock(hLocal); + ATLASSERT(lpszText != NULL); + + return lpszText; + } + + void UnlockBuffer() const + { + const T* pT = static_cast(this); + + ATLASSERT(pT->m_hWnd != NULL); + + BOOL useShadowBuffer = pT->UseShadowBuffer(); + if(!useShadowBuffer) + { + HLOCAL hLocal = pT->GetHandle(); + ATLASSERT(hLocal != NULL); + ::LocalUnlock(hLocal); + } + } + + UINT GetBufferLength() const + { + const T* pT = static_cast(this); + + ATLASSERT(pT->m_hWnd != NULL); + UINT nLen = 0; + LPCTSTR lpszText = pT->LockBuffer(); + if(lpszText != NULL) + nLen = ::lstrlen(lpszText); + pT->UnlockBuffer(); + + return nLen; + } + + LONG EndOfLine(LPCTSTR lpszText, UINT nLen, UINT nIndex) const + { + LPCTSTR lpsz = lpszText + nIndex; + LPCTSTR lpszStop = lpszText + nLen; + while(lpsz < lpszStop && *lpsz != _T('\r')) + ++lpsz; + return LONG(lpsz - lpszText); + } + + LONG GetSelText(_CSTRING_NS::CString& strText) const + { + const T* pT = static_cast(this); + + int nStartChar = 0, nEndChar = 0; + pT->GetSel(nStartChar, nEndChar); + ATLASSERT((UINT)nEndChar <= pT->GetBufferLength()); + LPCTSTR lpszText = pT->LockBuffer(); + LONG nLen = pT->EndOfLine(lpszText, nEndChar, nStartChar) - nStartChar; + SecureHelper::memcpy_x(strText.GetBuffer(nLen), nLen * sizeof(TCHAR), lpszText + nStartChar, nLen * sizeof(TCHAR)); + strText.ReleaseBuffer(nLen); + pT->UnlockBuffer(); + + return nLen; + } + + BOOL UseShadowBuffer(void) const + { + const T* pT = static_cast(this); + + if(pT->m_bShadowBufferNeeded < 0) + { + T* pThisNoConst = const_cast(pT); + + OSVERSIONINFO ovi = { 0 }; + ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + ::GetVersionEx(&ovi); + + bool bWin9x = (ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); + if(bWin9x) + { + // Windows 95, 98, ME + // Under Win9x, it is necessary to maintain a shadow buffer. + // It is only updated when the control contents have been changed. + pThisNoConst->m_bShadowBufferNeeded = TRUE; + } + else + { + // Windows NT, 2000, XP, etc. + pThisNoConst->m_bShadowBufferNeeded = FALSE; + +#ifndef _UNICODE + // On Windows XP (or later), if common controls version 6 is in use + // (such as via theming), then EM_GETHANDLE will always return a UNICODE string. + // If theming is enabled and Common Controls version 6 is in use, + // you're really not suppose to superclass or subclass common controls + // with an ANSI windows procedure (so its best to only theme if you use UNICODE). + // Using a shadow buffer uses GetWindowText instead, so it solves + // this problem for us (although it makes it a little less efficient). + + if((ovi.dwMajorVersion == 5 && ovi.dwMinorVersion >= 1) || (ovi.dwMajorVersion > 5)) + { + // We use DLLVERSIONINFO_private so we don't have to depend on shlwapi.h + typedef struct _DLLVERSIONINFO_private + { + DWORD cbSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwBuildNumber; + DWORD dwPlatformID; + } DLLVERSIONINFO_private; + + HMODULE hModule = ::LoadLibrary("comctl32.dll"); + if(hModule != NULL) + { + typedef HRESULT (CALLBACK *LPFN_DllGetVersion)(DLLVERSIONINFO_private *); + LPFN_DllGetVersion fnDllGetVersion = (LPFN_DllGetVersion)::GetProcAddress(hModule, "DllGetVersion"); + if(fnDllGetVersion != NULL) + { + DLLVERSIONINFO_private version = { 0 }; + version.cbSize = sizeof(DLLVERSIONINFO_private); + if(SUCCEEDED(fnDllGetVersion(&version))) + { + if(version.dwMajorVersion >= 6) + { + pThisNoConst->m_bShadowBufferNeeded = TRUE; + + ATLTRACE2(atlTraceUI, 0, _T("Warning: You have compiled for MBCS/ANSI but are using common controls version 6 or later (likely through a manifest file).\r\n")); + ATLTRACE2(atlTraceUI, 0, _T("If you use common controls version 6 or later, you should only do so for UNICODE builds.\r\n")); + } + } + } + + ::FreeLibrary(hModule); + hModule = NULL; + } + } +#endif // !_UNICODE + } + } + + return (pT->m_bShadowBufferNeeded == TRUE); + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CRichEditFindReplaceImpl - Mixin class for implementing Find/Replace for CRichEditCtrl +// based window classes. + +// Chain to CRichEditFindReplaceImpl message map. Your class must also derive from CRichEditCtrl. +// Example: +// class CMyRichEdit : public CWindowImpl, +// public CRichEditFindReplaceImpl +// { +// public: +// BEGIN_MSG_MAP(CMyRichEdit) +// // your handlers... +// CHAIN_MSG_MAP_ALT(CRichEditFindReplaceImpl, 1) +// END_MSG_MAP() +// // other stuff... +// }; + +template +class CRichEditFindReplaceImpl : public CEditFindReplaceImplBase +{ +protected: + typedef CRichEditFindReplaceImpl thisClass; + typedef CEditFindReplaceImplBase baseClass; + +public: + BEGIN_MSG_MAP(thisClass) + ALT_MSG_MAP(1) + CHAIN_MSG_MAP_ALT(baseClass, 1) + END_MSG_MAP() + +// Operations (overrideable) + BOOL FindTextSimple(LPCTSTR lpszFind, BOOL bMatchCase, BOOL bWholeWord, BOOL bFindDown = TRUE) + { + T* pT = static_cast(this); + + ATLASSERT(lpszFind != NULL); + FINDTEXTEX ft = { 0 }; + + pT->GetSel(ft.chrg); + if(m_bFirstSearch) + { + if(bFindDown) + m_nInitialSearchPos = ft.chrg.cpMin; + else + m_nInitialSearchPos = ft.chrg.cpMax; + m_bFirstSearch = FALSE; + } + +#if (_RICHEDIT_VER >= 0x0200) + ft.lpstrText = (LPTSTR)lpszFind; +#else // !(_RICHEDIT_VER >= 0x0200) + USES_CONVERSION; + ft.lpstrText = T2A((LPTSTR)lpszFind); +#endif // !(_RICHEDIT_VER >= 0x0200) + + if(ft.chrg.cpMin != ft.chrg.cpMax) // i.e. there is a selection + { + if(bFindDown) + { + ft.chrg.cpMin++; + } + else + { + // won't wraparound backwards + ft.chrg.cpMin = max(ft.chrg.cpMin, 0); + } + } + + DWORD dwFlags = bMatchCase ? FR_MATCHCASE : 0; + dwFlags |= bWholeWord ? FR_WHOLEWORD : 0; + + ft.chrg.cpMax = pT->GetTextLength() + m_nInitialSearchPos; + + if(bFindDown) + { + if(m_nInitialSearchPos >= 0) + ft.chrg.cpMax = pT->GetTextLength(); + + dwFlags |= FR_DOWN; + ATLASSERT(ft.chrg.cpMax >= ft.chrg.cpMin); + } + else + { + if(m_nInitialSearchPos >= 0) + ft.chrg.cpMax = 0; + + dwFlags &= ~FR_DOWN; + ATLASSERT(ft.chrg.cpMax <= ft.chrg.cpMin); + } + + BOOL bRet = FALSE; + + if(pT->FindAndSelect(dwFlags, ft) != -1) + { + bRet = TRUE; // we found the text + } + else if(m_nInitialSearchPos > 0) + { + // if the original starting point was not the beginning + // of the buffer and we haven't already been here + if(bFindDown) + { + ft.chrg.cpMin = 0; + ft.chrg.cpMax = m_nInitialSearchPos; + } + else + { + ft.chrg.cpMin = pT->GetTextLength(); + ft.chrg.cpMax = m_nInitialSearchPos; + } + m_nInitialSearchPos = m_nInitialSearchPos - pT->GetTextLength(); + + bRet = (pT->FindAndSelect(dwFlags, ft) != -1) ? TRUE : FALSE; + } + + return bRet; + } + + long FindAndSelect(DWORD dwFlags, FINDTEXTEX& ft) + { + T* pT = static_cast(this); + LONG index = pT->FindText(dwFlags, ft); + if(index != -1) // i.e. we found something + pT->SetSel(ft.chrgText); + + return index; + } +}; + +}; // namespace WTL + +#endif // __ATLFIND_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlframe.h b/Client/Client/GUI/BKWin/wtl/atlframe.h new file mode 100644 index 00000000..3fd8197f --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlframe.h @@ -0,0 +1,3462 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLFRAME_H__ +#define __ATLFRAME_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifndef __ATLAPP_H__ + #error atlframe.h requires atlapp.h to be included first +#endif + +#ifndef __ATLWIN_H__ + #error atlframe.h requires atlwin.h to be included first +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CFrameWindowImpl +// CMDIWindow +// CMDIFrameWindowImpl +// CMDIChildWindowImpl +// COwnerDraw +// CUpdateUIBase +// CUpdateUI +// CDynamicUpdateUI +// CDialogResize +// CDoubleBufferImpl +// CDoubleBufferWindowImpl +// +// Global functions: +// AtlCreateSimpleToolBar() + + +namespace WTL +{ + +/////////////////////////////////////////////////////////////////////////////// +// CFrameWndClassInfo - Manages frame window Windows class information + +class CFrameWndClassInfo +{ +public: +#ifndef _WIN32_WCE + enum { cchAutoName = 5 + sizeof(void*) * 2 }; // sizeof(void*) * 2 is the number of digits %p outputs + WNDCLASSEX m_wc; +#else // CE specific + enum { cchAutoName = MAX_PATH }; // MAX_PATH because this can be set in the wizard generated CMainFrame::ActivatePreviousInstance to a user defined string. + WNDCLASS m_wc; +#endif // !_WIN32_WCE + LPCTSTR m_lpszOrigName; + WNDPROC pWndProc; + LPCTSTR m_lpszCursorID; + BOOL m_bSystemCursor; + ATOM m_atom; + TCHAR m_szAutoName[cchAutoName]; + UINT m_uCommonResourceID; + +#ifndef _WIN32_WCE + ATOM Register(WNDPROC* pProc) + { + if (m_atom == 0) + { + CWindowCreateCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n")); + ATLASSERT(FALSE); + return 0; + } + + if(m_atom == 0) + { + HINSTANCE hInst = ModuleHelper::GetModuleInstance(); + + if (m_lpszOrigName != NULL) + { + ATLASSERT(pProc != NULL); + LPCTSTR lpsz = m_wc.lpszClassName; + WNDPROC proc = m_wc.lpfnWndProc; + + WNDCLASSEX wc = { 0 }; + wc.cbSize = sizeof(WNDCLASSEX); + // try process local class first + if(!::GetClassInfoEx(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc)) + { + // try global class + if(!::GetClassInfoEx(NULL, m_lpszOrigName, &wc)) + { + lock.Unlock(); + return 0; + } + } + m_wc = wc; + pWndProc = m_wc.lpfnWndProc; + m_wc.lpszClassName = lpsz; + m_wc.lpfnWndProc = proc; + } + else + { + m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID); + } + + m_wc.hInstance = hInst; + m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes + if (m_wc.lpszClassName == NULL) + { +#if (_WIN32_WINNT >= 0x0500) || defined(_WIN64) + SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%p"), &m_wc); +#else // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64)) + SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc); +#endif // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64)) + m_wc.lpszClassName = m_szAutoName; + } + + WNDCLASSEX wcTemp = m_wc; + m_atom = (ATOM)::GetClassInfoEx(m_wc.hInstance, m_wc.lpszClassName, &wcTemp); + if (m_atom == 0) + { + if(m_uCommonResourceID != 0) // use it if not zero + { + m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR); + m_wc.hIconSm = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + } + m_atom = ::RegisterClassEx(&m_wc); + } + } + + lock.Unlock(); + } + + if (m_lpszOrigName != NULL) + { + ATLASSERT(pProc != NULL); + ATLASSERT(pWndProc != NULL); + *pProc = pWndProc; + } + + return m_atom; + } +#else // CE specific + ATOM Register(WNDPROC* pProc) + { + if (m_atom == 0) + { + CWindowCreateCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n")); + ATLASSERT(FALSE); + return 0; + } + + if(m_atom == 0) + { + HINSTANCE hInst = ModuleHelper::GetModuleInstance(); + + if (m_lpszOrigName != NULL) + { + ATLASSERT(pProc != NULL); + LPCTSTR lpsz = m_wc.lpszClassName; + WNDPROC proc = m_wc.lpfnWndProc; + + WNDCLASS wc = { 0 }; + // try process local class first + if(!::GetClassInfo(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc)) + { + // try global class + if(!::GetClassInfo(NULL, m_lpszOrigName, &wc)) + { + lock.Unlock(); + return 0; + } + } + m_wc = wc; + pWndProc = m_wc.lpfnWndProc; + m_wc.lpszClassName = lpsz; + m_wc.lpfnWndProc = proc; + } + else + { +#if defined(GWES_CURSOR) || defined(GWES_MCURSOR) + m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID); +#else // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR)) + m_wc.hCursor = NULL; +#endif // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR)) + } + + m_wc.hInstance = hInst; + m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes + if (m_wc.lpszClassName == NULL) + { + wsprintf(m_szAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc); + m_wc.lpszClassName = m_szAutoName; + } + + WNDCLASS wcTemp = m_wc; + m_atom = (ATOM)::GetClassInfo(m_wc.hInstance, m_wc.lpszClassName, &wcTemp); + if (m_atom == 0) + { + if(m_uCommonResourceID != 0) // use it if not zero + m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR); + m_atom = ::RegisterClass(&m_wc); + } + } + + lock.Unlock(); + } + + if (m_lpszOrigName != NULL) + { + ATLASSERT(pProc != NULL); + ATLASSERT(pWndProc != NULL); + *pProc = pWndProc; + } + + return m_atom; + } +#endif // _WIN32_WCE +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Macros for declaring frame window WNDCLASS + +#ifndef _WIN32_WCE + +#define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \ +static WTL::CFrameWndClassInfo& GetWndClassInfo() \ +{ \ + static WTL::CFrameWndClassInfo wc = \ + { \ + { sizeof(WNDCLASSEX), 0, StartWindowProc, \ + 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \ + NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ + }; \ + return wc; \ +} + +#define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \ +static WTL::CFrameWndClassInfo& GetWndClassInfo() \ +{ \ + static WTL::CFrameWndClassInfo wc = \ + { \ + { sizeof(WNDCLASSEX), style, StartWindowProc, \ + 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \ + NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ + }; \ + return wc; \ +} + +#define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \ +static WTL::CFrameWndClassInfo& GetWndClassInfo() \ +{ \ + static WTL::CFrameWndClassInfo wc = \ + { \ + { sizeof(WNDCLASSEX), 0, StartWindowProc, \ + 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \ + OrigWndClassName, NULL, NULL, TRUE, 0, _T(""), uCommonResourceID \ + }; \ + return wc; \ +} + +#else // CE specific + +#define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \ +static WTL::CFrameWndClassInfo& GetWndClassInfo() \ +{ \ + static WTL::CFrameWndClassInfo wc = \ + { \ + { 0, StartWindowProc, \ + 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName }, \ + NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ + }; \ + return wc; \ +} + +#define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \ +static WTL::CFrameWndClassInfo& GetWndClassInfo() \ +{ \ + static WTL::CFrameWndClassInfo wc = \ + { \ + { style, StartWindowProc, \ + 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \ + NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ + }; \ + return wc; \ +} + +#define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \ +static WTL::CFrameWndClassInfo& GetWndClassInfo() \ +{ \ + static WTL::CFrameWndClassInfo wc = \ + { \ + { NULL, StartWindowProc, \ + 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName }, \ + OrigWndClassName, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ + }; \ + return wc; \ +} + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CFrameWindowImpl + +// Client window command chaining macro (only for frame windows) +#define CHAIN_CLIENT_COMMANDS() \ + if(uMsg == WM_COMMAND && m_hWndClient != NULL) \ + ::SendMessage(m_hWndClient, uMsg, wParam, lParam); + +// standard toolbar styles +#define ATL_SIMPLE_TOOLBAR_STYLE \ + (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS) +// toolbar in a rebar pane +#define ATL_SIMPLE_TOOLBAR_PANE_STYLE \ + (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT) +// standard rebar styles +#if (_WIN32_IE >= 0x0400) + #define ATL_SIMPLE_REBAR_STYLE \ + (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE) +#else + #define ATL_SIMPLE_REBAR_STYLE \ + (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS) +#endif // !(_WIN32_IE >= 0x0400) +// rebar without borders +#if (_WIN32_IE >= 0x0400) + #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \ + (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE | CCS_NODIVIDER) +#else + #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \ + (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | CCS_NODIVIDER) +#endif // !(_WIN32_IE >= 0x0400) + +// command bar support +#if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) + +#define CBRM_GETCMDBAR (WM_USER + 301) // returns command bar HWND +#define CBRM_GETMENU (WM_USER + 302) // returns loaded or attached menu +#define CBRM_TRACKPOPUPMENU (WM_USER + 303) // displays a popup menu + +struct _AtlFrameWnd_CmdBarPopupMenu +{ + int cbSize; + HMENU hMenu; + UINT uFlags; + int x; + int y; + LPTPMPARAMS lptpm; +}; + +#define CBRPOPUPMENU _AtlFrameWnd_CmdBarPopupMenu + +#endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) + + +template +class ATL_NO_VTABLE CFrameWindowImplBase : public ATL::CWindowImplBaseT< TBase, TWinTraits > +{ +public: + DECLARE_FRAME_WND_CLASS(NULL, 0) + +// Data members + HWND m_hWndToolBar; + HWND m_hWndStatusBar; + HWND m_hWndClient; + + HACCEL m_hAccel; + +#ifdef _WIN32_WCE + HWND m_hWndCECommandBar; +#endif // _WIN32_WCE + + struct _AtlToolBarData + { + WORD wVersion; + WORD wWidth; + WORD wHeight; + WORD wItemCount; + //WORD aItems[wItemCount] + + WORD* items() + { return (WORD*)(this+1); } + }; + +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + struct _ChevronMenuInfo + { + HMENU hMenu; + LPNMREBARCHEVRON lpnm; + bool bCmdBar; + }; +#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + +// Constructor + CFrameWindowImplBase() : +#ifdef _WIN32_WCE + m_hWndCECommandBar(NULL), +#endif // _WIN32_WCE + m_hWndToolBar(NULL), + m_hWndStatusBar(NULL), + m_hWndClient(NULL), + m_hAccel(NULL) + { } + +// Methods + HWND Create(HWND hWndParent, ATL::_U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, ATL::_U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam) + { + ATLASSERT(m_hWnd == NULL); + + if(atom == 0) + return NULL; + + ModuleHelper::AddCreateWndData(&m_thunk.cd, this); + + if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD)) + MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this; + if(rect.m_lpRect == NULL) + rect.m_lpRect = &TBase::rcDefault; + + HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName, + dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left, + rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu, + ModuleHelper::GetModuleInstance(), lpCreateParam); + + ATLASSERT(hWnd == NULL || m_hWnd == hWnd); + + return hWnd; + } + + static HWND CreateSimpleToolBarCtrl(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE, + DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) + { + HINSTANCE hInst = ModuleHelper::GetResourceInstance(); + HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nResourceID), RT_TOOLBAR); + if (hRsrc == NULL) + return NULL; + + HGLOBAL hGlobal = ::LoadResource(hInst, hRsrc); + if (hGlobal == NULL) + return NULL; + + _AtlToolBarData* pData = (_AtlToolBarData*)::LockResource(hGlobal); + if (pData == NULL) + return NULL; + ATLASSERT(pData->wVersion == 1); + + WORD* pItems = pData->items(); + int nItems = pData->wItemCount + (bInitialSeparator ? 1 : 0); + CTempBuffer buff; + TBBUTTON* pTBBtn = buff.Allocate(nItems); + ATLASSERT(pTBBtn != NULL); + if(pTBBtn == NULL) + return NULL; + + const int cxSeparator = 8; + + // set initial separator (half width) + if(bInitialSeparator) + { + pTBBtn[0].iBitmap = cxSeparator / 2; + pTBBtn[0].idCommand = 0; + pTBBtn[0].fsState = 0; + pTBBtn[0].fsStyle = TBSTYLE_SEP; + pTBBtn[0].dwData = 0; + pTBBtn[0].iString = 0; + } + + int nBmp = 0; + for(int i = 0, j = bInitialSeparator ? 1 : 0; i < pData->wItemCount; i++, j++) + { + if(pItems[i] != 0) + { + pTBBtn[j].iBitmap = nBmp++; + pTBBtn[j].idCommand = pItems[i]; + pTBBtn[j].fsState = TBSTATE_ENABLED; + pTBBtn[j].fsStyle = TBSTYLE_BUTTON; + pTBBtn[j].dwData = 0; + pTBBtn[j].iString = 0; + } + else + { + pTBBtn[j].iBitmap = cxSeparator; + pTBBtn[j].idCommand = 0; + pTBBtn[j].fsState = 0; + pTBBtn[j].fsStyle = TBSTYLE_SEP; + pTBBtn[j].dwData = 0; + pTBBtn[j].iString = 0; + } + } + +#ifndef _WIN32_WCE + HWND hWnd = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL); + if(hWnd == NULL) + { + ATLASSERT(FALSE); + return NULL; + } +#else // CE specific + dwStyle; + nID; + // The toolbar must go onto the existing CommandBar or MenuBar + HWND hWnd = hWndParent; +#endif // _WIN32_WCE + + ::SendMessage(hWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L); + + // check if font is taller than our bitmaps + CFontHandle font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0L); + if(font.IsNull()) + font = AtlGetDefaultGuiFont(); + LOGFONT lf = { 0 }; + font.GetLogFont(lf); + WORD cyFontHeight = (WORD)abs(lf.lfHeight); + +#ifndef _WIN32_WCE + WORD bitsPerPixel = AtlGetBitmapResourceBitsPerPixel(nResourceID); + if(bitsPerPixel > 4) + { + COLORREF crMask = CLR_DEFAULT; + if(bitsPerPixel == 32) + { + // 32-bit color bitmap with alpha channel (valid for Windows XP and later) + crMask = CLR_NONE; + } + HIMAGELIST hImageList = ImageList_LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nResourceID), pData->wWidth, 1, crMask, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_DEFAULTSIZE); + ATLASSERT(hImageList != NULL); + ::SendMessage(hWnd, TB_SETIMAGELIST, 0, (LPARAM)hImageList); + } + else +#endif // !_WIN32_WCE + { + TBADDBITMAP tbab = { 0 }; + tbab.hInst = hInst; + tbab.nID = nResourceID; + ::SendMessage(hWnd, TB_ADDBITMAP, nBmp, (LPARAM)&tbab); + } + + ::SendMessage(hWnd, TB_ADDBUTTONS, nItems, (LPARAM)pTBBtn); + ::SendMessage(hWnd, TB_SETBITMAPSIZE, 0, MAKELONG(pData->wWidth, max(pData->wHeight, cyFontHeight))); + const int cxyButtonMargin = 7; + ::SendMessage(hWnd, TB_SETBUTTONSIZE, 0, MAKELONG(pData->wWidth + cxyButtonMargin, max(pData->wHeight, cyFontHeight) + cxyButtonMargin)); + + return hWnd; + } + +#ifndef _WIN32_WCE + static HWND CreateSimpleReBarCtrl(HWND hWndParent, DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) + { + // Ensure style combinations for proper rebar painting + if(dwStyle & CCS_NODIVIDER && dwStyle & WS_BORDER) + dwStyle &= ~WS_BORDER; + else if(!(dwStyle & WS_BORDER) && !(dwStyle & CCS_NODIVIDER)) + dwStyle |= CCS_NODIVIDER; + + // Create rebar window + HWND hWndReBar = ::CreateWindowEx(0, REBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL); + if(hWndReBar == NULL) + { + ATLTRACE2(atlTraceUI, 0, _T("Failed to create rebar.\n")); + return NULL; + } + + // Initialize and send the REBARINFO structure + REBARINFO rbi = { 0 }; + rbi.cbSize = sizeof(REBARINFO); + rbi.fMask = 0; + if(!::SendMessage(hWndReBar, RB_SETBARINFO, 0, (LPARAM)&rbi)) + { + ATLTRACE2(atlTraceUI, 0, _T("Failed to initialize rebar.\n")); + ::DestroyWindow(hWndReBar); + return NULL; + } + + return hWndReBar; + } + + BOOL CreateSimpleReBar(DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) + { + ATLASSERT(!::IsWindow(m_hWndToolBar)); + m_hWndToolBar = CreateSimpleReBarCtrl(m_hWnd, dwStyle, nID); + return (m_hWndToolBar != NULL); + } + + static BOOL AddSimpleReBarBandCtrl(HWND hWndReBar, HWND hWndBand, int nID = 0, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE) + { + ATLASSERT(::IsWindow(hWndReBar)); // must be already created +#ifdef _DEBUG + // block - check if this is really a rebar + { + TCHAR lpszClassName[sizeof(REBARCLASSNAME)] = { 0 }; + ::GetClassName(hWndReBar, lpszClassName, sizeof(REBARCLASSNAME)); + ATLASSERT(lstrcmp(lpszClassName, REBARCLASSNAME) == 0); + } +#endif // _DEBUG + ATLASSERT(::IsWindow(hWndBand)); // must be already created + + // Get number of buttons on the toolbar + int nBtnCount = (int)::SendMessage(hWndBand, TB_BUTTONCOUNT, 0, 0L); + + // Set band info structure + REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() }; +#if (_WIN32_IE >= 0x0400) + rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE | RBBIM_IDEALSIZE; +#else + rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE; +#endif // !(_WIN32_IE >= 0x0400) + if(lpstrTitle != NULL) + rbBand.fMask |= RBBIM_TEXT; + rbBand.fStyle = RBBS_CHILDEDGE; +#if (_WIN32_IE >= 0x0500) + if(nBtnCount > 0) // add chevron style for toolbar with buttons + rbBand.fStyle |= RBBS_USECHEVRON; +#endif // (_WIN32_IE >= 0x0500) + if(bNewRow) + rbBand.fStyle |= RBBS_BREAK; + + rbBand.lpText = (LPTSTR)lpstrTitle; + rbBand.hwndChild = hWndBand; + if(nID == 0) // calc band ID + nID = ATL_IDW_BAND_FIRST + (int)::SendMessage(hWndReBar, RB_GETBANDCOUNT, 0, 0L); + rbBand.wID = nID; + + // Calculate the size of the band + BOOL bRet = FALSE; + RECT rcTmp = { 0 }; + if(nBtnCount > 0) + { + bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, nBtnCount - 1, (LPARAM)&rcTmp); + ATLASSERT(bRet); + rbBand.cx = (cxWidth != 0) ? cxWidth : rcTmp.right; + rbBand.cyMinChild = rcTmp.bottom - rcTmp.top; + if(bFullWidthAlways) + { + rbBand.cxMinChild = rbBand.cx; + } + else if(lpstrTitle == NULL) + { + bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, 0, (LPARAM)&rcTmp); + ATLASSERT(bRet); + rbBand.cxMinChild = rcTmp.right; + } + else + { + rbBand.cxMinChild = 0; + } + } + else // no buttons, either not a toolbar or really has no buttons + { + bRet = ::GetWindowRect(hWndBand, &rcTmp); + ATLASSERT(bRet); + rbBand.cx = (cxWidth != 0) ? cxWidth : (rcTmp.right - rcTmp.left); + rbBand.cxMinChild = bFullWidthAlways ? rbBand.cx : 0; + rbBand.cyMinChild = rcTmp.bottom - rcTmp.top; + } + +#if (_WIN32_IE >= 0x0400) + rbBand.cxIdeal = rbBand.cx; +#endif // (_WIN32_IE >= 0x0400) + + // Add the band + LRESULT lRes = ::SendMessage(hWndReBar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand); + if(lRes == 0) + { + ATLTRACE2(atlTraceUI, 0, _T("Failed to add a band to the rebar.\n")); + return FALSE; + } + +#if (_WIN32_IE >= 0x0501) + DWORD dwExStyle = (DWORD)::SendMessage(hWndBand, TB_GETEXTENDEDSTYLE, 0, 0L); + ::SendMessage(hWndBand, TB_SETEXTENDEDSTYLE, 0, dwExStyle | TBSTYLE_EX_HIDECLIPPEDBUTTONS); +#endif // (_WIN32_IE >= 0x0501) + + return TRUE; + } + + BOOL AddSimpleReBarBand(HWND hWndBand, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE) + { + ATLASSERT(::IsWindow(m_hWndToolBar)); // must be an existing rebar + ATLASSERT(::IsWindow(hWndBand)); // must be created + return AddSimpleReBarBandCtrl(m_hWndToolBar, hWndBand, 0, lpstrTitle, bNewRow, cxWidth, bFullWidthAlways); + } + +#if (_WIN32_IE >= 0x0400) + void SizeSimpleReBarBands() + { + ATLASSERT(::IsWindow(m_hWndToolBar)); // must be an existing rebar + + int nCount = (int)::SendMessage(m_hWndToolBar, RB_GETBANDCOUNT, 0, 0L); + + for(int i = 0; i < nCount; i++) + { + REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() }; + rbBand.fMask = RBBIM_SIZE; + BOOL bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_GETBANDINFO, i, (LPARAM)&rbBand); + ATLASSERT(bRet); + RECT rect = { 0, 0, 0, 0 }; + ::SendMessage(m_hWndToolBar, RB_GETBANDBORDERS, i, (LPARAM)&rect); + rbBand.cx += rect.left + rect.right; + bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_SETBANDINFO, i, (LPARAM)&rbBand); + ATLASSERT(bRet); + } + } +#endif // (_WIN32_IE >= 0x0400) +#endif // _WIN32_WCE + +#ifndef _WIN32_WCE + BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR) +#else // CE specific + BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR) +#endif // _WIN32_WCE + { + ATLASSERT(!::IsWindow(m_hWndStatusBar)); + m_hWndStatusBar = ::CreateStatusWindow(dwStyle, lpstrText, m_hWnd, nID); + return (m_hWndStatusBar != NULL); + } + +#ifndef _WIN32_WCE + BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR) +#else // CE specific + BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR) +#endif // _WIN32_WCE + { + const int cchMax = 128; // max text length is 127 for status bars (+1 for null) + TCHAR szText[cchMax]; + szText[0] = 0; + ::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szText, cchMax); + return CreateSimpleStatusBar(szText, dwStyle, nID); + } + +#ifdef _WIN32_WCE + BOOL CreateSimpleCECommandBar(LPTSTR pszMenu = NULL, WORD iButton = 0, DWORD dwFlags = 0, int nCmdBarID = 1) + { + ATLASSERT(m_hWndCECommandBar == NULL); + ATLASSERT(m_hWndToolBar == NULL); + + m_hWndCECommandBar = ::CommandBar_Create(ModuleHelper::GetModuleInstance(), m_hWnd, nCmdBarID); + if(m_hWndCECommandBar == NULL) + return FALSE; + + m_hWndToolBar = m_hWndCECommandBar; + + BOOL bRet = TRUE; + + if(pszMenu != NULL) + bRet &= ::CommandBar_InsertMenubarEx(m_hWndCECommandBar, IS_INTRESOURCE(pszMenu) ? ModuleHelper::GetResourceInstance() : NULL, pszMenu, iButton); + + bRet &= ::CommandBar_AddAdornments(m_hWndCECommandBar, dwFlags, 0); + + return bRet; + } + +#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) + BOOL CreateSimpleCEMenuBar(UINT nToolBarId = ATL_IDW_MENU_BAR, DWORD dwFlags = 0, int nBmpId = 0, int cBmpImages = 0) + { + ATLASSERT(m_hWndCECommandBar == NULL); + + SHMENUBARINFO mbi = { 0 }; + mbi.cbSize = sizeof(mbi); + mbi.hwndParent = m_hWnd; + mbi.dwFlags = dwFlags; + mbi.nToolBarId = nToolBarId; + mbi.hInstRes = ModuleHelper::GetResourceInstance(); + mbi.nBmpId = nBmpId; + mbi.cBmpImages = cBmpImages; + mbi.hwndMB = NULL; // This gets set by SHCreateMenuBar + + BOOL bRet = ::SHCreateMenuBar(&mbi); + if(bRet != FALSE) + { + m_hWndCECommandBar = mbi.hwndMB; + SizeToMenuBar(); + } + + return bRet; + } + + void SizeToMenuBar() // for menu bar only + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(::IsWindow(m_hWndCECommandBar)); + + RECT rect = { 0 }; + GetWindowRect(&rect); + RECT rectMB = { 0 }; + ::GetWindowRect(m_hWndCECommandBar, &rectMB); + int cy = ::IsWindowVisible(m_hWndCECommandBar) ? rectMB.top - rect.top : rectMB.bottom - rect.top; + SetWindowPos(NULL, 0, 0, rect.right - rect.left, cy, SWP_NOZORDER | SWP_NOMOVE); + } +#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) +#endif // _WIN32_WCE + + void UpdateLayout(BOOL bResizeBars = TRUE) + { + RECT rect = { 0 }; + GetClientRect(&rect); + + // position bars and offset their dimensions + UpdateBarsPosition(rect, bResizeBars); + + // resize client window + if(m_hWndClient != NULL) + ::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, + SWP_NOZORDER | SWP_NOACTIVATE); + } + + void UpdateBarsPosition(RECT& rect, BOOL bResizeBars = TRUE) + { + // resize toolbar + if(m_hWndToolBar != NULL && ((DWORD)::GetWindowLong(m_hWndToolBar, GWL_STYLE) & WS_VISIBLE)) + { + if(bResizeBars) + { + ::SendMessage(m_hWndToolBar, WM_SIZE, 0, 0); + ::InvalidateRect(m_hWndToolBar, NULL, FALSE); + } + RECT rectTB = { 0 }; + ::GetWindowRect(m_hWndToolBar, &rectTB); + rect.top += rectTB.bottom - rectTB.top; + } + + // resize status bar + if(m_hWndStatusBar != NULL && ((DWORD)::GetWindowLong(m_hWndStatusBar, GWL_STYLE) & WS_VISIBLE)) + { + if(bResizeBars) + ::SendMessage(m_hWndStatusBar, WM_SIZE, 0, 0); + RECT rectSB = { 0 }; + ::GetWindowRect(m_hWndStatusBar, &rectSB); + rect.bottom -= rectSB.bottom - rectSB.top; + } + } + + BOOL PreTranslateMessage(MSG* pMsg) + { + if(m_hAccel != NULL && ::TranslateAccelerator(m_hWnd, m_hAccel, pMsg)) + return TRUE; + return FALSE; + } + + BEGIN_MSG_MAP(CFrameWindowImplBase) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) +#ifndef _WIN32_WCE + MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect) +#endif // !_WIN32_WCE + MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) +#ifndef _WIN32_WCE + NOTIFY_CODE_HANDLER(TTN_GETDISPINFOA, OnToolTipTextA) + NOTIFY_CODE_HANDLER(TTN_GETDISPINFOW, OnToolTipTextW) +#endif // !_WIN32_WCE + END_MSG_MAP() + + LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + if(m_hWndClient != NULL) // view will paint itself instead + return 1; + + bHandled = FALSE; + return 0; + } + +#ifndef _WIN32_WCE + LRESULT OnMenuSelect(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + bHandled = FALSE; + + if(m_hWndStatusBar == NULL) + return 1; + + WORD wFlags = HIWORD(wParam); + if(wFlags == 0xFFFF && lParam == NULL) // menu closing + { + ::SendMessage(m_hWndStatusBar, SB_SIMPLE, FALSE, 0L); + } + else + { + const int cchBuff = 256; + TCHAR szBuff[cchBuff]; + szBuff[0] = 0; + if(!(wFlags & MF_POPUP)) + { + WORD wID = LOWORD(wParam); + // check for special cases + if(wID >= 0xF000 && wID < 0xF1F0) // system menu IDs + wID = (WORD)(((wID - 0xF000) >> 4) + ATL_IDS_SCFIRST); + else if(wID >= ID_FILE_MRU_FIRST && wID <= ID_FILE_MRU_LAST) // MRU items + wID = ATL_IDS_MRU_FILE; + else if(wID >= ATL_IDM_FIRST_MDICHILD && wID <= ATL_IDM_LAST_MDICHILD) // MDI child windows + wID = ATL_IDS_MDICHILD; + + int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), wID, szBuff, cchBuff); + for(int i = 0; i < nRet; i++) + { + if(szBuff[i] == _T('\n')) + { + szBuff[i] = 0; + break; + } + } + } + ::SendMessage(m_hWndStatusBar, SB_SIMPLE, TRUE, 0L); + ::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM)szBuff); + } + + return 1; + } +#endif // !_WIN32_WCE + + LRESULT OnSetFocus(UINT, WPARAM, LPARAM, BOOL& bHandled) + { + if(m_hWndClient != NULL) + ::SetFocus(m_hWndClient); + + bHandled = FALSE; + return 1; + } + + LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& bHandled) + { + if((GetStyle() & (WS_CHILD | WS_POPUP)) == 0) + ::PostQuitMessage(1); + + bHandled = FALSE; + return 1; + } + +#ifndef _WIN32_WCE + LRESULT OnToolTipTextA(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/) + { + LPNMTTDISPINFOA pDispInfo = (LPNMTTDISPINFOA)pnmh; + pDispInfo->szText[0] = 0; + + if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND)) + { + const int cchBuff = 256; + char szBuff[cchBuff]; + szBuff[0] = 0; + int nRet = ::LoadStringA(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff); + for(int i = 0; i < nRet; i++) + { + if(szBuff[i] == '\n') + { + SecureHelper::strncpyA_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE); + break; + } + } +#if (_WIN32_IE >= 0x0300) + if(nRet > 0) // string was loaded, save it + pDispInfo->uFlags |= TTF_DI_SETITEM; +#endif // (_WIN32_IE >= 0x0300) + } + + return 0; + } + + LRESULT OnToolTipTextW(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/) + { + LPNMTTDISPINFOW pDispInfo = (LPNMTTDISPINFOW)pnmh; + pDispInfo->szText[0] = 0; + + if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND)) + { + const int cchBuff = 256; + wchar_t szBuff[cchBuff]; + szBuff[0] = 0; + int nRet = ::LoadStringW(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff); + for(int i = 0; i < nRet; i++) + { + if(szBuff[i] == L'\n') + { + SecureHelper::strncpyW_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE); + break; + } + } +#if (_WIN32_IE >= 0x0300) + if(nRet > 0) // string was loaded, save it + pDispInfo->uFlags |= TTF_DI_SETITEM; +#endif // (_WIN32_IE >= 0x0300) + } + + return 0; + } +#endif // !_WIN32_WCE + +// Implementation - chevron menu support +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + bool PrepareChevronMenu(_ChevronMenuInfo& cmi) + { + // get rebar and toolbar + REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() }; + rbbi.fMask = RBBIM_CHILD; + BOOL bRet = (BOOL)::SendMessage(cmi.lpnm->hdr.hwndFrom, RB_GETBANDINFO, cmi.lpnm->uBand, (LPARAM)&rbbi); + ATLASSERT(bRet); + + // assume the band is a toolbar + ATL::CWindow wnd = rbbi.hwndChild; + int nCount = (int)wnd.SendMessage(TB_BUTTONCOUNT); + if(nCount <= 0) // probably not a toolbar + return false; + + // check if it's a command bar + CMenuHandle menuCmdBar = (HMENU)wnd.SendMessage(CBRM_GETMENU); + cmi.bCmdBar = (menuCmdBar.m_hMenu != NULL); + + // build a menu from hidden items + CMenuHandle menu; + bRet = menu.CreatePopupMenu(); + ATLASSERT(bRet); + RECT rcClient = { 0 }; + bRet = wnd.GetClientRect(&rcClient); + ATLASSERT(bRet); + for(int i = 0; i < nCount; i++) + { + TBBUTTON tbb = { 0 }; + bRet = (BOOL)wnd.SendMessage(TB_GETBUTTON, i, (LPARAM)&tbb); + ATLASSERT(bRet); + // skip hidden buttons + if((tbb.fsState & TBSTATE_HIDDEN) != 0) + continue; + RECT rcButton = { 0 }; + bRet = (BOOL)wnd.SendMessage(TB_GETITEMRECT, i, (LPARAM)&rcButton); + ATLASSERT(bRet); + bool bEnabled = ((tbb.fsState & TBSTATE_ENABLED) != 0); + if(rcButton.right > rcClient.right) + { + if(tbb.fsStyle & BTNS_SEP) + { + if(menu.GetMenuItemCount() > 0) + menu.AppendMenu(MF_SEPARATOR); + } + else if(cmi.bCmdBar) + { + const int cchBuff = 200; + TCHAR szBuff[cchBuff] = { 0 }; + CMenuItemInfo mii; + mii.fMask = MIIM_TYPE | MIIM_SUBMENU; + mii.dwTypeData = szBuff; + mii.cch = cchBuff; + bRet = menuCmdBar.GetMenuItemInfo(i, TRUE, &mii); + ATLASSERT(bRet); + // Note: CmdBar currently supports only drop-down items + ATLASSERT(::IsMenu(mii.hSubMenu)); + bRet = menu.AppendMenu(MF_STRING | MF_POPUP | (bEnabled ? MF_ENABLED : MF_GRAYED), (UINT_PTR)mii.hSubMenu, mii.dwTypeData); + ATLASSERT(bRet); + } + else + { + // get button's text + const int cchBuff = 200; + TCHAR szBuff[cchBuff] = { 0 }; + LPTSTR lpstrText = szBuff; + TBBUTTONINFO tbbi = { 0 }; + tbbi.cbSize = sizeof(TBBUTTONINFO); + tbbi.dwMask = TBIF_TEXT; + tbbi.pszText = szBuff; + tbbi.cchText = cchBuff; + if(wnd.SendMessage(TB_GETBUTTONINFO, tbb.idCommand, (LPARAM)&tbbi) == -1 || lstrlen(szBuff) == 0) + { + // no text for this button, try a resource string + lpstrText = _T(""); + int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), tbb.idCommand, szBuff, cchBuff); + for(int n = 0; n < nRet; n++) + { + if(szBuff[n] == _T('\n')) + { + lpstrText = &szBuff[n + 1]; + break; + } + } + } + bRet = menu.AppendMenu(MF_STRING | (bEnabled ? MF_ENABLED : MF_GRAYED), tbb.idCommand, lpstrText); + ATLASSERT(bRet); + } + } + } + + if(menu.GetMenuItemCount() == 0) // no hidden buttons after all + { + menu.DestroyMenu(); + ::MessageBeep((UINT)-1); + return false; + } + + cmi.hMenu = menu; + return true; + } + + void DisplayChevronMenu(_ChevronMenuInfo& cmi) + { +#ifndef TPM_VERPOSANIMATION + const UINT TPM_VERPOSANIMATION = 0x1000L; // Menu animation flag +#endif + // convert chevron rect to screen coordinates + ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom; + POINT pt = { cmi.lpnm->rc.left, cmi.lpnm->rc.bottom }; + wndFrom.MapWindowPoints(NULL, &pt, 1); + RECT rc = cmi.lpnm->rc; + wndFrom.MapWindowPoints(NULL, &rc); + // set up flags and rect + UINT uMenuFlags = TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | (!AtlIsOldWindows() ? TPM_VERPOSANIMATION : 0); + TPMPARAMS TPMParams = { 0 }; + TPMParams.cbSize = sizeof(TPMPARAMS); + TPMParams.rcExclude = rc; + // check if this window has a command bar + HWND hWndCmdBar = (HWND)::SendMessage(m_hWnd, CBRM_GETCMDBAR, 0, 0L); + if(::IsWindow(hWndCmdBar)) + { + CBRPOPUPMENU CBRPopupMenu = { sizeof(CBRPOPUPMENU), cmi.hMenu, uMenuFlags, pt.x, pt.y, &TPMParams }; + ::SendMessage(hWndCmdBar, CBRM_TRACKPOPUPMENU, 0, (LPARAM)&CBRPopupMenu); + } + else + { + CMenuHandle menu = cmi.hMenu; + menu.TrackPopupMenuEx(uMenuFlags, pt.x, pt.y, m_hWnd, &TPMParams); + } + } + + void CleanupChevronMenu(_ChevronMenuInfo& cmi) + { + CMenuHandle menu = cmi.hMenu; + // if menu is from a command bar, detach submenus so they are not destroyed + if(cmi.bCmdBar) + { + for(int i = menu.GetMenuItemCount() - 1; i >=0; i--) + menu.RemoveMenu(i, MF_BYPOSITION); + } + // destroy menu + menu.DestroyMenu(); + // convert chevron rect to screen coordinates + ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom; + RECT rc = cmi.lpnm->rc; + wndFrom.MapWindowPoints(NULL, &rc); + // eat next message if click is on the same button + MSG msg = { 0 }; + if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rc, msg.pt)) + ::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE); + } +#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) +}; + + +template +class ATL_NO_VTABLE CFrameWindowImpl : public CFrameWindowImplBase< TBase, TWinTraits > +{ +public: + HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + HMENU hMenu = NULL, LPVOID lpCreateParam = NULL) + { + ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc); + + dwStyle = T::GetWndStyle(dwStyle); + dwExStyle = T::GetWndExStyle(dwExStyle); + + if(rect.m_lpRect == NULL) + rect.m_lpRect = &TBase::rcDefault; + + return CFrameWindowImplBase< TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam); + } + + HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL) + { + const int cchName = 256; + TCHAR szWindowName[cchName]; + szWindowName[0] = 0; +#ifndef _WIN32_WCE + ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName); + HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); +#else // CE specific + ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName); + + // This always needs to be NULL for Windows CE. + // Frame Window menus have to go onto the CommandBar. + // Use CreateSimpleCECommandBar + HMENU hMenu = NULL; +#endif // _WIN32_WCE + + T* pT = static_cast(this); + HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam); + + if(hWnd != NULL) + m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); + + return hWnd; + } + + BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) + { + if(nResourceID == 0) + nResourceID = T::GetWndClassInfo().m_uCommonResourceID; +#ifndef _WIN32_WCE + ATLASSERT(!::IsWindow(m_hWndToolBar)); + m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID); + return (m_hWndToolBar != NULL); +#else // CE specific + HWND hWnd= T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID); + return (hWnd != NULL); +#endif // _WIN32_WCE + } + +#ifdef _WIN32_WCE + // CE specific variant that returns the handle of the toolbar + HWND CreateSimpleCEToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) + { + if(nResourceID == 0) + nResourceID = T::GetWndClassInfo().m_uCommonResourceID; + + return T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID); + } +#endif // _WIN32_WCE + +// message map and handlers + typedef CFrameWindowImplBase< TBase, TWinTraits > _baseClass; + + BEGIN_MSG_MAP(CFrameWindowImpl) + MESSAGE_HANDLER(WM_SIZE, OnSize) +#ifndef _ATL_NO_REBAR_SUPPORT +#if (_WIN32_IE >= 0x0400) + NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize) +#endif // (_WIN32_IE >= 0x0400) +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed) +#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) +#endif // !_ATL_NO_REBAR_SUPPORT + CHAIN_MSG_MAP(_baseClass) + END_MSG_MAP() + + LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + if(wParam != SIZE_MINIMIZED) + { + T* pT = static_cast(this); + pT->UpdateLayout(); + } + bHandled = FALSE; + return 1; + } + +#ifndef _ATL_NO_REBAR_SUPPORT +#if (_WIN32_IE >= 0x0400) + LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->UpdateLayout(FALSE); + return 0; + } +#endif // (_WIN32_IE >= 0x0400) + +#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) + LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) + { + T* pT = static_cast(this); + _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false }; + if(!pT->PrepareChevronMenu(cmi)) + { + bHandled = FALSE; + return 1; + } + // display a popup menu with hidden items + pT->DisplayChevronMenu(cmi); + // cleanup + pT->CleanupChevronMenu(cmi); + return 0; + } +#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) +#endif // !_ATL_NO_REBAR_SUPPORT +}; + + +/////////////////////////////////////////////////////////////////////////////// +// AtlCreateSimpleToolBar - helper for creating simple toolbars + +#ifndef _WIN32_WCE + +inline HWND AtlCreateSimpleToolBar(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE, + DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) +{ + return CFrameWindowImplBase<>::CreateSimpleToolBarCtrl(hWndParent, nResourceID, bInitialSeparator, dwStyle, nID); +} + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CMDIWindow + +#ifndef _WIN32_WCE + +#ifndef _WTL_MDIWINDOWMENU_TEXT +#define _WTL_MDIWINDOWMENU_TEXT _T("&Window") +#endif + +class CMDIWindow : public ATL::CWindow +{ +public: +// Data members + HWND m_hWndMDIClient; + HMENU m_hMenu; + +// Constructors + CMDIWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd), m_hWndMDIClient(NULL), m_hMenu(NULL) + { } + + CMDIWindow& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + +// Operations + HWND MDIGetActive(BOOL* lpbMaximized = NULL) + { + ATLASSERT(::IsWindow(m_hWndMDIClient)); + return (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)lpbMaximized); + } + + void MDIActivate(HWND hWndChildToActivate) + { + ATLASSERT(::IsWindow(m_hWndMDIClient)); + ATLASSERT(::IsWindow(hWndChildToActivate)); + ::SendMessage(m_hWndMDIClient, WM_MDIACTIVATE, (WPARAM)hWndChildToActivate, 0); + } + + void MDINext(HWND hWndChild, BOOL bPrevious = FALSE) + { + ATLASSERT(::IsWindow(m_hWndMDIClient)); + ATLASSERT(hWndChild == NULL || ::IsWindow(hWndChild)); + ::SendMessage(m_hWndMDIClient, WM_MDINEXT, (WPARAM)hWndChild, (LPARAM)bPrevious); + } + + void MDIMaximize(HWND hWndChildToMaximize) + { + ATLASSERT(::IsWindow(m_hWndMDIClient)); + ATLASSERT(::IsWindow(hWndChildToMaximize)); + ::SendMessage(m_hWndMDIClient, WM_MDIMAXIMIZE, (WPARAM)hWndChildToMaximize, 0); + } + + void MDIRestore(HWND hWndChildToRestore) + { + ATLASSERT(::IsWindow(m_hWndMDIClient)); + ATLASSERT(::IsWindow(hWndChildToRestore)); + ::SendMessage(m_hWndMDIClient, WM_MDIRESTORE, (WPARAM)hWndChildToRestore, 0); + } + + void MDIDestroy(HWND hWndChildToDestroy) + { + ATLASSERT(::IsWindow(m_hWndMDIClient)); + ATLASSERT(::IsWindow(hWndChildToDestroy)); + ::SendMessage(m_hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndChildToDestroy, 0); + } + + BOOL MDICascade(UINT uFlags = 0) + { + ATLASSERT(::IsWindow(m_hWndMDIClient)); + return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDICASCADE, (WPARAM)uFlags, 0); + } + + BOOL MDITile(UINT uFlags = MDITILE_HORIZONTAL) + { + ATLASSERT(::IsWindow(m_hWndMDIClient)); + return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDITILE, (WPARAM)uFlags, 0); + } + + void MDIIconArrange() + { + ATLASSERT(::IsWindow(m_hWndMDIClient)); + ::SendMessage(m_hWndMDIClient, WM_MDIICONARRANGE, 0, 0); + } + + HMENU MDISetMenu(HMENU hMenuFrame, HMENU hMenuWindow) + { + ATLASSERT(::IsWindow(m_hWndMDIClient)); + return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDISETMENU, (WPARAM)hMenuFrame, (LPARAM)hMenuWindow); + } + + HMENU MDIRefreshMenu() + { + ATLASSERT(::IsWindow(m_hWndMDIClient)); + return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0); + } + +// Additional operations + static HMENU GetStandardWindowMenu(HMENU hMenu) + { + int nCount = ::GetMenuItemCount(hMenu); + if(nCount == -1) + return NULL; + int nLen = ::GetMenuString(hMenu, nCount - 2, NULL, 0, MF_BYPOSITION); + if(nLen == 0) + return NULL; + CTempBuffer buff; + LPTSTR lpszText = buff.Allocate(nLen + 1); + if(lpszText == NULL) + return NULL; + if(::GetMenuString(hMenu, nCount - 2, lpszText, nLen + 1, MF_BYPOSITION) != nLen) + return NULL; + if(lstrcmp(lpszText, _WTL_MDIWINDOWMENU_TEXT) != 0) + return NULL; + return ::GetSubMenu(hMenu, nCount - 2); + } + + void SetMDIFrameMenu() + { + HMENU hWindowMenu = GetStandardWindowMenu(m_hMenu); + MDISetMenu(m_hMenu, hWindowMenu); + MDIRefreshMenu(); + ::DrawMenuBar(GetMDIFrame()); + } + + HWND GetMDIFrame() const + { + return ::GetParent(m_hWndMDIClient); + } +}; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CMDIFrameWindowImpl + +#ifndef _WIN32_WCE + +// MDI child command chaining macro (only for MDI frame windows) +#define CHAIN_MDI_CHILD_COMMANDS() \ + if(uMsg == WM_COMMAND) \ + { \ + HWND hWndChild = MDIGetActive(); \ + if(hWndChild != NULL) \ + ::SendMessage(hWndChild, uMsg, wParam, lParam); \ + } + +template +class ATL_NO_VTABLE CMDIFrameWindowImpl : public CFrameWindowImplBase +{ +public: + HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + HMENU hMenu = NULL, LPVOID lpCreateParam = NULL) + { + m_hMenu = hMenu; + ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc); + + dwStyle = T::GetWndStyle(dwStyle); + dwExStyle = T::GetWndExStyle(dwExStyle); + + if(rect.m_lpRect == NULL) + rect.m_lpRect = &TBase::rcDefault; + + return CFrameWindowImplBase::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam); + } + + HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL) + { + const int cchName = 256; + TCHAR szWindowName[cchName]; + szWindowName[0] = 0; + ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName); + HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); + + T* pT = static_cast(this); + HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam); + + if(hWnd != NULL) + m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); + + return hWnd; + } + + BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) + { + ATLASSERT(!::IsWindow(m_hWndToolBar)); + if(nResourceID == 0) + nResourceID = T::GetWndClassInfo().m_uCommonResourceID; + m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID); + return (m_hWndToolBar != NULL); + } + + virtual WNDPROC GetWindowProc() + { + return MDIFrameWindowProc; + } + + static LRESULT CALLBACK MDIFrameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + CMDIFrameWindowImpl< T, TBase, TWinTraits >* pThis = (CMDIFrameWindowImpl< T, TBase, TWinTraits >*)hWnd; + // set a ptr to this message and save the old value +#if (_ATL_VER >= 0x0700) + ATL::_ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam); + const ATL::_ATL_MSG* pOldMsg = pThis->m_pCurrentMsg; +#else // !(_ATL_VER >= 0x0700) + MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } }; + const MSG* pOldMsg = pThis->m_pCurrentMsg; +#endif // !(_ATL_VER >= 0x0700) + pThis->m_pCurrentMsg = &msg; + // pass to the message map to process + LRESULT lRes = 0; + BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0); + // restore saved value for the current message + ATLASSERT(pThis->m_pCurrentMsg == &msg); + pThis->m_pCurrentMsg = pOldMsg; + // do the default processing if message was not handled + if(!bRet) + { + if(uMsg != WM_NCDESTROY) + lRes = pThis->DefWindowProc(uMsg, wParam, lParam); + else + { + // unsubclass, if needed + LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC); + lRes = pThis->DefWindowProc(uMsg, wParam, lParam); + if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc) + ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc); +#if (_ATL_VER >= 0x0700) + // mark window as destryed + pThis->m_dwState |= WINSTATE_DESTROYED; +#else // !(_ATL_VER >= 0x0700) + // clear out window handle + HWND hWnd = pThis->m_hWnd; + pThis->m_hWnd = NULL; + // clean up after window is destroyed + pThis->OnFinalMessage(hWnd); +#endif // !(_ATL_VER >= 0x0700) + } + } +#if (_ATL_VER >= 0x0700) + if(pThis->m_dwState & WINSTATE_DESTROYED && pThis->m_pCurrentMsg == NULL) + { + // clear out window handle + HWND hWnd = pThis->m_hWnd; + pThis->m_hWnd = NULL; + pThis->m_dwState &= ~WINSTATE_DESTROYED; + // clean up after window is destroyed + pThis->OnFinalMessage(hWnd); + } +#endif // (_ATL_VER >= 0x0700) + return lRes; + } + + // Overriden to call DefWindowProc which uses DefFrameProc + LRESULT DefWindowProc() + { + const MSG* pMsg = m_pCurrentMsg; + LRESULT lRes = 0; + if (pMsg != NULL) + lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam); + return lRes; + } + + LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + return ::DefFrameProc(m_hWnd, m_hWndMDIClient, uMsg, wParam, lParam); + } + + BOOL PreTranslateMessage(MSG* pMsg) + { + if(CFrameWindowImplBase::PreTranslateMessage(pMsg)) + return TRUE; + return ::TranslateMDISysAccel(m_hWndMDIClient, pMsg); + } + + HWND CreateMDIClient(HMENU hWindowMenu = NULL, UINT nID = ATL_IDW_CLIENT, UINT nFirstChildID = ATL_IDM_FIRST_MDICHILD) + { + DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | MDIS_ALLCHILDSTYLES; + DWORD dwExStyle = WS_EX_CLIENTEDGE; + + CLIENTCREATESTRUCT ccs = { 0 }; + ccs.hWindowMenu = hWindowMenu; + ccs.idFirstChild = nFirstChildID; + + if((GetStyle() & (WS_HSCROLL | WS_VSCROLL)) != 0) + { + // parent MDI frame's scroll styles move to the MDICLIENT + dwStyle |= (GetStyle() & (WS_HSCROLL | WS_VSCROLL)); + + // fast way to turn off the scrollbar bits (without a resize) + ModifyStyle(WS_HSCROLL | WS_VSCROLL, 0, SWP_NOREDRAW | SWP_FRAMECHANGED); + } + + // Create MDICLIENT window + m_hWndClient = ::CreateWindowEx(dwExStyle, _T("MDIClient"), NULL, + dwStyle, 0, 0, 1, 1, m_hWnd, (HMENU)LongToHandle(nID), + ModuleHelper::GetModuleInstance(), (LPVOID)&ccs); + if (m_hWndClient == NULL) + { + ATLTRACE2(atlTraceUI, 0, _T("MDI Frame failed to create MDICLIENT.\n")); + return NULL; + } + + // Move it to the top of z-order + ::BringWindowToTop(m_hWndClient); + + // set as MDI client window + m_hWndMDIClient = m_hWndClient; + + // update to proper size + T* pT = static_cast(this); + pT->UpdateLayout(); + + return m_hWndClient; + } + + typedef CFrameWindowImplBase _baseClass; + + BEGIN_MSG_MAP(CMDIFrameWindowImpl) + MESSAGE_HANDLER(WM_SIZE, OnSize) + MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) + MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu) +#ifndef _ATL_NO_REBAR_SUPPORT +#if (_WIN32_IE >= 0x0400) + NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize) +#endif // (_WIN32_IE >= 0x0400) +#if (_WIN32_IE >= 0x0500) + NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed) +#endif // (_WIN32_IE >= 0x0500) +#endif // !_ATL_NO_REBAR_SUPPORT + CHAIN_MSG_MAP(_baseClass) + END_MSG_MAP() + + LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + if(wParam != SIZE_MINIMIZED) + { + T* pT = static_cast(this); + pT->UpdateLayout(); + } + // message must be handled, otherwise DefFrameProc would resize the client again + return 0; + } + + LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + // don't allow CFrameWindowImplBase to handle this one + return DefWindowProc(uMsg, wParam, lParam); + } + + LRESULT OnMDISetMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + SetMDIFrameMenu(); + return 0; + } + +#ifndef _ATL_NO_REBAR_SUPPORT +#if (_WIN32_IE >= 0x0400) + LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->UpdateLayout(FALSE); + return 0; + } +#endif // (_WIN32_IE >= 0x0400) + +#if (_WIN32_IE >= 0x0500) + LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) + { + T* pT = static_cast(this); + _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false }; + if(!pT->PrepareChevronMenu(cmi)) + { + bHandled = FALSE; + return 1; + } + // display a popup menu with hidden items + pT->DisplayChevronMenu(cmi); + // cleanup + pT->CleanupChevronMenu(cmi); + return 0; + } +#endif // (_WIN32_IE >= 0x0500) +#endif // !_ATL_NO_REBAR_SUPPORT +}; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CMDIChildWindowImpl + +#ifndef _WIN32_WCE + +template +class ATL_NO_VTABLE CMDIChildWindowImpl : public CFrameWindowImplBase +{ +public: + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + UINT nMenuID = 0, LPVOID lpCreateParam = NULL) + { + ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc); + + if(nMenuID != 0) + m_hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nMenuID)); + + dwStyle = T::GetWndStyle(dwStyle); + dwExStyle = T::GetWndExStyle(dwExStyle); + + dwExStyle |= WS_EX_MDICHILD; // force this one + m_pfnSuperWindowProc = ::DefMDIChildProc; + m_hWndMDIClient = hWndParent; + ATLASSERT(::IsWindow(m_hWndMDIClient)); + + if(rect.m_lpRect == NULL) + rect.m_lpRect = &TBase::rcDefault; + + // If the currently active MDI child is maximized, we want to create this one maximized too + ATL::CWindow wndParent = hWndParent; + BOOL bMaximized = FALSE; + wndParent.SendMessage(WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized); + if(bMaximized) + wndParent.SetRedraw(FALSE); + + HWND hWnd = CFrameWindowImplBase::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, (UINT)0U, atom, lpCreateParam); + + if(bMaximized) + { + // Maximize and redraw everything + if(hWnd != NULL) + MDIMaximize(hWnd); + wndParent.SetRedraw(TRUE); + wndParent.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); + ::SetFocus(GetMDIFrame()); // focus will be set back to this window + } + else if(hWnd != NULL && ::IsWindowVisible(m_hWnd) && !::IsChild(hWnd, ::GetFocus())) + { + ::SetFocus(hWnd); + } + + return hWnd; + } + + HWND CreateEx(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR lpcstrWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL) + { + const int cchName = 256; + TCHAR szWindowName[cchName]; + szWindowName[0] = 0; + if(lpcstrWindowName == NULL) + { + ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName); + lpcstrWindowName = szWindowName; + } + + T* pT = static_cast(this); + HWND hWnd = pT->Create(hWndParent, rect, lpcstrWindowName, dwStyle, dwExStyle, T::GetWndClassInfo().m_uCommonResourceID, lpCreateParam); + + if(hWnd != NULL) + m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); + + return hWnd; + } + + BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) + { + ATLASSERT(!::IsWindow(m_hWndToolBar)); + if(nResourceID == 0) + nResourceID = T::GetWndClassInfo().m_uCommonResourceID; + m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID); + return (m_hWndToolBar != NULL); + } + + BOOL UpdateClientEdge(LPRECT lpRect = NULL) + { + // only adjust for active MDI child window + HWND hWndChild = MDIGetActive(); + if(hWndChild != NULL && hWndChild != m_hWnd) + return FALSE; + + // need to adjust the client edge style as max/restore happens + DWORD dwStyle = ::GetWindowLong(m_hWndMDIClient, GWL_EXSTYLE); + DWORD dwNewStyle = dwStyle; + if(hWndChild != NULL && ((GetExStyle() & WS_EX_CLIENTEDGE) == 0) && ((GetStyle() & WS_MAXIMIZE) != 0)) + dwNewStyle &= ~(WS_EX_CLIENTEDGE); + else + dwNewStyle |= WS_EX_CLIENTEDGE; + + if(dwStyle != dwNewStyle) + { + // SetWindowPos will not move invalid bits + ::RedrawWindow(m_hWndMDIClient, NULL, NULL, + RDW_INVALIDATE | RDW_ALLCHILDREN); + // remove/add WS_EX_CLIENTEDGE to MDI client area + ::SetWindowLong(m_hWndMDIClient, GWL_EXSTYLE, dwNewStyle); + ::SetWindowPos(m_hWndMDIClient, NULL, 0, 0, 0, 0, + SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | + SWP_NOZORDER | SWP_NOCOPYBITS); + + // return new client area + if (lpRect != NULL) + ::GetClientRect(m_hWndMDIClient, lpRect); + + return TRUE; + } + + return FALSE; + } + + typedef CFrameWindowImplBase _baseClass; + BEGIN_MSG_MAP(CMDIChildWindowImpl) + MESSAGE_HANDLER(WM_SIZE, OnSize) + MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnWindowPosChanged) + MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate) + MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect) + MESSAGE_HANDLER(WM_MDIACTIVATE, OnMDIActivate) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) +#ifndef _ATL_NO_REBAR_SUPPORT +#if (_WIN32_IE >= 0x0400) + NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize) +#endif // (_WIN32_IE >= 0x0400) +#if (_WIN32_IE >= 0x0500) + NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed) +#endif // (_WIN32_IE >= 0x0500) +#endif // !_ATL_NO_REBAR_SUPPORT + CHAIN_MSG_MAP(_baseClass) + END_MSG_MAP() + + LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + DefWindowProc(uMsg, wParam, lParam); // needed for MDI children + if(wParam != SIZE_MINIMIZED) + { + T* pT = static_cast(this); + pT->UpdateLayout(); + } + return 0; + } + + LRESULT OnWindowPosChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + // update MDI client edge and adjust MDI child rect + LPWINDOWPOS lpWndPos = (LPWINDOWPOS)lParam; + + if(!(lpWndPos->flags & SWP_NOSIZE)) + { + RECT rectClient; + if(UpdateClientEdge(&rectClient) && ((GetStyle() & WS_MAXIMIZE) != 0)) + { + ::AdjustWindowRectEx(&rectClient, GetStyle(), FALSE, GetExStyle()); + lpWndPos->x = rectClient.left; + lpWndPos->y = rectClient.top; + lpWndPos->cx = rectClient.right - rectClient.left; + lpWndPos->cy = rectClient.bottom - rectClient.top; + } + } + + bHandled = FALSE; + return 1; + } + + LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + LRESULT lRes = DefWindowProc(uMsg, wParam, lParam); + + // Activate this MDI window if needed + if(lRes == MA_ACTIVATE || lRes == MA_ACTIVATEANDEAT) + { + if(MDIGetActive() != m_hWnd) + MDIActivate(m_hWnd); + } + + return lRes; + } + + LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + return ::SendMessage(GetMDIFrame(), uMsg, wParam, lParam); + } + + LRESULT OnMDIActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + if((HWND)lParam == m_hWnd && m_hMenu != NULL) + SetMDIFrameMenu(); + else if((HWND)lParam == NULL) + ::SendMessage(GetMDIFrame(), WM_MDISETMENU, 0, 0); + + bHandled = FALSE; + return 1; + } + + LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + if(m_hMenu != NULL) + { + ::DestroyMenu(m_hMenu); + m_hMenu = NULL; + } + UpdateClientEdge(); + bHandled = FALSE; + return 1; + } + +#ifndef _ATL_NO_REBAR_SUPPORT +#if (_WIN32_IE >= 0x0400) + LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->UpdateLayout(FALSE); + return 0; + } +#endif // (_WIN32_IE >= 0x0400) + +#if (_WIN32_IE >= 0x0500) + LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) + { + T* pT = static_cast(this); + _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false }; + if(!pT->PrepareChevronMenu(cmi)) + { + bHandled = FALSE; + return 1; + } + // display a popup menu with hidden items + pT->DisplayChevronMenu(cmi); + // cleanup + pT->CleanupChevronMenu(cmi); + return 0; + } +#endif // (_WIN32_IE >= 0x0500) +#endif // !_ATL_NO_REBAR_SUPPORT +}; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// COwnerDraw - MI class for owner-draw support + +template +class COwnerDraw +{ +public: +#if (_ATL_VER < 0x0700) + BOOL m_bHandledOD; + + BOOL IsMsgHandled() const + { + return m_bHandledOD; + } + void SetMsgHandled(BOOL bHandled) + { + m_bHandledOD = bHandled; + } +#endif // (_ATL_VER < 0x0700) + +// Message map and handlers + BEGIN_MSG_MAP(COwnerDraw< T >) + MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem) + MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem) + MESSAGE_HANDLER(WM_COMPAREITEM, OnCompareItem) + MESSAGE_HANDLER(WM_DELETEITEM, OnDeleteItem) + ALT_MSG_MAP(1) + MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem) + MESSAGE_HANDLER(OCM_MEASUREITEM, OnMeasureItem) + MESSAGE_HANDLER(OCM_COMPAREITEM, OnCompareItem) + MESSAGE_HANDLER(OCM_DELETEITEM, OnDeleteItem) + END_MSG_MAP() + + LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + T* pT = static_cast(this); + pT->SetMsgHandled(TRUE); + pT->DrawItem((LPDRAWITEMSTRUCT)lParam); + bHandled = pT->IsMsgHandled(); + return (LRESULT)TRUE; + } + + LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + T* pT = static_cast(this); + pT->SetMsgHandled(TRUE); + pT->MeasureItem((LPMEASUREITEMSTRUCT)lParam); + bHandled = pT->IsMsgHandled(); + return (LRESULT)TRUE; + } + + LRESULT OnCompareItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + T* pT = static_cast(this); + pT->SetMsgHandled(TRUE); + bHandled = pT->IsMsgHandled(); + return (LRESULT)pT->CompareItem((LPCOMPAREITEMSTRUCT)lParam); + } + + LRESULT OnDeleteItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + T* pT = static_cast(this); + pT->SetMsgHandled(TRUE); + pT->DeleteItem((LPDELETEITEMSTRUCT)lParam); + bHandled = pT->IsMsgHandled(); + return (LRESULT)TRUE; + } + +// Overrideables + void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/) + { + // must be implemented + ATLASSERT(FALSE); + } + + void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) + { + if(lpMeasureItemStruct->CtlType != ODT_MENU) + { + // return default height for a system font + T* pT = static_cast(this); + HWND hWnd = pT->GetDlgItem(lpMeasureItemStruct->CtlID); + CClientDC dc(hWnd); + TEXTMETRIC tm = { 0 }; + dc.GetTextMetrics(&tm); + + lpMeasureItemStruct->itemHeight = tm.tmHeight; + } + else + lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_CYMENU); + } + + int CompareItem(LPCOMPAREITEMSTRUCT /*lpCompareItemStruct*/) + { + // all items are equal + return 0; + } + + void DeleteItem(LPDELETEITEMSTRUCT /*lpDeleteItemStruct*/) + { + // default - nothing + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Update UI macros + +// these build the Update UI map inside a class definition +#define BEGIN_UPDATE_UI_MAP(thisClass) \ + static const CUpdateUIBase::_AtlUpdateUIMap* GetUpdateUIMap() \ + { \ + static const _AtlUpdateUIMap theMap[] = \ + { + +#define UPDATE_ELEMENT(nID, wType) \ + { nID, wType }, + +#define END_UPDATE_UI_MAP() \ + { (WORD)-1, 0 } \ + }; \ + return theMap; \ + } + +/////////////////////////////////////////////////////////////////////////////// +// CUpdateUI - manages UI elements updating + +class CUpdateUIBase +{ +public: + // constants + enum + { + // UI element type + UPDUI_MENUPOPUP = 0x0001, + UPDUI_MENUBAR = 0x0002, + UPDUI_CHILDWINDOW = 0x0004, + UPDUI_TOOLBAR = 0x0008, + UPDUI_STATUSBAR = 0x0010, + // state + UPDUI_ENABLED = 0x0000, + UPDUI_DISABLED = 0x0100, + UPDUI_CHECKED = 0x0200, + UPDUI_CHECKED2 = 0x0400, + UPDUI_RADIO = 0x0800, + UPDUI_DEFAULT = 0x1000, + UPDUI_TEXT = 0x2000, + // internal state + UPDUI_CLEARDEFAULT = 0x4000, + }; + + // element data + struct _AtlUpdateUIElement + { + HWND m_hWnd; + WORD m_wType; + + bool operator ==(const _AtlUpdateUIElement& e) const + { return (m_hWnd == e.m_hWnd && m_wType == e.m_wType); } + }; + + // map data + struct _AtlUpdateUIMap + { + WORD m_nID; + WORD m_wType; + + bool operator ==(const _AtlUpdateUIMap& e) const + { return (m_nID == e.m_nID && m_wType == e.m_wType); } + }; + + // instance data + struct _AtlUpdateUIData + { + WORD m_wState; + union + { + void* m_lpData; + LPTSTR m_lpstrText; + }; + + bool operator ==(const _AtlUpdateUIData& e) const + { return (m_wState == e.m_wState && m_lpData == e.m_lpData); } + }; + + ATL::CSimpleArray<_AtlUpdateUIElement> m_UIElements; // elements data + const _AtlUpdateUIMap* m_pUIMap; // static UI data + _AtlUpdateUIData* m_pUIData; // instance UI data + WORD m_wDirtyType; // global dirty flag + + bool m_bBlockAccelerators; + + +// Constructor, destructor + CUpdateUIBase() : m_pUIMap(NULL), m_pUIData(NULL), m_wDirtyType(0), m_bBlockAccelerators(false) + { } + + ~CUpdateUIBase() + { + if(m_pUIMap != NULL && m_pUIData != NULL) + { + const _AtlUpdateUIMap* pUIMap = m_pUIMap; + _AtlUpdateUIData* pUIData = m_pUIData; + while(pUIMap->m_nID != (WORD)-1) + { + if(pUIData->m_wState & UPDUI_TEXT) + delete [] pUIData->m_lpstrText; + pUIMap++; + pUIData++; + } + delete [] m_pUIData; + } + } + +// Check for disabled commands + bool UIGetBlockAccelerators() const + { + return m_bBlockAccelerators; + } + + bool UISetBlockAccelerators(bool bBlock) + { + bool bOld = m_bBlockAccelerators; + m_bBlockAccelerators = bBlock; + return bOld; + } + +// Add elements + BOOL UIAddMenuBar(HWND hWnd) // menu bar (main menu) + { + if(hWnd == NULL) + return FALSE; + _AtlUpdateUIElement e; + e.m_hWnd = hWnd; + e.m_wType = UPDUI_MENUBAR; + return m_UIElements.Add(e); + } + + BOOL UIAddToolBar(HWND hWnd) // toolbar + { + if(hWnd == NULL) + return FALSE; + _AtlUpdateUIElement e; + e.m_hWnd = hWnd; + e.m_wType = UPDUI_TOOLBAR; + return m_UIElements.Add(e); + } + + BOOL UIAddStatusBar(HWND hWnd) // status bar + { + if(hWnd == NULL) + return FALSE; + _AtlUpdateUIElement e; + e.m_hWnd = hWnd; + e.m_wType = UPDUI_STATUSBAR; + return m_UIElements.Add(e); + } + + BOOL UIAddChildWindowContainer(HWND hWnd) // child window + { + if(hWnd == NULL) + return FALSE; + _AtlUpdateUIElement e; + e.m_hWnd = hWnd; + e.m_wType = UPDUI_CHILDWINDOW; + return m_UIElements.Add(e); + } + +// Message map for popup menu updates and accelerator blocking + BEGIN_MSG_MAP(CUpdateUIBase) + MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup) + MESSAGE_HANDLER(WM_COMMAND, OnCommand) + END_MSG_MAP() + + LRESULT OnInitMenuPopup(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + bHandled = FALSE; + HMENU hMenu = (HMENU)wParam; + if(hMenu == NULL) + return 1; + _AtlUpdateUIData* pUIData = m_pUIData; + if(pUIData == NULL) + return 1; + const _AtlUpdateUIMap* pMap = m_pUIMap; + while(pMap->m_nID != (WORD)-1) + { + if(pMap->m_wType & UPDUI_MENUPOPUP) + UIUpdateMenuBarElement(pMap->m_nID, pUIData, hMenu); + pMap++; + pUIData++; + } + return 0; + } + + LRESULT OnCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + bHandled = FALSE; + if(m_bBlockAccelerators && HIWORD(wParam) == 1) // accelerators only + { + int nID = LOWORD(wParam); + if((UIGetState(nID) & UPDUI_DISABLED) == UPDUI_DISABLED) + { + ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIBase::OnCommand - blocked disabled command 0x%4.4X\n"), nID); + bHandled = TRUE; // eat the command, UI item is disabled + } + } + return 0; + } + +// methods for setting UI element state + BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE) + { + const _AtlUpdateUIMap* pMap = m_pUIMap; + _AtlUpdateUIData* pUIData = m_pUIData; + if(pUIData == NULL) + return FALSE; + + for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) + { + if(nID == (int)pMap->m_nID) + { + if(bEnable) + { + if(pUIData->m_wState & UPDUI_DISABLED) + { + pUIData->m_wState |= pMap->m_wType; + pUIData->m_wState &= ~UPDUI_DISABLED; + } + } + else + { + if(!(pUIData->m_wState & UPDUI_DISABLED)) + { + pUIData->m_wState |= pMap->m_wType; + pUIData->m_wState |= UPDUI_DISABLED; + } + } + + if(bForceUpdate) + pUIData->m_wState |= pMap->m_wType; + if(pUIData->m_wState & pMap->m_wType) + m_wDirtyType |= pMap->m_wType; + + break; // found + } + } + + return TRUE; + } + + BOOL UISetCheck(int nID, int nCheck, BOOL bForceUpdate = FALSE) + { + const _AtlUpdateUIMap* pMap = m_pUIMap; + _AtlUpdateUIData* pUIData = m_pUIData; + if(pUIData == NULL) + return FALSE; + + for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) + { + if(nID == (int)pMap->m_nID) + { + switch(nCheck) + { + case 0: + if((pUIData->m_wState & UPDUI_CHECKED) || (pUIData->m_wState & UPDUI_CHECKED2)) + { + pUIData->m_wState |= pMap->m_wType; + pUIData->m_wState &= ~(UPDUI_CHECKED | UPDUI_CHECKED2); + } + break; + case 1: + if(!(pUIData->m_wState & UPDUI_CHECKED)) + { + pUIData->m_wState |= pMap->m_wType; + pUIData->m_wState &= ~UPDUI_CHECKED2; + pUIData->m_wState |= UPDUI_CHECKED; + } + break; + case 2: + if(!(pUIData->m_wState & UPDUI_CHECKED2)) + { + pUIData->m_wState |= pMap->m_wType; + pUIData->m_wState &= ~UPDUI_CHECKED; + pUIData->m_wState |= UPDUI_CHECKED2; + } + break; + } + + if(bForceUpdate) + pUIData->m_wState |= pMap->m_wType; + if(pUIData->m_wState & pMap->m_wType) + m_wDirtyType |= pMap->m_wType; + + break; // found + } + } + + return TRUE; + } + + // variant that supports bool (checked/not-checked, no intermediate state) + BOOL UISetCheck(int nID, bool bCheck, BOOL bForceUpdate = FALSE) + { + return UISetCheck(nID, bCheck ? 1 : 0, bForceUpdate); + } + + BOOL UISetRadio(int nID, BOOL bRadio, BOOL bForceUpdate = FALSE) + { + const _AtlUpdateUIMap* pMap = m_pUIMap; + _AtlUpdateUIData* pUIData = m_pUIData; + if(pUIData == NULL) + return FALSE; + + for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) + { + if(nID == (int)pMap->m_nID) + { + if(bRadio) + { + if(!(pUIData->m_wState & UPDUI_RADIO)) + { + pUIData->m_wState |= pMap->m_wType; + pUIData->m_wState |= UPDUI_RADIO; + } + } + else + { + if(pUIData->m_wState & UPDUI_RADIO) + { + pUIData->m_wState |= pMap->m_wType; + pUIData->m_wState &= ~UPDUI_RADIO; + } + } + + if(bForceUpdate) + pUIData->m_wState |= pMap->m_wType; + if(pUIData->m_wState & pMap->m_wType) + m_wDirtyType |= pMap->m_wType; + + break; // found + } + } + + return TRUE; + } + + BOOL UISetText(int nID, LPCTSTR lpstrText, BOOL bForceUpdate = FALSE) + { + const _AtlUpdateUIMap* pMap = m_pUIMap; + _AtlUpdateUIData* pUIData = m_pUIData; + if(pUIData == NULL) + return FALSE; + if(lpstrText == NULL) + lpstrText = _T(""); + + for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) + { + if(nID == (int)pMap->m_nID) + { + if(pUIData->m_lpstrText == NULL || lstrcmp(pUIData->m_lpstrText, lpstrText)) + { + delete [] pUIData->m_lpstrText; + pUIData->m_lpstrText = NULL; + int nStrLen = lstrlen(lpstrText); + ATLTRY(pUIData->m_lpstrText = new TCHAR[nStrLen + 1]); + if(pUIData->m_lpstrText == NULL) + { + ATLTRACE2(atlTraceUI, 0, _T("UISetText - memory allocation failed\n")); + break; + } + SecureHelper::strcpy_x(pUIData->m_lpstrText, nStrLen + 1, lpstrText); + pUIData->m_wState |= (UPDUI_TEXT | pMap->m_wType); + } + + if(bForceUpdate) + pUIData->m_wState |= (UPDUI_TEXT | pMap->m_wType); + if(pUIData->m_wState & pMap->m_wType) + m_wDirtyType |= pMap->m_wType; + + break; // found + } + } + + return TRUE; + } + + BOOL UISetDefault(int nID, BOOL bDefault, BOOL bForceUpdate = FALSE) + { + const _AtlUpdateUIMap* pMap = m_pUIMap; + _AtlUpdateUIData* pUIData = m_pUIData; + if(pUIData == NULL) + return FALSE; + + for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) + { + if(nID == (int)pMap->m_nID) + { + if(bDefault) + { + if((pUIData->m_wState & UPDUI_DEFAULT) == 0) + { + pUIData->m_wState |= pMap->m_wType; + pUIData->m_wState |= UPDUI_DEFAULT; + } + } + else + { + if((pUIData->m_wState & UPDUI_DEFAULT) != 0) + { + pUIData->m_wState |= pMap->m_wType; + pUIData->m_wState &= ~UPDUI_DEFAULT; + pUIData->m_wState |= UPDUI_CLEARDEFAULT; + } + } + + if(bForceUpdate) + pUIData->m_wState |= pMap->m_wType; + if(pUIData->m_wState & pMap->m_wType) + m_wDirtyType |= pMap->m_wType; + + break; // found + } + } + + return TRUE; + } + +// methods for complete state set/get + BOOL UISetState(int nID, DWORD dwState) + { + const _AtlUpdateUIMap* pMap = m_pUIMap; + _AtlUpdateUIData* pUIData = m_pUIData; + if(pUIData == NULL) + return FALSE; + for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) + { + if(nID == (int)pMap->m_nID) + { + pUIData->m_wState = (WORD)(dwState | pMap->m_wType); + m_wDirtyType |= pMap->m_wType; + break; // found + } + } + return TRUE; + } + + DWORD UIGetState(int nID) + { + const _AtlUpdateUIMap* pMap = m_pUIMap; + _AtlUpdateUIData* pUIData = m_pUIData; + if(pUIData == NULL) + return 0; + for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) + { + if(nID == (int)pMap->m_nID) + return pUIData->m_wState; + } + return 0; + } + +// methods for updating UI +#ifndef _WIN32_WCE + BOOL UIUpdateMenuBar(BOOL bForceUpdate = FALSE, BOOL bMainMenu = FALSE) + { + if(!(m_wDirtyType & UPDUI_MENUBAR) && !bForceUpdate) + return TRUE; + + const _AtlUpdateUIMap* pMap = m_pUIMap; + _AtlUpdateUIData* pUIData = m_pUIData; + if(pUIData == NULL) + return FALSE; + + while(pMap->m_nID != (WORD)-1) + { + for(int i = 0; i < m_UIElements.GetSize(); i++) + { + if(m_UIElements[i].m_wType == UPDUI_MENUBAR) + { + HMENU hMenu = ::GetMenu(m_UIElements[i].m_hWnd); + if(hMenu != NULL && (pUIData->m_wState & UPDUI_MENUBAR) && (pMap->m_wType & UPDUI_MENUBAR)) + UIUpdateMenuBarElement(pMap->m_nID, pUIData, hMenu); + } + if(bMainMenu) + ::DrawMenuBar(m_UIElements[i].m_hWnd); + } + pMap++; + pUIData->m_wState &= ~UPDUI_MENUBAR; + if(pUIData->m_wState & UPDUI_TEXT) + { + delete [] pUIData->m_lpstrText; + pUIData->m_lpstrText = NULL; + pUIData->m_wState &= ~UPDUI_TEXT; + } + pUIData++; + } + + m_wDirtyType &= ~UPDUI_MENUBAR; + return TRUE; + } +#endif // !_WIN32_WCE + + BOOL UIUpdateToolBar(BOOL bForceUpdate = FALSE) + { + if(!(m_wDirtyType & UPDUI_TOOLBAR) && !bForceUpdate) + return TRUE; + + const _AtlUpdateUIMap* pMap = m_pUIMap; + _AtlUpdateUIData* pUIData = m_pUIData; + if(pUIData == NULL) + return FALSE; + + while(pMap->m_nID != (WORD)-1) + { + for(int i = 0; i < m_UIElements.GetSize(); i++) + { + if(m_UIElements[i].m_wType == UPDUI_TOOLBAR) + { + if((pUIData->m_wState & UPDUI_TOOLBAR) && (pMap->m_wType & UPDUI_TOOLBAR)) + UIUpdateToolBarElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd); + } + } + pMap++; + pUIData->m_wState &= ~UPDUI_TOOLBAR; + pUIData++; + } + + m_wDirtyType &= ~UPDUI_TOOLBAR; + return TRUE; + } + + BOOL UIUpdateStatusBar(BOOL bForceUpdate = FALSE) + { + if(!(m_wDirtyType & UPDUI_STATUSBAR) && !bForceUpdate) + return TRUE; + + const _AtlUpdateUIMap* pMap = m_pUIMap; + _AtlUpdateUIData* pUIData = m_pUIData; + if(pUIData == NULL) + return FALSE; + + while(pMap->m_nID != (WORD)-1) + { + for(int i = 0; i < m_UIElements.GetSize(); i++) + { + if(m_UIElements[i].m_wType == UPDUI_STATUSBAR) + { + if((pUIData->m_wState & UPDUI_STATUSBAR) && (pMap->m_wType & UPDUI_STATUSBAR)) + UIUpdateStatusBarElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd); + } + } + pMap++; + pUIData->m_wState &= ~UPDUI_STATUSBAR; + if(pUIData->m_wState & UPDUI_TEXT) + { + delete [] pUIData->m_lpstrText; + pUIData->m_lpstrText = NULL; + pUIData->m_wState &= ~UPDUI_TEXT; + } + pUIData++; + } + + m_wDirtyType &= ~UPDUI_STATUSBAR; + return TRUE; + } + + BOOL UIUpdateChildWindows(BOOL bForceUpdate = FALSE) + { + if(!(m_wDirtyType & UPDUI_CHILDWINDOW) && !bForceUpdate) + return TRUE; + + const _AtlUpdateUIMap* pMap = m_pUIMap; + _AtlUpdateUIData* pUIData = m_pUIData; + if(pUIData == NULL) + return FALSE; + + while(pMap->m_nID != (WORD)-1) + { + for(int i = 0; i < m_UIElements.GetSize(); i++) + { + if(m_UIElements[i].m_wType == UPDUI_CHILDWINDOW) + { + if((pUIData->m_wState & UPDUI_CHILDWINDOW) && (pMap->m_wType & UPDUI_CHILDWINDOW)) + UIUpdateChildWindow(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd); + } + } + pMap++; + pUIData->m_wState &= ~UPDUI_CHILDWINDOW; + if(pUIData->m_wState & UPDUI_TEXT) + { + delete [] pUIData->m_lpstrText; + pUIData->m_lpstrText = NULL; + pUIData->m_wState &= ~UPDUI_TEXT; + } + pUIData++; + } + + m_wDirtyType &= ~UPDUI_CHILDWINDOW; + return TRUE; + } + +// internal element specific methods + static void UIUpdateMenuBarElement(int nID, _AtlUpdateUIData* pUIData, HMENU hMenu) + { +#ifndef _WIN32_WCE + if((pUIData->m_wState & UPDUI_CLEARDEFAULT) != 0) + { + ::SetMenuDefaultItem(hMenu, (UINT)-1, 0); + pUIData->m_wState &= ~UPDUI_CLEARDEFAULT; + } +#endif // !_WIN32_WCE + + CMenuItemInfo mii; + mii.fMask = MIIM_STATE; + mii.wID = nID; + +#ifndef _WIN32_WCE + if((pUIData->m_wState & UPDUI_DISABLED) != 0) + mii.fState |= MFS_DISABLED | MFS_GRAYED; + else + mii.fState |= MFS_ENABLED; + + if((pUIData->m_wState & UPDUI_CHECKED) != 0) + mii.fState |= MFS_CHECKED; + else + mii.fState |= MFS_UNCHECKED; + + if((pUIData->m_wState & UPDUI_DEFAULT) != 0) + mii.fState |= MFS_DEFAULT; +#else // CE specific + // ::SetMenuItemInfo() can't disable or check menu items + // on Windows CE, so we have to do that directly + UINT uEnable = MF_BYCOMMAND; + if((pUIData->m_wState & UPDUI_DISABLED) != 0) + uEnable |= MF_GRAYED; + else + uEnable |= MF_ENABLED; + ::EnableMenuItem(hMenu, nID, uEnable); + + UINT uCheck = MF_BYCOMMAND; + if((pUIData->m_wState & UPDUI_CHECKED) != 0) + uCheck |= MF_CHECKED; + else + uCheck |= MF_UNCHECKED; + ::CheckMenuItem(hMenu, nID, uCheck); +#endif // _WIN32_WCE + + if((pUIData->m_wState & UPDUI_TEXT) != 0) + { + CMenuItemInfo miiNow; + miiNow.fMask = MIIM_TYPE; + miiNow.wID = nID; + if(::GetMenuItemInfo(hMenu, nID, FALSE, &miiNow)) + { + mii.fMask |= MIIM_TYPE; + // MFT_BITMAP and MFT_SEPARATOR don't go together with MFT_STRING +#ifndef _WIN32_WCE + mii.fType |= (miiNow.fType & ~(MFT_BITMAP | MFT_SEPARATOR)) | MFT_STRING; +#else // CE specific + mii.fType |= (miiNow.fType & ~(MFT_SEPARATOR)) | MFT_STRING; +#endif // _WIN32_WCE + mii.dwTypeData = pUIData->m_lpstrText; + } + } + + ::SetMenuItemInfo(hMenu, nID, FALSE, &mii); + } + + static void UIUpdateToolBarElement(int nID, _AtlUpdateUIData* pUIData, HWND hWndToolBar) + { + // Note: only handles enabled/disabled, checked state, and radio (press) + ::SendMessage(hWndToolBar, TB_ENABLEBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_DISABLED) ? FALSE : TRUE); + ::SendMessage(hWndToolBar, TB_CHECKBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_CHECKED) ? TRUE : FALSE); + ::SendMessage(hWndToolBar, TB_INDETERMINATE, nID, (LPARAM)(pUIData->m_wState & UPDUI_CHECKED2) ? TRUE : FALSE); + ::SendMessage(hWndToolBar, TB_PRESSBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_RADIO) ? TRUE : FALSE); + } + + static void UIUpdateStatusBarElement(int nID, _AtlUpdateUIData* pUIData, HWND hWndStatusBar) + { + // Note: only handles text + if(pUIData->m_wState & UPDUI_TEXT) + ::SendMessage(hWndStatusBar, SB_SETTEXT, nID, (LPARAM)pUIData->m_lpstrText); + } + + static void UIUpdateChildWindow(int nID, _AtlUpdateUIData* pUIData, HWND hWnd) + { + HWND hChild = ::GetDlgItem(hWnd, nID); + + ::EnableWindow(hChild, (pUIData->m_wState & UPDUI_DISABLED) ? FALSE : TRUE); + // for check and radio, assume that window is a button + int nCheck = BST_UNCHECKED; + if(pUIData->m_wState & UPDUI_CHECKED || pUIData->m_wState & UPDUI_RADIO) + nCheck = BST_CHECKED; + else if(pUIData->m_wState & UPDUI_CHECKED2) + nCheck = BST_INDETERMINATE; + ::SendMessage(hChild, BM_SETCHECK, nCheck, 0L); + if(pUIData->m_wState & UPDUI_DEFAULT) + { + DWORD dwRet = (DWORD)::SendMessage(hWnd, DM_GETDEFID, 0, 0L); + if(HIWORD(dwRet) == DC_HASDEFID) + { + HWND hOldDef = ::GetDlgItem(hWnd, (int)(short)LOWORD(dwRet)); + // remove BS_DEFPUSHBUTTON + ::SendMessage(hOldDef, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0)); + } + ::SendMessage(hWnd, DM_SETDEFID, nID, 0L); + } + if(pUIData->m_wState & UPDUI_TEXT) + ::SetWindowText(hChild, pUIData->m_lpstrText); + } +}; + +template +class CUpdateUI : public CUpdateUIBase +{ +public: + CUpdateUI() + { + T* pT = static_cast(this); + pT; + const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap(); + m_pUIMap = pMap; + ATLASSERT(m_pUIMap != NULL); + int nCount; + for(nCount = 1; pMap->m_nID != (WORD)-1; nCount++) + pMap++; + + // check for duplicates (debug only) +#ifdef _DEBUG + for(int i = 0; i < nCount; i++) + { + for(int j = 0; j < nCount; j++) + { + // shouldn't have duplicates in the update UI map + if(i != j) + ATLASSERT(m_pUIMap[j].m_nID != m_pUIMap[i].m_nID); + } + } +#endif // _DEBUG + + ATLTRY(m_pUIData = new _AtlUpdateUIData[nCount]); + ATLASSERT(m_pUIData != NULL); + + if(m_pUIData != NULL) + memset(m_pUIData, 0, sizeof(_AtlUpdateUIData) * nCount); + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CDynamicUpdateUI - allows update elements to dynamically added and removed +// in addition to a static update UI map + +template +class CDynamicUpdateUI : public CUpdateUIBase +{ +public: +// Data members + ATL::CSimpleArray<_AtlUpdateUIMap> m_arrUIMap; // copy of the static UI data + ATL::CSimpleArray<_AtlUpdateUIData> m_arrUIData; // instance UI data + +// Constructor/destructor + CDynamicUpdateUI() + { + T* pT = static_cast(this); + pT; + const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap(); + ATLASSERT(pMap != NULL); + + for(;;) + { + BOOL bRet = m_arrUIMap.Add(*(_AtlUpdateUIMap*)pMap); + ATLASSERT(bRet); + + if(bRet != FALSE) + { + _AtlUpdateUIData data = { 0, NULL }; + bRet = m_arrUIData.Add(data); + ATLASSERT(bRet); + } + + if(pMap->m_nID == (WORD)-1) + break; + + pMap++; + } + + ATLASSERT(m_arrUIMap.GetSize() == m_arrUIData.GetSize()); + +#ifdef _DEBUG + // check for duplicates (debug only) + for(int i = 0; i < m_arrUIMap.GetSize(); i++) + { + for(int j = 0; j < m_arrUIMap.GetSize(); j++) + { + // shouldn't have duplicates in the update UI map + if(i != j) + ATLASSERT(m_arrUIMap[j].m_nID != m_arrUIMap[i].m_nID); + } + } +#endif // _DEBUG + + // Set internal data pointers to point to the new data arrays + m_pUIMap = m_arrUIMap.m_aT; + m_pUIData = m_arrUIData.m_aT; + } + + ~CDynamicUpdateUI() + { + for(int i = 0; i < m_arrUIData.GetSize(); i++) + { + if((m_arrUIData[i].m_wState & UPDUI_TEXT) != 0) + delete [] m_arrUIData[i].m_lpstrText; + } + + // Reset internal data pointers (memory will be released by CSimpleArray d-tor) + m_pUIMap = NULL; + m_pUIData = NULL; + } + +// Methods for dynamically adding and removing update elements + bool UIAddUpdateElement(WORD nID, WORD wType) + { + // check for duplicates + for(int i = 0; i < m_arrUIMap.GetSize(); i++) + { + // shouldn't have duplicates in the update UI map + ATLASSERT(m_arrUIMap[i].m_nID != nID); + if(m_arrUIMap[i].m_nID == nID) + return false; + } + + bool bRetVal = false; + + // Add new end element + _AtlUpdateUIMap uumEnd = { (WORD)-1, 0 }; + BOOL bRet = m_arrUIMap.Add(uumEnd); + ATLASSERT(bRet); + + if(bRet != FALSE) + { + _AtlUpdateUIData uud = { 0, NULL }; + bRet = m_arrUIData.Add(uud); + ATLASSERT(bRet); + + // Set new data to the previous end element + if(bRet != FALSE) + { + int nSize = m_arrUIMap.GetSize(); + _AtlUpdateUIMap uum = { nID, wType }; + m_arrUIMap.SetAtIndex(nSize - 2, uum); + m_arrUIData.SetAtIndex(nSize - 2, uud); + + // Set internal data pointers again, just in case that memory moved + m_pUIMap = m_arrUIMap.m_aT; + m_pUIData = m_arrUIData.m_aT; + + bRetVal = true; + } + } + + return bRetVal; + } + + bool UIRemoveUpdateElement(WORD nID) + { + bool bRetVal = false; + + for(int i = 0; i < m_arrUIMap.GetSize(); i++) + { + if(m_arrUIMap[i].m_nID == nID) + { + BOOL bRet = m_arrUIMap.RemoveAt(i); + ATLASSERT(bRet); + bRet = m_arrUIData.RemoveAt(i); + ATLASSERT(bRet); + + bRetVal = true; + break; + } + } + + return bRetVal; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CDialogResize - provides support for resizing dialog controls +// (works for any window that has child controls) + +// Put CDialogResize in the list of base classes for a dialog (or even plain window), +// then implement DLGRESIZE map by specifying controls and groups of control +// and using DLSZ_* values to specify how are they supposed to be resized. +// +// Notes: +// - Resizeable border (WS_THICKFRAME style) should be set in the dialog template +// for top level dialogs (popup or overlapped), so that users can resize the dialog. +// - Some flags cannot be combined; for instance DLSZ_CENTER_X overrides DLSZ_SIZE_X, +// DLSZ_SIZE_X overrides DLSZ_MOVE_X. X and Y flags can be combined. +// - Order of controls is important - group controls are resized and moved based +// on the position of the previous control in a group. + +// dialog resize map macros +#define BEGIN_DLGRESIZE_MAP(thisClass) \ + static const _AtlDlgResizeMap* GetDlgResizeMap() \ + { \ + static const _AtlDlgResizeMap theMap[] = \ + { + +#define END_DLGRESIZE_MAP() \ + { -1, 0 }, \ + }; \ + return theMap; \ + } + +#define DLGRESIZE_CONTROL(id, flags) \ + { id, flags }, + +#define BEGIN_DLGRESIZE_GROUP() \ + { -1, _DLSZ_BEGIN_GROUP }, + +#define END_DLGRESIZE_GROUP() \ + { -1, _DLSZ_END_GROUP }, + + +template +class CDialogResize +{ +public: +// Data declarations and members + enum + { + DLSZ_SIZE_X = 0x00000001, + DLSZ_SIZE_Y = 0x00000002, + DLSZ_MOVE_X = 0x00000004, + DLSZ_MOVE_Y = 0x00000008, + DLSZ_REPAINT = 0x00000010, + DLSZ_CENTER_X = 0x00000020, + DLSZ_CENTER_Y = 0x00000040, + + // internal use only + _DLSZ_BEGIN_GROUP = 0x00001000, + _DLSZ_END_GROUP = 0x00002000, + _DLSZ_GRIPPER = 0x00004000 + }; + + struct _AtlDlgResizeMap + { + int m_nCtlID; + DWORD m_dwResizeFlags; + }; + + struct _AtlDlgResizeData + { + int m_nCtlID; + DWORD m_dwResizeFlags; + RECT m_rect; + + int GetGroupCount() const + { + return (int)LOBYTE(HIWORD(m_dwResizeFlags)); + } + + void SetGroupCount(int nCount) + { + ATLASSERT(nCount > 0 && nCount < 256); + DWORD dwCount = (DWORD)MAKELONG(0, MAKEWORD(nCount, 0)); + m_dwResizeFlags &= 0xFF00FFFF; + m_dwResizeFlags |= dwCount; + } + + bool operator ==(const _AtlDlgResizeData& r) const + { return (m_nCtlID == r.m_nCtlID && m_dwResizeFlags == r.m_dwResizeFlags); } + }; + + ATL::CSimpleArray<_AtlDlgResizeData> m_arrData; + SIZE m_sizeDialog; + POINT m_ptMinTrackSize; + bool m_bGripper; + + +// Constructor + CDialogResize() : m_bGripper(false) + { + m_sizeDialog.cx = 0; + m_sizeDialog.cy = 0; + m_ptMinTrackSize.x = -1; + m_ptMinTrackSize.y = -1; + } + +// Operations + void DlgResize_Init(bool bAddGripper = true, bool bUseMinTrackSize = true, DWORD dwForceStyle = WS_CLIPCHILDREN) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + + DWORD dwStyle = pT->GetStyle(); + +#ifdef _DEBUG + // Debug only: Check if top level dialogs have a resizeable border. + if(((dwStyle & WS_CHILD) == 0) && ((dwStyle & WS_THICKFRAME) == 0)) + ATLTRACE2(atlTraceUI, 0, _T("DlgResize_Init - warning: top level dialog without the WS_THICKFRAME style - user cannot resize it\n")); +#endif // _DEBUG + + // Force specified styles (default WS_CLIPCHILDREN reduces flicker) + if((dwStyle & dwForceStyle) != dwForceStyle) + pT->ModifyStyle(0, dwForceStyle); + + // Adding this style removes an empty icon that dialogs with WS_THICKFRAME have. + // Setting icon to NULL is required when XP themes are active. + // Note: This will not prevent adding an icon for the dialog using SetIcon() + if((dwStyle & WS_CHILD) == 0) + { + pT->ModifyStyleEx(0, WS_EX_DLGMODALFRAME); + if(pT->GetIcon(FALSE) == NULL) + pT->SetIcon(NULL, FALSE); + } + + // Cleanup in case of multiple initialization + // block: first check for the gripper control, destroy it if needed + { + ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_BAR); + if(wndGripper.IsWindow() && m_arrData.GetSize() > 0 && (m_arrData[0].m_dwResizeFlags & _DLSZ_GRIPPER) != 0) + wndGripper.DestroyWindow(); + } + // clear out everything else + m_arrData.RemoveAll(); + m_sizeDialog.cx = 0; + m_sizeDialog.cy = 0; + m_ptMinTrackSize.x = -1; + m_ptMinTrackSize.y = -1; + + // Get initial dialog client size + RECT rectDlg = { 0 }; + pT->GetClientRect(&rectDlg); + m_sizeDialog.cx = rectDlg.right; + m_sizeDialog.cy = rectDlg.bottom; + +#ifndef _WIN32_WCE + // Create gripper if requested + m_bGripper = false; + if(bAddGripper) + { + // shouldn't exist already + ATLASSERT(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR))); + if(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR))) + { + ATL::CWindow wndGripper; + wndGripper.Create(_T("SCROLLBAR"), pT->m_hWnd, rectDlg, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SBS_SIZEBOX | SBS_SIZEGRIP | SBS_SIZEBOXBOTTOMRIGHTALIGN, 0, ATL_IDW_STATUS_BAR); + ATLASSERT(wndGripper.IsWindow()); + if(wndGripper.IsWindow()) + { + m_bGripper = true; + RECT rectCtl = { 0 }; + wndGripper.GetWindowRect(&rectCtl); + ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2); + _AtlDlgResizeData data = { ATL_IDW_STATUS_BAR, DLSZ_MOVE_X | DLSZ_MOVE_Y | DLSZ_REPAINT | _DLSZ_GRIPPER, { rectCtl.left, rectCtl.top, rectCtl.right, rectCtl.bottom } }; + m_arrData.Add(data); + } + } + } +#else // CE specific + bAddGripper; // avoid level 4 warning +#endif // _WIN32_WCE + + // Get min track position if requested + if(bUseMinTrackSize) + { + if((dwStyle & WS_CHILD) != 0) + { + RECT rect = { 0 }; + pT->GetClientRect(&rect); + m_ptMinTrackSize.x = rect.right - rect.left; + m_ptMinTrackSize.y = rect.bottom - rect.top; + } + else + { + RECT rect = { 0 }; + pT->GetWindowRect(&rect); + m_ptMinTrackSize.x = rect.right - rect.left; + m_ptMinTrackSize.y = rect.bottom - rect.top; + } + } + + // Walk the map and initialize data + const _AtlDlgResizeMap* pMap = pT->GetDlgResizeMap(); + ATLASSERT(pMap != NULL); + int nGroupStart = -1; + for(int nCount = 1; !(pMap->m_nCtlID == -1 && pMap->m_dwResizeFlags == 0); nCount++, pMap++) + { + if(pMap->m_nCtlID == -1) + { + switch(pMap->m_dwResizeFlags) + { + case _DLSZ_BEGIN_GROUP: + ATLASSERT(nGroupStart == -1); + nGroupStart = m_arrData.GetSize(); + break; + case _DLSZ_END_GROUP: + { + ATLASSERT(nGroupStart != -1); + int nGroupCount = m_arrData.GetSize() - nGroupStart; + m_arrData[nGroupStart].SetGroupCount(nGroupCount); + nGroupStart = -1; + } + break; + default: + ATLASSERT(FALSE && _T("Invalid DLGRESIZE Map Entry")); + break; + } + } + else + { + // this ID conflicts with the default gripper one + ATLASSERT(m_bGripper ? (pMap->m_nCtlID != ATL_IDW_STATUS_BAR) : TRUE); + + ATL::CWindow ctl = pT->GetDlgItem(pMap->m_nCtlID); + ATLASSERT(ctl.IsWindow()); + RECT rectCtl = { 0 }; + ctl.GetWindowRect(&rectCtl); + ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2); + + DWORD dwGroupFlag = (nGroupStart != -1 && m_arrData.GetSize() == nGroupStart) ? _DLSZ_BEGIN_GROUP : 0; + _AtlDlgResizeData data = { pMap->m_nCtlID, pMap->m_dwResizeFlags | dwGroupFlag, { rectCtl.left, rectCtl.top, rectCtl.right, rectCtl.bottom } }; + m_arrData.Add(data); + } + } + ATLASSERT((nGroupStart == -1) && _T("No End Group Entry in the DLGRESIZE Map")); + } + + void DlgResize_UpdateLayout(int cxWidth, int cyHeight) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + + // Restrict minimum size if requested + if(((pT->GetStyle() & WS_CHILD) != 0) && m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1) + { + if(cxWidth < m_ptMinTrackSize.x) + cxWidth = m_ptMinTrackSize.x; + if(cyHeight < m_ptMinTrackSize.y) + cyHeight = m_ptMinTrackSize.y; + } + + BOOL bVisible = pT->IsWindowVisible(); + if(bVisible) + pT->SetRedraw(FALSE); + + for(int i = 0; i < m_arrData.GetSize(); i++) + { + if((m_arrData[i].m_dwResizeFlags & _DLSZ_BEGIN_GROUP) != 0) // start of a group + { + int nGroupCount = m_arrData[i].GetGroupCount(); + ATLASSERT(nGroupCount > 0 && i + nGroupCount - 1 < m_arrData.GetSize()); + RECT rectGroup = m_arrData[i].m_rect; + + int j = 1; + for(j = 1; j < nGroupCount; j++) + { + rectGroup.left = min(rectGroup.left, m_arrData[i + j].m_rect.left); + rectGroup.top = min(rectGroup.top, m_arrData[i + j].m_rect.top); + rectGroup.right = max(rectGroup.right, m_arrData[i + j].m_rect.right); + rectGroup.bottom = max(rectGroup.bottom, m_arrData[i + j].m_rect.bottom); + } + + for(j = 0; j < nGroupCount; j++) + { + _AtlDlgResizeData* pDataPrev = NULL; + if(j > 0) + pDataPrev = &(m_arrData[i + j - 1]); + pT->DlgResize_PositionControl(cxWidth, cyHeight, rectGroup, m_arrData[i + j], true, pDataPrev); + } + + i += nGroupCount - 1; // increment to skip all group controls + } + else // one control entry + { + RECT rectGroup = { 0, 0, 0, 0 }; + pT->DlgResize_PositionControl(cxWidth, cyHeight, rectGroup, m_arrData[i], false); + } + } + + if(bVisible) + pT->SetRedraw(TRUE); + + pT->RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); + } + +// Message map and handlers + BEGIN_MSG_MAP(CDialogResize) + MESSAGE_HANDLER(WM_SIZE, OnSize) +#ifndef _WIN32_WCE + MESSAGE_HANDLER(WM_GETMINMAXINFO, OnGetMinMaxInfo) +#endif // _WIN32_WCE + END_MSG_MAP() + + LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); +#ifndef _WIN32_WCE + if(m_bGripper) + { + ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_BAR); + if(wParam == SIZE_MAXIMIZED) + wndGripper.ShowWindow(SW_HIDE); + else if(wParam == SIZE_RESTORED) + wndGripper.ShowWindow(SW_SHOW); + } +#endif // _WIN32_WCE + if(wParam != SIZE_MINIMIZED) + { + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DlgResize_UpdateLayout(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + } + return 0; + } + +#ifndef _WIN32_WCE + LRESULT OnGetMinMaxInfo(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) + { + if(m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1) + { + LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam; + lpMMI->ptMinTrackSize = m_ptMinTrackSize; + } + return 0; + } +#endif // _WIN32_WCE + +// Implementation + bool DlgResize_PositionControl(int cxWidth, int cyHeight, RECT& rectGroup, _AtlDlgResizeData& data, bool bGroup, + _AtlDlgResizeData* pDataPrev = NULL) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + ATL::CWindow ctl; + RECT rectCtl = { 0 }; + + ctl = pT->GetDlgItem(data.m_nCtlID); + if(!ctl.GetWindowRect(&rectCtl)) + return false; + ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2); + + if(bGroup) + { + if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0) + { + int cxRight = rectGroup.right + cxWidth - m_sizeDialog.cx; + int cxCtl = data.m_rect.right - data.m_rect.left; + rectCtl.left = rectGroup.left + (cxRight - rectGroup.left - cxCtl) / 2; + rectCtl.right = rectCtl.left + cxCtl; + } + else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE_X)) != 0) + { + rectCtl.left = rectGroup.left + ::MulDiv(data.m_rect.left - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidth - m_sizeDialog.cx), rectGroup.right - rectGroup.left); + + if((data.m_dwResizeFlags & DLSZ_SIZE_X) != 0) + { + rectCtl.right = rectGroup.left + ::MulDiv(data.m_rect.right - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidth - m_sizeDialog.cx), rectGroup.right - rectGroup.left); + + if(pDataPrev != NULL) + { + ATL::CWindow ctlPrev = pT->GetDlgItem(pDataPrev->m_nCtlID); + RECT rcPrev = { 0 }; + ctlPrev.GetWindowRect(&rcPrev); + ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcPrev, 2); + int dxAdjust = (rectCtl.left - rcPrev.right) - (data.m_rect.left - pDataPrev->m_rect.right); + rcPrev.right += dxAdjust; + ctlPrev.SetWindowPos(NULL, &rcPrev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE); + } + } + else + { + rectCtl.right = rectCtl.left + (data.m_rect.right - data.m_rect.left); + } + } + + if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0) + { + int cyBottom = rectGroup.bottom + cyHeight - m_sizeDialog.cy; + int cyCtl = data.m_rect.bottom - data.m_rect.top; + rectCtl.top = rectGroup.top + (cyBottom - rectGroup.top - cyCtl) / 2; + rectCtl.bottom = rectCtl.top + cyCtl; + } + else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE_Y)) != 0) + { + rectCtl.top = rectGroup.top + ::MulDiv(data.m_rect.top - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeDialog.cy), rectGroup.bottom - rectGroup.top); + + if((data.m_dwResizeFlags & DLSZ_SIZE_Y) != 0) + { + rectCtl.bottom = rectGroup.top + ::MulDiv(data.m_rect.bottom - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeDialog.cy), rectGroup.bottom - rectGroup.top); + + if(pDataPrev != NULL) + { + ATL::CWindow ctlPrev = pT->GetDlgItem(pDataPrev->m_nCtlID); + RECT rcPrev = { 0 }; + ctlPrev.GetWindowRect(&rcPrev); + ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcPrev, 2); + int dxAdjust = (rectCtl.top - rcPrev.bottom) - (data.m_rect.top - pDataPrev->m_rect.bottom); + rcPrev.bottom += dxAdjust; + ctlPrev.SetWindowPos(NULL, &rcPrev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE); + } + } + else + { + rectCtl.bottom = rectCtl.top + (data.m_rect.bottom - data.m_rect.top); + } + } + } + else // no group + { + if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0) + { + int cxCtl = data.m_rect.right - data.m_rect.left; + rectCtl.left = (cxWidth - cxCtl) / 2; + rectCtl.right = rectCtl.left + cxCtl; + } + else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE_X)) != 0) + { + rectCtl.right = data.m_rect.right + (cxWidth - m_sizeDialog.cx); + + if((data.m_dwResizeFlags & DLSZ_MOVE_X) != 0) + rectCtl.left = rectCtl.right - (data.m_rect.right - data.m_rect.left); + } + + if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0) + { + int cyCtl = data.m_rect.bottom - data.m_rect.top; + rectCtl.top = (cyHeight - cyCtl) / 2; + rectCtl.bottom = rectCtl.top + cyCtl; + } + else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE_Y)) != 0) + { + rectCtl.bottom = data.m_rect.bottom + (cyHeight - m_sizeDialog.cy); + + if((data.m_dwResizeFlags & DLSZ_MOVE_Y) != 0) + rectCtl.top = rectCtl.bottom - (data.m_rect.bottom - data.m_rect.top); + } + } + + if((data.m_dwResizeFlags & DLSZ_REPAINT) != 0) + ctl.Invalidate(); + + if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_SIZE_Y | DLSZ_MOVE_X | DLSZ_MOVE_Y | DLSZ_REPAINT | DLSZ_CENTER_X | DLSZ_CENTER_Y)) != 0) + ctl.SetWindowPos(NULL, &rectCtl, SWP_NOZORDER | SWP_NOACTIVATE); + + return true; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CDoubleBufferImpl - Provides double-buffer painting support to any window + +template +class CDoubleBufferImpl +{ +public: +// Overrideables + void DoPaint(CDCHandle /*dc*/) + { + // must be implemented in a derived class + ATLASSERT(FALSE); + } + +// Message map and handlers + BEGIN_MSG_MAP(CDoubleBufferImpl) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) + MESSAGE_HANDLER(WM_PAINT, OnPaint) +#ifndef _WIN32_WCE + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) +#endif // !_WIN32_WCE + END_MSG_MAP() + + LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return 1; // no background painting needed + } + + LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + + if(wParam != NULL) + { + RECT rect = { 0 }; + pT->GetClientRect(&rect); + CMemoryDC dcMem((HDC)wParam, rect); + pT->DoPaint(dcMem.m_hDC); + } + else + { + CPaintDC dc(pT->m_hWnd); + CMemoryDC dcMem(dc.m_hDC, dc.m_ps.rcPaint); + pT->DoPaint(dcMem.m_hDC); + } + + return 0; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CDoubleBufferWindowImpl - Implements a double-buffer painting window + +template +class ATL_NO_VTABLE CDoubleBufferWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CDoubleBufferImpl< T > +{ +public: + BEGIN_MSG_MAP(CDoubleBufferWindowImpl) + CHAIN_MSG_MAP(CDoubleBufferImpl< T >) + END_MSG_MAP() +}; + + +// command bar support +#if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) + #undef CBRM_GETMENU + #undef CBRM_TRACKPOPUPMENU + #undef CBRM_GETCMDBAR + #undef CBRPOPUPMENU +#endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) + +}; // namespace WTL + +#endif // __ATLFRAME_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlgdi.h b/Client/Client/GUI/BKWin/wtl/atlgdi.h new file mode 100644 index 00000000..510f1e74 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlgdi.h @@ -0,0 +1,3847 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLGDI_H__ +#define __ATLGDI_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifndef __ATLAPP_H__ + #error atlgdi.h requires atlapp.h to be included first +#endif + + +// protect template members from windowsx.h macros +#ifdef _INC_WINDOWSX + #undef CopyRgn + #undef CreateBrush + #undef CreatePen + #undef SelectBrush + #undef SelectPen + #undef SelectFont + #undef SelectBitmap +#endif // _INC_WINDOWSX + +// required libraries +#if !defined(_ATL_NO_MSIMG) && !defined(_WIN32_WCE) + #pragma comment(lib, "msimg32.lib") +#endif // !defined(_ATL_NO_MSIMG) && !defined(_WIN32_WCE) +#if !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE) + #pragma comment(lib, "opengl32.lib") +#endif // !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE) + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CPenT +// CBrushT +// CLogFont +// CFontT +// CBitmapT +// CPaletteT +// CRgnT +// CDCT +// CPaintDC +// CClientDC +// CWindowDC +// CMemoryDC +// CEnhMetaFileInfo +// CEnhMetaFileT +// CEnhMetaFileDC +// +// Global functions: +// AtlGetBitmapResourceInfo() +// AtlGetBitmapResourceBitsPerPixel() +// AtlIsAlphaBitmapResource() +// AtlIsDib16() +// AtlGetDibColorTableSize() +// AtlGetDibNumColors(), +// AtlGetDibBitmap() +// AtlCopyBitmap() +// AtlCreatePackedDib16() +// AtlSetClipboardDib16() +// AtlGetClipboardDib() + + +namespace WTL +{ + +/////////////////////////////////////////////////////////////////////////////// +// Bitmap resource helpers to extract bitmap information for a bitmap resource + +inline LPBITMAPINFOHEADER AtlGetBitmapResourceInfo(HMODULE hModule, ATL::_U_STRINGorID image) +{ + HRSRC hResource = ::FindResource(hModule, image.m_lpstr, RT_BITMAP); + ATLASSERT(hResource != NULL); + HGLOBAL hGlobal = ::LoadResource(hModule, hResource); + ATLASSERT(hGlobal != NULL); + LPBITMAPINFOHEADER pBitmapInfoHeader = (LPBITMAPINFOHEADER)::LockResource(hGlobal); + ATLASSERT(pBitmapInfoHeader != NULL); + return pBitmapInfoHeader; +} + +inline WORD AtlGetBitmapResourceBitsPerPixel(HMODULE hModule, ATL::_U_STRINGorID image) +{ + LPBITMAPINFOHEADER pBitmapInfoHeader = AtlGetBitmapResourceInfo(hModule, image); + ATLASSERT(pBitmapInfoHeader != NULL); + return pBitmapInfoHeader->biBitCount; +} + +inline WORD AtlGetBitmapResourceBitsPerPixel(ATL::_U_STRINGorID image) +{ + return AtlGetBitmapResourceBitsPerPixel(ModuleHelper::GetResourceInstance(), image); +} + +/////////////////////////////////////////////////////////////////////////////// +// 32-bit (alpha channel) bitmap resource helper + +// Note: 32-bit (alpha channel) images work only on Windows XP with Common Controls version 6. +// If you want your app to work on older version of Windows, load non-alpha images if Common +// Controls version is less than 6. + +inline bool AtlIsAlphaBitmapResource(ATL::_U_STRINGorID image) +{ + return (AtlGetBitmapResourceBitsPerPixel(image) == 32); +} + + +/////////////////////////////////////////////////////////////////////////////// +// CPen + +template +class CPenT +{ +public: +// Data members + HPEN m_hPen; + +// Constructor/destructor/operators + CPenT(HPEN hPen = NULL) : m_hPen(hPen) + { } + + ~CPenT() + { + if(t_bManaged && m_hPen != NULL) + DeleteObject(); + } + + CPenT& operator =(HPEN hPen) + { + Attach(hPen); + return *this; + } + + void Attach(HPEN hPen) + { + if(t_bManaged && m_hPen != NULL && m_hPen != hPen) + ::DeleteObject(m_hPen); + m_hPen = hPen; + } + + HPEN Detach() + { + HPEN hPen = m_hPen; + m_hPen = NULL; + return hPen; + } + + operator HPEN() const { return m_hPen; } + + bool IsNull() const { return (m_hPen == NULL); } + +// Create methods + HPEN CreatePen(int nPenStyle, int nWidth, COLORREF crColor) + { + ATLASSERT(m_hPen == NULL); + m_hPen = ::CreatePen(nPenStyle, nWidth, crColor); + return m_hPen; + } + +#ifndef _WIN32_WCE + HPEN CreatePen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount = 0, const DWORD* lpStyle = NULL) + { + ATLASSERT(m_hPen == NULL); + m_hPen = ::ExtCreatePen(nPenStyle, nWidth, pLogBrush, nStyleCount, lpStyle); + return m_hPen; + } +#endif // !_WIN32_WCE + + HPEN CreatePenIndirect(LPLOGPEN lpLogPen) + { + ATLASSERT(m_hPen == NULL); + m_hPen = ::CreatePenIndirect(lpLogPen); + return m_hPen; + } + + BOOL DeleteObject() + { + ATLASSERT(m_hPen != NULL); + BOOL bRet = ::DeleteObject(m_hPen); + if(bRet) + m_hPen = NULL; + return bRet; + } + +// Attributes + int GetLogPen(LOGPEN* pLogPen) const + { + ATLASSERT(m_hPen != NULL); + return ::GetObject(m_hPen, sizeof(LOGPEN), pLogPen); + } + + bool GetLogPen(LOGPEN& LogPen) const + { + ATLASSERT(m_hPen != NULL); + return (::GetObject(m_hPen, sizeof(LOGPEN), &LogPen) == sizeof(LOGPEN)); + } + +#ifndef _WIN32_WCE + int GetExtLogPen(EXTLOGPEN* pLogPen) const + { + ATLASSERT(m_hPen != NULL); + return ::GetObject(m_hPen, sizeof(EXTLOGPEN), pLogPen); + } + + bool GetExtLogPen(EXTLOGPEN& ExtLogPen) const + { + ATLASSERT(m_hPen != NULL); + return (::GetObject(m_hPen, sizeof(EXTLOGPEN), &ExtLogPen) == sizeof(EXTLOGPEN)); + } +#endif // !_WIN32_WCE +}; + +typedef CPenT CPenHandle; +typedef CPenT CPen; + + +/////////////////////////////////////////////////////////////////////////////// +// CBrush + +template +class CBrushT +{ +public: +// Data members + HBRUSH m_hBrush; + +// Constructor/destructor/operators + CBrushT(HBRUSH hBrush = NULL) : m_hBrush(hBrush) + { } + + ~CBrushT() + { + if(t_bManaged && m_hBrush != NULL) + DeleteObject(); + } + + CBrushT& operator =(HBRUSH hBrush) + { + Attach(hBrush); + return *this; + } + + void Attach(HBRUSH hBrush) + { + if(t_bManaged && m_hBrush != NULL && m_hBrush != hBrush) + ::DeleteObject(m_hBrush); + m_hBrush = hBrush; + } + + HBRUSH Detach() + { + HBRUSH hBrush = m_hBrush; + m_hBrush = NULL; + return hBrush; + } + + operator HBRUSH() const { return m_hBrush; } + + bool IsNull() const { return (m_hBrush == NULL); } + +// Create methods + HBRUSH CreateSolidBrush(COLORREF crColor) + { + ATLASSERT(m_hBrush == NULL); + m_hBrush = ::CreateSolidBrush(crColor); + return m_hBrush; + } + +#ifndef _WIN32_WCE + HBRUSH CreateHatchBrush(int nIndex, COLORREF crColor) + { + ATLASSERT(m_hBrush == NULL); + m_hBrush = ::CreateHatchBrush(nIndex, crColor); + return m_hBrush; + } +#endif // !_WIN32_WCE + +#if !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800) + HBRUSH CreateBrushIndirect(const LOGBRUSH* lpLogBrush) + { + ATLASSERT(m_hBrush == NULL); +#ifndef _WIN32_WCE + m_hBrush = ::CreateBrushIndirect(lpLogBrush); +#else // CE specific + m_hBrush = ATL::CreateBrushIndirect(lpLogBrush); +#endif // _WIN32_WCE + return m_hBrush; + } +#endif // !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800) + + HBRUSH CreatePatternBrush(HBITMAP hBitmap) + { + ATLASSERT(m_hBrush == NULL); + m_hBrush = ::CreatePatternBrush(hBitmap); + return m_hBrush; + } + + HBRUSH CreateDIBPatternBrush(HGLOBAL hPackedDIB, UINT nUsage) + { + ATLASSERT(hPackedDIB != NULL); + const void* lpPackedDIB = GlobalLock(hPackedDIB); + ATLASSERT(lpPackedDIB != NULL); + m_hBrush = ::CreateDIBPatternBrushPt(lpPackedDIB, nUsage); + GlobalUnlock(hPackedDIB); + return m_hBrush; + } + + HBRUSH CreateDIBPatternBrush(const void* lpPackedDIB, UINT nUsage) + { + ATLASSERT(m_hBrush == NULL); + m_hBrush = ::CreateDIBPatternBrushPt(lpPackedDIB, nUsage); + return m_hBrush; + } + + HBRUSH CreateSysColorBrush(int nIndex) + { + ATLASSERT(m_hBrush == NULL); + m_hBrush = ::GetSysColorBrush(nIndex); + return m_hBrush; + } + + BOOL DeleteObject() + { + ATLASSERT(m_hBrush != NULL); + BOOL bRet = ::DeleteObject(m_hBrush); + if(bRet) + m_hBrush = NULL; + return bRet; + } + +// Attributes + int GetLogBrush(LOGBRUSH* pLogBrush) const + { + ATLASSERT(m_hBrush != NULL); + return ::GetObject(m_hBrush, sizeof(LOGBRUSH), pLogBrush); + } + + bool GetLogBrush(LOGBRUSH& LogBrush) const + { + ATLASSERT(m_hBrush != NULL); + return (::GetObject(m_hBrush, sizeof(LOGBRUSH), &LogBrush) == sizeof(LOGBRUSH)); + } +}; + +typedef CBrushT CBrushHandle; +typedef CBrushT CBrush; + + +/////////////////////////////////////////////////////////////////////////////// +// CFont + +class CLogFont : public LOGFONT +{ +public: + CLogFont() + { + memset(this, 0, sizeof(LOGFONT)); + } + + CLogFont(const LOGFONT& lf) + { + Copy(&lf); + } + + CLogFont(HFONT hFont) + { + ATLASSERT(::GetObjectType(hFont) == OBJ_FONT); + ::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*)this); + } + + HFONT CreateFontIndirect() + { + return ::CreateFontIndirect(this); + } + + void SetBold() + { + lfWeight = FW_BOLD; + } + + bool IsBold() const + { + return (lfWeight >= FW_BOLD); + } + + void MakeBolder(int iScale = 1) + { + lfWeight += FW_BOLD * iScale; + } + + void MakeLarger(int iScale) + { + if(lfHeight > 0) + lfHeight += iScale; + else + lfHeight -= iScale; + } + + void SetHeight(LONG nPointSize, HDC hDC = NULL) + { + // For MM_TEXT mapping mode + lfHeight = -::MulDiv(nPointSize, ::GetDeviceCaps(hDC, LOGPIXELSY), 72); + } + + LONG GetHeight(HDC hDC = NULL) const + { + // For MM_TEXT mapping mode + return ::MulDiv(-lfHeight, 72, ::GetDeviceCaps(hDC, LOGPIXELSY)); + } + + LONG GetDeciPointHeight(HDC hDC = NULL) const + { +#ifndef _WIN32_WCE + POINT ptOrg = { 0, 0 }; + ::DPtoLP(hDC, &ptOrg, 1); + POINT pt = { 0, 0 }; + pt.y = abs(lfHeight) + ptOrg.y; + ::LPtoDP(hDC,&pt,1); + return ::MulDiv(pt.y, 720, ::GetDeviceCaps(hDC, LOGPIXELSY)); // 72 points/inch, 10 decipoints/point +#else // CE specific + // DP and LP are always the same on CE + return ::MulDiv(abs(lfHeight), 720, ::GetDeviceCaps(hDC, LOGPIXELSY)); // 72 points/inch, 10 decipoints/point +#endif // _WIN32_WCE + } + + void SetHeightFromDeciPoint(LONG nDeciPtHeight, HDC hDC = NULL) + { +#ifndef _WIN32_WCE + POINT pt = { 0, 0 }; + pt.y = ::MulDiv(::GetDeviceCaps(hDC, LOGPIXELSY), nDeciPtHeight, 720); // 72 points/inch, 10 decipoints/point + ::DPtoLP(hDC, &pt, 1); + POINT ptOrg = { 0, 0 }; + ::DPtoLP(hDC, &ptOrg, 1); + lfHeight = -abs(pt.y - ptOrg.y); +#else // CE specific + // DP and LP are always the same on CE + lfHeight = -abs(::MulDiv(::GetDeviceCaps(hDC, LOGPIXELSY), nDeciPtHeight, 720)); // 72 points/inch, 10 decipoints/point +#endif // _WIN32_WCE + } + +#ifndef _WIN32_WCE + void SetCaptionFont() + { + NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; + ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)); + Copy(&ncm.lfCaptionFont); + } + + void SetMenuFont() + { + NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; + ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)); + Copy(&ncm.lfMenuFont); + } + + void SetStatusFont() + { + NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; + ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)); + Copy(&ncm.lfStatusFont); + } + + void SetMessageBoxFont() + { + NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; + ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)); + Copy(&ncm.lfMessageFont); + } +#endif // !_WIN32_WCE + + void Copy(const LOGFONT* pLogFont) + { + ATLASSERT(pLogFont != NULL); + *(LOGFONT*)this = *pLogFont; + } + + CLogFont& operator =(const CLogFont& src) + { + Copy(&src); + return *this; + } + + CLogFont& operator =(const LOGFONT& src) + { + Copy(&src); + return *this; + } + + CLogFont& operator =(HFONT hFont) + { + ATLASSERT(::GetObjectType(hFont) == OBJ_FONT); + ::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*)this); + return *this; + } + + bool operator ==(const LOGFONT& logfont) const + { + return(logfont.lfHeight == lfHeight && + logfont.lfWidth == lfWidth && + logfont.lfEscapement == lfEscapement && + logfont.lfOrientation == lfOrientation && + logfont.lfWeight == lfWeight && + logfont.lfItalic == lfItalic && + logfont.lfUnderline == lfUnderline && + logfont.lfStrikeOut == lfStrikeOut && + logfont.lfCharSet == lfCharSet && + logfont.lfOutPrecision == lfOutPrecision && + logfont.lfClipPrecision == lfClipPrecision && + logfont.lfQuality == lfQuality && + logfont.lfPitchAndFamily == lfPitchAndFamily && + lstrcmp(logfont.lfFaceName, lfFaceName) == 0); + } +}; + + +template +class CFontT +{ +public: +// Data members + HFONT m_hFont; + +// Constructor/destructor/operators + CFontT(HFONT hFont = NULL) : m_hFont(hFont) + { } + + ~CFontT() + { + if(t_bManaged && m_hFont != NULL) + DeleteObject(); + } + + CFontT& operator =(HFONT hFont) + { + Attach(hFont); + return *this; + } + + void Attach(HFONT hFont) + { + if(t_bManaged && m_hFont != NULL && m_hFont != hFont) + ::DeleteObject(m_hFont); + m_hFont = hFont; + } + + HFONT Detach() + { + HFONT hFont = m_hFont; + m_hFont = NULL; + return hFont; + } + + operator HFONT() const { return m_hFont; } + + bool IsNull() const { return (m_hFont == NULL); } + +// Create methods + HFONT CreateFontIndirect(const LOGFONT* lpLogFont) + { + ATLASSERT(m_hFont == NULL); + m_hFont = ::CreateFontIndirect(lpLogFont); + return m_hFont; + } + +#if !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0500) + HFONT CreateFontIndirectEx(CONST ENUMLOGFONTEXDV* penumlfex) + { + ATLASSERT(m_hFont == NULL); + m_hFont = ::CreateFontIndirectEx(penumlfex); + return m_hFont; + } +#endif // !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0500) + +#if !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800) + HFONT CreateFont(int nHeight, int nWidth, int nEscapement, + int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline, + BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision, + BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily, + LPCTSTR lpszFacename) + { + ATLASSERT(m_hFont == NULL); +#ifndef _WIN32_WCE + m_hFont = ::CreateFont(nHeight, nWidth, nEscapement, + nOrientation, nWeight, bItalic, bUnderline, cStrikeOut, + nCharSet, nOutPrecision, nClipPrecision, nQuality, + nPitchAndFamily, lpszFacename); +#else // CE specific + m_hFont = ATL::CreateFont(nHeight, nWidth, nEscapement, + nOrientation, nWeight, bItalic, bUnderline, cStrikeOut, + nCharSet, nOutPrecision, nClipPrecision, nQuality, + nPitchAndFamily, lpszFacename); +#endif // _WIN32_WCE + return m_hFont; + } +#endif // !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800) + + HFONT CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, HDC hDC = NULL, bool bBold = false, bool bItalic = false) + { + LOGFONT logFont = { 0 }; + logFont.lfCharSet = DEFAULT_CHARSET; + logFont.lfHeight = nPointSize; + SecureHelper::strncpy_x(logFont.lfFaceName, _countof(logFont.lfFaceName), lpszFaceName, _TRUNCATE); + + if(bBold) + logFont.lfWeight = FW_BOLD; + if(bItalic) + logFont.lfItalic = (BYTE)TRUE; + + return CreatePointFontIndirect(&logFont, hDC); + } + + HFONT CreatePointFontIndirect(const LOGFONT* lpLogFont, HDC hDC = NULL) + { + HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(NULL); + + // convert nPointSize to logical units based on hDC + LOGFONT logFont = *lpLogFont; +#ifndef _WIN32_WCE + POINT pt = { 0, 0 }; + pt.y = ::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), logFont.lfHeight, 720); // 72 points/inch, 10 decipoints/point + ::DPtoLP(hDC1, &pt, 1); + POINT ptOrg = { 0, 0 }; + ::DPtoLP(hDC1, &ptOrg, 1); + logFont.lfHeight = -abs(pt.y - ptOrg.y); +#else // CE specific + // DP and LP are always the same on CE + logFont.lfHeight = -abs(::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), logFont.lfHeight, 720)); // 72 points/inch, 10 decipoints/point +#endif // _WIN32_WCE + + if(hDC == NULL) + ::ReleaseDC(NULL, hDC1); + + return CreateFontIndirect(&logFont); + } + + BOOL DeleteObject() + { + ATLASSERT(m_hFont != NULL); + BOOL bRet = ::DeleteObject(m_hFont); + if(bRet) + m_hFont = NULL; + return bRet; + } + +// Attributes + int GetLogFont(LOGFONT* pLogFont) const + { + ATLASSERT(m_hFont != NULL); + return ::GetObject(m_hFont, sizeof(LOGFONT), pLogFont); + } + + bool GetLogFont(LOGFONT& LogFont) const + { + ATLASSERT(m_hFont != NULL); + return (::GetObject(m_hFont, sizeof(LOGFONT), &LogFont) == sizeof(LOGFONT)); + } +}; + +typedef CFontT CFontHandle; +typedef CFontT CFont; + + +/////////////////////////////////////////////////////////////////////////////// +// CBitmap + +template +class CBitmapT +{ +public: +// Data members + HBITMAP m_hBitmap; + +// Constructor/destructor/operators + CBitmapT(HBITMAP hBitmap = NULL) : m_hBitmap(hBitmap) + { } + + ~CBitmapT() + { + if(t_bManaged && m_hBitmap != NULL) + DeleteObject(); + } + + CBitmapT& operator =(HBITMAP hBitmap) + { + Attach(hBitmap); + return *this; + } + + void Attach(HBITMAP hBitmap) + { + if(t_bManaged && m_hBitmap != NULL&& m_hBitmap != hBitmap) + ::DeleteObject(m_hBitmap); + m_hBitmap = hBitmap; + } + + HBITMAP Detach() + { + HBITMAP hBitmap = m_hBitmap; + m_hBitmap = NULL; + return hBitmap; + } + + operator HBITMAP() const { return m_hBitmap; } + + bool IsNull() const { return (m_hBitmap == NULL); } + +// Create and load methods + HBITMAP LoadBitmap(ATL::_U_STRINGorID bitmap) + { + ATLASSERT(m_hBitmap == NULL); + m_hBitmap = ::LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr); + return m_hBitmap; + } + + HBITMAP LoadOEMBitmap(UINT nIDBitmap) // for OBM_/OCR_/OIC_ + { + ATLASSERT(m_hBitmap == NULL); + m_hBitmap = ::LoadBitmap(NULL, MAKEINTRESOURCE(nIDBitmap)); + return m_hBitmap; + } + +#ifndef _WIN32_WCE + HBITMAP LoadMappedBitmap(UINT nIDBitmap, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0) + { + ATLASSERT(m_hBitmap == NULL); + m_hBitmap = ::CreateMappedBitmap(ModuleHelper::GetResourceInstance(), nIDBitmap, (WORD)nFlags, lpColorMap, nMapSize); + return m_hBitmap; + } +#endif // !_WIN32_WCE + + HBITMAP CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitsPerPixel, const void* lpBits) + { + ATLASSERT(m_hBitmap == NULL); + m_hBitmap = ::CreateBitmap(nWidth, nHeight, nPlanes, nBitsPerPixel, lpBits); + return m_hBitmap; + } + +#ifndef _WIN32_WCE + HBITMAP CreateBitmapIndirect(LPBITMAP lpBitmap) + { + ATLASSERT(m_hBitmap == NULL); + m_hBitmap = ::CreateBitmapIndirect(lpBitmap); + return m_hBitmap; + } +#endif // !_WIN32_WCE + + HBITMAP CreateCompatibleBitmap(HDC hDC, int nWidth, int nHeight) + { + ATLASSERT(m_hBitmap == NULL); + m_hBitmap = ::CreateCompatibleBitmap(hDC, nWidth, nHeight); + return m_hBitmap; + } + +#ifndef _WIN32_WCE + HBITMAP CreateDiscardableBitmap(HDC hDC, int nWidth, int nHeight) + { + ATLASSERT(m_hBitmap == NULL); + m_hBitmap = ::CreateDiscardableBitmap(hDC, nWidth, nHeight); + return m_hBitmap; + } +#endif // !_WIN32_WCE + + BOOL DeleteObject() + { + ATLASSERT(m_hBitmap != NULL); + BOOL bRet = ::DeleteObject(m_hBitmap); + if(bRet) + m_hBitmap = NULL; + return bRet; + } + +// Attributes + int GetBitmap(BITMAP* pBitMap) const + { + ATLASSERT(m_hBitmap != NULL); + return ::GetObject(m_hBitmap, sizeof(BITMAP), pBitMap); + } + + bool GetBitmap(BITMAP& bm) const + { + ATLASSERT(m_hBitmap != NULL); + return (::GetObject(m_hBitmap, sizeof(BITMAP), &bm) == sizeof(BITMAP)); + } + + bool GetSize(SIZE& size) const + { + ATLASSERT(m_hBitmap != NULL); + BITMAP bm = { 0 }; + if(!GetBitmap(&bm)) + return false; + size.cx = bm.bmWidth; + size.cy = bm.bmHeight; + return true; + } + +#ifndef _WIN32_WCE + DWORD GetBitmapBits(DWORD dwCount, LPVOID lpBits) const + { + ATLASSERT(m_hBitmap != NULL); + return ::GetBitmapBits(m_hBitmap, dwCount, lpBits); + } +#endif // !_WIN32_WCE + +#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 410) + DWORD SetBitmapBits(DWORD dwCount, const void* lpBits) + { + ATLASSERT(m_hBitmap != NULL); + return ::SetBitmapBits(m_hBitmap, dwCount, lpBits); + } +#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 410) + +#ifndef _WIN32_WCE + BOOL GetBitmapDimension(LPSIZE lpSize) const + { + ATLASSERT(m_hBitmap != NULL); + return ::GetBitmapDimensionEx(m_hBitmap, lpSize); + } + + BOOL SetBitmapDimension(int nWidth, int nHeight, LPSIZE lpSize = NULL) + { + ATLASSERT(m_hBitmap != NULL); + return ::SetBitmapDimensionEx(m_hBitmap, nWidth, nHeight, lpSize); + } + +// DIB support + HBITMAP CreateDIBitmap(HDC hDC, CONST BITMAPINFOHEADER* lpbmih, DWORD dwInit, CONST VOID* lpbInit, CONST BITMAPINFO* lpbmi, UINT uColorUse) + { + ATLASSERT(m_hBitmap == NULL); + m_hBitmap = ::CreateDIBitmap(hDC, lpbmih, dwInit, lpbInit, lpbmi, uColorUse); + return m_hBitmap; + } +#endif // !_WIN32_WCE + + HBITMAP CreateDIBSection(HDC hDC, CONST BITMAPINFO* lpbmi, UINT uColorUse, VOID** ppvBits, HANDLE hSection, DWORD dwOffset) + { + ATLASSERT(m_hBitmap == NULL); + m_hBitmap = ::CreateDIBSection(hDC, lpbmi, uColorUse, ppvBits, hSection, dwOffset); + return m_hBitmap; + } + +#ifndef _WIN32_WCE + int GetDIBits(HDC hDC, UINT uStartScan, UINT cScanLines, LPVOID lpvBits, LPBITMAPINFO lpbmi, UINT uColorUse) const + { + ATLASSERT(m_hBitmap != NULL); + return ::GetDIBits(hDC, m_hBitmap, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse); + } + + int SetDIBits(HDC hDC, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse) + { + ATLASSERT(m_hBitmap != NULL); + return ::SetDIBits(hDC, m_hBitmap, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse); + } +#endif // !_WIN32_WCE +}; + +typedef CBitmapT CBitmapHandle; +typedef CBitmapT CBitmap; + + +/////////////////////////////////////////////////////////////////////////////// +// CPalette + +template +class CPaletteT +{ +public: +// Data members + HPALETTE m_hPalette; + +// Constructor/destructor/operators + CPaletteT(HPALETTE hPalette = NULL) : m_hPalette(hPalette) + { } + + ~CPaletteT() + { + if(t_bManaged && m_hPalette != NULL) + DeleteObject(); + } + + CPaletteT& operator =(HPALETTE hPalette) + { + Attach(hPalette); + return *this; + } + + void Attach(HPALETTE hPalette) + { + if(t_bManaged && m_hPalette != NULL && m_hPalette != hPalette) + ::DeleteObject(m_hPalette); + m_hPalette = hPalette; + } + + HPALETTE Detach() + { + HPALETTE hPalette = m_hPalette; + m_hPalette = NULL; + return hPalette; + } + + operator HPALETTE() const { return m_hPalette; } + + bool IsNull() const { return (m_hPalette == NULL); } + +// Create methods + HPALETTE CreatePalette(LPLOGPALETTE lpLogPalette) + { + ATLASSERT(m_hPalette == NULL); + m_hPalette = ::CreatePalette(lpLogPalette); + return m_hPalette; + } + +#ifndef _WIN32_WCE + HPALETTE CreateHalftonePalette(HDC hDC) + { + ATLASSERT(m_hPalette == NULL); + ATLASSERT(hDC != NULL); + m_hPalette = ::CreateHalftonePalette(hDC); + return m_hPalette; + } +#endif // !_WIN32_WCE + + BOOL DeleteObject() + { + ATLASSERT(m_hPalette != NULL); + BOOL bRet = ::DeleteObject(m_hPalette); + if(bRet) + m_hPalette = NULL; + return bRet; + } + +// Attributes + int GetEntryCount() const + { + ATLASSERT(m_hPalette != NULL); + WORD nEntries = 0; + ::GetObject(m_hPalette, sizeof(WORD), &nEntries); + return (int)nEntries; + } + + UINT GetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) const + { + ATLASSERT(m_hPalette != NULL); + return ::GetPaletteEntries(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors); + } + + UINT SetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) + { + ATLASSERT(m_hPalette != NULL); + return ::SetPaletteEntries(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors); + } + +// Operations +#ifndef _WIN32_WCE + void AnimatePalette(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) + { + ATLASSERT(m_hPalette != NULL); + ::AnimatePalette(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors); + } + + BOOL ResizePalette(UINT nNumEntries) + { + ATLASSERT(m_hPalette != NULL); + return ::ResizePalette(m_hPalette, nNumEntries); + } +#endif // !_WIN32_WCE + + UINT GetNearestPaletteIndex(COLORREF crColor) const + { + ATLASSERT(m_hPalette != NULL); + return ::GetNearestPaletteIndex(m_hPalette, crColor); + } +}; + +typedef CPaletteT CPaletteHandle; +typedef CPaletteT CPalette; + + +/////////////////////////////////////////////////////////////////////////////// +// CRgn + +template +class CRgnT +{ +public: +// Data members + HRGN m_hRgn; + +// Constructor/destructor/operators + CRgnT(HRGN hRgn = NULL) : m_hRgn(hRgn) + { } + + ~CRgnT() + { + if(t_bManaged && m_hRgn != NULL) + DeleteObject(); + } + + CRgnT& operator =(HRGN hRgn) + { + Attach(hRgn); + return *this; + } + + void Attach(HRGN hRgn) + { + if(t_bManaged && m_hRgn != NULL && m_hRgn != hRgn) + ::DeleteObject(m_hRgn); + m_hRgn = hRgn; + } + + HRGN Detach() + { + HRGN hRgn = m_hRgn; + m_hRgn = NULL; + return hRgn; + } + + operator HRGN() const { return m_hRgn; } + + bool IsNull() const { return (m_hRgn == NULL); } + +// Create methods + HRGN CreateRectRgn(int x1, int y1, int x2, int y2) + { + ATLASSERT(m_hRgn == NULL); + m_hRgn = ::CreateRectRgn(x1, y1, x2, y2); + return m_hRgn; + } + + HRGN CreateRectRgnIndirect(LPCRECT lpRect) + { + ATLASSERT(m_hRgn == NULL); + m_hRgn = ::CreateRectRgnIndirect(lpRect); + return m_hRgn; + } + +#ifndef _WIN32_WCE + HRGN CreateEllipticRgn(int x1, int y1, int x2, int y2) + { + ATLASSERT(m_hRgn == NULL); + m_hRgn = ::CreateEllipticRgn(x1, y1, x2, y2); + return m_hRgn; + } + + HRGN CreateEllipticRgnIndirect(LPCRECT lpRect) + { + ATLASSERT(m_hRgn == NULL); + m_hRgn = ::CreateEllipticRgnIndirect(lpRect); + return m_hRgn; + } + + HRGN CreatePolygonRgn(LPPOINT lpPoints, int nCount, int nMode) + { + ATLASSERT(m_hRgn == NULL); + m_hRgn = ::CreatePolygonRgn(lpPoints, nCount, nMode); + return m_hRgn; + } + + HRGN CreatePolyPolygonRgn(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount, int nPolyFillMode) + { + ATLASSERT(m_hRgn == NULL); + m_hRgn = ::CreatePolyPolygonRgn(lpPoints, lpPolyCounts, nCount, nPolyFillMode); + return m_hRgn; + } + + HRGN CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3) + { + ATLASSERT(m_hRgn == NULL); + m_hRgn = ::CreateRoundRectRgn(x1, y1, x2, y2, x3, y3); + return m_hRgn; + } + + HRGN CreateFromPath(HDC hDC) + { + ATLASSERT(m_hRgn == NULL); + ATLASSERT(hDC != NULL); + m_hRgn = ::PathToRegion(hDC); + return m_hRgn; + } + + HRGN CreateFromData(const XFORM* lpXForm, int nCount, const RGNDATA* pRgnData) + { + ATLASSERT(m_hRgn == NULL); + m_hRgn = ::ExtCreateRegion(lpXForm, nCount, pRgnData); + return m_hRgn; + } +#endif // !_WIN32_WCE + + BOOL DeleteObject() + { + ATLASSERT(m_hRgn != NULL); + BOOL bRet = ::DeleteObject(m_hRgn); + if(bRet) + m_hRgn = NULL; + return bRet; + } + +// Operations + void SetRectRgn(int x1, int y1, int x2, int y2) + { + ATLASSERT(m_hRgn != NULL); + ::SetRectRgn(m_hRgn, x1, y1, x2, y2); + } + + void SetRectRgn(LPCRECT lpRect) + { + ATLASSERT(m_hRgn != NULL); + ::SetRectRgn(m_hRgn, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + } + + int CombineRgn(HRGN hRgnSrc1, HRGN hRgnSrc2, int nCombineMode) + { + ATLASSERT(m_hRgn != NULL); + return ::CombineRgn(m_hRgn, hRgnSrc1, hRgnSrc2, nCombineMode); + } + + int CombineRgn(HRGN hRgnSrc, int nCombineMode) + { + ATLASSERT(m_hRgn != NULL); + return ::CombineRgn(m_hRgn, m_hRgn, hRgnSrc, nCombineMode); + } + + int CopyRgn(HRGN hRgnSrc) + { + ATLASSERT(m_hRgn != NULL); + return ::CombineRgn(m_hRgn, hRgnSrc, NULL, RGN_COPY); + } + + BOOL EqualRgn(HRGN hRgn) const + { + ATLASSERT(m_hRgn != NULL); + return ::EqualRgn(m_hRgn, hRgn); + } + + int OffsetRgn(int x, int y) + { + ATLASSERT(m_hRgn != NULL); + return ::OffsetRgn(m_hRgn, x, y); + } + + int OffsetRgn(POINT point) + { + ATLASSERT(m_hRgn != NULL); + return ::OffsetRgn(m_hRgn, point.x, point.y); + } + + int GetRgnBox(LPRECT lpRect) const + { + ATLASSERT(m_hRgn != NULL); + return ::GetRgnBox(m_hRgn, lpRect); + } + + BOOL PtInRegion(int x, int y) const + { + ATLASSERT(m_hRgn != NULL); + return ::PtInRegion(m_hRgn, x, y); + } + + BOOL PtInRegion(POINT point) const + { + ATLASSERT(m_hRgn != NULL); + return ::PtInRegion(m_hRgn, point.x, point.y); + } + + BOOL RectInRegion(LPCRECT lpRect) const + { + ATLASSERT(m_hRgn != NULL); + return ::RectInRegion(m_hRgn, lpRect); + } + + int GetRegionData(LPRGNDATA lpRgnData, int nDataSize) const + { + ATLASSERT(m_hRgn != NULL); + return (int)::GetRegionData(m_hRgn, nDataSize, lpRgnData); + } +}; + +typedef CRgnT CRgnHandle; +typedef CRgnT CRgn; + + +/////////////////////////////////////////////////////////////////////////////// +// CDC - The device context class + +template +class CDCT +{ +public: +// Data members + HDC m_hDC; + +// Constructor/destructor/operators + CDCT(HDC hDC = NULL) : m_hDC(hDC) + { + } + + ~CDCT() + { + if(t_bManaged && m_hDC != NULL) + ::DeleteDC(Detach()); + } + + CDCT& operator =(HDC hDC) + { + Attach(hDC); + return *this; + } + + void Attach(HDC hDC) + { + if(t_bManaged && m_hDC != NULL && m_hDC != hDC) + ::DeleteDC(m_hDC); + m_hDC = hDC; + } + + HDC Detach() + { + HDC hDC = m_hDC; + m_hDC = NULL; + return hDC; + } + + operator HDC() const { return m_hDC; } + + bool IsNull() const { return (m_hDC == NULL); } + +// Operations +#ifndef _WIN32_WCE + HWND WindowFromDC() const + { + ATLASSERT(m_hDC != NULL); + return ::WindowFromDC(m_hDC); + } +#endif // !_WIN32_WCE + + CPenHandle GetCurrentPen() const + { + ATLASSERT(m_hDC != NULL); + return CPenHandle((HPEN)::GetCurrentObject(m_hDC, OBJ_PEN)); + } + + CBrushHandle GetCurrentBrush() const + { + ATLASSERT(m_hDC != NULL); + return CBrushHandle((HBRUSH)::GetCurrentObject(m_hDC, OBJ_BRUSH)); + } + + CPaletteHandle GetCurrentPalette() const + { + ATLASSERT(m_hDC != NULL); + return CPaletteHandle((HPALETTE)::GetCurrentObject(m_hDC, OBJ_PAL)); + } + + CFontHandle GetCurrentFont() const + { + ATLASSERT(m_hDC != NULL); + return CFontHandle((HFONT)::GetCurrentObject(m_hDC, OBJ_FONT)); + } + + CBitmapHandle GetCurrentBitmap() const + { + ATLASSERT(m_hDC != NULL); + return CBitmapHandle((HBITMAP)::GetCurrentObject(m_hDC, OBJ_BITMAP)); + } + + HDC CreateDC(LPCTSTR lpszDriverName, LPCTSTR lpszDeviceName, LPCTSTR lpszOutput, const DEVMODE* lpInitData) + { + ATLASSERT(m_hDC == NULL); + m_hDC = ::CreateDC(lpszDriverName, lpszDeviceName, lpszOutput, lpInitData); + return m_hDC; + } + + HDC CreateCompatibleDC(HDC hDC = NULL) + { + ATLASSERT(m_hDC == NULL); + m_hDC = ::CreateCompatibleDC(hDC); + return m_hDC; + } + + BOOL DeleteDC() + { + if(m_hDC == NULL) + return FALSE; + BOOL bRet = ::DeleteDC(m_hDC); + if(bRet) + m_hDC = NULL; + return bRet; + } + +// Device-Context Functions + int SaveDC() + { + ATLASSERT(m_hDC != NULL); + return ::SaveDC(m_hDC); + } + + BOOL RestoreDC(int nSavedDC) + { + ATLASSERT(m_hDC != NULL); + return ::RestoreDC(m_hDC, nSavedDC); + } + + int GetDeviceCaps(int nIndex) const + { + ATLASSERT(m_hDC != NULL); + return ::GetDeviceCaps(m_hDC, nIndex); + } + +#ifndef _WIN32_WCE + UINT SetBoundsRect(LPCRECT lpRectBounds, UINT flags) + { + ATLASSERT(m_hDC != NULL); + return ::SetBoundsRect(m_hDC, lpRectBounds, flags); + } + + UINT GetBoundsRect(LPRECT lpRectBounds, UINT flags) const + { + ATLASSERT(m_hDC != NULL); + return ::GetBoundsRect(m_hDC, lpRectBounds, flags); + } + + BOOL ResetDC(const DEVMODE* lpDevMode) + { + ATLASSERT(m_hDC != NULL); + return ::ResetDC(m_hDC, lpDevMode) != NULL; + } + +// Drawing-Tool Functions + BOOL GetBrushOrg(LPPOINT lpPoint) const + { + ATLASSERT(m_hDC != NULL); + return ::GetBrushOrgEx(m_hDC, lpPoint); + } +#endif // !_WIN32_WCE + + BOOL SetBrushOrg(int x, int y, LPPOINT lpPoint = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::SetBrushOrgEx(m_hDC, x, y, lpPoint); + } + + BOOL SetBrushOrg(POINT point, LPPOINT lpPointRet = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::SetBrushOrgEx(m_hDC, point.x, point.y, lpPointRet); + } + +#ifndef _WIN32_WCE + int EnumObjects(int nObjectType, int (CALLBACK* lpfn)(LPVOID, LPARAM), LPARAM lpData) + { + ATLASSERT(m_hDC != NULL); +#ifdef STRICT + return ::EnumObjects(m_hDC, nObjectType, (GOBJENUMPROC)lpfn, lpData); +#else + return ::EnumObjects(m_hDC, nObjectType, (GOBJENUMPROC)lpfn, (LPVOID)lpData); +#endif + } +#endif // !_WIN32_WCE + +// Type-safe selection helpers + HPEN SelectPen(HPEN hPen) + { + ATLASSERT(m_hDC != NULL); +#ifndef _WIN32_WCE + ATLASSERT(hPen == NULL || ::GetObjectType(hPen) == OBJ_PEN || ::GetObjectType(hPen) == OBJ_EXTPEN); +#else // CE specific + ATLASSERT(hPen == NULL || ::GetObjectType(hPen) == OBJ_PEN); +#endif // _WIN32_WCE + return (HPEN)::SelectObject(m_hDC, hPen); + } + + HBRUSH SelectBrush(HBRUSH hBrush) + { + ATLASSERT(m_hDC != NULL); + ATLASSERT(hBrush == NULL || ::GetObjectType(hBrush) == OBJ_BRUSH); + return (HBRUSH)::SelectObject(m_hDC, hBrush); + } + + HFONT SelectFont(HFONT hFont) + { + ATLASSERT(m_hDC != NULL); + ATLASSERT(hFont == NULL || ::GetObjectType(hFont) == OBJ_FONT); + return (HFONT)::SelectObject(m_hDC, hFont); + } + + HBITMAP SelectBitmap(HBITMAP hBitmap) + { + ATLASSERT(m_hDC != NULL); + ATLASSERT(hBitmap == NULL || ::GetObjectType(hBitmap) == OBJ_BITMAP); + return (HBITMAP)::SelectObject(m_hDC, hBitmap); + } + + int SelectRgn(HRGN hRgn) // special return for regions + { + ATLASSERT(m_hDC != NULL); + ATLASSERT(hRgn == NULL || ::GetObjectType(hRgn) == OBJ_REGION); + return PtrToInt(::SelectObject(m_hDC, hRgn)); + } + +// Type-safe selection helpers for stock objects + HPEN SelectStockPen(int nPen) + { + ATLASSERT(m_hDC != NULL); +#if (_WIN32_WINNT >= 0x0500) + ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN || nPen == DC_PEN); +#else + ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN); +#endif // !(_WIN32_WINNT >= 0x0500) + return SelectPen((HPEN)::GetStockObject(nPen)); + } + + HBRUSH SelectStockBrush(int nBrush) + { +#if (_WIN32_WINNT >= 0x0500) + ATLASSERT((nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH) || nBrush == DC_BRUSH); +#else + ATLASSERT(nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH); +#endif // !(_WIN32_WINNT >= 0x0500) + return SelectBrush((HBRUSH)::GetStockObject(nBrush)); + } + + HFONT SelectStockFont(int nFont) + { +#ifndef _WIN32_WCE + ATLASSERT((nFont >= OEM_FIXED_FONT && nFont <= SYSTEM_FIXED_FONT) || nFont == DEFAULT_GUI_FONT); +#else // CE specific + ATLASSERT(nFont == SYSTEM_FONT); +#endif // _WIN32_WCE + return SelectFont((HFONT)::GetStockObject(nFont)); + } + + HPALETTE SelectStockPalette(int nPalette, BOOL bForceBackground) + { + ATLASSERT(nPalette == DEFAULT_PALETTE); // the only one supported + return SelectPalette((HPALETTE)::GetStockObject(nPalette), bForceBackground); + } + +// Color and Color Palette Functions + COLORREF GetNearestColor(COLORREF crColor) const + { + ATLASSERT(m_hDC != NULL); + return ::GetNearestColor(m_hDC, crColor); + } + + HPALETTE SelectPalette(HPALETTE hPalette, BOOL bForceBackground) + { + ATLASSERT(m_hDC != NULL); + + return ::SelectPalette(m_hDC, hPalette, bForceBackground); + } + + UINT RealizePalette() + { + ATLASSERT(m_hDC != NULL); + return ::RealizePalette(m_hDC); + } + +#ifndef _WIN32_WCE + void UpdateColors() + { + ATLASSERT(m_hDC != NULL); + ::UpdateColors(m_hDC); + } +#endif // !_WIN32_WCE + +// Drawing-Attribute Functions + COLORREF GetBkColor() const + { + ATLASSERT(m_hDC != NULL); + return ::GetBkColor(m_hDC); + } + + int GetBkMode() const + { + ATLASSERT(m_hDC != NULL); + return ::GetBkMode(m_hDC); + } + +#ifndef _WIN32_WCE + int GetPolyFillMode() const + { + ATLASSERT(m_hDC != NULL); + return ::GetPolyFillMode(m_hDC); + } + + int GetROP2() const + { + ATLASSERT(m_hDC != NULL); + return ::GetROP2(m_hDC); + } + + int GetStretchBltMode() const + { + ATLASSERT(m_hDC != NULL); + return ::GetStretchBltMode(m_hDC); + } +#endif // !_WIN32_WCE + + COLORREF GetTextColor() const + { + ATLASSERT(m_hDC != NULL); + return ::GetTextColor(m_hDC); + } + + COLORREF SetBkColor(COLORREF crColor) + { + ATLASSERT(m_hDC != NULL); + return ::SetBkColor(m_hDC, crColor); + } + + int SetBkMode(int nBkMode) + { + ATLASSERT(m_hDC != NULL); + return ::SetBkMode(m_hDC, nBkMode); + } + +#ifndef _WIN32_WCE + int SetPolyFillMode(int nPolyFillMode) + { + ATLASSERT(m_hDC != NULL); + return ::SetPolyFillMode(m_hDC, nPolyFillMode); + } +#endif // !_WIN32_WCE + + int SetROP2(int nDrawMode) + { + ATLASSERT(m_hDC != NULL); + return ::SetROP2(m_hDC, nDrawMode); + } + +#ifndef _WIN32_WCE + int SetStretchBltMode(int nStretchMode) + { + ATLASSERT(m_hDC != NULL); + return ::SetStretchBltMode(m_hDC, nStretchMode); + } +#endif // !_WIN32_WCE + + COLORREF SetTextColor(COLORREF crColor) + { + ATLASSERT(m_hDC != NULL); + return ::SetTextColor(m_hDC, crColor); + } + +#ifndef _WIN32_WCE + BOOL GetColorAdjustment(LPCOLORADJUSTMENT lpColorAdjust) const + { + ATLASSERT(m_hDC != NULL); + return ::GetColorAdjustment(m_hDC, lpColorAdjust); + } + + BOOL SetColorAdjustment(const COLORADJUSTMENT* lpColorAdjust) + { + ATLASSERT(m_hDC != NULL); + return ::SetColorAdjustment(m_hDC, lpColorAdjust); + } + +// Mapping Functions + int GetMapMode() const + { + ATLASSERT(m_hDC != NULL); + return ::GetMapMode(m_hDC); + } + + BOOL GetViewportOrg(LPPOINT lpPoint) const + { + ATLASSERT(m_hDC != NULL); + return ::GetViewportOrgEx(m_hDC, lpPoint); + } + + int SetMapMode(int nMapMode) + { + ATLASSERT(m_hDC != NULL); + return ::SetMapMode(m_hDC, nMapMode); + } +#endif // !_WIN32_WCE + + // Viewport Origin + BOOL SetViewportOrg(int x, int y, LPPOINT lpPoint = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::SetViewportOrgEx(m_hDC, x, y, lpPoint); + } + + BOOL SetViewportOrg(POINT point, LPPOINT lpPointRet = NULL) + { + ATLASSERT(m_hDC != NULL); + return SetViewportOrg(point.x, point.y, lpPointRet); + } + +#ifndef _WIN32_WCE + BOOL OffsetViewportOrg(int nWidth, int nHeight, LPPOINT lpPoint = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::OffsetViewportOrgEx(m_hDC, nWidth, nHeight, lpPoint); + } + + // Viewport Extent + BOOL GetViewportExt(LPSIZE lpSize) const + { + ATLASSERT(m_hDC != NULL); + return ::GetViewportExtEx(m_hDC, lpSize); + } + + BOOL SetViewportExt(int x, int y, LPSIZE lpSize = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::SetViewportExtEx(m_hDC, x, y, lpSize); + } + + BOOL SetViewportExt(SIZE size, LPSIZE lpSizeRet = NULL) + { + ATLASSERT(m_hDC != NULL); + return SetViewportExt(size.cx, size.cy, lpSizeRet); + } + + BOOL ScaleViewportExt(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::ScaleViewportExtEx(m_hDC, xNum, xDenom, yNum, yDenom, lpSize); + } +#endif // !_WIN32_WCE + + // Window Origin +#ifndef _WIN32_WCE + BOOL GetWindowOrg(LPPOINT lpPoint) const + { + ATLASSERT(m_hDC != NULL); + return ::GetWindowOrgEx(m_hDC, lpPoint); + } + + BOOL SetWindowOrg(int x, int y, LPPOINT lpPoint = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::SetWindowOrgEx(m_hDC, x, y, lpPoint); + } + + BOOL SetWindowOrg(POINT point, LPPOINT lpPointRet = NULL) + { + ATLASSERT(m_hDC != NULL); + return SetWindowOrg(point.x, point.y, lpPointRet); + } + + BOOL OffsetWindowOrg(int nWidth, int nHeight, LPPOINT lpPoint = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::OffsetWindowOrgEx(m_hDC, nWidth, nHeight, lpPoint); + } + + // Window extent + BOOL GetWindowExt(LPSIZE lpSize) const + { + ATLASSERT(m_hDC != NULL); + return ::GetWindowExtEx(m_hDC, lpSize); + } + + BOOL SetWindowExt(int x, int y, LPSIZE lpSize = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::SetWindowExtEx(m_hDC, x, y, lpSize); + } + + BOOL SetWindowExt(SIZE size, LPSIZE lpSizeRet = NULL) + { + ATLASSERT(m_hDC != NULL); + return SetWindowExt(size.cx, size.cy, lpSizeRet); + } + + BOOL ScaleWindowExt(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::ScaleWindowExtEx(m_hDC, xNum, xDenom, yNum, yDenom, lpSize); + } + +// Coordinate Functions + BOOL DPtoLP(LPPOINT lpPoints, int nCount = 1) const + { + ATLASSERT(m_hDC != NULL); + return ::DPtoLP(m_hDC, lpPoints, nCount); + } + + BOOL DPtoLP(LPRECT lpRect) const + { + ATLASSERT(m_hDC != NULL); + return ::DPtoLP(m_hDC, (LPPOINT)lpRect, 2); + } + + BOOL DPtoLP(LPSIZE lpSize) const + { + SIZE sizeWinExt = { 0, 0 }; + if(!GetWindowExt(&sizeWinExt)) + return FALSE; + SIZE sizeVpExt = { 0, 0 }; + if(!GetViewportExt(&sizeVpExt)) + return FALSE; + lpSize->cx = ::MulDiv(lpSize->cx, abs(sizeWinExt.cx), abs(sizeVpExt.cx)); + lpSize->cy = ::MulDiv(lpSize->cy, abs(sizeWinExt.cy), abs(sizeVpExt.cy)); + return TRUE; + } + + BOOL LPtoDP(LPPOINT lpPoints, int nCount = 1) const + { + ATLASSERT(m_hDC != NULL); + return ::LPtoDP(m_hDC, lpPoints, nCount); + } + + BOOL LPtoDP(LPRECT lpRect) const + { + ATLASSERT(m_hDC != NULL); + return ::LPtoDP(m_hDC, (LPPOINT)lpRect, 2); + } + + BOOL LPtoDP(LPSIZE lpSize) const + { + SIZE sizeWinExt = { 0, 0 }; + if(!GetWindowExt(&sizeWinExt)) + return FALSE; + SIZE sizeVpExt = { 0, 0 }; + if(!GetViewportExt(&sizeVpExt)) + return FALSE; + lpSize->cx = ::MulDiv(lpSize->cx, abs(sizeVpExt.cx), abs(sizeWinExt.cx)); + lpSize->cy = ::MulDiv(lpSize->cy, abs(sizeVpExt.cy), abs(sizeWinExt.cy)); + return TRUE; + } + +// Special Coordinate Functions (useful for dealing with metafiles and OLE) + #define HIMETRIC_INCH 2540 // HIMETRIC units per inch + + void DPtoHIMETRIC(LPSIZE lpSize) const + { + ATLASSERT(m_hDC != NULL); + int nMapMode; + if((nMapMode = GetMapMode()) < MM_ISOTROPIC && nMapMode != MM_TEXT) + { + // when using a constrained map mode, map against physical inch + ((CDCHandle*)this)->SetMapMode(MM_HIMETRIC); + DPtoLP(lpSize); + ((CDCHandle*)this)->SetMapMode(nMapMode); + } + else + { + // map against logical inch for non-constrained mapping modes + int cxPerInch = GetDeviceCaps(LOGPIXELSX); + int cyPerInch = GetDeviceCaps(LOGPIXELSY); + ATLASSERT(cxPerInch != 0 && cyPerInch != 0); + lpSize->cx = ::MulDiv(lpSize->cx, HIMETRIC_INCH, cxPerInch); + lpSize->cy = ::MulDiv(lpSize->cy, HIMETRIC_INCH, cyPerInch); + } + } + + void HIMETRICtoDP(LPSIZE lpSize) const + { + ATLASSERT(m_hDC != NULL); + int nMapMode; + if((nMapMode = GetMapMode()) < MM_ISOTROPIC && nMapMode != MM_TEXT) + { + // when using a constrained map mode, map against physical inch + ((CDCHandle*)this)->SetMapMode(MM_HIMETRIC); + LPtoDP(lpSize); + ((CDCHandle*)this)->SetMapMode(nMapMode); + } + else + { + // map against logical inch for non-constrained mapping modes + int cxPerInch = GetDeviceCaps(LOGPIXELSX); + int cyPerInch = GetDeviceCaps(LOGPIXELSY); + ATLASSERT(cxPerInch != 0 && cyPerInch != 0); + lpSize->cx = ::MulDiv(lpSize->cx, cxPerInch, HIMETRIC_INCH); + lpSize->cy = ::MulDiv(lpSize->cy, cyPerInch, HIMETRIC_INCH); + } + } + + void LPtoHIMETRIC(LPSIZE lpSize) const + { + LPtoDP(lpSize); + DPtoHIMETRIC(lpSize); + } + + void HIMETRICtoLP(LPSIZE lpSize) const + { + HIMETRICtoDP(lpSize); + DPtoLP(lpSize); + } +#endif // !_WIN32_WCE + +// Region Functions + BOOL FillRgn(HRGN hRgn, HBRUSH hBrush) + { + ATLASSERT(m_hDC != NULL); + return ::FillRgn(m_hDC, hRgn, hBrush); + } + +#ifndef _WIN32_WCE + BOOL FrameRgn(HRGN hRgn, HBRUSH hBrush, int nWidth, int nHeight) + { + ATLASSERT(m_hDC != NULL); + return ::FrameRgn(m_hDC, hRgn, hBrush, nWidth, nHeight); + } + + BOOL InvertRgn(HRGN hRgn) + { + ATLASSERT(m_hDC != NULL); + return ::InvertRgn(m_hDC, hRgn); + } + + BOOL PaintRgn(HRGN hRgn) + { + ATLASSERT(m_hDC != NULL); + return ::PaintRgn(m_hDC, hRgn); + } +#endif // !_WIN32_WCE + +// Clipping Functions + int GetClipBox(LPRECT lpRect) const + { + ATLASSERT(m_hDC != NULL); + return ::GetClipBox(m_hDC, lpRect); + } + + int GetClipRgn(CRgn& region) const + { + ATLASSERT(m_hDC != NULL); + if(region.IsNull()) + region.CreateRectRgn(0, 0, 0, 0); + + int nRet = ::GetClipRgn(m_hDC, region); + if(nRet != 1) + region.DeleteObject(); + + return nRet; + } + +#ifndef _WIN32_WCE + BOOL PtVisible(int x, int y) const + { + ATLASSERT(m_hDC != NULL); + return ::PtVisible(m_hDC, x, y); + } + + BOOL PtVisible(POINT point) const + { + ATLASSERT(m_hDC != NULL); + return ::PtVisible(m_hDC, point.x, point.y); + } +#endif // !_WIN32_WCE + + BOOL RectVisible(LPCRECT lpRect) const + { + ATLASSERT(m_hDC != NULL); + return ::RectVisible(m_hDC, lpRect); + } + + int SelectClipRgn(HRGN hRgn) + { + ATLASSERT(m_hDC != NULL); + return ::SelectClipRgn(m_hDC, (HRGN)hRgn); + } + + int ExcludeClipRect(int x1, int y1, int x2, int y2) + { + ATLASSERT(m_hDC != NULL); + return ::ExcludeClipRect(m_hDC, x1, y1, x2, y2); + } + + int ExcludeClipRect(LPCRECT lpRect) + { + ATLASSERT(m_hDC != NULL); + return ::ExcludeClipRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + } + +#ifndef _WIN32_WCE + int ExcludeUpdateRgn(HWND hWnd) + { + ATLASSERT(m_hDC != NULL); + return ::ExcludeUpdateRgn(m_hDC, hWnd); + } +#endif // !_WIN32_WCE + + int IntersectClipRect(int x1, int y1, int x2, int y2) + { + ATLASSERT(m_hDC != NULL); + return ::IntersectClipRect(m_hDC, x1, y1, x2, y2); + } + + int IntersectClipRect(LPCRECT lpRect) + { + ATLASSERT(m_hDC != NULL); + return ::IntersectClipRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + } + +#ifndef _WIN32_WCE + int OffsetClipRgn(int x, int y) + { + ATLASSERT(m_hDC != NULL); + return ::OffsetClipRgn(m_hDC, x, y); + } + + int OffsetClipRgn(SIZE size) + { + ATLASSERT(m_hDC != NULL); + return ::OffsetClipRgn(m_hDC, size.cx, size.cy); + } + + int SelectClipRgn(HRGN hRgn, int nMode) + { + ATLASSERT(m_hDC != NULL); + return ::ExtSelectClipRgn(m_hDC, hRgn, nMode); + } +#endif // !_WIN32_WCE + +// Line-Output Functions +#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) + BOOL GetCurrentPosition(LPPOINT lpPoint) const + { + ATLASSERT(m_hDC != NULL); + return ::GetCurrentPositionEx(m_hDC, lpPoint); + } + + BOOL MoveTo(int x, int y, LPPOINT lpPoint = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::MoveToEx(m_hDC, x, y, lpPoint); + } + + BOOL MoveTo(POINT point, LPPOINT lpPointRet = NULL) + { + ATLASSERT(m_hDC != NULL); + return MoveTo(point.x, point.y, lpPointRet); + } + + BOOL LineTo(int x, int y) + { + ATLASSERT(m_hDC != NULL); + return ::LineTo(m_hDC, x, y); + } + + BOOL LineTo(POINT point) + { + ATLASSERT(m_hDC != NULL); + return LineTo(point.x, point.y); + } +#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) + +#ifndef _WIN32_WCE + BOOL Arc(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) + { + ATLASSERT(m_hDC != NULL); + return ::Arc(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4); + } + + BOOL Arc(LPCRECT lpRect, POINT ptStart, POINT ptEnd) + { + ATLASSERT(m_hDC != NULL); + return ::Arc(m_hDC, lpRect->left, lpRect->top, + lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, + ptEnd.x, ptEnd.y); + } +#endif // !_WIN32_WCE + + BOOL Polyline(LPPOINT lpPoints, int nCount) + { + ATLASSERT(m_hDC != NULL); + return ::Polyline(m_hDC, lpPoints, nCount); + } + +#ifndef _WIN32_WCE + BOOL AngleArc(int x, int y, int nRadius, float fStartAngle, float fSweepAngle) + { + ATLASSERT(m_hDC != NULL); + return ::AngleArc(m_hDC, x, y, nRadius, fStartAngle, fSweepAngle); + } + + BOOL ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) + { + ATLASSERT(m_hDC != NULL); + return ::ArcTo(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4); + } + + BOOL ArcTo(LPCRECT lpRect, POINT ptStart, POINT ptEnd) + { + ATLASSERT(m_hDC != NULL); + return ArcTo(lpRect->left, lpRect->top, lpRect->right, + lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y); + } + + int GetArcDirection() const + { + ATLASSERT(m_hDC != NULL); + return ::GetArcDirection(m_hDC); + } + + int SetArcDirection(int nArcDirection) + { + ATLASSERT(m_hDC != NULL); + return ::SetArcDirection(m_hDC, nArcDirection); + } + + BOOL PolyDraw(const POINT* lpPoints, const BYTE* lpTypes, int nCount) + { + ATLASSERT(m_hDC != NULL); + return ::PolyDraw(m_hDC, lpPoints, lpTypes, nCount); + } + + BOOL PolylineTo(const POINT* lpPoints, int nCount) + { + ATLASSERT(m_hDC != NULL); + return ::PolylineTo(m_hDC, lpPoints, nCount); + } + + BOOL PolyPolyline(const POINT* lpPoints, + const DWORD* lpPolyPoints, int nCount) + { + ATLASSERT(m_hDC != NULL); + return ::PolyPolyline(m_hDC, lpPoints, lpPolyPoints, nCount); + } + + BOOL PolyBezier(const POINT* lpPoints, int nCount) + { + ATLASSERT(m_hDC != NULL); + return ::PolyBezier(m_hDC, lpPoints, nCount); + } + + BOOL PolyBezierTo(const POINT* lpPoints, int nCount) + { + ATLASSERT(m_hDC != NULL); + return ::PolyBezierTo(m_hDC, lpPoints, nCount); + } +#endif // !_WIN32_WCE + +// Simple Drawing Functions + BOOL FillRect(LPCRECT lpRect, HBRUSH hBrush) + { + ATLASSERT(m_hDC != NULL); + return ::FillRect(m_hDC, lpRect, hBrush); + } + + BOOL FillRect(LPCRECT lpRect, int nColorIndex) + { + ATLASSERT(m_hDC != NULL); +#ifndef _WIN32_WCE + return ::FillRect(m_hDC, lpRect, (HBRUSH)LongToPtr(nColorIndex + 1)); +#else // CE specific + return ::FillRect(m_hDC, lpRect, ::GetSysColorBrush(nColorIndex)); +#endif // _WIN32_WCE + } + +#ifndef _WIN32_WCE + BOOL FrameRect(LPCRECT lpRect, HBRUSH hBrush) + { + ATLASSERT(m_hDC != NULL); + return ::FrameRect(m_hDC, lpRect, hBrush); + } +#endif // !_WIN32_WCE + +#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 420) + BOOL InvertRect(LPCRECT lpRect) + { + ATLASSERT(m_hDC != NULL); + return ::InvertRect(m_hDC, lpRect); + } +#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 420) + + BOOL DrawIcon(int x, int y, HICON hIcon) + { + ATLASSERT(m_hDC != NULL); +#ifndef _WIN32_WCE + return ::DrawIcon(m_hDC, x, y, hIcon); +#else // CE specific + return ::DrawIconEx(m_hDC, x, y, hIcon, 0, 0, 0, NULL, DI_NORMAL); +#endif // _WIN32_WCE + } + + BOOL DrawIcon(POINT point, HICON hIcon) + { + ATLASSERT(m_hDC != NULL); +#ifndef _WIN32_WCE + return ::DrawIcon(m_hDC, point.x, point.y, hIcon); +#else // CE specific + return ::DrawIconEx(m_hDC, point.x, point.y, hIcon, 0, 0, 0, NULL, DI_NORMAL); +#endif // _WIN32_WCE + } + + BOOL DrawIconEx(int x, int y, HICON hIcon, int cxWidth, int cyWidth, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL) + { + ATLASSERT(m_hDC != NULL); + return ::DrawIconEx(m_hDC, x, y, hIcon, cxWidth, cyWidth, uStepIfAniCur, hbrFlickerFreeDraw, uFlags); + } + + BOOL DrawIconEx(POINT point, HICON hIcon, SIZE size, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL) + { + ATLASSERT(m_hDC != NULL); + return ::DrawIconEx(m_hDC, point.x, point.y, hIcon, size.cx, size.cy, uStepIfAniCur, hbrFlickerFreeDraw, uFlags); + } + +#ifndef _WIN32_WCE + BOOL DrawState(POINT pt, SIZE size, HBITMAP hBitmap, UINT nFlags, HBRUSH hBrush = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)hBitmap, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_BITMAP); + } + + BOOL DrawState(POINT pt, SIZE size, HICON hIcon, UINT nFlags, HBRUSH hBrush = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)hIcon, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_ICON); + } + + BOOL DrawState(POINT pt, SIZE size, LPCTSTR lpszText, UINT nFlags, BOOL bPrefixText = TRUE, int nTextLen = 0, HBRUSH hBrush = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)lpszText, (WPARAM)nTextLen, pt.x, pt.y, size.cx, size.cy, nFlags | (bPrefixText ? DST_PREFIXTEXT : DST_TEXT)); + } + + BOOL DrawState(POINT pt, SIZE size, DRAWSTATEPROC lpDrawProc, LPARAM lData, UINT nFlags, HBRUSH hBrush = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::DrawState(m_hDC, hBrush, lpDrawProc, lData, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_COMPLEX); + } +#endif // !_WIN32_WCE + +// Ellipse and Polygon Functions +#ifndef _WIN32_WCE + BOOL Chord(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) + { + ATLASSERT(m_hDC != NULL); + return ::Chord(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4); + } + + BOOL Chord(LPCRECT lpRect, POINT ptStart, POINT ptEnd) + { + ATLASSERT(m_hDC != NULL); + return ::Chord(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y); + } +#endif // !_WIN32_WCE + + void DrawFocusRect(LPCRECT lpRect) + { + ATLASSERT(m_hDC != NULL); + ::DrawFocusRect(m_hDC, lpRect); + } + + BOOL Ellipse(int x1, int y1, int x2, int y2) + { + ATLASSERT(m_hDC != NULL); + return ::Ellipse(m_hDC, x1, y1, x2, y2); + } + + BOOL Ellipse(LPCRECT lpRect) + { + ATLASSERT(m_hDC != NULL); + return ::Ellipse(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + } + +#ifndef _WIN32_WCE + BOOL Pie(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) + { + ATLASSERT(m_hDC != NULL); + return ::Pie(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4); + } + + BOOL Pie(LPCRECT lpRect, POINT ptStart, POINT ptEnd) + { + ATLASSERT(m_hDC != NULL); + return ::Pie(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y); + } +#endif // !_WIN32_WCE + + BOOL Polygon(LPPOINT lpPoints, int nCount) + { + ATLASSERT(m_hDC != NULL); + return ::Polygon(m_hDC, lpPoints, nCount); + } + +#ifndef _WIN32_WCE + BOOL PolyPolygon(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount) + { + ATLASSERT(m_hDC != NULL); + return ::PolyPolygon(m_hDC, lpPoints, lpPolyCounts, nCount); + } +#endif // !_WIN32_WCE + + BOOL Rectangle(int x1, int y1, int x2, int y2) + { + ATLASSERT(m_hDC != NULL); + return ::Rectangle(m_hDC, x1, y1, x2, y2); + } + + BOOL Rectangle(LPCRECT lpRect) + { + ATLASSERT(m_hDC != NULL); + return ::Rectangle(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + } + + BOOL RoundRect(int x1, int y1, int x2, int y2, int x3, int y3) + { + ATLASSERT(m_hDC != NULL); + return ::RoundRect(m_hDC, x1, y1, x2, y2, x3, y3); + } + + BOOL RoundRect(LPCRECT lpRect, POINT point) + { + ATLASSERT(m_hDC != NULL); + return ::RoundRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, point.x, point.y); + } + +// Bitmap Functions + BOOL PatBlt(int x, int y, int nWidth, int nHeight, DWORD dwRop) + { + ATLASSERT(m_hDC != NULL); + return ::PatBlt(m_hDC, x, y, nWidth, nHeight, dwRop); + } + + BOOL BitBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, + int xSrc, int ySrc, DWORD dwRop) + { + ATLASSERT(m_hDC != NULL); + return ::BitBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, dwRop); + } + + BOOL StretchBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop) + { + ATLASSERT(m_hDC != NULL); + return ::StretchBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, dwRop); + } + + COLORREF GetPixel(int x, int y) const + { + ATLASSERT(m_hDC != NULL); + return ::GetPixel(m_hDC, x, y); + } + + COLORREF GetPixel(POINT point) const + { + ATLASSERT(m_hDC != NULL); + return ::GetPixel(m_hDC, point.x, point.y); + } + + COLORREF SetPixel(int x, int y, COLORREF crColor) + { + ATLASSERT(m_hDC != NULL); + return ::SetPixel(m_hDC, x, y, crColor); + } + + COLORREF SetPixel(POINT point, COLORREF crColor) + { + ATLASSERT(m_hDC != NULL); + return ::SetPixel(m_hDC, point.x, point.y, crColor); + } + +#ifndef _WIN32_WCE + BOOL FloodFill(int x, int y, COLORREF crColor) + { + ATLASSERT(m_hDC != NULL); + return ::FloodFill(m_hDC, x, y, crColor); + } + + BOOL ExtFloodFill(int x, int y, COLORREF crColor, UINT nFillType) + { + ATLASSERT(m_hDC != NULL); + return ::ExtFloodFill(m_hDC, x, y, crColor, nFillType); + } +#endif // !_WIN32_WCE + + BOOL MaskBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, HBITMAP hMaskBitmap, int xMask, int yMask, DWORD dwRop) + { + ATLASSERT(m_hDC != NULL); + return ::MaskBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, hMaskBitmap, xMask, yMask, dwRop); + } + +#ifndef _WIN32_WCE + BOOL PlgBlt(LPPOINT lpPoint, HDC hSrcDC, int xSrc, int ySrc, int nWidth, int nHeight, HBITMAP hMaskBitmap, int xMask, int yMask) + { + ATLASSERT(m_hDC != NULL); + return ::PlgBlt(m_hDC, lpPoint, hSrcDC, xSrc, ySrc, nWidth, nHeight, hMaskBitmap, xMask, yMask); + } + + BOOL SetPixelV(int x, int y, COLORREF crColor) + { + ATLASSERT(m_hDC != NULL); + return ::SetPixelV(m_hDC, x, y, crColor); + } + + BOOL SetPixelV(POINT point, COLORREF crColor) + { + ATLASSERT(m_hDC != NULL); + return ::SetPixelV(m_hDC, point.x, point.y, crColor); + } +#endif // !_WIN32_WCE + +#if !defined(_ATL_NO_MSIMG) || defined(_WIN32_WCE) +#ifndef _WIN32_WCE + BOOL TransparentBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, UINT crTransparent) + { + ATLASSERT(m_hDC != NULL); + return ::TransparentBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, crTransparent); + } +#else // CE specific + BOOL TransparentImage(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, UINT crTransparent) + { + ATLASSERT(m_hDC != NULL); + return ::TransparentImage(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, crTransparent); + } +#endif // _WIN32_WCE + +#if (!defined(_WIN32_WCE) || (_WIN32_WCE >= 420)) + BOOL GradientFill(const PTRIVERTEX pVertices, DWORD nVertices, void* pMeshElements, DWORD nMeshElements, DWORD dwMode) + { + ATLASSERT(m_hDC != NULL); + return ::GradientFill(m_hDC, pVertices, nVertices, pMeshElements, nMeshElements, dwMode); + } +#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 420) + +#if !defined(_WIN32_WCE) || (_WIN32_WCE > 0x500) + BOOL AlphaBlend(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, BLENDFUNCTION bf) + { + ATLASSERT(m_hDC != NULL); + return ::AlphaBlend(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, bf); + } +#endif // !defined(_WIN32_WCE) || (_WIN32_WCE > 0x500) +#endif // !defined(_ATL_NO_MSIMG) || defined(_WIN32_WCE) + +// Extra bitmap functions + // Helper function for painting a disabled toolbar or menu bitmap + // This function can take either an HBITMAP (for SS) or a DC with + // the bitmap already painted (for cmdbar) + BOOL DitherBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, HBITMAP hBitmap, int xSrc, int ySrc, + HBRUSH hBrushBackground = ::GetSysColorBrush(COLOR_3DFACE), + HBRUSH hBrush3DEffect = ::GetSysColorBrush(COLOR_3DHILIGHT), + HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW)) + { + ATLASSERT(m_hDC != NULL || hBitmap != NULL); + ATLASSERT(nWidth > 0 && nHeight > 0); + + // Create a generic DC for all BitBlts + CDCHandle dc = (hSrcDC != NULL) ? hSrcDC : ::CreateCompatibleDC(m_hDC); + ATLASSERT(dc.m_hDC != NULL); + if(dc.m_hDC == NULL) + return FALSE; + + // Create a DC for the monochrome DIB section + CDC dcBW = ::CreateCompatibleDC(m_hDC); + ATLASSERT(dcBW.m_hDC != NULL); + if(dcBW.m_hDC == NULL) + { + if(hSrcDC == NULL) + dc.DeleteDC(); + return FALSE; + } + + // Create the monochrome DIB section with a black and white palette + struct RGBBWBITMAPINFO + { + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[2]; + }; + + RGBBWBITMAPINFO rgbBWBitmapInfo = + { + { sizeof(BITMAPINFOHEADER), nWidth, nHeight, 1, 1, BI_RGB, 0, 0, 0, 0, 0 }, + { { 0x00, 0x00, 0x00, 0x00 }, { 0xFF, 0xFF, 0xFF, 0x00 } } + }; + + VOID* pbitsBW; + CBitmap bmpBW = ::CreateDIBSection(dcBW, (LPBITMAPINFO)&rgbBWBitmapInfo, DIB_RGB_COLORS, &pbitsBW, NULL, 0); + ATLASSERT(bmpBW.m_hBitmap != NULL); + if(bmpBW.m_hBitmap == NULL) + { + if(hSrcDC == NULL) + dc.DeleteDC(); + return FALSE; + } + + // Attach the monochrome DIB section and the bitmap to the DCs + HBITMAP hbmOldBW = dcBW.SelectBitmap(bmpBW); + HBITMAP hbmOldDC = NULL; + if(hBitmap != NULL) + hbmOldDC = dc.SelectBitmap(hBitmap); + + // Block: Dark gray removal: we want (128, 128, 128) pixels to become black and not white + { + CDC dcTemp1 = ::CreateCompatibleDC(m_hDC); + CDC dcTemp2 = ::CreateCompatibleDC(m_hDC); + CBitmap bmpTemp1; + bmpTemp1.CreateCompatibleBitmap(dc, nWidth, nHeight); + CBitmap bmpTemp2; + bmpTemp2.CreateBitmap(nWidth, nHeight, 1, 1, NULL); + HBITMAP hOldBmp1 = dcTemp1.SelectBitmap(bmpTemp1); + HBITMAP hOldBmp2 = dcTemp2.SelectBitmap(bmpTemp2); + // Let's copy our image, it will be altered + dcTemp1.BitBlt(0, 0, nWidth, nHeight, dc, xSrc, ySrc, SRCCOPY); + + // All dark gray pixels will become white, the others black + dcTemp1.SetBkColor(RGB(128, 128, 128)); + dcTemp2.BitBlt(0, 0, nWidth, nHeight, dcTemp1, 0, 0, SRCCOPY); + // Do an XOR to set to black these white pixels + dcTemp1.BitBlt(0, 0, nWidth, nHeight, dcTemp2, 0, 0, SRCINVERT); + + // BitBlt the bitmap into the monochrome DIB section + // The DIB section will do a true monochrome conversion + // The magenta background being closer to white will become white + dcBW.BitBlt(0, 0, nWidth, nHeight, dcTemp1, 0, 0, SRCCOPY); + + // Cleanup + dcTemp1.SelectBitmap(hOldBmp1); + dcTemp2.SelectBitmap(hOldBmp2); + } + + // Paint the destination rectangle using hBrushBackground + if(hBrushBackground != NULL) + { + RECT rc = { x, y, x + nWidth, y + nHeight }; + FillRect(&rc, hBrushBackground); + } + + // BitBlt the black bits in the monochrome bitmap into hBrush3DEffect color in the destination DC + // The magic ROP comes from the Charles Petzold's book + HBRUSH hOldBrush = SelectBrush(hBrush3DEffect); + BitBlt(x + 1, y + 1, nWidth, nHeight, dcBW, 0, 0, 0xB8074A); + + // BitBlt the black bits in the monochrome bitmap into hBrushDisabledImage color in the destination DC + SelectBrush(hBrushDisabledImage); + BitBlt(x, y, nWidth, nHeight, dcBW, 0, 0, 0xB8074A); + + SelectBrush(hOldBrush); + dcBW.SelectBitmap(hbmOldBW); + dc.SelectBitmap(hbmOldDC); + + if(hSrcDC == NULL) + dc.DeleteDC(); + + return TRUE; + } + +// Text Functions +#ifndef _WIN32_WCE + BOOL TextOut(int x, int y, LPCTSTR lpszString, int nCount = -1) + { + ATLASSERT(m_hDC != NULL); + if(nCount == -1) + nCount = lstrlen(lpszString); + return ::TextOut(m_hDC, x, y, lpszString, nCount); + } +#endif // !_WIN32_WCE + + BOOL ExtTextOut(int x, int y, UINT nOptions, LPCRECT lpRect, LPCTSTR lpszString, UINT nCount = -1, LPINT lpDxWidths = NULL) + { + ATLASSERT(m_hDC != NULL); + if(nCount == -1) + nCount = lstrlen(lpszString); + return ::ExtTextOut(m_hDC, x, y, nOptions, lpRect, lpszString, nCount, lpDxWidths); + } + +#ifndef _WIN32_WCE + SIZE TabbedTextOut(int x, int y, LPCTSTR lpszString, int nCount = -1, int nTabPositions = 0, LPINT lpnTabStopPositions = NULL, int nTabOrigin = 0) + { + ATLASSERT(m_hDC != NULL); + if(nCount == -1) + nCount = lstrlen(lpszString); + LONG lRes = ::TabbedTextOut(m_hDC, x, y, lpszString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin); + SIZE size = { GET_X_LPARAM(lRes), GET_Y_LPARAM(lRes) }; + return size; + } +#endif // !_WIN32_WCE + + int DrawText(LPCTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat) + { + ATLASSERT(m_hDC != NULL); +#ifndef _WIN32_WCE + ATLASSERT((uFormat & DT_MODIFYSTRING) == 0); +#endif // !_WIN32_WCE + return ::DrawText(m_hDC, lpstrText, cchText, lpRect, uFormat); + } + + int DrawText(LPTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat) + { + ATLASSERT(m_hDC != NULL); + return ::DrawText(m_hDC, lpstrText, cchText, lpRect, uFormat); + } + +#ifndef _WIN32_WCE + int DrawTextEx(LPTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat, LPDRAWTEXTPARAMS lpDTParams = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::DrawTextEx(m_hDC, lpstrText, cchText, lpRect, uFormat, lpDTParams); + } +#endif // !_WIN32_WCE + +#if (_WIN32_WINNT >= 0x0501) + int DrawShadowText(LPCWSTR lpstrText, int cchText, LPRECT lpRect, DWORD dwFlags, COLORREF clrText, COLORREF clrShadow, int xOffset, int yOffset) + { + ATLASSERT(m_hDC != NULL); + // This function is present only if comctl32.dll version 6 is loaded; + // we use LoadLibrary/GetProcAddress to allow apps compiled with + // _WIN32_WINNT >= 0x0501 to run on older Windows/CommCtrl + int nRet = 0; + HMODULE hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll")); + ATLASSERT(hCommCtrlDLL != NULL); + if(hCommCtrlDLL != NULL) + { + typedef int (WINAPI *PFN_DrawShadowText)(HDC hDC, LPCWSTR lpstrText, UINT cchText, LPRECT lpRect, DWORD dwFlags, COLORREF clrText, COLORREF clrShadow, int xOffset, int yOffset); + PFN_DrawShadowText pfnDrawShadowText = (PFN_DrawShadowText)::GetProcAddress(hCommCtrlDLL, "DrawShadowText"); + ATLASSERT(pfnDrawShadowText != NULL); // this function requires CommCtrl6 + if(pfnDrawShadowText != NULL) + nRet = pfnDrawShadowText(m_hDC, lpstrText, cchText, lpRect, dwFlags, clrText, clrShadow, xOffset, yOffset); + ::FreeLibrary(hCommCtrlDLL); + } + return nRet; + } +#endif // (_WIN32_WINNT >= 0x0501) + + BOOL GetTextExtent(LPCTSTR lpszString, int nCount, LPSIZE lpSize) const + { + ATLASSERT(m_hDC != NULL); + if(nCount == -1) + nCount = lstrlen(lpszString); + return ::GetTextExtentPoint32(m_hDC, lpszString, nCount, lpSize); + } + + BOOL GetTextExtentExPoint(LPCTSTR lpszString, int cchString, LPSIZE lpSize, int nMaxExtent, LPINT lpnFit = NULL, LPINT alpDx = NULL) + { + ATLASSERT(m_hDC != NULL); + return ::GetTextExtentExPoint(m_hDC, lpszString, cchString, nMaxExtent, lpnFit, alpDx, lpSize); + } + +#ifndef _WIN32_WCE + DWORD GetTabbedTextExtent(LPCTSTR lpszString, int nCount = -1, int nTabPositions = 0, LPINT lpnTabStopPositions = NULL) const + { + ATLASSERT(m_hDC != NULL); + if(nCount == -1) + nCount = lstrlen(lpszString); + return ::GetTabbedTextExtent(m_hDC, lpszString, nCount, nTabPositions, lpnTabStopPositions); + } + + BOOL GrayString(HBRUSH hBrush, BOOL (CALLBACK* lpfnOutput)(HDC, LPARAM, int), LPARAM lpData, int nCount, int x, int y, int nWidth, int nHeight) + { + ATLASSERT(m_hDC != NULL); + return ::GrayString(m_hDC, hBrush, (GRAYSTRINGPROC)lpfnOutput, lpData, nCount, x, y, nWidth, nHeight); + } +#endif // !_WIN32_WCE + +#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) + UINT GetTextAlign() const + { + ATLASSERT(m_hDC != NULL); + return ::GetTextAlign(m_hDC); + } + + UINT SetTextAlign(UINT nFlags) + { + ATLASSERT(m_hDC != NULL); + return ::SetTextAlign(m_hDC, nFlags); + } +#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) + + int GetTextFace(LPTSTR lpszFacename, int nCount) const + { + ATLASSERT(m_hDC != NULL); + return ::GetTextFace(m_hDC, nCount, lpszFacename); + } + + int GetTextFaceLen() const + { + ATLASSERT(m_hDC != NULL); + return ::GetTextFace(m_hDC, 0, NULL); + } + +#ifndef _ATL_NO_COM +#ifdef _OLEAUTO_H_ + BOOL GetTextFace(BSTR& bstrFace) const + { + USES_CONVERSION; + ATLASSERT(m_hDC != NULL); + ATLASSERT(bstrFace == NULL); + + int nLen = GetTextFaceLen(); + if(nLen == 0) + return FALSE; + + CTempBuffer buff; + LPTSTR lpszText = buff.Allocate(nLen); + if(lpszText == NULL) + return FALSE; + + if(!GetTextFace(lpszText, nLen)) + return FALSE; + + bstrFace = ::SysAllocString(T2OLE(lpszText)); + return (bstrFace != NULL) ? TRUE : FALSE; + } +#endif +#endif // !_ATL_NO_COM + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + int GetTextFace(_CSTRING_NS::CString& strFace) const + { + ATLASSERT(m_hDC != NULL); + + int nLen = GetTextFaceLen(); + if(nLen == 0) + return 0; + + LPTSTR lpstr = strFace.GetBufferSetLength(nLen); + if(lpstr == NULL) + return 0; + int nRet = GetTextFace(lpstr, nLen); + strFace.ReleaseBuffer(); + return nRet; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + + BOOL GetTextMetrics(LPTEXTMETRIC lpMetrics) const + { + ATLASSERT(m_hDC != NULL); + return ::GetTextMetrics(m_hDC, lpMetrics); + } + +#ifndef _WIN32_WCE + int SetTextJustification(int nBreakExtra, int nBreakCount) + { + ATLASSERT(m_hDC != NULL); + return ::SetTextJustification(m_hDC, nBreakExtra, nBreakCount); + } + + int GetTextCharacterExtra() const + { + ATLASSERT(m_hDC != NULL); + return ::GetTextCharacterExtra(m_hDC); + } + + int SetTextCharacterExtra(int nCharExtra) + { + ATLASSERT(m_hDC != NULL); + return ::SetTextCharacterExtra(m_hDC, nCharExtra); + } +#endif // !_WIN32_WCE + +// Advanced Drawing + BOOL DrawEdge(LPRECT lpRect, UINT nEdge, UINT nFlags) + { + ATLASSERT(m_hDC != NULL); + return ::DrawEdge(m_hDC, lpRect, nEdge, nFlags); + } + + BOOL DrawFrameControl(LPRECT lpRect, UINT nType, UINT nState) + { + ATLASSERT(m_hDC != NULL); + return ::DrawFrameControl(m_hDC, lpRect, nType, nState); + } + +// Scrolling Functions + BOOL ScrollDC(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, HRGN hRgnUpdate, LPRECT lpRectUpdate) + { + ATLASSERT(m_hDC != NULL); + return ::ScrollDC(m_hDC, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate); + } + +// Font Functions +#ifndef _WIN32_WCE + BOOL GetCharWidth(UINT nFirstChar, UINT nLastChar, LPINT lpBuffer) const + { + ATLASSERT(m_hDC != NULL); + return ::GetCharWidth(m_hDC, nFirstChar, nLastChar, lpBuffer); + } + + // GetCharWidth32 is not supported under Win9x + BOOL GetCharWidth32(UINT nFirstChar, UINT nLastChar, LPINT lpBuffer) const + { + ATLASSERT(m_hDC != NULL); + return ::GetCharWidth32(m_hDC, nFirstChar, nLastChar, lpBuffer); + } + + DWORD SetMapperFlags(DWORD dwFlag) + { + ATLASSERT(m_hDC != NULL); + return ::SetMapperFlags(m_hDC, dwFlag); + } + + BOOL GetAspectRatioFilter(LPSIZE lpSize) const + { + ATLASSERT(m_hDC != NULL); + return ::GetAspectRatioFilterEx(m_hDC, lpSize); + } + + BOOL GetCharABCWidths(UINT nFirstChar, UINT nLastChar, LPABC lpabc) const + { + ATLASSERT(m_hDC != NULL); + return ::GetCharABCWidths(m_hDC, nFirstChar, nLastChar, lpabc); + } + + DWORD GetFontData(DWORD dwTable, DWORD dwOffset, LPVOID lpData, DWORD cbData) const + { + ATLASSERT(m_hDC != NULL); + return ::GetFontData(m_hDC, dwTable, dwOffset, lpData, cbData); + } + + int GetKerningPairs(int nPairs, LPKERNINGPAIR lpkrnpair) const + { + ATLASSERT(m_hDC != NULL); + return ::GetKerningPairs(m_hDC, nPairs, lpkrnpair); + } + + UINT GetOutlineTextMetrics(UINT cbData, LPOUTLINETEXTMETRIC lpotm) const + { + ATLASSERT(m_hDC != NULL); + return ::GetOutlineTextMetrics(m_hDC, cbData, lpotm); + } + + DWORD GetGlyphOutline(UINT nChar, UINT nFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpBuffer, const MAT2* lpmat2) const + { + ATLASSERT(m_hDC != NULL); + return ::GetGlyphOutline(m_hDC, nChar, nFormat, lpgm, cbBuffer, lpBuffer, lpmat2); + } + + BOOL GetCharABCWidths(UINT nFirstChar, UINT nLastChar, LPABCFLOAT lpABCF) const + { + ATLASSERT(m_hDC != NULL); + return ::GetCharABCWidthsFloat(m_hDC, nFirstChar, nLastChar, lpABCF); + } + + BOOL GetCharWidth(UINT nFirstChar, UINT nLastChar, float* lpFloatBuffer) const + { + ATLASSERT(m_hDC != NULL); + return ::GetCharWidthFloat(m_hDC, nFirstChar, nLastChar, lpFloatBuffer); + } +#endif // !_WIN32_WCE + +// Printer/Device Escape Functions +#ifndef _WIN32_WCE + int Escape(int nEscape, int nCount, LPCSTR lpszInData, LPVOID lpOutData) + { + ATLASSERT(m_hDC != NULL); + return ::Escape(m_hDC, nEscape, nCount, lpszInData, lpOutData); + } +#endif // !_WIN32_WCE + + int Escape(int nEscape, int nInputSize, LPCSTR lpszInputData, + int nOutputSize, LPSTR lpszOutputData) + { + ATLASSERT(m_hDC != NULL); + return ::ExtEscape(m_hDC, nEscape, nInputSize, lpszInputData, nOutputSize, lpszOutputData); + } + +#ifndef _WIN32_WCE + int DrawEscape(int nEscape, int nInputSize, LPCSTR lpszInputData) + { + ATLASSERT(m_hDC != NULL); + return ::DrawEscape(m_hDC, nEscape, nInputSize, lpszInputData); + } +#endif // !_WIN32_WCE + + // Escape helpers +#if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 200) && defined(StartDoc)) + int StartDoc(LPCTSTR lpszDocName) // old Win3.0 version + { + DOCINFO di = { 0 }; + di.cbSize = sizeof(DOCINFO); + di.lpszDocName = lpszDocName; + return StartDoc(&di); + } + + int StartDoc(LPDOCINFO lpDocInfo) + { + ATLASSERT(m_hDC != NULL); + return ::StartDoc(m_hDC, lpDocInfo); + } + + int StartPage() + { + ATLASSERT(m_hDC != NULL); + return ::StartPage(m_hDC); + } + + int EndPage() + { + ATLASSERT(m_hDC != NULL); + return ::EndPage(m_hDC); + } + + int SetAbortProc(BOOL (CALLBACK* lpfn)(HDC, int)) + { + ATLASSERT(m_hDC != NULL); + return ::SetAbortProc(m_hDC, (ABORTPROC)lpfn); + } + + int AbortDoc() + { + ATLASSERT(m_hDC != NULL); + return ::AbortDoc(m_hDC); + } + + int EndDoc() + { + ATLASSERT(m_hDC != NULL); + return ::EndDoc(m_hDC); + } +#endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 200) && defined(StartDoc)) + +// MetaFile Functions +#ifndef _WIN32_WCE + BOOL PlayMetaFile(HMETAFILE hMF) + { + ATLASSERT(m_hDC != NULL); + if(::GetDeviceCaps(m_hDC, TECHNOLOGY) == DT_METAFILE) + { + // playing metafile in metafile, just use core windows API + return ::PlayMetaFile(m_hDC, hMF); + } + + // for special playback, lParam == pDC + return ::EnumMetaFile(m_hDC, hMF, EnumMetaFileProc, (LPARAM)this); + } + + BOOL PlayMetaFile(HENHMETAFILE hEnhMetaFile, LPCRECT lpBounds) + { + ATLASSERT(m_hDC != NULL); + return ::PlayEnhMetaFile(m_hDC, hEnhMetaFile, lpBounds); + } + + BOOL AddMetaFileComment(UINT nDataSize, const BYTE* pCommentData) // can be used for enhanced metafiles only + { + ATLASSERT(m_hDC != NULL); + return ::GdiComment(m_hDC, nDataSize, pCommentData); + } + + // Special handling for metafile playback + static int CALLBACK EnumMetaFileProc(HDC hDC, HANDLETABLE* pHandleTable, METARECORD* pMetaRec, int nHandles, LPARAM lParam) + { + CDCHandle* pDC = (CDCHandle*)lParam; + + switch (pMetaRec->rdFunction) + { + case META_SETMAPMODE: + pDC->SetMapMode((int)(short)pMetaRec->rdParm[0]); + break; + case META_SETWINDOWEXT: + pDC->SetWindowExt((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); + break; + case META_SETWINDOWORG: + pDC->SetWindowOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); + break; + case META_SETVIEWPORTEXT: + pDC->SetViewportExt((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); + break; + case META_SETVIEWPORTORG: + pDC->SetViewportOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); + break; + case META_SCALEWINDOWEXT: + pDC->ScaleWindowExt((int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2], + (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); + break; + case META_SCALEVIEWPORTEXT: + pDC->ScaleViewportExt((int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2], + (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); + break; + case META_OFFSETVIEWPORTORG: + pDC->OffsetViewportOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); + break; + case META_SAVEDC: + pDC->SaveDC(); + break; + case META_RESTOREDC: + pDC->RestoreDC((int)(short)pMetaRec->rdParm[0]); + break; + case META_SETBKCOLOR: + pDC->SetBkColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]); + break; + case META_SETTEXTCOLOR: + pDC->SetTextColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]); + break; + + // need to watch out for SelectObject(HFONT), for custom font mapping + case META_SELECTOBJECT: + { + HGDIOBJ hObject = pHandleTable->objectHandle[pMetaRec->rdParm[0]]; + UINT nObjType = ::GetObjectType(hObject); + if(nObjType == 0) + { + // object type is unknown, determine if it is a font + HFONT hStockFont = (HFONT)::GetStockObject(SYSTEM_FONT); + HFONT hFontOld = (HFONT)::SelectObject(pDC->m_hDC, hStockFont); + HGDIOBJ hObjOld = ::SelectObject(pDC->m_hDC, hObject); + if(hObjOld == hStockFont) + { + // got the stock object back, so must be selecting a font + pDC->SelectFont((HFONT)hObject); + break; // don't play the default record + } + else + { + // didn't get the stock object back, so restore everything + ::SelectObject(pDC->m_hDC, hFontOld); + ::SelectObject(pDC->m_hDC, hObjOld); + } + // and fall through to PlayMetaFileRecord... + } + else if(nObjType == OBJ_FONT) + { + // play back as CDCHandle::SelectFont(HFONT) + pDC->SelectFont((HFONT)hObject); + break; // don't play the default record + } + } + // fall through... + + default: + ::PlayMetaFileRecord(hDC, pHandleTable, pMetaRec, nHandles); + break; + } + + return 1; + } +#endif // !_WIN32_WCE + +// Path Functions +#ifndef _WIN32_WCE + BOOL AbortPath() + { + ATLASSERT(m_hDC != NULL); + return ::AbortPath(m_hDC); + } + + BOOL BeginPath() + { + ATLASSERT(m_hDC != NULL); + return ::BeginPath(m_hDC); + } + + BOOL CloseFigure() + { + ATLASSERT(m_hDC != NULL); + return ::CloseFigure(m_hDC); + } + + BOOL EndPath() + { + ATLASSERT(m_hDC != NULL); + return ::EndPath(m_hDC); + } + + BOOL FillPath() + { + ATLASSERT(m_hDC != NULL); + return ::FillPath(m_hDC); + } + + BOOL FlattenPath() + { + ATLASSERT(m_hDC != NULL); + return ::FlattenPath(m_hDC); + } + + BOOL StrokeAndFillPath() + { + ATLASSERT(m_hDC != NULL); + return ::StrokeAndFillPath(m_hDC); + } + + BOOL StrokePath() + { + ATLASSERT(m_hDC != NULL); + return ::StrokePath(m_hDC); + } + + BOOL WidenPath() + { + ATLASSERT(m_hDC != NULL); + return ::WidenPath(m_hDC); + } + + BOOL GetMiterLimit(PFLOAT pfMiterLimit) const + { + ATLASSERT(m_hDC != NULL); + return ::GetMiterLimit(m_hDC, pfMiterLimit); + } + + BOOL SetMiterLimit(float fMiterLimit) + { + ATLASSERT(m_hDC != NULL); + return ::SetMiterLimit(m_hDC, fMiterLimit, NULL); + } + + int GetPath(LPPOINT lpPoints, LPBYTE lpTypes, int nCount) const + { + ATLASSERT(m_hDC != NULL); + return ::GetPath(m_hDC, lpPoints, lpTypes, nCount); + } + + BOOL SelectClipPath(int nMode) + { + ATLASSERT(m_hDC != NULL); + return ::SelectClipPath(m_hDC, nMode); + } +#endif // !_WIN32_WCE + +// Misc Helper Functions + static CBrushHandle PASCAL GetHalftoneBrush() + { + HBRUSH halftoneBrush = NULL; + WORD grayPattern[8]; + for(int i = 0; i < 8; i++) + grayPattern[i] = (WORD)(0x5555 << (i & 1)); + HBITMAP grayBitmap = CreateBitmap(8, 8, 1, 1, &grayPattern); + if(grayBitmap != NULL) + { + halftoneBrush = ::CreatePatternBrush(grayBitmap); + DeleteObject(grayBitmap); + } + return CBrushHandle(halftoneBrush); + } + + void DrawDragRect(LPCRECT lpRect, SIZE size, LPCRECT lpRectLast, SIZE sizeLast, HBRUSH hBrush = NULL, HBRUSH hBrushLast = NULL) + { + // first, determine the update region and select it + CRgn rgnOutside; + rgnOutside.CreateRectRgnIndirect(lpRect); + RECT rect = *lpRect; + ::InflateRect(&rect, -size.cx, -size.cy); + ::IntersectRect(&rect, &rect, lpRect); + CRgn rgnInside; + rgnInside.CreateRectRgnIndirect(&rect); + CRgn rgnNew; + rgnNew.CreateRectRgn(0, 0, 0, 0); + rgnNew.CombineRgn(rgnOutside, rgnInside, RGN_XOR); + + HBRUSH hBrushOld = NULL; + CBrush brushHalftone; + if(hBrush == NULL) + brushHalftone = hBrush = CDCHandle::GetHalftoneBrush(); + if(hBrushLast == NULL) + hBrushLast = hBrush; + + CRgn rgnLast; + CRgn rgnUpdate; + if(lpRectLast != NULL) + { + // find difference between new region and old region + rgnLast.CreateRectRgn(0, 0, 0, 0); + rgnOutside.SetRectRgn(lpRectLast->left, lpRectLast->top, lpRectLast->right, lpRectLast->bottom); + rect = *lpRectLast; + ::InflateRect(&rect, -sizeLast.cx, -sizeLast.cy); + ::IntersectRect(&rect, &rect, lpRectLast); + rgnInside.SetRectRgn(rect.left, rect.top, rect.right, rect.bottom); + rgnLast.CombineRgn(rgnOutside, rgnInside, RGN_XOR); + + // only diff them if brushes are the same + if(hBrush == hBrushLast) + { + rgnUpdate.CreateRectRgn(0, 0, 0, 0); + rgnUpdate.CombineRgn(rgnLast, rgnNew, RGN_XOR); + } + } + if(hBrush != hBrushLast && lpRectLast != NULL) + { + // brushes are different -- erase old region first + SelectClipRgn(rgnLast); + GetClipBox(&rect); + hBrushOld = SelectBrush(hBrushLast); + PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT); + SelectBrush(hBrushOld); + hBrushOld = NULL; + } + + // draw into the update/new region + SelectClipRgn(rgnUpdate.IsNull() ? rgnNew : rgnUpdate); + GetClipBox(&rect); + hBrushOld = SelectBrush(hBrush); + PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT); + + // cleanup DC + if(hBrushOld != NULL) + SelectBrush(hBrushOld); + SelectClipRgn(NULL); + } + + void FillSolidRect(LPCRECT lpRect, COLORREF clr) + { + ATLASSERT(m_hDC != NULL); + + COLORREF clrOld = ::SetBkColor(m_hDC, clr); + ATLASSERT(clrOld != CLR_INVALID); + if(clrOld != CLR_INVALID) + { + ::ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL); + ::SetBkColor(m_hDC, clrOld); + } + } + + void FillSolidRect(int x, int y, int cx, int cy, COLORREF clr) + { + ATLASSERT(m_hDC != NULL); + + RECT rect = { x, y, x + cx, y + cy }; + FillSolidRect(&rect, clr); + } + + void Draw3dRect(LPCRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight) + { + Draw3dRect(lpRect->left, lpRect->top, lpRect->right - lpRect->left, + lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight); + } + + void Draw3dRect(int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight) + { + FillSolidRect(x, y, cx - 1, 1, clrTopLeft); + FillSolidRect(x, y, 1, cy - 1, clrTopLeft); + FillSolidRect(x + cx, y, -1, cy, clrBottomRight); + FillSolidRect(x, y + cy, cx, -1, clrBottomRight); + } + +// DIB support +#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 410) + int SetDIBitsToDevice(int x, int y, DWORD dwWidth, DWORD dwHeight, int xSrc, int ySrc, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse) + { + ATLASSERT(m_hDC != NULL); + return ::SetDIBitsToDevice(m_hDC, x, y, dwWidth, dwHeight, xSrc, ySrc, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse); + } +#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 410) + +#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) + int StretchDIBits(int x, int y, int nWidth, int nHeight, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse, DWORD dwRop) + { + ATLASSERT(m_hDC != NULL); + return ::StretchDIBits(m_hDC, x, y, nWidth, nHeight, xSrc, ySrc, nSrcWidth, nSrcHeight, lpvBits, lpbmi, uColorUse, dwRop); + } + + UINT GetDIBColorTable(UINT uStartIndex, UINT cEntries, RGBQUAD* pColors) const + { + ATLASSERT(m_hDC != NULL); + return ::GetDIBColorTable(m_hDC, uStartIndex, cEntries, pColors); + } + + UINT SetDIBColorTable(UINT uStartIndex, UINT cEntries, CONST RGBQUAD* pColors) + { + ATLASSERT(m_hDC != NULL); + return ::SetDIBColorTable(m_hDC, uStartIndex, cEntries, pColors); + } +#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) + +// OpenGL support +#if !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE) + int ChoosePixelFormat(CONST PIXELFORMATDESCRIPTOR* ppfd) + { + ATLASSERT(m_hDC != NULL); + return ::ChoosePixelFormat(m_hDC, ppfd); + } + + int DescribePixelFormat(int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd) + { + ATLASSERT(m_hDC != NULL); + return ::DescribePixelFormat(m_hDC, iPixelFormat, nBytes, ppfd); + } + + int GetPixelFormat() const + { + ATLASSERT(m_hDC != NULL); + return ::GetPixelFormat(m_hDC); + } + + BOOL SetPixelFormat(int iPixelFormat, CONST PIXELFORMATDESCRIPTOR* ppfd) + { + ATLASSERT(m_hDC != NULL); + return ::SetPixelFormat(m_hDC, iPixelFormat, ppfd); + } + + BOOL SwapBuffers() + { + ATLASSERT(m_hDC != NULL); + return ::SwapBuffers(m_hDC); + } + + HGLRC wglCreateContext() + { + ATLASSERT(m_hDC != NULL); + return ::wglCreateContext(m_hDC); + } + + HGLRC wglCreateLayerContext(int iLayerPlane) + { + ATLASSERT(m_hDC != NULL); + return ::wglCreateLayerContext(m_hDC, iLayerPlane); + } + + BOOL wglMakeCurrent(HGLRC hglrc) + { + ATLASSERT(m_hDC != NULL); + return ::wglMakeCurrent(m_hDC, hglrc); + } + + BOOL wglUseFontBitmaps(DWORD dwFirst, DWORD dwCount, DWORD listBase) + { + ATLASSERT(m_hDC != NULL); + return ::wglUseFontBitmaps(m_hDC, dwFirst, dwCount, listBase); + } + + BOOL wglUseFontOutlines(DWORD dwFirst, DWORD dwCount, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf) + { + ATLASSERT(m_hDC != NULL); + return ::wglUseFontOutlines(m_hDC, dwFirst, dwCount, listBase, deviation, extrusion, format, lpgmf); + } + + BOOL wglDescribeLayerPlane(int iPixelFormat, int iLayerPlane, UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd) + { + ATLASSERT(m_hDC != NULL); + return ::wglDescribeLayerPlane(m_hDC, iPixelFormat, iLayerPlane, nBytes, plpd); + } + + int wglSetLayerPaletteEntries(int iLayerPlane, int iStart, int cEntries, CONST COLORREF* pclr) + { + ATLASSERT(m_hDC != NULL); + return ::wglSetLayerPaletteEntries(m_hDC, iLayerPlane, iStart, cEntries, pclr); + } + + int wglGetLayerPaletteEntries(int iLayerPlane, int iStart, int cEntries, COLORREF* pclr) + { + ATLASSERT(m_hDC != NULL); + return ::wglGetLayerPaletteEntries(m_hDC, iLayerPlane, iStart, cEntries, pclr); + } + + BOOL wglRealizeLayerPalette(int iLayerPlane, BOOL bRealize) + { + ATLASSERT(m_hDC != NULL); + return ::wglRealizeLayerPalette(m_hDC, iLayerPlane, bRealize); + } + + BOOL wglSwapLayerBuffers(UINT uPlanes) + { + ATLASSERT(m_hDC != NULL); + return ::wglSwapLayerBuffers(m_hDC, uPlanes); + } +#endif // !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE) + +// New for Windows 2000 only +#if (_WIN32_WINNT >= 0x0500) + COLORREF GetDCPenColor() const + { + ATLASSERT(m_hDC != NULL); + return ::GetDCPenColor(m_hDC); + } + + COLORREF SetDCPenColor(COLORREF clr) + { + ATLASSERT(m_hDC != NULL); + return ::SetDCPenColor(m_hDC, clr); + } + + COLORREF GetDCBrushColor() const + { + ATLASSERT(m_hDC != NULL); + return ::GetDCBrushColor(m_hDC); + } + + COLORREF SetDCBrushColor(COLORREF clr) + { + ATLASSERT(m_hDC != NULL); + return ::SetDCBrushColor(m_hDC, clr); + } + +#ifndef _WIN32_WCE + DWORD GetFontUnicodeRanges(LPGLYPHSET lpgs) const + { + ATLASSERT(m_hDC != NULL); + return ::GetFontUnicodeRanges(m_hDC, lpgs); + } +#endif // !_WIN32_WCE + + DWORD GetGlyphIndices(LPCTSTR lpstr, int cch, LPWORD pgi, DWORD dwFlags) const + { + ATLASSERT(m_hDC != NULL); + return ::GetGlyphIndices(m_hDC, lpstr, cch, pgi, dwFlags); + } + + BOOL GetTextExtentPointI(LPWORD pgiIn, int cgi, LPSIZE lpSize) const + { + ATLASSERT(m_hDC != NULL); + return ::GetTextExtentPointI(m_hDC, pgiIn, cgi, lpSize); + } + + BOOL GetTextExtentExPointI(LPWORD pgiIn, int cgi, int nMaxExtent, LPINT lpnFit, LPINT alpDx, LPSIZE lpSize) const + { + ATLASSERT(m_hDC != NULL); + return ::GetTextExtentExPointI(m_hDC, pgiIn, cgi, nMaxExtent, lpnFit, alpDx, lpSize); + } + + BOOL GetCharWidthI(UINT giFirst, UINT cgi, LPWORD pgi, LPINT lpBuffer) const + { + ATLASSERT(m_hDC != NULL); + return ::GetCharWidthI(m_hDC, giFirst, cgi, pgi, lpBuffer); + } + + BOOL GetCharABCWidthsI(UINT giFirst, UINT cgi, LPWORD pgi, LPABC lpabc) const + { + ATLASSERT(m_hDC != NULL); + return ::GetCharABCWidthsI(m_hDC, giFirst, cgi, pgi, lpabc); + } +#endif // (_WIN32_WINNT >= 0x0500) + +// New for Windows 2000 and Windows 98 +#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) + BOOL ColorCorrectPalette(HPALETTE hPalette, DWORD dwFirstEntry, DWORD dwNumOfEntries) + { + ATLASSERT(m_hDC != NULL); + return ::ColorCorrectPalette(m_hDC, hPalette, dwFirstEntry, dwNumOfEntries); + } +#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) +}; + +typedef CDCT CDCHandle; +typedef CDCT CDC; + + +/////////////////////////////////////////////////////////////////////////////// +// CDC Helpers + +class CPaintDC : public CDC +{ +public: +// Data members + HWND m_hWnd; + PAINTSTRUCT m_ps; + +// Constructor/destructor + CPaintDC(HWND hWnd) + { + ATLASSERT(::IsWindow(hWnd)); + m_hWnd = hWnd; + m_hDC = ::BeginPaint(hWnd, &m_ps); + } + + ~CPaintDC() + { + ATLASSERT(m_hDC != NULL); + ATLASSERT(::IsWindow(m_hWnd)); + ::EndPaint(m_hWnd, &m_ps); + Detach(); + } +}; + +class CClientDC : public CDC +{ +public: +// Data members + HWND m_hWnd; + +// Constructor/destructor + CClientDC(HWND hWnd) + { + ATLASSERT(hWnd == NULL || ::IsWindow(hWnd)); + m_hWnd = hWnd; + m_hDC = ::GetDC(hWnd); + } + + ~CClientDC() + { + ATLASSERT(m_hDC != NULL); + ::ReleaseDC(m_hWnd, Detach()); + } +}; + +class CWindowDC : public CDC +{ +public: +// Data members + HWND m_hWnd; + +// Constructor/destructor + CWindowDC(HWND hWnd) + { + ATLASSERT(hWnd == NULL || ::IsWindow(hWnd)); + m_hWnd = hWnd; + m_hDC = ::GetWindowDC(hWnd); + } + + ~CWindowDC() + { + ATLASSERT(m_hDC != NULL); + ::ReleaseDC(m_hWnd, Detach()); + } +}; + +class CMemoryDC : public CDC +{ +public: +// Data members + HDC m_hDCOriginal; + RECT m_rcPaint; + CBitmap m_bmp; + HBITMAP m_hBmpOld; + +// Constructor/destructor + CMemoryDC(HDC hDC, RECT& rcPaint) : m_hDCOriginal(hDC), m_hBmpOld(NULL) + { + m_rcPaint = rcPaint; + CreateCompatibleDC(m_hDCOriginal); + ATLASSERT(m_hDC != NULL); + m_bmp.CreateCompatibleBitmap(m_hDCOriginal, m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top); + ATLASSERT(m_bmp.m_hBitmap != NULL); + m_hBmpOld = SelectBitmap(m_bmp); + SetViewportOrg(-m_rcPaint.left, -m_rcPaint.top); + } + + ~CMemoryDC() + { + ::BitBlt(m_hDCOriginal, m_rcPaint.left, m_rcPaint.top, m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top, m_hDC, m_rcPaint.left, m_rcPaint.top, SRCCOPY); + SelectBitmap(m_hBmpOld); + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Enhanced metafile support + +#ifndef _WIN32_WCE + +class CEnhMetaFileInfo +{ +public: +// Data members + HENHMETAFILE m_hEMF; + BYTE* m_pBits; + TCHAR* m_pDesc; + ENHMETAHEADER m_header; + PIXELFORMATDESCRIPTOR m_pfd; + +// Constructor/destructor + CEnhMetaFileInfo(HENHMETAFILE hEMF) : m_pBits(NULL), m_pDesc(NULL), m_hEMF(hEMF) + { } + + ~CEnhMetaFileInfo() + { + delete [] m_pBits; + delete [] m_pDesc; + } + +// Operations + BYTE* GetEnhMetaFileBits() + { + ATLASSERT(m_hEMF != NULL); + UINT nBytes = ::GetEnhMetaFileBits(m_hEMF, 0, NULL); + delete [] m_pBits; + m_pBits = NULL; + ATLTRY(m_pBits = new BYTE[nBytes]); + if (m_pBits != NULL) + ::GetEnhMetaFileBits(m_hEMF, nBytes, m_pBits); + return m_pBits; + } + + LPTSTR GetEnhMetaFileDescription() + { + ATLASSERT(m_hEMF != NULL); + UINT nLen = ::GetEnhMetaFileDescription(m_hEMF, 0, NULL); + delete [] m_pDesc; + m_pDesc = NULL; + ATLTRY(m_pDesc = new TCHAR[nLen]); + if (m_pDesc != NULL) + nLen = ::GetEnhMetaFileDescription(m_hEMF, nLen, m_pDesc); + return m_pDesc; + } + + ENHMETAHEADER* GetEnhMetaFileHeader() + { + ATLASSERT(m_hEMF != NULL); + memset(&m_header, 0, sizeof(m_header)); + m_header.iType = EMR_HEADER; + m_header.nSize = sizeof(ENHMETAHEADER); + UINT n = ::GetEnhMetaFileHeader(m_hEMF, sizeof(ENHMETAHEADER), &m_header); + return (n != 0) ? &m_header : NULL; + } + + PIXELFORMATDESCRIPTOR* GetEnhMetaFilePixelFormat() + { + ATLASSERT(m_hEMF != NULL); + memset(&m_pfd, 0, sizeof(m_pfd)); + UINT n = ::GetEnhMetaFilePixelFormat(m_hEMF, sizeof(m_pfd), &m_pfd); + return (n != 0) ? &m_pfd : NULL; + } +}; + + +template +class CEnhMetaFileT +{ +public: +// Data members + HENHMETAFILE m_hEMF; + +// Constructor/destructor + CEnhMetaFileT(HENHMETAFILE hEMF = NULL) : m_hEMF(hEMF) + { + } + + ~CEnhMetaFileT() + { + if(t_bManaged && m_hEMF != NULL) + DeleteObject(); + } + +// Operations + CEnhMetaFileT& operator =(HENHMETAFILE hEMF) + { + Attach(hEMF); + return *this; + } + + void Attach(HENHMETAFILE hEMF) + { + if(t_bManaged && m_hEMF != NULL && m_hEMF != hEMF) + DeleteObject(); + m_hEMF = hEMF; + } + + HENHMETAFILE Detach() + { + HENHMETAFILE hEMF = m_hEMF; + m_hEMF = NULL; + return hEMF; + } + + operator HENHMETAFILE() const { return m_hEMF; } + + bool IsNull() const { return (m_hEMF == NULL); } + + BOOL DeleteObject() + { + ATLASSERT(m_hEMF != NULL); + BOOL bRet = ::DeleteEnhMetaFile(m_hEMF); + m_hEMF = NULL; + return bRet; + } + + UINT GetEnhMetaFileBits(UINT cbBuffer, LPBYTE lpbBuffer) const + { + ATLASSERT(m_hEMF != NULL); + return ::GetEnhMetaFileBits(m_hEMF, cbBuffer, lpbBuffer); + } + + UINT GetEnhMetaFileDescription(UINT cchBuffer, LPTSTR lpszDescription) const + { + ATLASSERT(m_hEMF != NULL); + return ::GetEnhMetaFileDescription(m_hEMF, cchBuffer, lpszDescription); + } + + UINT GetEnhMetaFileHeader(LPENHMETAHEADER lpemh) const + { + ATLASSERT(m_hEMF != NULL); + lpemh->iType = EMR_HEADER; + lpemh->nSize = sizeof(ENHMETAHEADER); + return ::GetEnhMetaFileHeader(m_hEMF, sizeof(ENHMETAHEADER), lpemh); + } + + UINT GetEnhMetaFilePaletteEntries(UINT cEntries, LPPALETTEENTRY lppe) const + { + ATLASSERT(m_hEMF != NULL); + return ::GetEnhMetaFilePaletteEntries(m_hEMF, cEntries, lppe); + } + + UINT GetEnhMetaFilePixelFormat(DWORD cbBuffer, PIXELFORMATDESCRIPTOR* ppfd) const + { + ATLASSERT(m_hEMF != NULL); + return ::GetEnhMetaFilePixelFormat(m_hEMF, cbBuffer, ppfd); + } +}; + +typedef CEnhMetaFileT CEnhMetaFileHandle; +typedef CEnhMetaFileT CEnhMetaFile; + + +class CEnhMetaFileDC : public CDC +{ +public: +// Constructor/destructor + CEnhMetaFileDC() + { + } + + CEnhMetaFileDC(HDC hdc, LPCRECT lpRect) + { + Create(hdc, NULL, lpRect, NULL); + ATLASSERT(m_hDC != NULL); + } + + CEnhMetaFileDC(HDC hdcRef, LPCTSTR lpFilename, LPCRECT lpRect, LPCTSTR lpDescription) + { + Create(hdcRef, lpFilename, lpRect, lpDescription); + ATLASSERT(m_hDC != NULL); + } + + ~CEnhMetaFileDC() + { + HENHMETAFILE hEMF = Close(); + if (hEMF != NULL) + ::DeleteEnhMetaFile(hEMF); + } + +// Operations + void Create(HDC hdcRef, LPCTSTR lpFilename, LPCRECT lpRect, LPCTSTR lpDescription) + { + ATLASSERT(m_hDC == NULL); + m_hDC = ::CreateEnhMetaFile(hdcRef, lpFilename, lpRect, lpDescription); + } + + HENHMETAFILE Close() + { + HENHMETAFILE hEMF = NULL; + if (m_hDC != NULL) + { + hEMF = ::CloseEnhMetaFile(m_hDC); + m_hDC = NULL; + } + return hEMF; + } +}; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// WinCE compatible clipboard CF_DIB format support functions + +#ifndef _WTL_NO_DIB16 + +#define DIBINFO16_BITFIELDS { 31744, 992, 31 } + +// DIBINFO16 - To avoid color table problems in WinCE we only create this type of Dib +struct DIBINFO16 // a BITMAPINFO with 2 additional color bitfields +{ + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[3]; + + DIBINFO16(SIZE size) + { + BITMAPINFOHEADER bmih = { sizeof(BITMAPINFOHEADER), size.cx, size.cy, + 1, 16, BI_BITFIELDS, 2 * size.cx * size.cy , 0, 0, 3 }; + DWORD dw[3] = DIBINFO16_BITFIELDS ; + + bmiHeader = bmih; + memcpy(bmiColors, dw, 3 * sizeof(DWORD)); + } +}; + + +// AtlxxxDibxxx minimal packed DIB implementation and helpers to copy and paste CF_DIB + +inline bool AtlIsDib16(LPBITMAPINFOHEADER pbmih) +{ + return (pbmih->biBitCount == 16) && (pbmih->biCompression == BI_BITFIELDS); +} + +inline int AtlGetDibColorTableSize(LPBITMAPINFOHEADER pbmih) +{ + switch (pbmih->biBitCount) + { + case 2: + case 4: + case 8: + return pbmih->biClrUsed ? pbmih->biClrUsed : 1 << pbmih->biBitCount; + case 24: + break; + case 16: + case 32: + return pbmih->biCompression == BI_BITFIELDS ? 3 : 0; + default: + ATLASSERT(FALSE); // should never come here + } + + return 0; +} + +inline int AtlGetDibNumColors(LPBITMAPINFOHEADER pbmih) +{ + switch (pbmih->biBitCount) + { + case 2: + case 4: + case 8: + if (pbmih->biClrUsed) + return pbmih->biClrUsed; + else + break; + case 16: + if (pbmih->biCompression == BI_BITFIELDS ) + return 1 << 15; + else + break; + case 24: + break; + case 32: + if (pbmih->biCompression == BI_BITFIELDS ) + return 1 << 24; + else + break; + default: + ATLASSERT(FALSE); + } + + return 1 << pbmih->biBitCount; +} + +inline HBITMAP AtlGetDibBitmap(LPBITMAPINFO pbmi) +{ + HBITMAP hbm = NULL; + CDC dc(NULL); + void * pBits = NULL; + + LPBYTE pDibBits = (LPBYTE)pbmi + sizeof(BITMAPINFOHEADER) + AtlGetDibColorTableSize(&pbmi->bmiHeader) * sizeof(RGBQUAD); + if (hbm = CreateDIBSection(dc, pbmi, DIB_RGB_COLORS, &pBits, NULL, NULL)) + memcpy(pBits, pDibBits, pbmi->bmiHeader.biSizeImage); + + return hbm; +} + +inline HBITMAP AtlCopyBitmap(HBITMAP hbm , SIZE sizeDst, bool bAsBitmap = false) +{ + CDC hdcSrc = CreateCompatibleDC(NULL); + CDC hdcDst = CreateCompatibleDC(NULL); + + CBitmapHandle hbmOld = NULL, hbmOld2 = NULL, bmSrc = hbm; + + CBitmap bmNew = NULL; + + SIZE sizeSrc = { 0 }; + bmSrc.GetSize(sizeSrc); + + hbmOld = hdcSrc.SelectBitmap(bmSrc); + + if (bAsBitmap) + { + bmNew.CreateCompatibleBitmap(hdcSrc, sizeDst.cx, sizeDst.cy); + } + else + { + DIBINFO16 dib16(sizeDst); + LPVOID pBits = NULL; + bmNew = CreateDIBSection(hdcDst, (const BITMAPINFO*)&dib16, DIB_RGB_COLORS, &pBits, NULL, NULL); + } + + ATLASSERT(!bmNew.IsNull()); + + hbmOld2 = hdcDst.SelectBitmap(bmNew); + BOOL bOK = FALSE; + + if ((sizeDst.cx == sizeSrc.cx) && (sizeDst.cy == sizeSrc.cy)) + bOK = hdcDst.BitBlt(0, 0, sizeDst.cx, sizeDst.cy, hdcSrc, 0, 0, SRCCOPY); + else + bOK = hdcDst.StretchBlt(0, 0, sizeDst.cx, sizeDst.cy, hdcSrc, 0, 0, sizeSrc.cx, sizeSrc.cy, SRCCOPY); + + hdcSrc.SelectBitmap(hbmOld); + hdcDst.SelectBitmap(hbmOld2); + + if (bOK == FALSE) + bmNew.DeleteObject(); + + return bmNew.Detach(); +} + +inline HLOCAL AtlCreatePackedDib16(HBITMAP hbm, SIZE size) +{ + DIBSECTION ds = { 0 }; + LPBYTE pDib = NULL; + bool bCopied = false; + + bool bOK = GetObject(hbm, sizeof(ds), &ds) == sizeof(ds); + if ((bOK == FALSE) || (ds.dsBm.bmBits == NULL) || (AtlIsDib16(&ds.dsBmih) == FALSE) || + (ds.dsBmih.biWidth != size.cx ) || (ds.dsBmih.biHeight != size.cy )) + { + if ((hbm = AtlCopyBitmap(hbm, size)) != NULL) + { + bCopied = true; + bOK = GetObject(hbm, sizeof(ds), &ds) == sizeof(ds); + } + else + { + bOK = FALSE; + } + } + + if((bOK == TRUE) && (AtlIsDib16(&ds.dsBmih) == TRUE) && (ds.dsBm.bmBits != NULL)) + { + pDib = (LPBYTE)LocalAlloc(LMEM_ZEROINIT, sizeof(DIBINFO16) + ds.dsBmih.biSizeImage); + if (pDib != NULL) + { + memcpy(pDib , &ds.dsBmih, sizeof(DIBINFO16)); + memcpy(pDib + sizeof(DIBINFO16), ds.dsBm.bmBits, ds.dsBmih.biSizeImage); + } + } + + if (bCopied == true) + DeleteObject(hbm); + + return (HLOCAL)pDib; +} + +inline bool AtlSetClipboardDib16(HBITMAP hbm, SIZE size, HWND hWnd) +{ + ATLASSERT(::IsWindow(hWnd)); + BOOL bOK = OpenClipboard(hWnd); + if (bOK == TRUE) + { + if ((bOK = EmptyClipboard()) == TRUE) + { + HLOCAL hDib = AtlCreatePackedDib16(hbm, size); + if (hDib != NULL) + { + bOK = SetClipboardData(CF_DIB, hDib) != NULL; + if (bOK == FALSE) + LocalFree(hDib); + } + else + { + bOK = FALSE; + } + } + CloseClipboard(); + } + + return bOK == TRUE; +} + +inline HBITMAP AtlGetClipboardDib(HWND hWnd) +{ + ATLASSERT(::IsWindow(hWnd) == TRUE); + HBITMAP hbm = NULL; + if (OpenClipboard(hWnd) == TRUE) + { + LPBITMAPINFO pbmi = (LPBITMAPINFO)GetClipboardData(CF_DIB); + if (pbmi != NULL) + hbm = AtlGetDibBitmap(pbmi); + CloseClipboard(); + } + + return hbm; +} + +#endif // _WTL_NO_DIB16 + +}; // namespace WTL + +#endif // __ATLGDI_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlmisc.h b/Client/Client/GUI/BKWin/wtl/atlmisc.h new file mode 100644 index 00000000..2009dd44 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlmisc.h @@ -0,0 +1,4018 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLMISC_H__ +#define __ATLMISC_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifndef __ATLAPP_H__ + #error atlmisc.h requires atlapp.h to be included first +#endif + + +#ifdef _ATL_TMP_NO_CSTRING + #define _WTL_NO_CSTRING +#endif + +#if defined(_WTL_USE_CSTRING) && defined(_WTL_NO_CSTRING) + #error Conflicting options - both _WTL_USE_CSTRING and _WTL_NO_CSTRING are defined +#endif // defined(_WTL_USE_CSTRING) && defined(_WTL_NO_CSTRING) + +#if !defined(_WTL_USE_CSTRING) && !defined(_WTL_NO_CSTRING) + #define _WTL_USE_CSTRING +#endif // !defined(_WTL_USE_CSTRING) && !defined(_WTL_NO_CSTRING) + +#ifndef _WTL_NO_CSTRING + #if defined(_ATL_USE_CSTRING_FLOAT) && defined(_ATL_MIN_CRT) + #error Cannot use CString floating point formatting with _ATL_MIN_CRT defined + #endif // defined(_ATL_USE_CSTRING_FLOAT) && defined(_ATL_MIN_CRT) +#endif // !_WTL_NO_CSTRING + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CSize +// CPoint +// CRect +// CString +// +// CRecentDocumentListBase +// CRecentDocumentList +// CFindFile +// +// Global functions: +// AtlLoadAccelerators() +// AtlLoadMenu() +// AtlLoadBitmap() +// AtlLoadSysBitmap() +// AtlLoadCursor() +// AtlLoadSysCursor() +// AtlLoadIcon() +// AtlLoadSysIcon() +// AtlLoadBitmapImage() +// AtlLoadCursorImage() +// AtlLoadIconImage() +// AtlLoadSysBitmapImage() +// AtlLoadSysCursorImage() +// AtlLoadSysIconImage() +// AtlLoadString() +// +// AtlGetStockPen() +// AtlGetStockBrush() +// AtlGetStockFont() +// AtlGetStockPalette() +// +// AtlCompactPath() + + +namespace WTL +{ + +#ifndef _WTL_NO_WTYPES + +// forward declarations +class CSize; +class CPoint; +class CRect; + +/////////////////////////////////////////////////////////////////////////////// +// CSize - Wrapper for Windows SIZE structure. + +class CSize : public SIZE +{ +public: +// Constructors + CSize() + { + cx = 0; + cy = 0; + } + + CSize(int initCX, int initCY) + { + cx = initCX; + cy = initCY; + } + + CSize(SIZE initSize) + { + *(SIZE*)this = initSize; + } + + CSize(POINT initPt) + { + *(POINT*)this = initPt; + } + + CSize(DWORD dwSize) + { + cx = (short)LOWORD(dwSize); + cy = (short)HIWORD(dwSize); + } + +// Operations + BOOL operator ==(SIZE size) const + { + return (cx == size.cx && cy == size.cy); + } + + BOOL operator !=(SIZE size) const + { + return (cx != size.cx || cy != size.cy); + } + + void operator +=(SIZE size) + { + cx += size.cx; + cy += size.cy; + } + + void operator -=(SIZE size) + { + cx -= size.cx; + cy -= size.cy; + } + + void SetSize(int CX, int CY) + { + cx = CX; + cy = CY; + } + +// Operators returning CSize values + CSize operator +(SIZE size) const + { + return CSize(cx + size.cx, cy + size.cy); + } + + CSize operator -(SIZE size) const + { + return CSize(cx - size.cx, cy - size.cy); + } + + CSize operator -() const + { + return CSize(-cx, -cy); + } + +// Operators returning CPoint values + CPoint operator +(POINT point) const; + CPoint operator -(POINT point) const; + +// Operators returning CRect values + CRect operator +(const RECT* lpRect) const; + CRect operator -(const RECT* lpRect) const; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CPoint - Wrapper for Windows POINT structure. + +class CPoint : public POINT +{ +public: +// Constructors + CPoint() + { + x = 0; + y = 0; + } + + CPoint(int initX, int initY) + { + x = initX; + y = initY; + } + + CPoint(POINT initPt) + { + *(POINT*)this = initPt; + } + + CPoint(SIZE initSize) + { + *(SIZE*)this = initSize; + } + + CPoint(DWORD dwPoint) + { + x = (short)LOWORD(dwPoint); + y = (short)HIWORD(dwPoint); + } + +// Operations + void Offset(int xOffset, int yOffset) + { + x += xOffset; + y += yOffset; + } + + void Offset(POINT point) + { + x += point.x; + y += point.y; + } + + void Offset(SIZE size) + { + x += size.cx; + y += size.cy; + } + + BOOL operator ==(POINT point) const + { + return (x == point.x && y == point.y); + } + + BOOL operator !=(POINT point) const + { + return (x != point.x || y != point.y); + } + + void operator +=(SIZE size) + { + x += size.cx; + y += size.cy; + } + + void operator -=(SIZE size) + { + x -= size.cx; + y -= size.cy; + } + + void operator +=(POINT point) + { + x += point.x; + y += point.y; + } + + void operator -=(POINT point) + { + x -= point.x; + y -= point.y; + } + + void SetPoint(int X, int Y) + { + x = X; + y = Y; + } + +// Operators returning CPoint values + CPoint operator +(SIZE size) const + { + return CPoint(x + size.cx, y + size.cy); + } + + CPoint operator -(SIZE size) const + { + return CPoint(x - size.cx, y - size.cy); + } + + CPoint operator -() const + { + return CPoint(-x, -y); + } + + CPoint operator +(POINT point) const + { + return CPoint(x + point.x, y + point.y); + } + +// Operators returning CSize values + CSize operator -(POINT point) const + { + return CSize(x - point.x, y - point.y); + } + +// Operators returning CRect values + CRect operator +(const RECT* lpRect) const; + CRect operator -(const RECT* lpRect) const; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CRect - Wrapper for Windows RECT structure. + +class CRect : public RECT +{ +public: +// Constructors + CRect() + { + left = 0; + top = 0; + right = 0; + bottom = 0; + } + + CRect(int l, int t, int r, int b) + { + left = l; + top = t; + right = r; + bottom = b; + } + + CRect(const RECT& srcRect) + { + ::CopyRect(this, &srcRect); + } + + CRect(LPCRECT lpSrcRect) + { + ::CopyRect(this, lpSrcRect); + } + + CRect(POINT point, SIZE size) + { + right = (left = point.x) + size.cx; + bottom = (top = point.y) + size.cy; + } + + CRect(POINT topLeft, POINT bottomRight) + { + left = topLeft.x; + top = topLeft.y; + right = bottomRight.x; + bottom = bottomRight.y; + } + +// Attributes (in addition to RECT members) + int Width() const + { + return right - left; + } + + int Height() const + { + return bottom - top; + } + + CSize Size() const + { + return CSize(right - left, bottom - top); + } + + CPoint& TopLeft() + { + return *((CPoint*)this); + } + + CPoint& BottomRight() + { + return *((CPoint*)this + 1); + } + + const CPoint& TopLeft() const + { + return *((CPoint*)this); + } + + const CPoint& BottomRight() const + { + return *((CPoint*)this + 1); + } + + CPoint CenterPoint() const + { + return CPoint((left + right) / 2, (top + bottom) / 2); + } + + // convert between CRect and LPRECT/LPCRECT (no need for &) + operator LPRECT() + { + return this; + } + + operator LPCRECT() const + { + return this; + } + + BOOL IsRectEmpty() const + { + return ::IsRectEmpty(this); + } + + BOOL IsRectNull() const + { + return (left == 0 && right == 0 && top == 0 && bottom == 0); + } + + BOOL PtInRect(POINT point) const + { + return ::PtInRect(this, point); + } + +// Operations + void SetRect(int x1, int y1, int x2, int y2) + { + ::SetRect(this, x1, y1, x2, y2); + } + + void SetRect(POINT topLeft, POINT bottomRight) + { + ::SetRect(this, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y); + } + + void SetRectEmpty() + { + ::SetRectEmpty(this); + } + + void CopyRect(LPCRECT lpSrcRect) + { + ::CopyRect(this, lpSrcRect); + } + + BOOL EqualRect(LPCRECT lpRect) const + { + return ::EqualRect(this, lpRect); + } + + void InflateRect(int x, int y) + { + ::InflateRect(this, x, y); + } + + void InflateRect(SIZE size) + { + ::InflateRect(this, size.cx, size.cy); + } + + void InflateRect(LPCRECT lpRect) + { + left -= lpRect->left; + top -= lpRect->top; + right += lpRect->right; + bottom += lpRect->bottom; + } + + void InflateRect(int l, int t, int r, int b) + { + left -= l; + top -= t; + right += r; + bottom += b; + } + + void DeflateRect(int x, int y) + { + ::InflateRect(this, -x, -y); + } + + void DeflateRect(SIZE size) + { + ::InflateRect(this, -size.cx, -size.cy); + } + + void DeflateRect(LPCRECT lpRect) + { + left += lpRect->left; + top += lpRect->top; + right -= lpRect->right; + bottom -= lpRect->bottom; + } + + void DeflateRect(int l, int t, int r, int b) + { + left += l; + top += t; + right -= r; + bottom -= b; + } + + void OffsetRect(int x, int y) + { + ::OffsetRect(this, x, y); + } + void OffsetRect(SIZE size) + { + ::OffsetRect(this, size.cx, size.cy); + } + + void OffsetRect(POINT point) + { + ::OffsetRect(this, point.x, point.y); + } + + void NormalizeRect() + { + int nTemp; + if (left > right) + { + nTemp = left; + left = right; + right = nTemp; + } + if (top > bottom) + { + nTemp = top; + top = bottom; + bottom = nTemp; + } + } + + // absolute position of rectangle + void MoveToY(int y) + { + bottom = Height() + y; + top = y; + } + + void MoveToX(int x) + { + right = Width() + x; + left = x; + } + + void MoveToXY(int x, int y) + { + MoveToX(x); + MoveToY(y); + } + + void MoveToXY(POINT pt) + { + MoveToX(pt.x); + MoveToY(pt.y); + } + + // operations that fill '*this' with result + BOOL IntersectRect(LPCRECT lpRect1, LPCRECT lpRect2) + { + return ::IntersectRect(this, lpRect1, lpRect2); + } + + BOOL UnionRect(LPCRECT lpRect1, LPCRECT lpRect2) + { + return ::UnionRect(this, lpRect1, lpRect2); + } + + BOOL SubtractRect(LPCRECT lpRectSrc1, LPCRECT lpRectSrc2) + { + return ::SubtractRect(this, lpRectSrc1, lpRectSrc2); + } + +// Additional Operations + void operator =(const RECT& srcRect) + { + ::CopyRect(this, &srcRect); + } + + BOOL operator ==(const RECT& rect) const + { + return ::EqualRect(this, &rect); + } + + BOOL operator !=(const RECT& rect) const + { + return !::EqualRect(this, &rect); + } + + void operator +=(POINT point) + { + ::OffsetRect(this, point.x, point.y); + } + + void operator +=(SIZE size) + { + ::OffsetRect(this, size.cx, size.cy); + } + + void operator +=(LPCRECT lpRect) + { + InflateRect(lpRect); + } + + void operator -=(POINT point) + { + ::OffsetRect(this, -point.x, -point.y); + } + + void operator -=(SIZE size) + { + ::OffsetRect(this, -size.cx, -size.cy); + } + + void operator -=(LPCRECT lpRect) + { + DeflateRect(lpRect); + } + + void operator &=(const RECT& rect) + { + ::IntersectRect(this, this, &rect); + } + + void operator |=(const RECT& rect) + { + ::UnionRect(this, this, &rect); + } + +// Operators returning CRect values + CRect operator +(POINT pt) const + { + CRect rect(*this); + ::OffsetRect(&rect, pt.x, pt.y); + return rect; + } + + CRect operator -(POINT pt) const + { + CRect rect(*this); + ::OffsetRect(&rect, -pt.x, -pt.y); + return rect; + } + + CRect operator +(LPCRECT lpRect) const + { + CRect rect(this); + rect.InflateRect(lpRect); + return rect; + } + + CRect operator +(SIZE size) const + { + CRect rect(*this); + ::OffsetRect(&rect, size.cx, size.cy); + return rect; + } + + CRect operator -(SIZE size) const + { + CRect rect(*this); + ::OffsetRect(&rect, -size.cx, -size.cy); + return rect; + } + + CRect operator -(LPCRECT lpRect) const + { + CRect rect(this); + rect.DeflateRect(lpRect); + return rect; + } + + CRect operator &(const RECT& rect2) const + { + CRect rect; + ::IntersectRect(&rect, this, &rect2); + return rect; + } + + CRect operator |(const RECT& rect2) const + { + CRect rect; + ::UnionRect(&rect, this, &rect2); + return rect; + } + + CRect MulDiv(int nMultiplier, int nDivisor) const + { + return CRect( + ::MulDiv(left, nMultiplier, nDivisor), + ::MulDiv(top, nMultiplier, nDivisor), + ::MulDiv(right, nMultiplier, nDivisor), + ::MulDiv(bottom, nMultiplier, nDivisor)); + } +}; + + +// CSize implementation + +inline CPoint CSize::operator +(POINT point) const +{ return CPoint(cx + point.x, cy + point.y); } + +inline CPoint CSize::operator -(POINT point) const +{ return CPoint(cx - point.x, cy - point.y); } + +inline CRect CSize::operator +(const RECT* lpRect) const +{ return CRect(lpRect) + *this; } + +inline CRect CSize::operator -(const RECT* lpRect) const +{ return CRect(lpRect) - *this; } + + +// CPoint implementation + +inline CRect CPoint::operator +(const RECT* lpRect) const +{ return CRect(lpRect) + *this; } + +inline CRect CPoint::operator -(const RECT* lpRect) const +{ return CRect(lpRect) - *this; } + +#endif // !_WTL_NO_WTYPES + + +// WTL::CSize or ATL::CSize scalar operators + +#if !defined(_WTL_NO_SIZE_SCALAR) && (!defined(_WTL_NO_WTYPES) || defined(__ATLTYPES_H__)) + +template +inline CSize operator *(SIZE s, Num n) +{ + return CSize((int)(s.cx * n), (int)(s.cy * n)); +}; + +template +inline void operator *=(SIZE & s, Num n) +{ + s = s * n; +}; + +template +inline CSize operator /(SIZE s, Num n) +{ + return CSize((int)(s.cx / n), (int)(s.cy / n)); +}; + +template +inline void operator /=(SIZE & s, Num n) +{ + s = s / n; +}; + +#endif // !defined(_WTL_NO_SIZE_SCALAR) && (!defined(_WTL_NO_WTYPES) || defined(__ATLTYPES_H__)) + + +/////////////////////////////////////////////////////////////////////////////// +// CString - String class + +#ifndef _WTL_NO_CSTRING + +struct CStringData +{ + long nRefs; // reference count + int nDataLength; + int nAllocLength; + // TCHAR data[nAllocLength] + + TCHAR* data() + { return (TCHAR*)(this + 1); } +}; + +// Globals + +// For an empty string, m_pchData will point here +// (note: avoids special case of checking for NULL m_pchData) +// empty string data (and locked) +_declspec(selectany) int rgInitData[] = { -1, 0, 0, 0 }; +_declspec(selectany) CStringData* _atltmpDataNil = (CStringData*)&rgInitData; +_declspec(selectany) LPCTSTR _atltmpPchNil = (LPCTSTR)(((BYTE*)&rgInitData) + sizeof(CStringData)); + + +class CString +{ +public: +// Constructors + CString() + { + Init(); + } + + CString(const CString& stringSrc) + { + ATLASSERT(stringSrc.GetData()->nRefs != 0); + if (stringSrc.GetData()->nRefs >= 0) + { + ATLASSERT(stringSrc.GetData() != _atltmpDataNil); + m_pchData = stringSrc.m_pchData; + InterlockedIncrement(&GetData()->nRefs); + } + else + { + Init(); + *this = stringSrc.m_pchData; + } + } + + CString(TCHAR ch, int nRepeat = 1) + { + ATLASSERT(!_istlead(ch)); // can't create a lead byte string + Init(); + if (nRepeat >= 1) + { + if(AllocBuffer(nRepeat)) + { +#ifdef _UNICODE + for (int i = 0; i < nRepeat; i++) + m_pchData[i] = ch; +#else + memset(m_pchData, ch, nRepeat); +#endif + } + } + } + + CString(LPCTSTR lpsz) + { + Init(); + if (lpsz != NULL && HIWORD(lpsz) == NULL) + { + UINT nID = LOWORD((DWORD_PTR)lpsz); + if (!LoadString(nID)) + ATLTRACE2(atlTraceUI, 0, _T("Warning: implicit LoadString(%u) in CString failed\n"), nID); + } + else + { + int nLen = SafeStrlen(lpsz); + if (nLen != 0) + { + if(AllocBuffer(nLen)) + SecureHelper::memcpy_x(m_pchData, (nLen + 1) * sizeof(TCHAR), lpsz, nLen * sizeof(TCHAR)); + } + } + } + +#ifdef _UNICODE + CString(LPCSTR lpsz) + { + Init(); +#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800) + int nSrcLen = (lpsz != NULL) ? ATL::lstrlenA(lpsz) : 0; +#else + int nSrcLen = (lpsz != NULL) ? lstrlenA(lpsz) : 0; +#endif + if (nSrcLen != 0) + { + if(AllocBuffer(nSrcLen)) + { + _mbstowcsz(m_pchData, lpsz, nSrcLen + 1); + ReleaseBuffer(); + } + } + } +#else // !_UNICODE + CString(LPCWSTR lpsz) + { + Init(); + int nSrcLen = (lpsz != NULL) ? (int)wcslen(lpsz) : 0; + if (nSrcLen != 0) + { + if(AllocBuffer(nSrcLen * 2)) + { + _wcstombsz(m_pchData, lpsz, (nSrcLen * 2) + 1); + ReleaseBuffer(); + } + } + } +#endif // !_UNICODE + + CString(LPCTSTR lpch, int nLength) + { + Init(); + if (nLength != 0) + { + if(AllocBuffer(nLength)) + SecureHelper::memcpy_x(m_pchData, (nLength + 1) * sizeof(TCHAR), lpch, nLength * sizeof(TCHAR)); + } + } + +#ifdef _UNICODE + CString(LPCSTR lpsz, int nLength) + { + Init(); + if (nLength != 0) + { + if(AllocBuffer(nLength)) + { + int n = ::MultiByteToWideChar(CP_ACP, 0, lpsz, nLength, m_pchData, nLength + 1); + ReleaseBuffer((n >= 0) ? n : -1); + } + } + } +#else // !_UNICODE + CString(LPCWSTR lpsz, int nLength) + { + Init(); + if (nLength != 0) + { + if(((nLength * 2) > nLength) && AllocBuffer(nLength * 2)) + { + int n = ::WideCharToMultiByte(CP_ACP, 0, lpsz, nLength, m_pchData, (nLength * 2) + 1, NULL, NULL); + ReleaseBuffer((n >= 0) ? n : -1); + } + } + } +#endif // !_UNICODE + + CString(const unsigned char* lpsz) + { + Init(); + *this = (LPCSTR)lpsz; + } + +// Attributes & Operations + int GetLength() const // as an array of characters + { + return GetData()->nDataLength; + } + + BOOL IsEmpty() const + { + return GetData()->nDataLength == 0; + } + + void Empty() // free up the data + { + if (GetData()->nDataLength == 0) + return; + + if (GetData()->nRefs >= 0) + Release(); + else + *this = _T(""); + + ATLASSERT(GetData()->nDataLength == 0); + ATLASSERT(GetData()->nRefs < 0 || GetData()->nAllocLength == 0); + } + + TCHAR GetAt(int nIndex) const // 0 based + { + ATLASSERT(nIndex >= 0); + ATLASSERT(nIndex < GetData()->nDataLength); + return m_pchData[nIndex]; + } + + TCHAR operator [](int nIndex) const // same as GetAt + { + // same as GetAt + ATLASSERT(nIndex >= 0); + ATLASSERT(nIndex < GetData()->nDataLength); + return m_pchData[nIndex]; + } + + void SetAt(int nIndex, TCHAR ch) + { + ATLASSERT(nIndex >= 0); + ATLASSERT(nIndex < GetData()->nDataLength); + + CopyBeforeWrite(); + m_pchData[nIndex] = ch; + } + + operator LPCTSTR() const // as a C string + { + return m_pchData; + } + + // overloaded assignment + CString& operator =(const CString& stringSrc) + { + if (m_pchData != stringSrc.m_pchData) + { + if ((GetData()->nRefs < 0 && GetData() != _atltmpDataNil) || stringSrc.GetData()->nRefs < 0) + { + // actual copy necessary since one of the strings is locked + AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData); + } + else + { + // can just copy references around + Release(); + ATLASSERT(stringSrc.GetData() != _atltmpDataNil); + m_pchData = stringSrc.m_pchData; + InterlockedIncrement(&GetData()->nRefs); + } + } + return *this; + } + + CString& operator =(TCHAR ch) + { + ATLASSERT(!_istlead(ch)); // can't set single lead byte + AssignCopy(1, &ch); + return *this; + } + +#ifdef _UNICODE + CString& operator =(char ch) + { + *this = (TCHAR)ch; + return *this; + } +#endif + + CString& operator =(LPCTSTR lpsz) + { + ATLASSERT(lpsz == NULL || _IsValidString(lpsz)); + AssignCopy(SafeStrlen(lpsz), lpsz); + return *this; + } + +#ifdef _UNICODE + CString& operator =(LPCSTR lpsz) + { +#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800) + int nSrcLen = (lpsz != NULL) ? ATL::lstrlenA(lpsz) : 0; +#else + int nSrcLen = (lpsz != NULL) ? lstrlenA(lpsz) : 0; +#endif + if(AllocBeforeWrite(nSrcLen)) + { + _mbstowcsz(m_pchData, lpsz, nSrcLen + 1); + ReleaseBuffer(); + } + return *this; + } +#else // !_UNICODE + CString& operator =(LPCWSTR lpsz) + { + int nSrcLen = (lpsz != NULL) ? (int)wcslen(lpsz) : 0; + if(AllocBeforeWrite(nSrcLen * 2)) + { + _wcstombsz(m_pchData, lpsz, (nSrcLen * 2) + 1); + ReleaseBuffer(); + } + return *this; + } +#endif // !_UNICODE + + CString& operator =(const unsigned char* lpsz) + { + *this = (LPCSTR)lpsz; + return *this; + } + + // string concatenation + CString& operator +=(const CString& string) + { + ConcatInPlace(string.GetData()->nDataLength, string.m_pchData); + return *this; + } + + CString& operator +=(TCHAR ch) + { + ConcatInPlace(1, &ch); + return *this; + } + +#ifdef _UNICODE + CString& operator +=(char ch) + { + *this += (TCHAR)ch; + return *this; + } +#endif + + CString& operator +=(LPCTSTR lpsz) + { + ATLASSERT(lpsz == NULL || _IsValidString(lpsz)); + ConcatInPlace(SafeStrlen(lpsz), lpsz); + return *this; + } + + friend CString __stdcall operator +(const CString& string1, const CString& string2); + friend CString __stdcall operator +(const CString& string, TCHAR ch); + friend CString __stdcall operator +(TCHAR ch, const CString& string); +#ifdef _UNICODE + friend CString __stdcall operator +(const CString& string, char ch); + friend CString __stdcall operator +(char ch, const CString& string); +#endif + friend CString __stdcall operator +(const CString& string, LPCTSTR lpsz); + friend CString __stdcall operator +(LPCTSTR lpsz, const CString& string); + + // string comparison + int Compare(LPCTSTR lpsz) const // straight character (MBCS/Unicode aware) + { + return _cstrcmp(m_pchData, lpsz); + } + + int CompareNoCase(LPCTSTR lpsz) const // ignore case (MBCS/Unicode aware) + { + return _cstrcmpi(m_pchData, lpsz); + } + +#ifndef _WIN32_WCE + // CString::Collate is often slower than Compare but is MBSC/Unicode + // aware as well as locale-sensitive with respect to sort order. + int Collate(LPCTSTR lpsz) const // NLS aware + { + return _cstrcoll(m_pchData, lpsz); + } + + int CollateNoCase(LPCTSTR lpsz) const // ignore case + { + return _cstrcolli(m_pchData, lpsz); + } +#endif // !_WIN32_WCE + + // simple sub-string extraction + CString Mid(int nFirst, int nCount) const + { + // out-of-bounds requests return sensible things + if (nFirst < 0) + nFirst = 0; + if (nCount < 0) + nCount = 0; + + if (nFirst + nCount > GetData()->nDataLength) + nCount = GetData()->nDataLength - nFirst; + if (nFirst > GetData()->nDataLength) + nCount = 0; + + CString dest; + AllocCopy(dest, nCount, nFirst, 0); + return dest; + } + + CString Mid(int nFirst) const + { + return Mid(nFirst, GetData()->nDataLength - nFirst); + } + + CString Left(int nCount) const + { + if (nCount < 0) + nCount = 0; + else if (nCount > GetData()->nDataLength) + nCount = GetData()->nDataLength; + + CString dest; + AllocCopy(dest, nCount, 0, 0); + return dest; + } + + CString Right(int nCount) const + { + if (nCount < 0) + nCount = 0; + else if (nCount > GetData()->nDataLength) + nCount = GetData()->nDataLength; + + CString dest; + AllocCopy(dest, nCount, GetData()->nDataLength-nCount, 0); + return dest; + } + + CString SpanIncluding(LPCTSTR lpszCharSet) const // strspn equivalent + { + ATLASSERT(_IsValidString(lpszCharSet)); + return Left(_cstrspn(m_pchData, lpszCharSet)); + } + + CString SpanExcluding(LPCTSTR lpszCharSet) const // strcspn equivalent + { + ATLASSERT(_IsValidString(lpszCharSet)); + return Left(_cstrcspn(m_pchData, lpszCharSet)); + } + + // upper/lower/reverse conversion + void MakeUpper() + { + CopyBeforeWrite(); + CharUpper(m_pchData); + } + + void MakeLower() + { + CopyBeforeWrite(); + CharLower(m_pchData); + } + + void MakeReverse() + { + CopyBeforeWrite(); + _cstrrev(m_pchData); + } + + // trimming whitespace (either side) + void TrimRight() + { + CopyBeforeWrite(); + + // find beginning of trailing spaces by starting at beginning (DBCS aware) + LPTSTR lpsz = m_pchData; + LPTSTR lpszLast = NULL; + while (*lpsz != _T('\0')) + { + if (_cstrisspace(*lpsz)) + { + if (lpszLast == NULL) + lpszLast = lpsz; + } + else + { + lpszLast = NULL; + } + lpsz = ::CharNext(lpsz); + } + + if (lpszLast != NULL) + { + // truncate at trailing space start + *lpszLast = _T('\0'); + GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData); + } + } + + void TrimLeft() + { + CopyBeforeWrite(); + + // find first non-space character + LPCTSTR lpsz = m_pchData; + while (_cstrisspace(*lpsz)) + lpsz = ::CharNext(lpsz); + + // fix up data and length + int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData); + SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR)); + GetData()->nDataLength = nDataLength; + } + + // remove continuous occurrences of chTarget starting from right + void TrimRight(TCHAR chTarget) + { + // find beginning of trailing matches + // by starting at beginning (DBCS aware) + + CopyBeforeWrite(); + LPTSTR lpsz = m_pchData; + LPTSTR lpszLast = NULL; + + while (*lpsz != _T('\0')) + { + if (*lpsz == chTarget) + { + if (lpszLast == NULL) + lpszLast = lpsz; + } + else + lpszLast = NULL; + lpsz = ::CharNext(lpsz); + } + + if (lpszLast != NULL) + { + // truncate at left-most matching character + *lpszLast = _T('\0'); + GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData); + } + } + + // remove continuous occcurrences of characters in passed string, starting from right + void TrimRight(LPCTSTR lpszTargetList) + { + // find beginning of trailing matches by starting at beginning (DBCS aware) + + CopyBeforeWrite(); + LPTSTR lpsz = m_pchData; + LPTSTR lpszLast = NULL; + + while (*lpsz != _T('\0')) + { + TCHAR* pNext = ::CharNext(lpsz); + if(pNext > lpsz + 1) + { + if (_cstrchr_db(lpszTargetList, *lpsz, *(lpsz + 1)) != NULL) + { + if (lpszLast == NULL) + lpszLast = lpsz; + } + else + { + lpszLast = NULL; + } + } + else + { + if (_cstrchr(lpszTargetList, *lpsz) != NULL) + { + if (lpszLast == NULL) + lpszLast = lpsz; + } + else + { + lpszLast = NULL; + } + } + + lpsz = pNext; + } + + if (lpszLast != NULL) + { + // truncate at left-most matching character + *lpszLast = _T('\0'); + GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData); + } + } + + // remove continuous occurrences of chTarget starting from left + void TrimLeft(TCHAR chTarget) + { + // find first non-matching character + + CopyBeforeWrite(); + LPCTSTR lpsz = m_pchData; + + while (chTarget == *lpsz) + lpsz = ::CharNext(lpsz); + + if (lpsz != m_pchData) + { + // fix up data and length + int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData); + SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR)); + GetData()->nDataLength = nDataLength; + } + } + + // remove continuous occcurrences of characters in passed string, starting from left + void TrimLeft(LPCTSTR lpszTargets) + { + // if we're not trimming anything, we're not doing any work + if (SafeStrlen(lpszTargets) == 0) + return; + + CopyBeforeWrite(); + LPCTSTR lpsz = m_pchData; + + while (*lpsz != _T('\0')) + { + TCHAR* pNext = ::CharNext(lpsz); + if(pNext > lpsz + 1) + { + if (_cstrchr_db(lpszTargets, *lpsz, *(lpsz + 1)) == NULL) + break; + } + else + { + if (_cstrchr(lpszTargets, *lpsz) == NULL) + break; + } + lpsz = pNext; + } + + if (lpsz != m_pchData) + { + // fix up data and length + int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData); + SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR)); + GetData()->nDataLength = nDataLength; + } + } + + // advanced manipulation + // replace occurrences of chOld with chNew + int Replace(TCHAR chOld, TCHAR chNew) + { + int nCount = 0; + + // short-circuit the nop case + if (chOld != chNew) + { + // otherwise modify each character that matches in the string + CopyBeforeWrite(); + LPTSTR psz = m_pchData; + LPTSTR pszEnd = psz + GetData()->nDataLength; + while (psz < pszEnd) + { + // replace instances of the specified character only + if (*psz == chOld) + { + *psz = chNew; + nCount++; + } + psz = ::CharNext(psz); + } + } + return nCount; + } + + // replace occurrences of substring lpszOld with lpszNew; + // empty lpszNew removes instances of lpszOld + int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew) + { + // can't have empty or NULL lpszOld + + int nSourceLen = SafeStrlen(lpszOld); + if (nSourceLen == 0) + return 0; + int nReplacementLen = SafeStrlen(lpszNew); + + // loop once to figure out the size of the result string + int nCount = 0; + LPTSTR lpszStart = m_pchData; + LPTSTR lpszEnd = m_pchData + GetData()->nDataLength; + LPTSTR lpszTarget = NULL; + while (lpszStart < lpszEnd) + { + while ((lpszTarget = (TCHAR*)_cstrstr(lpszStart, lpszOld)) != NULL) + { + nCount++; + lpszStart = lpszTarget + nSourceLen; + } + lpszStart += lstrlen(lpszStart) + 1; + } + + // if any changes were made, make them + if (nCount > 0) + { + CopyBeforeWrite(); + + // if the buffer is too small, just allocate a new buffer (slow but sure) + int nOldLength = GetData()->nDataLength; + int nNewLength = nOldLength + (nReplacementLen - nSourceLen) * nCount; + if (GetData()->nAllocLength < nNewLength || GetData()->nRefs > 1) + { + CStringData* pOldData = GetData(); + LPTSTR pstr = m_pchData; + if(!AllocBuffer(nNewLength)) + return -1; + SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstr, pOldData->nDataLength * sizeof(TCHAR)); + CString::Release(pOldData); + } + // else, we just do it in-place + lpszStart = m_pchData; + lpszEnd = m_pchData + GetData()->nDataLength; + + // loop again to actually do the work + while (lpszStart < lpszEnd) + { + while ((lpszTarget = (TCHAR*)_cstrstr(lpszStart, lpszOld)) != NULL) + { + int nBalance = nOldLength - ((int)(DWORD_PTR)(lpszTarget - m_pchData) + nSourceLen); + int cchBuffLen = GetData()->nAllocLength - (int)(DWORD_PTR)(lpszTarget - m_pchData); + SecureHelper::memmove_x(lpszTarget + nReplacementLen, (cchBuffLen - nReplacementLen + 1) * sizeof(TCHAR), lpszTarget + nSourceLen, nBalance * sizeof(TCHAR)); + SecureHelper::memcpy_x(lpszTarget, (cchBuffLen + 1) * sizeof(TCHAR), lpszNew, nReplacementLen * sizeof(TCHAR)); + lpszStart = lpszTarget + nReplacementLen; + lpszStart[nBalance] = _T('\0'); + nOldLength += (nReplacementLen - nSourceLen); + } + lpszStart += lstrlen(lpszStart) + 1; + } + ATLASSERT(m_pchData[nNewLength] == _T('\0')); + GetData()->nDataLength = nNewLength; + } + + return nCount; + } + + // remove occurrences of chRemove + int Remove(TCHAR chRemove) + { + CopyBeforeWrite(); + + LPTSTR pstrSource = m_pchData; + LPTSTR pstrDest = m_pchData; + LPTSTR pstrEnd = m_pchData + GetData()->nDataLength; + + while (pstrSource < pstrEnd) + { + if (*pstrSource != chRemove) + { + *pstrDest = *pstrSource; + pstrDest = ::CharNext(pstrDest); + } + pstrSource = ::CharNext(pstrSource); + } + *pstrDest = _T('\0'); + int nCount = (int)(DWORD_PTR)(pstrSource - pstrDest); + GetData()->nDataLength -= nCount; + + return nCount; + } + + // insert character at zero-based index; concatenates if index is past end of string + int Insert(int nIndex, TCHAR ch) + { + CopyBeforeWrite(); + + if (nIndex < 0) + nIndex = 0; + + int nNewLength = GetData()->nDataLength; + if (nIndex > nNewLength) + nIndex = nNewLength; + nNewLength++; + + if (GetData()->nAllocLength < nNewLength) + { + CStringData* pOldData = GetData(); + LPTSTR pstr = m_pchData; + if(!AllocBuffer(nNewLength)) + return -1; + SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstr, (pOldData->nDataLength + 1) * sizeof(TCHAR)); + CString::Release(pOldData); + } + + // move existing bytes down + SecureHelper::memmove_x(m_pchData + nIndex + 1, (GetData()->nAllocLength - nIndex) * sizeof(TCHAR), m_pchData + nIndex, (nNewLength - nIndex) * sizeof(TCHAR)); + m_pchData[nIndex] = ch; + GetData()->nDataLength = nNewLength; + + return nNewLength; + } + + // insert substring at zero-based index; concatenates if index is past end of string + int Insert(int nIndex, LPCTSTR pstr) + { + if (nIndex < 0) + nIndex = 0; + + int nInsertLength = SafeStrlen(pstr); + int nNewLength = GetData()->nDataLength; + if (nInsertLength > 0) + { + CopyBeforeWrite(); + if (nIndex > nNewLength) + nIndex = nNewLength; + nNewLength += nInsertLength; + + if (GetData()->nAllocLength < nNewLength) + { + CStringData* pOldData = GetData(); + LPTSTR pstr = m_pchData; + if(!AllocBuffer(nNewLength)) + return -1; + SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstr, (pOldData->nDataLength + 1) * sizeof(TCHAR)); + CString::Release(pOldData); + } + + // move existing bytes down + SecureHelper::memmove_x(m_pchData + nIndex + nInsertLength, (GetData()->nAllocLength + 1 - nIndex - nInsertLength) * sizeof(TCHAR), m_pchData + nIndex, (nNewLength - nIndex - nInsertLength + 1) * sizeof(TCHAR)); + SecureHelper::memcpy_x(m_pchData + nIndex, (GetData()->nAllocLength + 1 - nIndex) * sizeof(TCHAR), pstr, nInsertLength * sizeof(TCHAR)); + GetData()->nDataLength = nNewLength; + } + + return nNewLength; + } + + // delete nCount characters starting at zero-based index + int Delete(int nIndex, int nCount = 1) + { + if (nIndex < 0) + nIndex = 0; + int nLength = GetData()->nDataLength; + if (nCount > 0 && nIndex < nLength) + { + if((nIndex + nCount) > nLength) + nCount = nLength - nIndex; + CopyBeforeWrite(); + int nBytesToCopy = nLength - (nIndex + nCount) + 1; + + SecureHelper::memmove_x(m_pchData + nIndex, (GetData()->nAllocLength + 1 - nIndex) * sizeof(TCHAR), m_pchData + nIndex + nCount, nBytesToCopy * sizeof(TCHAR)); + nLength -= nCount; + GetData()->nDataLength = nLength; + } + + return nLength; + } + + // searching (return starting index, or -1 if not found) + // look for a single character match + int Find(TCHAR ch) const // like "C" strchr + { + return Find(ch, 0); + } + + int ReverseFind(TCHAR ch) const + { + // find last single character + LPCTSTR lpsz = _cstrrchr(m_pchData, (_TUCHAR)ch); + + // return -1 if not found, distance from beginning otherwise + return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); + } + + int Find(TCHAR ch, int nStart) const // starting at index + { + int nLength = GetData()->nDataLength; + if (nStart < 0 || nStart >= nLength) + return -1; + + // find first single character + LPCTSTR lpsz = _cstrchr(m_pchData + nStart, (_TUCHAR)ch); + + // return -1 if not found and index otherwise + return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); + } + + int FindOneOf(LPCTSTR lpszCharSet) const + { + ATLASSERT(_IsValidString(lpszCharSet)); + LPCTSTR lpsz = _cstrpbrk(m_pchData, lpszCharSet); + return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); + } + + // look for a specific sub-string + // find a sub-string (like strstr) + int Find(LPCTSTR lpszSub) const // like "C" strstr + { + return Find(lpszSub, 0); + } + + int Find(LPCTSTR lpszSub, int nStart) const // starting at index + { + ATLASSERT(_IsValidString(lpszSub)); + + int nLength = GetData()->nDataLength; + if (nStart < 0 || nStart > nLength) + return -1; + + // find first matching substring + LPCTSTR lpsz = _cstrstr(m_pchData + nStart, lpszSub); + + // return -1 for not found, distance from beginning otherwise + return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); + } + + // Concatentation for non strings + CString& Append(int n) + { + const int cchBuff = 12; + TCHAR szBuffer[cchBuff] = { 0 }; + SecureHelper::wsprintf_x(szBuffer, cchBuff, _T("%d"), n); + ConcatInPlace(SafeStrlen(szBuffer), szBuffer); + return *this; + } + + // simple formatting + // formatting (using wsprintf style formatting) + BOOL __cdecl Format(LPCTSTR lpszFormat, ...) + { + ATLASSERT(_IsValidString(lpszFormat)); + + va_list argList; + va_start(argList, lpszFormat); + BOOL bRet = FormatV(lpszFormat, argList); + va_end(argList); + return bRet; + } + + BOOL __cdecl Format(UINT nFormatID, ...) + { + CString strFormat; + BOOL bRet = strFormat.LoadString(nFormatID); + ATLASSERT(bRet != 0); + + va_list argList; + va_start(argList, nFormatID); + bRet = FormatV(strFormat, argList); + va_end(argList); + return bRet; + } + + BOOL FormatV(LPCTSTR lpszFormat, va_list argList) + { + ATLASSERT(_IsValidString(lpszFormat)); + + enum _FormatModifiers + { + FORCE_ANSI = 0x10000, + FORCE_UNICODE = 0x20000, + FORCE_INT64 = 0x40000 + }; + + va_list argListSave = argList; + + // make a guess at the maximum length of the resulting string + int nMaxLen = 0; + for (LPCTSTR lpsz = lpszFormat; *lpsz != _T('\0'); lpsz = ::CharNext(lpsz)) + { + // handle '%' character, but watch out for '%%' + if (*lpsz != _T('%') || *(lpsz = ::CharNext(lpsz)) == _T('%')) + { + nMaxLen += (int)(::CharNext(lpsz) - lpsz); + continue; + } + + int nItemLen = 0; + + // handle '%' character with format + int nWidth = 0; + for (; *lpsz != _T('\0'); lpsz = ::CharNext(lpsz)) + { + // check for valid flags + if (*lpsz == _T('#')) + nMaxLen += 2; // for '0x' + else if (*lpsz == _T('*')) + nWidth = va_arg(argList, int); + else if (*lpsz == _T('-') || *lpsz == _T('+') || *lpsz == _T('0') || *lpsz == _T(' ')) + ; + else // hit non-flag character + break; + } + // get width and skip it + if (nWidth == 0) + { + // width indicated by + nWidth = _cstrtoi(lpsz); + for (; *lpsz != _T('\0') && _cstrisdigit(*lpsz); lpsz = ::CharNext(lpsz)) + ; + } + ATLASSERT(nWidth >= 0); + + int nPrecision = 0; + if (*lpsz == _T('.')) + { + // skip past '.' separator (width.precision) + lpsz = ::CharNext(lpsz); + + // get precision and skip it + if (*lpsz == _T('*')) + { + nPrecision = va_arg(argList, int); + lpsz = ::CharNext(lpsz); + } + else + { + nPrecision = _cstrtoi(lpsz); + for (; *lpsz != _T('\0') && _cstrisdigit(*lpsz); lpsz = ::CharNext(lpsz)) + ; + } + ATLASSERT(nPrecision >= 0); + } + + // should be on type modifier or specifier + int nModifier = 0; + if(lpsz[0] == _T('I') && lpsz[1] == _T('6') && lpsz[2] == _T('4')) + { + lpsz += 3; + nModifier = FORCE_INT64; + } + else + { + switch (*lpsz) + { + // modifiers that affect size + case _T('h'): + nModifier = FORCE_ANSI; + lpsz = ::CharNext(lpsz); + break; + case _T('l'): + nModifier = FORCE_UNICODE; + lpsz = ::CharNext(lpsz); + break; + + // modifiers that do not affect size + case _T('F'): + case _T('N'): + case _T('L'): + lpsz = ::CharNext(lpsz); + break; + } + } + + // now should be on specifier + switch (*lpsz | nModifier) + { + // single characters + case _T('c'): + case _T('C'): + nItemLen = 2; + va_arg(argList, TCHAR); + break; + case _T('c') | FORCE_ANSI: + case _T('C') | FORCE_ANSI: + nItemLen = 2; + va_arg(argList, char); + break; + case _T('c') | FORCE_UNICODE: + case _T('C') | FORCE_UNICODE: + nItemLen = 2; + va_arg(argList, WCHAR); + break; + + // strings + case _T('s'): + { + LPCTSTR pstrNextArg = va_arg(argList, LPCTSTR); + if (pstrNextArg == NULL) + { + nItemLen = 6; // "(null)" + } + else + { + nItemLen = lstrlen(pstrNextArg); + nItemLen = max(1, nItemLen); + } + break; + } + + case _T('S'): + { +#ifndef _UNICODE + LPWSTR pstrNextArg = va_arg(argList, LPWSTR); + if (pstrNextArg == NULL) + { + nItemLen = 6; // "(null)" + } + else + { + nItemLen = (int)wcslen(pstrNextArg); + nItemLen = max(1, nItemLen); + } +#else // _UNICODE + LPCSTR pstrNextArg = va_arg(argList, LPCSTR); + if (pstrNextArg == NULL) + { + nItemLen = 6; // "(null)" + } + else + { +#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800) + nItemLen = ATL::lstrlenA(pstrNextArg); +#else + nItemLen = lstrlenA(pstrNextArg); +#endif + nItemLen = max(1, nItemLen); + } +#endif // _UNICODE + break; + } + + case _T('s') | FORCE_ANSI: + case _T('S') | FORCE_ANSI: + { + LPCSTR pstrNextArg = va_arg(argList, LPCSTR); + if (pstrNextArg == NULL) + { + nItemLen = 6; // "(null)" + } + else + { +#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800) + nItemLen = ATL::lstrlenA(pstrNextArg); +#else + nItemLen = lstrlenA(pstrNextArg); +#endif + nItemLen = max(1, nItemLen); + } + break; + } + + case _T('s') | FORCE_UNICODE: + case _T('S') | FORCE_UNICODE: + { + LPWSTR pstrNextArg = va_arg(argList, LPWSTR); + if (pstrNextArg == NULL) + { + nItemLen = 6; // "(null)" + } + else + { + nItemLen = (int)wcslen(pstrNextArg); + nItemLen = max(1, nItemLen); + } + break; + } + } + + // adjust nItemLen for strings + if (nItemLen != 0) + { + nItemLen = max(nItemLen, nWidth); + if (nPrecision != 0) + nItemLen = min(nItemLen, nPrecision); + } + else + { + switch (*lpsz) + { + // integers + case _T('d'): + case _T('i'): + case _T('u'): + case _T('x'): + case _T('X'): + case _T('o'): + if (nModifier & FORCE_INT64) + va_arg(argList, __int64); + else + va_arg(argList, int); + nItemLen = 32; + nItemLen = max(nItemLen, nWidth + nPrecision); + break; + +#ifndef _ATL_USE_CSTRING_FLOAT + case _T('e'): + case _T('E'): + case _T('f'): + case _T('g'): + case _T('G'): + ATLASSERT(!"Floating point (%%e, %%E, %%f, %%g, and %%G) is not supported by the WTL::CString class."); +#ifndef _DEBUG + ::OutputDebugString(_T("Floating point (%%e, %%f, %%g, and %%G) is not supported by the WTL::CString class.")); +#ifndef _WIN32_WCE + ::DebugBreak(); +#else // CE specific + DebugBreak(); +#endif // _WIN32_WCE +#endif // !_DEBUG + break; +#else // _ATL_USE_CSTRING_FLOAT + case _T('e'): + case _T('E'): + case _T('g'): + case _T('G'): + va_arg(argList, double); + nItemLen = 128; + nItemLen = max(nItemLen, nWidth + nPrecision); + break; + case _T('f'): + { + double f = va_arg(argList, double); + // 312 == strlen("-1+(309 zeroes).") + // 309 zeroes == max precision of a double + // 6 == adjustment in case precision is not specified, + // which means that the precision defaults to 6 + int cchLen = max(nWidth, 312 + nPrecision + 6); + CTempBuffer buff; + LPTSTR pszTemp = buff.Allocate(cchLen); + if(pszTemp != NULL) + { + SecureHelper::sprintf_x(pszTemp, cchLen, _T("%*.*f"), nWidth, nPrecision + 6, f); + nItemLen = (int)_tcslen(pszTemp); + } + else + { + nItemLen = cchLen; + } + } + break; +#endif // _ATL_USE_CSTRING_FLOAT + + case _T('p'): + va_arg(argList, void*); + nItemLen = 32; + nItemLen = max(nItemLen, nWidth + nPrecision); + break; + + // no output + case _T('n'): + va_arg(argList, int*); + break; + + default: + ATLASSERT(FALSE); // unknown formatting option + } + } + + // adjust nMaxLen for output nItemLen + nMaxLen += nItemLen; + } + + if(GetBuffer(nMaxLen) == NULL) + return FALSE; +#ifndef _ATL_USE_CSTRING_FLOAT + int nRet = SecureHelper::wvsprintf_x(m_pchData, GetAllocLength() + 1, lpszFormat, argListSave); +#else // _ATL_USE_CSTRING_FLOAT + int nRet = SecureHelper::vsprintf_x(m_pchData, GetAllocLength() + 1, lpszFormat, argListSave); +#endif // _ATL_USE_CSTRING_FLOAT + nRet; // ref + ATLASSERT(nRet <= GetAllocLength()); + ReleaseBuffer(); + + va_end(argListSave); + return TRUE; + } + + // formatting for localization (uses FormatMessage API) + // formatting (using FormatMessage style formatting) + BOOL __cdecl FormatMessage(LPCTSTR lpszFormat, ...) + { + // format message into temporary buffer lpszTemp + va_list argList; + va_start(argList, lpszFormat); + LPTSTR lpszTemp; + BOOL bRet = TRUE; + + if (::FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, + lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 || lpszTemp == NULL) + bRet = FALSE; + + // assign lpszTemp into the resulting string and free the temporary + *this = lpszTemp; + LocalFree(lpszTemp); + va_end(argList); + return bRet; + } + + BOOL __cdecl FormatMessage(UINT nFormatID, ...) + { + // get format string from string table + CString strFormat; + BOOL bRetTmp = strFormat.LoadString(nFormatID); + bRetTmp; // ref + ATLASSERT(bRetTmp != 0); + + // format message into temporary buffer lpszTemp + va_list argList; + va_start(argList, nFormatID); + LPTSTR lpszTemp; + BOOL bRet = TRUE; + + if (::FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, + strFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 || lpszTemp == NULL) + bRet = FALSE; + + // assign lpszTemp into the resulting string and free lpszTemp + *this = lpszTemp; + LocalFree(lpszTemp); + va_end(argList); + return bRet; + } + + // Windows support + BOOL LoadString(UINT nID) // load from string resource (255 chars max.) + { +#ifdef _UNICODE + const int CHAR_FUDGE = 1; // one TCHAR unused is good enough +#else + const int CHAR_FUDGE = 2; // two BYTES unused for case of DBC last char +#endif + + // try fixed buffer first (to avoid wasting space in the heap) + TCHAR szTemp[256]; + int nCount = sizeof(szTemp) / sizeof(szTemp[0]); + int nLen = _LoadString(nID, szTemp, nCount); + if (nCount - nLen > CHAR_FUDGE) + { + *this = szTemp; + return (nLen > 0); + } + + // try buffer size of 512, then larger size until entire string is retrieved + int nSize = 256; + do + { + nSize += 256; + LPTSTR lpstr = GetBuffer(nSize - 1); + if(lpstr == NULL) + { + nLen = 0; + break; + } + nLen = _LoadString(nID, lpstr, nSize); + } while (nSize - nLen <= CHAR_FUDGE); + ReleaseBuffer(); + + return (nLen > 0); + } + +#ifndef _UNICODE + // ANSI <-> OEM support (convert string in place) + void AnsiToOem() + { + CopyBeforeWrite(); + ::AnsiToOem(m_pchData, m_pchData); + } + + void OemToAnsi() + { + CopyBeforeWrite(); + ::OemToAnsi(m_pchData, m_pchData); + } +#endif + +#ifndef _ATL_NO_COM + // OLE BSTR support (use for OLE automation) + BSTR AllocSysString() const + { +#if defined(_UNICODE) || defined(OLE2ANSI) + BSTR bstr = ::SysAllocStringLen(m_pchData, GetData()->nDataLength); +#else + int nLen = MultiByteToWideChar(CP_ACP, 0, m_pchData, + GetData()->nDataLength, NULL, NULL); + BSTR bstr = ::SysAllocStringLen(NULL, nLen); + if(bstr != NULL) + MultiByteToWideChar(CP_ACP, 0, m_pchData, GetData()->nDataLength, bstr, nLen); +#endif + return bstr; + } + + BSTR SetSysString(BSTR* pbstr) const + { +#if defined(_UNICODE) || defined(OLE2ANSI) + ::SysReAllocStringLen(pbstr, m_pchData, GetData()->nDataLength); +#else + int nLen = MultiByteToWideChar(CP_ACP, 0, m_pchData, + GetData()->nDataLength, NULL, NULL); + if(::SysReAllocStringLen(pbstr, NULL, nLen)) + MultiByteToWideChar(CP_ACP, 0, m_pchData, GetData()->nDataLength, *pbstr, nLen); +#endif + ATLASSERT(*pbstr != NULL); + return *pbstr; + } +#endif // !_ATL_NO_COM + + // Access to string implementation buffer as "C" character array + LPTSTR GetBuffer(int nMinBufLength) + { + ATLASSERT(nMinBufLength >= 0); + + if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength) + { + // we have to grow the buffer + CStringData* pOldData = GetData(); + int nOldLen = GetData()->nDataLength; // AllocBuffer will tromp it + if (nMinBufLength < nOldLen) + nMinBufLength = nOldLen; + + if(!AllocBuffer(nMinBufLength)) + return NULL; + + SecureHelper::memcpy_x(m_pchData, (nMinBufLength + 1) * sizeof(TCHAR), pOldData->data(), (nOldLen + 1) * sizeof(TCHAR)); + GetData()->nDataLength = nOldLen; + CString::Release(pOldData); + } + ATLASSERT(GetData()->nRefs <= 1); + + // return a pointer to the character storage for this string + ATLASSERT(m_pchData != NULL); + return m_pchData; + } + + void ReleaseBuffer(int nNewLength = -1) + { + CopyBeforeWrite(); // just in case GetBuffer was not called + + if (nNewLength == -1) + nNewLength = lstrlen(m_pchData); // zero terminated + + ATLASSERT(nNewLength <= GetData()->nAllocLength); + GetData()->nDataLength = nNewLength; + m_pchData[nNewLength] = _T('\0'); + } + + LPTSTR GetBufferSetLength(int nNewLength) + { + ATLASSERT(nNewLength >= 0); + + if(GetBuffer(nNewLength) == NULL) + return NULL; + + GetData()->nDataLength = nNewLength; + m_pchData[nNewLength] = _T('\0'); + return m_pchData; + } + + void FreeExtra() + { + ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength); + if (GetData()->nDataLength != GetData()->nAllocLength) + { + CStringData* pOldData = GetData(); + if(AllocBuffer(GetData()->nDataLength)) + { + SecureHelper::memcpy_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), pOldData->data(), pOldData->nDataLength * sizeof(TCHAR)); + ATLASSERT(m_pchData[GetData()->nDataLength] == _T('\0')); + CString::Release(pOldData); + } + } + ATLASSERT(GetData() != NULL); + } + + // Use LockBuffer/UnlockBuffer to turn refcounting off + LPTSTR LockBuffer() + { + LPTSTR lpsz = GetBuffer(0); + if(lpsz != NULL) + GetData()->nRefs = -1; + return lpsz; + } + + void UnlockBuffer() + { + ATLASSERT(GetData()->nRefs == -1); + if (GetData() != _atltmpDataNil) + GetData()->nRefs = 1; + } + +// Implementation +public: + ~CString() // free any attached data + { + if (GetData() != _atltmpDataNil) + { + if (InterlockedDecrement(&GetData()->nRefs) <= 0) + delete[] (BYTE*)GetData(); + } + } + + int GetAllocLength() const + { + return GetData()->nAllocLength; + } + + static BOOL __stdcall _IsValidString(LPCTSTR lpsz, int /*nLength*/ = -1) + { + return (lpsz != NULL) ? TRUE : FALSE; + } + +protected: + LPTSTR m_pchData; // pointer to ref counted string data + + // implementation helpers + CStringData* GetData() const + { + ATLASSERT(m_pchData != NULL); + return ((CStringData*)m_pchData) - 1; + } + + void Init() + { + m_pchData = _GetEmptyString().m_pchData; + } + + BOOL AllocCopy(CString& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const + { + // will clone the data attached to this string + // allocating 'nExtraLen' characters + // Places results in uninitialized string 'dest' + // Will copy the part or all of original data to start of new string + + BOOL bRet = FALSE; + int nNewLen = nCopyLen + nExtraLen; + if (nNewLen == 0) + { + dest.Init(); + bRet = TRUE; + } + else if(nNewLen >= nCopyLen) + { + if(dest.AllocBuffer(nNewLen)) + { + SecureHelper::memcpy_x(dest.m_pchData, (nNewLen + 1) * sizeof(TCHAR), m_pchData + nCopyIndex, nCopyLen * sizeof(TCHAR)); + bRet = TRUE; + } + } + + return bRet; + } + + // always allocate one extra character for '\0' termination + // assumes [optimistically] that data length will equal allocation length + BOOL AllocBuffer(int nLen) + { + ATLASSERT(nLen >= 0); + ATLASSERT(nLen <= INT_MAX - 1); // max size (enough room for 1 extra) + + if (nLen == 0) + { + Init(); + } + else + { + CStringData* pData = NULL; + ATLTRY(pData = (CStringData*)new BYTE[sizeof(CStringData) + (nLen + 1) * sizeof(TCHAR)]); + if(pData == NULL) + return FALSE; + + pData->nRefs = 1; + pData->data()[nLen] = _T('\0'); + pData->nDataLength = nLen; + pData->nAllocLength = nLen; + m_pchData = pData->data(); + } + + return TRUE; + } + + // Assignment operators + // All assign a new value to the string + // (a) first see if the buffer is big enough + // (b) if enough room, copy on top of old buffer, set size and type + // (c) otherwise free old string data, and create a new one + // + // All routines return the new string (but as a 'const CString&' so that + // assigning it again will cause a copy, eg: s1 = s2 = "hi there". + // + void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData) + { + if(AllocBeforeWrite(nSrcLen)) + { + SecureHelper::memcpy_x(m_pchData, (nSrcLen + 1) * sizeof(TCHAR), lpszSrcData, nSrcLen * sizeof(TCHAR)); + GetData()->nDataLength = nSrcLen; + m_pchData[nSrcLen] = _T('\0'); + } + } + + // Concatenation + // NOTE: "operator +" is done as friend functions for simplicity + // There are three variants: + // CString + CString + // and for ? = TCHAR, LPCTSTR + // CString + ? + // ? + CString + BOOL ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data, int nSrc2Len, LPCTSTR lpszSrc2Data) + { + // -- master concatenation routine + // Concatenate two sources + // -- assume that 'this' is a new CString object + + BOOL bRet = TRUE; + int nNewLen = nSrc1Len + nSrc2Len; + if(nNewLen < nSrc1Len || nNewLen < nSrc2Len) + { + bRet = FALSE; + } + else if(nNewLen != 0) + { + bRet = AllocBuffer(nNewLen); + if (bRet) + { + SecureHelper::memcpy_x(m_pchData, (nNewLen + 1) * sizeof(TCHAR), lpszSrc1Data, nSrc1Len * sizeof(TCHAR)); + SecureHelper::memcpy_x(m_pchData + nSrc1Len, (nNewLen + 1 - nSrc1Len) * sizeof(TCHAR), lpszSrc2Data, nSrc2Len * sizeof(TCHAR)); + } + } + return bRet; + } + + void ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData) + { + // -- the main routine for += operators + + // concatenating an empty string is a no-op! + if (nSrcLen == 0) + return; + + // if the buffer is too small, or we have a width mis-match, just + // allocate a new buffer (slow but sure) + if (GetData()->nRefs > 1 || GetData()->nDataLength + nSrcLen > GetData()->nAllocLength) + { + // we have to grow the buffer, use the ConcatCopy routine + CStringData* pOldData = GetData(); + if (ConcatCopy(GetData()->nDataLength, m_pchData, nSrcLen, lpszSrcData)) + { + ATLASSERT(pOldData != NULL); + CString::Release(pOldData); + } + } + else + { + // fast concatenation when buffer big enough + SecureHelper::memcpy_x(m_pchData + GetData()->nDataLength, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpszSrcData, nSrcLen * sizeof(TCHAR)); + GetData()->nDataLength += nSrcLen; + ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength); + m_pchData[GetData()->nDataLength] = _T('\0'); + } + } + + void CopyBeforeWrite() + { + if (GetData()->nRefs > 1) + { + CStringData* pData = GetData(); + Release(); + if(AllocBuffer(pData->nDataLength)) + SecureHelper::memcpy_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), pData->data(), (pData->nDataLength + 1) * sizeof(TCHAR)); + } + ATLASSERT(GetData()->nRefs <= 1); + } + + BOOL AllocBeforeWrite(int nLen) + { + BOOL bRet = TRUE; + if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength) + { + Release(); + bRet = AllocBuffer(nLen); + } + ATLASSERT(GetData()->nRefs <= 1); + return bRet; + } + + void Release() + { + if (GetData() != _atltmpDataNil) + { + ATLASSERT(GetData()->nRefs != 0); + if (InterlockedDecrement(&GetData()->nRefs) <= 0) + delete[] (BYTE*)GetData(); + Init(); + } + } + + static void PASCAL Release(CStringData* pData) + { + if (pData != _atltmpDataNil) + { + ATLASSERT(pData->nRefs != 0); + if (InterlockedDecrement(&pData->nRefs) <= 0) + delete[] (BYTE*)pData; + } + } + + static int PASCAL SafeStrlen(LPCTSTR lpsz) + { + return (lpsz == NULL) ? 0 : lstrlen(lpsz); + } + + static int __stdcall _LoadString(UINT nID, LPTSTR lpszBuf, UINT nMaxBuf) + { +#ifdef _DEBUG + // LoadString without annoying warning from the Debug kernel if the + // segment containing the string is not present + if (::FindResource(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE((nID >> 4) + 1), RT_STRING) == NULL) + { + lpszBuf[0] = _T('\0'); + return 0; // not found + } +#endif // _DEBUG + + int nLen = ::LoadString(ModuleHelper::GetResourceInstance(), nID, lpszBuf, nMaxBuf); + if (nLen == 0) + lpszBuf[0] = _T('\0'); + + return nLen; + } + + static const CString& __stdcall _GetEmptyString() + { + return *(CString*)&_atltmpPchNil; + } + +// CString conversion helpers + static int __cdecl _wcstombsz(char* mbstr, const wchar_t* wcstr, size_t count) + { + if (count == 0 && mbstr != NULL) + return 0; + + int result = ::WideCharToMultiByte(CP_ACP, 0, wcstr, -1, mbstr, (int)count, NULL, NULL); + ATLASSERT(mbstr == NULL || result <= (int)count); + if (result > 0) + mbstr[result - 1] = 0; + return result; + } + + static int __cdecl _mbstowcsz(wchar_t* wcstr, const char* mbstr, size_t count) + { + if (count == 0 && wcstr != NULL) + return 0; + + int result = ::MultiByteToWideChar(CP_ACP, 0, mbstr, -1, wcstr, (int)count); + ATLASSERT(wcstr == NULL || result <= (int)count); + if (result > 0) + wcstr[result - 1] = 0; + return result; + } + +// Helpers to avoid CRT startup code +#ifdef _ATL_MIN_CRT + static const TCHAR* _cstrchr(const TCHAR* p, TCHAR ch) + { + // strchr for '\0' should succeed + while (*p != 0) + { + if (*p == ch) + break; + p = ::CharNext(p); + } + return (*p == ch) ? p : NULL; + } + + static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch) + { + const TCHAR* lpsz = NULL; + while (*p != 0) + { + if (*p == ch) + lpsz = p; + p = ::CharNext(p); + } + return lpsz; + } + + static TCHAR* _cstrrev(TCHAR* pStr) + { + // optimize NULL, zero-length, and single-char case + if ((pStr == NULL) || (pStr[0] == _T('\0')) || (pStr[1] == _T('\0'))) + return pStr; + + TCHAR* p = pStr; + + while (*p != 0) + { + TCHAR* pNext = ::CharNext(p); + if(pNext > p + 1) + { + char p1 = *(char*)p; + *(char*)p = *(char*)(p + 1); + *(char*)(p + 1) = p1; + } + p = pNext; + } + + p--; + TCHAR* q = pStr; + + while (q < p) + { + TCHAR t = *q; + *q = *p; + *p = t; + q++; + p--; + } + return pStr; + } + + static const TCHAR* _cstrstr(const TCHAR* pStr, const TCHAR* pCharSet) + { + int nLen = lstrlen(pCharSet); + if (nLen == 0) + return (TCHAR*)pStr; + + const TCHAR* pRet = NULL; + const TCHAR* pCur = pStr; + while((pCur = _cstrchr(pCur, *pCharSet)) != NULL) + { + if(memcmp(pCur, pCharSet, nLen * sizeof(TCHAR)) == 0) + { + pRet = pCur; + break; + } + pCur = ::CharNext(pCur); + } + return pRet; + } + + static int _cstrspn(const TCHAR* pStr, const TCHAR* pCharSet) + { + int nRet = 0; + const TCHAR* p = pStr; + while (*p != 0) + { + const TCHAR* pNext = ::CharNext(p); + if(pNext > p + 1) + { + if(_cstrchr_db(pCharSet, *p, *(p + 1)) == NULL) + break; + nRet += 2; + } + else + { + if(_cstrchr(pCharSet, *p) == NULL) + break; + nRet++; + } + p = pNext; + } + return nRet; + } + + static int _cstrcspn(const TCHAR* pStr, const TCHAR* pCharSet) + { + int nRet = 0; + TCHAR* p = (TCHAR*)pStr; + while (*p != 0) + { + TCHAR* pNext = ::CharNext(p); + if(pNext > p + 1) + { + if(_cstrchr_db(pCharSet, *p, *(p + 1)) != NULL) + break; + nRet += 2; + } + else + { + if(_cstrchr(pCharSet, *p) != NULL) + break; + nRet++; + } + p = pNext; + } + return nRet; + } + + static const TCHAR* _cstrpbrk(const TCHAR* p, const TCHAR* lpszCharSet) + { + int n = _cstrcspn(p, lpszCharSet); + return (p[n] != 0) ? &p[n] : NULL; + } + + static int _cstrisdigit(TCHAR ch) + { + WORD type; + GetStringTypeEx(GetThreadLocale(), CT_CTYPE1, &ch, 1, &type); + return (type & C1_DIGIT) == C1_DIGIT; + } + + static int _cstrisspace(TCHAR ch) + { + WORD type; + GetStringTypeEx(GetThreadLocale(), CT_CTYPE1, &ch, 1, &type); + return (type & C1_SPACE) == C1_SPACE; + } + + static int _cstrcmp(const TCHAR* pstrOne, const TCHAR* pstrOther) + { + return lstrcmp(pstrOne, pstrOther); + } + + static int _cstrcmpi(const TCHAR* pstrOne, const TCHAR* pstrOther) + { + return lstrcmpi(pstrOne, pstrOther); + } + + static int _cstrcoll(const TCHAR* pstrOne, const TCHAR* pstrOther) + { + int nRet = CompareString(GetThreadLocale(), 0, pstrOne, -1, pstrOther, -1); + ATLASSERT(nRet != 0); + return nRet - 2; // convert to strcmp convention + } + + static int _cstrcolli(const TCHAR* pstrOne, const TCHAR* pstrOther) + { + int nRet = CompareString(GetThreadLocale(), NORM_IGNORECASE, pstrOne, -1, pstrOther, -1); + ATLASSERT(nRet != 0); + return nRet - 2; // convert to strcmp convention + } + + static int _cstrtoi(const TCHAR* nptr) + { + int c; // current char + int total; // current total + int sign; // if '-', then negative, otherwise positive + + while (_cstrisspace(*nptr)) + ++nptr; + + c = (int)(_TUCHAR)*nptr++; + sign = c; // save sign indication + if (c == _T('-') || c == _T('+')) + c = (int)(_TUCHAR)*nptr++; // skip sign + + total = 0; + + while (_cstrisdigit((TCHAR)c)) + { + total = 10 * total + (c - '0'); // accumulate digit + c = (int)(_TUCHAR)*nptr++; // get next char + } + + if (sign == '-') + return -total; + else + return total; // return result, negated if necessary + } +#else // !_ATL_MIN_CRT + static const TCHAR* _cstrchr(const TCHAR* p, TCHAR ch) + { + return _tcschr(p, ch); + } + + static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch) + { + return _tcsrchr(p, ch); + } + + static TCHAR* _cstrrev(TCHAR* pStr) + { + return _tcsrev(pStr); + } + + static const TCHAR* _cstrstr(const TCHAR* pStr, const TCHAR* pCharSet) + { + return _tcsstr(pStr, pCharSet); + } + + static int _cstrspn(const TCHAR* pStr, const TCHAR* pCharSet) + { + return (int)_tcsspn(pStr, pCharSet); + } + + static int _cstrcspn(const TCHAR* pStr, const TCHAR* pCharSet) + { + return (int)_tcscspn(pStr, pCharSet); + } + + static const TCHAR* _cstrpbrk(const TCHAR* p, const TCHAR* lpszCharSet) + { + return _tcspbrk(p, lpszCharSet); + } + + static int _cstrisdigit(TCHAR ch) + { + return _istdigit(ch); + } + + static int _cstrisspace(TCHAR ch) + { + return _istspace((_TUCHAR)ch); + } + + static int _cstrcmp(const TCHAR* pstrOne, const TCHAR* pstrOther) + { + return _tcscmp(pstrOne, pstrOther); + } + + static int _cstrcmpi(const TCHAR* pstrOne, const TCHAR* pstrOther) + { + return _tcsicmp(pstrOne, pstrOther); + } + +#ifndef _WIN32_WCE + static int _cstrcoll(const TCHAR* pstrOne, const TCHAR* pstrOther) + { + return _tcscoll(pstrOne, pstrOther); + } + + static int _cstrcolli(const TCHAR* pstrOne, const TCHAR* pstrOther) + { + return _tcsicoll(pstrOne, pstrOther); + } +#endif // !_WIN32_WCE + + static int _cstrtoi(const TCHAR* nptr) + { + return _ttoi(nptr); + } +#endif // !_ATL_MIN_CRT + + static const TCHAR* _cstrchr_db(const TCHAR* p, TCHAR ch1, TCHAR ch2) + { + const TCHAR* lpsz = NULL; + while (*p != 0) + { + if (*p == ch1 && *(p + 1) == ch2) + { + lpsz = p; + break; + } + p = ::CharNext(p); + } + return lpsz; + } +}; + + +// Compare helpers + +inline bool __stdcall operator ==(const CString& s1, const CString& s2) +{ return s1.Compare(s2) == 0; } + +inline bool __stdcall operator ==(const CString& s1, LPCTSTR s2) +{ return s1.Compare(s2) == 0; } + +inline bool __stdcall operator ==(LPCTSTR s1, const CString& s2) +{ return s2.Compare(s1) == 0; } + +inline bool __stdcall operator !=(const CString& s1, const CString& s2) +{ return s1.Compare(s2) != 0; } + +inline bool __stdcall operator !=(const CString& s1, LPCTSTR s2) +{ return s1.Compare(s2) != 0; } + +inline bool __stdcall operator !=(LPCTSTR s1, const CString& s2) +{ return s2.Compare(s1) != 0; } + +inline bool __stdcall operator <(const CString& s1, const CString& s2) +{ return s1.Compare(s2) < 0; } + +inline bool __stdcall operator <(const CString& s1, LPCTSTR s2) +{ return s1.Compare(s2) < 0; } + +inline bool __stdcall operator <(LPCTSTR s1, const CString& s2) +{ return s2.Compare(s1) > 0; } + +inline bool __stdcall operator >(const CString& s1, const CString& s2) +{ return s1.Compare(s2) > 0; } + +inline bool __stdcall operator >(const CString& s1, LPCTSTR s2) +{ return s1.Compare(s2) > 0; } + +inline bool __stdcall operator >(LPCTSTR s1, const CString& s2) +{ return s2.Compare(s1) < 0; } + +inline bool __stdcall operator <=(const CString& s1, const CString& s2) +{ return s1.Compare(s2) <= 0; } + +inline bool __stdcall operator <=(const CString& s1, LPCTSTR s2) +{ return s1.Compare(s2) <= 0; } + +inline bool __stdcall operator <=(LPCTSTR s1, const CString& s2) +{ return s2.Compare(s1) >= 0; } + +inline bool __stdcall operator >=(const CString& s1, const CString& s2) +{ return s1.Compare(s2) >= 0; } + +inline bool __stdcall operator >=(const CString& s1, LPCTSTR s2) +{ return s1.Compare(s2) >= 0; } + +inline bool __stdcall operator >=(LPCTSTR s1, const CString& s2) +{ return s2.Compare(s1) <= 0; } + + +// CString "operator +" functions + +inline CString __stdcall operator +(const CString& string1, const CString& string2) +{ + CString s; + s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData, string2.GetData()->nDataLength, string2.m_pchData); + return s; +} + +inline CString __stdcall operator +(const CString& string, TCHAR ch) +{ + CString s; + s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, 1, &ch); + return s; +} + +inline CString __stdcall operator +(TCHAR ch, const CString& string) +{ + CString s; + s.ConcatCopy(1, &ch, string.GetData()->nDataLength, string.m_pchData); + return s; +} + +#ifdef _UNICODE +inline CString __stdcall operator +(const CString& string, char ch) +{ + return string + (TCHAR)ch; +} + +inline CString __stdcall operator +(char ch, const CString& string) +{ + return (TCHAR)ch + string; +} +#endif // _UNICODE + +inline CString __stdcall operator +(const CString& string, LPCTSTR lpsz) +{ + ATLASSERT(lpsz == NULL || CString::_IsValidString(lpsz)); + CString s; + s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, CString::SafeStrlen(lpsz), lpsz); + return s; +} + +inline CString __stdcall operator +(LPCTSTR lpsz, const CString& string) +{ + ATLASSERT(lpsz == NULL || CString::_IsValidString(lpsz)); + CString s; + s.ConcatCopy(CString::SafeStrlen(lpsz), lpsz, string.GetData()->nDataLength, string.m_pchData); + return s; +} + +#endif // !_WTL_NO_CSTRING + + +/////////////////////////////////////////////////////////////////////////////// +// CRecentDocumentList - MRU List Support + +#ifndef _WIN32_WCE + +#ifndef _WTL_MRUEMPTY_TEXT + #define _WTL_MRUEMPTY_TEXT _T("(empty)") +#endif + +// forward declaration +inline bool AtlCompactPath(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen); + +template +class CRecentDocumentListBase +{ +public: +// Declarations + struct _DocEntry + { + TCHAR szDocName[t_cchItemLen]; + bool operator ==(const _DocEntry& de) const + { return (lstrcmpi(szDocName, de.szDocName) == 0); } + }; + + enum + { + m_nMaxEntries_Min = 2, + m_nMaxEntries_Max = t_nLastID - t_nFirstID + 1, + m_cchMaxItemLen_Min = 6, + m_cchMaxItemLen_Max = t_cchItemLen, + m_cchItemNameLen = 11 + }; + +// Data members + ATL::CSimpleArray<_DocEntry> m_arrDocs; + int m_nMaxEntries; // default is 4 + HMENU m_hMenu; + + TCHAR m_szNoEntries[t_cchItemLen]; + + int m_cchMaxItemLen; + +// Constructor + CRecentDocumentListBase() : m_hMenu(NULL), m_nMaxEntries(4), m_cchMaxItemLen(-1) + { + // These ASSERTs verify values of the template arguments + ATLASSERT(t_cchItemLen > m_cchMaxItemLen_Min); + ATLASSERT(m_nMaxEntries_Max > m_nMaxEntries_Min); + } + +// Attributes + HMENU GetMenuHandle() const + { + return m_hMenu; + } + + void SetMenuHandle(HMENU hMenu) + { + ATLASSERT(hMenu == NULL || ::IsMenu(hMenu)); + m_hMenu = hMenu; + if(m_hMenu == NULL || (::GetMenuString(m_hMenu, t_nFirstID, m_szNoEntries, t_cchItemLen, MF_BYCOMMAND) == 0)) + { + T* pT = static_cast(this); + pT; // avoid level 4 warning + SecureHelper::strncpy_x(m_szNoEntries, _countof(m_szNoEntries), pT->GetMRUEmptyText(), _TRUNCATE); + } + } + + int GetMaxEntries() const + { + return m_nMaxEntries; + } + + void SetMaxEntries(int nMaxEntries) + { + ATLASSERT(nMaxEntries >= m_nMaxEntries_Min && nMaxEntries <= m_nMaxEntries_Max); + if(nMaxEntries < m_nMaxEntries_Min) + nMaxEntries = m_nMaxEntries_Min; + else if(nMaxEntries > m_nMaxEntries_Max) + nMaxEntries = m_nMaxEntries_Max; + m_nMaxEntries = nMaxEntries; + } + + int GetMaxItemLength() const + { + return m_cchMaxItemLen; + } + + void SetMaxItemLength(int cchMaxLen) + { + ATLASSERT((cchMaxLen >= m_cchMaxItemLen_Min && cchMaxLen <= m_cchMaxItemLen_Max) || cchMaxLen == -1); + if(cchMaxLen != -1) + { + if(cchMaxLen < m_cchMaxItemLen_Min) + cchMaxLen = m_cchMaxItemLen_Min; + else if(cchMaxLen > m_cchMaxItemLen_Max) + cchMaxLen = m_cchMaxItemLen_Max; + } + m_cchMaxItemLen = cchMaxLen; + T* pT = static_cast(this); + pT->UpdateMenu(); + } + +// Operations + BOOL AddToList(LPCTSTR lpstrDocName) + { + _DocEntry de; + errno_t nRet = SecureHelper::strncpy_x(de.szDocName, _countof(de.szDocName), lpstrDocName, _TRUNCATE); + if(nRet != 0 && nRet != STRUNCATE) + return FALSE; + + for(int i = 0; i < m_arrDocs.GetSize(); i++) + { + if(lstrcmpi(m_arrDocs[i].szDocName, lpstrDocName) == 0) + { + m_arrDocs.RemoveAt(i); + break; + } + } + + if(m_arrDocs.GetSize() == m_nMaxEntries) + m_arrDocs.RemoveAt(0); + + BOOL bRet = m_arrDocs.Add(de); + if(bRet) + { + T* pT = static_cast(this); + bRet = pT->UpdateMenu(); + } + return bRet; + } + + // This function is deprecated because it is not safe. + // Use the version below that accepts the buffer length. +#if (_MSC_VER >= 1300) + __declspec(deprecated) +#endif + BOOL GetFromList(int /*nItemID*/, LPTSTR /*lpstrDocName*/) + { + ATLASSERT(FALSE); + return FALSE; + } + + BOOL GetFromList(int nItemID, LPTSTR lpstrDocName, int cchLength) + { + int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1; + if(nIndex < 0 || nIndex >= m_arrDocs.GetSize()) + return FALSE; + if(lstrlen(m_arrDocs[nIndex].szDocName) >= cchLength) + return FALSE; + SecureHelper::strcpy_x(lpstrDocName, cchLength, m_arrDocs[nIndex].szDocName); + + return TRUE; + } + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + BOOL GetFromList(int nItemID, _CSTRING_NS::CString& strDocName) + { + int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1; + if(nIndex < 0 || nIndex >= m_arrDocs.GetSize()) + return FALSE; + strDocName = m_arrDocs[nIndex].szDocName; + return TRUE; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + + BOOL RemoveFromList(int nItemID) + { + int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1; + BOOL bRet = m_arrDocs.RemoveAt(nIndex); + if(bRet) + { + T* pT = static_cast(this); + bRet = pT->UpdateMenu(); + } + return bRet; + } + + BOOL MoveToTop(int nItemID) + { + int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1; + if(nIndex < 0 || nIndex >= m_arrDocs.GetSize()) + return FALSE; + _DocEntry de; + de = m_arrDocs[nIndex]; + m_arrDocs.RemoveAt(nIndex); + BOOL bRet = m_arrDocs.Add(de); + if(bRet) + { + T* pT = static_cast(this); + bRet = pT->UpdateMenu(); + } + return bRet; + } + + BOOL ReadFromRegistry(LPCTSTR lpstrRegKey) + { + T* pT = static_cast(this); + ATL::CRegKey rkParent; + ATL::CRegKey rk; + + LONG lRet = rkParent.Open(HKEY_CURRENT_USER, lpstrRegKey); + if(lRet != ERROR_SUCCESS) + return FALSE; + lRet = rk.Open(rkParent, pT->GetRegKeyName()); + if(lRet != ERROR_SUCCESS) + return FALSE; + + DWORD dwRet = 0; +#if (_ATL_VER >= 0x0700) + lRet = rk.QueryDWORDValue(pT->GetRegCountName(), dwRet); +#else + lRet = rk.QueryValue(dwRet, pT->GetRegCountName()); +#endif + if(lRet != ERROR_SUCCESS) + return FALSE; + SetMaxEntries(dwRet); + + m_arrDocs.RemoveAll(); + + TCHAR szRetString[t_cchItemLen] = { 0 }; + _DocEntry de; + + for(int nItem = m_nMaxEntries; nItem > 0; nItem--) + { + TCHAR szBuff[m_cchItemNameLen] = { 0 }; + SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem); +#if (_ATL_VER >= 0x0700) + ULONG ulCount = t_cchItemLen; + lRet = rk.QueryStringValue(szBuff, szRetString, &ulCount); +#else + DWORD dwCount = t_cchItemLen * sizeof(TCHAR); + lRet = rk.QueryValue(szRetString, szBuff, &dwCount); +#endif + if(lRet == ERROR_SUCCESS) + { + SecureHelper::strcpy_x(de.szDocName, _countof(de.szDocName), szRetString); + m_arrDocs.Add(de); + } + } + + rk.Close(); + rkParent.Close(); + + return pT->UpdateMenu(); + } + + BOOL WriteToRegistry(LPCTSTR lpstrRegKey) + { + T* pT = static_cast(this); + pT; // avoid level 4 warning + ATL::CRegKey rkParent; + ATL::CRegKey rk; + + LONG lRet = rkParent.Create(HKEY_CURRENT_USER, lpstrRegKey); + if(lRet != ERROR_SUCCESS) + return FALSE; + lRet = rk.Create(rkParent, pT->GetRegKeyName()); + if(lRet != ERROR_SUCCESS) + return FALSE; + +#if (_ATL_VER >= 0x0700) + lRet = rk.SetDWORDValue(pT->GetRegCountName(), m_nMaxEntries); +#else + lRet = rk.SetValue(m_nMaxEntries, pT->GetRegCountName()); +#endif + ATLASSERT(lRet == ERROR_SUCCESS); + + // set new values + int nItem; + for(nItem = m_arrDocs.GetSize(); nItem > 0; nItem--) + { + TCHAR szBuff[m_cchItemNameLen] = { 0 }; + SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem); + TCHAR szDocName[t_cchItemLen] = { 0 }; + GetFromList(t_nFirstID + nItem - 1, szDocName, t_cchItemLen); +#if (_ATL_VER >= 0x0700) + lRet = rk.SetStringValue(szBuff, szDocName); +#else + lRet = rk.SetValue(szDocName, szBuff); +#endif + ATLASSERT(lRet == ERROR_SUCCESS); + } + + // delete unused keys + for(nItem = m_arrDocs.GetSize() + 1; nItem < m_nMaxEntries_Max; nItem++) + { + TCHAR szBuff[m_cchItemNameLen] = { 0 }; + SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem); + rk.DeleteValue(szBuff); + } + + rk.Close(); + rkParent.Close(); + + return TRUE; + } + +// Implementation + BOOL UpdateMenu() + { + if(m_hMenu == NULL) + return FALSE; + ATLASSERT(::IsMenu(m_hMenu)); + + int nItems = ::GetMenuItemCount(m_hMenu); + int nInsertPoint; + for(nInsertPoint = 0; nInsertPoint < nItems; nInsertPoint++) + { + CMenuItemInfo mi; + mi.fMask = MIIM_ID; + ::GetMenuItemInfo(m_hMenu, nInsertPoint, TRUE, &mi); + if (mi.wID == t_nFirstID) + break; + } + ATLASSERT(nInsertPoint < nItems && "You need a menu item with an ID = t_nFirstID"); + + int nItem; + for(nItem = t_nFirstID; nItem < t_nFirstID + m_nMaxEntries; nItem++) + { + // keep the first one as an insertion point + if (nItem != t_nFirstID) + ::DeleteMenu(m_hMenu, nItem, MF_BYCOMMAND); + } + + TCHAR szItemText[t_cchItemLen + 6] = { 0 }; // add space for &, 2 digits, and a space + int nSize = m_arrDocs.GetSize(); + nItem = 0; + if(nSize > 0) + { + for(nItem = 0; nItem < nSize; nItem++) + { + if(m_cchMaxItemLen == -1) + { + SecureHelper::wsprintf_x(szItemText, t_cchItemLen + 6, _T("&%i %s"), nItem + 1, m_arrDocs[nSize - 1 - nItem].szDocName); + } + else + { + TCHAR szBuff[t_cchItemLen] = { 0 }; + T* pT = static_cast(this); + pT; // avoid level 4 warning + bool bRet = pT->CompactDocumentName(szBuff, m_arrDocs[nSize - 1 - nItem].szDocName, m_cchMaxItemLen); + bRet; // avoid level 4 warning + ATLASSERT(bRet); + SecureHelper::wsprintf_x(szItemText, t_cchItemLen + 6, _T("&%i %s"), nItem + 1, szBuff); + } + ::InsertMenu(m_hMenu, nInsertPoint + nItem, MF_BYPOSITION | MF_STRING, t_nFirstID + nItem, szItemText); + } + } + else // empty + { + ::InsertMenu(m_hMenu, nInsertPoint, MF_BYPOSITION | MF_STRING, t_nFirstID, m_szNoEntries); + ::EnableMenuItem(m_hMenu, t_nFirstID, MF_GRAYED); + nItem++; + } + ::DeleteMenu(m_hMenu, nInsertPoint + nItem, MF_BYPOSITION); + + return TRUE; + } + +// Overrideables + // override to provide a different method of compacting document names + static bool CompactDocumentName(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen) + { + return AtlCompactPath(lpstrOut, lpstrIn, cchLen); + } + + static LPCTSTR GetRegKeyName() + { + return _T("Recent Document List"); + } + + static LPCTSTR GetRegCountName() + { + return _T("DocumentCount"); + } + + static LPCTSTR GetRegItemName() + { + // Note: This string is a format string used with wsprintf(). + // Resulting formatted string must be m_cchItemNameLen or less + // characters long, including the terminating null character. + return _T("Document%i"); + } + + static LPCTSTR GetMRUEmptyText() + { + return _WTL_MRUEMPTY_TEXT; + } +}; + +class CRecentDocumentList : public CRecentDocumentListBase +{ +public: +// nothing here +}; + +#endif // _WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CFindFile - file search helper class + +class CFindFile +{ +public: +// Data members + WIN32_FIND_DATA m_fd; + TCHAR m_lpszRoot[MAX_PATH]; + TCHAR m_chDirSeparator; + HANDLE m_hFind; + BOOL m_bFound; + +// Constructor/destructor + CFindFile() : m_hFind(NULL), m_chDirSeparator(_T('\\')), m_bFound(FALSE) + { } + + ~CFindFile() + { + Close(); + } + +// Attributes + ULONGLONG GetFileSize() const + { + ATLASSERT(m_hFind != NULL); + + ULARGE_INTEGER nFileSize = { 0 }; + + if(m_bFound) + { + nFileSize.LowPart = m_fd.nFileSizeLow; + nFileSize.HighPart = m_fd.nFileSizeHigh; + } + else + { + nFileSize.QuadPart = 0; + } + + return nFileSize.QuadPart; + } + + BOOL GetFileName(LPTSTR lpstrFileName, int cchLength) const + { + ATLASSERT(m_hFind != NULL); + if(lstrlen(m_fd.cFileName) >= cchLength) + return FALSE; + + if(m_bFound) + SecureHelper::strcpy_x(lpstrFileName, cchLength, m_fd.cFileName); + + return m_bFound; + } + + BOOL GetFilePath(LPTSTR lpstrFilePath, int cchLength) const + { + ATLASSERT(m_hFind != NULL); + + int nLen = lstrlen(m_lpszRoot); +#ifndef _WIN32_WCE + ATLASSERT(nLen > 0); + if(nLen == 0) + return FALSE; + + bool bAddSep = (m_lpszRoot[nLen - 1] != _T('\\') && m_lpszRoot[nLen - 1] !=_T('/')); +#else // CE specific + // allow diskless devices (nLen == 0) + bool bAddSep = ((nLen == 0) || (m_lpszRoot[nLen - 1] != _T('\\') && m_lpszRoot[nLen - 1] !=_T('/'))); +#endif // _WIN32_WCE + + if((lstrlen(m_lpszRoot) + (bAddSep ? 1 : 0)) >= cchLength) + return FALSE; + + SecureHelper::strcpy_x(lpstrFilePath, cchLength, m_lpszRoot); + + if(bAddSep) + { + TCHAR szSeparator[2] = { m_chDirSeparator, 0 }; + SecureHelper::strcat_x(lpstrFilePath, cchLength, szSeparator); + } + + SecureHelper::strcat_x(lpstrFilePath, cchLength, m_fd.cFileName); + + return TRUE; + } + +#ifndef _WIN32_WCE + BOOL GetFileTitle(LPTSTR lpstrFileTitle, int cchLength) const + { + ATLASSERT(m_hFind != NULL); + + TCHAR szBuff[MAX_PATH] = { 0 }; + if(!GetFileName(szBuff, MAX_PATH)) + return FALSE; + + if(lstrlen(szBuff) >= cchLength || cchLength < 1) + return FALSE; + + // find the last dot + LPTSTR pstrDot = (LPTSTR)_cstrrchr(szBuff, _T('.')); + if(pstrDot != NULL) + *pstrDot = 0; + + SecureHelper::strcpy_x(lpstrFileTitle, cchLength, szBuff); + + return TRUE; + } +#endif // !_WIN32_WCE + + BOOL GetFileURL(LPTSTR lpstrFileURL, int cchLength) const + { + ATLASSERT(m_hFind != NULL); + + TCHAR szBuff[MAX_PATH] = { 0 }; + if(!GetFilePath(szBuff, MAX_PATH)) + return FALSE; + LPCTSTR lpstrFileURLPrefix = _T("file://"); + if(lstrlen(szBuff) + lstrlen(lpstrFileURLPrefix) >= cchLength) + return FALSE; + SecureHelper::strcpy_x(lpstrFileURL, cchLength, lpstrFileURLPrefix); + SecureHelper::strcat_x(lpstrFileURL, cchLength, szBuff); + + return TRUE; + } + + BOOL GetRoot(LPTSTR lpstrRoot, int cchLength) const + { + ATLASSERT(m_hFind != NULL); + if(lstrlen(m_lpszRoot) >= cchLength) + return FALSE; + + SecureHelper::strcpy_x(lpstrRoot, cchLength, m_lpszRoot); + + return TRUE; + } + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + _CSTRING_NS::CString GetFileName() const + { + ATLASSERT(m_hFind != NULL); + + _CSTRING_NS::CString ret; + + if(m_bFound) + ret = m_fd.cFileName; + return ret; + } + + _CSTRING_NS::CString GetFilePath() const + { + ATLASSERT(m_hFind != NULL); + + _CSTRING_NS::CString strResult = m_lpszRoot; + int nLen = strResult.GetLength(); +#ifndef _WIN32_WCE + ATLASSERT(nLen > 0); + if(nLen == 0) + return strResult; + + if((strResult[nLen - 1] != _T('\\')) && (strResult[nLen - 1] != _T('/'))) +#else // CE specific + // allow diskless devices (nLen == 0) + if((nLen == 0) || ((strResult[nLen - 1] != _T('\\')) && (strResult[nLen - 1] != _T('/')))) +#endif // _WIN32_WCE + strResult += m_chDirSeparator; + strResult += GetFileName(); + return strResult; + } + +#ifndef _WIN32_WCE + _CSTRING_NS::CString GetFileTitle() const + { + ATLASSERT(m_hFind != NULL); + + _CSTRING_NS::CString strResult; + GetFileTitle(strResult.GetBuffer(MAX_PATH), MAX_PATH); + strResult.ReleaseBuffer(); + + return strResult; + } +#endif // !_WIN32_WCE + + _CSTRING_NS::CString GetFileURL() const + { + ATLASSERT(m_hFind != NULL); + + _CSTRING_NS::CString strResult("file://"); + strResult += GetFilePath(); + return strResult; + } + + _CSTRING_NS::CString GetRoot() const + { + ATLASSERT(m_hFind != NULL); + + _CSTRING_NS::CString str = m_lpszRoot; + return str; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + + BOOL GetLastWriteTime(FILETIME* pTimeStamp) const + { + ATLASSERT(m_hFind != NULL); + ATLASSERT(pTimeStamp != NULL); + + if(m_bFound && pTimeStamp != NULL) + { + *pTimeStamp = m_fd.ftLastWriteTime; + return TRUE; + } + + return FALSE; + } + + BOOL GetLastAccessTime(FILETIME* pTimeStamp) const + { + ATLASSERT(m_hFind != NULL); + ATLASSERT(pTimeStamp != NULL); + + if(m_bFound && pTimeStamp != NULL) + { + *pTimeStamp = m_fd.ftLastAccessTime; + return TRUE; + } + + return FALSE; + } + + BOOL GetCreationTime(FILETIME* pTimeStamp) const + { + ATLASSERT(m_hFind != NULL); + + if(m_bFound && pTimeStamp != NULL) + { + *pTimeStamp = m_fd.ftCreationTime; + return TRUE; + } + + return FALSE; + } + + BOOL MatchesMask(DWORD dwMask) const + { + ATLASSERT(m_hFind != NULL); + + if(m_bFound) + return ((m_fd.dwFileAttributes & dwMask) != 0); + + return FALSE; + } + + BOOL IsDots() const + { + ATLASSERT(m_hFind != NULL); + + // return TRUE if the file name is "." or ".." and + // the file is a directory + + BOOL bResult = FALSE; + if(m_bFound && IsDirectory()) + { + if(m_fd.cFileName[0] == _T('.') && (m_fd.cFileName[1] == _T('\0') || (m_fd.cFileName[1] == _T('.') && m_fd.cFileName[2] == _T('\0')))) + bResult = TRUE; + } + + return bResult; + } + + BOOL IsReadOnly() const + { + return MatchesMask(FILE_ATTRIBUTE_READONLY); + } + + BOOL IsDirectory() const + { + return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); + } + + BOOL IsCompressed() const + { + return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); + } + + BOOL IsSystem() const + { + return MatchesMask(FILE_ATTRIBUTE_SYSTEM); + } + + BOOL IsHidden() const + { + return MatchesMask(FILE_ATTRIBUTE_HIDDEN); + } + + BOOL IsTemporary() const + { + return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); + } + + BOOL IsNormal() const + { + return MatchesMask(FILE_ATTRIBUTE_NORMAL); + } + + BOOL IsArchived() const + { + return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); + } + +// Operations + BOOL FindFile(LPCTSTR pstrName = NULL) + { + Close(); + + if(pstrName == NULL) + { + pstrName = _T("*.*"); + } + else if(lstrlen(pstrName) >= MAX_PATH) + { + ATLASSERT(FALSE); + return FALSE; + } + + SecureHelper::strcpy_x(m_fd.cFileName, _countof(m_fd.cFileName), pstrName); + + m_hFind = ::FindFirstFile(pstrName, &m_fd); + + if(m_hFind == INVALID_HANDLE_VALUE) + return FALSE; + +#ifndef _WIN32_WCE + bool bFullPath = (::GetFullPathName(pstrName, MAX_PATH, m_lpszRoot, NULL) != 0); +#else // CE specific + errno_t nRet = SecureHelper::strncpy_x(m_lpszRoot, _countof(m_lpszRoot), pstrName, _TRUNCATE); + bool bFullPath = (nRet == 0 || nRet == STRUNCATE); +#endif // _WIN32_WCE + + // passed name isn't a valid path but was found by the API + ATLASSERT(bFullPath); + if(!bFullPath) + { + Close(); + ::SetLastError(ERROR_INVALID_NAME); + return FALSE; + } + else + { + // find the last forward or backward whack + LPTSTR pstrBack = (LPTSTR)_cstrrchr(m_lpszRoot, _T('\\')); + LPTSTR pstrFront = (LPTSTR)_cstrrchr(m_lpszRoot, _T('/')); + + if(pstrFront != NULL || pstrBack != NULL) + { + if(pstrFront == NULL) + pstrFront = m_lpszRoot; + if(pstrBack == NULL) + pstrBack = m_lpszRoot; + + // from the start to the last whack is the root + + if(pstrFront >= pstrBack) + *pstrFront = _T('\0'); + else + *pstrBack = _T('\0'); + } + } + + m_bFound = TRUE; + + return TRUE; + } + + BOOL FindNextFile() + { + ATLASSERT(m_hFind != NULL); + + if(m_hFind == NULL) + return FALSE; + + if(!m_bFound) + return FALSE; + + m_bFound = ::FindNextFile(m_hFind, &m_fd); + + return m_bFound; + } + + void Close() + { + m_bFound = FALSE; + + if(m_hFind != NULL && m_hFind != INVALID_HANDLE_VALUE) + { + ::FindClose(m_hFind); + m_hFind = NULL; + } + } + +// Helper + static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch) + { +#ifdef _ATL_MIN_CRT + const TCHAR* lpsz = NULL; + while (*p != 0) + { + if (*p == ch) + lpsz = p; + p = ::CharNext(p); + } + return lpsz; +#else // !_ATL_MIN_CRT + return _tcsrchr(p, ch); +#endif // !_ATL_MIN_CRT + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Global functions for loading resources + +inline HACCEL AtlLoadAccelerators(ATL::_U_STRINGorID table) +{ + return ::LoadAccelerators(ModuleHelper::GetResourceInstance(), table.m_lpstr); +} + +inline HMENU AtlLoadMenu(ATL::_U_STRINGorID menu) +{ + return ::LoadMenu(ModuleHelper::GetResourceInstance(), menu.m_lpstr); +} + +inline HBITMAP AtlLoadBitmap(ATL::_U_STRINGorID bitmap) +{ + return ::LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr); +} + +#ifdef OEMRESOURCE +inline HBITMAP AtlLoadSysBitmap(ATL::_U_STRINGorID bitmap) +{ +#ifdef _DEBUG + WORD wID = (WORD)bitmap.m_lpstr; + ATLASSERT(wID >= 32734 && wID <= 32767); +#endif // _DEBUG + return ::LoadBitmap(NULL, bitmap.m_lpstr); +} +#endif // OEMRESOURCE + +inline HCURSOR AtlLoadCursor(ATL::_U_STRINGorID cursor) +{ + return ::LoadCursor(ModuleHelper::GetResourceInstance(), cursor.m_lpstr); +} + +inline HCURSOR AtlLoadSysCursor(LPCTSTR lpCursorName) +{ +#if (WINVER >= 0x0500) + ATLASSERT(lpCursorName == IDC_ARROW || lpCursorName == IDC_IBEAM || lpCursorName == IDC_WAIT || + lpCursorName == IDC_CROSS || lpCursorName == IDC_UPARROW || lpCursorName == IDC_SIZE || + lpCursorName == IDC_ICON || lpCursorName == IDC_SIZENWSE || lpCursorName == IDC_SIZENESW || + lpCursorName == IDC_SIZEWE || lpCursorName == IDC_SIZENS || lpCursorName == IDC_SIZEALL || + lpCursorName == IDC_NO || lpCursorName == IDC_APPSTARTING || lpCursorName == IDC_HELP || + lpCursorName == IDC_HAND); +#else // !(WINVER >= 0x0500) + ATLASSERT(lpCursorName == IDC_ARROW || lpCursorName == IDC_IBEAM || lpCursorName == IDC_WAIT || + lpCursorName == IDC_CROSS || lpCursorName == IDC_UPARROW || lpCursorName == IDC_SIZE || + lpCursorName == IDC_ICON || lpCursorName == IDC_SIZENWSE || lpCursorName == IDC_SIZENESW || + lpCursorName == IDC_SIZEWE || lpCursorName == IDC_SIZENS || lpCursorName == IDC_SIZEALL || + lpCursorName == IDC_NO || lpCursorName == IDC_APPSTARTING || lpCursorName == IDC_HELP); +#endif // !(WINVER >= 0x0500) + return ::LoadCursor(NULL, lpCursorName); +} + +inline HICON AtlLoadIcon(ATL::_U_STRINGorID icon) +{ + return ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr); +} + +#ifndef _WIN32_WCE +inline HICON AtlLoadSysIcon(LPCTSTR lpIconName) +{ +#if (WINVER >= 0x0600) + ATLASSERT(lpIconName == IDI_APPLICATION || lpIconName == IDI_ASTERISK || lpIconName == IDI_EXCLAMATION || + lpIconName == IDI_HAND || lpIconName == IDI_QUESTION || lpIconName == IDI_WINLOGO || + lpIconName == IDI_SHIELD); +#else // !(WINVER >= 0x0600) + ATLASSERT(lpIconName == IDI_APPLICATION || lpIconName == IDI_ASTERISK || lpIconName == IDI_EXCLAMATION || + lpIconName == IDI_HAND || lpIconName == IDI_QUESTION || lpIconName == IDI_WINLOGO); +#endif // !(WINVER >= 0x0600) + return ::LoadIcon(NULL, lpIconName); +} +#endif // !_WIN32_WCE + +inline HBITMAP AtlLoadBitmapImage(ATL::_U_STRINGorID bitmap, UINT fuLoad = LR_DEFAULTCOLOR) +{ + return (HBITMAP)::LoadImage(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr, IMAGE_BITMAP, 0, 0, fuLoad); +} + +inline HCURSOR AtlLoadCursorImage(ATL::_U_STRINGorID cursor, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0) +{ + return (HCURSOR)::LoadImage(ModuleHelper::GetResourceInstance(), cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad); +} + +inline HICON AtlLoadIconImage(ATL::_U_STRINGorID icon, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0) +{ + return (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad); +} + +#ifdef OEMRESOURCE +inline HBITMAP AtlLoadSysBitmapImage(WORD wBitmapID, UINT fuLoad = LR_DEFAULTCOLOR) +{ + ATLASSERT(wBitmapID >= 32734 && wBitmapID <= 32767); + ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0); // this one doesn't load from a file + return (HBITMAP)::LoadImage(NULL, MAKEINTRESOURCE(wBitmapID), IMAGE_BITMAP, 0, 0, fuLoad); +} +#endif // OEMRESOURCE + +inline HCURSOR AtlLoadSysCursorImage(ATL::_U_STRINGorID cursor, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0) +{ +#ifdef _DEBUG + WORD wID = (WORD)cursor.m_lpstr; + ATLASSERT((wID >= 32512 && wID <= 32516) || (wID >= 32640 && wID <= 32648) || (wID == 32650) || (wID == 32651)); + ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0); // this one doesn't load from a file +#endif // _DEBUG + return (HCURSOR)::LoadImage(NULL, cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad); +} + +inline HICON AtlLoadSysIconImage(ATL::_U_STRINGorID icon, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0) +{ +#ifdef _DEBUG + WORD wID = (WORD)icon.m_lpstr; + ATLASSERT(wID >= 32512 && wID <= 32517); + ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0); // this one doesn't load from a file +#endif // _DEBUG + return (HICON)::LoadImage(NULL, icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad); +} + +#if (_ATL_VER < 0x0700) +inline int AtlLoadString(UINT uID, LPTSTR lpBuffer, int nBufferMax) +{ + return ::LoadString(_Module.GetResourceInstance(), uID, lpBuffer, nBufferMax); +} +#endif // (_ATL_VER < 0x0700) + +#ifdef _WIN32_WCE // CE only direct access to the resource +inline LPCTSTR AtlLoadString(UINT uID) +{ + LPCTSTR s = (LPCTSTR)::LoadString(ModuleHelper::GetResourceInstance(), uID, NULL, 0); +#ifdef DEBUG // Check for null-termination + if(s != NULL) + // Note: RC -n compiles null-terminated resource strings + ATLASSERT(s[*((WORD*)s -1) - 1] == L'\0'); +#endif + return s; +} +#endif // _WIN32_WCE + +inline bool AtlLoadString(UINT uID, BSTR& bstrText) +{ + USES_CONVERSION; + ATLASSERT(bstrText == NULL); + + LPTSTR lpstrText = NULL; + int nRes = 0; + for(int nLen = 256; ; nLen *= 2) + { + ATLTRY(lpstrText = new TCHAR[nLen]); + if(lpstrText == NULL) + break; + nRes = ::LoadString(ModuleHelper::GetResourceInstance(), uID, lpstrText, nLen); + if(nRes < nLen - 1) + break; + delete [] lpstrText; + lpstrText = NULL; + } + + if(lpstrText != NULL) + { + if(nRes != 0) + bstrText = ::SysAllocString(T2OLE(lpstrText)); + delete [] lpstrText; + } + + return (bstrText != NULL) ? true : false; +} + + +/////////////////////////////////////////////////////////////////////////////// +// Global functions for stock GDI objects + +inline HPEN AtlGetStockPen(int nPen) +{ +#if (_WIN32_WINNT >= 0x0500) && !defined(_WIN32_WCE) + ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN || nPen == DC_PEN); +#else + ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN); +#endif + return (HPEN)::GetStockObject(nPen); +} + +inline HBRUSH AtlGetStockBrush(int nBrush) +{ +#if (_WIN32_WINNT >= 0x0500) && !defined(_WIN32_WCE) + ATLASSERT((nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH) || nBrush == DC_BRUSH); +#else + ATLASSERT(nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH); +#endif + return (HBRUSH)::GetStockObject(nBrush); +} + +inline HFONT AtlGetStockFont(int nFont) +{ +#ifndef _WIN32_WCE + ATLASSERT((nFont >= OEM_FIXED_FONT && nFont <= SYSTEM_FIXED_FONT) || nFont == DEFAULT_GUI_FONT); +#else // CE specific + ATLASSERT(nFont == SYSTEM_FONT); +#endif // _WIN32_WCE + return (HFONT)::GetStockObject(nFont); +} + +inline HPALETTE AtlGetStockPalette(int nPalette) +{ + ATLASSERT(nPalette == DEFAULT_PALETTE); // the only one supported + return (HPALETTE)::GetStockObject(nPalette); +} + + +/////////////////////////////////////////////////////////////////////////////// +// Global function for compacting a path by replacing parts with ellipsis + +// helper for multi-byte character sets +inline bool _IsDBCSTrailByte(LPCTSTR lpstr, int nChar) +{ +#ifndef _UNICODE + int i = nChar; + for( ; i > 0; i--) + { + if(!::IsDBCSLeadByte(lpstr[i - 1])) + break; + } + return ((nChar > 0) && (((nChar - i) & 1) != 0)); +#else // _UNICODE + lpstr; nChar; + return false; +#endif // _UNICODE +} + +inline bool AtlCompactPath(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen) +{ + ATLASSERT(lpstrOut != NULL); + ATLASSERT(lpstrIn != NULL); + ATLASSERT(cchLen > 0); + + LPCTSTR szEllipsis = _T("..."); + const int cchEndEllipsis = 3; + const int cchMidEllipsis = 4; + + if(lstrlen(lpstrIn) < cchLen) + { + SecureHelper::strcpy_x(lpstrOut, cchLen, lpstrIn); + return true; + } + + lpstrOut[0] = 0; + + // check if the separator is a slash or a backslash + TCHAR chSlash = _T('\\'); + for(LPTSTR lpstr = (LPTSTR)lpstrIn; *lpstr != 0; lpstr = ::CharNext(lpstr)) + { + if((*lpstr == _T('/')) || (*lpstr == _T('\\'))) + chSlash = *lpstr; + } + + // find the filename portion of the path + LPCTSTR lpstrFileName = lpstrIn; + for(LPCTSTR pPath = lpstrIn; *pPath; pPath = ::CharNext(pPath)) + { + if((pPath[0] == _T('\\') || pPath[0] == _T(':') || pPath[0] == _T('/')) + && pPath[1] && pPath[1] != _T('\\') && pPath[1] != _T('/')) + lpstrFileName = pPath + 1; + } + int cchFileName = lstrlen(lpstrFileName); + + // handle just the filename without a path + if(lpstrFileName == lpstrIn && cchLen > cchEndEllipsis) + { + bool bRet = (SecureHelper::strncpy_x(lpstrOut, cchLen, lpstrIn, cchLen - cchEndEllipsis - 1) == 0); + if(bRet) + { +#ifndef _UNICODE + if(_IsDBCSTrailByte(lpstrIn, cchLen - cchEndEllipsis)) + lpstrOut[cchLen - cchEndEllipsis - 1] = 0; +#endif // _UNICODE + SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis); + } + return bRet; + } + + // handle just ellipsis + if((cchLen < (cchMidEllipsis + cchEndEllipsis))) + { + for(int i = 0; i < cchLen - 1; i++) + lpstrOut[i] = ((i + 1) == cchMidEllipsis) ? chSlash : _T('.'); + lpstrOut[cchLen - 1] = 0; + return true; + } + + // calc how much we have to copy + int cchToCopy = cchLen - (cchMidEllipsis + cchFileName) - 1; + + if(cchToCopy < 0) + cchToCopy = 0; + +#ifndef _UNICODE + if(cchToCopy > 0 && _IsDBCSTrailByte(lpstrIn, cchToCopy)) + cchToCopy--; +#endif // _UNICODE + + bool bRet = (SecureHelper::strncpy_x(lpstrOut, cchLen, lpstrIn, cchToCopy) == 0); + if(!bRet) + return false; + + // add ellipsis + SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis); + if(!bRet) + return false; + TCHAR szSlash[2] = { chSlash, 0 }; + SecureHelper::strcat_x(lpstrOut, cchLen, szSlash); + if(!bRet) + return false; + + // add filename (and ellipsis, if needed) + if(cchLen > (cchMidEllipsis + cchFileName)) + { + SecureHelper::strcat_x(lpstrOut, cchLen, lpstrFileName); + } + else + { + cchToCopy = cchLen - cchMidEllipsis - cchEndEllipsis - 1; +#ifndef _UNICODE + if(cchToCopy > 0 && _IsDBCSTrailByte(lpstrFileName, cchToCopy)) + cchToCopy--; +#endif // _UNICODE + bRet = (SecureHelper::strncpy_x(&lpstrOut[cchMidEllipsis], cchLen - cchMidEllipsis, lpstrFileName, cchToCopy) == 0); + if(bRet) + SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis); + } + + return bRet; +} + +}; // namespace WTL + +#endif // __ATLMISC_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlprint.h b/Client/Client/GUI/BKWin/wtl/atlprint.h new file mode 100644 index 00000000..db30a06a --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlprint.h @@ -0,0 +1,1110 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLPRINT_H__ +#define __ATLPRINT_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifdef _WIN32_WCE + #error atlprint.h is not supported on Windows CE +#endif + +#ifndef __ATLAPP_H__ + #error atlprint.h requires atlapp.h to be included first +#endif + +#ifndef __ATLWIN_H__ + #error atlprint.h requires atlwin.h to be included first +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CPrinterInfo +// CPrinterT +// CDevModeT +// CPrinterDC +// CPrintJobInfo +// CPrintJob +// CPrintPreview +// CPrintPreviewWindowImpl +// CPrintPreviewWindow +// CZoomPrintPreviewWindowImpl +// CZoomPrintPreviewWindow + +namespace WTL +{ + +/////////////////////////////////////////////////////////////////////////////// +// CPrinterInfo - This class wraps all of the PRINTER_INFO_* structures +// and provided by ::GetPrinter. + +template +class _printer_info +{ +public: + typedef void infotype; +}; + +template <> class _printer_info<1> { public: typedef PRINTER_INFO_1 infotype; }; +template <> class _printer_info<2> { public: typedef PRINTER_INFO_2 infotype; }; +template <> class _printer_info<3> { public: typedef PRINTER_INFO_3 infotype; }; +template <> class _printer_info<4> { public: typedef PRINTER_INFO_4 infotype; }; +template <> class _printer_info<5> { public: typedef PRINTER_INFO_5 infotype; }; +template <> class _printer_info<6> { public: typedef PRINTER_INFO_6 infotype; }; +template <> class _printer_info<7> { public: typedef PRINTER_INFO_7 infotype; }; +// these are not in the old (vc6.0) headers +#ifdef _ATL_USE_NEW_PRINTER_INFO +template <> class _printer_info<8> { public: typedef PRINTER_INFO_8 infotype; }; +template <> class _printer_info<9> { public: typedef PRINTER_INFO_9 infotype; }; +#endif // _ATL_USE_NEW_PRINTER_INFO + + +template +class CPrinterInfo +{ +public: +// Data members + typename _printer_info::infotype* m_pi; + +// Constructor/destructor + CPrinterInfo() : m_pi(NULL) + { } + + CPrinterInfo(HANDLE hPrinter) : m_pi(NULL) + { + GetPrinterInfo(hPrinter); + } + + ~CPrinterInfo() + { + Cleanup(); + } + +// Operations + bool GetPrinterInfo(HANDLE hPrinter) + { + Cleanup(); + return GetPrinterInfoHelper(hPrinter, (BYTE**)&m_pi, t_nInfo); + } + +// Implementation + void Cleanup() + { + delete [] (BYTE*)m_pi; + m_pi = NULL; + } + + static bool GetPrinterInfoHelper(HANDLE hPrinter, BYTE** pi, int nIndex) + { + ATLASSERT(pi != NULL); + DWORD dw = 0; + BYTE* pb = NULL; + ::GetPrinter(hPrinter, nIndex, NULL, 0, &dw); + if (dw > 0) + { + ATLTRY(pb = new BYTE[dw]); + if (pb != NULL) + { + memset(pb, 0, dw); + DWORD dwNew; + if (!::GetPrinter(hPrinter, nIndex, pb, dw, &dwNew)) + { + delete [] pb; + pb = NULL; + } + } + } + *pi = pb; + return (pb != NULL); + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CPrinter - Wrapper class for a HANDLE to a printer + +template +class CPrinterT +{ +public: +// Data members + HANDLE m_hPrinter; + +// Constructor/destructor + CPrinterT(HANDLE hPrinter = NULL) : m_hPrinter(hPrinter) + { } + + ~CPrinterT() + { + ClosePrinter(); + } + +// Operations + CPrinterT& operator =(HANDLE hPrinter) + { + if (hPrinter != m_hPrinter) + { + ClosePrinter(); + m_hPrinter = hPrinter; + } + return *this; + } + + bool IsNull() const { return (m_hPrinter == NULL); } + + bool OpenPrinter(HANDLE hDevNames, const DEVMODE* pDevMode = NULL) + { + bool b = false; + DEVNAMES* pdn = (DEVNAMES*)::GlobalLock(hDevNames); + if (pdn != NULL) + { + LPTSTR lpszPrinterName = (LPTSTR)pdn + pdn->wDeviceOffset; + b = OpenPrinter(lpszPrinterName, pDevMode); + ::GlobalUnlock(hDevNames); + } + return b; + } + + bool OpenPrinter(LPCTSTR lpszPrinterName, const DEVMODE* pDevMode = NULL) + { + ClosePrinter(); + PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE }; + ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs); + + return (m_hPrinter != NULL); + } + + bool OpenPrinter(LPCTSTR lpszPrinterName, PRINTER_DEFAULTS* pprintdefs) + { + ClosePrinter(); + ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, pprintdefs); + return (m_hPrinter != NULL); + } + + bool OpenDefaultPrinter(const DEVMODE* pDevMode = NULL) + { + ClosePrinter(); + const int cchBuff = 512; + TCHAR buffer[cchBuff]; + buffer[0] = 0; + ::GetProfileString(_T("windows"), _T("device"), _T(",,,"), buffer, cchBuff); + int nLen = lstrlen(buffer); + if (nLen != 0) + { + LPTSTR lpsz = buffer; + while (*lpsz) + { + if (*lpsz == _T(',')) + { + *lpsz = 0; + break; + } + lpsz = CharNext(lpsz); + } + PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE }; + ::OpenPrinter(buffer, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs); + } + return m_hPrinter != NULL; + } + + void ClosePrinter() + { + if (m_hPrinter != NULL) + { + if (t_bManaged) + ::ClosePrinter(m_hPrinter); + m_hPrinter = NULL; + } + } + + bool PrinterProperties(HWND hWnd = NULL) + { + if (hWnd == NULL) + hWnd = ::GetActiveWindow(); + return !!::PrinterProperties(hWnd, m_hPrinter); + } + + HANDLE CopyToHDEVNAMES() const + { + HANDLE h = NULL; + CPrinterInfo<5> pinfon5; + CPrinterInfo<2> pinfon2; + LPTSTR lpszPrinterName = NULL; + // Some printers fail for PRINTER_INFO_5 in some situations + if (pinfon5.GetPrinterInfo(m_hPrinter)) + lpszPrinterName = pinfon5.m_pi->pPrinterName; + else if (pinfon2.GetPrinterInfo(m_hPrinter)) + lpszPrinterName = pinfon2.m_pi->pPrinterName; + if (lpszPrinterName != NULL) + { + int nLen = sizeof(DEVNAMES) + (lstrlen(lpszPrinterName) + 1) * sizeof(TCHAR); + h = ::GlobalAlloc(GMEM_MOVEABLE, nLen); + BYTE* pv = (BYTE*)::GlobalLock(h); + DEVNAMES* pdev = (DEVNAMES*)pv; + if (pv != NULL) + { + memset(pv, 0, nLen); + pdev->wDeviceOffset = sizeof(DEVNAMES) / sizeof(TCHAR); + pv = pv + sizeof(DEVNAMES); // now points to end + SecureHelper::strcpy_x((LPTSTR)pv, lstrlen(lpszPrinterName) + 1, lpszPrinterName); + ::GlobalUnlock(h); + } + } + return h; + } + + HDC CreatePrinterDC(const DEVMODE* pdm = NULL) const + { + CPrinterInfo<5> pinfo5; + CPrinterInfo<2> pinfo2; + HDC hDC = NULL; + LPTSTR lpszPrinterName = NULL; + // Some printers fail for PRINTER_INFO_5 in some situations + if (pinfo5.GetPrinterInfo(m_hPrinter)) + lpszPrinterName = pinfo5.m_pi->pPrinterName; + else if (pinfo2.GetPrinterInfo(m_hPrinter)) + lpszPrinterName = pinfo2.m_pi->pPrinterName; + if (lpszPrinterName != NULL) + hDC = ::CreateDC(NULL, lpszPrinterName, NULL, pdm); + return hDC; + } + + HDC CreatePrinterIC(const DEVMODE* pdm = NULL) const + { + CPrinterInfo<5> pinfo5; + CPrinterInfo<2> pinfo2; + HDC hDC = NULL; + LPTSTR lpszPrinterName = NULL; + // Some printers fail for PRINTER_INFO_5 in some situations + if (pinfo5.GetPrinterInfo(m_hPrinter)) + lpszPrinterName = pinfo5.m_pi->pPrinterName; + else if (pinfo2.GetPrinterInfo(m_hPrinter)) + lpszPrinterName = pinfo2.m_pi->pPrinterName; + if (lpszPrinterName != NULL) + hDC = ::CreateIC(NULL, lpszPrinterName, NULL, pdm); + return hDC; + } + + void Attach(HANDLE hPrinter) + { + ClosePrinter(); + m_hPrinter = hPrinter; + } + + HANDLE Detach() + { + HANDLE hPrinter = m_hPrinter; + m_hPrinter = NULL; + return hPrinter; + } + + operator HANDLE() const { return m_hPrinter; } +}; + +typedef CPrinterT CPrinterHandle; +typedef CPrinterT CPrinter; + + +/////////////////////////////////////////////////////////////////////////////// +// CDevMode - Wrapper class for DEVMODE + +template +class CDevModeT +{ +public: +// Data members + HANDLE m_hDevMode; + DEVMODE* m_pDevMode; + +// Constructor/destructor + CDevModeT(HANDLE hDevMode = NULL) : m_hDevMode(hDevMode) + { + m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL; + } + + ~CDevModeT() + { + Cleanup(); + } + +// Operations + CDevModeT& operator =(HANDLE hDevMode) + { + Attach(hDevMode); + return *this; + } + + void Attach(HANDLE hDevModeNew) + { + Cleanup(); + m_hDevMode = hDevModeNew; + m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL; + } + + HANDLE Detach() + { + if (m_hDevMode != NULL) + ::GlobalUnlock(m_hDevMode); + HANDLE hDevMode = m_hDevMode; + m_hDevMode = NULL; + return hDevMode; + } + + bool IsNull() const { return (m_hDevMode == NULL); } + + bool CopyFromPrinter(HANDLE hPrinter) + { + CPrinterInfo<2> pinfo; + bool b = pinfo.GetPrinterInfo(hPrinter); + if (b) + b = CopyFromDEVMODE(pinfo.m_pi->pDevMode); + return b; + } + + bool CopyFromDEVMODE(const DEVMODE* pdm) + { + if (pdm == NULL) + return false; + int nSize = pdm->dmSize + pdm->dmDriverExtra; + HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize); + if (h != NULL) + { + void* p = ::GlobalLock(h); + SecureHelper::memcpy_x(p, nSize, pdm, nSize); + ::GlobalUnlock(h); + } + Attach(h); + return (h != NULL); + } + + bool CopyFromHDEVMODE(HANDLE hdm) + { + bool b = false; + if (hdm != NULL) + { + DEVMODE* pdm = (DEVMODE*)::GlobalLock(hdm); + b = CopyFromDEVMODE(pdm); + ::GlobalUnlock(hdm); + } + return b; + } + + HANDLE CopyToHDEVMODE() + { + if ((m_hDevMode == NULL) || (m_pDevMode == NULL)) + return NULL; + int nSize = m_pDevMode->dmSize + m_pDevMode->dmDriverExtra; + HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize); + if (h != NULL) + { + void* p = ::GlobalLock(h); + SecureHelper::memcpy_x(p, nSize, m_pDevMode, nSize); + ::GlobalUnlock(h); + } + return h; + } + + // If this devmode was for another printer, this will create a new devmode + // based on the existing devmode, but retargeted at the new printer + bool UpdateForNewPrinter(HANDLE hPrinter) + { + bool bRet = false; + LONG nLen = ::DocumentProperties(NULL, hPrinter, NULL, NULL, NULL, 0); + CTempBuffer buff; + DEVMODE* pdm = buff.AllocateBytes(nLen); + if(pdm != NULL) + { + memset(pdm, 0, nLen); + LONG l = ::DocumentProperties(NULL, hPrinter, NULL, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER); + if (l == IDOK) + bRet = CopyFromDEVMODE(pdm); + } + + return bRet; + } + + bool DocumentProperties(HANDLE hPrinter, HWND hWnd = NULL) + { + CPrinterInfo<1> pi; + pi.GetPrinterInfo(hPrinter); + if (hWnd == NULL) + hWnd = ::GetActiveWindow(); + + bool bRet = false; + LONG nLen = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, NULL, NULL, 0); + CTempBuffer buff; + DEVMODE* pdm = buff.AllocateBytes(nLen); + if(pdm != NULL) + { + memset(pdm, 0, nLen); + LONG l = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER | DM_PROMPT); + if (l == IDOK) + bRet = CopyFromDEVMODE(pdm); + } + + return bRet; + } + + operator HANDLE() const { return m_hDevMode; } + + operator DEVMODE*() const { return m_pDevMode; } + +// Implementation + void Cleanup() + { + if (m_hDevMode != NULL) + { + ::GlobalUnlock(m_hDevMode); + if(t_bManaged) + ::GlobalFree(m_hDevMode); + m_hDevMode = NULL; + } + } +}; + +typedef CDevModeT CDevModeHandle; +typedef CDevModeT CDevMode; + + +/////////////////////////////////////////////////////////////////////////////// +// CPrinterDC + +class CPrinterDC : public CDC +{ +public: +// Constructors/destructor + CPrinterDC() + { + CPrinter printer; + printer.OpenDefaultPrinter(); + Attach(printer.CreatePrinterDC()); + ATLASSERT(m_hDC != NULL); + } + + CPrinterDC(HANDLE hPrinter, const DEVMODE* pdm = NULL) + { + CPrinterHandle p; + p.Attach(hPrinter); + Attach(p.CreatePrinterDC(pdm)); + ATLASSERT(m_hDC != NULL); + } + + ~CPrinterDC() + { + DeleteDC(); + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CPrintJob - Wraps a set of tasks for a specific printer (StartDoc/EndDoc) +// Handles aborting, background printing + +// Defines callbacks used by CPrintJob (not a COM interface) +class ATL_NO_VTABLE IPrintJobInfo +{ +public: + virtual void BeginPrintJob(HDC hDC) = 0; // allocate handles needed, etc. + virtual void EndPrintJob(HDC hDC, bool bAborted) = 0; // free handles, etc. + virtual void PrePrintPage(UINT nPage, HDC hDC) = 0; + virtual bool PrintPage(UINT nPage, HDC hDC) = 0; + virtual void PostPrintPage(UINT nPage, HDC hDC) = 0; + // If you want per page devmodes, return the DEVMODE* to use for nPage. + // You can optimize by only returning a new DEVMODE* when it is different + // from the one for nLastPage, otherwise return NULL. + // When nLastPage==0, the current DEVMODE* will be the default passed to + // StartPrintJob. + // Note: During print preview, nLastPage will always be "0". + virtual DEVMODE* GetNewDevModeForPage(UINT nLastPage, UINT nPage) = 0; + virtual bool IsValidPage(UINT nPage) = 0; +}; + +// Provides a default implementatin for IPrintJobInfo +// Typically, MI'd into a document or view class +class ATL_NO_VTABLE CPrintJobInfo : public IPrintJobInfo +{ +public: + virtual void BeginPrintJob(HDC /*hDC*/) // allocate handles needed, etc + { + } + + virtual void EndPrintJob(HDC /*hDC*/, bool /*bAborted*/) // free handles, etc + { + } + + virtual void PrePrintPage(UINT /*nPage*/, HDC hDC) + { + m_nPJState = ::SaveDC(hDC); + } + + virtual bool PrintPage(UINT /*nPage*/, HDC /*hDC*/) = 0; + + virtual void PostPrintPage(UINT /*nPage*/, HDC hDC) + { + RestoreDC(hDC, m_nPJState); + } + + virtual DEVMODE* GetNewDevModeForPage(UINT /*nLastPage*/, UINT /*nPage*/) + { + return NULL; + } + + virtual bool IsValidPage(UINT /*nPage*/) + { + return true; + } + +// Implementation - data + int m_nPJState; +}; + + +class CPrintJob +{ +public: +// Data members + CPrinterHandle m_printer; + IPrintJobInfo* m_pInfo; + DEVMODE* m_pDefDevMode; + DOCINFO m_docinfo; + int m_nJobID; + bool m_bCancel; + bool m_bComplete; + unsigned long m_nStartPage; + unsigned long m_nEndPage; + +// Constructor/destructor + CPrintJob() : m_nJobID(0), m_bCancel(false), m_bComplete(true) + { } + + ~CPrintJob() + { + ATLASSERT(IsJobComplete()); // premature destruction? + } + +// Operations + bool IsJobComplete() const + { + return m_bComplete; + } + + bool StartPrintJob(bool bBackground, HANDLE hPrinter, DEVMODE* pDefaultDevMode, + IPrintJobInfo* pInfo, LPCTSTR lpszDocName, + unsigned long nStartPage, unsigned long nEndPage, + bool bPrintToFile = false, LPCTSTR lpstrOutputFile = NULL) + { + ATLASSERT(m_bComplete); // previous job not done yet? + if (pInfo == NULL) + return false; + + memset(&m_docinfo, 0, sizeof(m_docinfo)); + m_docinfo.cbSize = sizeof(m_docinfo); + m_docinfo.lpszDocName = lpszDocName; + m_pInfo = pInfo; + m_nStartPage = nStartPage; + m_nEndPage = nEndPage; + m_printer.Attach(hPrinter); + m_pDefDevMode = pDefaultDevMode; + m_bComplete = false; + + if(bPrintToFile) + m_docinfo.lpszOutput = (lpstrOutputFile != NULL) ? lpstrOutputFile : _T("FILE:"); + + if (!bBackground) + { + m_bComplete = true; + return StartHelper(); + } + + // Create a thread and return + DWORD dwThreadID = 0; +#if !defined(_ATL_MIN_CRT) && defined(_MT) + HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))StartProc, this, 0, (UINT*)&dwThreadID); +#else + HANDLE hThread = ::CreateThread(NULL, 0, StartProc, (void*)this, 0, &dwThreadID); +#endif + if (hThread == NULL) + return false; + + ::CloseHandle(hThread); + + return true; + } + +// Implementation + static DWORD WINAPI StartProc(void* p) + { + CPrintJob* pThis = (CPrintJob*)p; + pThis->StartHelper(); + pThis->m_bComplete = true; + return 0; + } + + bool StartHelper() + { + CDC dcPrinter; + dcPrinter.Attach(m_printer.CreatePrinterDC(m_pDefDevMode)); + if (dcPrinter.IsNull()) + return false; + + m_nJobID = ::StartDoc(dcPrinter, &m_docinfo); + if (m_nJobID <= 0) + return false; + + m_pInfo->BeginPrintJob(dcPrinter); + + // print all the pages now + unsigned long nLastPage = 0; + for (unsigned long nPage = m_nStartPage; nPage <= m_nEndPage; nPage++) + { + if (!m_pInfo->IsValidPage(nPage)) + break; + DEVMODE* pdm = m_pInfo->GetNewDevModeForPage(nLastPage, nPage); + if (pdm != NULL) + dcPrinter.ResetDC(pdm); + dcPrinter.StartPage(); + m_pInfo->PrePrintPage(nPage, dcPrinter); + if (!m_pInfo->PrintPage(nPage, dcPrinter)) + m_bCancel = true; + m_pInfo->PostPrintPage(nPage, dcPrinter); + dcPrinter.EndPage(); + if (m_bCancel) + break; + nLastPage = nPage; + } + + m_pInfo->EndPrintJob(dcPrinter, m_bCancel); + if (m_bCancel) + ::AbortDoc(dcPrinter); + else + ::EndDoc(dcPrinter); + m_nJobID = 0; + return true; + } + + // Cancels a print job. Can be called asynchronously. + void CancelPrintJob() + { + m_bCancel = true; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CPrintPreview - Adds print preview support to an existing window + +class CPrintPreview +{ +public: +// Data members + IPrintJobInfo* m_pInfo; + CPrinterHandle m_printer; + CEnhMetaFile m_meta; + DEVMODE* m_pDefDevMode; + DEVMODE* m_pCurDevMode; + SIZE m_sizeCurPhysOffset; + +// Constructor + CPrintPreview() : m_pInfo(NULL), m_pDefDevMode(NULL), m_pCurDevMode(NULL) + { + m_sizeCurPhysOffset.cx = 0; + m_sizeCurPhysOffset.cy = 0; + } + +// Operations + void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, IPrintJobInfo* pji) + { + m_printer.Attach(hPrinter); + m_pDefDevMode = pDefaultDevMode; + m_pInfo = pji; + m_nCurPage = 0; + m_pCurDevMode = NULL; + } + + void SetEnhMetaFile(HENHMETAFILE hEMF) + { + m_meta = hEMF; + } + + void SetPage(int nPage) + { + if (!m_pInfo->IsValidPage(nPage)) + return; + m_nCurPage = nPage; + m_pCurDevMode = m_pInfo->GetNewDevModeForPage(0, nPage); + if (m_pCurDevMode == NULL) + m_pCurDevMode = m_pDefDevMode; + CDC dcPrinter = m_printer.CreatePrinterDC(m_pCurDevMode); + + int iWidth = dcPrinter.GetDeviceCaps(PHYSICALWIDTH); + int iHeight = dcPrinter.GetDeviceCaps(PHYSICALHEIGHT); + int nLogx = dcPrinter.GetDeviceCaps(LOGPIXELSX); + int nLogy = dcPrinter.GetDeviceCaps(LOGPIXELSY); + + RECT rcMM = { 0, 0, ::MulDiv(iWidth, 2540, nLogx), ::MulDiv(iHeight, 2540, nLogy) }; + + m_sizeCurPhysOffset.cx = dcPrinter.GetDeviceCaps(PHYSICALOFFSETX); + m_sizeCurPhysOffset.cy = dcPrinter.GetDeviceCaps(PHYSICALOFFSETY); + + CEnhMetaFileDC dcMeta(dcPrinter, &rcMM); + m_pInfo->PrePrintPage(nPage, dcMeta); + m_pInfo->PrintPage(nPage, dcMeta); + m_pInfo->PostPrintPage(nPage, dcMeta); + m_meta.Attach(dcMeta.Close()); + } + + void GetPageRect(RECT& rc, LPRECT prc) + { + int x1 = rc.right-rc.left; + int y1 = rc.bottom - rc.top; + if ((x1 < 0) || (y1 < 0)) + return; + + CEnhMetaFileInfo emfinfo(m_meta); + ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader(); + + // Compute whether we are OK vertically or horizontally + int x2 = pmh->szlDevice.cx; + int y2 = pmh->szlDevice.cy; + int y1p = MulDiv(x1, y2, x2); + int x1p = MulDiv(y1, x2, y2); + ATLASSERT((x1p <= x1) || (y1p <= y1)); + if (x1p <= x1) + { + prc->left = rc.left + (x1 - x1p) / 2; + prc->right = prc->left + x1p; + prc->top = rc.top; + prc->bottom = rc.bottom; + } + else + { + prc->left = rc.left; + prc->right = rc.right; + prc->top = rc.top + (y1 - y1p) / 2; + prc->bottom = prc->top + y1p; + } + } + +// Painting helpers + void DoPaint(CDCHandle dc) + { + // this one is not used + } + + void DoPaint(CDCHandle dc, RECT& rc) + { + CEnhMetaFileInfo emfinfo(m_meta); + ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader(); + int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx); + int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy); + + dc.OffsetWindowOrg(-nOffsetX, -nOffsetY); + dc.PlayMetaFile(m_meta, &rc); + } + +// Implementation - data + int m_nCurPage; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CPrintPreviewWindow - Implements a print preview window + +template +class ATL_NO_VTABLE CPrintPreviewWindowImpl : public ATL::CWindowImpl, public CPrintPreview +{ +public: + DECLARE_WND_CLASS_EX(NULL, CS_VREDRAW | CS_HREDRAW, -1) + + enum { m_cxOffset = 10, m_cyOffset = 10 }; + +// Constructor + CPrintPreviewWindowImpl() : m_nMaxPage(0), m_nMinPage(0) + { } + +// Operations + void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, + IPrintJobInfo* pji, int nMinPage, int nMaxPage) + { + CPrintPreview::SetPrintPreviewInfo(hPrinter, pDefaultDevMode, pji); + m_nMinPage = nMinPage; + m_nMaxPage = nMaxPage; + } + + bool NextPage() + { + if (m_nCurPage == m_nMaxPage) + return false; + SetPage(m_nCurPage + 1); + Invalidate(); + return true; + } + + bool PrevPage() + { + if (m_nCurPage == m_nMinPage) + return false; + if (m_nCurPage == 0) + return false; + SetPage(m_nCurPage - 1); + Invalidate(); + return true; + } + +// Message map and handlers + BEGIN_MSG_MAP(CPrintPreviewWindowImpl) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd) + MESSAGE_HANDLER(WM_PAINT, OnPaint) + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) + END_MSG_MAP() + + LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return 1; // no need for the background + } + + LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + RECT rc = { 0 }; + + if(wParam != NULL) + { + pT->DoPrePaint((HDC)wParam, rc); + pT->DoPaint((HDC)wParam, rc); + } + else + { + CPaintDC dc(m_hWnd); + pT->DoPrePaint(dc.m_hDC, rc); + pT->DoPaint(dc.m_hDC, rc); + } + + return 0; + } + +// Painting helper + void DoPrePaint(CDCHandle dc, RECT& rc) + { + RECT rcClient = { 0 }; + GetClientRect(&rcClient); + RECT rcArea = rcClient; + T* pT = static_cast(this); + pT; // avoid level 4 warning + ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset); + if (rcArea.left > rcArea.right) + rcArea.right = rcArea.left; + if (rcArea.top > rcArea.bottom) + rcArea.bottom = rcArea.top; + GetPageRect(rcArea, &rc); + CRgn rgn1, rgn2; + rgn1.CreateRectRgnIndirect(&rc); + rgn2.CreateRectRgnIndirect(&rcClient); + rgn2.CombineRgn(rgn1, RGN_DIFF); + dc.SelectClipRgn(rgn2); + dc.FillRect(&rcClient, COLOR_BTNSHADOW); + dc.SelectClipRgn(NULL); + dc.FillRect(&rc, (HBRUSH)::GetStockObject(WHITE_BRUSH)); + } + +// Implementation - data + int m_nMinPage; + int m_nMaxPage; +}; + + +class CPrintPreviewWindow : public CPrintPreviewWindowImpl +{ +public: + DECLARE_WND_CLASS_EX(_T("WTL_PrintPreview"), CS_VREDRAW | CS_HREDRAW, -1) +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CZoomPrintPreviewWindowImpl - Implements print preview window with zooming + +#ifdef __ATLSCRL_H__ + +template +class ATL_NO_VTABLE CZoomPrintPreviewWindowImpl : public CPrintPreviewWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T > +{ +public: + bool m_bSized; + + CZoomPrintPreviewWindowImpl() + { + SetScrollExtendedStyle(SCRL_DISABLENOSCROLL); + InitZoom(); + } + + // should be called to reset data members before recreating window + void InitZoom() + { + m_bSized = false; + m_nZoomMode = ZOOMMODE_OFF; + m_fZoomScaleMin = 1.0; + m_fZoomScale = 1.0; + } + + BEGIN_MSG_MAP(CZoomPrintPreviewWindowImpl) + MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor) + MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) + MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) + MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) +#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) + MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) +#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) + MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) + MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown) + MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove) + MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp) + MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged) + MESSAGE_HANDLER(WM_SIZE, OnSize) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd) + MESSAGE_HANDLER(WM_PAINT, OnPaint) + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) + ALT_MSG_MAP(1) + COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) + COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) + COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) + COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) + COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) + COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) + COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) + COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) + END_MSG_MAP() + + LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + SIZE sizeClient = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; + POINT ptOffset = m_ptOffset; + SIZE sizeAll = m_sizeAll; + SetScrollSize(sizeClient); + if(sizeAll.cx > 0) + ptOffset.x = ::MulDiv(ptOffset.x, m_sizeAll.cx, sizeAll.cx); + if(sizeAll.cy > 0) + ptOffset.y = ::MulDiv(ptOffset.y, m_sizeAll.cy, sizeAll.cy); + SetScrollOffset(ptOffset); + CScrollImpl< T >::OnSize(uMsg, wParam, lParam, bHandled); + if(!m_bSized) + { + m_bSized = true; + T* pT = static_cast(this); + pT->ShowScrollBar(SB_HORZ, TRUE); + pT->ShowScrollBar(SB_VERT, TRUE); + } + return 0; + } + + LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return 1; + } + + LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + RECT rc = { 0 }; + + if(wParam != NULL) + { + CDCHandle dc = (HDC)wParam; + int nMapModeSav = dc.GetMapMode(); + dc.SetMapMode(MM_ANISOTROPIC); + SIZE szWindowExt = { 0, 0 }; + dc.SetWindowExt(m_sizeLogAll, &szWindowExt); + SIZE szViewportExt = { 0, 0 }; + dc.SetViewportExt(m_sizeAll, &szViewportExt); + POINT ptViewportOrg = { 0, 0 }; + dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg); + + pT->DoPrePaint(dc, rc); + pT->DoPaint(dc, rc); + + dc.SetMapMode(nMapModeSav); + dc.SetWindowExt(szWindowExt); + dc.SetViewportExt(szViewportExt); + dc.SetViewportOrg(ptViewportOrg); + } + else + { + CPaintDC dc(pT->m_hWnd); + pT->PrepareDC(dc.m_hDC); + pT->DoPrePaint(dc.m_hDC, rc); + pT->DoPaint(dc.m_hDC, rc); + } + + return 0; + } + + // Painting helpers + void DoPaint(CDCHandle dc) + { + // this one is not used + } + + void DoPrePaint(CDCHandle dc, RECT& rc) + { + RECT rcClient; + GetClientRect(&rcClient); + RECT rcArea = rcClient; + T* pT = static_cast(this); + pT; // avoid level 4 warning + ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset); + if (rcArea.left > rcArea.right) + rcArea.right = rcArea.left; + if (rcArea.top > rcArea.bottom) + rcArea.bottom = rcArea.top; + GetPageRect(rcArea, &rc); + HBRUSH hbrOld = dc.SelectBrush(::GetSysColorBrush(COLOR_BTNSHADOW)); + dc.PatBlt(rcClient.left, rcClient.top, rc.left - rcClient.left, rcClient.bottom - rcClient.top, PATCOPY); + dc.PatBlt(rc.left, rcClient.top, rc.right - rc.left, rc.top - rcClient.top, PATCOPY); + dc.PatBlt(rc.right, rcClient.top, rcClient.right - rc.right, rcClient.bottom - rcClient.top, PATCOPY); + dc.PatBlt(rc.left, rc.bottom, rc.right - rc.left, rcClient.bottom - rc.bottom, PATCOPY); + dc.SelectBrush((HBRUSH)::GetStockObject(WHITE_BRUSH)); + dc.PatBlt(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); + dc.SelectBrush(::GetSysColorBrush(COLOR_3DDKSHADOW)); + dc.PatBlt(rc.right, rc.top + 4, 4, rc.bottom - rc.top, PATCOPY); + dc.PatBlt(rc.left + 4, rc.bottom, rc.right - rc.left, 4, PATCOPY); + dc.SelectBrush(hbrOld); + } + + void DoPaint(CDCHandle dc, RECT& rc) + { + CEnhMetaFileInfo emfinfo(m_meta); + ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader(); + int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx); + int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy); + + dc.OffsetWindowOrg(-nOffsetX, -nOffsetY); + dc.PlayMetaFile(m_meta, &rc); + } +}; + +class CZoomPrintPreviewWindow : public CZoomPrintPreviewWindowImpl +{ +public: + DECLARE_WND_CLASS_EX(_T("WTL_ZoomPrintPreview"), CS_VREDRAW | CS_HREDRAW, -1) +}; + +#endif // __ATLSCRL_H__ + +}; // namespace WTL + +#endif // __ATLPRINT_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlres.h b/Client/Client/GUI/BKWin/wtl/atlres.h new file mode 100644 index 00000000..8f9dff44 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlres.h @@ -0,0 +1,259 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLRES_H__ +#define __ATLRES_H__ + +#pragma once + +#if defined(_WIN32_WCE) && !defined(__ATLRESCE_H__) + #error Use atlresCE.h instead of atlres.h for Windows CE +#endif + + +#ifdef RC_INVOKED +#ifndef _INC_WINDOWS + + #define _INC_WINDOWS + + #ifndef _WIN32_WCE + #define VS_VERSION_INFO 1 + + #ifdef APSTUDIO_INVOKED + #define APSTUDIO_HIDDEN_SYMBOLS // Ignore following symbols + #endif // APSTUDIO_INVOKED + + #ifndef WINVER + #define WINVER 0x0400 // default to Windows Version 4.0 + #endif // !WINVER + + #include + + // operation messages sent to DLGINIT + #define LB_ADDSTRING (WM_USER+1) + #define CB_ADDSTRING (WM_USER+3) + #endif // !_WIN32_WCE + + #ifdef APSTUDIO_INVOKED + #undef APSTUDIO_HIDDEN_SYMBOLS + #endif // APSTUDIO_INVOKED + + #ifdef IDC_STATIC + #undef IDC_STATIC + #endif // IDC_STATIC + #define IDC_STATIC (-1) + +#endif // !_INC_WINDOWS +#endif // RC_INVOKED + +#ifdef APSTUDIO_INVOKED + #define APSTUDIO_HIDDEN_SYMBOLS +#endif // APSTUDIO_INVOKED + +/////////////////////////////////////////////////////////////////////////////// +// ATL resource types + +#ifndef RC_INVOKED + #define RT_DLGINIT MAKEINTRESOURCE(240) + #define RT_TOOLBAR MAKEINTRESOURCE(241) +#endif // RC_INVOKED + +/////////////////////////////////////////////////////////////////////////////// + +#ifdef APSTUDIO_INVOKED + #undef APSTUDIO_HIDDEN_SYMBOLS +#endif // APSTUDIO_INVOKED + +/////////////////////////////////////////////////////////////////////////////// +// Standard window components + +#define ID_SEPARATOR 0 // special separator value +#define ID_DEFAULT_PANE 0 // default status bar pane + +#ifndef RC_INVOKED // code only +// standard control bars (IDW = window ID) + #define ATL_IDW_TOOLBAR 0xE800 // main Toolbar for window + #define ATL_IDW_STATUS_BAR 0xE801 // Status bar window + #define ATL_IDW_COMMAND_BAR 0xE802 // Command bar window + +// parts of a frame window + #define ATL_IDW_CLIENT 0xE900 + #define ATL_IDW_PANE_FIRST 0xE900 // first pane (256 max) + #define ATL_IDW_PANE_LAST 0xE9FF + #define ATL_IDW_HSCROLL_FIRST 0xEA00 // first Horz scrollbar (16 max) + #define ATL_IDW_VSCROLL_FIRST 0xEA10 // first Vert scrollbar (16 max) + + #define ATL_IDW_SIZE_BOX 0xEA20 // size box for splitters + #define ATL_IDW_PANE_SAVE 0xEA21 // to shift ATL_IDW_PANE_FIRST + +// bands for a rebar + #define ATL_IDW_BAND_FIRST 0xEB00 + #define ATL_IDW_BAND_LAST 0xEBFF +#endif // !RC_INVOKED + +/////////////////////////////////////////////////////////////////////////////// +// Standard Commands + +// File commands +#define ID_FILE_NEW 0xE100 +#define ID_FILE_OPEN 0xE101 +#define ID_FILE_CLOSE 0xE102 +#define ID_FILE_SAVE 0xE103 +#define ID_FILE_SAVE_AS 0xE104 +#define ID_FILE_PAGE_SETUP 0xE105 +#define ID_FILE_PRINT_SETUP 0xE106 +#define ID_FILE_PRINT 0xE107 +#define ID_FILE_PRINT_DIRECT 0xE108 +#define ID_FILE_PRINT_PREVIEW 0xE109 +#define ID_FILE_UPDATE 0xE10A +#define ID_FILE_SAVE_COPY_AS 0xE10B +#define ID_FILE_SEND_MAIL 0xE10C + +#define ID_FILE_MRU_FIRST 0xE110 +#define ID_FILE_MRU_FILE1 0xE110 // range - 16 max +#define ID_FILE_MRU_FILE2 0xE111 +#define ID_FILE_MRU_FILE3 0xE112 +#define ID_FILE_MRU_FILE4 0xE113 +#define ID_FILE_MRU_FILE5 0xE114 +#define ID_FILE_MRU_FILE6 0xE115 +#define ID_FILE_MRU_FILE7 0xE116 +#define ID_FILE_MRU_FILE8 0xE117 +#define ID_FILE_MRU_FILE9 0xE118 +#define ID_FILE_MRU_FILE10 0xE119 +#define ID_FILE_MRU_FILE11 0xE11A +#define ID_FILE_MRU_FILE12 0xE11B +#define ID_FILE_MRU_FILE13 0xE11C +#define ID_FILE_MRU_FILE14 0xE11D +#define ID_FILE_MRU_FILE15 0xE11E +#define ID_FILE_MRU_FILE16 0xE11F +#define ID_FILE_MRU_LAST 0xE11F + +// Edit commands +#define ID_EDIT_CLEAR 0xE120 +#define ID_EDIT_CLEAR_ALL 0xE121 +#define ID_EDIT_COPY 0xE122 +#define ID_EDIT_CUT 0xE123 +#define ID_EDIT_FIND 0xE124 +#define ID_EDIT_PASTE 0xE125 +#define ID_EDIT_PASTE_LINK 0xE126 +#define ID_EDIT_PASTE_SPECIAL 0xE127 +#define ID_EDIT_REPEAT 0xE128 +#define ID_EDIT_REPLACE 0xE129 +#define ID_EDIT_SELECT_ALL 0xE12A +#define ID_EDIT_UNDO 0xE12B +#define ID_EDIT_REDO 0xE12C + +// Window commands +#define ID_WINDOW_NEW 0xE130 +#define ID_WINDOW_ARRANGE 0xE131 +#define ID_WINDOW_CASCADE 0xE132 +#define ID_WINDOW_TILE_HORZ 0xE133 +#define ID_WINDOW_TILE_VERT 0xE134 +#define ID_WINDOW_SPLIT 0xE135 +#ifndef RC_INVOKED // code only + #define ATL_IDM_WINDOW_FIRST 0xE130 + #define ATL_IDM_WINDOW_LAST 0xE13F + #define ATL_IDM_FIRST_MDICHILD 0xFF00 // window list starts here + #define ATL_IDM_LAST_MDICHILD 0xFFFD +#endif // !RC_INVOKED +// TabView +#define ID_WINDOW_TABFIRST 0xFF00 // = ATL_IDM_FIRST_MDICHILD +#define ID_WINDOW_TABLAST 0xFFFD +#define ID_WINDOW_SHOWTABLIST 0xFFFE + +// Help and App commands +#define ID_APP_ABOUT 0xE140 +#define ID_APP_EXIT 0xE141 +#define ID_HELP_INDEX 0xE142 +#define ID_HELP_FINDER 0xE143 +#define ID_HELP_USING 0xE144 +#define ID_CONTEXT_HELP 0xE145 // shift-F1 +// special commands for processing help +#define ID_HELP 0xE146 // first attempt for F1 +#define ID_DEFAULT_HELP 0xE147 // last attempt + +// Misc +#define ID_NEXT_PANE 0xE150 +#define ID_PREV_PANE 0xE151 +#define ID_PANE_CLOSE 0xE152 + +// Format +#define ID_FORMAT_FONT 0xE160 + +// Scroll +#define ID_SCROLL_UP 0xE170 +#define ID_SCROLL_DOWN 0xE171 +#define ID_SCROLL_PAGE_UP 0xE172 +#define ID_SCROLL_PAGE_DOWN 0xE173 +#define ID_SCROLL_TOP 0xE174 +#define ID_SCROLL_BOTTOM 0xE175 +#define ID_SCROLL_LEFT 0xE176 +#define ID_SCROLL_RIGHT 0xE177 +#define ID_SCROLL_PAGE_LEFT 0xE178 +#define ID_SCROLL_PAGE_RIGHT 0xE179 +#define ID_SCROLL_ALL_LEFT 0xE17A +#define ID_SCROLL_ALL_RIGHT 0xE17B + +// OLE commands +#define ID_OLE_INSERT_NEW 0xE200 +#define ID_OLE_EDIT_LINKS 0xE201 +#define ID_OLE_EDIT_CONVERT 0xE202 +#define ID_OLE_EDIT_CHANGE_ICON 0xE203 +#define ID_OLE_EDIT_PROPERTIES 0xE204 +#define ID_OLE_VERB_FIRST 0xE210 // range - 16 max +#ifndef RC_INVOKED // code only + #define ID_OLE_VERB_LAST 0xE21F +#endif // !RC_INVOKED + +// View commands (same number used as IDW used for toolbar and status bar) +#define ID_VIEW_TOOLBAR 0xE800 +#define ID_VIEW_STATUS_BAR 0xE801 +#define ID_VIEW_REFRESH 0xE803 + +/////////////////////////////////////////////////////////////////////////////// +// Standard control IDs + +#ifdef IDC_STATIC + #undef IDC_STATIC +#endif // IDC_STATIC +#define IDC_STATIC (-1) // all static controls + +/////////////////////////////////////////////////////////////////////////////// +// Standard string error/warnings + +// idle status bar message +#define ATL_IDS_IDLEMESSAGE 0xE001 + +#ifndef RC_INVOKED // code only + #define ATL_IDS_SCFIRST 0xEF00 +#endif // !RC_INVOKED + +#define ATL_IDS_SCSIZE 0xEF00 +#define ATL_IDS_SCMOVE 0xEF01 +#define ATL_IDS_SCMINIMIZE 0xEF02 +#define ATL_IDS_SCMAXIMIZE 0xEF03 +#define ATL_IDS_SCNEXTWINDOW 0xEF04 +#define ATL_IDS_SCPREVWINDOW 0xEF05 +#define ATL_IDS_SCCLOSE 0xEF06 +#define ATL_IDS_SCRESTORE 0xEF12 +#define ATL_IDS_SCTASKLIST 0xEF13 + +#define ATL_IDS_MDICHILD 0xEF1F +#define ATL_IDS_MRU_FILE 0xEFDA + +/////////////////////////////////////////////////////////////////////////////// +// Misc. control IDs + +// Property Sheet control id's (determined with Spy++) +#define ID_APPLY_NOW 0x3021 +#define ID_WIZBACK 0x3023 +#define ID_WIZNEXT 0x3024 +#define ID_WIZFINISH 0x3025 +#define ATL_IDC_TAB_CONTROL 0x3020 + +#endif // __ATLRES_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlresce.h b/Client/Client/GUI/BKWin/wtl/atlresce.h new file mode 100644 index 00000000..bc72a0a7 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlresce.h @@ -0,0 +1,90 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLRESCE_H__ +#define __ATLRESCE_H__ + +#pragma once + +#ifndef _WIN32_WCE + #error atlresCE.h is only for Windows CE +#endif + + +#ifdef RC_INVOKED +#ifndef _INC_WINDOWS + + #define VS_VERSION_INFO 1 + + #ifdef APSTUDIO_INVOKED + #define APSTUDIO_HIDDEN_SYMBOLS // Ignore following symbols + #endif // APSTUDIO_INVOKED + + #ifndef WINVER + #define WINVER 0x0400 // default to Windows Version 4.0 + #endif // !WINVER + + #if !defined(WCEOLE_ENABLE_DIALOGEX) + #define DIALOGEX DIALOG DISCARDABLE + #endif + + #include + #define SHMENUBAR RCDATA + + #if defined(SHELLSDK_MODULES_AYGSHELL) + #include + #else + #define NOMENU 0xFFFF + #define IDS_SHNEW 1 + #define IDM_SHAREDNEW 10 + #define IDM_SHAREDNEWDEFAULT 11 + #endif + #ifndef I_IMAGENONE + #define I_IMAGENONE (-2) + #endif + + #include + +#endif // !_INC_WINDOWS +#endif // RC_INVOKED + +#include "atlres.h" + +#ifdef APSTUDIO_INVOKED + #undef APSTUDIO_HIDDEN_SYMBOLS +#endif // APSTUDIO_INVOKED + +// Visual Studio dialog editor bug fix +#ifndef DS_FIXEDSYS + #define DS_FIXEDSYS 0 +#endif + +#define IDC_INFOSTATIC 0xFFFE // == IDC_STATIC -1 + +/////////////////////////////////////////////////////////////////////////////// +// Smartphone and PPC 2005 Resource IDs + +// Command and associated string resource IDs +#define ID_MENU_OK 0xE790 +#define ID_MENU_CANCEL 0xE791 +#define ID_MENU 0xE792 +#define ID_ACTION 0xE793 +#define ID_VIEW_FULLSCREEN 0xE802 + +// MenuBar resource IDs +#define ATL_IDM_MENU_DONE 0xE701 +#define ATL_IDM_MENU_CANCEL 0xE702 +#define ATL_IDM_MENU_DONECANCEL 0xE703 + +// Default device MenuBar control ID and MenuBar resource ID +#define ATL_IDW_MENU_BAR 0xE802 + +// SmartPhone spinned controls ID offset for CSpinCtrl +#define ATL_IDW_SPIN_ID 9999 + +#endif // __ATLRESCE_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlscrl.h b/Client/Client/GUI/BKWin/wtl/atlscrl.h new file mode 100644 index 00000000..a143da44 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlscrl.h @@ -0,0 +1,2012 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLSCRL_H__ +#define __ATLSCRL_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifndef __ATLAPP_H__ + #error atlscrl.h requires atlapp.h to be included first +#endif + +#ifndef __ATLWIN_H__ + #error atlscrl.h requires atlwin.h to be included first +#endif + +#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) + #include +#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) + +#ifndef GET_WHEEL_DELTA_WPARAM + #define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam)) +#endif + +#ifndef WM_MOUSEHWHEEL + #define WM_MOUSEHWHEEL 0x020E +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CScrollImpl +// CScrollWindowImpl +// CMapScrollImpl +// CMapScrollWindowImpl +// CFSBWindowT +// CZoomScrollImpl +// CZoomScrollWindowImpl +// CScrollContainerImpl +// CScrollContainer + +namespace WTL +{ + +/////////////////////////////////////////////////////////////////////////////// +// CScrollImpl - Provides scrolling support to any window + +// Scroll extended styles +#define SCRL_SCROLLCHILDREN 0x00000001 +#define SCRL_ERASEBACKGROUND 0x00000002 +#define SCRL_NOTHUMBTRACKING 0x00000004 +#if (WINVER >= 0x0500) +#define SCRL_SMOOTHSCROLL 0x00000008 +#endif // (WINVER >= 0x0500) +#define SCRL_DISABLENOSCROLLV 0x00000010 +#define SCRL_DISABLENOSCROLLH 0x00000020 +#define SCRL_DISABLENOSCROLL (SCRL_DISABLENOSCROLLV | SCRL_DISABLENOSCROLLH) + + +template +class CScrollImpl +{ +public: + enum { uSCROLL_FLAGS = SW_INVALIDATE }; + + POINT m_ptOffset; + SIZE m_sizeAll; + SIZE m_sizeLine; + SIZE m_sizePage; + SIZE m_sizeClient; + int m_zDelta; // current wheel value + int m_nWheelLines; // number of lines to scroll on wheel +#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) + // Note that this message must be forwarded from a top level window + UINT m_uMsgMouseWheel; // MSH_MOUSEWHEEL +#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) + int m_zHDelta; // current horizontal wheel value + int m_nHWheelChars; // number of chars to scroll on horizontal wheel + UINT m_uScrollFlags; + DWORD m_dwExtendedStyle; // scroll specific extended styles + +// Constructor + CScrollImpl() : m_zDelta(0), m_nWheelLines(3), +#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) + m_uMsgMouseWheel(0U), +#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) + m_zHDelta(0), m_nHWheelChars(3), + m_uScrollFlags(0U), m_dwExtendedStyle(0) + { + m_ptOffset.x = 0; + m_ptOffset.y = 0; + m_sizeAll.cx = 0; + m_sizeAll.cy = 0; + m_sizePage.cx = 0; + m_sizePage.cy = 0; + m_sizeLine.cx = 0; + m_sizeLine.cy = 0; + m_sizeClient.cx = 0; + m_sizeClient.cy = 0; + + SetScrollExtendedStyle(SCRL_SCROLLCHILDREN | SCRL_ERASEBACKGROUND); + } + +// Attributes & Operations + DWORD GetScrollExtendedStyle() const + { + return m_dwExtendedStyle; + } + + DWORD SetScrollExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) + { + DWORD dwPrevStyle = m_dwExtendedStyle; + if(dwMask == 0) + m_dwExtendedStyle = dwExtendedStyle; + else + m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); + // cache scroll flags + T* pT = static_cast(this); + pT; // avoid level 4 warning + m_uScrollFlags = pT->uSCROLL_FLAGS | (IsScrollingChildren() ? SW_SCROLLCHILDREN : 0) | (IsErasingBackground() ? SW_ERASE : 0); +#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) + m_uScrollFlags |= (IsSmoothScroll() ? SW_SMOOTHSCROLL : 0); +#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) + return dwPrevStyle; + } + + // offset operations + void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + + pT->AdjustScrollOffset(x, y); + + int dx = m_ptOffset.x - x; + int dy = m_ptOffset.y - y; + m_ptOffset.x = x; + m_ptOffset.y = y; + + // block: set horizontal scroll bar + { + SCROLLINFO si = { sizeof(SCROLLINFO) }; + si.fMask = SIF_POS; + if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0) + si.fMask |= SIF_DISABLENOSCROLL; + si.nPos = m_ptOffset.x; + pT->SetScrollInfo(SB_HORZ, &si, bRedraw); + } + + // block: set vertical scroll bar + { + SCROLLINFO si = { sizeof(SCROLLINFO) }; + si.fMask = SIF_POS; + if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0) + si.fMask |= SIF_DISABLENOSCROLL; + si.nPos = m_ptOffset.y; + pT->SetScrollInfo(SB_VERT, &si, bRedraw); + } + + // Move all children if needed + if(IsScrollingChildren() && (dx != 0 || dy != 0)) + { + for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT)) + { + RECT rect = { 0 }; + ::GetWindowRect(hWndChild, &rect); + ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1); + ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); + } + } + + if(bRedraw) + pT->Invalidate(); + } + + void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE) + { + SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw); + } + + void GetScrollOffset(POINT& ptOffset) const + { + ptOffset = m_ptOffset; + } + + // size operations + void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + + m_sizeAll.cx = cx; + m_sizeAll.cy = cy; + + int x = 0; + int y = 0; + if(!bResetOffset) + { + x = m_ptOffset.x; + y = m_ptOffset.y; + pT->AdjustScrollOffset(x, y); + } + + int dx = m_ptOffset.x - x; + int dy = m_ptOffset.y - y; + m_ptOffset.x = x; + m_ptOffset.y = y; + + // block: set horizontal scroll bar + { + SCROLLINFO si = { sizeof(SCROLLINFO) }; + si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; + if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0) + si.fMask |= SIF_DISABLENOSCROLL; + si.nMin = 0; + si.nMax = m_sizeAll.cx - 1; + si.nPage = m_sizeClient.cx; + si.nPos = m_ptOffset.x; + pT->SetScrollInfo(SB_HORZ, &si, bRedraw); + } + + // block: set vertical scroll bar + { + SCROLLINFO si = { sizeof(SCROLLINFO) }; + si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; + if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0) + si.fMask |= SIF_DISABLENOSCROLL; + si.nMin = 0; + si.nMax = m_sizeAll.cy - 1; + si.nPage = m_sizeClient.cy; + si.nPos = m_ptOffset.y; + pT->SetScrollInfo(SB_VERT, &si, bRedraw); + } + + // Move all children if needed + if(IsScrollingChildren() && (dx != 0 || dy != 0)) + { + for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT)) + { + RECT rect = { 0 }; + ::GetWindowRect(hWndChild, &rect); + ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1); + ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); + } + } + + SetScrollLine(0, 0); + SetScrollPage(0, 0); + + if(bRedraw) + pT->Invalidate(); + } + + void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true) + { + SetScrollSize(size.cx, size.cy, bRedraw, bResetOffset); + } + + void GetScrollSize(SIZE& sizeWnd) const + { + sizeWnd = m_sizeAll; + } + + // line operations + void SetScrollLine(int cxLine, int cyLine) + { + ATLASSERT(cxLine >= 0 && cyLine >= 0); + ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0); + + m_sizeLine.cx = T::CalcLineOrPage(cxLine, m_sizeAll.cx, 100); + m_sizeLine.cy = T::CalcLineOrPage(cyLine, m_sizeAll.cy, 100); + } + + void SetScrollLine(SIZE sizeLine) + { + SetScrollLine(sizeLine.cx, sizeLine.cy); + } + + void GetScrollLine(SIZE& sizeLine) const + { + sizeLine = m_sizeLine; + } + + // page operations + void SetScrollPage(int cxPage, int cyPage) + { + ATLASSERT(cxPage >= 0 && cyPage >= 0); + ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0); + + m_sizePage.cx = T::CalcLineOrPage(cxPage, m_sizeAll.cx, 10); + m_sizePage.cy = T::CalcLineOrPage(cyPage, m_sizeAll.cy, 10); + } + + void SetScrollPage(SIZE sizePage) + { + SetScrollPage(sizePage.cx, sizePage.cy); + } + + void GetScrollPage(SIZE& sizePage) const + { + sizePage = m_sizePage; + } + + // commands + void ScrollLineDown() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DoScroll(SB_VERT, SB_LINEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); + } + + void ScrollLineUp() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DoScroll(SB_VERT, SB_LINEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); + } + + void ScrollPageDown() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DoScroll(SB_VERT, SB_PAGEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); + } + + void ScrollPageUp() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DoScroll(SB_VERT, SB_PAGEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); + } + + void ScrollTop() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DoScroll(SB_VERT, SB_TOP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); + } + + void ScrollBottom() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DoScroll(SB_VERT, SB_BOTTOM, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); + } + + void ScrollLineRight() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DoScroll(SB_HORZ, SB_LINEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); + } + + void ScrollLineLeft() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DoScroll(SB_HORZ, SB_LINEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); + } + + void ScrollPageRight() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DoScroll(SB_HORZ, SB_PAGEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); + } + + void ScrollPageLeft() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DoScroll(SB_HORZ, SB_PAGEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); + } + + void ScrollAllLeft() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DoScroll(SB_HORZ, SB_TOP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); + } + + void ScrollAllRight() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DoScroll(SB_HORZ, SB_BOTTOM, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); + } + + // scroll to make point/view/window visible + void ScrollToView(POINT pt) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + RECT rect = { pt.x, pt.y, pt.x, pt.y }; + pT->ScrollToView(rect); + } + + void ScrollToView(RECT& rect) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + + RECT rcClient = { 0 }; + pT->GetClientRect(&rcClient); + + int x = m_ptOffset.x; + if(rect.left < m_ptOffset.x) + x = rect.left; + else if(rect.right > (m_ptOffset.x + rcClient.right)) + x = rect.right - rcClient.right; + + int y = m_ptOffset.y; + if(rect.top < m_ptOffset.y) + y = rect.top; + else if(rect.bottom > (m_ptOffset.y + rcClient.bottom)) + y = rect.bottom - rcClient.bottom; + + SetScrollOffset(x, y); + } + + void ScrollToView(HWND hWnd) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + + RECT rect = { 0 }; + ::GetWindowRect(hWnd, &rect); + ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 2); + ScrollToView(rect); + } + + BEGIN_MSG_MAP(CScrollImpl) + MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_VSCROLL, OnVScroll) + MESSAGE_HANDLER(WM_HSCROLL, OnHScroll) + MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel) +#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) + MESSAGE_HANDLER(m_uMsgMouseWheel, OnMouseWheel) +#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) + MESSAGE_HANDLER(WM_MOUSEHWHEEL, OnMouseHWheel) + MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) + MESSAGE_HANDLER(WM_SIZE, OnSize) + MESSAGE_HANDLER(WM_PAINT, OnPaint) +#ifndef _WIN32_WCE + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) +#endif // !_WIN32_WCE + // standard scroll commands + ALT_MSG_MAP(1) + COMMAND_ID_HANDLER(ID_SCROLL_UP, OnScrollUp) + COMMAND_ID_HANDLER(ID_SCROLL_DOWN, OnScrollDown) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, OnScrollPageUp) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, OnScrollPageDown) + COMMAND_ID_HANDLER(ID_SCROLL_TOP, OnScrollTop) + COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, OnScrollBottom) + COMMAND_ID_HANDLER(ID_SCROLL_LEFT, OnScrollLeft) + COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, OnScrollRight) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, OnScrollPageLeft) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, OnScrollPageRight) + COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, OnScrollAllLeft) + COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, OnScrollAllRight) + END_MSG_MAP() + + LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + GetSystemSettings(); + bHandled = FALSE; + return 1; + } + + LRESULT OnVScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DoScroll(SB_VERT, (int)(short)LOWORD(wParam), (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); + return 0; + } + + LRESULT OnHScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + pT->DoScroll(SB_HORZ, (int)(short)LOWORD(wParam), (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); + return 0; + } + + LRESULT OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + +#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE) + uMsg; + int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam); +#else + int zDelta = (uMsg == WM_MOUSEWHEEL) ? (int)GET_WHEEL_DELTA_WPARAM(wParam) : (int)wParam; +#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE)) + int nScrollCode = (m_nWheelLines == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGEUP : SB_PAGEDOWN) : ((zDelta > 0) ? SB_LINEUP : SB_LINEDOWN); + m_zDelta += zDelta; // cumulative + int zTotal = (m_nWheelLines == WHEEL_PAGESCROLL) ? abs(m_zDelta) : abs(m_zDelta) * m_nWheelLines; + if(m_sizeAll.cy > m_sizeClient.cy) + { + for(int i = 0; i < zTotal; i += WHEEL_DELTA) + { + pT->DoScroll(SB_VERT, nScrollCode, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); + pT->UpdateWindow(); + } + } + else // can't scroll vertically, scroll horizontally + { + for(int i = 0; i < zTotal; i += WHEEL_DELTA) + { + pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); + pT->UpdateWindow(); + } + } + m_zDelta %= WHEEL_DELTA; + + return 0; + } + + LRESULT OnMouseHWheel(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + + int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam); + int nScrollCode = (m_nHWheelChars == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGERIGHT : SB_PAGELEFT) : ((zDelta > 0) ? SB_LINERIGHT : SB_LINELEFT); + m_zHDelta += zDelta; // cumulative + int zTotal = (m_nHWheelChars == WHEEL_PAGESCROLL) ? abs(m_zHDelta) : abs(m_zHDelta) * m_nHWheelChars; + if(m_sizeAll.cx > m_sizeClient.cx) + { + for(int i = 0; i < zTotal; i += WHEEL_DELTA) + { + pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); + pT->UpdateWindow(); + } + } + m_zHDelta %= WHEEL_DELTA; + + return 0; + } + + LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + GetSystemSettings(); + return 0; + } + + LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + + m_sizeClient.cx = GET_X_LPARAM(lParam); + m_sizeClient.cy = GET_Y_LPARAM(lParam); + + // block: set horizontal scroll bar + { + SCROLLINFO si = { sizeof(SCROLLINFO) }; + si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; + si.nMin = 0; + si.nMax = m_sizeAll.cx - 1; + if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0) + si.fMask |= SIF_DISABLENOSCROLL; + si.nPage = m_sizeClient.cx; + si.nPos = m_ptOffset.x; + pT->SetScrollInfo(SB_HORZ, &si, TRUE); + } + + // block: set vertical scroll bar + { + SCROLLINFO si = { sizeof(SCROLLINFO) }; + si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; + si.nMin = 0; + si.nMax = m_sizeAll.cy - 1; + if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0) + si.fMask |= SIF_DISABLENOSCROLL; + si.nPage = m_sizeClient.cy; + si.nPos = m_ptOffset.y; + pT->SetScrollInfo(SB_VERT, &si, TRUE); + } + + int x = m_ptOffset.x; + int y = m_ptOffset.y; + if(pT->AdjustScrollOffset(x, y)) + { + // Children will be moved in SetScrollOffset, if needed + pT->ScrollWindowEx(m_ptOffset.x - x, m_ptOffset.y - y, (m_uScrollFlags & ~SCRL_SCROLLCHILDREN)); + SetScrollOffset(x, y, FALSE); + } + + bHandled = FALSE; + return 1; + } + + LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + if(wParam != NULL) + { + CDCHandle dc = (HDC)wParam; + POINT ptViewportOrg = { 0, 0 }; + dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg); + pT->DoPaint(dc); + dc.SetViewportOrg(ptViewportOrg); + } + else + { + CPaintDC dc(pT->m_hWnd); + dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y); + pT->DoPaint(dc.m_hDC); + } + return 0; + } + + // scrolling handlers + LRESULT OnScrollUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + ScrollLineUp(); + return 0; + } + + LRESULT OnScrollDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + ScrollLineDown(); + return 0; + } + + LRESULT OnScrollPageUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + ScrollPageUp(); + return 0; + } + + LRESULT OnScrollPageDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + ScrollPageDown(); + return 0; + } + + LRESULT OnScrollTop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + ScrollTop(); + return 0; + } + + LRESULT OnScrollBottom(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + ScrollBottom(); + return 0; + } + + LRESULT OnScrollLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + ScrollLineLeft(); + return 0; + } + + LRESULT OnScrollRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + ScrollLineRight(); + return 0; + } + + LRESULT OnScrollPageLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + ScrollPageLeft(); + return 0; + } + + LRESULT OnScrollPageRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + ScrollPageRight(); + return 0; + } + + LRESULT OnScrollAllLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + ScrollAllLeft(); + return 0; + } + + LRESULT OnScrollAllRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + ScrollAllRight(); + return 0; + } + +// Overrideables + void DoPaint(CDCHandle /*dc*/) + { + // must be implemented in a derived class + ATLASSERT(FALSE); + } + +// Implementation + void DoScroll(int nType, int nScrollCode, int& cxyOffset, int cxySizeAll, int cxySizePage, int cxySizeLine) + { + T* pT = static_cast(this); + RECT rect = { 0 }; + pT->GetClientRect(&rect); + int cxyClient = (nType == SB_VERT) ? rect.bottom : rect.right; + int cxyMax = cxySizeAll - cxyClient; + + if(cxyMax < 0) // can't scroll, client area is bigger + return; + + bool bUpdate = true; + int cxyScroll = 0; + + switch(nScrollCode) + { + case SB_TOP: // top or all left + cxyScroll = cxyOffset; + cxyOffset = 0; + break; + case SB_BOTTOM: // bottom or all right + cxyScroll = cxyOffset - cxyMax; + cxyOffset = cxyMax; + break; + case SB_LINEUP: // line up or line left + if(cxyOffset >= cxySizeLine) + { + cxyScroll = cxySizeLine; + cxyOffset -= cxySizeLine; + } + else + { + cxyScroll = cxyOffset; + cxyOffset = 0; + } + break; + case SB_LINEDOWN: // line down or line right + if(cxyOffset < cxyMax - cxySizeLine) + { + cxyScroll = -cxySizeLine; + cxyOffset += cxySizeLine; + } + else + { + cxyScroll = cxyOffset - cxyMax; + cxyOffset = cxyMax; + } + break; + case SB_PAGEUP: // page up or page left + if(cxyOffset >= cxySizePage) + { + cxyScroll = cxySizePage; + cxyOffset -= cxySizePage; + } + else + { + cxyScroll = cxyOffset; + cxyOffset = 0; + } + break; + case SB_PAGEDOWN: // page down or page right + if(cxyOffset < cxyMax - cxySizePage) + { + cxyScroll = -cxySizePage; + cxyOffset += cxySizePage; + } + else + { + cxyScroll = cxyOffset - cxyMax; + cxyOffset = cxyMax; + } + break; + case SB_THUMBTRACK: + if(IsNoThumbTracking()) + break; + // else fall through + case SB_THUMBPOSITION: + { + SCROLLINFO si = { sizeof(SCROLLINFO), SIF_TRACKPOS }; + if(pT->GetScrollInfo(nType, &si)) + { + cxyScroll = cxyOffset - si.nTrackPos; + cxyOffset = si.nTrackPos; + } + } + break; + case SB_ENDSCROLL: + default: + bUpdate = false; + break; + } + + if(bUpdate && cxyScroll != 0) + { + pT->SetScrollPos(nType, cxyOffset, TRUE); + if(nType == SB_VERT) + pT->ScrollWindowEx(0, cxyScroll, m_uScrollFlags); + else + pT->ScrollWindowEx(cxyScroll, 0, m_uScrollFlags); + } + } + + static int CalcLineOrPage(int nVal, int nMax, int nDiv) + { + if(nVal == 0) + { + nVal = nMax / nDiv; + if(nVal < 1) + nVal = 1; + } + else if(nVal > nMax) + { + nVal = nMax; + } + + return nVal; + } + + bool AdjustScrollOffset(int& x, int& y) + { + int xOld = x; + int yOld = y; + + int cxMax = m_sizeAll.cx - m_sizeClient.cx; + if(x > cxMax) + x = (cxMax >= 0) ? cxMax : 0; + else if(x < 0) + x = 0; + + int cyMax = m_sizeAll.cy - m_sizeClient.cy; + if(y > cyMax) + y = (cyMax >= 0) ? cyMax : 0; + else if(y < 0) + y = 0; + + return (x != xOld || y != yOld); + } + + void GetSystemSettings() + { +#ifndef _WIN32_WCE +#ifndef SPI_GETWHEELSCROLLLINES + const UINT SPI_GETWHEELSCROLLLINES = 104; +#endif // !SPI_GETWHEELSCROLLLINES + ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &m_nWheelLines, 0); + +#ifndef SPI_GETWHEELSCROLLCHARS + const UINT SPI_GETWHEELSCROLLCHARS = 0x006C; +#endif // !SPI_GETWHEELSCROLLCHARS + ::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &m_nHWheelChars, 0); + +#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) + if(m_uMsgMouseWheel != 0) + m_uMsgMouseWheel = ::RegisterWindowMessage(MSH_MOUSEWHEEL); + + HWND hWndWheel = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE); + if(::IsWindow(hWndWheel)) + { + UINT uMsgScrollLines = ::RegisterWindowMessage(MSH_SCROLL_LINES); + if(uMsgScrollLines != 0) + m_nWheelLines = (int)::SendMessage(hWndWheel, uMsgScrollLines, 0, 0L); + } +#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) +#endif // !_WIN32_WCE + } + + bool IsScrollingChildren() const + { + return (m_dwExtendedStyle & SCRL_SCROLLCHILDREN) != 0; + } + + bool IsErasingBackground() const + { + return (m_dwExtendedStyle & SCRL_ERASEBACKGROUND) != 0; + } + + bool IsNoThumbTracking() const + { + return (m_dwExtendedStyle & SCRL_NOTHUMBTRACKING) != 0; + } + +#if (WINVER >= 0x0500) + bool IsSmoothScroll() const + { + return (m_dwExtendedStyle & SCRL_SMOOTHSCROLL) != 0; + } +#endif // (WINVER >= 0x0500) +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CScrollWindowImpl - Implements a scrollable window + +template +class ATL_NO_VTABLE CScrollWindowImpl : public ATL::CWindowImpl, public CScrollImpl< T > +{ +public: + BEGIN_MSG_MAP(CScrollWindowImpl) + MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) + MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) + MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) +#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) + MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) +#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) + MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) + MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) + MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) + MESSAGE_HANDLER(WM_PAINT, CScrollImpl< T >::OnPaint) +#ifndef _WIN32_WCE + MESSAGE_HANDLER(WM_PRINTCLIENT, CScrollImpl< T >::OnPaint) +#endif // !_WIN32_WCE + ALT_MSG_MAP(1) + COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) + COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) + COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) + COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) + COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) + COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) + COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) + COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) + END_MSG_MAP() +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CMapScrollImpl - Provides mapping and scrolling support to any window + +#ifndef _WIN32_WCE + +template +class CMapScrollImpl : public CScrollImpl< T > +{ +public: + int m_nMapMode; + RECT m_rectLogAll; + SIZE m_sizeLogLine; + SIZE m_sizeLogPage; + +// Constructor + CMapScrollImpl() : m_nMapMode(MM_TEXT) + { + ::SetRectEmpty(&m_rectLogAll); + m_sizeLogPage.cx = 0; + m_sizeLogPage.cy = 0; + m_sizeLogLine.cx = 0; + m_sizeLogLine.cy = 0; + } + +// Attributes & Operations + // mapping mode operations + void SetScrollMapMode(int nMapMode) + { + ATLASSERT(nMapMode >= MM_MIN && nMapMode <= MM_MAX_FIXEDSCALE); + m_nMapMode = nMapMode; + } + + int GetScrollMapMode() const + { + ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); + return m_nMapMode; + } + + // offset operations + void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE) + { + ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); + POINT ptOff = { x, y }; + // block: convert logical to device units + { + CWindowDC dc(NULL); + dc.SetMapMode(m_nMapMode); + dc.LPtoDP(&ptOff); + } + CScrollImpl< T >::SetScrollOffset(ptOff, bRedraw); + } + + void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE) + { + SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw); + } + + void GetScrollOffset(POINT& ptOffset) const + { + ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); + ptOffset = m_ptOffset; + // block: convert device to logical units + { + CWindowDC dc(NULL); + dc.SetMapMode(m_nMapMode); + dc.DPtoLP(&ptOffset); + } + } + + // size operations + void SetScrollSize(int xMin, int yMin, int xMax, int yMax, BOOL bRedraw = TRUE, bool bResetOffset = true) + { + ATLASSERT(xMax > xMin && yMax > yMin); + ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); + + ::SetRect(&m_rectLogAll, xMin, yMin, xMax, yMax); + + SIZE sizeAll = { 0 }; + sizeAll.cx = xMax - xMin + 1; + sizeAll.cy = yMax - yMin + 1; + // block: convert logical to device units + { + CWindowDC dc(NULL); + dc.SetMapMode(m_nMapMode); + dc.LPtoDP(&sizeAll); + } + CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset); + SetScrollLine(0, 0); + SetScrollPage(0, 0); + } + + void SetScrollSize(RECT& rcScroll, BOOL bRedraw = TRUE, bool bResetOffset = true) + { + SetScrollSize(rcScroll.left, rcScroll.top, rcScroll.right, rcScroll.bottom, bRedraw, bResetOffset); + } + + void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true) + { + SetScrollSize(0, 0, cx, cy, bRedraw, bResetOffset); + } + + void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true) + { + SetScrollSize(0, 0, size.cx, size.cy, bRedraw, bResetOffset); + } + + void GetScrollSize(RECT& rcScroll) const + { + ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); + rcScroll = m_rectLogAll; + } + + // line operations + void SetScrollLine(int cxLine, int cyLine) + { + ATLASSERT(cxLine >= 0 && cyLine >= 0); + ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); + + m_sizeLogLine.cx = cxLine; + m_sizeLogLine.cy = cyLine; + SIZE sizeLine = m_sizeLogLine; + // block: convert logical to device units + { + CWindowDC dc(NULL); + dc.SetMapMode(m_nMapMode); + dc.LPtoDP(&sizeLine); + } + CScrollImpl< T >::SetScrollLine(sizeLine); + } + + void SetScrollLine(SIZE sizeLine) + { + SetScrollLine(sizeLine.cx, sizeLine.cy); + } + + void GetScrollLine(SIZE& sizeLine) const + { + ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); + sizeLine = m_sizeLogLine; + } + + // page operations + void SetScrollPage(int cxPage, int cyPage) + { + ATLASSERT(cxPage >= 0 && cyPage >= 0); + ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); + + m_sizeLogPage.cx = cxPage; + m_sizeLogPage.cy = cyPage; + SIZE sizePage = m_sizeLogPage; + // block: convert logical to device units + { + CWindowDC dc(NULL); + dc.SetMapMode(m_nMapMode); + dc.LPtoDP(&sizePage); + } + CScrollImpl< T >::SetScrollPage(sizePage); + } + + void SetScrollPage(SIZE sizePage) + { + SetScrollPage(sizePage.cx, sizePage.cy); + } + + void GetScrollPage(SIZE& sizePage) const + { + ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); + sizePage = m_sizeLogPage; + } + + BEGIN_MSG_MAP(CMapScrollImpl) + MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) + MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) + MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) +#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) + MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) +#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) + MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) + MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) + MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) + MESSAGE_HANDLER(WM_PAINT, OnPaint) + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) + ALT_MSG_MAP(1) + COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) + COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) + COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) + COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) + COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) + COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) + COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) + COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) + END_MSG_MAP() + + LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + if(wParam != NULL) + { + CDCHandle dc = (HDC)wParam; + int nMapModeSav = dc.GetMapMode(); + dc.SetMapMode(m_nMapMode); + POINT ptViewportOrg = { 0, 0 }; + if(m_nMapMode == MM_TEXT) + dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg); + else + dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy, &ptViewportOrg); + POINT ptWindowOrg = { 0, 0 }; + dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top, &ptWindowOrg); + + pT->DoPaint(dc); + + dc.SetMapMode(nMapModeSav); + dc.SetViewportOrg(ptViewportOrg); + dc.SetWindowOrg(ptWindowOrg); + } + else + { + CPaintDC dc(pT->m_hWnd); + dc.SetMapMode(m_nMapMode); + if(m_nMapMode == MM_TEXT) + dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y); + else + dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy); + dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top); + pT->DoPaint(dc.m_hDC); + } + return 0; + } +}; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CMapScrollWindowImpl - Implements scrolling window with mapping + +#ifndef _WIN32_WCE + +template +class ATL_NO_VTABLE CMapScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CMapScrollImpl< T > +{ +public: + BEGIN_MSG_MAP(CMapScrollWindowImpl) + MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) + MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) + MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) +#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) + MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) +#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) + MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) + MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) + MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) + MESSAGE_HANDLER(WM_PAINT, CMapScrollImpl< T >::OnPaint) + MESSAGE_HANDLER(WM_PRINTCLIENT, CMapScrollImpl< T >::OnPaint) + ALT_MSG_MAP(1) + COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) + COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) + COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) + COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) + COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) + COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) + COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) + COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) + END_MSG_MAP() +}; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CFSBWindow - Use as a base instead of CWindow to get flat scroll bar support + +#if defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + +template +class CFSBWindowT : public TBase, public CFlatScrollBarImpl > +{ +public: +// Constructors + CFSBWindowT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CFSBWindowT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + +// CWindow overrides that use flat scroll bar API +// (only those methods that are used by scroll window classes) + int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return FlatSB_SetScrollPos(nBar, nPos, bRedraw); + } + + BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo) + { + ATLASSERT(::IsWindow(m_hWnd)); + return FlatSB_GetScrollInfo(nBar, lpScrollInfo); + } + + BOOL SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return FlatSB_SetScrollInfo(nBar, lpScrollInfo, bRedraw); + } +}; + +typedef CFSBWindowT CFSBWindow; + +#endif // defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) + + +/////////////////////////////////////////////////////////////////////////////// +// CZoomScrollImpl - Provides zooming and scrolling support to any window + +#ifndef _WIN32_WCE + +// The zoom modes that can be set with the SetZoomMode method +enum +{ + ZOOMMODE_OFF, + ZOOMMODE_IN, // If left mouse button is clicked or dragged, zoom in on point clicked or rectangle dragged. + ZOOMMODE_OUT // If left mouse button clicked, zoom out on point clicked. +}; + +// Notification to parent that zoom scale changed as a result of user mouse action. +#define ZSN_ZOOMCHANGED (NM_FIRST - 50) + +template +class CZoomScrollImpl : public CScrollImpl< T > +{ +public: + enum { m_cxyMinZoomRect = 12 }; // min rect size to zoom in on rect. + +// Data members + SIZE m_sizeLogAll; + SIZE m_sizeLogLine; + SIZE m_sizeLogPage; + float m_fZoomScale; + float m_fZoomScaleMin; + float m_fZoomDelta; // Used in ZOOMMODE_IN and ZOOMMODE_OUT on left-button click. + int m_nZoomMode; + RECT m_rcTrack; + bool m_bTracking; + +// Constructor + CZoomScrollImpl(): + m_fZoomScale(1.0), + m_fZoomScaleMin(0.5), + m_fZoomDelta(0.5), + m_nZoomMode(ZOOMMODE_OFF), + m_bTracking(false) + { + m_sizeLogAll.cx = 0; + m_sizeLogAll.cy = 0; + m_sizeLogPage.cx = 0; + m_sizeLogPage.cy = 0; + m_sizeLogLine.cx = 0; + m_sizeLogLine.cy = 0; + ::SetRectEmpty(&m_rcTrack); + } + +// Attributes & Operations + + // size operations + void SetScrollSize(int cxLog, int cyLog, BOOL bRedraw = TRUE, bool bResetOffset = true) + { + ATLASSERT(cxLog >= 0 && cyLog >= 0); + + // Set up the defaults + if (cxLog == 0 && cyLog == 0) + { + cxLog = 1; + cyLog = 1; + } + + m_sizeLogAll.cx = cxLog; + m_sizeLogAll.cy = cyLog; + SIZE sizeAll = { 0 }; + sizeAll.cx = (int)((float)m_sizeLogAll.cx * m_fZoomScale); + sizeAll.cy = (int)((float)m_sizeLogAll.cy * m_fZoomScale); + + CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset); + } + + void SetScrollSize(SIZE sizeLog, BOOL bRedraw = TRUE, bool bResetOffset = true) + { + SetScrollSize(sizeLog.cx, sizeLog.cy, bRedraw, bResetOffset); + } + + void GetScrollSize(SIZE& sizeLog) const + { + sizeLog = m_sizeLogAll; + } + + // line operations + void SetScrollLine(int cxLogLine, int cyLogLine) + { + ATLASSERT(cxLogLine >= 0 && cyLogLine >= 0); + + m_sizeLogLine.cx = cxLogLine; + m_sizeLogLine.cy = cyLogLine; + + SIZE sizeLine = { 0 }; + sizeLine.cx = (int)((float)m_sizeLogLine.cx * m_fZoomScale); + sizeLine.cy = (int)((float)m_sizeLogLine.cy * m_fZoomScale); + CScrollImpl< T >::SetScrollLine(sizeLine); + } + + void SetScrollLine(SIZE sizeLogLine) + { + SetScrollLine(sizeLogLine.cx, sizeLogLine.cy); + } + + void GetScrollLine(SIZE& sizeLogLine) const + { + sizeLogLine = m_sizeLogLine; + } + + // page operations + void SetScrollPage(int cxLogPage, int cyLogPage) + { + ATLASSERT(cxLogPage >= 0 && cyLogPage >= 0); + + m_sizeLogPage.cx = cxLogPage; + m_sizeLogPage.cy = cyLogPage; + + SIZE sizePage = { 0 }; + sizePage.cx = (int)((float)m_sizeLogPage.cx * m_fZoomScale); + sizePage.cy = (int)((float)m_sizeLogPage.cy * m_fZoomScale); + + CScrollImpl< T >::SetScrollPage(sizePage); + } + + void SetScrollPage(SIZE sizeLogPage) + { + SetScrollPage(sizeLogPage.cx, sizeLogPage.cy); + } + + void GetScrollPage(SIZE& sizeLogPage) const + { + sizeLogPage = m_sizeLogPage; + } + + void SetZoomScale(float fZoomScale) + { + ATLASSERT(fZoomScale > 0); + + if(fZoomScale > 0 && fZoomScale >= m_fZoomScaleMin) + m_fZoomScale = fZoomScale; + } + + float GetZoomScale() const + { + return m_fZoomScale; + } + + void SetZoomScaleMin(float fZoomScaleMin) + { + m_fZoomScaleMin = fZoomScaleMin; + } + + float GetZoomScaleMin() const + { + return m_fZoomScaleMin; + } + + void SetZoomDelta(float fZoomDelta) + { + ATLASSERT(fZoomDelta >= 0); + + if(fZoomDelta >= 0) + m_fZoomDelta = fZoomDelta; + } + + float GetZoomDelta() const + { + return m_fZoomDelta; + } + + void SetZoomMode(int nZoomMode) + { + m_nZoomMode = nZoomMode; + } + + int GetZoomMode() const + { + return m_nZoomMode; + } + + void Zoom(int x, int y, float fZoomScale) + { + if(fZoomScale <= 0) + return; + + fZoomScale = max(fZoomScale, m_fZoomScaleMin); + + T* pT = static_cast(this); + POINT pt = { x, y }; + if(!pT->PtInDevRect(pt)) + return; + + pT->ViewDPtoLP(&pt); + pT->Zoom(fZoomScale, false); + pT->CenterOnLogicalPoint(pt); + } + + void Zoom(POINT pt, float fZoomScale) + { + T* pT = static_cast(this); + pT->Zoom(pt.x, pt.y, fZoomScale); + } + + void Zoom(RECT& rc) + { + T* pT = static_cast(this); + RECT rcZoom = rc; + pT->NormalizeRect(rcZoom); + SIZE size = { rcZoom.right - rcZoom.left, rcZoom.bottom - rcZoom.top }; + POINT pt = { rcZoom.left + size.cx / 2, rcZoom.top + size.cy / 2 }; + if(size.cx < m_cxyMinZoomRect || size.cy < m_cxyMinZoomRect) + { + pT->Zoom(pt, m_fZoomScale + m_fZoomDelta); + return; + } + + ATLASSERT(size.cx > 0 && size.cy > 0); + + float fScaleH = (float)(m_sizeClient.cx + 1) / (float)size.cx; + float fScaleV = (float)(m_sizeClient.cy + 1) / (float)size.cy; + float fZoomScale = min(fScaleH, fScaleV) * m_fZoomScale; + pT->Zoom(pt, fZoomScale); + } + + void Zoom(float fZoomScale, bool bCenter = true) + { + if(fZoomScale <= 0) + return; + + fZoomScale = max(fZoomScale, m_fZoomScaleMin); + + + T* pT = static_cast(this); + POINT pt = { 0 }; + if(bCenter) + { + RECT rc; + ::GetClientRect(pT->m_hWnd, &rc); + pt.x = rc.right / 2; + pt.y = rc.bottom / 2; + pT->ViewDPtoLP(&pt); + } + + // Modify the Viewport extent + m_fZoomScale = fZoomScale; + SIZE sizeAll = { 0 }; + sizeAll.cx = (int)((float)m_sizeLogAll.cx * fZoomScale); + sizeAll.cy = (int)((float)m_sizeLogAll.cy * fZoomScale); + + // Update scroll bars and window + CScrollImpl< T >::SetScrollSize(sizeAll); + + if(bCenter) + pT->CenterOnLogicalPoint(pt); + } + + // Helper functions + void PrepareDC(CDCHandle dc) + { + ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0); + dc.SetMapMode(MM_ANISOTROPIC); + dc.SetWindowExt(m_sizeLogAll); + dc.SetViewportExt(m_sizeAll); + dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y); + } + + void ViewDPtoLP(LPPOINT lpPoints, int nCount = 1) + { + ATLASSERT(lpPoints); + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + + CWindowDC dc(pT->m_hWnd); + pT->PrepareDC(dc.m_hDC); + dc.DPtoLP(lpPoints, nCount); + } + + void ViewLPtoDP(LPPOINT lpPoints, int nCount = 1) + { + ATLASSERT(lpPoints); + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + + CWindowDC dc(pT->m_hWnd); + pT->PrepareDC(dc.m_hDC); + dc.LPtoDP(lpPoints, nCount); + } + + void ClientToDevice(POINT &pt) + { + pt.x += m_ptOffset.x; + pt.y += m_ptOffset.y; + } + + void DeviceToClient(POINT &pt) + { + pt.x -= m_ptOffset.x; + pt.y -= m_ptOffset.y; + } + + void CenterOnPoint(POINT pt) + { + T* pT = static_cast(this); + RECT rect; + pT->GetClientRect(&rect); + + int xOfs = pt.x - (rect.right / 2) + m_ptOffset.x; + if(xOfs < 0) + { + xOfs = 0; + } + else + { + int xMax = max((int)(m_sizeAll.cx - rect.right), 0); + if(xOfs > xMax) + xOfs = xMax; + } + + int yOfs = pt.y - (rect.bottom / 2) + m_ptOffset.y; + if(yOfs < 0) + { + yOfs = 0; + } + else + { + int yMax = max((int)(m_sizeAll.cy - rect.bottom), 0); + if(yOfs > yMax) + yOfs = yMax; + } + + CScrollImpl< T >::SetScrollOffset(xOfs, yOfs); + } + + void CenterOnLogicalPoint(POINT ptLog) + { + T* pT = static_cast(this); + pT->ViewLPtoDP(&ptLog); + pT->DeviceToClient(ptLog); + pT->CenterOnPoint(ptLog); + } + + BOOL PtInDevRect(POINT pt) + { + RECT rc = { 0, 0, m_sizeAll.cx, m_sizeAll.cy }; + ::OffsetRect(&rc, -m_ptOffset.x, -m_ptOffset.y); + return ::PtInRect(&rc, pt); + } + + void NormalizeRect(RECT& rc) + { + if(rc.left > rc.right) + { + int r = rc.right; + rc.right = rc.left; + rc.left = r; + } + if(rc.top > rc.bottom) + { + int b = rc.bottom; + rc.bottom = rc.top; + rc.top = b; + } + } + + void DrawTrackRect() + { + T* pT = static_cast(this); + const SIZE sizeLines = { 2, 2 }; + RECT rc = m_rcTrack; + pT->NormalizeRect(rc); + if(!::IsRectEmpty(&rc)) + { + ::MapWindowPoints(pT->m_hWnd, NULL, (LPPOINT)&rc, 2); + CWindowDC dc(NULL); + dc.DrawDragRect(&rc, sizeLines, NULL, sizeLines); + } + } + + void NotifyParentZoomChanged() + { + T* pT = static_cast(this); + int nId = pT->GetDlgCtrlID(); + NMHDR nmhdr = { pT->m_hWnd, nId, ZSN_ZOOMCHANGED }; + ::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nId, (LPARAM)&nmhdr); + } + + BEGIN_MSG_MAP(CZoomScrollImpl) + MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor) + MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) + MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) + MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) +#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) + MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) +#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) + MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) + MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) + MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) + MESSAGE_HANDLER(WM_PAINT, OnPaint) + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) + MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) + MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) + MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) + MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged) + ALT_MSG_MAP(1) + COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) + COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) + COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) + COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) + COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) + COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) + COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) + COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) + END_MSG_MAP() + + LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + ATLASSERT(m_sizeLogAll.cx >= 0 && m_sizeLogAll.cy >= 0); + ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0); + + if(wParam != NULL) + { + CDCHandle dc = (HDC)wParam; + int nMapModeSav = dc.GetMapMode(); + dc.SetMapMode(MM_ANISOTROPIC); + SIZE szWindowExt = { 0, 0 }; + dc.SetWindowExt(m_sizeLogAll, &szWindowExt); + SIZE szViewportExt = { 0, 0 }; + dc.SetViewportExt(m_sizeAll, &szViewportExt); + POINT ptViewportOrg = { 0, 0 }; + dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg); + + pT->DoPaint(dc); + + dc.SetMapMode(nMapModeSav); + dc.SetWindowExt(szWindowExt); + dc.SetViewportExt(szViewportExt); + dc.SetViewportOrg(ptViewportOrg); + } + else + { + CPaintDC dc(pT->m_hWnd); + pT->PrepareDC(dc.m_hDC); + pT->DoPaint(dc.m_hDC); + } + return 0; + } + + LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + if(m_nZoomMode == ZOOMMODE_IN && !m_bTracking) + { + T* pT = static_cast(this); + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + if(pT->PtInDevRect(pt)) + { + pT->SetCapture(); + m_bTracking = true; + ::SetRect(&m_rcTrack, pt.x, pt.y, pt.x, pt.y); + } + } + bHandled = FALSE; + return 0; + } + + LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + if(m_bTracking) + { + T* pT = static_cast(this); + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + if(pT->PtInDevRect(pt)) + { + pT->DrawTrackRect(); + m_rcTrack.right = pt.x; + m_rcTrack.bottom = pt.y; + pT->DrawTrackRect(); + } + } + bHandled = FALSE; + return 0; + } + + LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + ::ReleaseCapture(); + if(m_nZoomMode == ZOOMMODE_OUT) + { + T* pT = static_cast(this); + pT->Zoom(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), m_fZoomScale - m_fZoomDelta); + pT->NotifyParentZoomChanged(); + } + bHandled = FALSE; + return 0; + } + + LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + if(m_bTracking) + { + m_bTracking = false; + T* pT = static_cast(this); + pT->DrawTrackRect(); + pT->Zoom(m_rcTrack); + pT->NotifyParentZoomChanged(); + ::SetRectEmpty(&m_rcTrack); + } + bHandled = FALSE; + return 0; + } + + LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + if(LOWORD(lParam) == HTCLIENT && m_nZoomMode != ZOOMMODE_OFF) + { + T* pT = static_cast(this); + if((HWND)wParam == pT->m_hWnd) + { + DWORD dwPos = ::GetMessagePos(); + POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) }; + pT->ScreenToClient(&pt); + if(pT->PtInDevRect(pt)) + { + ::SetCursor(::LoadCursor(NULL, IDC_CROSS)); + return 1; + } + } + } + bHandled = FALSE; + return 0; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// CZoomScrollWindowImpl - Implements scrolling window with zooming + +template +class ATL_NO_VTABLE CZoomScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T > +{ +public: + BEGIN_MSG_MAP(CZoomScrollWindowImpl) + MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor) + MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) + MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) + MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) +#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) + MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) +#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) + MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) + MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) + MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) + MESSAGE_HANDLER(WM_PAINT, CZoomScrollImpl< T >::OnPaint) + MESSAGE_HANDLER(WM_PRINTCLIENT, CZoomScrollImpl< T >::OnPaint) + MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown) + MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove) + MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp) + MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged) + ALT_MSG_MAP(1) + COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) + COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) + COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) + COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) + COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) + COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) + COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) + COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) + COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) + END_MSG_MAP() +}; + +#endif // !_WIN32_WCE + + +/////////////////////////////////////////////////////////////////////////////// +// CScrollContainer + +template +class ATL_NO_VTABLE CScrollContainerImpl : public CScrollWindowImpl< T, TBase, TWinTraits > +{ +public: + DECLARE_WND_CLASS_EX(NULL, 0, -1) + + typedef CScrollWindowImpl< T, TBase, TWinTraits > _baseClass; + +// Data members + ATL::CWindow m_wndClient; + bool m_bAutoSizeClient; + bool m_bDrawEdgeIfEmpty; + +// Constructor + CScrollContainerImpl() : m_bAutoSizeClient(true), m_bDrawEdgeIfEmpty(false) + { + // Set CScrollWindowImpl extended style + SetScrollExtendedStyle(SCRL_SCROLLCHILDREN); + } + +// Attributes + HWND GetClient() const + { + return m_wndClient; + } + + HWND SetClient(HWND hWndClient, bool bClientSizeAsMin = true) + { + ATLASSERT(::IsWindow(m_hWnd)); + + HWND hWndOldClient = m_wndClient; + m_wndClient = hWndClient; + + SetRedraw(FALSE); + SetScrollSize(1, 1, FALSE); + + if(m_wndClient.m_hWnd != NULL) + { + m_wndClient.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + + if(bClientSizeAsMin) + { + RECT rect = { 0 }; + m_wndClient.GetWindowRect(&rect); + if((rect.right - rect.left) > 0 && (rect.bottom - rect.top) > 0) + SetScrollSize(rect.right - rect.left, rect.bottom - rect.top, FALSE); + } + + T* pT = static_cast(this); + pT->UpdateLayout(); + } + + SetRedraw(TRUE); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); + + return hWndOldClient; + } + +// Message map and handlers + BEGIN_MSG_MAP(CScrollContainerImpl) + MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) + MESSAGE_HANDLER(WM_SIZE, OnSize) + CHAIN_MSG_MAP(_baseClass) + FORWARD_NOTIFICATIONS() + ALT_MSG_MAP(1) + CHAIN_MSG_MAP_ALT(_baseClass, 1) + END_MSG_MAP() + + LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + if(m_wndClient.m_hWnd != NULL) + m_wndClient.SetFocus(); + + return 0; + } + + LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return 1; // no background needed + } + + LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + BOOL bTmp = TRUE; + LRESULT lRet = _baseClass::OnSize(uMsg, wParam, lParam, bTmp); + + T* pT = static_cast(this); + pT->UpdateLayout(); + + return lRet; + } + +// Overrides for CScrollWindowImpl + void DoPaint(CDCHandle dc) + { + if(!m_bAutoSizeClient || m_wndClient.m_hWnd == NULL) + { + T* pT = static_cast(this); + RECT rect = { 0 }; + pT->GetContainerRect(rect); + + if(m_bDrawEdgeIfEmpty && m_wndClient.m_hWnd == NULL) + dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); + + dc.FillRect(&rect, COLOR_APPWORKSPACE); + } + } + + void ScrollToView(POINT pt) + { + CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(pt); + } + + void ScrollToView(RECT& rect) + { + CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(rect); + } + + void ScrollToView(HWND hWnd) // client window coordinates + { + T* pT = static_cast(this); + pT; // avoid level 4 warning + ATLASSERT(::IsWindow(pT->m_hWnd)); + ATLASSERT(m_wndClient.IsWindow()); + + RECT rect = { 0 }; + ::GetWindowRect(hWnd, &rect); + ::MapWindowPoints(NULL, m_wndClient.m_hWnd, (LPPOINT)&rect, 2); + ScrollToView(rect); + } + +// Implementation - overrideable methods + void UpdateLayout() + { + ATLASSERT(::IsWindow(m_hWnd)); + + if(m_bAutoSizeClient && m_wndClient.m_hWnd != NULL) + { + T* pT = static_cast(this); + RECT rect = { 0 }; + pT->GetContainerRect(rect); + + m_wndClient.SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE); + } + else + { + Invalidate(); + } + } + + void GetContainerRect(RECT& rect) + { + GetClientRect(&rect); + + if(rect.right < m_sizeAll.cx) + rect.right = m_sizeAll.cx; + + if(rect.bottom < m_sizeAll.cy) + rect.bottom = m_sizeAll.cy; + } +}; + +class CScrollContainer : public CScrollContainerImpl +{ +public: + DECLARE_WND_CLASS_EX(_T("WTL_ScrollContainer"), 0, -1) +}; + +}; // namespace WTL + +#endif // __ATLSCRL_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlsplit.h b/Client/Client/GUI/BKWin/wtl/atlsplit.h new file mode 100644 index 00000000..9f9424b2 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlsplit.h @@ -0,0 +1,889 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLSPLIT_H__ +#define __ATLSPLIT_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifndef __ATLAPP_H__ + #error atlsplit.h requires atlapp.h to be included first +#endif + +#ifndef __ATLWIN_H__ + #error atlsplit.h requires atlwin.h to be included first +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CSplitterImpl +// CSplitterWindowImpl +// CSplitterWindowT + + +namespace WTL +{ + +/////////////////////////////////////////////////////////////////////////////// +// CSplitterImpl - Provides splitter support to any window + +// Splitter panes constants +#define SPLIT_PANE_LEFT 0 +#define SPLIT_PANE_RIGHT 1 +#define SPLIT_PANE_TOP SPLIT_PANE_LEFT +#define SPLIT_PANE_BOTTOM SPLIT_PANE_RIGHT +#define SPLIT_PANE_NONE -1 + +// Splitter extended styles +#define SPLIT_PROPORTIONAL 0x00000001 +#define SPLIT_NONINTERACTIVE 0x00000002 +#define SPLIT_RIGHTALIGNED 0x00000004 +#define SPLIT_BOTTOMALIGNED SPLIT_RIGHTALIGNED + +// Note: SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED/SPLIT_BOTTOMALIGNED are +// mutually exclusive. If both are set, splitter defaults to SPLIT_PROPORTIONAL + + +template +class CSplitterImpl +{ +public: + enum { m_nPanesCount = 2, m_nPropMax = 10000 }; + + HWND m_hWndPane[m_nPanesCount]; + RECT m_rcSplitter; + int m_xySplitterPos; + int m_nDefActivePane; + int m_cxySplitBar; // splitter bar width/height + static HCURSOR m_hCursor; + int m_cxyMin; // minimum pane size + int m_cxyBarEdge; // splitter bar edge + bool m_bFullDrag; + int m_cxyDragOffset; + int m_nProportionalPos; + bool m_bUpdateProportionalPos; + DWORD m_dwExtendedStyle; // splitter specific extended styles + int m_nSinglePane; // single pane mode + +// Constructor + CSplitterImpl() : + m_xySplitterPos(-1), m_nDefActivePane(SPLIT_PANE_NONE), + m_cxySplitBar(0), m_cxyMin(0), m_cxyBarEdge(0), m_bFullDrag(true), + m_cxyDragOffset(0), m_nProportionalPos(0), m_bUpdateProportionalPos(true), + m_dwExtendedStyle(SPLIT_PROPORTIONAL), + m_nSinglePane(SPLIT_PANE_NONE) + { + m_hWndPane[SPLIT_PANE_LEFT] = NULL; + m_hWndPane[SPLIT_PANE_RIGHT] = NULL; + + ::SetRectEmpty(&m_rcSplitter); + + if(m_hCursor == NULL) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CSplitterImpl::CSplitterImpl.\n")); + ATLASSERT(FALSE); + return; + } + + if(m_hCursor == NULL) + m_hCursor = ::LoadCursor(NULL, t_bVertical ? IDC_SIZEWE : IDC_SIZENS); + + lock.Unlock(); + } + } + +// Attributes + void SetSplitterRect(LPRECT lpRect = NULL, bool bUpdate = true) + { + if(lpRect == NULL) + { + T* pT = static_cast(this); + pT->GetClientRect(&m_rcSplitter); + } + else + { + m_rcSplitter = *lpRect; + } + + if(IsProportional()) + UpdateProportionalPos(); + else if(IsRightAligned()) + UpdateRightAlignPos(); + + if(bUpdate) + UpdateSplitterLayout(); + } + + void GetSplitterRect(LPRECT lpRect) const + { + ATLASSERT(lpRect != NULL); + *lpRect = m_rcSplitter; + } + + bool SetSplitterPos(int xyPos = -1, bool bUpdate = true) + { + if(xyPos == -1) // -1 == middle + { + if(t_bVertical) + xyPos = (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) / 2; + else + xyPos = (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge) / 2; + } + + // Adjust if out of valid range + int cxyMax = 0; + if(t_bVertical) + cxyMax = m_rcSplitter.right - m_rcSplitter.left; + else + cxyMax = m_rcSplitter.bottom - m_rcSplitter.top; + + if(xyPos < m_cxyMin + m_cxyBarEdge) + xyPos = m_cxyMin; + else if(xyPos > (cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin)) + xyPos = cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin; + + // Set new position and update if requested + bool bRet = (m_xySplitterPos != xyPos); + m_xySplitterPos = xyPos; + + if(m_bUpdateProportionalPos) + { + if(IsProportional()) + StoreProportionalPos(); + else if(IsRightAligned()) + StoreRightAlignPos(); + } + else + { + m_bUpdateProportionalPos = true; + } + + if(bUpdate && bRet) + UpdateSplitterLayout(); + + return bRet; + } + + void SetSplitterPosPct(int nPct, bool bUpdate = true) + { + ATLASSERT(nPct >= 0 && nPct <= 100); + + m_nProportionalPos = ::MulDiv(nPct, m_nPropMax, 100); + UpdateProportionalPos(); + + if(bUpdate) + UpdateSplitterLayout(); + } + + int GetSplitterPos() const + { + return m_xySplitterPos; + } + + bool SetSinglePaneMode(int nPane = SPLIT_PANE_NONE) + { + ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT || nPane == SPLIT_PANE_NONE); + if(!(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT || nPane == SPLIT_PANE_NONE)) + return false; + + if(nPane != SPLIT_PANE_NONE) + { + if(!::IsWindowVisible(m_hWndPane[nPane])) + ::ShowWindow(m_hWndPane[nPane], SW_SHOW); + int nOtherPane = (nPane == SPLIT_PANE_LEFT) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT; + ::ShowWindow(m_hWndPane[nOtherPane], SW_HIDE); + if(m_nDefActivePane != nPane) + m_nDefActivePane = nPane; + } + else if(m_nSinglePane != SPLIT_PANE_NONE) + { + int nOtherPane = (m_nSinglePane == SPLIT_PANE_LEFT) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT; + ::ShowWindow(m_hWndPane[nOtherPane], SW_SHOW); + } + + m_nSinglePane = nPane; + UpdateSplitterLayout(); + return true; + } + + int GetSinglePaneMode() const + { + return m_nSinglePane; + } + + DWORD GetSplitterExtendedStyle() const + { + return m_dwExtendedStyle; + } + + DWORD SetSplitterExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) + { + DWORD dwPrevStyle = m_dwExtendedStyle; + if(dwMask == 0) + m_dwExtendedStyle = dwExtendedStyle; + else + m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); +#ifdef _DEBUG + if(IsProportional() && IsRightAligned()) + ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::SetSplitterExtendedStyle - SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED are mutually exclusive, defaulting to SPLIT_PROPORTIONAL.\n")); +#endif // _DEBUG + return dwPrevStyle; + } + +// Splitter operations + void SetSplitterPanes(HWND hWndLeftTop, HWND hWndRightBottom, bool bUpdate = true) + { + m_hWndPane[SPLIT_PANE_LEFT] = hWndLeftTop; + m_hWndPane[SPLIT_PANE_RIGHT] = hWndRightBottom; + ATLASSERT(m_hWndPane[SPLIT_PANE_LEFT] == NULL || m_hWndPane[SPLIT_PANE_RIGHT] == NULL || m_hWndPane[SPLIT_PANE_LEFT] != m_hWndPane[SPLIT_PANE_RIGHT]); + if(bUpdate) + UpdateSplitterLayout(); + } + + bool SetSplitterPane(int nPane, HWND hWnd, bool bUpdate = true) + { + ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); + + if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT) + return false; + m_hWndPane[nPane] = hWnd; + ATLASSERT(m_hWndPane[SPLIT_PANE_LEFT] == NULL || m_hWndPane[SPLIT_PANE_RIGHT] == NULL || m_hWndPane[SPLIT_PANE_LEFT] != m_hWndPane[SPLIT_PANE_RIGHT]); + if(bUpdate) + UpdateSplitterLayout(); + return true; + } + + HWND GetSplitterPane(int nPane) const + { + ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); + + if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT) + return false; + return m_hWndPane[nPane]; + } + + bool SetActivePane(int nPane) + { + ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); + + if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT) + return false; + if(m_nSinglePane != SPLIT_PANE_NONE && nPane != m_nSinglePane) + return false; + ::SetFocus(m_hWndPane[nPane]); + m_nDefActivePane = nPane; + return true; + } + + int GetActivePane() const + { + int nRet = SPLIT_PANE_NONE; + HWND hWndFocus = ::GetFocus(); + if(hWndFocus != NULL) + { + for(int nPane = 0; nPane < m_nPanesCount; nPane++) + { + if(hWndFocus == m_hWndPane[nPane] || ::IsChild(m_hWndPane[nPane], hWndFocus)) + { + nRet = nPane; + break; + } + } + } + return nRet; + } + + bool ActivateNextPane(bool bNext = true) + { + int nPane = m_nSinglePane; + if(nPane == SPLIT_PANE_NONE) + { + switch(GetActivePane()) + { + case SPLIT_PANE_LEFT: + nPane = SPLIT_PANE_RIGHT; + break; + case SPLIT_PANE_RIGHT: + nPane = SPLIT_PANE_LEFT; + break; + default: + nPane = bNext ? SPLIT_PANE_LEFT : SPLIT_PANE_RIGHT; + break; + } + } + return SetActivePane(nPane); + } + + bool SetDefaultActivePane(int nPane) + { + ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); + + if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT) + return false; + m_nDefActivePane = nPane; + return true; + } + + bool SetDefaultActivePane(HWND hWnd) + { + for(int nPane = 0; nPane < m_nPanesCount; nPane++) + { + if(hWnd == m_hWndPane[nPane]) + { + m_nDefActivePane = nPane; + return true; + } + } + return false; // not found + } + + int GetDefaultActivePane() const + { + return m_nDefActivePane; + } + + void DrawSplitter(CDCHandle dc) + { + ATLASSERT(dc.m_hDC != NULL); + if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1) + return; + + T* pT = static_cast(this); + if(m_nSinglePane == SPLIT_PANE_NONE) + { + pT->DrawSplitterBar(dc); + + for(int nPane = 0; nPane < m_nPanesCount; nPane++) + { + if(m_hWndPane[nPane] == NULL) + pT->DrawSplitterPane(dc, nPane); + } + } + else + { + if(m_hWndPane[m_nSinglePane] == NULL) + pT->DrawSplitterPane(dc, m_nSinglePane); + } + } + +// Overrideables + void DrawSplitterBar(CDCHandle dc) + { + RECT rect; + if(GetSplitterBarRect(&rect)) + { + dc.FillRect(&rect, COLOR_3DFACE); + // draw 3D edge if needed + T* pT = static_cast(this); + if((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0) + dc.DrawEdge(&rect, EDGE_RAISED, t_bVertical ? (BF_LEFT | BF_RIGHT) : (BF_TOP | BF_BOTTOM)); + } + } + + // called only if pane is empty + void DrawSplitterPane(CDCHandle dc, int nPane) + { + RECT rect; + if(GetSplitterPaneRect(nPane, &rect)) + { + T* pT = static_cast(this); + if((pT->GetExStyle() & WS_EX_CLIENTEDGE) == 0) + dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); + dc.FillRect(&rect, COLOR_APPWORKSPACE); + } + } + +// Message map and handlers + BEGIN_MSG_MAP(CSplitterImpl) + MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_PAINT, OnPaint) +#ifndef _WIN32_WCE + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) +#endif // !_WIN32_WCE + if(IsInteractive()) + { + MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor) + MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) + MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) + MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) + MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDoubleClick) + MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged) + } + MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) +#ifndef _WIN32_WCE + MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate) +#endif // !_WIN32_WCE + MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) + END_MSG_MAP() + + LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + GetSystemSettings(false); + bHandled = FALSE; + return 1; + } + + LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + // try setting position if not set + if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1) + pT->SetSplitterPos(); + // do painting + CPaintDC dc(pT->m_hWnd); + pT->DrawSplitter(dc.m_hDC); + return 0; + } + + LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + T* pT = static_cast(this); + if((HWND)wParam == pT->m_hWnd && LOWORD(lParam) == HTCLIENT) + { + DWORD dwPos = ::GetMessagePos(); + POINT ptPos = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) }; + pT->ScreenToClient(&ptPos); + if(IsOverSplitterBar(ptPos.x, ptPos.y)) + return 1; + } + + bHandled = FALSE; + return 0; + } + + LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + T* pT = static_cast(this); + int xPos = GET_X_LPARAM(lParam); + int yPos = GET_Y_LPARAM(lParam); + if((wParam & MK_LBUTTON) && ::GetCapture() == pT->m_hWnd) + { + int xyNewSplitPos = 0; + if(t_bVertical) + xyNewSplitPos = xPos - m_rcSplitter.left - m_cxyDragOffset; + else + xyNewSplitPos = yPos - m_rcSplitter.top - m_cxyDragOffset; + + if(xyNewSplitPos == -1) // avoid -1, that means middle + xyNewSplitPos = -2; + + if(m_xySplitterPos != xyNewSplitPos) + { + if(m_bFullDrag) + { + if(pT->SetSplitterPos(xyNewSplitPos, true)) + pT->UpdateWindow(); + } + else + { + DrawGhostBar(); + pT->SetSplitterPos(xyNewSplitPos, false); + DrawGhostBar(); + } + } + } + else // not dragging, just set cursor + { + if(IsOverSplitterBar(xPos, yPos)) + ::SetCursor(m_hCursor); + bHandled = FALSE; + } + + return 0; + } + + LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + int xPos = GET_X_LPARAM(lParam); + int yPos = GET_Y_LPARAM(lParam); + if(IsOverSplitterBar(xPos, yPos)) + { + T* pT = static_cast(this); + pT->SetCapture(); + ::SetCursor(m_hCursor); + if(!m_bFullDrag) + DrawGhostBar(); + if(t_bVertical) + m_cxyDragOffset = xPos - m_rcSplitter.left - m_xySplitterPos; + else + m_cxyDragOffset = yPos - m_rcSplitter.top - m_xySplitterPos; + } + bHandled = FALSE; + return 1; + } + + LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + ::ReleaseCapture(); + bHandled = FALSE; + return 1; + } + + LRESULT OnLButtonDoubleClick(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->SetSplitterPos(); // middle + return 0; + } + + LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + if(!m_bFullDrag) + { + DrawGhostBar(); + UpdateSplitterLayout(); + T* pT = static_cast(this); + pT->UpdateWindow(); + } + return 0; + } + + LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM, BOOL& bHandled) + { + if(m_nSinglePane == SPLIT_PANE_NONE) + { + if(m_nDefActivePane == SPLIT_PANE_LEFT || m_nDefActivePane == SPLIT_PANE_RIGHT) + ::SetFocus(m_hWndPane[m_nDefActivePane]); + } + else + { + ::SetFocus(m_hWndPane[m_nSinglePane]); + } + bHandled = FALSE; + return 1; + } + +#ifndef _WIN32_WCE + LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam); + if(lRet == MA_ACTIVATE || lRet == MA_ACTIVATEANDEAT) + { + DWORD dwPos = ::GetMessagePos(); + POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) }; + pT->ScreenToClient(&pt); + RECT rcPane; + for(int nPane = 0; nPane < m_nPanesCount; nPane++) + { + if(GetSplitterPaneRect(nPane, &rcPane) && ::PtInRect(&rcPane, pt)) + { + m_nDefActivePane = nPane; + break; + } + } + } + return lRet; + } +#endif // !_WIN32_WCE + + LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + GetSystemSettings(true); + return 0; + } + +// Implementation - internal helpers + void UpdateSplitterLayout() + { + if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1) + return; + + T* pT = static_cast(this); + RECT rect = { 0, 0, 0, 0 }; + if(m_nSinglePane == SPLIT_PANE_NONE) + { + if(GetSplitterBarRect(&rect)) + pT->InvalidateRect(&rect); + + for(int nPane = 0; nPane < m_nPanesCount; nPane++) + { + if(GetSplitterPaneRect(nPane, &rect)) + { + if(m_hWndPane[nPane] != NULL) + ::SetWindowPos(m_hWndPane[nPane], NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER); + else + pT->InvalidateRect(&rect); + } + } + } + else + { + if(GetSplitterPaneRect(m_nSinglePane, &rect)) + { + if(m_hWndPane[m_nSinglePane] != NULL) + ::SetWindowPos(m_hWndPane[m_nSinglePane], NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER); + else + pT->InvalidateRect(&rect); + } + } + } + + bool GetSplitterBarRect(LPRECT lpRect) const + { + ATLASSERT(lpRect != NULL); + if(m_nSinglePane != SPLIT_PANE_NONE || m_xySplitterPos == -1) + return false; + + if(t_bVertical) + { + lpRect->left = m_rcSplitter.left + m_xySplitterPos; + lpRect->top = m_rcSplitter.top; + lpRect->right = m_rcSplitter.left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge; + lpRect->bottom = m_rcSplitter.bottom; + } + else + { + lpRect->left = m_rcSplitter.left; + lpRect->top = m_rcSplitter.top + m_xySplitterPos; + lpRect->right = m_rcSplitter.right; + lpRect->bottom = m_rcSplitter.top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge; + } + + return true; + } + + bool GetSplitterPaneRect(int nPane, LPRECT lpRect) const + { + ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); + ATLASSERT(lpRect != NULL); + bool bRet = true; + if(m_nSinglePane != SPLIT_PANE_NONE) + { + if(nPane == m_nSinglePane) + *lpRect = m_rcSplitter; + else + bRet = false; + } + else if(nPane == SPLIT_PANE_LEFT) + { + if(t_bVertical) + { + lpRect->left = m_rcSplitter.left; + lpRect->top = m_rcSplitter.top; + lpRect->right = m_rcSplitter.left + m_xySplitterPos; + lpRect->bottom = m_rcSplitter.bottom; + } + else + { + lpRect->left = m_rcSplitter.left; + lpRect->top = m_rcSplitter.top; + lpRect->right = m_rcSplitter.right; + lpRect->bottom = m_rcSplitter.top + m_xySplitterPos; + } + } + else if(nPane == SPLIT_PANE_RIGHT) + { + if(t_bVertical) + { + lpRect->left = m_rcSplitter.left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge; + lpRect->top = m_rcSplitter.top; + lpRect->right = m_rcSplitter.right; + lpRect->bottom = m_rcSplitter.bottom; + } + else + { + lpRect->left = m_rcSplitter.left; + lpRect->top = m_rcSplitter.top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge; + lpRect->right = m_rcSplitter.right; + lpRect->bottom = m_rcSplitter.bottom; + } + } + else + { + bRet = false; + } + return bRet; + } + + bool IsOverSplitterRect(int x, int y) const + { + // -1 == don't check + return ((x == -1 || (x >= m_rcSplitter.left && x <= m_rcSplitter.right)) && + (y == -1 || (y >= m_rcSplitter.top && y <= m_rcSplitter.bottom))); + } + + bool IsOverSplitterBar(int x, int y) const + { + if(m_nSinglePane != SPLIT_PANE_NONE) + return false; + if(m_xySplitterPos == -1 || !IsOverSplitterRect(x, y)) + return false; + int xy = t_bVertical ? x : y; + int xyOff = t_bVertical ? m_rcSplitter.left : m_rcSplitter.top; + return ((xy >= (xyOff + m_xySplitterPos)) && (xy < xyOff + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge)); + } + + void DrawGhostBar() + { + RECT rect = { 0, 0, 0, 0 }; + if(GetSplitterBarRect(&rect)) + { + // invert the brush pattern (looks just like frame window sizing) + T* pT = static_cast(this); + CWindowDC dc(pT->m_hWnd); + CBrush brush = CDCHandle::GetHalftoneBrush(); + if(brush.m_hBrush != NULL) + { + CBrushHandle brushOld = dc.SelectBrush(brush); + dc.PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT); + dc.SelectBrush(brushOld); + } + } + } + + void GetSystemSettings(bool bUpdate) + { +#ifndef _WIN32_WCE + m_cxySplitBar = ::GetSystemMetrics(t_bVertical ? SM_CXSIZEFRAME : SM_CYSIZEFRAME); +#else // CE specific + m_cxySplitBar = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE); +#endif // _WIN32_WCE + + T* pT = static_cast(this); + if((pT->GetExStyle() & WS_EX_CLIENTEDGE)) + { + m_cxyBarEdge = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE); + m_cxyMin = 0; + } + else + { + m_cxyBarEdge = 0; + m_cxyMin = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE); + } + +#ifndef _WIN32_WCE + ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &m_bFullDrag, 0); +#endif // !_WIN32_WCE + + if(bUpdate) + UpdateSplitterLayout(); + } + + bool IsProportional() const + { + return ((m_dwExtendedStyle & SPLIT_PROPORTIONAL) != 0); + } + + void StoreProportionalPos() + { + int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge); + if(cxyTotal > 0) + m_nProportionalPos = ::MulDiv(m_xySplitterPos, m_nPropMax, cxyTotal); + else + m_nProportionalPos = 0; + ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::StoreProportionalPos - %i\n"), m_nProportionalPos); + } + + void UpdateProportionalPos() + { + int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge); + if(cxyTotal > 0) + { + int xyNewPos = ::MulDiv(m_nProportionalPos, cxyTotal, m_nPropMax); + m_bUpdateProportionalPos = false; + T* pT = static_cast(this); + pT->SetSplitterPos(xyNewPos, false); + } + } + + bool IsRightAligned() const + { + return ((m_dwExtendedStyle & SPLIT_RIGHTALIGNED) != 0); + } + + void StoreRightAlignPos() + { + int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge); + if(cxyTotal > 0) + m_nProportionalPos = cxyTotal - m_xySplitterPos; + else + m_nProportionalPos = 0; + ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::StoreRightAlignPos - %i\n"), m_nProportionalPos); + } + + void UpdateRightAlignPos() + { + int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge); + if(cxyTotal > 0) + { + m_bUpdateProportionalPos = false; + T* pT = static_cast(this); + pT->SetSplitterPos(cxyTotal - m_nProportionalPos, false); + } + } + + bool IsInteractive() const + { + return ((m_dwExtendedStyle & SPLIT_NONINTERACTIVE) == 0); + } +}; + +template HCURSOR CSplitterImpl< T, t_bVertical>::m_hCursor = NULL; + + +/////////////////////////////////////////////////////////////////////////////// +// CSplitterWindowImpl - Implements a splitter window + +template +class ATL_NO_VTABLE CSplitterWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CSplitterImpl< T , t_bVertical > +{ +public: + DECLARE_WND_CLASS_EX(NULL, CS_DBLCLKS, COLOR_WINDOW) + + typedef CSplitterImpl< T , t_bVertical > _baseClass; + + BEGIN_MSG_MAP(CSplitterWindowImpl) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) + MESSAGE_HANDLER(WM_SIZE, OnSize) + CHAIN_MSG_MAP(_baseClass) + FORWARD_NOTIFICATIONS() + END_MSG_MAP() + + LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + // handled, no background painting needed + return 1; + } + + LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + if(wParam != SIZE_MINIMIZED) + SetSplitterRect(); + + bHandled = FALSE; + return 1; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CSplitterWindow - Implements a splitter window to be used as is + +template +class CSplitterWindowT : public CSplitterWindowImpl, t_bVertical> +{ +public: + DECLARE_WND_CLASS_EX(_T("WTL_SplitterWindow"), CS_DBLCLKS, COLOR_WINDOW) +}; + +typedef CSplitterWindowT CSplitterWindow; +typedef CSplitterWindowT CHorSplitterWindow; + +}; // namespace WTL + +#endif // __ATLSPLIT_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atltheme.h b/Client/Client/GUI/BKWin/wtl/atltheme.h new file mode 100644 index 00000000..73d46e82 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atltheme.h @@ -0,0 +1,1215 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLTHEME_H__ +#define __ATLTHEME_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifdef _WIN32_WCE + #error atltheme.h is not supported on Windows CE +#endif + +#ifndef __ATLAPP_H__ + #error atltheme.h requires atlapp.h to be included first +#endif + +#ifndef __ATLWIN_H__ + #error atltheme.h requires atlwin.h to be included first +#endif + +#if (_WIN32_WINNT < 0x0501) + #error atltheme.h requires _WIN32_WINNT >= 0x0501 +#endif // (_WIN32_WINNT < 0x0501) + +#if defined(_WTL_USE_VSSYM32) || (defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)) + #include +#else + #include +#endif + +#include +#pragma comment(lib, "uxtheme.lib") + +// Note: To create an application that also runs on older versions of Windows, +// use delay load of uxtheme.dll and ensure that no calls to the Theme API are +// made if theming is not supported. It is enough to check if m_hTheme is NULL. +// Example: +// if(m_hTheme != NULL) +// { +// DrawThemeBackground(dc, BP_PUSHBUTTON, PBS_NORMAL, &rect, NULL); +// DrawThemeText(dc, BP_PUSHBUTTON, PBS_NORMAL, L"Button", -1, DT_SINGLELINE | DT_CENTER | DT_VCENTER, 0, &rect); +// } +// else +// { +// dc.DrawFrameControl(&rect, DFC_BUTTON, DFCS_BUTTONPUSH); +// dc.DrawText(_T("Button"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); +// } +// +// Delay load is NOT AUTOMATIC for VC++ 7, you have to link to delayimp.lib, +// and add uxtheme.dll in the Linker.Input.Delay Loaded DLLs section of the +// project properties. +#if (_MSC_VER < 1300) && !defined(_WTL_NO_THEME_DELAYLOAD) + #pragma comment(lib, "delayimp.lib") + #pragma comment(linker, "/delayload:uxtheme.dll") +#endif // (_MSC_VER < 1300) && !defined(_WTL_NO_THEME_DELAYLOAD) + +// Hack: Signatures in uxtheme.h changed - the only way to check which variant of uxtheme.h +// is included is to check for presence of new defines MAX_THEMECOLOR and MAX_THEMESIZE +#ifndef _WTL_NEW_UXTHEME + #if defined(MAX_THEMECOLOR) && defined(MAX_THEMESIZE) + #define _WTL_NEW_UXTHEME + #endif // defined(MAX_THEMECOLOR) && defined(MAX_THEMESIZE) +#endif // _WTL_NEW_UXTHEME + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CTheme +// CThemeImpl +// +// CBufferedPaint +// CBufferedPaintImpl +// CBufferedPaintWindowImpl +// CBufferedAnimation +// CBufferedAnimationImpl +// CBufferedAnimationWindowImpl +// +// Global functions: +// AtlDrawThemeClientEdge() + + +namespace WTL +{ + +/////////////////////////////////////////////////////////////////////////////// +// CTheme - wrapper for theme handle + +class CTheme +{ +public: +// Data members + HTHEME m_hTheme; + static int m_nIsThemingSupported; + +// Constructor + CTheme(HTHEME hTheme = NULL) : m_hTheme(hTheme) + { + IsThemingSupported(); + } + +// Operators and helpers + bool IsThemeNull() const + { + return (m_hTheme == NULL); + } + + CTheme& operator =(HTHEME hTheme) + { + m_hTheme = hTheme; + return *this; + } + + operator HTHEME() const + { + return m_hTheme; + } + + void Attach(HTHEME hTheme) + { + m_hTheme = hTheme; + } + + HTHEME Detach() + { + HTHEME hTheme = m_hTheme; + m_hTheme = NULL; + return hTheme; + } + +// Theme support helper + static bool IsThemingSupported() + { + if(m_nIsThemingSupported == -1) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CTheme::IsThemingSupported.\n")); + ATLASSERT(FALSE); + return false; + } + + if(m_nIsThemingSupported == -1) + { + HMODULE hThemeDLL = ::LoadLibrary(_T("uxtheme.dll")); + m_nIsThemingSupported = (hThemeDLL != NULL) ? 1 : 0; + if(hThemeDLL != NULL) + ::FreeLibrary(hThemeDLL); + } + + lock.Unlock(); + } + + ATLASSERT(m_nIsThemingSupported != -1); + return (m_nIsThemingSupported == 1); + } + +// Operations and theme properties + HTHEME OpenThemeData(HWND hWnd, LPCWSTR pszClassList) + { + if(!IsThemingSupported()) + return NULL; + + ATLASSERT(m_hTheme == NULL); + m_hTheme = ::OpenThemeData(hWnd, pszClassList); + return m_hTheme; + } + + HRESULT CloseThemeData() + { + HRESULT hRet = S_FALSE; + if(m_hTheme != NULL) + { + hRet = ::CloseThemeData(m_hTheme); + if(SUCCEEDED(hRet)) + m_hTheme = NULL; + } + return hRet; + } + + HRESULT DrawThemeBackground(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, LPCRECT pClipRect = NULL) + { + ATLASSERT(m_hTheme != NULL); + return ::DrawThemeBackground(m_hTheme, hDC, nPartID, nStateID, pRect, pClipRect); + } + + HRESULT DrawThemeBackgroundEx(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, const DTBGOPTS* pOptions = NULL) + { + ATLASSERT(m_hTheme != NULL); + return ::DrawThemeBackgroundEx(m_hTheme, hDC, nPartID, nStateID, pRect, pOptions); + } + + HRESULT DrawThemeText(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int nCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect) + { + ATLASSERT(m_hTheme != NULL); + return ::DrawThemeText(m_hTheme, hDC, nPartID, nStateID, pszText, nCharCount, dwTextFlags, dwTextFlags2, pRect); + } + + HRESULT GetThemeBackgroundContentRect(HDC hDC, int nPartID, int nStateID, LPCRECT pBoundingRect, LPRECT pContentRect) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeBackgroundContentRect(m_hTheme, hDC, nPartID, nStateID, pBoundingRect, pContentRect); + } + + HRESULT GetThemeBackgroundExtent(HDC hDC, int nPartID, int nStateID, LPCRECT pContentRect, LPRECT pExtentRect) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeBackgroundExtent(m_hTheme, hDC, nPartID, nStateID, pContentRect, pExtentRect); + } + + HRESULT GetThemePartSize(HDC hDC, int nPartID, int nStateID, LPRECT pRect, enum THEMESIZE eSize, LPSIZE pSize) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemePartSize(m_hTheme, hDC, nPartID, nStateID, pRect, eSize, pSize); + } + + HRESULT GetThemeTextExtent(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int nCharCount, DWORD dwTextFlags, LPCRECT pBoundingRect, LPRECT pExtentRect) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeTextExtent(m_hTheme, hDC, nPartID, nStateID, pszText, nCharCount, dwTextFlags, pBoundingRect, pExtentRect); + } + + HRESULT GetThemeTextMetrics(HDC hDC, int nPartID, int nStateID, PTEXTMETRICW pTextMetric) const + { + ATLASSERT(m_hTheme != NULL); +#ifdef _WTL_NEW_UXTHEME + return ::GetThemeTextMetrics(m_hTheme, hDC, nPartID, nStateID, pTextMetric); +#else // !_WTL_NEW_UXTHEME + // Note: The cast to PTEXTMETRIC is because uxtheme.h incorrectly uses it instead of PTEXTMETRICW + return ::GetThemeTextMetrics(m_hTheme, hDC, nPartID, nStateID, (PTEXTMETRIC)pTextMetric); +#endif // !_WTL_NEW_UXTHEME + } + + HRESULT GetThemeBackgroundRegion(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, HRGN* pRegion) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeBackgroundRegion(m_hTheme, hDC, nPartID, nStateID, pRect, pRegion); + } + + HRESULT HitTestThemeBackground(HDC hDC, int nPartID, int nStateID, DWORD dwOptions, LPCRECT pRect, HRGN hrgn, POINT ptTest, WORD* pwHitTestCode) const + { + ATLASSERT(m_hTheme != NULL); + return ::HitTestThemeBackground(m_hTheme, hDC, nPartID, nStateID, dwOptions, pRect, hrgn, ptTest, pwHitTestCode); + } + + HRESULT DrawThemeEdge(HDC hDC, int nPartID, int nStateID, LPCRECT pDestRect, UINT uEdge, UINT uFlags, LPRECT pContentRect = NULL) + { + ATLASSERT(m_hTheme != NULL); + return ::DrawThemeEdge(m_hTheme, hDC, nPartID, nStateID, pDestRect, uEdge, uFlags, pContentRect); + } + + HRESULT DrawThemeIcon(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, HIMAGELIST himl, int nImageIndex) + { + ATLASSERT(m_hTheme != NULL); + return ::DrawThemeIcon(m_hTheme, hDC, nPartID, nStateID, pRect, himl, nImageIndex); + } + + BOOL IsThemePartDefined(int nPartID, int nStateID) const + { + ATLASSERT(m_hTheme != NULL); + return ::IsThemePartDefined(m_hTheme, nPartID, nStateID); + } + + BOOL IsThemeBackgroundPartiallyTransparent(int nPartID, int nStateID) const + { + ATLASSERT(m_hTheme != NULL); + return ::IsThemeBackgroundPartiallyTransparent(m_hTheme, nPartID, nStateID); + } + + HRESULT GetThemeColor(int nPartID, int nStateID, int nPropID, COLORREF* pColor) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeColor(m_hTheme, nPartID, nStateID, nPropID, pColor); + } + + HRESULT GetThemeMetric(HDC hDC, int nPartID, int nStateID, int nPropID, int* pnVal) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeMetric(m_hTheme, hDC, nPartID, nStateID, nPropID, pnVal); + } + + HRESULT GetThemeString(int nPartID, int nStateID, int nPropID, LPWSTR pszBuff, int cchMaxBuffChars) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeString(m_hTheme, nPartID, nStateID, nPropID, pszBuff, cchMaxBuffChars); + } + + HRESULT GetThemeBool(int nPartID, int nStateID, int nPropID, BOOL* pfVal) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeBool(m_hTheme, nPartID, nStateID, nPropID, pfVal); + } + + HRESULT GetThemeInt(int nPartID, int nStateID, int nPropID, int* pnVal) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeInt(m_hTheme, nPartID, nStateID, nPropID, pnVal); + } + + HRESULT GetThemeEnumValue(int nPartID, int nStateID, int nPropID, int* pnVal) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeEnumValue(m_hTheme, nPartID, nStateID, nPropID, pnVal); + } + + HRESULT GetThemePosition(int nPartID, int nStateID, int nPropID, LPPOINT pPoint) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemePosition(m_hTheme, nPartID, nStateID, nPropID, pPoint); + } + + // deprecated + HRESULT GetThemeFont(int nPartID, HDC hDC, int nStateID, int nPropID, LOGFONTW* pFont) const + { + ATLASSERT(m_hTheme != NULL); +#ifdef _WTL_NEW_UXTHEME + return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, pFont); +#else // !_WTL_NEW_UXTHEME + // Note: The cast to LOGFONT* is because uxtheme.h incorrectly uses it instead of LOGFONTW* + return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, (LOGFONT*)pFont); +#endif // !_WTL_NEW_UXTHEME + } + + HRESULT GetThemeFont(HDC hDC, int nPartID, int nStateID, int nPropID, LOGFONTW* pFont) const + { + ATLASSERT(m_hTheme != NULL); +#ifdef _WTL_NEW_UXTHEME + return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, pFont); +#else // !_WTL_NEW_UXTHEME + // Note: The cast to LOGFONT* is because uxtheme.h incorrectly uses it instead of LOGFONTW* + return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, (LOGFONT*)pFont); +#endif // !_WTL_NEW_UXTHEME + } + + HRESULT GetThemeRect(int nPartID, int nStateID, int nPropID, LPRECT pRect) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeRect(m_hTheme, nPartID, nStateID, nPropID, pRect); + } + + HRESULT GetThemeMargins(HDC hDC, int nPartID, int nStateID, int nPropID, LPRECT pRect, PMARGINS pMargins) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeMargins(m_hTheme, hDC, nPartID, nStateID, nPropID, pRect, pMargins); + } + + HRESULT GetThemeIntList(int nPartID, int nStateID, int nPropID, INTLIST* pIntList) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeIntList(m_hTheme, nPartID, nStateID, nPropID, pIntList); + } + + HRESULT GetThemePropertyOrigin(int nPartID, int nStateID, int nPropID, enum PROPERTYORIGIN* pOrigin) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemePropertyOrigin(m_hTheme, nPartID, nStateID, nPropID, pOrigin); + } + + HRESULT GetThemeFilename(int nPartID, int nStateID, int nPropID, LPWSTR pszThemeFileName, int cchMaxBuffChars) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeFilename(m_hTheme, nPartID, nStateID, nPropID, pszThemeFileName, cchMaxBuffChars); + } + + COLORREF GetThemeSysColor(int nColorID) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeSysColor(m_hTheme, nColorID); + } + + HBRUSH GetThemeSysColorBrush(int nColorID) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeSysColorBrush(m_hTheme, nColorID); + } + + int GetThemeSysSize(int nSizeID) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeSysSize(m_hTheme, nSizeID); + } + + BOOL GetThemeSysBool(int nBoolID) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeSysBool(m_hTheme, nBoolID); + } + + HRESULT GetThemeSysFont(int nFontID, LOGFONTW* plf) const + { + ATLASSERT(m_hTheme != NULL); +#ifdef _WTL_NEW_UXTHEME + return ::GetThemeSysFont(m_hTheme, nFontID, plf); +#else // !_WTL_NEW_UXTHEME + // Note: The cast to LOGFONT* is because uxtheme.h incorrectly uses it instead of LOGFONTW* + return ::GetThemeSysFont(m_hTheme, nFontID, (LOGFONT*)plf); +#endif // !_WTL_NEW_UXTHEME + } + + HRESULT GetThemeSysString(int nStringID, LPWSTR pszStringBuff, int cchMaxStringChars) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeSysString(m_hTheme, nStringID, pszStringBuff, cchMaxStringChars); + } + + HRESULT GetThemeSysInt(int nIntID, int* pnValue) const + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeSysInt(m_hTheme, nIntID, pnValue); + } + +#ifdef _WTL_NEW_UXTHEME + HTHEME OpenThemeDataEx(HWND hWnd, LPCWSTR pszClassList, DWORD dwFlags) + { + if(!IsThemingSupported()) + return NULL; + + ATLASSERT(m_hTheme == NULL); + m_hTheme = ::OpenThemeDataEx(hWnd, pszClassList, dwFlags); + return m_hTheme; + } + + HRESULT DrawThemeTextEx(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int cchText, DWORD dwTextFlags, LPRECT lpRect, const DTTOPTS* pOptions) + { + ATLASSERT(m_hTheme != NULL); + return ::DrawThemeTextEx(m_hTheme, hDC, nPartID, nStateID, pszText, cchText, dwTextFlags, lpRect, pOptions); + } + + HRESULT GetThemeTransitionDuration(int nPartID, int nFromStateID, int nToStateID, int nPropID, DWORD& dwDuration) + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeTransitionDuration(m_hTheme, nPartID, nFromStateID, nToStateID, nPropID, &dwDuration); + } +#endif // _WTL_NEW_UXTHEME + +#if (_WIN32_WINNT >= 0x0600) + HRESULT GetThemeBitmap(int nPartID, int nStateID, int nPropID, ULONG uFlags, HBITMAP& hBitmap) + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeBitmap(m_hTheme, nPartID, nStateID, nPropID, uFlags, &hBitmap); + } + + HRESULT GetThemeStream(int nPartID, int nStateID, int nPropID, VOID** ppvStream, DWORD* pcbStream, HINSTANCE hInstance) + { + ATLASSERT(m_hTheme != NULL); + return ::GetThemeStream(m_hTheme, nPartID, nStateID, nPropID, ppvStream, pcbStream, hInstance); + } +#endif // (_WIN32_WINNT >= 0x0600) +}; + +__declspec(selectany) int CTheme::m_nIsThemingSupported = -1; + + +/////////////////////////////////////////////////////////////////////////////// +// CThemeImpl - theme support implementation + +// Derive from this class to implement window with theme support. +// Example: +// class CMyThemeWindow : public CWindowImpl, public CThemeImpl +// { +// ... +// BEGIN_MSG_MAP(CMyThemeWindow) +// CHAIN_MSG_MAP(CThemeImpl) +// ... +// END_MSG_MAP() +// ... +// }; +// +// If you set theme class list, the class will automaticaly open/close/reopen theme data. + + +// Helper for drawing theme client edge +inline bool AtlDrawThemeClientEdge(HTHEME hTheme, HWND hWnd, HRGN hRgnUpdate = NULL, HBRUSH hBrush = NULL, int nPartID = 0, int nStateID = 0) +{ + ATLASSERT(hTheme != NULL); + ATLASSERT(::IsWindow(hWnd)); + + CWindowDC dc(hWnd); + if(dc.IsNull()) + return false; + + // Get border size + int cxBorder = GetSystemMetrics(SM_CXBORDER); + int cyBorder = GetSystemMetrics(SM_CYBORDER); + if(SUCCEEDED(::GetThemeInt(hTheme, nPartID, nStateID, TMT_SIZINGBORDERWIDTH, &cxBorder))) + cyBorder = cxBorder; + + RECT rect; + ::GetWindowRect(hWnd, &rect); + + // Remove the client edge from the update region + int cxEdge = GetSystemMetrics(SM_CXEDGE); + int cyEdge = GetSystemMetrics(SM_CYEDGE); + ::InflateRect(&rect, -cxEdge, -cyEdge); + CRgn rgn; + rgn.CreateRectRgnIndirect(&rect); + if(rgn.IsNull()) + return false; + + if(hRgnUpdate != NULL) + rgn.CombineRgn(hRgnUpdate, rgn, RGN_AND); + + ::OffsetRect(&rect, -rect.left, -rect.top); + + ::OffsetRect(&rect, cxEdge, cyEdge); + dc.ExcludeClipRect(&rect); + ::InflateRect(&rect, cxEdge, cyEdge); + + ::DrawThemeBackground(hTheme, dc, nPartID, nStateID, &rect, NULL); + + // Use background brush too, since theme border might not cover everything + if(cxBorder < cxEdge && cyBorder < cyEdge) + { + if(hBrush == NULL) +// need conditional code because types don't match in winuser.h +#ifdef _WIN64 + hBrush = (HBRUSH)::GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND); +#else + hBrush = (HBRUSH)UlongToPtr(::GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND)); +#endif + + ::InflateRect(&rect, cxBorder - cxEdge, cyBorder - cyEdge); + dc.FillRect(&rect, hBrush); + } + + ::DefWindowProc(hWnd, WM_NCPAINT, (WPARAM)rgn.m_hRgn, 0L); + + return true; +} + + +// Theme extended styles +#define THEME_EX_3DCLIENTEDGE 0x00000001 +#define THEME_EX_THEMECLIENTEDGE 0x00000002 + +template +class CThemeImpl : public TBase +{ +public: +// Data members + LPWSTR m_lpstrThemeClassList; + DWORD m_dwExtendedStyle; // theme specific extended styles + +// Constructor & destructor + CThemeImpl() : m_lpstrThemeClassList(NULL), m_dwExtendedStyle(0) + { } + + ~CThemeImpl() + { + delete [] m_lpstrThemeClassList; + } + +// Attributes + bool SetThemeClassList(LPCWSTR lpstrThemeClassList) + { + if(m_lpstrThemeClassList != NULL) + { + delete [] m_lpstrThemeClassList; + m_lpstrThemeClassList = NULL; + } + + if(lpstrThemeClassList == NULL) + return true; + + int cchLen = lstrlenW(lpstrThemeClassList) + 1; + ATLTRY(m_lpstrThemeClassList = new WCHAR[cchLen]); + if(m_lpstrThemeClassList == NULL) + return false; + + SecureHelper::strcpyW_x(m_lpstrThemeClassList, cchLen, lpstrThemeClassList); + + return true; + } + + bool GetThemeClassList(LPWSTR lpstrThemeClassList, int cchListBuffer) const + { + int cchLen = lstrlenW(m_lpstrThemeClassList) + 1; + if(cchListBuffer < cchLen) + return false; + + SecureHelper::strcpyW_x(lpstrThemeClassList, cchListBuffer, m_lpstrThemeClassList); + + return true; + } + + LPCWSTR GetThemeClassList() const + { + return m_lpstrThemeClassList; + } + + DWORD SetThemeExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) + { + DWORD dwPrevStyle = m_dwExtendedStyle; + if(dwMask == 0) + m_dwExtendedStyle = dwExtendedStyle; + else + m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); + return dwPrevStyle; + } + + DWORD GetThemeExtendedStyle() const + { + return m_dwExtendedStyle; + } + +// Operations + HTHEME OpenThemeData() + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + ATLASSERT(m_lpstrThemeClassList != NULL); + if(m_lpstrThemeClassList == NULL) + return NULL; + CloseThemeData(); + return TBase::OpenThemeData(pT->m_hWnd, m_lpstrThemeClassList); + } + + HTHEME OpenThemeData(LPCWSTR pszClassList) + { + if(!SetThemeClassList(pszClassList)) + return NULL; + return OpenThemeData(); + } + + HRESULT SetWindowTheme(LPCWSTR pszSubAppName, LPCWSTR pszSubIDList) + { + if(!IsThemingSupported()) + return S_FALSE; + + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::SetWindowTheme(pT->m_hWnd, pszSubAppName, pszSubIDList); + } + + HTHEME GetWindowTheme() const + { + if(!IsThemingSupported()) + return NULL; + + const T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::GetWindowTheme(pT->m_hWnd); + } + + HRESULT EnableThemeDialogTexture(DWORD dwFlags) + { + if(!IsThemingSupported()) + return S_FALSE; + + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::EnableThemeDialogTexture(pT->m_hWnd, dwFlags); + } + + BOOL IsThemeDialogTextureEnabled() const + { + if(!IsThemingSupported()) + return FALSE; + + const T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::IsThemeDialogTextureEnabled(pT->m_hWnd); + } + + HRESULT DrawThemeParentBackground(HDC hDC, const RECT* pRect = NULL) + { + if(!IsThemingSupported()) + return S_FALSE; + + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); +#ifdef _WTL_NEW_UXTHEME + return ::DrawThemeParentBackground(pT->m_hWnd, hDC, pRect); +#else + return ::DrawThemeParentBackground(pT->m_hWnd, hDC, (RECT*)pRect); +#endif + } + +#ifdef _WTL_NEW_UXTHEME + HRESULT SetWindowThemeAttribute(WINDOWTHEMEATTRIBUTETYPE type, PVOID pvAttribute, DWORD cbAttribute) + { + if(!IsThemingSupported()) + return S_FALSE; + + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::SetWindowThemeAttribute(pT->m_hWnd, type, pvAttribute, cbAttribute); + } + + HRESULT SetWindowThemeNonClientAttributes(DWORD dwAttributes, DWORD dwMask) + { + if(!IsThemingSupported()) + return S_FALSE; + + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + WTA_OPTIONS opt = { dwAttributes, dwMask }; + return ::SetWindowThemeAttribute(pT->m_hWnd, WTA_NONCLIENT, (PVOID)&opt, sizeof(opt)); + } + + HRESULT DrawThemeParentBackgroundEx(HDC hDC, DWORD dwFlags, const RECT* lpRect = NULL) + { + if(!IsThemingSupported()) + return S_FALSE; + + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + return ::DrawThemeParentBackgroundEx(pT->m_hWnd, hDC, dwFlags, lpRect); + } +#endif // _WTL_NEW_UXTHEME + +// Message map and handlers + // Note: If you handle any of these messages in your derived class, + // it is better to put CHAIN_MSG_MAP at the start of your message map. + BEGIN_MSG_MAP(CThemeImpl) + MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) + MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged) + MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint) + END_MSG_MAP() + + LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + if(m_lpstrThemeClassList != NULL) + OpenThemeData(); + bHandled = FALSE; + return 1; + } + + LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + CloseThemeData(); + bHandled = FALSE; + return 1; + } + + LRESULT OnThemeChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + CloseThemeData(); + if(m_lpstrThemeClassList != NULL) + OpenThemeData(); + bHandled = FALSE; + return 1; + } + + LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + LRESULT lRet = 0; + bHandled = FALSE; + if(IsThemingSupported() && ((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0)) + { + if((m_dwExtendedStyle & THEME_EX_3DCLIENTEDGE) != 0) + { + lRet = ::DefWindowProc(pT->m_hWnd, uMsg, wParam, lParam); + bHandled = TRUE; + } + else if((m_hTheme != NULL) && ((m_dwExtendedStyle & THEME_EX_THEMECLIENTEDGE) != 0)) + { + HRGN hRgn = (wParam != 1) ? (HRGN)wParam : NULL; + if(pT->DrawThemeClientEdge(hRgn)) + bHandled = TRUE; + } + } + return lRet; + } + +// Drawing helper + bool DrawThemeClientEdge(HRGN hRgnUpdate) + { + T* pT = static_cast(this); + return AtlDrawThemeClientEdge(m_hTheme, pT->m_hWnd, hRgnUpdate, NULL, 0, 0); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// Buffered Paint and Animation + +#ifdef _WTL_NEW_UXTHEME + +/////////////////////////////////////////////////////////////////////////////// +// CBufferedPaintBase - Buffered Paint support for othe classes + +class CBufferedPaintBase +{ +public: + static int m_nIsBufferedPaintSupported; + + CBufferedPaintBase() + { + if(IsBufferedPaintSupported()) + ATLVERIFY(SUCCEEDED(::BufferedPaintInit())); + } + + ~CBufferedPaintBase() + { + if(IsBufferedPaintSupported()) + ATLVERIFY(SUCCEEDED(::BufferedPaintUnInit())); + } + + static bool IsBufferedPaintSupported() + { + if(m_nIsBufferedPaintSupported == -1) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CBufferedPaintBase::IsBufferedPaintSupported.\n")); + ATLASSERT(FALSE); + return false; + } + + if(m_nIsBufferedPaintSupported == -1) + m_nIsBufferedPaintSupported = RunTimeHelper::IsVista() ? 1 : 0; + + lock.Unlock(); + } + + ATLASSERT(m_nIsBufferedPaintSupported != -1); + return (m_nIsBufferedPaintSupported == 1); + } +}; + +__declspec(selectany) int CBufferedPaintBase::m_nIsBufferedPaintSupported = -1; + + +/////////////////////////////////////////////////////////////////////////////// +// CBufferedPaint - support for buffered paint functions + +class CBufferedPaint +{ +public: + HPAINTBUFFER m_hPaintBuffer; + + CBufferedPaint() : m_hPaintBuffer(NULL) + { } + + ~CBufferedPaint() + { + ATLVERIFY(SUCCEEDED(End())); + } + + bool IsNull() const + { + return (m_hPaintBuffer == NULL); + } + + HPAINTBUFFER Begin(HDC hdcTarget, const RECT* prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS* pPaintParams, HDC* phdcPaint) + { + ATLASSERT(m_hPaintBuffer == NULL); + m_hPaintBuffer = ::BeginBufferedPaint(hdcTarget, prcTarget, dwFormat, pPaintParams, phdcPaint); + return m_hPaintBuffer; + } + + HRESULT End(BOOL bUpdate = TRUE) + { + HRESULT hRet = S_FALSE; + if(m_hPaintBuffer != NULL) + { + hRet = ::EndBufferedPaint(m_hPaintBuffer, bUpdate); + m_hPaintBuffer = NULL; + } + return hRet; + } + + HRESULT GetTargetRect(LPRECT pRect) const + { + ATLASSERT(m_hPaintBuffer != NULL); + return ::GetBufferedPaintTargetRect(m_hPaintBuffer, pRect); + } + + HDC GetTargetDC() const + { + ATLASSERT(m_hPaintBuffer != NULL); + return ::GetBufferedPaintTargetDC(m_hPaintBuffer); + } + + HDC GetPaintDC() const + { + ATLASSERT(m_hPaintBuffer != NULL); + return ::GetBufferedPaintDC(m_hPaintBuffer); + } + + HRESULT GetBits(RGBQUAD** ppbBuffer, int* pcxRow) const + { + ATLASSERT(m_hPaintBuffer != NULL); + return ::GetBufferedPaintBits(m_hPaintBuffer, ppbBuffer, pcxRow); + } + + HRESULT Clear(const RECT* pRect = NULL) + { + ATLASSERT(m_hPaintBuffer != NULL); + return ::BufferedPaintClear(m_hPaintBuffer, pRect); + } + + HRESULT SetAlpha(BYTE alpha, const RECT* pRect = NULL) + { + ATLASSERT(m_hPaintBuffer != NULL); + return ::BufferedPaintSetAlpha(m_hPaintBuffer, pRect, alpha); + } + + HRESULT MakeOpaque(const RECT* pRect = NULL) + { + ATLASSERT(m_hPaintBuffer != NULL); + return ::BufferedPaintSetAlpha(m_hPaintBuffer, pRect, 255); + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CBufferedPaintImpl - provides buffered paint for any window + +template +class ATL_NO_VTABLE CBufferedPaintImpl : public CBufferedPaintBase +{ +public: + CBufferedPaint m_BufferedPaint; + BP_BUFFERFORMAT m_dwFormat; + BP_PAINTPARAMS m_PaintParams; + + CBufferedPaintImpl() : m_dwFormat(BPBF_TOPDOWNDIB) + { + memset(&m_PaintParams, 0, sizeof(BP_PAINTPARAMS)); + m_PaintParams.cbSize = sizeof(BP_PAINTPARAMS); + } + +// Message map and handlers + BEGIN_MSG_MAP(CBufferedPaintImpl) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) + MESSAGE_HANDLER(WM_PAINT, OnPaint) + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) + END_MSG_MAP() + + LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return 1; // no background needed + } + + LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + if(wParam != NULL) + { + RECT rect = { 0 }; + pT->GetClientRect(&rect); + pT->DoPaint((HDC)wParam, rect); + } + else + { + CPaintDC dc(pT->m_hWnd); + pT->DoBufferedPaint(dc.m_hDC, dc.m_ps.rcPaint); + } + + return 0; + } + +// Overrideables + void DoBufferedPaint(CDCHandle dc, RECT& rect) + { + HDC hDCPaint = NULL; + if(IsBufferedPaintSupported()) + m_BufferedPaint.Begin(dc, &rect, m_dwFormat, &m_PaintParams, &hDCPaint); + + T* pT = static_cast(this); + if(hDCPaint != NULL) + pT->DoPaint(hDCPaint, rect); + else + pT->DoPaint(dc.m_hDC, rect); + + if(IsBufferedPaintSupported()) + m_BufferedPaint.End(); + } + + void DoPaint(CDCHandle /*dc*/, RECT& /*rect*/) + { + // must be implemented in a derived class + ATLASSERT(FALSE); + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CBufferedPaintWindowImpl - implements a window that uses buffered paint + +template +class ATL_NO_VTABLE CBufferedPaintWindowImpl : + public ATL::CWindowImpl, + public CBufferedPaintImpl< T > +{ +public: + BEGIN_MSG_MAP(CBufferedPaintWindowImpl) + CHAIN_MSG_MAP(CBufferedPaintImpl< T >) + END_MSG_MAP() +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CBufferedAnimation - support for buffered animation + +class CBufferedAnimation +{ +public: + HANIMATIONBUFFER m_hAnimationBuffer; + + CBufferedAnimation() : m_hAnimationBuffer(NULL) + { } + + ~CBufferedAnimation() + { + ATLVERIFY(SUCCEEDED(End())); + } + + bool IsNull() const + { + return (m_hAnimationBuffer == NULL); + } + + HANIMATIONBUFFER Begin(HWND hWnd, HDC hDCTarget, const RECT* pRectTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS* pPaintParams, BP_ANIMATIONPARAMS* pAnimationParams, HDC* phdcFrom, HDC* phdcTo) + { + ATLASSERT(m_hAnimationBuffer == NULL); + m_hAnimationBuffer = ::BeginBufferedAnimation(hWnd, hDCTarget, pRectTarget, dwFormat, pPaintParams, pAnimationParams, phdcFrom, phdcTo); + return m_hAnimationBuffer; + } + + HRESULT End(BOOL bUpdate = TRUE) + { + HRESULT hRet = S_FALSE; + if(m_hAnimationBuffer != NULL) + { + hRet = ::EndBufferedAnimation(m_hAnimationBuffer, bUpdate); + m_hAnimationBuffer = NULL; + } + return hRet; + } + + static bool IsRendering(HWND hWnd, HDC hDC) + { + return (::BufferedPaintRenderAnimation(hWnd, hDC) != FALSE); + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CBufferedAnimationImpl - provides buffered animation support for any window + +// Note: You can either use m_State and m_NewState to store the state information +// for the animation change, or map your state to those data members. DoPaint() +// should only rely on the state information that is passed to it. + +template +class ATL_NO_VTABLE CBufferedAnimationImpl : public CBufferedPaintBase +{ +public: + BP_BUFFERFORMAT m_dwFormat; + BP_PAINTPARAMS m_PaintParams; + BP_ANIMATIONPARAMS m_AnimationParams; + + TState m_State; + TState m_NewState; + + CBufferedAnimationImpl(TState InitialState) : m_dwFormat(BPBF_TOPDOWNDIB) + { + memset(&m_PaintParams, 0, sizeof(BP_PAINTPARAMS)); + m_PaintParams.cbSize = sizeof(BP_PAINTPARAMS); + + memset(&m_AnimationParams, 0, sizeof(BP_ANIMATIONPARAMS)); + m_AnimationParams.cbSize = sizeof(BP_ANIMATIONPARAMS); + m_AnimationParams.style = BPAS_LINEAR; + m_AnimationParams.dwDuration = 500; + + T* pT = static_cast(this); + pT->SetState(InitialState); + pT->SetNewState(InitialState); + } + + DWORD GetDuration() const + { + return m_AnimationParams.dwDuration; + } + + void SetDuration(DWORD dwDuration) + { + m_AnimationParams.dwDuration = dwDuration; + } + + void DoAnimation(TState NewState, const RECT* pRect = NULL) + { + T* pT = static_cast(this); + pT->SetNewState(NewState); + + pT->InvalidateRect(pRect, FALSE); + pT->UpdateWindow(); + + pT->SetState(NewState); + } + +// Message map and handlers + BEGIN_MSG_MAP(CBufferedAnimationImpl) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) + MESSAGE_HANDLER(WM_PAINT, OnPaint) + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) + END_MSG_MAP() + + LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + return 1; // no background needed + } + + LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + if(wParam != NULL) + { + RECT rect = { 0 }; + pT->GetClientRect(&rect); + pT->DoPaint((HDC)wParam, rect, m_NewState); + } + else + { + CPaintDC dc(pT->m_hWnd); + pT->DoAnimationPaint(dc.m_hDC, dc.m_ps.rcPaint); + } + + return 0; + } + +// Overrideables + void SetState(TState State) + { + m_State = State; + } + + void SetNewState(TState State) + { + m_NewState = State; + } + + bool AreStatesEqual() const + { + return (m_State == m_NewState); + } + + void DoAnimationPaint(CDCHandle dc, RECT& rect) + { + T* pT = static_cast(this); + if(IsBufferedPaintSupported() && CBufferedAnimation::IsRendering(pT->m_hWnd, dc)) + return; + + DWORD dwDurationSave = m_AnimationParams.dwDuration; + if(pT->AreStatesEqual()) + m_AnimationParams.dwDuration = 0; + + HDC hdcFrom = NULL, hdcTo = NULL; + CBufferedAnimation ba; + if(IsBufferedPaintSupported()) + ba.Begin(pT->m_hWnd, dc, &rect, m_dwFormat, &m_PaintParams, &m_AnimationParams, &hdcFrom, &hdcTo); + + if(!ba.IsNull()) + { + if(hdcFrom != NULL) + pT->DoPaint(hdcFrom, rect, m_State); + + if (hdcTo != NULL) + pT->DoPaint(hdcTo, rect, m_NewState); + } + else + { + pT->DoPaint(dc.m_hDC, rect, m_NewState); + } + + m_AnimationParams.dwDuration = dwDurationSave; + } + + void DoPaint(CDCHandle /*dc*/, RECT& /*rect*/, TState /*State*/) + { + // must be implemented in a derived class + ATLASSERT(FALSE); + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CBufferedAnimationWindowImpl - implements a window that uses buffered animation + +template +class ATL_NO_VTABLE CBufferedAnimationWindowImpl : + public ATL::CWindowImpl, + public CBufferedAnimationImpl< T, TState > +{ +public: + CBufferedAnimationWindowImpl(TState InitialState) : CBufferedAnimationImpl< T, TState >(InitialState) + { } + + typedef CBufferedAnimationImpl< T, TState > _baseBufferedAnimation; + BEGIN_MSG_MAP(CBufferedAnimationWindowImpl) + CHAIN_MSG_MAP(_baseBufferedAnimation) + END_MSG_MAP() +}; + +#endif // _WTL_NEW_UXTHEME + +}; // namespace WTL + +#endif // __ATLTHEME_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atluser.h b/Client/Client/GUI/BKWin/wtl/atluser.h new file mode 100644 index 00000000..2df3b4d3 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atluser.h @@ -0,0 +1,1159 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLUSER_H__ +#define __ATLUSER_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifndef __ATLAPP_H__ + #error atluser.h requires atlapp.h to be included first +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CMenuItemInfo +// CMenuT +// CAcceleratorT +// CIconT +// CCursorT +// CResource +// +// Global functions: +// AtlMessageBox() + + +namespace WTL +{ + +/////////////////////////////////////////////////////////////////////////////// +// AtlMessageBox - accepts both memory and resource based strings + +inline int AtlMessageBox(HWND hWndOwner, ATL::_U_STRINGorID message, ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uType = MB_OK | MB_ICONINFORMATION) +{ + ATLASSERT(hWndOwner == NULL || ::IsWindow(hWndOwner)); + + LPTSTR lpstrMessage = NULL; + if(IS_INTRESOURCE(message.m_lpstr)) + { + for(int nLen = 256; ; nLen *= 2) + { + ATLTRY(lpstrMessage = new TCHAR[nLen]); + if(lpstrMessage == NULL) + { + ATLASSERT(FALSE); + return 0; + } + int nRes = ::LoadString(ModuleHelper::GetResourceInstance(), LOWORD(message.m_lpstr), lpstrMessage, nLen); + if(nRes < nLen - 1) + break; + delete [] lpstrMessage; + lpstrMessage = NULL; + } + + message.m_lpstr = lpstrMessage; + } + + LPTSTR lpstrTitle = NULL; + if(IS_INTRESOURCE(title.m_lpstr) && LOWORD(title.m_lpstr) != 0) + { + for(int nLen = 256; ; nLen *= 2) + { + ATLTRY(lpstrTitle = new TCHAR[nLen]); + if(lpstrTitle == NULL) + { + ATLASSERT(FALSE); + return 0; + } + int nRes = ::LoadString(ModuleHelper::GetResourceInstance(), LOWORD(title.m_lpstr), lpstrTitle, nLen); + if(nRes < nLen - 1) + break; + delete [] lpstrTitle; + lpstrTitle = NULL; + } + + title.m_lpstr = lpstrTitle; + } + + int nRet = ::MessageBox(hWndOwner, message.m_lpstr, title.m_lpstr, uType); + + delete [] lpstrMessage; + delete [] lpstrTitle; + + return nRet; +} + + +/////////////////////////////////////////////////////////////////////////////// +// CMenu + +#if (WINVER >= 0x0500) + #ifndef MII_SIZEOF_STRUCT + #define MII_SIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member)) + #endif + #define MENUITEMINFO_SIZE_VERSION_400A MII_SIZEOF_STRUCT(MENUITEMINFOA, cch) + #define MENUITEMINFO_SIZE_VERSION_400W MII_SIZEOF_STRUCT(MENUITEMINFOW, cch) + #ifdef UNICODE + #define MENUITEMINFO_SIZE_VERSION_400 MENUITEMINFO_SIZE_VERSION_400W + #else + #define MENUITEMINFO_SIZE_VERSION_400 MENUITEMINFO_SIZE_VERSION_400A + #endif // !UNICODE +#endif // (WINVER >= 0x0500) + +class CMenuItemInfo : public MENUITEMINFO +{ +public: + CMenuItemInfo() + { + memset(this, 0, sizeof(MENUITEMINFO)); + cbSize = sizeof(MENUITEMINFO); +#if (WINVER >= 0x0500) + // adjust struct size if running on older version of Windows + if(AtlIsOldWindows()) + { + ATLASSERT(cbSize > MENUITEMINFO_SIZE_VERSION_400); // must be + cbSize = MENUITEMINFO_SIZE_VERSION_400; + } +#endif // (WINVER >= 0x0500) + } +}; + + +// forward declarations +template class CMenuT; +typedef CMenuT CMenuHandle; +typedef CMenuT CMenu; + + +template +class CMenuT +{ +public: +// Data members + HMENU m_hMenu; + +// Constructor/destructor/operators + CMenuT(HMENU hMenu = NULL) : m_hMenu(hMenu) + { } + + ~CMenuT() + { + if(t_bManaged && m_hMenu != NULL) + DestroyMenu(); + } + + CMenuT& operator =(HMENU hMenu) + { + Attach(hMenu); + return *this; + } + + void Attach(HMENU hMenuNew) + { + ATLASSERT(::IsMenu(hMenuNew)); + if(t_bManaged && m_hMenu != NULL && m_hMenu != hMenuNew) + ::DestroyMenu(m_hMenu); + m_hMenu = hMenuNew; + } + + HMENU Detach() + { + HMENU hMenu = m_hMenu; + m_hMenu = NULL; + return hMenu; + } + + operator HMENU() const { return m_hMenu; } + + bool IsNull() const { return (m_hMenu == NULL); } + + BOOL IsMenu() const + { + return ::IsMenu(m_hMenu); + } + +// Create/destroy methods + BOOL CreateMenu() + { + ATLASSERT(m_hMenu == NULL); + m_hMenu = ::CreateMenu(); + return (m_hMenu != NULL) ? TRUE : FALSE; + } + + BOOL CreatePopupMenu() + { + ATLASSERT(m_hMenu == NULL); + m_hMenu = ::CreatePopupMenu(); + return (m_hMenu != NULL) ? TRUE : FALSE; + } + + BOOL LoadMenu(ATL::_U_STRINGorID menu) + { + ATLASSERT(m_hMenu == NULL); + m_hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), menu.m_lpstr); + return (m_hMenu != NULL) ? TRUE : FALSE; + } + +#ifndef _WIN32_WCE + BOOL LoadMenuIndirect(const void* lpMenuTemplate) + { + ATLASSERT(m_hMenu == NULL); + m_hMenu = ::LoadMenuIndirect(lpMenuTemplate); + return (m_hMenu != NULL) ? TRUE : FALSE; + } +#endif // !_WIN32_WCE + + BOOL DestroyMenu() + { + if (m_hMenu == NULL) + return FALSE; + BOOL bRet = ::DestroyMenu(m_hMenu); + if(bRet) + m_hMenu = NULL; + return bRet; + } + +// Menu Operations + BOOL DeleteMenu(UINT nPosition, UINT nFlags) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::DeleteMenu(m_hMenu, nPosition, nFlags); + } + + BOOL TrackPopupMenu(UINT nFlags, int x, int y, HWND hWnd, LPCRECT lpRect = NULL) + { + ATLASSERT(::IsMenu(m_hMenu)); +#ifndef _WIN32_WCE +#if (WINVER >= 0x0500) + x = _FixTrackMenuPopupX(x, y); +#endif // !(WINVER >= 0x0500) + return ::TrackPopupMenu(m_hMenu, nFlags, x, y, 0, hWnd, lpRect); +#else // CE specific + lpRect; + return ::TrackPopupMenuEx(m_hMenu, nFlags, x, y, hWnd, NULL); +#endif // _WIN32_WCE + } + + BOOL TrackPopupMenuEx(UINT uFlags, int x, int y, HWND hWnd, LPTPMPARAMS lptpm = NULL) + { + ATLASSERT(::IsMenu(m_hMenu)); +#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) + x = _FixTrackMenuPopupX(x, y); +#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) + return ::TrackPopupMenuEx(m_hMenu, uFlags, x, y, hWnd, lptpm); + } + +#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) + // helper that fixes popup menu X position when it's off-screen + static int _FixTrackMenuPopupX(int x, int y) + { + POINT pt = { x, y }; + HMONITOR hMonitor = ::MonitorFromPoint(pt, MONITOR_DEFAULTTONULL); + if(hMonitor == NULL) + { + HMONITOR hMonitorNear = ::MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + if(hMonitorNear != NULL) + { + MONITORINFO mi = { 0 }; + mi.cbSize = sizeof(MONITORINFO); + if(::GetMonitorInfo(hMonitorNear, &mi) != FALSE) + { + if(x < mi.rcWork.left) + x = mi.rcWork.left; + else if(x > mi.rcWork.right) + x = mi.rcWork.right; + } + } + } + + return x; + } + + BOOL GetMenuInfo(LPMENUINFO lpMenuInfo) const + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::GetMenuInfo(m_hMenu, lpMenuInfo); + } + + BOOL SetMenuInfo(LPCMENUINFO lpMenuInfo) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::SetMenuInfo(m_hMenu, lpMenuInfo); + } +#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) + +// Menu Item Operations + BOOL AppendMenu(UINT nFlags, UINT_PTR nIDNewItem = 0, LPCTSTR lpszNewItem = NULL) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::AppendMenu(m_hMenu, nFlags, nIDNewItem, lpszNewItem); + } + + BOOL AppendMenu(UINT nFlags, HMENU hSubMenu, LPCTSTR lpszNewItem) + { + ATLASSERT(::IsMenu(m_hMenu)); + ATLASSERT(::IsMenu(hSubMenu)); + return ::AppendMenu(m_hMenu, nFlags | MF_POPUP, (UINT_PTR)hSubMenu, lpszNewItem); + } + +#ifndef _WIN32_WCE + BOOL AppendMenu(UINT nFlags, UINT_PTR nIDNewItem, HBITMAP hBmp) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::AppendMenu(m_hMenu, nFlags | MF_BITMAP, nIDNewItem, (LPCTSTR)hBmp); + } + + BOOL AppendMenu(UINT nFlags, HMENU hSubMenu, HBITMAP hBmp) + { + ATLASSERT(::IsMenu(m_hMenu)); + ATLASSERT(::IsMenu(hSubMenu)); + return ::AppendMenu(m_hMenu, nFlags | (MF_BITMAP | MF_POPUP), (UINT_PTR)hSubMenu, (LPCTSTR)hBmp); + } +#endif // !_WIN32_WCE + + UINT CheckMenuItem(UINT nIDCheckItem, UINT nCheck) + { + ATLASSERT(::IsMenu(m_hMenu)); + return (UINT)::CheckMenuItem(m_hMenu, nIDCheckItem, nCheck); + } + + UINT EnableMenuItem(UINT nIDEnableItem, UINT nEnable) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::EnableMenuItem(m_hMenu, nIDEnableItem, nEnable); + } + +#ifndef _WIN32_WCE + BOOL HiliteMenuItem(HWND hWnd, UINT uIDHiliteItem, UINT uHilite) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::HiliteMenuItem(hWnd, m_hMenu, uIDHiliteItem, uHilite); + } + + int GetMenuItemCount() const + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::GetMenuItemCount(m_hMenu); + } + + UINT GetMenuItemID(int nPos) const + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::GetMenuItemID(m_hMenu, nPos); + } + + UINT GetMenuState(UINT nID, UINT nFlags) const + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::GetMenuState(m_hMenu, nID, nFlags); + } + + int GetMenuString(UINT nIDItem, LPTSTR lpString, int nMaxCount, UINT nFlags) const + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::GetMenuString(m_hMenu, nIDItem, lpString, nMaxCount, nFlags); + } + + int GetMenuStringLen(UINT nIDItem, UINT nFlags) const + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::GetMenuString(m_hMenu, nIDItem, NULL, 0, nFlags); + } + +#ifndef _ATL_NO_COM + BOOL GetMenuString(UINT nIDItem, BSTR& bstrText, UINT nFlags) const + { + USES_CONVERSION; + ATLASSERT(::IsMenu(m_hMenu)); + ATLASSERT(bstrText == NULL); + + int nLen = GetMenuStringLen(nIDItem, nFlags); + if(nLen == 0) + { + bstrText = ::SysAllocString(OLESTR("")); + return (bstrText != NULL) ? TRUE : FALSE; + } + + nLen++; // increment to include terminating NULL char + CTempBuffer buff; + LPTSTR lpszText = buff.Allocate(nLen); + if(lpszText == NULL) + return FALSE; + + if(!GetMenuString(nIDItem, lpszText, nLen, nFlags)) + return FALSE; + + bstrText = ::SysAllocString(T2OLE(lpszText)); + return (bstrText != NULL) ? TRUE : FALSE; + } +#endif // !_ATL_NO_COM +#endif // !_WIN32_WCE + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + int GetMenuString(UINT nIDItem, _CSTRING_NS::CString& strText, UINT nFlags) const + { + ATLASSERT(::IsMenu(m_hMenu)); + + int nLen = GetMenuStringLen(nIDItem, nFlags); + if(nLen == 0) + return 0; + + nLen++; // increment to include terminating NULL char + LPTSTR lpstr = strText.GetBufferSetLength(nLen); + if(lpstr == NULL) + return 0; + int nRet = GetMenuString(nIDItem, lpstr, nLen, nFlags); + strText.ReleaseBuffer(); + return nRet; + } +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + + CMenuHandle GetSubMenu(int nPos) const + { + ATLASSERT(::IsMenu(m_hMenu)); + return CMenuHandle(::GetSubMenu(m_hMenu, nPos)); + } + + BOOL InsertMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem = 0, LPCTSTR lpszNewItem = NULL) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::InsertMenu(m_hMenu, nPosition, nFlags, nIDNewItem, lpszNewItem); + } + + BOOL InsertMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, LPCTSTR lpszNewItem) + { + ATLASSERT(::IsMenu(m_hMenu)); + ATLASSERT(::IsMenu(hSubMenu)); + return ::InsertMenu(m_hMenu, nPosition, nFlags | MF_POPUP, (UINT_PTR)hSubMenu, lpszNewItem); + } + +#ifndef _WIN32_WCE + BOOL InsertMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem, HBITMAP hBmp) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::InsertMenu(m_hMenu, nPosition, nFlags | MF_BITMAP, nIDNewItem, (LPCTSTR)hBmp); + } + + BOOL InsertMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, HBITMAP hBmp) + { + ATLASSERT(::IsMenu(m_hMenu)); + ATLASSERT(::IsMenu(hSubMenu)); + return ::InsertMenu(m_hMenu, nPosition, nFlags | (MF_BITMAP | MF_POPUP), (UINT_PTR)hSubMenu, (LPCTSTR)hBmp); + } + + BOOL ModifyMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem = 0, LPCTSTR lpszNewItem = NULL) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::ModifyMenu(m_hMenu, nPosition, nFlags, nIDNewItem, lpszNewItem); + } + + BOOL ModifyMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, LPCTSTR lpszNewItem) + { + ATLASSERT(::IsMenu(m_hMenu)); + ATLASSERT(::IsMenu(hSubMenu)); + return ::ModifyMenu(m_hMenu, nPosition, nFlags | MF_POPUP, (UINT_PTR)hSubMenu, lpszNewItem); + } + + BOOL ModifyMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem, HBITMAP hBmp) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::ModifyMenu(m_hMenu, nPosition, nFlags | MF_BITMAP, nIDNewItem, (LPCTSTR)hBmp); + } + + BOOL ModifyMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, HBITMAP hBmp) + { + ATLASSERT(::IsMenu(m_hMenu)); + ATLASSERT(::IsMenu(hSubMenu)); + return ::ModifyMenu(m_hMenu, nPosition, nFlags | (MF_BITMAP | MF_POPUP), (UINT_PTR)hSubMenu, (LPCTSTR)hBmp); + } +#endif // !_WIN32_WCE + + BOOL RemoveMenu(UINT nPosition, UINT nFlags) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::RemoveMenu(m_hMenu, nPosition, nFlags); + } + +#ifndef _WIN32_WCE + BOOL SetMenuItemBitmaps(UINT nPosition, UINT nFlags, HBITMAP hBmpUnchecked, HBITMAP hBmpChecked) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::SetMenuItemBitmaps(m_hMenu, nPosition, nFlags, hBmpUnchecked, hBmpChecked); + } +#endif // !_WIN32_WCE + + BOOL CheckMenuRadioItem(UINT nIDFirst, UINT nIDLast, UINT nIDItem, UINT nFlags) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::CheckMenuRadioItem(m_hMenu, nIDFirst, nIDLast, nIDItem, nFlags); + } + + BOOL GetMenuItemInfo(UINT uItem, BOOL bByPosition, LPMENUITEMINFO lpmii) const + { + ATLASSERT(::IsMenu(m_hMenu)); + return (BOOL)::GetMenuItemInfo(m_hMenu, uItem, bByPosition, lpmii); + } + + BOOL SetMenuItemInfo(UINT uItem, BOOL bByPosition, LPMENUITEMINFO lpmii) + { + ATLASSERT(::IsMenu(m_hMenu)); + return (BOOL)::SetMenuItemInfo(m_hMenu, uItem, bByPosition, lpmii); + } + +#ifndef _WIN32_WCE + BOOL InsertMenuItem(UINT uItem, BOOL bByPosition, LPMENUITEMINFO lpmii) + { + ATLASSERT(::IsMenu(m_hMenu)); + return (BOOL)::InsertMenuItem(m_hMenu, uItem, bByPosition, lpmii); + } + + UINT GetMenuDefaultItem(BOOL bByPosition = FALSE, UINT uFlags = 0U) const + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::GetMenuDefaultItem(m_hMenu, (UINT)bByPosition, uFlags); + } + + BOOL SetMenuDefaultItem(UINT uItem = (UINT)-1, BOOL bByPosition = FALSE) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::SetMenuDefaultItem(m_hMenu, uItem, (UINT)bByPosition); + } + + BOOL GetMenuItemRect(HWND hWnd, UINT uItem, LPRECT lprcItem) const + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::GetMenuItemRect(hWnd, m_hMenu, uItem, lprcItem); + } + + int MenuItemFromPoint(HWND hWnd, POINT point) const + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::MenuItemFromPoint(hWnd, m_hMenu, point); + } + +// Context Help Functions + BOOL SetMenuContextHelpId(DWORD dwContextHelpId) + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::SetMenuContextHelpId(m_hMenu, dwContextHelpId); + } + + DWORD GetMenuContextHelpId() const + { + ATLASSERT(::IsMenu(m_hMenu)); + return ::GetMenuContextHelpId(m_hMenu); + } +#endif // !_WIN32_WCE +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CAccelerator + +template +class CAcceleratorT +{ +public: + HACCEL m_hAccel; + +// Constructor/destructor/operators + CAcceleratorT(HACCEL hAccel = NULL) : m_hAccel(hAccel) + { } + + ~CAcceleratorT() + { + if(t_bManaged && m_hAccel != NULL) + ::DestroyAcceleratorTable(m_hAccel); + } + + CAcceleratorT& operator =(HACCEL hAccel) + { + Attach(hAccel); + return *this; + } + + void Attach(HACCEL hAccel) + { + if(t_bManaged && m_hAccel != NULL) + ::DestroyAcceleratorTable(m_hAccel); + m_hAccel = hAccel; + } + + HACCEL Detach() + { + HACCEL hAccel = m_hAccel; + m_hAccel = NULL; + return hAccel; + } + + operator HACCEL() const { return m_hAccel; } + + bool IsNull() const { return m_hAccel == NULL; } + +// Create/destroy methods + HACCEL LoadAccelerators(ATL::_U_STRINGorID accel) + { + ATLASSERT(m_hAccel == NULL); + m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), accel.m_lpstr); + return m_hAccel; + } + + HACCEL CreateAcceleratorTable(LPACCEL pAccel, int cEntries) + { + ATLASSERT(m_hAccel == NULL); + ATLASSERT(pAccel != NULL); + m_hAccel = ::CreateAcceleratorTable(pAccel, cEntries); + return m_hAccel; + } + + void DestroyObject() + { + if(m_hAccel != NULL) + { + ::DestroyAcceleratorTable(m_hAccel); + m_hAccel = NULL; + } + } + +// Operations +#ifndef _WIN32_WCE + int CopyAcceleratorTable(LPACCEL lpAccelDst, int cEntries) + { + ATLASSERT(m_hAccel != NULL); + ATLASSERT(lpAccelDst != NULL); + return ::CopyAcceleratorTable(m_hAccel, lpAccelDst, cEntries); + } + + int GetEntriesCount() const + { + ATLASSERT(m_hAccel != NULL); + return ::CopyAcceleratorTable(m_hAccel, NULL, 0); + } +#endif // !_WIN32_WCE + + BOOL TranslateAccelerator(HWND hWnd, LPMSG pMsg) + { + ATLASSERT(m_hAccel != NULL); + ATLASSERT(::IsWindow(hWnd)); + ATLASSERT(pMsg != NULL); + return ::TranslateAccelerator(hWnd, m_hAccel, pMsg); + } +}; + +typedef CAcceleratorT CAcceleratorHandle; +typedef CAcceleratorT CAccelerator; + + +/////////////////////////////////////////////////////////////////////////////// +// CIcon + +template +class CIconT +{ +public: + HICON m_hIcon; + +// Constructor/destructor/operators + CIconT(HICON hIcon = NULL) : m_hIcon(hIcon) + { } + + ~CIconT() + { + if(t_bManaged && m_hIcon != NULL) + ::DestroyIcon(m_hIcon); + } + + CIconT& operator =(HICON hIcon) + { + Attach(hIcon); + return *this; + } + + void Attach(HICON hIcon) + { + if(t_bManaged && m_hIcon != NULL) + ::DestroyIcon(m_hIcon); + m_hIcon = hIcon; + } + + HICON Detach() + { + HICON hIcon = m_hIcon; + m_hIcon = NULL; + return hIcon; + } + + operator HICON() const { return m_hIcon; } + + bool IsNull() const { return m_hIcon == NULL; } + +// Create/destroy methods + HICON LoadIcon(ATL::_U_STRINGorID icon) + { + ATLASSERT(m_hIcon == NULL); + m_hIcon = ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr); + return m_hIcon; + } + + HICON LoadIcon(ATL::_U_STRINGorID icon, int cxDesired, int cyDesired, UINT fuLoad = 0) + { + ATLASSERT(m_hIcon == NULL); + m_hIcon = (HICON) ::LoadImage(ModuleHelper::GetResourceInstance(), icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad); + return m_hIcon; + } + +#ifndef _WIN32_WCE + HICON LoadOEMIcon(LPCTSTR lpstrIconName) + { + ATLASSERT(m_hIcon == NULL); + ATLASSERT(IsOEMIcon(lpstrIconName)); + m_hIcon = ::LoadIcon(NULL, lpstrIconName); + return m_hIcon; + } + + HICON CreateIcon(int nWidth, int nHeight, BYTE cPlanes, BYTE cBitsPixel, CONST BYTE* lpbANDbits, CONST BYTE *lpbXORbits) + { + ATLASSERT(m_hIcon == NULL); + ATLASSERT(lpbANDbits != NULL); + ATLASSERT(lpbXORbits != NULL); + m_hIcon = ::CreateIcon(ModuleHelper::GetResourceInstance(), nWidth, nHeight, cPlanes, cBitsPixel, lpbANDbits, lpbXORbits); + return m_hIcon; + } + + HICON CreateIconFromResource(PBYTE pBits, DWORD dwResSize, DWORD dwVersion = 0x00030000) + { + ATLASSERT(m_hIcon == NULL); + ATLASSERT(pBits != NULL); + m_hIcon = ::CreateIconFromResource(pBits, dwResSize, TRUE, dwVersion); + return m_hIcon; + } + + HICON CreateIconFromResourceEx(PBYTE pbBits, DWORD cbBits, DWORD dwVersion = 0x00030000, int cxDesired = 0, int cyDesired = 0, UINT uFlags = LR_DEFAULTCOLOR) + { + ATLASSERT(m_hIcon == NULL); + ATLASSERT(pbBits != NULL); + ATLASSERT(cbBits > 0); + m_hIcon = ::CreateIconFromResourceEx(pbBits, cbBits, TRUE, dwVersion, cxDesired, cyDesired, uFlags); + return m_hIcon; + } +#endif // !_WIN32_WCE + + HICON CreateIconIndirect(PICONINFO pIconInfo) + { + ATLASSERT(m_hIcon == NULL); + ATLASSERT(pIconInfo != NULL); + m_hIcon = ::CreateIconIndirect(pIconInfo); + return m_hIcon; + } + +#ifndef _WIN32_WCE + HICON ExtractIcon(LPCTSTR lpszExeFileName, UINT nIconIndex) + { + ATLASSERT(m_hIcon == NULL); + ATLASSERT(lpszExeFileName != NULL); + m_hIcon = ::ExtractIcon(ModuleHelper::GetModuleInstance(), lpszExeFileName, nIconIndex); + return m_hIcon; + } + + HICON ExtractAssociatedIcon(HINSTANCE hInst, LPTSTR lpIconPath, LPWORD lpiIcon) + { + ATLASSERT(m_hIcon == NULL); + ATLASSERT(lpIconPath != NULL); + ATLASSERT(lpiIcon != NULL); + m_hIcon = ::ExtractAssociatedIcon(hInst, lpIconPath, lpiIcon); + return m_hIcon; + } +#endif // !_WIN32_WCE + + BOOL DestroyIcon() + { + ATLASSERT(m_hIcon != NULL); + BOOL bRet = ::DestroyIcon(m_hIcon); + if(bRet != FALSE) + m_hIcon = NULL; + return bRet; + } + +// Operations +#ifndef _WIN32_WCE + HICON CopyIcon() + { + ATLASSERT(m_hIcon != NULL); + return ::CopyIcon(m_hIcon); + } + + HICON DuplicateIcon() + { + ATLASSERT(m_hIcon != NULL); + return ::DuplicateIcon(NULL, m_hIcon); + } +#endif // !_WIN32_WCE + + BOOL DrawIcon(HDC hDC, int x, int y) + { + ATLASSERT(m_hIcon != NULL); +#ifndef _WIN32_WCE + return ::DrawIcon(hDC, x, y, m_hIcon); +#else // CE specific + return ::DrawIconEx(hDC, x, y, m_hIcon, 0, 0, 0, NULL, DI_NORMAL); +#endif // _WIN32_WCE + } + + BOOL DrawIcon(HDC hDC, POINT pt) + { + ATLASSERT(m_hIcon != NULL); +#ifndef _WIN32_WCE + return ::DrawIcon(hDC, pt.x, pt.y, m_hIcon); +#else // CE specific + return ::DrawIconEx(hDC, pt.x, pt.y, m_hIcon, 0, 0, 0, NULL, DI_NORMAL); +#endif // _WIN32_WCE + } + + BOOL DrawIconEx(HDC hDC, int x, int y, int cxWidth, int cyWidth, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL) + { + ATLASSERT(m_hIcon != NULL); + return ::DrawIconEx(hDC, x, y, m_hIcon, cxWidth, cyWidth, uStepIfAniCur, hbrFlickerFreeDraw, uFlags); + } + + BOOL DrawIconEx(HDC hDC, POINT pt, SIZE size, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL) + { + ATLASSERT(m_hIcon != NULL); + return ::DrawIconEx(hDC, pt.x, pt.y, m_hIcon, size.cx, size.cy, uStepIfAniCur, hbrFlickerFreeDraw, uFlags); + } + +#ifndef _WIN32_WCE + BOOL GetIconInfo(PICONINFO pIconInfo) const + { + ATLASSERT(m_hIcon != NULL); + ATLASSERT(pIconInfo != NULL); + return ::GetIconInfo(m_hIcon, pIconInfo); + } + +#if (_WIN32_WINNT >= 0x0600) + BOOL GetIconInfoEx(PICONINFOEX pIconInfo) const + { + ATLASSERT(m_hIcon != NULL); + ATLASSERT(pIconInfo != NULL); + return ::GetIconInfoEx(m_hIcon, pIconInfo); + } +#endif // (_WIN32_WINNT >= 0x0600) + +#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) + HRESULT LoadIconMetric(ATL::_U_STRINGorID icon, int lims) + { + ATLASSERT(m_hIcon == NULL); + USES_CONVERSION; + return ::LoadIconMetric(ModuleHelper::GetResourceInstance(), T2CW(icon.m_lpstr), lims, &m_hIcon); + } + + HRESULT LoadIconWithScaleDown(ATL::_U_STRINGorID icon, int cx, int cy) + { + ATLASSERT(m_hIcon == NULL); + USES_CONVERSION; + return ::LoadIconWithScaleDown(ModuleHelper::GetResourceInstance(), T2CW(icon.m_lpstr), cx, cy, &m_hIcon); + } + + HRESULT LoadOEMIconMetric(LPCTSTR lpstrIconName, int lims) + { + ATLASSERT(m_hIcon == NULL); + ATLASSERT(IsOEMIcon(lpstrIconName)); + return ::LoadIconMetric(NULL, (LPCWSTR)lpstrIconName, lims, &m_hIcon); + } + + HRESULT LoadOEMIconWithScaleDown(LPCTSTR lpstrIconName, int cx, int cy) + { + ATLASSERT(m_hIcon == NULL); + ATLASSERT(IsOEMIcon(lpstrIconName)); + USES_CONVERSION; + return ::LoadIconWithScaleDown(NULL, (LPCWSTR)lpstrIconName, cx, cy, &m_hIcon); + } +#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) +#endif // !_WIN32_WCE + + // Helper +#ifndef _WIN32_WCE + static bool IsOEMIcon(LPCTSTR lpstrIconName) + { +#if (WINVER >= 0x0600) + return (lpstrIconName == IDI_APPLICATION || lpstrIconName == IDI_ASTERISK || lpstrIconName == IDI_EXCLAMATION || + lpstrIconName == IDI_HAND || lpstrIconName == IDI_QUESTION || lpstrIconName == IDI_WINLOGO || + lpstrIconName == IDI_SHIELD); +#else // !(WINVER >= 0x0600) + return (lpstrIconName == IDI_APPLICATION || lpstrIconName == IDI_ASTERISK || lpstrIconName == IDI_EXCLAMATION || + lpstrIconName == IDI_HAND || lpstrIconName == IDI_QUESTION || lpstrIconName == IDI_WINLOGO); +#endif // !(WINVER >= 0x0600) + } +#endif // !_WIN32_WCE +}; + +typedef CIconT CIconHandle; +typedef CIconT CIcon; + + +/////////////////////////////////////////////////////////////////////////////// +// CCursor + +// protect template member from a winuser.h macro +#ifdef CopyCursor + #undef CopyCursor +#endif + +template +class CCursorT +{ +public: + HCURSOR m_hCursor; + +// Constructor/destructor/operators + CCursorT(HCURSOR hCursor = NULL) : m_hCursor(hCursor) + { } + + ~CCursorT() + { + if(t_bManaged && m_hCursor != NULL) + DestroyCursor(); + } + + CCursorT& operator =(HCURSOR hCursor) + { + Attach(hCursor); + return *this; + } + + void Attach(HCURSOR hCursor) + { + if(t_bManaged && m_hCursor != NULL) + DestroyCursor(); + m_hCursor = hCursor; + } + + HCURSOR Detach() + { + HCURSOR hCursor = m_hCursor; + m_hCursor = NULL; + return hCursor; + } + + operator HCURSOR() const { return m_hCursor; } + + bool IsNull() const { return m_hCursor == NULL; } + +// Create/destroy methods + HCURSOR LoadCursor(ATL::_U_STRINGorID cursor) + { + ATLASSERT(m_hCursor == NULL); + m_hCursor = ::LoadCursor(ModuleHelper::GetResourceInstance(), cursor.m_lpstr); + return m_hCursor; + } + + HCURSOR LoadSysCursor(LPCTSTR lpstrCursorName) + { + ATLASSERT(m_hCursor == NULL); +#if (WINVER >= 0x0500) + ATLASSERT(lpstrCursorName == IDC_ARROW || lpstrCursorName == IDC_IBEAM || lpstrCursorName == IDC_WAIT || + lpstrCursorName == IDC_CROSS || lpstrCursorName == IDC_UPARROW || lpstrCursorName == IDC_SIZE || + lpstrCursorName == IDC_ICON || lpstrCursorName == IDC_SIZENWSE || lpstrCursorName == IDC_SIZENESW || + lpstrCursorName == IDC_SIZEWE || lpstrCursorName == IDC_SIZENS || lpstrCursorName == IDC_SIZEALL || + lpstrCursorName == IDC_NO || lpstrCursorName == IDC_APPSTARTING || lpstrCursorName == IDC_HELP || + lpstrCursorName == IDC_HAND); +#else // !(WINVER >= 0x0500) + ATLASSERT(lpstrCursorName == IDC_ARROW || lpstrCursorName == IDC_IBEAM || lpstrCursorName == IDC_WAIT || + lpstrCursorName == IDC_CROSS || lpstrCursorName == IDC_UPARROW || lpstrCursorName == IDC_SIZE || + lpstrCursorName == IDC_ICON || lpstrCursorName == IDC_SIZENWSE || lpstrCursorName == IDC_SIZENESW || + lpstrCursorName == IDC_SIZEWE || lpstrCursorName == IDC_SIZENS || lpstrCursorName == IDC_SIZEALL || + lpstrCursorName == IDC_NO || lpstrCursorName == IDC_APPSTARTING || lpstrCursorName == IDC_HELP); +#endif // !(WINVER >= 0x0500) + m_hCursor = ::LoadCursor(NULL, lpstrCursorName); + return m_hCursor; + } + + // deprecated + HCURSOR LoadOEMCursor(LPCTSTR lpstrCursorName) + { + return LoadSysCursor(lpstrCursorName); + } + + HCURSOR LoadCursor(ATL::_U_STRINGorID cursor, int cxDesired, int cyDesired, UINT fuLoad = 0) + { + ATLASSERT(m_hCursor == NULL); + m_hCursor = (HCURSOR) ::LoadImage(ModuleHelper::GetResourceInstance(), cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad); + return m_hCursor; + } + +#ifndef _WIN32_WCE + HCURSOR LoadCursorFromFile(LPCTSTR pstrFilename) + { + ATLASSERT(m_hCursor == NULL); + ATLASSERT(pstrFilename != NULL); + m_hCursor = ::LoadCursorFromFile(pstrFilename); + return m_hCursor; + } +#endif // !_WIN32_WCE + +#if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))) + HCURSOR CreateCursor(int xHotSpot, int yHotSpot, int nWidth, int nHeight, CONST VOID *pvANDPlane, CONST VOID *pvXORPlane) + { + ATLASSERT(m_hCursor == NULL); + m_hCursor = ::CreateCursor(ModuleHelper::GetResourceInstance(), xHotSpot, yHotSpot, nWidth, nHeight, pvANDPlane, pvXORPlane); + return m_hCursor; + } +#endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))) + +#ifndef _WIN32_WCE + HCURSOR CreateCursorFromResource(PBYTE pBits, DWORD dwResSize, DWORD dwVersion = 0x00030000) + { + ATLASSERT(m_hCursor == NULL); + ATLASSERT(pBits != NULL); + m_hCursor = (HCURSOR)::CreateIconFromResource(pBits, dwResSize, FALSE, dwVersion); + return m_hCursor; + } + + HCURSOR CreateCursorFromResourceEx(PBYTE pbBits, DWORD cbBits, DWORD dwVersion = 0x00030000, int cxDesired = 0, int cyDesired = 0, UINT uFlags = LR_DEFAULTCOLOR) + { + ATLASSERT(m_hCursor == NULL); + ATLASSERT(pbBits != NULL); + ATLASSERT(cbBits > 0); + m_hCursor = (HCURSOR)::CreateIconFromResourceEx(pbBits, cbBits, FALSE, dwVersion, cxDesired, cyDesired, uFlags); + return m_hCursor; + } +#endif // !_WIN32_WCE + + BOOL DestroyCursor() + { + ATLASSERT(m_hCursor != NULL); +#if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))) + BOOL bRet = ::DestroyCursor(m_hCursor); + if(bRet != FALSE) + m_hCursor = NULL; + return bRet; +#else // !(!defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))) + ATLTRACE2(atlTraceUI, 0, _T("Warning: This version of Windows CE does not have ::DestroyCursor()\n")); + return FALSE; +#endif // !(!defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))) + } + +// Operations +#ifndef _WIN32_WCE + HCURSOR CopyCursor() + { + ATLASSERT(m_hCursor != NULL); + return (HCURSOR)::CopyIcon((HICON)m_hCursor); + } +#endif // !_WIN32_WCE + +#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) + BOOL GetCursorInfo(LPCURSORINFO pCursorInfo) + { + ATLASSERT(m_hCursor != NULL); + ATLASSERT(pCursorInfo != NULL); + return ::GetCursorInfo(pCursorInfo); + } +#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) +}; + +typedef CCursorT CCursorHandle; +typedef CCursorT CCursor; + + +/////////////////////////////////////////////////////////////////////////////// +// CResource - Wraps a generic Windows resource. +// Use it with custom resource types other than the +// standard RT_CURSOR, RT_BITMAP, etc. + +class CResource +{ +public: + HGLOBAL m_hGlobal; + HRSRC m_hResource; + +// Constructor/destructor + CResource() : m_hGlobal(NULL), m_hResource(NULL) + { } + + ~CResource() + { + Release(); + } + +// Load methods + bool Load(ATL::_U_STRINGorID Type, ATL::_U_STRINGorID ID) + { + ATLASSERT(m_hResource == NULL); + ATLASSERT(m_hGlobal == NULL); + + m_hResource = ::FindResource(ModuleHelper::GetResourceInstance(), ID.m_lpstr, Type.m_lpstr); + if(m_hResource == NULL) + return false; + + m_hGlobal = ::LoadResource(ModuleHelper::GetResourceInstance(), m_hResource); + if(m_hGlobal == NULL) + { + m_hResource = NULL; + return false; + } + + return true; + } + +#ifndef _WIN32_WCE + bool LoadEx(ATL::_U_STRINGorID Type, ATL::_U_STRINGorID ID, WORD wLanguage) + { + ATLASSERT(m_hResource == NULL); + ATLASSERT(m_hGlobal == NULL); + + m_hResource = ::FindResourceEx(ModuleHelper::GetResourceInstance(), ID.m_lpstr, Type.m_lpstr, wLanguage); + if(m_hResource == NULL) + return false; + + m_hGlobal = ::LoadResource(ModuleHelper::GetResourceInstance(), m_hResource); + if(m_hGlobal == NULL) + { + m_hResource = NULL; + return false; + } + + return true; + } +#endif // !_WIN32_WCE + +// Misc. operations + DWORD GetSize() const + { + ATLASSERT(m_hResource != NULL); + return ::SizeofResource(ModuleHelper::GetResourceInstance(), m_hResource); + } + + LPVOID Lock() + { + ATLASSERT(m_hResource != NULL); + ATLASSERT(m_hGlobal != NULL); + LPVOID pVoid = ::LockResource(m_hGlobal); + ATLASSERT(pVoid != NULL); + return pVoid; + } + + void Release() + { + if(m_hGlobal != NULL) + { + FreeResource(m_hGlobal); + m_hGlobal = NULL; + m_hResource = NULL; + } + } +}; + +}; // namespace WTL + +#endif // __ATLUSER_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlwince.h b/Client/Client/GUI/BKWin/wtl/atlwince.h new file mode 100644 index 00000000..31ba35aa --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlwince.h @@ -0,0 +1,3007 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLWINCE_H__ +#define __ATLWINCE_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifndef __ATLAPP_H__ + #error atlwince.h requires atlapp.h to be included first +#endif + +#ifndef __ATLWIN_H__ + #error atlwince.h requires atlwin.h to be included first +#endif + +#ifndef _WIN32_WCE + #error atlwince.h compiles under Windows CE only +#elif (_WIN32_WCE < 300) + #error atlwince.h requires Windows CE 3.0 or higher. +#endif + +#if defined(WIN32_PLATFORM_WFSP) && _MSC_VER < 1400 // EVC compiling SmartPhone code + #if (WIN32_PLATFORM_WFSP < 200) + #error atlwince.h requires Smartphone 2003 or higher + #endif +#endif // WIN32_PLATFORM_WFSP + +#if defined(WIN32_PLATFORM_PSPC) && _MSC_VER < 1400 // EVC compiling Pocket PC code + #if (WIN32_PLATFORM_PSPC < 310) + #error atlwince.h requires Pocket PC 2002 or higher + #endif +#endif // WIN32_PLATFORM_PSPC + +#if !defined(_AYGSHELL_H_) && !defined(__AYGSHELL_H__) + #error atlwince.h requires aygshell.h to be included first +#else + #if defined(WIN32_PLATFORM_WFSP) && !defined(_TPCSHELL_H_) + #error SmartPhone dialog classes require tpcshell.h to be included first + #endif +#endif + +#if (_MSC_VER >= 1400) // VS2005 + #include + #define _WTL_CE_DRA +#endif // (_MSC_VER >= 1400) + +#if !defined(_WTL_CE_NO_DIALOGS) && !defined(__ATLFRAME_H__) + #error Orientation aware dialog classes require atlframe.h to be included first +#endif + +#if !defined(_WTL_CE_NO_APPWINDOW) && !defined(__ATLFRAME_H__) + #error Application window class require atlframe.h to be included first +#endif + +#if !defined(_WTL_CE_NO_ZOOMSCROLL) && !defined(__ATLSCRL_H__) + #error ZoomScroll implementation requires atlscrl.h to be included first +#endif + +#if !defined(_WTL_CE_NO_ZOOMSCROLL) + #if !(defined(__ATLTYPES_H__) || (defined(__ATLMISC_H__) && !defined(_WTL_NO_WTYPES))) + #error ZoomScroll requires _WTL_NO_WTYPES not to be defined and either atlmisc.h or atltypes.h to be included first + #endif // !(defined(__ATLTYPES_H__) || (defined(__ATLMISC_H__) && !defined(_WTL_NO_WTYPES))) +#endif // !defined(_WTL_CE_NO_ZOOMSCROLL) + +#if !defined(WIN32_PLATFORM_WFSP) && !defined(WIN32_PLATFORM_PSPC) + #define _WTL_CE_NO_CONTROLS +#endif // !defined(WIN32_PLATFORM_WFSP) && !defined(WIN32_PLATFORM_PSPC) + +#ifndef _WTL_CE_NO_CONTROLS + #ifndef __ATLCTRLS_H__ + #error The PPC/SmartPhone controls classes require atlctrls.h to be included first + #endif + + #include + #pragma comment(lib, "htmlview.lib") + + #include + #pragma comment(lib, "voicectl.lib") + + #ifdef WIN32_PLATFORM_PSPC + #include + #pragma comment(lib, "richink.lib") + + #include + #pragma comment(lib, "inkx.lib") + + #include + #pragma comment(lib, "doclist.lib") + #endif +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CStdDialogBase : Standard PPC/SmartPhone dialog base class +// CStdDialogImplBase - Base implementation of standard dialog +// CStdDialogImpl : Standard dialog implementation +// CStdIndirectDialogImpl - implementation of standard indirect PPC/SmartPhone dialog +// CStdAxDialogImpl : Standard AxDialog implementation +// CStdSimpleDialog : Standard simple dialog +// CStdDialogResizeImplBase - Base implementation of orientation resizing standard dialog +// CStdDialogResizeImpl : Orientation resizing standard dialog implementation +// CStdAxDialogResizeImpl - implementation of orientation resizing standard AxDialog +// CStdSimpleDialogResizeImpl : Standard resizing simple dialog implementation +// CStdOrientedDialogBase - Oriented PPC standard dialog base class +// CStdOrientedDialogImplBase - Oriented PPC standard dialog base implementation +// CStdOrientedDialogImpl : Oriented PPC standard dialog implementation +// CStdAxOrientedDialogImpl - Oriented PPC standard AxDialog implementation +// CStdSimpleOrientedDialog : Standard simple orientable dialog +// +// CAppInfoBase : Helper for application state save/restore to registry +// CAppInfoT : CAppInfoBase constructed from a CAppWindow +// CAppWindowBase : Base class for PPC/SmartPhone well-behaved application window or dialog +// CAppWindow : PPC/SmartPhone well-behaved application window class +// CAppDialog : PPC/SmartPhone well-behaved application dialog class +// CAppStdDialogImplBase - Base implementation of standard application dialogs +// CAppStdDialogImpl : Implementation of standard application dialog +// CAppStdDialogResizeImpl - implementation of orientation resizing standard application dialog +// CAppStdAxDialogImpl - Implementation of standard application AxDialog +// CAppStdAxDialogResizeImpl - implementation of orientation resizing standard application AxDialog +// CAppStdOrientedDialogImpl - implementation of oriented PPC standard application dialog +// CAppStdAxOrientedDialogImpl - implementation of oriented PPC standard application AxDialog +// +// CFullScreenFrame : Full screen frame class +// +// CZoomScrollImpl : WinCE zooming implementation +// +// CBottomTabViewImpl - CBottomTabView +// CHtmlCtrlT - CHtmlCtrl +// CRichInkCtrlT - CRichInkCtrl +// CInkXCtrlT - CInkXCtrl +// CVoiceRecorderCtrlT - CVoiceRecorderCtrl +// CDocListCtrlT - CDocListCtrl +// CCapEditT - CCapEdit +// CTTStaticT - CTTStatic +// CTTButtonT - CTTButton +// +// CSpinCtrlT - CSpinCtrl : SmartPhone specific UpDown control +// CSpinned : SmartPhone association of control and Spin +// CSpinListBox : SmartPhone spinned ListBox control +// CExpandListBox : SmartPhone expandable ListBox control +// CExpandEdit : SmartPhone expandable Edit control +// CExpandCapEdit : SmartPhone expandable CapEdit control +// +// Global functions: +// AtlCreateMenuBar() +// AtlCreateEmptyMenuBar() +// AtlIsEditFocus() +// AtlActivateBackKey() + +namespace WTL +{ + +/////////////////////////////////////////////////////////////////////////////// +// MenuBar creation functions for property sheets and dialogs +// Frame windows use CreateSimpleCEMenuBar + +inline HWND AtlCreateMenuBar(SHMENUBARINFO& mbi) +{ + ATLASSERT(::IsWindow(mbi.hwndParent)); + ATLVERIFY(::SHCreateMenuBar(&mbi) != FALSE); + return mbi.hwndMB; +}; + +inline HWND AtlCreateMenuBar(HWND hWnd, UINT nToolBarId = ATL_IDW_TOOLBAR, DWORD dwFlags = 0, int nBmpId = 0, int cBmpImages = 0, COLORREF clrBk = 0) +{ + SHMENUBARINFO mbi = { sizeof(mbi), hWnd, dwFlags, nToolBarId, ModuleHelper::GetResourceInstance(), nBmpId, cBmpImages, 0, clrBk }; + return AtlCreateMenuBar(mbi); +} + +inline HWND AtlCreateEmptyMenuBar(HWND hWnd, bool bSip = true) +{ + SHMENUBARINFO embi = { sizeof(SHMENUBARINFO), hWnd, SHCMBF_EMPTYBAR }; + if (!bSip) + embi.dwFlags |= SHCMBF_HIDESIPBUTTON; + + return AtlCreateMenuBar(embi); +} + +/////////////////////////////////////////////////////////////////////////////// +// Helper functions for SmartPhone back key handling + +inline bool AtlIsEditFocus() +{ + ATL::CWindow wCtrl = GetFocus(); + if (wCtrl.IsWindow()) + { + TCHAR szClassName[8] = {0}; + ATLVERIFY(::GetClassName(wCtrl.m_hWnd, szClassName, 8)); + return !_tcscmp(szClassName, _T("Edit")) || !_tcscmp(szClassName, WC_CAPEDIT); + } + return false; +} + +#if defined WIN32_PLATFORM_WFSP +inline void AtlActivateBackKey(HWND hMenuBar) +{ + ATLASSERT(::IsWindow(hMenuBar)); + ::SendMessage(hMenuBar, SHCMBM_OVERRIDEKEY, VK_TBACK, + MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY)); +} +#endif // WIN32_PLATFORM_WFSP + +// --- Standard PPC/SmartPhone dialogs --- + +#ifndef _WTL_CE_NO_DIALOGS + +/////////////////////////////////////////////////////////////////////////////// +// CStdDialogBase - base class for standard PPC/SmartPhone dialogs + +#define WTL_STD_SHIDIF SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN +#define WTL_SP_SHIDIF SHIDIF_SIZEDLGFULLSCREEN + +// Title setting macros +#define WTL_DLG_TITLEHEIGHT(iHeight) static const int GetTitleHeight(){return iHeight;} +#define WTL_DLG_NOTITLE WTL_DLG_TITLEHEIGHT(0) + +/////////////////////////////////////////////////////////////////////////////// +// CStdDialogBase - Base class for standard PPC/SmartPhone dialog + +template +class CStdDialogBase +{ +public: +#ifdef WIN32_PLATFORM_PSPC +// Pocket PC only Dialog title handling + const int nTitleHeight; + + CStdDialogBase() : nTitleHeight(T::GetTitleHeight()) + { } + +// Overloads + BOOL GetClientRect(LPRECT lpRect) + { + T* pT = static_cast(this); + ATLASSERT(pT->IsWindow()); + BOOL bRes = ::GetClientRect(pT->m_hWnd, lpRect); + lpRect->top += nTitleHeight; + return bRes; + } + + BOOL SetWindowText(LPCTSTR lpszString) + { + T* pT = static_cast(this); + ATLASSERT(pT->IsWindow()); + BOOL bRes = ::SetWindowText(pT->m_hWnd, lpszString); + if (nTitleHeight != 0) + pT->DoPaintTitle(); + return bRes; + } + +// Overrideables + static const int GetTitleHeight() + { + #ifdef _WTL_CE_DRA + return DRA::SCALEY(24); + #else // !_WTL_CE_DRA + CWindowDC dc(NULL); + return dc.GetDeviceCaps(LOGPIXELSY) >> 2; // LOGPIXELSY * 24 / 96, + #endif // !_WTL_CE_DRA + } + + // Title painting + bool DoPaintTitle() + { + T* pT = static_cast(this); + ATLASSERT(pT->IsWindow()); + TCHAR sTitle[48]; + + // Preparation + CPaintDC dc(pT->m_hWnd); + CFont fontTitle = AtlCreateBoldFont(); + CFontHandle fontOld = dc.SelectFont(fontTitle); + dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHT)); + int nLen = pT->GetWindowText(sTitle, 48); + int nWidth = dc.GetDeviceCaps(HORZRES); + + // Display title text + RECT rTitle = { 0, 0, nWidth, nTitleHeight }; + dc.FillRect(&rTitle, COLOR_3DHIGHLIGHT); + #ifdef _WTL_CE_DRA + rTitle.left = DRA::SCALEX(8); + #else // !_WTL_CE_DRA + rTitle.left = nTitleHeight / 3; // 8 == 24 / 3 + #endif // !_WTL_CE_DRA + dc.DrawText(sTitle, nLen, &rTitle, DT_VCENTER | DT_SINGLELINE); + dc.SelectFont(fontOld); + + // Draw bottom line, 2 pixels thick if HI_RES_AWARE + CPenHandle penOld = dc.SelectStockPen(BLACK_PEN); + POINT line[4] = {{0, nTitleHeight}, {nWidth, nTitleHeight}, {0, nTitleHeight - 1}, {nWidth, nTitleHeight - 1}}; + + #ifdef _WTL_CE_DRA + int nSeg = DRA::SCALEY(1); + #else // !_WTL_CE_DRA + int nSeg = nTitleHeight / 24; + #endif // !_WTL_CE_DRA + + dc.Polyline(line, nSeg <= 2 ? nSeg * 2 : 4); + dc.SelectPen(penOld); + + return false; + } + + // Title preparation: move the dialog controls down to make room for title + void DialogTitleInit() + { + T* pT = static_cast(this); + ATLASSERT(pT->IsWindow()); + + ATL::CWindow wCtl = pT->GetWindow(GW_CHILD); + while (wCtl.IsWindow()) + { + RECT rCtl = { 0 }; + wCtl.GetWindowRect(&rCtl); + ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rCtl, 2); + ::OffsetRect(&rCtl, 0, nTitleHeight); + wCtl.MoveWindow(&rCtl, FALSE); + wCtl = wCtl.GetWindow(GW_HWNDNEXT); + } + } + + // SIP management + void DoSipInfo() + { + T* pT = static_cast(this); + ATLASSERT(pT->IsWindow()); + + SIPINFO si = {sizeof(SIPINFO)}; + SipGetInfo(&si); + if ((si.fdwFlags & SIPF_ON) ^ SIPF_ON) + si.rcVisibleDesktop.bottom = si.rcSipRect.bottom; + pT->MoveWindow(&si.rcVisibleDesktop, FALSE); + } + +// Title painting handler + LRESULT OnPaintTitle(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + T* pT = static_cast(this); + return bHandled = nTitleHeight ? pT->DoPaintTitle() : FALSE; + } + +// SIP handler + LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + T* pT = static_cast(this); + if (wParam == SPI_SETSIPINFO) + { + pT->DoSipInfo(); + return TRUE; + } + return bHandled = FALSE; + } + +#elif defined WIN32_PLATFORM_WFSP +// SmartPhone VK_TBACK key standard management + LRESULT OnHotKey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + const UINT uModif = (UINT)LOWORD(lParam); + const UINT uVirtKey = (UINT)HIWORD(lParam); + + if(uVirtKey == VK_TBACK) + if (AtlIsEditFocus()) + ::SHSendBackToFocusWindow(uMsg, wParam, lParam); + else if (uModif & MOD_KEYUP) + pT->StdCloseDialog(IDCANCEL); + return 1; + } + + // SmartPhone MenuBar and VK_TBACK key initialization + void StdSPInit() + { + T* pT = static_cast(this); + HWND hMenuBar = ::SHFindMenuBar(pT->m_hWnd); + + if (!hMenuBar && (t_shidiFlags & SHIDIF_DONEBUTTON)) + hMenuBar = CreateMenuBar(ATL_IDM_MENU_DONE); + + if(hMenuBar != NULL) + AtlActivateBackKey(hMenuBar); + } + + void SetStaticBold() + { + T* pT = static_cast(this); + ATLASSERT(pT->IsWindow()); + + CFontHandle fontBold = AtlCreateBoldFont(pT->GetFont()); + + ATL::CWindow wCtl = pT->GetWindow(GW_CHILD); + + while (wCtl.IsWindow()) + { + if ((short int)wCtl.GetDlgCtrlID() == IDC_STATIC) + wCtl.SetFont(fontBold); + wCtl = wCtl.GetWindow(GW_HWNDNEXT); + } + } +#endif // WIN32_PLATFORM_WFSP + +// Platform dependant initialization + void StdPlatformInit() + { + T* pT = static_cast(this); +#ifdef WIN32_PLATFORM_PSPC // Pocket PC title initialization + if (nTitleHeight != 0) + pT->DialogTitleInit(); +#elif defined(WIN32_PLATFORM_WFSP) + pT->StdSPInit(); + SetStaticBold(); +#endif // WIN32_PLATFORM_WFSP + } + + // Menu bar creation + HWND CreateMenuBar(UINT uiMB = T::IDD, int nBmpImages = 0) + { + T* pT = static_cast(this); + return AtlCreateMenuBar(pT->m_hWnd, uiMB, 0, nBmpImages ? uiMB : 0, nBmpImages); + } + + // Dialog closing + void StdCloseDialog(WORD wID) + { + T* pT = static_cast(this); + if (t_bModal) + ::EndDialog(pT->m_hWnd, wID); + else + pT->DestroyWindow(); + } + + // Shell dialog layout initialization + void StdShidInit() + { + T* pT = static_cast(this); + SHINITDLGINFO shidi = { SHIDIM_FLAGS, pT->m_hWnd, t_shidiFlags }; + ::SHInitDialog(&shidi); + } + +// IDC_INFOSTATIC background setting + LRESULT OnColorStatic(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + if (::GetDlgCtrlID((HWND)lParam) == IDC_INFOSTATIC) + { + ::SetBkMode((HDC)wParam, TRANSPARENT); + return (LRESULT)::GetSysColorBrush(COLOR_INFOBK); + } + return bHandled = FALSE; + } + +// Menu dialog ending + LRESULT OnMenuClose(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->StdCloseDialog((WORD)(wID - ID_MENU_OK + IDOK)); + return 0; + } + +// Standard dialog ending: may be used with any command + LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->StdCloseDialog(wID); + return 0; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CStdDialogImplBase - Base implementation of standard PPC/SmartPhone dialog + +template > +class ATL_NO_VTABLE CStdDialogImplBase : + public TBase, + public CStdDialogBase +{ +public: +#ifdef WIN32_PLATFORM_PSPC + BOOL GetClientRect(LPRECT lpRect) + { + return CStdDialogBase::GetClientRect(lpRect); + } + + BOOL SetWindowText(LPCTSTR lpszString) + { + return CStdDialogBase::SetWindowText(lpszString); + } +#endif + + BEGIN_MSG_MAP(CStdDialogImplBase) +#ifdef WIN32_PLATFORM_PSPC // Pocket PC title and SIP + MESSAGE_HANDLER(WM_PAINT, OnPaintTitle) + MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) +#elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key + MESSAGE_HANDLER(WM_HOTKEY, OnHotKey) +#endif + MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic) + MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) + COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd) + COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose) + END_MSG_MAP() + + LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { +#ifdef _DEBUG + T* pT = static_cast(this); + ATLASSERT(t_bModal == pT->m_bModal); +#endif + StdPlatformInit(); + StdShidInit(); + return bHandled = FALSE; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// CStdDialogImpl - implementation of standard PPC/SmartPhone dialog + +template +class ATL_NO_VTABLE CStdDialogImpl : public CStdDialogImplBase< T, t_shidiFlags, t_bModal> +{}; + +/////////////////////////////////////////////////////////////////////////////// +// CStdIndirectDialogImpl - implementation of standard indirect PPC/SmartPhone dialog + +#if defined __ATLDLGS_H__ + +template +class ATL_NO_VTABLE CStdIndirectDialogImpl : + public CIndirectDialogImpl< T, CMemDlgTemplate, CStdDialogImpl > +{ +public: + typedef CIndirectDialogImpl< T, CMemDlgTemplate, CStdDialogImpl > _baseClass; + typedef CStdDialogImpl _baseStd; + + INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL) + { + ATLASSERT(t_bModal); + + if (!m_Template.IsValid()) + CreateTemplate(); + + if (m_Template.IsTemplateEx()) + { + if (m_Template.GetTemplateExPtr()->style & DS_CENTER) + { + ATLASSERT(m_Template.GetTemplateExPtr()->style ^ WS_CHILD); + GetTemplateExPtr()->style |= WS_POPUP; + } + } + else + { + if (m_Template.GetTemplatePtr()->style & DS_CENTER) + { + ATLASSERT(m_Template.GetTemplatePtr()->style ^ WS_CHILD); + m_Template.GetTemplatePtr()->style |= WS_POPUP; + } + } + + return _baseClass::DoModal(hWndParent, dwInitParam); + } + + HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL) + { + ATLASSERT(!t_bModal); + + if (!m_Template.IsValid()) + CreateTemplate(); + + if (m_Template.IsTemplateEx()) + { + if (GetTemplateExPtr()->style & DS_CENTER) + { + ATLASSERT(GetTemplateExPtr()->style ^ WS_CHILD); + GetTemplateExPtr()->style |= WS_POPUP; + } + } + else + { + if (GetTemplatePtr()->style & DS_CENTER) + { + ATLASSERT(GetTemplatePtr()->style ^ WS_CHILD); + GetTemplatePtr()->style |= WS_POPUP; + } + } + + return _baseClass::Create(hWndParent, dwInitParam); + } + + BEGIN_MSG_MAP(CStdIndirectDialogImpl) + CHAIN_MSG_MAP(_baseStd) + END_MSG_MAP() + +}; + +#endif // defined __ATLDLGS_H__ + +#ifndef _ATL_NO_HOSTING + +/////////////////////////////////////////////////////////////////////////////// +// CStdAxDialogImpl - implementation of standard PPC/SmartPhone AxDialog + +template +class ATL_NO_VTABLE CStdAxDialogImpl : public CStdDialogImplBase< T, t_shidiFlags, t_bModal, ATL::CAxDialogImpl< T > > +{}; +#endif // _ATL_NO_HOSTING + +/////////////////////////////////////////////////////////////////////////////// +// CStdSimpleDialog - standard PPC/SmartPhone simple dialog with SHIDIF_xxx flags + +template +class CStdSimpleDialog : + public ATL::CSimpleDialog, + public CStdDialogBase, t_shidiFlags> +{ +public: + typedef CStdDialogBase, t_shidiFlags> baseClass; + +#ifdef WIN32_PLATFORM_PSPC + BOOL GetClientRect(LPRECT lpRect) + { + return baseClass::GetClientRect(lpRect); + } + + BOOL SetWindowText(LPCTSTR lpszString) + { + return baseClass::SetWindowText(lpszString); + } +#endif + + BEGIN_MSG_MAP(CStdSimpleDialog) +#ifdef WIN32_PLATFORM_PSPC // Pocket PC title and SIP + MESSAGE_HANDLER(WM_PAINT, OnPaintTitle) + MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) +#elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key + MESSAGE_HANDLER(WM_HOTKEY, OnHotKey) +#endif + MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic) + MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) + COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose) + COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, baseClass::OnCloseCmd) + END_MSG_MAP() + + LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + StdPlatformInit(); + StdShidInit(); + return bHandled = FALSE; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// CStdDialogResizeImplBase - Base implementation of orientation resizing standard PPC/SmartPhone dialog + +template > +class ATL_NO_VTABLE CStdDialogResizeImplBase : + public CStdDialogImplBase< T, t_shidiFlags, t_bModal, TBase>, + public CDialogResize +{ +public: + // Note: BEGIN_DLGRESIZE_MAP is required in the derived class. + + BEGIN_MSG_MAP(CStdResizeDialogImplBase) +#ifdef WIN32_PLATFORM_PSPC // Pocket PC title + MESSAGE_HANDLER(WM_PAINT, OnPaintTitle) +#elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key + MESSAGE_HANDLER(WM_HOTKEY, OnHotKey) +#endif + MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic) + MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) + COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd) + COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose) + CHAIN_MSG_MAP(CDialogResize< T >) + END_MSG_MAP() + + LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { +#ifdef _DEBUG + T* pT = static_cast(this); + ATLASSERT(t_bModal == pT->m_bModal); +#endif + StdPlatformInit(); + DlgResize_Init(FALSE); + StdShidInit(); + return bHandled = FALSE; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// CStdDialogResizeImpl - implementation of orientation resizing standard PPC/SmartPhone dialog + +template +class ATL_NO_VTABLE CStdDialogResizeImpl : public CStdDialogResizeImplBase< T, t_shidiFlags, t_bModal> +{}; + +#ifndef _ATL_NO_HOSTING + +/////////////////////////////////////////////////////////////////////////////// +// CStdAxDialogResizeImpl - implementation of orientation resizing standard PPC/SmartPhone AxDialog + +template +class ATL_NO_VTABLE CStdAxDialogResizeImpl : public CStdDialogResizeImplBase< T, t_shidiFlags, t_bModal, ATL::CAxDialogImpl > +{}; +#endif // _ATL_NO_HOSTING + +/////////////////////////////////////////////////////////////////////////////// +// CStdSimpleDialogResizeImpl - implementation of standard resizing simple dialog with SHIDIF_xxx flags + +// Usage: +// class CMyDlg : public CStdSimpleDialogResize +// { +// public: +// BEGIN_DLGRESIZE_MAP(CMyDlg) +// ... +// END_DLGRESIZE_MAP() +// }; + +template +class ATL_NO_VTABLE CStdSimpleDialogResizeImpl : + public CStdSimpleDialog, + public CDialogResize< T > +{ +public: + typedef CStdSimpleDialog::baseClass baseClass; + + BEGIN_MSG_MAP(CStdSimpleDialogResizeImpl) +#ifdef WIN32_PLATFORM_PSPC // Pocket PC title + MESSAGE_HANDLER(WM_PAINT, OnPaintTitle) +#elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key + MESSAGE_HANDLER(WM_HOTKEY, OnHotKey) +#endif + MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic) + MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) + COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, baseClass::OnCloseCmd) + COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose) + CHAIN_MSG_MAP(CDialogResize< T >) + END_MSG_MAP() + + LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + StdPlatformInit(); + DlgResize_Init(FALSE); + StdShidInit(); + return bHandled = FALSE; + } +}; + +#if defined(_WTL_CE_DRA) && defined(WIN32_PLATFORM_PSPC) + +/////////////////////////////////////////////////////////////////////////////// +// CStdOrientedDialogBase - Oriented PPC standard dialog base class + +template +class CStdOrientedDialogBase +{ +public: +// Operation + BOOL SetOrientation(DRA::DisplayMode mode) + { + T* pT = static_cast(this); + ATLASSERT(pT->IsWindow()); + ATLASSERT(mode == DRA::GetDisplayMode()); + + // Derived dialog must enumerate TWO dialog templates with the same control ids and types ie: + // enum { IDD = IDD_MYDLG, IDD_LANDSCAPE = IDD_MYDLG_L }; + UINT iResource = (mode == DRA::Landscape)? T::IDD_LANDSCAPE : T::IDD; + + BOOL bRes = DRA::RelayoutDialog(ModuleHelper::GetResourceInstance(), pT->m_hWnd, MAKEINTRESOURCE(iResource)); + pT->OnOrientation(mode); + return bRes; + } + +// Override + void OnOrientation(DRA::DisplayMode /*mode*/) + {} + +// Message handlers + LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + T* pT = static_cast(this); + ATLASSERT(pT->IsWindow()); + if (wParam == SETTINGCHANGE_RESET) + { + SetOrientation(DRA::GetDisplayMode()); + pT->StdPlatformInit(); + pT->StdShidInit(); + } + else if (wParam == SPI_SETSIPINFO) + { + pT->DoSipInfo(); + return TRUE; + } + return bHandled = FALSE; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// CStdOrientedDialogImplBase - Oriented PPC standard dialog base implementation + +template > +class ATL_NO_VTABLE CStdOrientedDialogImplBase : + public CStdDialogImplBase< T, t_shidiFlags, t_bModal, TBase>, + public CStdOrientedDialogBase +{ +public: + BEGIN_MSG_MAP(CStdOrientedDialogImpl) + MESSAGE_HANDLER(WM_PAINT, OnPaintTitle) + MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic) + MESSAGE_HANDLER(WM_SETTINGCHANGE, CStdOrientedDialogBase::OnSettingChange) + MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) + COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd) + COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose) + END_MSG_MAP() + + LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + T* pT = static_cast(this); +#ifdef _DEBUG + ATLASSERT(t_bModal == pT->m_bModal); +#endif + if (DRA::GetDisplayMode() == DRA::Landscape) + SetOrientation(DRA::Landscape); + pT->StdPlatformInit(); + pT->StdShidInit(); + return bHandled = FALSE; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// CStdOrientedDialogImpl - Oriented PPC standard dialog implementation + +template +class ATL_NO_VTABLE CStdOrientedDialogImpl : public CStdOrientedDialogImplBase< T, t_shidiFlags, t_bModal> +{}; + +#ifndef _ATL_NO_HOSTING +/////////////////////////////////////////////////////////////////////////////// +// CStdAxOrientedDialogImpl - Oriented PPC standard AxDialog implementation + +template +class ATL_NO_VTABLE CStdAxOrientedDialogImpl : public CStdOrientedDialogImplBase< T, t_shidiFlags, t_bModal, ATL::CAxDialogImpl > +{}; +#endif // _ATL_NO_HOSTING + +/////////////////////////////////////////////////////////////////////////////// +// CStdSimpleOrientedDialog - Standard simple orientable dialog + +template +class CStdSimpleOrientedDialog : + public CStdSimpleDialog, + public CStdOrientedDialogBase > +{ +public: + typedef CStdSimpleDialog::baseClass baseClass; + typedef CStdOrientedDialogBase > baseOriented; + + enum {IDD = t_wDlgTemplateID, IDD_LANDSCAPE = t_wDlgLandscapeID}; + + BEGIN_MSG_MAP(CStdSimpleDialog) + MESSAGE_HANDLER(WM_PAINT, OnPaintTitle) + MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic) + MESSAGE_HANDLER(WM_SETTINGCHANGE, baseOriented::OnSettingChange) + MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) + COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, baseClass::OnCloseCmd) + COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose) + END_MSG_MAP() + + LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + if (DRA::GetDisplayMode() == DRA::Landscape) + SetOrientation(DRA::Landscape); + StdPlatformInit(); + StdShidInit(); + return bHandled = FALSE; + } +}; + +#endif // _WTL_CE_DRA + + +#endif // _WTL_CE_NO_DIALOGS + + +// --- PPC/SmartPhone application window and helpers --- + +#ifndef _WTL_CE_NO_APPWINDOW + +/////////////////////////////////////////////////////////////////////////////// +// CAppInfoBase - Helper for application state save/restore to registry + +class CAppInfoBase +{ +public: + ATL::CRegKey m_Key; + + CAppInfoBase(ATL::_U_STRINGorID sAppKey) + { + m_Key.Create(HKEY_CURRENT_USER, sAppKey.m_lpstr); + ATLASSERT(m_Key.m_hKey); + } + + template + LONG Save(V& val, ATL::_U_STRINGorID sName) + { + return ::RegSetValueEx(m_Key, sName.m_lpstr, 0, REG_BINARY, (LPBYTE)&val, sizeof(V)); + } + + template + LONG Save(int nb, V& val0, ATL::_U_STRINGorID sName) + { + return ::RegSetValueEx(m_Key, sName.m_lpstr, 0, REG_BINARY, (LPBYTE)&val0, nb * sizeof(V)); + } + + template + LONG Restore(V& val, ATL::_U_STRINGorID sName) + { + DWORD valtype; + DWORD bufSize = sizeof(V); + return ::RegQueryValueEx(m_Key, sName.m_lpstr, 0, &valtype, (LPBYTE)&val, &bufSize); + } + + template + LONG Restore(int nb, V& val0, ATL::_U_STRINGorID sName) + { + DWORD valtype; + DWORD bufSize = nb * sizeof(V); + return ::RegQueryValueEx(m_Key, sName.m_lpstr, 0, &valtype, (LPBYTE)&val0, &bufSize); + } + +#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) +#if (_ATL_VER < 0x0800) + LONG Save(_CSTRING_NS::CString& sval, ATL::_U_STRINGorID sName) + { + return m_Key.SetValue(sval, sName.m_lpstr); + } + + LONG Restore(_CSTRING_NS::CString& sval, ATL::_U_STRINGorID sName) + { + DWORD size = MAX_PATH; + LONG res = m_Key.QueryValue(sval.GetBuffer(size), sName.m_lpstr, &size); + sval.ReleaseBuffer(); + return res; + } +#else // !(_ATL_VER < 0x0800) + LONG Save(_CSTRING_NS::CString& sval, ATL::_U_STRINGorID sName) + { + return m_Key.SetStringValue(sName.m_lpstr, sval); + } + + LONG Restore(_CSTRING_NS::CString& sval, ATL::_U_STRINGorID sName) + { + DWORD size = MAX_PATH; + LONG res = m_Key.QueryStringValue(sName.m_lpstr, sval.GetBuffer(size), &size); + sval.ReleaseBuffer(); + return res; + } +#endif // !(_ATL_VER < 0x0800) +#else + #pragma message("Warning: CAppInfoBase compiles without CString support. Do not use CString in Save or Restore.") +#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) + +#if (_ATL_VER < 0x0800) + LONG Save(LPCTSTR sval, ATL::_U_STRINGorID sName) + { + return m_Key.SetValue(sval, sName.m_lpstr); + } + + LONG Restore(LPTSTR sval, ATL::_U_STRINGorID sName, DWORD *plength) + { + return m_Key.QueryValue(sval, sName.m_lpstr, plength); + } +#else // !(_ATL_VER < 0x0800) + LONG Save(LPCTSTR sval, ATL::_U_STRINGorID sName) + { + return m_Key.SetStringValue(sName.m_lpstr, sval); + } + + LONG Restore(LPTSTR sval, ATL::_U_STRINGorID sName, DWORD *plength) + { + return m_Key.QueryStringValue(sName.m_lpstr, sval, plength); + } +#endif // !(_ATL_VER < 0x0800) + + LONG Delete(ATL::_U_STRINGorID sName) + { + return m_Key.DeleteValue(sName.m_lpstr); + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CAppInfoT - CAppInfoBase constructed from a class with T::GetAppKey() + +// Macro for declaring AppKey +#define DECLARE_APPKEY(uAppKey) \ + static LPCTSTR GetAppKey() \ + { \ + static LPCTSTR sAppKey = ATL::_U_STRINGorID(uAppKey).m_lpstr; \ + return sAppKey; \ + } + +template +class CAppInfoT : public CAppInfoBase +{ +public: + CAppInfoT() : CAppInfoBase(T::GetAppKey()){} +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CAppWindowBase - Base class for PPC/SmartPhone "well-behaved" application window or dialog + +// Macros for declaring frame WNDCLASS and AppKey +#define DECLARE_APP_FRAME_CLASS(WndClassName, uCommonResourceID, uAppKey) \ + DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \ + DECLARE_APPKEY(uAppKey) + +#define DECLARE_APP_FRAME_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd, uAppKey) \ + DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \ + DECLARE_APPKEY(uAppKey) + +template +class CAppWindowBase +{ +public: + typedef class CAppInfoT< T > CAppInfo; + +#ifndef WIN32_PLATFORM_WFSP + SHACTIVATEINFO m_sai; // NoOp on SmartPhones +#endif // WIN32_PLATFORM_WFSP + + bool m_bHibernate; + + CAppWindowBase< T >() : m_bHibernate(false) + { +#ifndef WIN32_PLATFORM_WFSP + SHACTIVATEINFO sai = { sizeof(SHACTIVATEINFO) }; + m_sai = sai; +#endif // WIN32_PLATFORM_WFSP + }; + + // Same as WTL 7.1 AppWizard generated ActivatePreviousInstance + SendMessage WM_COPYDATA + static HRESULT ActivatePreviousInstance(HINSTANCE hInstance, LPCTSTR lpstrCmdLine, bool bDialog) + { + // requires T does DECLARE_APP_FRAME_CLASS, DECLARE_APP_FRAME_CLASS_EX or DECLARE_APP_DLG_CLASS + CFrameWndClassInfo& classInfo = T::GetWndClassInfo(); + + ATLVERIFY(::LoadString(hInstance, classInfo.m_uCommonResourceID, classInfo.m_szAutoName, sizeof(classInfo.m_szAutoName)/sizeof(classInfo.m_szAutoName[0])) != 0); + + classInfo.m_wc.lpszClassName = classInfo.m_szAutoName; + + const TCHAR* pszClass = classInfo.m_wc.lpszClassName; + + if(NULL == pszClass || '\0' == *pszClass) + { + return E_FAIL; + } + + const DWORD dRetryInterval = 100; + const int iMaxRetries = 25; + + for(int i = 0; i < iMaxRetries; ++i) + { + HANDLE hMutex = CreateMutex(NULL, FALSE, pszClass); + + DWORD dw = GetLastError(); + + if(NULL == hMutex) + { + HRESULT hr; + + switch(dw) + { + case ERROR_INVALID_HANDLE: + // A non-mutext object with this name already exists. + hr = E_INVALIDARG; + break; + default: + // This should never happen... + hr = E_FAIL; + } + + return hr; + } + + // If the mutex already exists, then there should be another instance running + if(dw == ERROR_ALREADY_EXISTS) + { + CloseHandle(hMutex); + + HWND hwnd = NULL; + if (bDialog) + hwnd = FindWindow(NULL, pszClass); + else + hwnd = FindWindow(pszClass, NULL); + + if(hwnd == NULL) + { + Sleep(dRetryInterval); + continue; + } + else + { + // Transmit our params to previous instance + if (lpstrCmdLine && *lpstrCmdLine) + { + COPYDATASTRUCT cd = { NULL, sizeof(TCHAR) * (wcslen(lpstrCmdLine) + 1), (PVOID)lpstrCmdLine }; + ::SendMessage(hwnd, WM_COPYDATA, NULL, (LPARAM)&cd); + } + // Set the previous instance as the foreground window + if(0 != SetForegroundWindow(reinterpret_cast(reinterpret_cast(hwnd) | 0x1))) + return S_FALSE; + } + } + else + { + return S_OK; + } + } + return S_OK; + } + +// Operations overriden in derived class + bool AppHibernate(bool /*bHibernate*/) + { + return false; + } + + bool AppNewInstance(LPCTSTR /*lpstrCmdLine*/) + { + return false; + } + + void AppSave() + { + } + +#ifdef WIN32_PLATFORM_WFSP + void AppBackKey() + { + ::SHNavigateBack(); + } +#endif + +// Message map and handlers + BEGIN_MSG_MAP(CAppWindowBase) + MESSAGE_HANDLER(WM_ACTIVATE, OnActivate) +#ifdef WIN32_PLATFORM_WFSP + MESSAGE_HANDLER(WM_HOTKEY, OnHotKey) +#else + MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) +#endif // WIN32_PLATFORM_WFSP + MESSAGE_HANDLER(WM_HIBERNATE, OnHibernate) + MESSAGE_HANDLER(WM_COPYDATA, OnNewInstance) + MESSAGE_HANDLER(WM_CLOSE, OnClose) + END_MSG_MAP() + + LRESULT OnActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + T* pT = static_cast(this); + if (m_bHibernate) + m_bHibernate = pT->AppHibernate(false); +#ifndef WIN32_PLATFORM_WFSP + ::SHHandleWMActivate(pT->m_hWnd, wParam, lParam, &m_sai, 0); +#else + wParam; + lParam; +#endif // WIN32_PLATFORM_WFSP + return bHandled = FALSE; + } + +#ifdef WIN32_PLATFORM_WFSP +// SmartPhone VK_TBACK key standard management + LRESULT OnHotKey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + const UINT uModif = (UINT)LOWORD(lParam); + const UINT uVirtKey = (UINT)HIWORD(lParam); + if(uVirtKey == VK_TBACK) + if (AtlIsEditFocus()) + ::SHSendBackToFocusWindow(uMsg, wParam, lParam); + else if (uModif & MOD_KEYUP) + pT->AppBackKey(); + return 1; + } + +#else // !WIN32_PLATFORM_WFSP +// PPC SIP handling + LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + T* pT = static_cast(this); + bHandled = FALSE; + return ::SHHandleWMSettingChange(pT->m_hWnd, wParam, lParam, &m_sai); + } +#endif // !WIN32_PLATFORM_WFSP + + LRESULT OnHibernate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + return m_bHibernate = pT->AppHibernate(true); + } + + LRESULT OnNewInstance(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + PCOPYDATASTRUCT pcds = (PCOPYDATASTRUCT)lParam; + return pT->AppNewInstance((LPCTSTR)pcds->lpData); + } + + LRESULT OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + T* pT = static_cast(this); + pT->AppSave(); + bHandled = FALSE; + return 1; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CAppWindow - PPC/SmartPhone "well-behaved" application window class + +template +class CAppWindow : public CAppWindowBase< T > +{ +public: + // Same as WTL 7.1 AppWizard generated Run + lpstrCmdLine in CreateEx + static int AppRun(LPTSTR lpstrCmdLine = NULL, int nCmdShow = SW_SHOWNORMAL) + { + CMessageLoop theLoop; + _Module.AddMessageLoop(&theLoop); + + T wndMain; + + if(wndMain.CreateEx(NULL, NULL, 0, 0, lpstrCmdLine) == NULL) + { + ATLTRACE2(atlTraceUI, 0, _T("Main window creation failed!\n")); + return 0; + } + + wndMain.ShowWindow(nCmdShow); + + int nRet = theLoop.Run(); + + _Module.RemoveMessageLoop(); + return nRet; + } + + static HRESULT ActivatePreviousInstance(HINSTANCE hInstance, LPCTSTR lpstrCmdLine) + { + return CAppWindowBase< T >::ActivatePreviousInstance(hInstance, lpstrCmdLine, false); + } +}; + + +#ifndef _WTL_CE_NO_DIALOGS + +/////////////////////////////////////////////////////////////////////////////// +// CAppDialog - PPC/SmartPhone "well-behaved" dialog application class + +// Macro for declaring dialog WNDCLASS and AppKey +#define DECLARE_APP_DLG_CLASS(WndClassName, uCommonResourceID, uAppKey) \ + static WTL::CFrameWndClassInfo& GetWndClassInfo() \ + { \ + static WTL::CFrameWndClassInfo wc = \ + { \ + { 0, (WNDPROC)StartDialogProc, \ + 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName }, \ + NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ + }; \ + return wc; \ + }; \ + DECLARE_APPKEY(uAppKey) + +template +class CAppDialog : public CAppWindowBase< T > +{ +public: + static int AppRun(LPTSTR lpstrCmdLine = NULL, int nCmdShow = SW_SHOWNORMAL) + { + CMessageLoop theLoop; + _Module.AddMessageLoop(&theLoop); + + T dlgMain; + + if(dlgMain.Create(NULL, (LPARAM)lpstrCmdLine) == NULL) + { + ATLTRACE2(atlTraceUI, 0, _T("Main dialog creation failed!\n")); + return 0; + } + + dlgMain.ShowWindow(nCmdShow); + + int nRet = theLoop.Run(); + + _Module.RemoveMessageLoop(); + return nRet; + } + + static HRESULT ActivatePreviousInstance(HINSTANCE hInstance, LPCTSTR lpstrCmdLine) + { + return CAppWindowBase< T >::ActivatePreviousInstance(hInstance, lpstrCmdLine, true); + }; +}; + +// PPC/SmartPhone standard application dialogs + +#ifdef WIN32_PLATFORM_WFSP +#define WTL_APP_SHIDIF WTL_SP_SHIDIF +#else +#define WTL_APP_SHIDIF WTL_STD_SHIDIF +#endif + +/////////////////////////////////////////////////////////////////////////////// +// CAppStdDialogImplBase - Base implementation of standard application dialogs + +template +class ATL_NO_VTABLE CAppStdDialogImplBase : + public TImplBase, + public CAppDialog< T > +{ +public: + WTL_DLG_NOTITLE; + + void StdCloseDialog(int nVal) + { + T* pT = static_cast(this); + if (nVal != IDCANCEL) + pT->AppSave(); + if (t_bModal == false) + { + pT->DestroyWindow(); + ::PostQuitMessage(nVal); + } + else + ::EndDialog(pT->m_hWnd, nVal); + } + + BEGIN_MSG_MAP(CAppStdDialogImplBase) + MESSAGE_HANDLER(WM_CLOSE, OnSystemClose) + CHAIN_MSG_MAP(TImplBase) + CHAIN_MSG_MAP(CAppDialog< T >) + END_MSG_MAP() + + LRESULT OnSystemClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->StdCloseDialog(IDCANCEL); + return 0; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// CAppStdDialogImpl - Implementation of standard application dialog + +template +class ATL_NO_VTABLE CAppStdDialogImpl : + public CAppStdDialogImplBase, t_shidiFlags, t_bModal> +{}; + +/////////////////////////////////////////////////////////////////////////////// +// CAppStdDialogResizeImpl - implementation of orientation resizing standard application dialog + +template +class ATL_NO_VTABLE CAppStdDialogResizeImpl : + public CAppStdDialogImplBase, t_shidiFlags, t_bModal> +{}; + +#ifndef _ATL_NO_HOSTING +/////////////////////////////////////////////////////////////////////////////// +// CAppStdAxDialogImpl - Implementation of standard application AxDialog + +template +class ATL_NO_VTABLE CAppStdAxDialogImpl : + public CAppStdDialogImplBase, t_shidiFlags, t_bModal> +{}; + +/////////////////////////////////////////////////////////////////////////////// +// CAppStdAxDialogResizeImpl - implementation of orientation resizing standard application AxDialog + +template +class ATL_NO_VTABLE CAppStdAxDialogResizeImpl : + public CAppStdDialogImplBase, t_shidiFlags, t_bModal> +{}; +#endif // _ATL_NO_HOSTING + +#if defined(_WTL_CE_DRA) && defined(WIN32_PLATFORM_PSPC) +/////////////////////////////////////////////////////////////////////////////// +// CAppStdOrientedDialogImpl - implementation of oriented PPC standard application dialog + +template +class ATL_NO_VTABLE CAppStdOrientedDialogImpl : + public CAppStdDialogImplBase, t_shidiFlags, t_bModal> +{}; + +#ifndef _ATL_NO_HOSTING +/////////////////////////////////////////////////////////////////////////////// +// CAppStdAxOrientedDialogImpl - implementation of oriented PPC standard application AxDialog + +template +class ATL_NO_VTABLE CAppStdAxOrientedDialogImpl : + public CAppStdDialogImplBase, t_shidiFlags, t_bModal> +{}; +#endif // _ATL_NO_HOSTING + +#endif // defined(_WTL_CE_DRA) && defined(WIN32_PLATFORM_PSPC) + +#endif // _WTL_CE_NO_DIALOGS + +#endif // _WTL_CE_NO_APPWINDOW + + +// --- Full screen support --- + +#ifndef _WTL_CE_NO_FULLSCREEN + +/////////////////////////////////////////////////////////////////////////////// +// CFullScreenFrame - full screen frame implementation + +template +class CFullScreenFrame +{ +public: + bool m_bFullScreen; + + CFullScreenFrame() : m_bFullScreen(false) + { } + +// Operation + void SetFullScreen(bool bFull) + { + m_bFullScreen = bFull; + ShowTaskBar(!bFull, false); + ShowMenuBar(!bFull); + } + +// Manage TaskBar for modal dialogs and property sheets + template + int FSDoModal(D& dlg) + { + T* pT = static_cast(this); + pT; // avoid level 4 warning + ATLASSERT(pT->IsWindow()); + if (m_bFullScreen) // Show taskbar if hidden + ShowTaskBar(true, false); + int iRet = dlg.DoModal(); + if (m_bFullScreen) // Hide taskbar if restored + ShowTaskBar(false); + return iRet; + } + +// Implementation + void ShowMenuBar(bool bShow) + { + T* pT = static_cast(this); + ATLASSERT(pT->IsWindow()); + ATL::CWindow MenuBar = pT->m_hWndCECommandBar; + ATLASSERT(MenuBar.IsWindow()); + MenuBar.ShowWindow(bShow ? SW_SHOWNORMAL : SW_HIDE); + pT->SizeToMenuBar(); + } + + void ShowTaskBar(bool bShow, bool bRepaint = true) + { + T* pT = static_cast(this); + ATLASSERT(pT->IsWindow()); + RECT rect = { 0 }; + SystemParametersInfo(SPI_GETWORKAREA, NULL, &rect, FALSE); + if (!bShow) + rect.top = 0; + +#ifdef WIN32_PLATFORM_PSPC // Pocket PC code + UINT uShow = t_bHasSip ? SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON : SHFS_SHOWTASKBAR | SHFS_HIDESIPBUTTON; + SHFullScreen(pT->m_hWnd, bShow ? uShow : SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON); +#elif _WIN32_WCE > 0x500 // Smartphone 2005 code + SHFullScreen(pT->m_hWnd, bShow ? SHFS_SHOWTASKBAR : SHFS_HIDETASKBAR); +#else // Smartphone 2003 + HWND hTaskBar = FindWindow(_T("tray"), NULL); + ATLASSERT(::IsWindow(hTaskBar)); + ::ShowWindow(hTaskBar, bShow ? SW_SHOW : SW_HIDE); +#endif // WIN32_PLATFORM_PSPC + + pT->MoveWindow(&rect, bRepaint); + } + +// Message map and handler + BEGIN_MSG_MAP(CFullScreenFrame) + MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) + MESSAGE_HANDLER(WM_ACTIVATE, OnActivate) + END_MSG_MAP() + + LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { +#ifndef SETTINGCHANGE_RESET // not defined for PPC 2002 + #define SETTINGCHANGE_RESET SPI_SETWORKAREA +#endif + if (m_bFullScreen && (wParam & SETTINGCHANGE_RESET)) + SetFullScreen(m_bFullScreen); + return bHandled = FALSE; + } + + LRESULT OnActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + if (m_bFullScreen) + { + ShowTaskBar(!wParam); + ShowMenuBar(!wParam); + } + return bHandled = FALSE; + } +}; + +#endif // _WTL_CE_NO_FULLSCREEN + + +// --- WinCE zoom support --- + +#ifndef _WTL_CE_NO_ZOOMSCROLL + +/////////////////////////////////////////////////////////////////////////////// +// CZoomScrollImpl - WinCE zooming implementation on top of CScrollImpl + +template +class CZoomScrollImpl: public CScrollImpl< T > +{ +public: +// Data members + _WTYPES_NS::CSize m_sizeTrue; + double m_fzoom; + +// Creation + CZoomScrollImpl() : m_sizeTrue(0), m_fzoom(1.) + { } + +// Zoom operations and access + void SetZoomScrollSize(_WTYPES_NS::CSize sizeTrue, double fzoom = 1., BOOL bRedraw = TRUE) + { + ATLASSERT(fzoom > 0.); + m_sizeTrue = sizeTrue; + m_fzoom = fzoom; + + CScrollImpl< T >::SetScrollSize(sizeTrue / fzoom, bRedraw); + } + + void SetZoomScrollSize(int cx, int cy, double fzoom=1., BOOL bRedraw = TRUE) + { + SetZoomScrollSize(_WTYPES_NS::CSize(cx, cy), fzoom, bRedraw); + } + + void SetZoom(double fzoom, BOOL bRedraw = TRUE) + { + _WTYPES_NS::CPoint ptCenter = WndtoTrue(m_sizeClient / 2); + _WTYPES_NS::CSize sizePage = GetScrollPage(); + _WTYPES_NS::CSize sizeLine = GetScrollLine(); + + SetZoomScrollSize(GetScrollSize(), fzoom, bRedraw); + + SetScrollLine(sizeLine); + SetScrollPage(sizePage); + _WTYPES_NS::CPoint ptOffset = ptCenter - (m_sizeClient / 2) * fzoom; + SetScrollOffset(ptOffset, bRedraw); + } + + double GetZoom() + { + return m_fzoom; + } + +// CScrollImpl overrides + void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE) + { + CScrollImpl< T >::SetScrollOffset((int)(x / m_fzoom), (int)(y / m_fzoom), bRedraw); + } + + void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE) + { + SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw); + } + + void GetScrollOffset(POINT& ptOffset) + { + ptOffset.x = (LONG)(m_ptOffset.x * m_fzoom); + ptOffset.y = (LONG)(m_ptOffset.y * m_fzoom); + } + + void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE) + { + SetZoomScrollSize(cx, cy, GetZoom(), bRedraw); + } + + void SetScrollSize(SIZE sizeTrue, BOOL bRedraw = TRUE) + { + SetZoomScrollSize(sizeTrue, GetZoom(), bRedraw); + } + + void GetScrollSize(SIZE& sizeTrue) const + { + sizeTrue = m_sizeTrue; + } + + void SetScrollPage(int cxPage, int cyPage) + { + SetScrollPage(_WTYPES_NS::CSize(cxPage, cyPage)); + } + + void SetScrollPage(SIZE sizePage) + { + CScrollImpl< T >::SetScrollPage(sizePage / m_fzoom); + } + + void GetScrollPage(SIZE& sizePage) const + { + sizePage = m_sizePage * m_fzoom; + } + + void SetScrollLine(int cxLine, int cyLine) + { + SetScrollLine(_WTYPES_NS::CSize(cxLine, cyLine)); + } + + void SetScrollLine(SIZE sizeLine) + { + CScrollImpl< T >::SetScrollLine(sizeLine / m_fzoom); + } + + void GetScrollLine(SIZE& sizeLine) const + { + sizeLine = m_sizeLine * m_fzoom; + } + +// Data access complements + _WTYPES_NS::CSize GetScrollSize() + { + return m_sizeTrue; + } + + _WTYPES_NS::CSize GetScrollPage() + { + return m_sizePage * m_fzoom; + } + + _WTYPES_NS::CSize GetScrollLine() + { + return m_sizeLine * m_fzoom; + } + + _WTYPES_NS::CPoint GetScrollOffset() + { + return (_WTYPES_NS::CSize)m_ptOffset * m_fzoom; + } + +// Helper coordinate functions + _WTYPES_NS::CPoint WndtoTrue(CPoint ptW) + { + return (_WTYPES_NS::CSize)ptW * GetZoom() + GetScrollOffset(); + } + + void WndtoTrue(LPPOINT aptW, int nPts) // in place coord transformation + { + for (int i = 0 ; i < nPts ; i++) + aptW[i] = WndtoTrue(aptW[i]); + } + + void WndtoTrue(LPRECT prectW) // in place coord transformation + { + WndtoTrue((LPPOINT)prectW, 2); + } + + _WTYPES_NS::CPoint TruetoWnd(CPoint ptT) + { + return (ptT - GetScrollOffset()) / GetZoom(); + } + + void TruetoWnd(LPPOINT aptT, int nPts) // in place coord transformation + { + for (int i = 0 ; i < nPts ; i++) + aptT[i] = TruetoWnd(aptT[i]); + } + + void TruetoWnd(LPRECT prectT) // in place coord transformation + { + TruetoWnd((LPPOINT)prectT, 2); + } + +// Drawing operations : assume adequate setting of data members + BOOL Draw(HBITMAP hbm, HDC hdestDC, DWORD dwROP = SRCCOPY) + { + CDC memDC = CreateCompatibleDC(hdestDC); + CBitmapHandle bmpOld = memDC.SelectBitmap(hbm); + BOOL bRes = Draw(memDC, hdestDC, dwROP); + memDC.SelectBitmap(bmpOld); + return bRes; + } + + BOOL Draw(HDC hsourceDC, HDC hdestDC, DWORD dwROP = SRCCOPY) + { + CDCHandle destDC = hdestDC; + destDC.SetViewportOrg(0,0); + _WTYPES_NS::CPoint ptOffset = GetScrollOffset(); + _WTYPES_NS::CSize sizeZClient = m_sizeClient * GetZoom(); + return destDC.StretchBlt(0, 0, m_sizeClient.cx, m_sizeClient.cy, hsourceDC, ptOffset.x, ptOffset.y, sizeZClient.cx, sizeZClient.cy, dwROP); + } + +#ifdef _IMAGING_H + BOOL Draw(IImage* pIImage, HDC hdestDC) + { + CDCHandle destDC = hdestDC; + destDC.SetViewportOrg(0,0); + return SUCCEEDED(pIImage->Draw(destDC, _WTYPES_NS::CRect(-_WTYPES_NS::CPoint(m_ptOffset), m_sizeAll), NULL)); + } +#endif + +// Message map and handlers + BEGIN_MSG_MAP(CZoomScrollImpl< T >) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd) + CHAIN_MSG_MAP(CScrollImpl< T >) + END_MSG_MAP() + + LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + T* pT = static_cast(this); + ATLASSERT(::IsWindow(pT->m_hWnd)); + if ((GetScrollExtendedStyle() & SCRL_ERASEBACKGROUND)) + { + _WTYPES_NS::CRect rect; + pT->GetClientRect(rect); + _WTYPES_NS::CSize sizeClient=rect.Size(); + + if (m_sizeAll.cx < sizeClient.cx || m_sizeAll.cy < sizeClient.cy) + { + CDCHandle hdc = (HDC)wParam; + HBRUSH hbr = GetSysColorBrush((int)T::GetWndClassInfo().m_wc.hbrBackground - 1); + + if (m_sizeAll.cx < sizeClient.cx) + { + _WTYPES_NS::CRect rectBG(_WTYPES_NS::CPoint(m_sizeAll.cx, 0), sizeClient); + hdc.FillRect(rectBG, hbr); + } + + if (m_sizeAll.cy < sizeClient.cy) + { + _WTYPES_NS::CRect rectBG(_WTYPES_NS::CPoint(0, m_sizeAll.cy), sizeClient); + hdc.FillRect(rectBG, hbr); + } + } + } + else + { + bHandled = FALSE; + } + + return 1; + } +}; + +#endif // _WTL_CE_NO_ZOOMSCROLL + +#ifndef _WTL_CE_NO_CONTROLS + +// --- PPC bottom TabView control --- + +#if defined(__ATLCTRLX_H__) && defined(WIN32_PLATFORM_PSPC) + +/////////////////////////////////////////////////////////////////////////////// +// CBottomTabViewImpl + +template +class ATL_NO_VTABLE CBottomTabViewImpl : public CTabViewImpl +{ +public: + DECLARE_WND_CLASS_EX(NULL, 0, COLOR_APPWORKSPACE) + +// Implementation overrideables + bool CreateTabControl() + { + m_tab.Create(m_hWnd, rcDefault, NULL, WS_CHILD | TCS_BOTTOM, 0, m_nTabID); + + ATLASSERT(m_tab.m_hWnd != NULL); + if(m_tab.m_hWnd == NULL) + return false; + + m_tab.SendMessage(CCM_SETVERSION, COMCTL32_VERSION); + m_tab.SetItemExtra(sizeof(TABVIEWPAGE)); + + T* pT = static_cast(this); + m_cyTabHeight = pT->CalcTabHeight(); + + return true; + } + + int CalcTabHeight() + { + int nCount = m_tab.GetItemCount(); + TCITEMEXTRA tcix = { 0 }; + tcix.tciheader.mask = TCIF_TEXT; + tcix.tciheader.pszText = _T("NS"); + int nIndex = m_tab.InsertItem(nCount, tcix); + + RECT rect = { 0 }; + SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0); + RECT rcWnd = rect; + + m_tab.AdjustRect(FALSE, &rect); + rcWnd.top = rect.bottom; + ::AdjustWindowRectEx(&rcWnd, m_tab.GetStyle(), FALSE, m_tab.GetExStyle()); + m_tab.DeleteItem(nIndex); + + return rcWnd.bottom - rcWnd.top; + } + + void UpdateLayout() + { + RECT rect; + GetClientRect(&rect); + + if(m_tab.IsWindow() && ((m_tab.GetStyle() & WS_VISIBLE) != 0)) + m_tab.SetWindowPos(NULL, 0, rect.bottom - m_cyTabHeight, rect.right - rect.left, m_cyTabHeight, SWP_NOZORDER /*| SWP_SHOWWINDOW*/); + + if(m_nActivePage != -1) + ::SetWindowPos(GetPageHWND(m_nActivePage), NULL, 0, 0, rect.right - rect.left, rect.bottom - m_cyTabHeight, SWP_NOZORDER); + } + +}; + +class CBottomTabView : public CBottomTabViewImpl +{ +public: + DECLARE_WND_CLASS_EX(_T("WTL_BottomTabView"), 0, COLOR_APPWORKSPACE) +}; + +#endif // defined(__ATLCTRLX_H__) && defined(WIN32_PLATFORM_PSPC) + + +// --- PPC/SmartPhone controls --- + +//////////////////////////////////////////////////////////////////////////////// +// These are wrapper classes for the Pocket PC 2002/2003 and SmartPhone 2003 controls +// To implement a window based on a control, use following: +// Example: Implementing a window based on a Html control +// +// class CMyHtml : CWindowImpl +// { +// public: +// BEGIN_MSG_MAP(CMyHtml) +// // put your message handler entries here +// END_MSG_MAP() +// }; +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// CHtmlCtrl + +template +class CHtmlCtrlT : public TBase +{ +public: +// Constructors + CHtmlCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CHtmlCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + ATLASSERT(hWnd != NULL); // Did you remember to call InitHTMLControl(hInstance) ?? + return hWnd; + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return WC_HTML; + } + +#if (_WIN32_WCE >= 400) + void AddStyle(LPCWSTR pszStyle) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_ADDSTYLE, 0, (LPARAM)pszStyle); + } +#endif // (_WIN32_WCE >= 400) + + void AddText(BOOL bPlainText, LPCSTR pszText) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_ADDTEXT, (WPARAM)bPlainText, (LPARAM)pszText); + } + + void AddHTML(LPCSTR pszHTML) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_ADDTEXT, (WPARAM)FALSE, (LPARAM)pszHTML); + } + + void AddText(BOOL bPlainText, LPCWSTR pszText) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_ADDTEXTW, (WPARAM)bPlainText, (LPARAM)pszText); + } + + void AddHTML(LPCWSTR pszHTML) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_ADDTEXTW, (WPARAM)FALSE, (LPARAM)pszHTML); + } + + void Anchor(LPCSTR pszAnchor) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_ANCHOR, 0, (LPARAM)pszAnchor); + } + + void Anchor(LPCWSTR pszAnchor) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_ANCHORW, 0, (LPARAM)pszAnchor); + } + +#if (_WIN32_WCE >= 420) + void GetBrowserDispatch(IDispatch** ppDispatch) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(ppDispatch); + ATLASSERT(*ppDispatch==NULL); + ::SendMessage(m_hWnd, DTM_BROWSERDISPATCH, 0, (LPARAM)ppDispatch); + } + void GetDocumentDispatch(IDispatch** ppDispatch) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(ppDispatch); + ATLASSERT(*ppDispatch==NULL); + ::SendMessage(m_hWnd, DTM_DOCUMENTDISPATCH , 0, (LPARAM)ppDispatch); + } +#endif // (_WIN32_WCE >= 420) + + void Clear() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_CLEAR, 0, 0L); + } + + void EnableClearType(BOOL bEnable = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_ENABLECLEARTYPE, 0, (LPARAM)bEnable); + } + + void EnableContextMenu(BOOL bEnable = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_ENABLECONTEXTMENU, 0, (LPARAM)bEnable); + } + + void EnableScripting(BOOL bEnable = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_ENABLESCRIPTING, 0, (LPARAM)bEnable); + } + + void EnableShrink(BOOL bEnable = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_ENABLESHRINK, 0, (LPARAM)bEnable); + } + + void EndOfSource() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_ENDOFSOURCE, 0, 0L); + } + + void ImageFail(DWORD dwCookie) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_IMAGEFAIL, 0, (LPARAM)dwCookie); + } + + int GetLayoutHeight() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, DTM_LAYOUTHEIGHT, 0, 0L); + } + + int GetLayoutWidth() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, DTM_LAYOUTWIDTH, 0, 0L); + } + + void Navigate(LPCTSTR pstrURL, UINT uFlags = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pstrURL); + ::SendMessage(m_hWnd, DTM_NAVIGATE, (WPARAM)uFlags, (LPARAM)pstrURL); + } + + void SelectAll() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_SELECTALL, 0, 0L); + } + + void SetImage(INLINEIMAGEINFO* pImageInfo) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pImageInfo); + ::SendMessage(m_hWnd, DTM_SETIMAGE, 0, (LPARAM)pImageInfo); + } + + void ZoomLevel(int iLevel) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_ZOOMLEVEL, 0, (LPARAM)iLevel); + } + +#if (_WIN32_WCE >= 400) + void Stop() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DTM_STOP, 0, 0L); + } +#endif // (_WIN32_WCE >= 400) + + void GetScriptDispatch(IDispatch** ppDispatch) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(ppDispatch); + ATLASSERT(*ppDispatch==NULL); + ::SendMessage(m_hWnd, DTM_SCRIPTDISPATCH, 0, (LPARAM)ppDispatch); + } +}; + +typedef CHtmlCtrlT CHtmlCtrl; + + +#ifdef WIN32_PLATFORM_PSPC + +/////////////////////////////////////////////////////////////////////////////// +// CRichInkCtrl + +template +class CRichInkCtrlT : public TBase +{ +public: +// Constructors + CRichInkCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CRichInkCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + ATLASSERT(hWnd != NULL); // Did you remember to call InitRichInkDLL() ?? + return hWnd; + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return WC_RICHINK; + } + + BOOL CanPaste(UINT uFormat = 0) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_CANPASTE, (WPARAM)uFormat, 0L); + } + + BOOL CanRedo() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_CANREDO, 0, 0L); + } + + BOOL CanUndo() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_CANUNDO, 0, 0L); + } + + void ClearAll(BOOL bRepaint = TRUE) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_CLEARALL, (WPARAM)bRepaint, 0L); + } + + BOOL GetModify() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, EM_GETMODIFY, 0, 0L); + } + + UINT GetPageStyle() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, EM_GETPAGESTYLE, 0, 0L); + } + + UINT GetPenMode() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, EM_GETPENMODE, 0, 0L); + } + + UINT GetViewStyle() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, EM_GETVIEW, 0, 0L); + } + + UINT GetWrapMode() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, EM_GETWRAPMODE, 0, 0L); + } + + UINT GetZoomPercent() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, EM_GETZOOMPERCENT, 0, 0L); + } + + void InsertLinks(LPWSTR lpString, int cchLength = -1) + { + ATLASSERT(::IsWindow(m_hWnd)); + if(cchLength == -1) + cchLength = lstrlen(lpString); + ::SendMessage(m_hWnd, EM_INSERTLINKS, (WPARAM)cchLength, (LPARAM)lpString); + } + + void RedoEvent() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_REDOEVENT, 0, 0L); + } + + UINT SetInkLayer(UINT uLayer) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (UINT)::SendMessage(m_hWnd, EM_SETINKLAYER, (WPARAM)uLayer, 0L); + } + + void SetPageStyle(UINT uStyle) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETPAGESTYLE, (WPARAM)uStyle, 0L); + } + + void SetPenMode(UINT uMode) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETPENMODE, (WPARAM)uMode, 0L); + } + + void SetViewStyle(UINT uStyle) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETVIEW, (WPARAM)uStyle, 0L); + } + + void SetViewAttributes(VIEWATTRIBUTES* pAttribs) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pAttribs); + ::SendMessage(m_hWnd, EM_SETVIEWATTRIBUTES, 0, (LPARAM)pAttribs); + } + + void SetWrapMode(UINT uMode) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETWRAPMODE, (WPARAM)uMode, 0L); + } + + void SetZoomPercent(UINT uPercent) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETZOOMPERCENT, (WPARAM)uPercent, 0L); + } + + LONG StreamIn(UINT uFormat, EDITSTREAM& es) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (LONG)::SendMessage(m_hWnd, EM_STREAMIN, (WPARAM)uFormat, (LPARAM)&es); + } + + LONG StreamOut(UINT uFormat, EDITSTREAM& es) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (LONG)::SendMessage(m_hWnd, EM_STREAMOUT, (WPARAM)uFormat, (LPARAM)&es); + } + + void UndoEvent() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_UNDOEVENT, 0, 0L); + } + +// Standard EM_xxx messages + DWORD GetSel() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, EM_GETSEL, 0, 0L); + } + + void GetSel(int& nStartChar, int& nEndChar) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar); + } + + void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM)bCanUndo, (LPARAM)lpszNewText); + } + + void SetModify(BOOL bModified = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, EM_SETMODIFY, (WPARAM)bModified, 0L); + } + + int GetTextLength() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, WM_GETTEXTLENGTH, 0, 0L); + } + +// Clipboard operations + void Clear() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L); + } + + void Copy() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_COPY, 0, 0L); + } + + void Cut() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_CUT, 0, 0L); + } + + void Paste() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_PASTE, 0, 0L); + } +}; + +typedef CRichInkCtrlT CRichInkCtrl; + + +/////////////////////////////////////////////////////////////////////////////// +// CInkXCtrl + +template +class CInkXCtrlT : public TBase +{ +public: +// Constructors + CInkXCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CInkXCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + ATLASSERT(hWnd != NULL); // Did you remember to call InitInkX() ?? + return hWnd; + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return WC_INKX; + } + + static UINT GetHotRecordingMessage() + { + return ::RegisterWindowMessage(szHotRecording); + } + + void ClearAll() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, IM_CLEARALL, 0, 0L); + } + + int GetData(BYTE* lpBuffer, INT cbBuffer) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(lpBuffer); + return (int)::SendMessage(m_hWnd, IM_GETDATA, (WPARAM)cbBuffer, (LPARAM)lpBuffer); + } + + int GetDataLen() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, IM_GETDATALEN, 0, 0L); + } + + CRichInkCtrl GetRichInk() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HWND)::SendMessage(m_hWnd, IM_GETRICHINK, 0, 0L); + } + + BOOL IsRecording() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, IM_RECORDING, 0, 0L); + } + + void ReInit() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, IM_REINIT, 0, 0L); + } + + void SetData(const BYTE* lpInkData, INT cbInkData) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(lpInkData); + ::SendMessage(m_hWnd, IM_SETDATA, (WPARAM)cbInkData, (LPARAM)lpInkData); + } + + void VoicePlay() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, IM_VOICE_PLAY, 0, 0L); + } + + BOOL IsVoicePlaying() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, IM_VOICE_PLAYING, 0, 0L); + } + + BOOL VoiceRecord() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, IM_VOICE_RECORD, 0, 0L); + } + + void VoiceStop() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, IM_VOICE_STOP, 0, 0L); + } + + void ShowVoiceBar(BOOL bShow = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, IM_VOICEBAR, (WPARAM)bShow, 0L); + } +}; + +typedef CInkXCtrlT CInkXCtrl; + +#endif // WIN32_PLATFORM_PSPC + + +/////////////////////////////////////////////////////////////////////////////// +// CVoiceRecorderCtrl + +template +class CVoiceRecorderCtrlT : public TBase +{ +public: +// Constructors + CVoiceRecorderCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CVoiceRecorderCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, const POINT pt, LPTSTR pstrFileName, UINT nID, DWORD dwStyle = 0) + { + ATLASSERT(pstrFileName != NULL); + CM_VOICE_RECORDER cmvr = { 0 }; + cmvr.cb = sizeof(CM_VOICE_RECORDER); + cmvr.dwStyle = dwStyle; + cmvr.xPos = pt.x; + cmvr.yPos = pt.y; + cmvr.hwndParent = hWndParent; + cmvr.id = nID; + cmvr.lpszRecordFileName = pstrFileName; + m_hWnd = VoiceRecorder_Create(&cmvr); + return m_hWnd; + } + + HWND Create(LPCM_VOICE_RECORDER pAttribs) + { + ATLASSERT(pAttribs); + m_hWnd = VoiceRecorder_Create(pAttribs); + return m_hWnd; + } + +// Attributes + void Record() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, VRM_RECORD, 0, 0L); + } + + void Play() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, VRM_PLAY, 0, 0L); + } + + void Stop() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, VRM_STOP, 0, 0L); + } + + void Cancel() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, VRM_CANCEL, 0, 0L); + } + + void Done() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, VRM_OK, 0, 0L); + } +}; + +typedef CVoiceRecorderCtrlT CVoiceRecorderCtrl; + + +#ifdef WIN32_PLATFORM_PSPC + +/////////////////////////////////////////////////////////////////////////////// +// CDocListCtrl + +template +class CDocListCtrlT : public TBase +{ +public: +// Attributes + DOCLISTCREATE m_dlc; + TCHAR m_szPath[MAX_PATH]; + +// Constructors + CDocListCtrlT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CDocListCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, WORD wId, LPCTSTR pszFolder = NULL, LPCTSTR pstrFilter = NULL, + WORD wFilterIndex = 0, DWORD dwFlags = DLF_SHOWEXTENSION) + { + ATLASSERT(pstrFilter != NULL); // It seems to need a filter badly!! + ::ZeroMemory(&m_dlc, sizeof(DOCLISTCREATE)); + ::ZeroMemory(m_szPath, sizeof(m_szPath)); + if(pszFolder != NULL) + ::lstrcpyn(m_szPath, pszFolder, MAX_PATH - 1); + m_dlc.dwStructSize = sizeof(DOCLISTCREATE); + m_dlc.hwndParent = hWndParent; + m_dlc.pszFolder = m_szPath; + m_dlc.pstrFilter = pstrFilter; + m_dlc.wFilterIndex = wFilterIndex; + m_dlc.wId = wId; + m_dlc.dwFlags = dwFlags; + m_hWnd = DocList_Create(&m_dlc); + return m_hWnd; + } + + HWND Create(DOCLISTCREATE* pDlc) + { + m_dlc = *pDlc; + m_hWnd = DocList_Create(&m_dlc); + return m_hWnd; + } + +// Attributes + void DeleteSel() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DLM_DELETESEL, 0, 0L); + } + + void DisableUpdates() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DLM_DISABLEUPDATES, 0, 0L); + } + + void EnableUpdates() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DLM_ENABLEUPDATES, 0, 0L); + } + + int GetFilterIndex() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, DLM_GETFILTERINDEX, 0, 0L); + } + + int GetItemCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, DLM_GETITEMCOUNT, 0, 0L); + } + + int GetNextItem(int iIndex, DWORD dwRelation = LVNI_ALL) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, DLM_GETNEXTITEM, (WPARAM)iIndex, (LPARAM)dwRelation); + } + + int GetFirstItem(DWORD dwRelation = LVNI_ALL) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, DLM_GETNEXTITEM, (WPARAM)-1, (LPARAM)dwRelation); + } + + BOOL GetNextWave(int* pIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pIndex); + return (BOOL)::SendMessage(m_hWnd, DLM_GETNEXTWAVE, 0, (LPARAM)pIndex); + } + + BOOL GetPrevWave(int* pIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pIndex); + return (BOOL)::SendMessage(m_hWnd, DLM_GETPREVWAVE, 0, (LPARAM)pIndex); + } + + int GetSelCount() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, DLM_GETSELCOUNT, 0, 0L); + } + + BOOL GetSelPathName(LPTSTR pstrPath, int cchMax) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pstrPath); + return (BOOL)::SendMessage(m_hWnd, DLM_GETSELPATHNAME, (WPARAM)cchMax, (LPARAM)pstrPath); + } + + void ReceiveIR(LPCTSTR pstrPath) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pstrPath); + ::SendMessage(m_hWnd, DLM_RECEIVEIR, 0, (LPARAM)pstrPath); + } + + void Refresh() + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DLM_REFRESH, 0, 0L); + } + + BOOL RenameMoveSelectedItems() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, DLM_RENAMEMOVE, 0, 0L); + } + + int SelectAll() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (int)::SendMessage(m_hWnd, DLM_SELECTALL, 0, 0L); + } + + HRESULT SelectItem(LPCTSTR pstrPath, BOOL bVisible = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pstrPath); + return (HRESULT)::SendMessage(m_hWnd, DLM_SELECTITEM, (WPARAM)bVisible, (LPARAM)pstrPath); + } + + void SendEMail(LPCTSTR pstrAttachment) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DLM_SENDEMAIL, 0, (LPARAM)pstrAttachment); + } + + void SendIR(LPCTSTR pstrPath) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DLM_SENDIR, 0, (LPARAM)pstrPath); + } + + HRESULT SetFilterIndex(int iIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HRESULT)::SendMessage(m_hWnd, DLM_SETFILTERINDEX, (WPARAM)iIndex, 0L); + } + + void SetFolder(LPCTSTR pstrPath) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pstrPath); + ::SendMessage(m_hWnd, DLM_SETFOLDER, 0, (LPARAM)pstrPath); + } + + BOOL SetItemState(int iIndex, const LVITEM* pItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pItem); + return (BOOL)::SendMessage(m_hWnd, DLM_SETITEMSTATE, (WPARAM)iIndex, (LPARAM)pItem); + } + + BOOL SetItemState(int iIndex, UINT uState, UINT uMask) + { + ATLASSERT(::IsWindow(m_hWnd)); + LV_ITEM lvi = { 0 }; + lvi.stateMask = uMask; + lvi.state = uState; + return (BOOL)::SendMessage(m_hWnd, DLM_SETITEMSTATE, (WPARAM)iIndex, (LPARAM)&lvi); + } + + void SetOneItem(int iIndex, LPCVOID pPA) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DLM_SETONEITEM, (WPARAM)iIndex, (LPARAM)pPA); + } + + void SetSelect(int iIndex) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, DLM_SETSELECT, (WPARAM)iIndex, 0L); + } + + void SetSelPathName(LPCTSTR pstrPath) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pstrPath); + ::SendMessage(m_hWnd, DLM_SETSELPATHNAME, 0, (LPARAM)pstrPath); + } + + BOOL SetSortOrder() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, DLM_SETSORTORDER, 0, 0L); + } + + HRESULT Update() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HRESULT)::SendMessage(m_hWnd, DLM_UPDATE, 0, 0L); + } + + BOOL ValidateFolder() + { + ATLASSERT(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, DLM_VALIDATEFOLDER, 0, 0L); + } + +// Functions + BOOL GetFirstSelectedWaveFile(int* pIndex, LPTSTR szPath, const size_t cchPath) + { + ATLASSERT(::IsWindow(m_hWnd)); + return DocList_GetFirstSelectedWaveFile(m_hWnd, pIndex, szPath, cchPath); + } + + BOOL GetNextSelectedWaveFile(int* pIndex, LPTSTR szPath, const size_t cchPath) + { + ATLASSERT(::IsWindow(m_hWnd)); + return DocList_GetNextSelectedWaveFile(m_hWnd, pIndex, szPath, cchPath); + } +}; + +typedef CDocListCtrlT CDocListCtrl; + +#endif // WIN32_PLATFORM_PSPC + + +/////////////////////////////////////////////////////////////////////////////// +// CCapEdit + +template +class CCapEditT : public TBase +{ +public: +// Constructors + CCapEditT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CCapEditT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + HWND hWnd = /*TBase*/CWindow::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + ATLASSERT(hWnd != NULL); // Did you remember to call SHInitExtraControls() ?? + return hWnd; + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return WC_CAPEDIT; + } +}; + +typedef CCapEditT CCapEdit; + +/////////////////////////////////////////////////////////////////////////////// +// CTTStatic + +#ifndef WIN32_PLATFORM_WFSP // Tooltips not supported on SmartPhone + +template +class CTTStaticT : public TBase +{ +public: +// Constructors + CTTStaticT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CTTStaticT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + HWND hWnd = TBase::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + ATLASSERT(hWnd != NULL); // Did you remember to call SHInitExtraControls() ?? + return hWnd; + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return WC_TSTATIC; + } + +// Operations + BOOL SetToolTipText(LPCTSTR pstrTipText) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pstrTipText); + ATLASSERT(lstrlen(pstrTipText)<= 253); + CTempBuffer buff; + LPTSTR pstr = buff.Allocate(lstrlen(pstrTipText) + 3); + if(pstr == NULL) + return FALSE; + ::lstrcpy(pstr, _T("~~")); + ::lstrcat(pstr, pstrTipText); + return SetWindowText(pstr); + } +}; + +typedef CTTStaticT CTTStatic; + + +/////////////////////////////////////////////////////////////////////////////// +// CTTButton + +template +class CTTButtonT : public TBase +{ +public: +// Constructors + CTTButtonT(HWND hWnd = NULL) : TBase(hWnd) + { } + + CTTButtonT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + HWND hWnd = TBase::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); + ATLASSERT(hWnd != NULL); // Did you remember to call SHInitExtraControls() ?? + return hWnd; + } + +// Attributes + static LPCTSTR GetWndClassName() + { + return WC_TBUTTON; + } + +// Operations + BOOL SetToolTipText(LPCTSTR pstrTipText) + { + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(pstrTipText); + ATLASSERT(lstrlen(pstrTipText)<= 253); + CTempBuffer buff; + LPTSTR pstr = buff.Allocate(lstrlen(pstrTipText) + 3); + if(pstr == NULL) + return FALSE; + ::lstrcpy(pstr, _T("~~")); + ::lstrcat(pstr, pstrTipText); + return SetWindowText(pstr); + } +}; + +typedef CTTButtonT CTTButton; + +#endif // !WIN32_PLATFORM_WFSP + + +// --- SmartPhone specific controls --- + +#ifdef WIN32_PLATFORM_WFSP + +/////////////////////////////////////////////////////////////////////////////// +// CSpinCtrlT - CSpinCtrl : SmartPhone adapted UpDown control + +template +class CSpinCtrlT : public CUpDownCtrlT< TBase > +{ +public: +// Constructors + CSpinCtrlT(HWND hWnd = NULL) : CUpDownCtrlT< TBase >(hWnd) + { } + + CSpinCtrlT< TBase >& operator =(HWND hWnd) + { + m_hWnd = hWnd; + return *this; + } + + HWND Create(HWND hWndParent, HWND hBuddy, DWORD dwStyle, int nID, LPCTSTR szExpandedName = NULL) + { + ATLASSERT(::IsWindow(hWndParent)); + CUpDownCtrlT< TBase >::Create(hWndParent, NULL, szExpandedName, dwStyle, 0, nID, NULL); + ATLASSERT(m_hWnd != NULL); // Did you remember to call AtlInitCommonControls(ICC_UPDOWN_CLASS)? + if (hBuddy != NULL) + { + ATLASSERT(::IsWindow(hBuddy)); + SetBuddy(hBuddy); + } + return m_hWnd; + } +}; + +typedef CSpinCtrlT CSpinCtrl; + + +/////////////////////////////////////////////////////////////////////////////// +// CSpinned - SmartPhone association of control and Spin + +template +class CSpinned : public TBase +{ +public: + CSpinCtrl m_SpinCtrl; + DWORD m_dwSpinnedStyle; + +// Constructors + CSpinned(HWND hWnd = NULL) : TBase(hWnd) + { + m_dwSpinnedStyle = WS_VISIBLE | UDS_ALIGNRIGHT | UDS_EXPANDABLE; + + if (t_bExpandOnly == true) + m_dwSpinnedStyle |= UDS_NOSCROLL; + else + m_dwSpinnedStyle |= UDS_HORZ | UDS_ARROWKEYS | UDS_SETBUDDYINT | UDS_WRAP; + + if (hWnd != NULL) + AttachOrCreateSpinCtrl(); + } + + CSpinned& operator =(HWND hWnd) + { + Attach(hWnd); + return *this; + } + + void Attach(HWND hWnd) + { + ATLASSERT(!IsWindow()); + TBase* pT = static_cast(this); + pT->m_hWnd = hWnd; + if (hWnd != NULL) + AttachOrCreateSpinCtrl(); + } + + HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szExpandedName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, + ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + + TBase* pT = static_cast(this); + TBase::Create(hWndParent, rect, NULL, dwStyle, dwExStyle, MenuOrID, lpCreateParam); + ATLASSERT(pT->m_hWnd != NULL); + + m_SpinCtrl.Create(hWndParent, pT->m_hWnd, m_dwSpinnedStyle, ATL_IDW_SPIN_ID + (int)MenuOrID.m_hMenu, szExpandedName); + + ATLASSERT(m_SpinCtrl.m_hWnd != NULL); // Did you remember to call AtlInitCommonControls(ICC_UPDOWN_CLASS)? + + return pT->m_hWnd; + } + +// Attributes + CSpinCtrl& GetSpinCtrl() + { + return m_SpinCtrl; + } + +// Implementation + // Attach our existing SpinCtrl or create one + bool AttachOrCreateSpinCtrl() + { + TBase* pT = static_cast(this); + + HWND hSpin = ::GetDlgItem(pT->GetParent(), ATL_IDW_SPIN_ID + pT->GetDlgCtrlID()); + + if (hSpin != NULL) + { + m_SpinCtrl.Attach(hSpin); +#ifdef DEBUG + TCHAR sClassName[16]; + ::GetClassName(hSpin, sClassName, 16); + ATLASSERT(!_tcscmp(sClassName, UPDOWN_CLASS)); + ATLASSERT(m_SpinCtrl.GetBuddy().m_hWnd == pT->m_hWnd); +#endif // DEBUG + } + else + { + m_SpinCtrl.Create(pT->GetParent(), pT->m_hWnd, m_dwSpinnedStyle, ATL_IDW_SPIN_ID + pT->GetDlgCtrlID()); + } + + return m_SpinCtrl.m_hWnd != NULL; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CSpinListBox - SmartPhone spinned ListBox control +// CExpandListBox - SmartPhone expandable ListBox control +// CExpandEdit - SmartPhone expandable Edit control +// CExpandCapEdit - SmartPhone expandable CapEdit control + +typedef CSpinned CSpinListBox; +typedef CSpinned CExpandListBox; +typedef CSpinned CExpandEdit; +typedef CSpinned CExpandCapEdit; + +#endif // WIN32_PLATFORM_WFSP + +#endif // _WTL_CE_NO_CONTROLS + +}; // namespace WTL + +#endif // __ATLWINCE_H__ diff --git a/Client/Client/GUI/BKWin/wtl/atlwinx.h b/Client/Client/GUI/BKWin/wtl/atlwinx.h new file mode 100644 index 00000000..d0f1c480 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtl/atlwinx.h @@ -0,0 +1,526 @@ +// Windows Template Library - WTL version 8.0 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Microsoft Permissive License (Ms-PL) which can be found in the file +// Ms-PL.txt at the root of this distribution. + +#ifndef __ATLWINX_H__ +#define __ATLWINX_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifndef __ATLAPP_H__ + #error atlwinx.h requires atlapp.h to be included first +#endif + +#if (_ATL_VER >= 0x0700) + #include +#endif // (_ATL_VER >= 0x0700) + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// _U_RECT +// _U_MENUorID +// _U_STRINGorID + + +/////////////////////////////////////////////////////////////////////////////// +// Command Chaining Macros + +#define CHAIN_COMMANDS(theChainClass) \ + if(uMsg == WM_COMMAND) \ + CHAIN_MSG_MAP(theChainClass) + +#define CHAIN_COMMANDS_ALT(theChainClass, msgMapID) \ + if(uMsg == WM_COMMAND) \ + CHAIN_MSG_MAP_ALT(theChainClass, msgMapID) + +#define CHAIN_COMMANDS_MEMBER(theChainMember) \ + if(uMsg == WM_COMMAND) \ + CHAIN_MSG_MAP_MEMBER(theChainMember) + +#define CHAIN_COMMANDS_ALT_MEMBER(theChainMember, msgMapID) \ + if(uMsg == WM_COMMAND) \ + CHAIN_MSG_MAP_ALT_MEMBER(theChainMember, msgMapID) + + +/////////////////////////////////////////////////////////////////////////////// +// Macros for parent message map to selectively reflect control messages + +// NOTE: ReflectNotifications is a member of ATL's CWindowImplRoot +// (and overridden in 2 cases - CContainedWindowT and CAxHostWindow) +// Since we can't modify ATL, we'll provide the needed additions +// in a separate function (that is not a member of CWindowImplRoot) + +namespace WTL +{ + +inline LRESULT WtlReflectNotificationsFiltered(HWND hWndParent, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled, + UINT uMsgFilter = WM_NULL, UINT_PTR idFromFilter = 0, HWND hWndChildFilter = NULL) +{ + if((uMsgFilter != WM_NULL) && (uMsgFilter != uMsg)) + { + // The notification message doesn't match the filter. + bHandled = FALSE; + return 1; + } + + HWND hWndChild = NULL; + UINT_PTR idFrom = 0; + + switch(uMsg) + { + case WM_COMMAND: + if(lParam != NULL) // not from a menu + { + hWndChild = (HWND)lParam; + idFrom = (UINT_PTR)LOWORD(wParam); + } + break; + case WM_NOTIFY: + hWndChild = ((LPNMHDR)lParam)->hwndFrom; + idFrom = ((LPNMHDR)lParam)->idFrom; + break; +#ifndef _WIN32_WCE + case WM_PARENTNOTIFY: + switch(LOWORD(wParam)) + { + case WM_CREATE: + case WM_DESTROY: + hWndChild = (HWND)lParam; + idFrom = (UINT_PTR)HIWORD(wParam); + break; + default: + hWndChild = ::GetDlgItem(hWndParent, HIWORD(wParam)); + idFrom = (UINT_PTR)::GetDlgCtrlID(hWndChild); + break; + } + break; +#endif // !_WIN32_WCE + case WM_DRAWITEM: + if(wParam) // not from a menu + { + hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem; + idFrom = (UINT_PTR)wParam; + } + break; + case WM_MEASUREITEM: + if(wParam) // not from a menu + { + hWndChild = ::GetDlgItem(hWndParent, ((LPMEASUREITEMSTRUCT)lParam)->CtlID); + idFrom = (UINT_PTR)wParam; + } + break; + case WM_COMPAREITEM: + if(wParam) // not from a menu + { + hWndChild = ((LPCOMPAREITEMSTRUCT)lParam)->hwndItem; + idFrom = (UINT_PTR)wParam; + } + break; + case WM_DELETEITEM: + if(wParam) // not from a menu + { + hWndChild = ((LPDELETEITEMSTRUCT)lParam)->hwndItem; + idFrom = (UINT_PTR)wParam; + } + break; + case WM_VKEYTOITEM: + case WM_CHARTOITEM: + case WM_HSCROLL: + case WM_VSCROLL: + hWndChild = (HWND)lParam; + idFrom = (UINT_PTR)::GetDlgCtrlID(hWndChild); + break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLOREDIT: + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLORMSGBOX: + case WM_CTLCOLORSCROLLBAR: + case WM_CTLCOLORSTATIC: + hWndChild = (HWND)lParam; + idFrom = (UINT_PTR)::GetDlgCtrlID(hWndChild); + break; + default: + break; + } + + if((hWndChild == NULL) || + ((hWndChildFilter != NULL) && (hWndChildFilter != hWndChild))) + { + // Either hWndChild isn't valid, or + // hWndChild doesn't match the filter. + bHandled = FALSE; + return 1; + } + + if((idFromFilter != 0) && (idFromFilter != idFrom)) + { + // The dialog control id doesn't match the filter. + bHandled = FALSE; + return 1; + } + + ATLASSERT(::IsWindow(hWndChild)); + LRESULT lResult = ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam); + if((lResult == 0) && (uMsg >= WM_CTLCOLORMSGBOX) && (uMsg <= WM_CTLCOLORSTATIC)) + { + // Try to prevent problems with WM_CTLCOLOR* messages when + // the message wasn't really handled + bHandled = FALSE; + } + + return lResult; +} + +}; // namespace WTL + +// Try to prevent problems with WM_CTLCOLOR* messages when +// the message wasn't really handled +#define REFLECT_NOTIFICATIONS_EX() \ +{ \ + bHandled = TRUE; \ + lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ + if((lResult == 0) && (uMsg >= WM_CTLCOLORMSGBOX) && (uMsg <= WM_CTLCOLORSTATIC)) \ + bHandled = FALSE; \ + if(bHandled) \ + return TRUE; \ +} + +#define REFLECT_NOTIFICATIONS_MSG_FILTERED(uMsgFilter) \ + { \ + bHandled = TRUE; \ + lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, uMsgFilter, 0, NULL); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECT_NOTIFICATIONS_ID_FILTERED(idFromFilter) \ + { \ + bHandled = TRUE; \ + lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, WM_NULL, idFromFilter, NULL); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECT_NOTIFICATIONS_HWND_FILTERED(hWndChildFilter) \ + { \ + bHandled = TRUE; \ + lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, WM_NULL, 0, hWndChildFilter); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECT_NOTIFICATIONS_MSG_ID_FILTERED(uMsgFilter, idFromFilter) \ + { \ + bHandled = TRUE; \ + lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, uMsgFilter, idFromFilter, NULL); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECT_NOTIFICATIONS_MSG_HWND_FILTERED(uMsgFilter, hWndChildFilter) \ + { \ + bHandled = TRUE; \ + lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, uMsgFilter, 0, hWndChildFilter); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECT_COMMAND(id, code) \ + if(uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \ + { \ + bHandled = TRUE; \ + lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECT_COMMAND_ID(id) \ + if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \ + { \ + bHandled = TRUE; \ + lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECT_COMMAND_CODE(code) \ + if(uMsg == WM_COMMAND && code == HIWORD(wParam)) \ + { \ + bHandled = TRUE; \ + lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECT_COMMAND_RANGE(idFirst, idLast) \ + if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ + { \ + bHandled = TRUE; \ + lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECT_COMMAND_RANGE_CODE(idFirst, idLast, code) \ + if(uMsg == WM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ + { \ + bHandled = TRUE; \ + lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECT_NOTIFY(id, cd) \ + if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \ + { \ + bHandled = TRUE; \ + lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECT_NOTIFY_ID(id) \ + if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \ + { \ + bHandled = TRUE; \ + lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECT_NOTIFY_CODE(cd) \ + if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \ + { \ + bHandled = TRUE; \ + lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECT_NOTIFY_RANGE(idFirst, idLast) \ + if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ + { \ + bHandled = TRUE; \ + lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECT_NOTIFY_RANGE_CODE(idFirst, idLast, cd) \ + if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ + { \ + bHandled = TRUE; \ + lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + + +/////////////////////////////////////////////////////////////////////////////// +// Reflected message handler macros for message maps (for ATL 3.0) + +#if (_ATL_VER < 0x0700) + +#define REFLECTED_COMMAND_HANDLER(id, code, func) \ + if(uMsg == OCM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \ + { \ + bHandled = TRUE; \ + lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECTED_COMMAND_ID_HANDLER(id, func) \ + if(uMsg == OCM_COMMAND && id == LOWORD(wParam)) \ + { \ + bHandled = TRUE; \ + lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECTED_COMMAND_CODE_HANDLER(code, func) \ + if(uMsg == OCM_COMMAND && code == HIWORD(wParam)) \ + { \ + bHandled = TRUE; \ + lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECTED_COMMAND_RANGE_HANDLER(idFirst, idLast, func) \ + if(uMsg == OCM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ + { \ + bHandled = TRUE; \ + lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECTED_COMMAND_RANGE_CODE_HANDLER(idFirst, idLast, code, func) \ + if(uMsg == OCM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ + { \ + bHandled = TRUE; \ + lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECTED_NOTIFY_HANDLER(id, cd, func) \ + if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \ + { \ + bHandled = TRUE; \ + lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECTED_NOTIFY_ID_HANDLER(id, func) \ + if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \ + { \ + bHandled = TRUE; \ + lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECTED_NOTIFY_CODE_HANDLER(cd, func) \ + if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \ + { \ + bHandled = TRUE; \ + lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECTED_NOTIFY_RANGE_HANDLER(idFirst, idLast, func) \ + if(uMsg == OCM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ + { \ + bHandled = TRUE; \ + lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#define REFLECTED_NOTIFY_RANGE_CODE_HANDLER(idFirst, idLast, cd, func) \ + if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ + { \ + bHandled = TRUE; \ + lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +#endif // (_ATL_VER < 0x0700) + + +/////////////////////////////////////////////////////////////////////////////// +// Dual argument helper classes (for ATL 3.0) + +#if (_ATL_VER < 0x0700) + +namespace ATL +{ + +class _U_RECT +{ +public: + _U_RECT(LPRECT lpRect) : m_lpRect(lpRect) + { } + _U_RECT(RECT& rc) : m_lpRect(&rc) + { } + LPRECT m_lpRect; +}; + +class _U_MENUorID +{ +public: + _U_MENUorID(HMENU hMenu) : m_hMenu(hMenu) + { } + _U_MENUorID(UINT nID) : m_hMenu((HMENU)LongToHandle(nID)) + { } + HMENU m_hMenu; +}; + +class _U_STRINGorID +{ +public: + _U_STRINGorID(LPCTSTR lpString) : m_lpstr(lpString) + { } + _U_STRINGorID(UINT nID) : m_lpstr(MAKEINTRESOURCE(nID)) + { } + LPCTSTR m_lpstr; +}; + +}; // namespace ATL + +#endif // (_ATL_VER < 0x0700) + + +namespace WTL +{ + +/////////////////////////////////////////////////////////////////////////////// +// Forward notifications support for message maps (for ATL 3.0) + +#if (_ATL_VER < 0x0700) + +// forward notifications support +#define FORWARD_NOTIFICATIONS() \ + { \ + bHandled = TRUE; \ + lResult = WTL::Atl3ForwardNotifications(m_hWnd, uMsg, wParam, lParam, bHandled); \ + if(bHandled) \ + return TRUE; \ + } + +static LRESULT Atl3ForwardNotifications(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + LRESULT lResult = 0; + switch(uMsg) + { + case WM_COMMAND: + case WM_NOTIFY: +#ifndef _WIN32_WCE + case WM_PARENTNOTIFY: +#endif // !_WIN32_WCE + case WM_DRAWITEM: + case WM_MEASUREITEM: + case WM_COMPAREITEM: + case WM_DELETEITEM: + case WM_VKEYTOITEM: + case WM_CHARTOITEM: + case WM_HSCROLL: + case WM_VSCROLL: + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLOREDIT: + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLORMSGBOX: + case WM_CTLCOLORSCROLLBAR: + case WM_CTLCOLORSTATIC: + lResult = ::SendMessage(::GetParent(hWnd), uMsg, wParam, lParam); + break; + default: + bHandled = FALSE; + break; + } + return lResult; +} + +#endif // (_ATL_VER < 0x0700) + +}; // namespace WTL + +#endif // __ATLWINX_H__ diff --git a/Client/Client/GUI/BKWin/wtlhelper/bkfolderbrowsectrl.h b/Client/Client/GUI/BKWin/wtlhelper/bkfolderbrowsectrl.h new file mode 100644 index 00000000..17a69a51 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtlhelper/bkfolderbrowsectrl.h @@ -0,0 +1,960 @@ +#pragma once + +#include +#include +#include "iidl.h" +#include "wh3statecheckimglst.h" + +#define WH3STVN_ITEMCHECKCHANGE 1 + +class CWH3StateCheckTreeCtrl + : public CWindowImpl +{ +public: + + enum { + CHECK_STATE_NONE = 0, + CHECK_STATE_UNCHECKED, + CHECK_STATE_CHECKED, + CHECK_STATE_MIXED, + }; + + BOOL GetCheckState(HTREEITEM hItem) + { + return CHECK_STATE_CHECKED == (GetItemState(hItem, TVIS_STATEIMAGEMASK) >> 12); + } + + BOOL HasCheckedItem() + { + HTREEITEM hItem = GetChildItem(TVI_ROOT); + + while (NULL != hItem) + { + switch (GetItemState(hItem, TVIS_STATEIMAGEMASK) >> 12) + { + case CHECK_STATE_UNCHECKED: + break; + + case CHECK_STATE_CHECKED: + case CHECK_STATE_MIXED: + return TRUE; + + case CHECK_STATE_NONE: + hItem = GetChildItem(hItem); + continue; + } + + HTREEITEM hNextItem = GetNextSiblingItem(hItem); + if (NULL == hNextItem) + { + HTREEITEM hParentItem = hItem; + + do + { + hParentItem = GetParentItem(hParentItem); + if (NULL == hParentItem) + break; + + hNextItem = GetNextSiblingItem(hParentItem); + + } while (NULL == hNextItem); + } + + hItem = hNextItem; + } + + return FALSE; + } + + void Init3State() + { + _Init3State(); + } + +protected: + + CWH3StateCheckImageList m_wnd3StateCheckImgList; + + void _Init3State() + { + m_wnd3StateCheckImgList.Create(); + + SetImageList(m_wnd3StateCheckImgList, TVSIL_STATE); + } + + void _CheckSelfAndAllChilds(HTREEITEM hItem, BOOL bCheck) + { + SetCheckState(hItem, bCheck); + + HTREEITEM hItemChild = GetChildItem(hItem); + while (NULL != hItemChild) + { + _CheckSelfAndAllChilds(hItemChild, bCheck); + + hItemChild = GetNextSiblingItem(hItemChild); + } + } + + void _ResetParentState(HTREEITEM hItem) + { + HTREEITEM hItemParent = GetParentItem(hItem); + + if (NULL == hItemParent) + return; + + UINT uCheck = (GetItemState(hItemParent, TVIS_STATEIMAGEMASK) >> 12); + + if (CHECK_STATE_NONE == uCheck) + return; + + HTREEITEM hItemParentChild = GetChildItem(hItemParent); + + BOOL bHasCheck = FALSE, bHasUncheck = FALSE; + + while (NULL != hItemParentChild) + { + uCheck = (GetItemState(hItemParentChild, TVIS_STATEIMAGEMASK) >> 12); + + bHasCheck |= CHECK_STATE_CHECKED == uCheck || CHECK_STATE_MIXED == uCheck; + bHasUncheck |= CHECK_STATE_UNCHECKED == uCheck || CHECK_STATE_MIXED == uCheck; + + hItemParentChild = GetNextSiblingItem(hItemParentChild); + } + + if (bHasCheck) + { + uCheck = CHECK_STATE_MIXED; +// if (bHasUncheck) +// else +// uCheck = CHECK_STATE_CHECKED; + } + else + { + if (bHasUncheck) + uCheck = CHECK_STATE_UNCHECKED; + else + uCheck = CHECK_STATE_NONE; + } + + SetItemState(hItemParent, INDEXTOSTATEIMAGEMASK(uCheck), TVIS_STATEIMAGEMASK); + + _ResetParentState(hItemParent); + } + + void _ToggleItem(HTREEITEM hItem) + { + UINT uState = GetItemState(hItem, TVIS_STATEIMAGEMASK) >> 12; + + if (CHECK_STATE_NONE == uState) + return; + + SetRedraw(FALSE); + + BOOL bCheck = !(CHECK_STATE_CHECKED == uState); + + _CheckSelfAndAllChilds(hItem, bCheck); + _ResetParentState(hItem); + + SetRedraw(TRUE); + + NMHDR nms; + nms.code = WH3STVN_ITEMCHECKCHANGE; + nms.hwndFrom = m_hWnd; + nms.idFrom = GetDlgCtrlID(); + + LRESULT lRet = ::SendMessage(GetParent(), WM_NOTIFY, (LPARAM)nms.idFrom, (WPARAM)&nms); + } + + void OnLButtonDown(UINT nFlags, CPoint point) + { + TVHITTESTINFO htinfo; + + ZeroMemory(&htinfo, sizeof(htinfo)); + + htinfo.pt = point; + + HitTest(&htinfo); + + if (NULL == htinfo.hItem || TVHT_ONITEMSTATEICON != htinfo.flags) + { + SetMsgHandled(FALSE); + return; + } + + _ToggleItem(htinfo.hItem); + } + + void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) + { + if (VK_SPACE != nChar) + { + SetMsgHandled(FALSE); + return; + } + + HTREEITEM hItem = GetSelectedItem(); + if (NULL == hItem) + { + SetMsgHandled(FALSE); + return; + } + + _ToggleItem(hItem); + } + + void OnDestroy() + { + m_wnd3StateCheckImgList.Destroy(); + + SetMsgHandled(FALSE); + } + +public: + + BEGIN_MSG_MAP_EX(CBkFolderBrowseCtrl) + MSG_WM_LBUTTONDOWN(OnLButtonDown) + MSG_WM_LBUTTONDBLCLK(OnLButtonDown) + MSG_WM_KEYDOWN(OnKeyDown) + MSG_WM_DESTROY(OnDestroy) + END_MSG_MAP() +}; + +// 첽ʽӽڵʱϢ +#define MSG_BKFBC_INSERT_ITEM (WM_APP) + +class CBkFolderBrowseCtrl : public CWH3StateCheckTreeCtrl +{ +protected: + typedef CAtlMap __MapItemToPath; + +public: + CBkFolderBrowseCtrl() + : m_hItemMyComputer(NULL) + { + } + + HWND Create( + HWND hWndParent, UINT uID = 0U, DWORD dwStyle = 0, DWORD dwExStyle = 0, + _U_RECT rect = NULL) + { + dwStyle |= WS_CHILD | TVS_CHECKBOXES | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS; + + m_hItemMyComputer = NULL; + + HWND hWnd = __super::Create(hWndParent, rect, NULL, dwStyle, dwExStyle, uID); + if (NULL == hWnd) + return NULL; + + _Init(); + + _Init3State(); + + return hWnd; + } + + void GetSelectedPathes(CAtlList& lstPathes) + { + HTREEITEM hItem = GetChildItem(TVI_ROOT); + CString strPath; + + lstPathes.RemoveAll(); + + while (NULL != hItem) + { + switch (GetItemState(hItem, TVIS_STATEIMAGEMASK) >> 12) + { + case CHECK_STATE_UNCHECKED: + break; + + case CHECK_STATE_CHECKED: + if (hItem != m_hItemMyComputer) + { + _GetFullPath(hItem, strPath); + lstPathes.AddTail(strPath); + break; + } + + case CHECK_STATE_NONE: + case CHECK_STATE_MIXED: + hItem = GetChildItem(hItem); + continue; + } + + HTREEITEM hNextItem = GetNextSiblingItem(hItem); + if (NULL == hNextItem) + { + HTREEITEM hParentItem = hItem; + + do + { + hParentItem = GetParentItem(hParentItem); + if (NULL == hParentItem) + break; + + hNextItem = GetNextSiblingItem(hParentItem); + + } while (NULL == hNextItem); + } + + hItem = hNextItem; + } + } + + BOOL Expand(HTREEITEM hItem, UINT nCode) + { + if ((nCode != TVE_EXPAND) && (nCode != TVE_TOGGLE)) + return TRUE; + + TVITEM tvi = {0}; + TVITEM *ptvi = &tvi; + ZeroMemory(&tvi, sizeof(tvi)); + + tvi.hItem = hItem; + tvi.mask = TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM; + tvi.stateMask = 0x0FFFF; + + GetItem(&tvi); + + if (tvi.state & (TVIS_EXPANDED | TVIS_EXPANDEDONCE)) + return FALSE; + + _ExpandByNewThread(hItem, nCode); + + return TRUE; + } + + static void SpeedUp() + { + DWORD dwThreadId = 0; + HANDLE hThread = ::CreateThread( + NULL, 0, + _SpeedUpThread, + NULL, 0, &dwThreadId + ); + ::CloseHandle(hThread); + } + +protected: + + struct __EXPAND_THREAD_PARAM + { + CBkFolderBrowseCtrl *pThis; + HWND hWnd; + HTREEITEM hItem; +// UINT nCode; + BOOL bCheck; + CString strFullPath; + }; + + CImageList m_wndIconList; + __MapItemToPath m_mapItemToPath; + HTREEITEM m_hItemMyComputer; + + static DWORD WINAPI _SpeedUpThread(LPVOID pvParam) + { + SHFILEINFO sfi; + size_t size = sizeof(SHFILEINFO); + + CIidl iidl(CSIDL_DESKTOP), iidlDrives(CSIDL_DRIVES); + + ::SHGetFileInfo( + (LPCTSTR)(LPITEMIDLIST)iidl, 0, + &sfi, sizeof(sfi), + SHGFI_SYSICONINDEX | SHGFI_PIDL | SHGFI_SMALLICON); + + CIidl iidlChild, iidlFull; + + IShellFolder *piFolder = iidlDrives.GetShellFolder(); + if (NULL == piFolder) + goto Exit0; + + IEnumIDList *piEnum = NULL; + HRESULT hRet = piFolder->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN, &piEnum); + if (FAILED(hRet)) + goto Exit0; + + while (TRUE) + { + hRet = piEnum->Next(1, iidlChild, NULL); + if (S_OK != hRet) + break; + + iidlFull = iidlDrives.Append(iidlChild); + + SHFILEINFO sfi; + DWORD_PTR dwRet = ::SHGetFileInfo( + (LPCTSTR)(LPITEMIDLIST)iidlFull, + 0, + &sfi, + sizeof(SHFILEINFO), + SHGFI_ICON | SHGFI_SMALLICON | SHGFI_PIDL | SHGFI_ATTRIBUTES | SHGFI_DISPLAYNAME); + +// if (0 == dwRet) +// continue; +// +// if (SFGAO_FILESYSTEM == (SFGAO_FILESYSTEM & sfi.dwAttributes)) +// { +// CString strPath; +// +// BOOL bRet = ::SHGetPathFromIDList(iidlFull, strPath.GetBuffer(MAX_PATH + 1)); +// if (bRet) +// { +// strPath.ReleaseBuffer(); +// strPath.TrimRight(L'\\'); +// } +// else +// strPath.ReleaseBuffer(0); +// } + } + +Exit0: + + if (piEnum) + { + piEnum->Release(); + piEnum = NULL; + } + + if (piFolder) + { + piFolder->Release(); + piFolder = NULL; + } + + DEBUG_TRACE(L" * CBkFolderBrowseCtrl _Speedup Finish\r\n"); + + return 0; + } + + void _ExpandByNewThread(HTREEITEM hItem, UINT nCode) + { + __EXPAND_THREAD_PARAM *pThreadParam; + CString strFullPath; + + BOOL bRet = _GetFullPath(hItem, strFullPath); + if (!bRet) + return; + + pThreadParam = new __EXPAND_THREAD_PARAM; + pThreadParam->hWnd = m_hWnd; + pThreadParam->hItem = hItem; +// pThreadParam->nCode = nCode; + pThreadParam->bCheck = GetCheckState(hItem); + pThreadParam->strFullPath = strFullPath; + + DWORD dwThreadId = 0; + HANDLE hThread = ::CreateThread( + NULL, 0, + _ExpandThreadProc, + pThreadParam, 0, &dwThreadId + ); + ::CloseHandle(hThread); + } + + HRESULT _Init() + { + HRESULT hRet = E_FAIL; + + DWORD dwTickCountFrom = ::GetTickCount(), dwTickCountTo = 0; + + hRet = _InitIconList(); + if (S_OK != hRet) + return hRet; + + dwTickCountTo = ::GetTickCount(); + DEBUG_TRACE(L" * CBkFolderBrowseCtrl _InitIconList %dms\r\n", dwTickCountTo - dwTickCountFrom); + dwTickCountFrom = dwTickCountTo; + + SetImageList(m_wndIconList, TVSIL_NORMAL); + + HTREEITEM hRootItem = _InsertItem(CSIDL_DESKTOP, TVI_ROOT); + + SetItemState( + hRootItem, + INDEXTOSTATEIMAGEMASK(CHECK_STATE_NONE) | TVIS_EXPANDED | TVIS_EXPANDEDONCE, + TVIS_STATEIMAGEMASK | TVIS_EXPANDED | TVIS_EXPANDEDONCE); + + m_hItemMyComputer = _InsertItem(CSIDL_DRIVES, hRootItem); + HTREEITEM hPersonalItem = _InsertItem(CSIDL_PERSONAL, hRootItem); + + CString strDesktopPath, strPersonalPath; + BOOL bRet = ::SHGetSpecialFolderPath(NULL, strDesktopPath.GetBuffer(MAX_PATH + 1), CSIDL_DESKTOPDIRECTORY, FALSE); + if (!bRet) + { + strDesktopPath.ReleaseBuffer(0); + + _Uninit(); + + return E_FAIL; + } + + strDesktopPath.ReleaseBuffer(); + + m_mapItemToPath[hRootItem] = strDesktopPath; + + dwTickCountTo = ::GetTickCount(); + DEBUG_TRACE(L" * CBkFolderBrowseCtrl Before _InsertSubFolders %dms\r\n", dwTickCountTo - dwTickCountFrom); + dwTickCountFrom = dwTickCountTo; + + _ExpandByNewThread(hRootItem, TVE_EXPAND); + //_InsertSubFolders(hRootItem, strDesktopPath); + + dwTickCountTo = ::GetTickCount(); + DEBUG_TRACE(L" * CBkFolderBrowseCtrl _InsertSubFolders %dms\r\n", dwTickCountTo - dwTickCountFrom); + dwTickCountFrom = dwTickCountTo; + + bRet = ::SHGetSpecialFolderPath(NULL, strPersonalPath.GetBuffer(MAX_PATH + 1), CSIDL_PERSONAL, FALSE); + if (!bRet) + { + strPersonalPath.ReleaseBuffer(0); + + return E_FAIL; + } + else + { + strPersonalPath.ReleaseBuffer(); + + m_mapItemToPath[hPersonalItem] = strPersonalPath; + } + + SetItemState(m_hItemMyComputer, TVIS_EXPANDED | TVIS_EXPANDEDONCE, TVIS_EXPANDED | TVIS_EXPANDEDONCE); + + dwTickCountTo = ::GetTickCount(); + DEBUG_TRACE(L" * CBkFolderBrowseCtrl Before _InsertDrives %dms\r\n", dwTickCountTo - dwTickCountFrom); + dwTickCountFrom = dwTickCountTo; + +// CIidl iidlDrives(CSIDL_DRIVES); +// +// _InsertDrives(m_hItemMyComputer, iidlDrives); + DWORD dwThreadId = 0; + HANDLE hThread = ::CreateThread( + NULL, 0, + _ExpandDrivesThreadProc, + this, 0, &dwThreadId + ); + ::CloseHandle(hThread); + + dwTickCountTo = ::GetTickCount(); + DEBUG_TRACE(L" * CBkFolderBrowseCtrl _InsertDrives %dms\r\n", dwTickCountTo - dwTickCountFrom); + dwTickCountFrom = dwTickCountTo; + + return S_OK; + } + + HRESULT _Uninit() + { + m_mapItemToPath.RemoveAll(); + + if (m_wndIconList.m_hImageList) + { + m_wndIconList.Detach(); + } + + m_hItemMyComputer = NULL; + + return S_OK; + } + + HRESULT _InitIconList() + { + SHFILEINFO sfi; + size_t size = sizeof(SHFILEINFO); + HRESULT hRet = E_FAIL; + + if (NULL != m_wndIconList.m_hImageList) + return S_FALSE; + + CIidl iidl(CSIDL_DESKTOP); + + m_wndIconList.Attach((HIMAGELIST)::SHGetFileInfo( + (LPCTSTR)(LPITEMIDLIST)iidl, 0, + &sfi, sizeof(sfi), + SHGFI_SYSICONINDEX | SHGFI_PIDL | SHGFI_SMALLICON) + ); + + m_wndIconList.SetBkColor(CLR_NONE); + + return (NULL != m_wndIconList.m_hImageList) ? S_OK : E_FAIL; + } + + HTREEITEM _InsertItem(int nFolder, HTREEITEM hParent = TVI_ROOT) + { + HTREEITEM hItem = NULL; + HRESULT hrRet = E_FAIL; + + SHFILEINFO sfi = { 0 }; + + hItem = _InsertItem(CIidl(nFolder), hParent); + + return hItem; + } + + HTREEITEM _InsertItem(LPITEMIDLIST pidl, HTREEITEM hParent = TVI_ROOT) + { + SHFILEINFO sfi; + TVINSERTSTRUCT tvis; + HTREEITEM hItem = NULL; + TCHAR szRootPath[MAX_PATH] = { 0 }; + + ATLASSERT(pidl != NULL); + + ZeroMemory(&sfi, sizeof(sfi)); + + ::SHGetFileInfo( + (LPCTSTR) pidl, 0, + &sfi, sizeof(sfi), + SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_DISPLAYNAME | SHGFI_PIDL | SHGFI_ATTRIBUTES + ); + if (0 == sfi.dwAttributes) + goto Exit0; + + ZeroMemory(&tvis, sizeof(tvis)); + + tvis.hParent = hParent; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN; + + tvis.item.pszText = sfi.szDisplayName; + tvis.item.iImage = sfi.iIcon; + tvis.item.iSelectedImage = sfi.iIcon; + + if (sfi.dwAttributes & SFGAO_HASSUBFOLDER) + tvis.item.cChildren = TRUE; + + hItem = __super::InsertItem(&tvis); + + Exit0: + + return hItem; + } + + struct __InsertItemWParam + { + HTREEITEM hParent; + LPTSTR lpszText; + int nImage; + BOOL bHasSubFolder; +// BOOL bCheck; + LPCTSTR lpszPath; + }; + + static BOOL _InsertItem(HWND hWndTree, HTREEITEM hParent, LPTSTR lpszText, int nImage, BOOL bHasSubFolder/*, BOOL bCheck*/, LPCTSTR lpszPath = NULL) + { + BOOL bRet = FALSE; + __InsertItemWParam wParam; + + wParam.hParent = hParent; + wParam.lpszText = lpszText; + wParam.nImage = nImage; + wParam.bHasSubFolder = bHasSubFolder; +// wParam.bCheck = bCheck; + wParam.lpszPath = lpszPath; + + if (::IsWindow(hWndTree)) + bRet = ::SendMessage(hWndTree, MSG_BKFBC_INSERT_ITEM, (WPARAM)&wParam, 0); + + return bRet; + } + + static DWORD WINAPI _ExpandDrivesThreadProc(LPVOID lpParam) + { + CBkFolderBrowseCtrl *pThis = (CBkFolderBrowseCtrl *)(lpParam); + + CIidl iidlDrives(CSIDL_DRIVES); + + _InsertDrives(pThis->m_hWnd, pThis->m_hItemMyComputer, iidlDrives); + + return TRUE; + } + + static BOOL _InsertDrives(HWND hWnd, HTREEITEM hParent, LPITEMIDLIST pidlParent) + { + CIidl iidlParent, iidlChild, iidlFull; + + iidlParent.Attach(pidlParent); + + IShellFolder *piFolder = iidlParent.GetShellFolder(); + if (NULL == piFolder) + goto Exit0; + + IEnumIDList *piEnum = NULL; + HRESULT hRet = piFolder->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN, &piEnum); + if (FAILED(hRet)) + goto Exit0; + + while (TRUE) + { + hRet = piEnum->Next(1, iidlChild, NULL); + if (S_OK != hRet) + break; + + iidlFull = iidlParent.Append(iidlChild); + + SHFILEINFO sfi; + DWORD_PTR dwRet = ::SHGetFileInfo( + (LPCTSTR)(LPITEMIDLIST)iidlFull, + 0, + &sfi, + sizeof(SHFILEINFO), + /*SHGFI_ICON | */SHGFI_SMALLICON | SHGFI_PIDL | SHGFI_ATTRIBUTES | SHGFI_DISPLAYNAME | SHGFI_SYSICONINDEX); + + if (0 == dwRet) + continue; + + if (SFGAO_FILESYSTEM == (SFGAO_FILESYSTEM & sfi.dwAttributes)) + { + CString strPath; + + BOOL bRet = ::SHGetPathFromIDList(iidlFull, strPath.GetBuffer(MAX_PATH + 1)); + if (bRet) + { + strPath.ReleaseBuffer(); + strPath.TrimRight(L'\\'); + } + else + strPath.ReleaseBuffer(0); + + _InsertItem( + hWnd, hParent, sfi.szDisplayName, sfi.iIcon, + SFGAO_HASSUBFOLDER == (sfi.dwAttributes & SFGAO_HASSUBFOLDER), + /*FALSE, */strPath); + +/* + TVINSERTSTRUCT tvis; + + ZeroMemory(&tvis, sizeof(tvis)); + + tvis.hParent = hParent; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN; + + tvis.item.pszText = sfi.szDisplayName; + tvis.item.iImage = sfi.iIcon; + tvis.item.iSelectedImage = sfi.iIcon; + + if (sfi.dwAttributes & SFGAO_HASSUBFOLDER) + tvis.item.cChildren = TRUE; + + HTREEITEM hItem = __super::InsertItem(&tvis); + m_mapItemToPath[hItem] = strPath; +*/ + + } + } + +Exit0: + + if (piEnum) + { + piEnum->Release(); + piEnum = NULL; + } + + if (piFolder) + { + piFolder->Release(); + piFolder = NULL; + } + + iidlParent.Detach(); + + return TRUE; + } + + static BOOL _InsertSubFolders(HWND hWnd, HTREEITEM hParent, LPCTSTR lpszPath, BOOL bCheck) + { + SHFILEINFOW sfi = {0}; + DWORD_PTR dwRet = 0; + + WIN32_FIND_DATA findData; + HANDLE hFind = INVALID_HANDLE_VALUE; + + CString strPath = lpszPath, strFileName; + + if (strPath[strPath.GetLength() - 1] != L'\\') + strPath += L'\\'; + + hFind = ::FindFirstFile(strPath + L"*.*", &findData); + if (hFind) + { + do + { + if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) + continue; + + if (L'.' == findData.cFileName[0] && (L'\0' == findData.cFileName[1] || (L'.' == findData.cFileName[1] && L'\0' == findData.cFileName[2]))) + continue; + + strFileName = strPath + findData.cFileName; + + dwRet = ::SHGetFileInfo( + strFileName, + INVALID_FILE_ATTRIBUTES, + &sfi, + sizeof(sfi), + SHGFI_ATTRIBUTES | SHGFI_DISPLAYNAME | SHGFI_SYSICONINDEX); + + if (0 == dwRet || (SFGAO_LINK == (sfi.dwAttributes & SFGAO_LINK))) + continue; + +// TVINSERTSTRUCT tvis; +// ZeroMemory(&tvis, sizeof(tvis)); +// +// tvis.hParent = hParent; +// tvis.hInsertAfter = TVI_LAST; +// tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_STATE; +// tvis.item.pszText = findData.cFileName;//sfi.szDisplayName; +// tvis.item.iImage = sfi.iIcon; +// tvis.item.iSelectedImage = sfi.iIcon; +// tvis.item.state = INDEXTOSTATEIMAGEMASK(bCheck ? CHECK_STATE_CHECKED : CHECK_STATE_UNCHECKED); +// tvis.item.stateMask = TVIS_STATEIMAGEMASK; +// +// if (sfi.dwAttributes & SFGAO_HASSUBFOLDER) +// tvis.item.cChildren = TRUE; +// +// InsertItem(&tvis); + + _InsertItem( + hWnd, hParent, findData.cFileName, sfi.iIcon, + SFGAO_HASSUBFOLDER == (sfi.dwAttributes & SFGAO_HASSUBFOLDER) + /*, bCheck*/); + + } while (::FindNextFile(hFind, &findData)); + + ::FindClose(hFind); + hFind = INVALID_HANDLE_VALUE; + } + + return TRUE; + } + + static BOOL _Expand(HWND hWnd, HTREEITEM hItem, LPCTSTR lpszFullPath, BOOL bCheck) + { + //__super::Expand(hItem, nCode); +// CString strFullPath; +// +// BOOL bRet = _GetFullPath(hItem, strFullPath); +// if (!bRet) +// return FALSE; + + BOOL bRet = FALSE; + + if (::IsWindow(hWnd)) + { + TVITEM item = { 0 }; + item.hItem = hItem; + item.mask = TVIF_STATE; + item.pszText = NULL; + item.iImage = 0; + item.iSelectedImage = 0; + item.state = TVIS_EXPANDED | TVIS_EXPANDEDONCE; + item.stateMask = TVIS_EXPANDED | TVIS_EXPANDEDONCE; + item.lParam = NULL; + + ::SendMessage(hWnd, TVM_SETITEM, 0, (LPARAM)&item); + + bRet = _InsertSubFolders(hWnd, hItem, lpszFullPath, bCheck); + } + + return bRet; + } + + BOOL _GetFullPath(HTREEITEM hItem, CString& strFullPath) + { + CString strPath; + strFullPath.Empty(); + + while (TVI_ROOT != hItem) + { + const __MapItemToPath::CPair *pPair = m_mapItemToPath.Lookup(hItem); + + if (NULL != pPair) + { + strFullPath = pPair->m_value + L'\\' + strFullPath; + return TRUE; + } + + GetItemText(hItem, strPath); + + if (strFullPath.IsEmpty()) + strFullPath = strPath; + else + strFullPath = strPath + L'\\' + strFullPath; + + hItem = GetParentItem(hItem); + } + + return FALSE; + } + + static DWORD WINAPI _ExpandThreadProc(LPVOID lpParam) + { + __EXPAND_THREAD_PARAM *pThreadParam; + + pThreadParam = (__EXPAND_THREAD_PARAM *)lpParam; + +// CBkFolderBrowseCtrl *pThis = (CBkFolderBrowseCtrl *)(pThreadParam->pThis); + + _Expand(pThreadParam->hWnd, pThreadParam->hItem, pThreadParam->strFullPath, pThreadParam->bCheck); + + delete pThreadParam; + + return TRUE; + } + + void OnDestroy() + { + _Uninit(); + + SetMsgHandled(FALSE); + } + + LRESULT OnTVNItemExpanding(int n, LPNMHDR pnmh, BOOL &bHandled) + { + LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)pnmh; + + if (TVE_COLLAPSE == pnmtv->action) + return FALSE; + + return Expand(pnmtv->itemNew.hItem, pnmtv->action); + } + + LRESULT OnBkFBCInsertItem(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam) + { + __InsertItemWParam *pwParam = (__InsertItemWParam *)wParam; + + if (NULL == pwParam) + return FALSE; + + TVINSERTSTRUCT tvis; + + ZeroMemory(&tvis, sizeof(tvis)); + + tvis.hParent = pwParam->hParent; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_STATE; + tvis.item.state = INDEXTOSTATEIMAGEMASK(GetCheckState(pwParam->hParent) ? CHECK_STATE_CHECKED : CHECK_STATE_UNCHECKED); + tvis.item.stateMask = TVIS_STATEIMAGEMASK; + tvis.item.pszText = pwParam->lpszText; + tvis.item.iImage = pwParam->nImage; + tvis.item.iSelectedImage = pwParam->nImage; + tvis.item.cChildren = pwParam->bHasSubFolder; + + HTREEITEM hItem = __super::InsertItem(&tvis); + + if (pwParam->lpszPath) + m_mapItemToPath[hItem] = pwParam->lpszPath; + + return TRUE; + } + +public: + + BEGIN_MSG_MAP_EX(CBkFolderBrowseCtrl) + CHAIN_MSG_MAP(CWH3StateCheckTreeCtrl) + MSG_WM_DESTROY(OnDestroy) + MESSAGE_HANDLER_EX(MSG_BKFBC_INSERT_ITEM, OnBkFBCInsertItem) + REFLECTED_NOTIFY_CODE_HANDLER(TVN_ITEMEXPANDING, OnTVNItemExpanding) + DEFAULT_REFLECTION_HANDLER() + END_MSG_MAP() +}; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/wtlhelper/iidl.h b/Client/Client/GUI/BKWin/wtlhelper/iidl.h new file mode 100644 index 00000000..57e2bd6d --- /dev/null +++ b/Client/Client/GUI/BKWin/wtlhelper/iidl.h @@ -0,0 +1,214 @@ +#pragma once + +#include + +class CIidl +{ +public: + CIidl() + : m_pidl(NULL) + { + } + + CIidl(LPITEMIDLIST pidl) + : m_pidl(pidl) + { + } + + CIidl(CIidl& src) + : m_pidl(src.Clone()) + { + } + + CIidl(int nSpecialFolder) + { + ::SHGetSpecialFolderLocation(NULL, nSpecialFolder, &m_pidl); + } + + virtual ~CIidl() + { + Free(); + } + + void Free() + { + if (m_pidl) + { + ::CoTaskMemFree(m_pidl); + m_pidl = NULL; + } + } + + void Attach(LPITEMIDLIST pidl) + { + Free(); + + m_pidl = pidl; + } + + LPITEMIDLIST Detach() + { + LPITEMIDLIST pidl = m_pidl; + + m_pidl = NULL; + + return pidl; + } + + LPITEMIDLIST Clone() + { + int nSize = GetSize(); + + if (0 == nSize) + return NULL; + + LPITEMIDLIST pidlNew = (LPITEMIDLIST)::CoTaskMemAlloc(nSize + sizeof(USHORT)); + if (pidlNew == NULL) + return NULL; + + CopyMemory(pidlNew, m_pidl, nSize); + + *((USHORT *)(((LPBYTE)pidlNew) + nSize)) = 0; + + return pidlNew; + } + + int GetSize() + { + if(NULL == m_pidl) + return 0; + + int nSize = 0; + LPCITEMIDLIST pidl = m_pidl; + + while (pidl->mkid.cb) + { + nSize += pidl->mkid.cb; + pidl = (LPCITEMIDLIST)(((LPBYTE)pidl) + pidl->mkid.cb); + } + + return nSize; + } + + operator LPITEMIDLIST() + { + return m_pidl; + } + + operator LPCITEMIDLIST() + { + return m_pidl; + } + + operator LPITEMIDLIST*() + { + return &m_pidl; + } + + operator LPCITEMIDLIST*() + { + return (LPCITEMIDLIST*)&m_pidl; + } + + CIidl& operator=(LPITEMIDLIST pidl) + { + Attach(pidl); + + return *this; + } + + CIidl& operator=(CIidl& src) + { + Attach(src.Clone()); + + return *this; + } + + BOOL IsValid() + { + return NULL != m_pidl; + } + + IShellFolder* GetShellFolder() + { + if (!IsValid()) + return NULL; + + IShellFolder *piFolder = NULL; + IShellFolder *piDesktop = NULL; + + HRESULT hRet = ::SHGetDesktopFolder(&piDesktop); + if (FAILED(hRet)) + return NULL; + + piDesktop->BindToObject( + m_pidl, + NULL, + IID_IShellFolder, + (LPVOID *)&piFolder + ); + + piDesktop->Release(); + piDesktop = NULL; + + return piFolder; + } + + LPITEMIDLIST Append(LPITEMIDLIST pidl) + { + if (!IsValid()) + return NULL; + + CIidl iidl; + + iidl.Attach(pidl); + + int nThisSize = GetSize(); + int nSize = nThisSize + iidl.GetSize(); + + LPITEMIDLIST pidlNew = (LPITEMIDLIST)::CoTaskMemAlloc(nSize + sizeof(USHORT)); + if (pidlNew == NULL) + return NULL; + + CopyMemory(((LPBYTE)pidlNew), m_pidl, nThisSize); + CopyMemory(((LPBYTE)pidlNew) + nThisSize, pidl, iidl.GetSize()); + + *((USHORT *)(((LPBYTE) pidlNew) + nSize)) = 0; + + iidl.Detach(); + + return pidlNew; + } + +/* + LPITEMIDLIST MergeItemID(LPCITEMIDLIST pidl,...) + { + va_list marker; + int nSize = GetItemIDSize(pidl) + sizeof(pidl->mkid.cb); + LPITEMIDLIST p; + + // count size of pidl + va_start(marker,pidl); + while( p = va_arg(marker, LPITEMIDLIST) ) + nSize += GetItemIDSize(p); + va_end(marker); + // allocate and merge pidls + LPITEMIDLIST pidlNew = (LPITEMIDLIST)GetMalloc()->Alloc(nSize); + if(pidlNew == NULL) return NULL; + + va_start(marker,pidl); + CopyMemory(((LPBYTE)pidlNew), pidl, nSize = GetItemIDSize(pidl)); + while( p = va_arg(marker, LPITEMIDLIST) ) { + CopyMemory(((LPBYTE)pidlNew) + nSize, p, GetItemIDSize(p)); + nSize += p->mkid.cb; + } + va_end(marker); + *((USHORT *)(((LPBYTE) pidlNew) + nSize)) = 0; + return pidlNew; + } +*/ + +protected: + + LPITEMIDLIST m_pidl; +}; diff --git a/Client/Client/GUI/BKWin/wtlhelper/wh3statecheckimglst.h b/Client/Client/GUI/BKWin/wtlhelper/wh3statecheckimglst.h new file mode 100644 index 00000000..11ea1379 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtlhelper/wh3statecheckimglst.h @@ -0,0 +1,66 @@ +#pragma once + +#include "../bkwin/bkimage.h" + +class CWH3StateCheckImageList + : public CImageList +{ +public: + + BOOL Create(int cx = 16, int cy = 16) + { + BOOL bRet = CImageList::Create(cx, cy, ILC_COLOR24 | ILC_MASK, 0, 4); + + CBkImage img; + CDC dc, dcMem; + CBkCheckBoxTheme theme; + CRect rcCheckBox; + + int nThemeState[] = { + 0, + CBS_UNCHECKEDNORMAL, + CBS_CHECKEDNORMAL, + CBS_MIXEDNORMAL + }; + int nNoThemeState[] = { + 0, + DFCS_BUTTONCHECK | DFCS_TRANSPARENT, + DFCS_BUTTONCHECK | DFCS_TRANSPARENT | DFCS_CHECKED, + DFCS_BUTTONCHECK | DFCS_TRANSPARENT | DFCS_CHECKED | DFCS_BUTTON3STATE + }; + + HWND hWndDesktop = ::GetDesktopWindow(); + HDC hDCDesktop = ::GetDC(hWndDesktop); + + dcMem.CreateCompatibleDC(hDCDesktop); + img.CreateBitmap(cx * 4, cy, RGB(0xFF, 0, 0xFF)); + + HBITMAP hBmpOld = dcMem.SelectBitmap(img); + + ::ReleaseDC(hWndDesktop, hDCDesktop); + + theme.OpenTheme(hWndDesktop); + + for (int i = 1; i < 4; i ++) + { + rcCheckBox.SetRect(i * cx + (cx - 13) / 2, (cy - 13) / 2, i * cx + (cx + 13) / 2, (cy + 13) / 2); + + if (theme.IsValid()) + { + theme.DrawBackground(dcMem, nThemeState[i], rcCheckBox); + } + else + { + dcMem.DrawFrameControl(rcCheckBox, DFC_BUTTON, nNoThemeState[i]); + } + } + + dcMem.SelectBitmap(hBmpOld); + + Add(img, RGB(0xFF, 0, 0xFF)); + + img.DeleteObject(); + + return bRet; + } +}; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/wtlhelper/whthreadnotify.h b/Client/Client/GUI/BKWin/wtlhelper/whthreadnotify.h new file mode 100644 index 00000000..220e662b --- /dev/null +++ b/Client/Client/GUI/BKWin/wtlhelper/whthreadnotify.h @@ -0,0 +1,77 @@ +#pragma once + +template +class CThreadNotify +{ +public: + CThreadNotify() + : m_hEventStop(::CreateEvent(NULL, TRUE, FALSE, NULL)) + , m_hWndNotify(NULL) + , m_uMsgNotify(WM_NULL) + { + } + + virtual ~CThreadNotify() + { + if (m_hEventStop) + { + ::CloseHandle(m_hEventStop); + m_hEventStop = NULL; + } + } + + void Start(HWND hWnd, UINT uMsg) + { + m_hWndNotify = hWnd; + m_uMsgNotify = uMsg; + + HANDLE hThread = ::CreateThread(NULL, 0, _WorkThreadProc, this, 0, NULL); + ::CloseHandle(hThread); + } + + void Stop() + { + ::SetEvent(m_hEventStop); + } + + // Need Overide + // Return NeedNotify + void Work(BOOL &bNeedNotify, WPARAM& wParam, LPARAM& lParam) + { + ATLASSERT(FALSE); + } + +private: + + HANDLE m_hEventStop; + HWND m_hWndNotify; + UINT m_uMsgNotify; + +protected: + + static DWORD WINAPI _WorkThreadProc(LPVOID pvParam) + { + BOOL bNeedNotify = FALSE; + WPARAM wParam = 0; + LPARAM lParam = 0; + + T *pThis = (reinterpret_cast(pvParam)); + + while (TRUE) + { + pThis->Work(bNeedNotify, wParam, lParam); + + if (bNeedNotify && pThis->m_hWndNotify && ::IsWindow(pThis->m_hWndNotify)) + { + ::SendMessage(pThis->m_hWndNotify, pThis->m_uMsgNotify, wParam, lParam); + } + + DWORD dwRet = ::WaitForSingleObject(pThis->m_hEventStop, t_dwElapse); + if (WAIT_TIMEOUT != dwRet) + break; + } + + return 0; + } + +}; \ No newline at end of file diff --git a/Client/Client/GUI/BKWin/wtlhelper/whwindow.h b/Client/Client/GUI/BKWin/wtlhelper/whwindow.h new file mode 100644 index 00000000..240489d1 --- /dev/null +++ b/Client/Client/GUI/BKWin/wtlhelper/whwindow.h @@ -0,0 +1,1892 @@ +#pragma once + +#include "../bkwin/bkimage.h" +#include "../bkwin/bkskin.h" +#include "wh3statecheckimglst.h" + +////////////////////////////////////////////////////////////////////////// +// Cached Owner Draw Window Implement +////////////////////////////////////////////////////////////////////////// + +template +class CWHCachedOwnerDrawWindowImpl +{ +protected: + CWHCachedOwnerDrawWindowImpl() + : m_bNeedRedraw(TRUE) + { + } + + virtual ~CWHCachedOwnerDrawWindowImpl() + { + if (!m_imgCache.IsNull()) + m_imgCache.DeleteObject(); + } + + BOOL m_bNeedRedraw; + CBkImage m_imgCache; + + void OnSize(UINT nType, CSize size) + { + SetMsgHandled(FALSE); + + if (nType == SIZE_MINIMIZED) + return; + + if (!m_imgCache.IsNull()) + m_imgCache.DeleteObject(); + + m_imgCache.CreateBitmap(size.cx, size.cy); + + NeedRedraw(); + } + + void OnPaint(CDCHandle /*dc*/) + { + CPaintDC dc(static_cast(this)->m_hWnd); + + if (m_bNeedRedraw) + { + CDC dcMem; + + dcMem.CreateCompatibleDC(dc); + + HBITMAP hbmpOld = dcMem.SelectBitmap(m_imgCache); + + static_cast(this)->DoPaint((HDC)dcMem); + + dcMem.SelectBitmap(hbmpOld); + + m_bNeedRedraw = FALSE; + } + + m_imgCache.Draw(dc, 0, 0); + } + + BOOL OnEraseBkgnd(CDCHandle dc) + { + return TRUE; + } + +public: + + void NeedRedraw() + { + m_bNeedRedraw = TRUE; + static_cast(this)->Invalidate(FALSE); + } + + // Need Overide + void DoPaint(CDCHandle dc) + { + ATLASSERT(FALSE); + } + +public: + + BEGIN_MSG_MAP_EX(CWHCachedOwnerDrawWindowImpl) + MSG_WM_SIZE(OnSize) + MSG_WM_PAINT(OnPaint) + MSG_WM_ERASEBKGND(OnEraseBkgnd) + END_MSG_MAP() +}; + +////////////////////////////////////////////////////////////////////////// +// Resize Control Replacing Helper +////////////////////////////////////////////////////////////////////////// + +template +class CWHControlReplacingHelperImpl +{ +protected: + + void OnSize(UINT nType, CSize size) + { + SetMsgHandled(FALSE); + + if (nType == SIZE_MINIMIZED) + return; + + CRect rcClient; + + static_cast(this)->GetClientRect(rcClient); + + static_cast(this)->ReplacingControls(rcClient); + } + +public: + + // Need Overide + void ReplacingControls(CRect& rcClient) + { + ATLASSERT(FALSE); + } + + BEGIN_MSG_MAP_EX(CWHControlReplacingHelperImpl) + MSG_WM_SIZE(OnSize) + END_MSG_MAP() +}; + +#define BEGIN_REPLACING_CONTROLS() \ + void ReplacingControls(CRect& rcClient) \ + { \ + CWindow wndCtrl; \ + +#define REPLACING_CONTROL_BASE(id, x, y, cx, cy, method) \ + wndCtrl.Attach(::GetDlgItem(m_hWnd, id)); \ + wndCtrl.SetWindowPos( \ + NULL, x, y, cx, cy, \ + method | SWP_NOZORDER | SWP_NOACTIVATE); \ + wndCtrl.Detach(); \ + +#define END_REPLACING_CONTROLS() \ + } \ + +#define PARENT_WIDTH rcClient.Width() +#define PARENT_HEIGHT rcClient.Height() + +#define REPLACING_CONTROL(id, x, y, cx, cy) \ + REPLACING_CONTROL_BASE(id, x, y, cx, cy, 0) \ + +#define REPLACING_CONTROL_POSITON(id, x, y) \ + REPLACING_CONTROL_BASE(id, x, y, 0, 0, SWP_NOSIZE) \ + +////////////////////////////////////////////////////////////////////////// +// Skined Button Control +////////////////////////////////////////////////////////////////////////// + +class CWHSkinedButton + : public CWindowImpl + , public COwnerDraw +{ +public: + CWHSkinedButton() + : m_bTracking(FALSE) + , m_bPushed(FALSE) + , m_bHorzExtend(FALSE) + , m_lHorzExSkinLeft(0) + , m_crText(CLR_INVALID) + { + + } + + BOOL SubclassWindow(HWND hWnd) + { + BOOL bRet = __super::SubclassWindow(hWnd); + if (bRet) + CWindow::ModifyStyle(0, BS_OWNERDRAW); + + return bRet; + } + + void SetSkin(HBITMAP hbmpSkin, BOOL bSingle = FALSE, BOOL bHasDisable = FALSE, COLORREF crText = CLR_INVALID, BOOL bAutoResize = TRUE) + { + m_imgSkin.Attach(hbmpSkin); + + if (m_imgSkin.IsNull()) + return; + + m_imgSkin.SetTransparentMode(CBkImage::ModeMaskColor); + + SIZE sizeImg; + + m_imgSkin.GetImageSize(sizeImg); + + if (!bSingle) + sizeImg.cx /= bHasDisable ? 4 : 3; + + m_imgSkin.SetSubImageWidth(sizeImg.cx); + + if (bAutoResize) + ResizeClient(sizeImg.cx, sizeImg.cy); + + m_bHorzExtend = FALSE; + m_crText = crText; + } + + void SetHorzExtendSkin(HBITMAP hbmpSkin, LONG lHorzExSkinLeft, BOOL bSingle = FALSE, BOOL bHasDisable = FALSE, COLORREF crText = CLR_INVALID, BOOL bAutoResize = TRUE) + { + SetSkin(hbmpSkin, bSingle, bHasDisable, crText, FALSE); + + m_lHorzExSkinLeft = lHorzExSkinLeft; + + if (bAutoResize) + { + SIZE sizeImg; + + m_imgSkin.GetImageSize(sizeImg); + + if (!bSingle) + sizeImg.cx /= bHasDisable ? 4 : 3; + + CRect rcBtn; + GetWindowRect(rcBtn); + + ResizeClient(rcBtn.Width(), sizeImg.cy); + } + + m_bHorzExtend = TRUE; + } + + void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) + { + int nSubImage = -1; + CRect rcBtn = lpDrawItemStruct->rcItem; + CDCHandle dc; + + dc.Attach(lpDrawItemStruct->hDC); + + if (m_bTracking) + { + if (m_bPushed) + nSubImage = 2; + else + nSubImage = 1; + } + else + { + nSubImage = 0; + } + + if (m_bHorzExtend) + { + CBkSkinBase::HorzExtendDraw(dc, m_imgSkin, rcBtn, m_lHorzExSkinLeft, nSubImage); + } + else + { + m_imgSkin.Draw(lpDrawItemStruct->hDC, 0, 0, nSubImage); + } + + if (CLR_INVALID != m_crText) + { + CString strText; + + GetWindowText(strText); + + dc.SetBkMode(TRANSPARENT); + + HFONT hftOld = dc.SelectFont(BkFontPool::GetFont(BKF_DEFAULTFONT)); + COLORREF crOld = dc.SetTextColor(m_crText); + dc.DrawText(strText, strText.GetLength(), rcBtn, DT_SINGLELINE | DT_CENTER | DT_VCENTER); + dc.SelectFont(hftOld); + dc.SetTextColor(crOld); + } + } + +protected: + + void OnLButtonDown(UINT nFlags, CPoint point) + { + SetCapture(); + + m_bPushed = TRUE; + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + + void OnLButtonUp(UINT nFlags, CPoint point) + { + ReleaseCapture(); + + m_bPushed = FALSE; + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + if (m_bTracking) + GetParent().SendMessage(WM_COMMAND, GetDlgCtrlID(), (LPARAM)m_hWnd); + } + + void OnMouseMove(UINT nFlags, CPoint point) + { + CRect rcBtn; + + GetClientRect(rcBtn); + + BOOL bTracking = rcBtn.PtInRect(point); + + if (bTracking != m_bTracking) + { + m_bPushed = ((MK_LBUTTON & nFlags) == MK_LBUTTON); + m_bTracking = bTracking; + + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(tme); + tme.hwndTrack = m_hWnd; + tme.dwFlags = TME_LEAVE; + tme.dwHoverTime = 0; + _TrackMouseEvent(&tme); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + } + + void OnMouseLeave() + { + if (m_bTracking) + { + m_bTracking = FALSE; + m_bPushed = FALSE; + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + } + + BOOL OnSetCursor(CWindow /*wnd*/, UINT /*nHitTest*/, UINT /*message*/) + { + SetCursor(::LoadCursor(NULL, IDC_HAND)); + + return TRUE; + } + + CBkImage m_imgSkin; + BOOL m_bTracking; + BOOL m_bPushed; + + BOOL m_bHorzExtend; + LONG m_lHorzExSkinLeft; + COLORREF m_crText; + + BEGIN_MSG_MAP_EX(CWHSkinedButton) + MSG_WM_LBUTTONDOWN(OnLButtonDown) + MSG_WM_LBUTTONUP(OnLButtonUp) + MSG_WM_MOUSEMOVE(OnMouseMove) + MSG_WM_MOUSELEAVE(OnMouseLeave) + MSG_WM_SETCURSOR(OnSetCursor) + CHAIN_MSG_MAP_ALT(COwnerDraw, 1) + DEFAULT_REFLECTION_HANDLER() + END_MSG_MAP() +}; + +template +class CWHRoundRectFrameHelper +{ +protected: + + SIZE m_sizeWnd; + + void OnSize(UINT nType, CSize size) + { + T *pT = static_cast(this); + + if (nType == SIZE_MINIMIZED) + return; + + if (size == m_sizeWnd) + return; + + CRect rcWindow, rcClient; + CRgn rgnWindow, rgnMinus, rgnAdd; + + pT->GetWindowRect(rcWindow); + pT->GetClientRect(rcClient); + pT->ClientToScreen(rcClient); + + rcClient.OffsetRect(- rcWindow.TopLeft()); + + rgnWindow.CreateRectRgn(rcClient.left, rcClient.top + 2, rcClient.right, rcClient.bottom - 2); + rgnAdd.CreateRectRgn(rcClient.left + 2, rcClient.top, rcClient.right - 2, rcClient.top + 1); + rgnWindow.CombineRgn(rgnAdd, RGN_OR); + rgnAdd.OffsetRgn(0, rcClient.Height() - 1); + rgnWindow.CombineRgn(rgnAdd, RGN_OR); + rgnAdd.SetRectRgn(rcClient.left + 1, rcClient.top + 1, rcClient.right - 1, rcClient.top + 2); + rgnWindow.CombineRgn(rgnAdd, RGN_OR); + rgnAdd.OffsetRgn(0, rcClient.Height() - 3); + rgnWindow.CombineRgn(rgnAdd, RGN_OR); +// rgnAdd.OffsetRgn(0, rcClient.Height()); +// rgnWindow.CombineRgn(rgnAdd, RGN_OR); + +// rgnMinus.CreateRectRgn(rcClient.left, rcClient.top, rcClient.left + 2, rcClient.top + 1); +// rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); +// rgnMinus.OffsetRgn(rcClient.Width() - 2, 0); +// rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); +// rgnMinus.OffsetRgn(0, rcClient.Height() - 1); +// rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); +// rgnMinus.OffsetRgn(3 - rcClient.Width(), 0); +// rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); +// +// rgnMinus.SetRectRgn(rcClient.left, rcClient.top, rcClient.left + 1, rcClient.top + 2); +// rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); +// rgnMinus.OffsetRgn(rcClient.Width() - 1, 0); +// rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); +// rgnMinus.OffsetRgn(0, rcClient.Height() - 2); +// rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); +// rgnMinus.OffsetRgn(1 - rcClient.Width(), 0); +// rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); + + pT->SetWindowRgn(rgnWindow); + + m_sizeWnd = size; + } + +public: + + BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) + { + BOOL bHandled = TRUE; + + switch(dwMsgMapID) + { + case 0: + if (uMsg == WM_SIZE) + { + OnSize((UINT)wParam, _WTYPES_NS::CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); + lResult = 0; + } + break; + } + return FALSE; + } +}; + +template +class CWHRoundRectDialog + : public T + , public CWHRoundRectFrameHelper> +{ +public: + BEGIN_MSG_MAP_EX(CWHRoundRectDialog) + CHAIN_MSG_MAP(CWHRoundRectFrameHelper>) + CHAIN_MSG_MAP(T) + END_MSG_MAP() +}; + +template +class CWHDragMoveDlgHelper +{ +protected: + +public: + + BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) + { + BOOL bHandled = TRUE; + + switch(dwMsgMapID) + { + case 0: + if (uMsg == WM_LBUTTONDOWN) + { + T *pT = static_cast(this); + + if (0 == (pT->GetStyle() & (WS_MAXIMIZE | WS_MINIMIZE))) + pT->SendMessage(WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0); + + pT->SetMsgHandled(TRUE); + } + break; + } + return FALSE; + } +}; + +class CWHHeaderCtrl + : public CWindowImpl +{ +public: + ~CWHHeaderCtrl() + { + for(int i = m_iSortUp; i <= m_iSortDown; i++) + { + if(!m_bmSort[i].IsNull()) + m_bmSort[i].DeleteObject(); + } + } + + typedef struct _FRG_PARAM + { + LONG lOffset; + COLORREF crColor; + } FRG_PARAM; + + void FrameRect(HDC hDC, RECT rect, COLORREF crColor) + { + HBRUSH hBrush = ::CreateSolidBrush(crColor); + + ::FrameRect(hDC, &rect, hBrush); + + ::DeleteObject(hBrush); + } + + void Line(HDC hDC, int x1, int y1, int x2, int y2, COLORREF crColor) + { + HPEN hPen = ::CreatePen(PS_SOLID, 1, crColor), hOldPen = NULL; + + hOldPen = (HPEN)::SelectObject(hDC, hPen); + + ::MoveToEx(hDC, x1, y1, NULL); + ::LineTo(hDC, x2, y2); + + ::SelectObject(hDC, hOldPen); + + ::DeleteObject(hPen); + } + + void GradientFillRectV(HDC hdc, CRect rcFill, FRG_PARAM params[], int nCount) + { + GRADIENT_RECT gRect = {0, 1}; + TRIVERTEX vert[2] = { + {rcFill.left, rcFill.top, 0, 0, 0, 0}, + {rcFill.right, rcFill.top, 0, 0, 0, 0} + }; + int i = 0; + + for (i = 1; i < nCount && vert[0].y <= rcFill.bottom; i ++) + { + vert[0].y = vert[1].y; + vert[1].y += params[i].lOffset; + vert[0].Red = GetRValue(params[i - 1].crColor) << 8; + vert[0].Green = GetGValue(params[i - 1].crColor) << 8; + vert[0].Blue = GetBValue(params[i - 1].crColor) << 8; + vert[1].Red = GetRValue(params[i].crColor) << 8; + vert[1].Green = GetGValue(params[i].crColor) << 8; + vert[1].Blue = GetBValue(params[i].crColor) << 8; + CBkSkinBase::GradientFill2(hdc, vert, 2, &gRect, 1, GRADIENT_FILL_RECT_V); + } + } + + void DrawHeaderBg(HDC hdc, CRect rcRect) + { + FRG_PARAM frgHeaderBg[2] = { + {0, RGB(242, 247, 252)}, + {21, RGB(231, 235, 242)}, + }; + + rcRect.bottom --; + + FrameRect(hdc, rcRect, RGB(0xFF, 0xFF, 0xFF)); + Line(hdc, rcRect.left, rcRect.bottom, rcRect.right, rcRect.bottom, RGB(195, 195, 195)); + + rcRect.DeflateRect(1, 1); + + GradientFillRectV(hdc, rcRect, frgHeaderBg, 2); + } + + void OnPaint(CDCHandle /*dc*/) + { + CPaintDC dc(m_hWnd); + CRect rcClient, rcItem; + int nItems = GetItemCount(); + HFONT hftOld = NULL; + TCHAR szText[MAX_PATH] = {0}; + HDITEM hditem = {0}; + UINT uFormat = DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS; + + GetClientRect(&rcClient); + rcClient.InflateRect(1, 0); + + dc.SetBkMode(TRANSPARENT); + + DrawHeaderBg(dc, rcClient); + + hftOld = dc.SelectFont(BkFontPool::GetFont(BKF_DEFAULTFONT)); + dc.SetTextColor(RGB(0, 0, 0)); + uFormat |= DT_CENTER; + + for (int i = 0; i < nItems; i++) + { + hditem.mask = HDI_TEXT | HDI_FORMAT; + hditem.pszText = szText; + hditem.cchTextMax = sizeof(szText); + + if (!GetItem(i, &hditem)) + continue; + + if (!GetItemRect(i, rcItem)) + continue; + + Line(dc, rcItem.right - 1, rcItem.top + 2, rcItem.right - 1, rcItem.bottom - 3, RGB(195, 195, 195)); + Line(dc, rcItem.right, rcItem.top + 2, rcItem.right, rcItem.bottom - 3, RGB(255, 255, 255)); + + rcItem.DeflateRect(5, 0); + if (rcItem.left < rcItem.right) + dc.DrawText(szText, (int)_tcslen(szText), &rcItem, uFormat); + + if (HDF_SORTDOWN == (hditem.fmt & HDF_SORTDOWN) && rcItem.Width() > 11) + { + CreateSortBitmaps(); + m_bmSort[m_iSortDown].Draw(dc, rcItem.right - 11, rcItem.top + (rcItem.Height() - 15) / 2); + } + else if (HDF_SORTUP == (hditem.fmt & HDF_SORTUP) && rcItem.Width() > 11) + { + CreateSortBitmaps(); + m_bmSort[m_iSortUp].Draw(dc, rcItem.right - 11, rcItem.top + (rcItem.Height() - 15) / 2); + } + } + + dc.SelectFont(hftOld); + } + + enum + { + m_iSortUp = 0, // index of sort bitmaps + m_iSortDown = 1, + m_nShellSortUpID = 133 + }; + + CBkImage m_bmSort[2]; + + void CreateSortBitmaps() + { + bool bFree = false; + LPCTSTR pszModule = _T("shell32.dll"); + HINSTANCE hShell = ::GetModuleHandle(pszModule); + + if (hShell == NULL) + { + hShell = ::LoadLibrary(pszModule); + bFree = true; + } + + if (hShell != NULL) + { + bool bSuccess = true; + for(int i = m_iSortUp; i <= m_iSortDown; i++) + { + if(!m_bmSort[i].IsNull()) + continue; + m_bmSort[i] = (HBITMAP)::LoadImage(hShell, MAKEINTRESOURCE(m_nShellSortUpID + i), + IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); + if(m_bmSort[i].IsNull()) + { + bSuccess = false; + break; + } + m_bmSort[i].SetTransparentMode(CBkImage::ModeMaskColor); + m_bmSort[i].SetMaskColor(::GetSysColor(COLOR_3DFACE)); + } + if(bFree) + ::FreeLibrary(hShell); + if(bSuccess) + return; + } + } + + LRESULT OnLayout(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + LRESULT lResult = 0L; + LPHDLAYOUT pLayOut = (LPHDLAYOUT)lParam; + RECT& rect = *(pLayOut->prc); + WINDOWPOS& pos = *(pLayOut->pwpos); + + lResult = DefWindowProc(HDM_LAYOUT, wParam, lParam); + + pos.cy = 24; + rect.top = 24; + + return lResult; + } + + void OnLButtonDblClk(UINT nFlags, CPoint point) + { + Invalidate(); + + SetMsgHandled(FALSE); + } + +protected: + + BEGIN_MSG_MAP_EX(CWHHeaderCtrl) + MSG_WM_PAINT(OnPaint) + MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk) + MESSAGE_HANDLER_EX(HDM_LAYOUT, OnLayout) + END_MSG_MAP() +}; + +#define WHLVN_ITEMSORT (LVN_LAST - 1) + +typedef struct tagWHLVNITEMSORT +{ + NMHDR hdr; + int nCol; + BOOL bDescending; +} WHLVNITEMSORT, *LPWHLVNITEMSORT; + +class CWHListViewCtrl + : public CWindowImpl> + , public CCustomDraw +{ +public: + CWHListViewCtrl() + : m_nSortColumn(-1) + , m_bSortDescending(FALSE) + , m_nItemHeight(20) + { + } + + HWND Create( + HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, + DWORD dwStyle = 0, DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, + LPVOID lpCreateParam = NULL) + { + HWND hWnd = __super::Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam); + + if (!hWnd) + return NULL; + + SetExtendedListViewStyle(LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); + + m_imglstCheck.Create(); + + SetItemHeight(); + + ShowCheckBox(FALSE); + + SetFont(BkFontPool::GetFont(BKF_DEFAULTFONT), FALSE); + + if (0 == (dwStyle & LVS_NOCOLUMNHEADER)) + m_hdrListVirus.SubclassWindow(GetHeader()); + + return hWnd; + } + + void SetItemHeight(int nHeight = 0) + { + CImageList imglst; + + imglst.Create(max(1, m_imgList.GetSubImageWidth()), nHeight ? nHeight : m_nItemHeight, ILC_COLOR24, 0, 1); + + __super::SetImageList(imglst, LVSIL_SMALL); + __super::SetImageList(NULL, LVSIL_SMALL); + + imglst.Destroy(); + + if (nHeight) + m_nItemHeight = nHeight; + } + + void ShowCheckBox(BOOL bShow) + { + if (bShow) + { + SetExtendedListViewStyle(LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); + __super::SetImageList(m_imglstCheck, LVSIL_STATE); + + } + else + { + __super::SetImageList(NULL, LVSIL_STATE); + SetExtendedListViewStyle(0, LVS_EX_CHECKBOXES); + } + } + + BOOL GetCheckState(int nItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + + if (LVS_OWNERDATA == (LVS_OWNERDATA & GetStyle())) + { + if (nItem >= GetItemCount() || nItem < 0) + return FALSE; + + if (nItem >= (int)m_arrItemCheck.GetCount()) + return FALSE; + + return (2 == m_arrItemCheck[nItem]); + } + else + return __super::GetCheckState(nItem); + } + + BOOL SetCheckState(int nItem, BOOL bCheck, BOOL bForce = FALSE, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + + if (LVS_OWNERDATA == (LVS_OWNERDATA & GetStyle())) + { + if (nItem >= GetItemCount() || nItem < 0) + return FALSE; + + if (nItem >= (int)m_arrItemCheck.GetCount()) + m_arrItemCheck.SetCount(GetItemCount()); + + if (bForce || 0 != m_arrItemCheck[nItem]) + { + m_arrItemCheck[nItem] = bCheck ? 2 : 1; + + if (bRedraw) + RedrawItems(nItem, nItem); + } + + return TRUE; + } + else + return __super::SetCheckState(nItem, bCheck); + } + + BOOL DisableItemCheck(int nItem, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + + if (LVS_OWNERDATA == (LVS_OWNERDATA & GetStyle())) + { + if (nItem >= GetItemCount() || nItem < 0) + return FALSE; + + if (nItem >= (int)m_arrItemCheck.GetCount()) + m_arrItemCheck.SetCount(GetItemCount()); + + m_arrItemCheck[nItem] = 0; + + if (bRedraw) + RedrawItems(nItem, nItem); + + return TRUE; + } + else + return __super::SetItemState(nItem, INDEXTOSTATEIMAGEMASK(0), LVIS_STATEIMAGEMASK); + } + + BOOL IsItemCheckDisabled(int nItem) + { + ATLASSERT(::IsWindow(m_hWnd)); + + if (LVS_OWNERDATA == (LVS_OWNERDATA & GetStyle())) + { + if (nItem >= GetItemCount()) + return FALSE; + + if (nItem >= (int)m_arrItemCheck.GetCount()) + m_arrItemCheck.SetCount(GetItemCount()); + + return 0 == m_arrItemCheck[nItem]; + } + else + return 0 == (__super::GetItemState(nItem, LVIS_STATEIMAGEMASK) >> 12); + } + + BOOL IsAllItemChecked() + { + ATLASSERT(::IsWindow(m_hWnd)); + + int nCount = GetItemCount(); + BOOL bAllCheck = TRUE; + + for (int i = 0; i < nCount; i ++) + { + if (!IsItemCheckDisabled(i)) + bAllCheck &= GetCheckState(i); + } + + return bAllCheck; + } + + BOOL IsAnyItemChecked() + { + ATLASSERT(::IsWindow(m_hWnd)); + + int nCount = GetItemCount(); + + for (int i = 0; i < nCount; i ++) + { + if (!IsItemCheckDisabled(i)) + { + if (GetCheckState(i)) + return TRUE; + } + } + + return FALSE; + } + + BOOL CheckAllItems(BOOL bCheck, BOOL bForce = FALSE, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + + int nCount = GetItemCount(); + + for (int i = 0; i < nCount; i ++) + SetCheckState(i, bCheck, bForce, bRedraw); + + return TRUE; + } + + void SetImageList(HBITMAP hImageList, int cx, COLORREF crMaskColor = RGB(0xFF, 0, 0xFF)) + { + m_imgList.Attach(hImageList); + m_imgList.SetTransparentMode(CBkImage::ModeMaskColor); + m_imgList.SetMaskColor(crMaskColor); + m_imgList.SetSubImageWidth(cx); + + SetItemHeight(); + } + + DWORD_PTR GetItemData(int nItem) const + { + ATLASSERT(::IsWindow(m_hWnd)); + + if (LVS_OWNERDATA == (LVS_OWNERDATA & GetStyle())) + { + if (nItem >= GetItemCount() || nItem < 0) + return 0; + + if (nItem >= (int)m_arrItemData.GetCount()) + return 0; + + return m_arrItemData[nItem]; + } + else + return __super::GetItemData(nItem); + } + + BOOL SetItemData(int nItem, DWORD_PTR dwData) + { + ATLASSERT(::IsWindow(m_hWnd)); + + if (LVS_OWNERDATA == (LVS_OWNERDATA & GetStyle())) + { + if (nItem >= GetItemCount() || nItem < 0) + return FALSE; + + if (nItem >= (int)m_arrItemData.GetCount()) + m_arrItemData.SetCount(GetItemCount()); + + m_arrItemData[nItem] = dwData; + + return TRUE; + } + else + return __super::SetItemData(nItem, dwData); + } + + BOOL OnSetCursor(CWindow wnd, UINT nHitTest, UINT message) + { + ::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW))); + + return TRUE; + } + + DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) + { + return CDRF_NOTIFYITEMDRAW; + } + + DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw) + { + LPNMLVCUSTOMDRAW lpcd = (LPNMLVCUSTOMDRAW)lpNMCustomDraw; + CRect rcItem, rcDraw; + CBkImage img; + WTL::CDC dc; + CString strText; + BOOL bEnabled = IsWindowEnabled(); + + GetItemRect((int)lpcd->nmcd.dwItemSpec, rcItem, LVIR_BOUNDS); + + img.CreateBitmap(rcItem.Width(), rcItem.Height()); + + dc.CreateCompatibleDC(lpcd->nmcd.hdc); + dc.SetWindowOrg(rcItem.TopLeft()); + + dc.SetBkMode(TRANSPARENT); + + if (!bEnabled) + dc.SetTextColor(RGB(0xAA, 0xAA, 0xAA)); + + HBITMAP hbmpOld = dc.SelectBitmap(img); + + // Draw Background +// COLORREF crBg = RGB(0xDD, 0xDD, 0xDD); +// if (bEnabled) +// crBg = ((lpcd->nmcd.dwItemSpec & 1) == 1) ? RGB(0xFA, 0xFA, 0xFA) : RGB(0xFF, 0xFF, 0xFF); + + COLORREF crBg = RGB(0xFF, 0xFF, 0xFF); + + if (LVIS_SELECTED == GetItemState((int)lpcd->nmcd.dwItemSpec, LVIS_SELECTED) && bEnabled) + crBg = RGB(0xB9, 0xDB, 0xFF); + + dc.FillSolidRect(rcItem, crBg); + + GetItemRect((int)lpcd->nmcd.dwItemSpec, rcDraw, LVIR_SELECTBOUNDS); + + //rcDraw = rcItem; + + if (LVS_EX_CHECKBOXES == (LVS_EX_CHECKBOXES & GetExtendedListViewStyle())) + { + UINT uCheck = IsItemCheckDisabled((int)lpcd->nmcd.dwItemSpec) ? 0 : (GetCheckState((int)lpcd->nmcd.dwItemSpec) ? 2 : 1); + + SIZE size; + CRect rcCheck = rcDraw; + + m_imglstCheck.GetIconSize(size); + + rcCheck.top += (rcDraw.Height() - size.cy) / 2; + rcCheck.left += 2; + + rcDraw.left += size.cx; + + m_imglstCheck.Draw(dc, uCheck, rcCheck.TopLeft(), ILD_TRANSPARENT); + } + + { + CPen penLine; + + penLine.CreatePen( + PS_SOLID, + 1, + RGB(0xEA, 0xEA, 0xEA) + ); + HPEN hpenOld = dc.SelectPen(penLine); + dc.MoveTo(rcItem.left, rcItem.bottom - 1); + dc.LineTo(rcItem.right, rcItem.bottom - 1); + dc.SelectPen(hpenOld); + } + +/* + if (LVIS_SELECTED == GetItemState((int)lpcd->nmcd.dwItemSpec, LVIS_SELECTED) && bEnabled) + { + CWHHeaderCtrl::FRG_PARAM frgSelBg[2] = { + {0, RGB(242, 247, 252)}, + {rcDraw.Height() - 2, RGB(231, 235, 242)}, + }; + CPen penFrame; + + penFrame.CreatePen( + PS_SOLID, + 1, + RGB(209, 214, 221) + ); + + HPEN hpenOld = dc.SelectPen(penFrame); + HBRUSH hbshOld = NULL, hbshNull = (HBRUSH)::GetStockObject(NULL_BRUSH); + + hbshOld = dc.SelectBrush(hbshNull); + + rcDraw.left ++; + dc.RoundRect(rcDraw, CPoint(2, 2)); + + rcDraw.DeflateRect(1, 1); + + m_hdrListVirus.GradientFillRectV(dc, rcDraw, frgSelBg, 2); + + dc.SelectBrush(hbshOld); + dc.SelectPen(hpenOld); + } +*/ + + if (!m_imgList.IsNull()) + { + LVITEM li = {LVIF_IMAGE, (int)lpcd->nmcd.dwItemSpec}; + if (GetItem(&li) && li.iImage != -1) + { + GetItemRect((int)lpcd->nmcd.dwItemSpec, rcDraw, LVIR_ICON); + SIZE sizeImg; + m_imgList.GetImageSize(sizeImg); + m_imgList.Draw(dc, rcDraw.left - 2, rcDraw.top + (rcDraw.Height() - sizeImg.cy) / 2, li.iImage); + } + } + + // Draw Sub Items + + HFONT hftOld = dc.SelectFont(BkFontPool::GetFont(BKF_DEFAULTFONT)); + + for (int nSubItem = 0; nSubItem < GetHeader().GetItemCount(); nSubItem ++) + { + GetSubItemRect((int)lpcd->nmcd.dwItemSpec, nSubItem, LVIR_LABEL, rcDraw); + UINT uFormat = DT_SINGLELINE | DT_END_ELLIPSIS | DT_VCENTER; + + GetItemText((int)lpcd->nmcd.dwItemSpec, nSubItem, strText); + + LVCOLUMN colInfo = {LVCF_FMT}; + + GetColumn(nSubItem, &colInfo); + + if (colInfo.fmt & LVCFMT_CENTER) + uFormat |= DT_CENTER; + else if (colInfo.fmt & LVCFMT_RIGHT) + uFormat |= DT_RIGHT; + + dc.DrawText(strText, strText.GetLength(), rcDraw, uFormat); + } + + dc.SelectFont(hftOld); + dc.SelectBitmap(hbmpOld); + + img.Draw(lpcd->nmcd.hdc, rcItem.left, rcItem.top); + + img.DeleteObject(); + + return CDRF_SKIPDEFAULT; + } + + LRESULT OnLVNHeaderItemClick(LPNMHDR pnmh) + { + if (LVS_OWNERDATA == (LVS_OWNERDATA & GetStyle())) + { + LPNMHEADER p = (LPNMHEADER)pnmh; + if (p->iButton == 0) + { + int nOld = m_nSortColumn; + + WHLVNITEMSORT nms; + nms.hdr.code = WHLVN_ITEMSORT; + nms.hdr.hwndFrom = m_hWnd; + nms.hdr.idFrom = GetDlgCtrlID(); + nms.bDescending = (m_nSortColumn == p->iItem) ? !m_bSortDescending : FALSE; + nms.nCol = p->iItem; + + LRESULT lRet = ::SendMessage(GetParent(), WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + + if (lRet) + { + m_nSortColumn = p->iItem; + m_bSortDescending = nms.bDescending; + + HDITEM hdi = {HDI_FORMAT}; + m_hdrListVirus.GetItem(nOld, &hdi); + hdi.fmt &= ~(HDF_SORTDOWN | HDF_SORTUP); + m_hdrListVirus.SetItem(nOld, &hdi); + m_hdrListVirus.GetItem(m_nSortColumn, &hdi); + hdi.fmt |= m_bSortDescending ? HDF_SORTUP : HDF_SORTDOWN; + m_hdrListVirus.SetItem(m_nSortColumn, &hdi); + } + } + } + + SetMsgHandled(FALSE); + + return 0; + } + + BOOL OnEraseBkgnd(CDCHandle dc) + { + int nTop = GetTopIndex(); + int nBottom = nTop + GetCountPerPage(); + + nBottom = min(nBottom, GetItemCount() - 1); + + CRect rcClient, rcItemTop, rcItemBottom; + COLORREF crBg = IsWindowEnabled() ? RGB(0xFF, 0xFF, 0xFF) : RGB(0xDD, 0xDD, 0xDD); + + GetClientRect(rcClient); + GetItemRect(nTop, rcItemTop, LVIR_BOUNDS); + GetItemRect(nBottom, rcItemBottom, LVIR_BOUNDS); + + dc.FillSolidRect(rcItemBottom.right, rcItemTop.top, rcClient.right - rcItemBottom.right, rcClient.bottom - rcItemTop.top, crBg); + dc.FillSolidRect(rcClient.left, rcItemBottom.bottom, rcItemBottom.Width(), rcClient.bottom - rcItemBottom.bottom, crBg); + + return TRUE; + } + + LRESULT OnLVNKeyDown(LPNMHDR pnmh) + { + if (LVS_OWNERDATA == (LVS_OWNERDATA & GetStyle())) + { + LPNMLVKEYDOWN pnms = (LPNMLVKEYDOWN)pnmh; + + if (VK_SPACE == pnms->wVKey) + { + int nCurSel = GetSelectedIndex(); + if (-1 != nCurSel) + { + BOOL bCheck = !GetCheckState(nCurSel); + SetCheckState(nCurSel, bCheck); + _SendItemCheckStateChangedNotify(nCurSel, bCheck); + } + } + } + else + SetMsgHandled(FALSE); + + return 0; + } + + LRESULT OnNMClick(LPNMHDR pnmh) + { + if (LVS_OWNERDATA == (LVS_OWNERDATA & GetStyle())) + { + LPNMLISTVIEW pnms = (LPNMLISTVIEW)pnmh; + LVHITTESTINFO hitinfo; + + hitinfo.pt = pnms->ptAction; + + int nItem = HitTest(&hitinfo); + + if(nItem != -1) + { + if( (hitinfo.flags & LVHT_ONITEM) == LVHT_ONITEMSTATEICON) + { + BOOL bCheck = !GetCheckState(nItem); + SetCheckState(nItem, bCheck); + _SendItemCheckStateChangedNotify(nItem, bCheck); + } + } + } + else + SetMsgHandled(FALSE); + + return 0; + } + + void _SendItemCheckStateChangedNotify(int nItem, BOOL bCheck) + { + NMLISTVIEW nms = {0}; + + nms.hdr.idFrom = GetDlgCtrlID(); + nms.hdr.hwndFrom = m_hWnd; + nms.hdr.code = LVN_ITEMCHANGED; + + nms.iItem = nItem; + nms.iSubItem = 0; + nms.uOldState = INDEXTOSTATEIMAGEMASK(bCheck ? 1 : 2); + nms.uNewState = INDEXTOSTATEIMAGEMASK(bCheck ? 2 : 1); + + ::SendMessage(::GetParent(m_hWnd), WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); + } + +protected: + + CWHHeaderCtrl m_hdrListVirus; + CWH3StateCheckImageList m_imglstCheck; + CBkImage m_imgList; + int m_nSortColumn; + int m_nItemHeight; + BOOL m_bSortDescending; + CAtlArray m_arrItemData; + CAtlArray m_arrItemCheck; + + BEGIN_MSG_MAP_EX(CWHListViewCtrl) + MSG_WM_ERASEBKGND(OnEraseBkgnd) + MSG_WM_SETCURSOR(OnSetCursor) + NOTIFY_CODE_HANDLER_EX(HDN_ITEMCLICKA, OnLVNHeaderItemClick) + NOTIFY_CODE_HANDLER_EX(HDN_ITEMCLICKW, OnLVNHeaderItemClick) + REFLECTED_NOTIFY_CODE_HANDLER_EX(LVN_KEYDOWN, OnLVNKeyDown) + REFLECTED_NOTIFY_CODE_HANDLER_EX(NM_CLICK, OnNMClick) + REFLECTED_NOTIFY_CODE_HANDLER_EX(NM_DBLCLK, OnNMClick) + CHAIN_MSG_MAP_ALT(CCustomDraw, 1) + DEFAULT_REFLECTION_HANDLER() + END_MSG_MAP() +}; + +#define WHNM_TRAYICON 1 + +typedef struct _WHNMTRAYICON +{ + NMHDR hdr; + UINT uMsg; +} WHNMTRAYICON, *LPWHNMTRAYICON; + +class CWHTrayIcon + : public CWindowImpl +{ +public: + CWHTrayIcon() + { + } + + ~CWHTrayIcon() + { + if (IsWindow()) + DestroyWindow(); + } + + BOOL Create(HWND hWndNotify, UINT uID, UINT uIconResID) + { + if (!IsWindow()) + { + HWND hWnd = __super::Create(NULL, NULL, NULL, WS_POPUP); + if (NULL == hWnd) + return FALSE; + } + + NOTIFYICONDATA nid = {sizeof(NOTIFYICONDATA)}; + HICON hTray = ::LoadIcon((HINSTANCE)(&__ImageBase), MAKEINTRESOURCE(uIconResID)); + + nid.uFlags = NIF_ICON | NIF_MESSAGE; + nid.hIcon = hTray; + nid.hWnd = m_hWnd; + nid.uID = 0; + nid.uCallbackMessage = WM_APP; + + BOOL bRet = ::Shell_NotifyIcon(NIM_ADD, &nid); + + ::DestroyIcon(hTray); + + if (bRet) + { + m_hWndNotify = hWndNotify; + m_uID = uID; + m_uIconResID = uIconResID; + } + + return bRet; + } + + BOOL SetTip(LPCTSTR lpszTip) + { + NOTIFYICONDATA nid = {sizeof(NOTIFYICONDATA)}; + + nid.uFlags = NIF_TIP; + nid.hWnd = m_hWnd; + nid.uID = 0; + ::StrCpyN(nid.szTip, lpszTip, 63); + + return ::Shell_NotifyIcon(NIM_MODIFY, &nid); + } + + BOOL ShowBalloon(LPCTSTR lpszBalloonTitle,LPCTSTR lpszBalloonInfo,UINT uTimeout) + { + NOTIFYICONDATA IconData = {0}; + IconData.cbSize = sizeof(NOTIFYICONDATA); + IconData.hWnd = m_hWnd; + IconData.uID = 0; + IconData.uFlags = NIF_INFO; + + lstrcpy(IconData.szInfo, lpszBalloonInfo); + lstrcpy(IconData.szInfoTitle, lpszBalloonTitle); + IconData.uTimeout = uTimeout; + IconData.dwState = NIS_SHAREDICON; + IconData.dwStateMask = 0; + IconData.dwInfoFlags = NIIF_INFO; + + return Shell_NotifyIcon(NIM_MODIFY, &IconData); + } + + BOOL SetIcon(UINT uIconResID) + { + NOTIFYICONDATA nid = {sizeof(NOTIFYICONDATA)}; + HICON hTray = ::LoadIcon((HINSTANCE)(&__ImageBase), MAKEINTRESOURCE(uIconResID)); + + nid.uFlags = NIF_ICON; + nid.hIcon = hTray; + nid.hWnd = m_hWnd; + nid.uID = 0; + + BOOL bRet = ::Shell_NotifyIcon(NIM_MODIFY, &nid); + + ::DestroyIcon(hTray); + + return bRet; + } + + BOOL Destroy() + { + NOTIFYICONDATA nid = {sizeof(NOTIFYICONDATA)}; + + nid.uFlags = 0; + nid.hWnd = m_hWnd; + nid.uID = 0; + + return ::Shell_NotifyIcon(NIM_DELETE, &nid); + } + +protected: + + static const UINT WM_TASKBARCREATED; + + HWND m_hWndNotify; + UINT m_uID; + UINT m_uIconResID; + + void OnDestroy() + { + Destroy(); + } + + LRESULT OnTaskbarCreated(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/) + { + Create(m_hWndNotify, m_uID, m_uIconResID); + + return 0; + } + + LRESULT OnTrayNotify(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + if (m_hWndNotify && ::IsWindow(m_hWndNotify) && ::IsWindowEnabled(m_hWndNotify)) + { + WHNMTRAYICON nms; + nms.hdr.code = WHNM_TRAYICON; + nms.hdr.hwndFrom = m_hWnd; + nms.hdr.idFrom = m_uID; + nms.uMsg = (UINT)lParam; + + LRESULT lRet = ::SendMessage(m_hWndNotify, WM_NOTIFY, (LPARAM)m_uID, (WPARAM)&nms); + } + + return 0; + } + + static UINT _RegisterTaskbarCreatedMessage() + { + UINT uMsg = ::RegisterWindowMessage(_T("TaskbarCreated")); + + typedef BOOL (WINAPI *pfn_ChangeWindowMessageFilter)(UINT, DWORD); + #define MyMSGFLT_ADD 1 + + pfn_ChangeWindowMessageFilter MyChangeWindowMessageFilter + = (pfn_ChangeWindowMessageFilter)::GetProcAddress(::GetModuleHandle(_T("user32.dll")), "ChangeWindowMessageFilter"); + + if (MyChangeWindowMessageFilter) + MyChangeWindowMessageFilter(uMsg, MyMSGFLT_ADD); + + return uMsg; + } + +public: + BEGIN_MSG_MAP_EX(CWHTrayIcon) + MSG_WM_DESTROY(OnDestroy) + MESSAGE_HANDLER_EX(WM_TASKBARCREATED, OnTaskbarCreated) + MESSAGE_HANDLER_EX(WM_APP, OnTrayNotify) + DEFAULT_REFLECTION_HANDLER() + END_MSG_MAP() +}; + +__declspec(selectany) const UINT CWHTrayIcon::WM_TASKBARCREATED = CWHTrayIcon::_RegisterTaskbarCreatedMessage(); + + +class CWHLink + : public CWindowImpl +{ +public: + CWHLink() + : m_bTrackFlag(FALSE) + , m_crBg(GetSysColor(COLOR_3DFACE)) + { + + } + + void SetBackground(COLORREF crBg) + { + m_crBg = crBg; + } + + BOOL SubclassWindow(HWND hWnd) + { + BOOL bRet = __super::SubclassWindow(hWnd); + + if (bRet) + ModifyStyle(0, SS_NOTIFY); + + return bRet; + } + + void OnPaint(CDCHandle /*dc*/) + { + CString strCaption; + CRect rcClient; + CPaintDC dc(m_hWnd); + + GetWindowText(strCaption); + GetClientRect(rcClient); + + dc.SetBkMode(TRANSPARENT); + + HFONT hftOld = dc.SelectFont(BkFontPool::GetFont(FALSE, TRUE, FALSE)); + dc.FillSolidRect(rcClient, m_crBg); + + if (m_bTrackFlag) + { + dc.SetTextColor(RGB(0xFF, 0, 0)); + } + else + { + dc.SetTextColor(RGB(0x30, 0x64, 0xA5)); + } + + dc.DrawText(strCaption, strCaption.GetLength(), rcClient, DT_SINGLELINE); + + dc.SetTextColor(RGB(0, 0, 0)); + + dc.SelectFont(hftOld); + } + + BOOL OnEraseBkgnd(CDCHandle dc) + { + return TRUE; + } + + void OnMouseMove(UINT nFlags, CPoint point) + { + if (!m_bTrackFlag) + { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(tme); + tme.hwndTrack = m_hWnd; + tme.dwFlags = TME_LEAVE; + tme.dwHoverTime = 0; + m_bTrackFlag = _TrackMouseEvent(&tme); + + Invalidate(FALSE); + } + } + + void OnMouseLeave() + { + m_bTrackFlag = FALSE; + + Invalidate(FALSE); + } + + void OnLButtonDown(UINT nFlags, CPoint point) + { + SetCapture(); + } + + void OnLButtonUp(UINT nFlags, CPoint point) + { + ReleaseCapture(); + + GetParent().SendMessage(WM_COMMAND, GetDlgCtrlID()); + } + + BOOL OnSetCursor(CWindow wnd, UINT nHitTest, UINT message) + { + ::SetCursor(::LoadCursor(NULL, IDC_HAND)); + + return TRUE; + } + + +protected: + + BOOL m_bTrackFlag; + COLORREF m_crBg; + + BEGIN_MSG_MAP_EX(CWHLink) + MSG_WM_PAINT(OnPaint) + MSG_WM_ERASEBKGND(OnEraseBkgnd) + MSG_WM_MOUSEMOVE(OnMouseMove) + MSG_WM_MOUSELEAVE(OnMouseLeave) + MSG_WM_LBUTTONDOWN(OnLButtonDown) + MSG_WM_LBUTTONUP(OnLButtonUp) + MSG_WM_SETCURSOR(OnSetCursor) + END_MSG_MAP() +}; + +class CWHHtmlContainerWindow + : public CWindowImpl + , public IDispEventImpl +{ +public: + CWHHtmlContainerWindow() + : m_bNavigateError(FALSE) + , m_crBg(RGB(0xFF, 0xFF, 0xFF)) + { + } + + HWND Create(HWND hWndParent, UINT nID, BOOL bVisible = TRUE, COLORREF crBg = RGB(0xFF, 0xFF, 0xFF)) + { + HWND hWnd = __super::Create(hWndParent, NULL, NULL, WS_CHILD/* | WS_CLIPCHILDREN*/ | (bVisible ? WS_VISIBLE : 0), 0, nID); + if (!hWnd) + return NULL; + + m_crBg = crBg; + + _CreateIEControl(hWnd); + + return hWnd; + } + + void Show(LPCTSTR lpszURL) + { + m_bNavigateError = FALSE; + + m_strUrl = lpszURL; + + SetTimer(1, 500); + +// ::CloseHandle(::CreateThread(NULL, 0, _CreateCtrlProc, this, 0, NULL)); + } + + // Navi ʧܺԶһҳ + void Show2(LPCTSTR lpszUrl, LPCTSTR lpszErrorUrl) + { + if (lpszErrorUrl != NULL) + m_strErrorUrl = lpszErrorUrl; + + Show(lpszUrl); + } + + void SetBkColor(COLORREF color) + { + m_crBg = color; + Invalidate(); + } + +protected: + + CAxWindow m_wndIE; + CString m_strUrl; + BOOL m_bNavigateError; + COLORREF m_crBg; + CString m_strErrorUrl; + + static DWORD WINAPI _CreateCtrlProc(LPVOID pvParam) + { + CWHHtmlContainerWindow *pThis = (CWHHtmlContainerWindow *)pvParam; + CComPtr piWebBrowser; + CComVariant v; + + + ::Sleep(1000); + + pThis->m_wndIE.QueryControl(&piWebBrowser); + + if (piWebBrowser) + { + piWebBrowser->put_RegisterAsDropTarget( VARIANT_FALSE ); + piWebBrowser->put_Silent( VARIANT_TRUE ); + piWebBrowser->Navigate(CComBSTR(pThis->m_strUrl), &v, &v, &v, &v); + } + + return 0; + } + + void WINAPI NavigateComplete2WebAdinfo(LPDISPATCH pDisp, VARIANT* URL) + { + if (!m_bNavigateError) + { + m_wndIE.ShowWindow(SW_SHOW); + } + } + + void WINAPI NavigateErrorWebAdinfo( + IDispatch* pDisp, + VARIANT* pvtURL, + VARIANT* pvtFrame, + VARIANT* pvtStatusCode, + VARIANT_BOOL* pvbCancel + ) + { + BOOL bNaviErrorPage = FALSE; + if (pvtURL!=NULL && !m_strErrorUrl.IsEmpty()) + { + CComBSTR bstrUrl(pvtURL->bstrVal); + if (bstrUrl == CComBSTR(m_strUrl)) + { + CComPtr piWebBrowser; + CComVariant v; + + m_wndIE.QueryControl(&piWebBrowser); + + if (piWebBrowser) + { + piWebBrowser->put_RegisterAsDropTarget( VARIANT_FALSE ); + piWebBrowser->put_Silent( VARIANT_TRUE ); + piWebBrowser->Navigate(CComBSTR(m_strErrorUrl), &v, &v, &v, &v); + bNaviErrorPage = TRUE; + } + } + } + + + if ( !bNaviErrorPage) + { + m_bNavigateError = TRUE; + } + *pvbCancel = VARIANT_TRUE; + } + + void WINAPI NewWindow3WebAdinfo( + IDispatch **ppDisp, + VARIANT_BOOL *Cancel, + DWORD dwFlags, + BSTR bstrUrlContext, + BSTR bstrUrl) + { + CString strUrl(bstrUrl); + + ::ShellExecute(NULL, _T("open"), strUrl, NULL, NULL, SW_SHOWNORMAL); + + *Cancel = TRUE; + } + + void OnDestroy() + { + AtlAdviseSinkMap(this, FALSE); + if (m_wndIE.IsWindow()) + m_wndIE.DestroyWindow(); + } + + BOOL OnEraseBkgnd(CDCHandle dc) + { +// if (!m_wndIE.IsWindow() || !m_wndIE.IsWindowVisible()) +// { +// CRect rcClient; +// +// GetClientRect(rcClient); +// +// dc.FillSolidRect(rcClient, m_crBg); +// dc.SetBkMode(TRANSPARENT); +// HFONT hftOld = dc.SelectFont(BkFontPool::GetFont(BKF_DEFAULTFONT)); +// +// CString strText = L"ڶȡϢ..."; +// dc.DrawText(strText, strText.GetLength(), rcClient, DT_SINGLELINE); +// +// dc.SelectFont(hftOld); +// } + + return TRUE; + } + + void OnPaint(CDCHandle /*dc*/) + { + CPaintDC dc(m_hWnd); + + if (!m_wndIE.IsWindow() || !m_wndIE.IsWindowVisible()) + { + CRect rcClient; + + GetClientRect(rcClient); + + dc.FillSolidRect(rcClient, m_crBg); + } + } + + void OnSize(UINT nType, CSize /*size*/) + { + if (m_wndIE.IsWindow()) + { + CRect rcClient; + + GetClientRect(rcClient); + + m_wndIE.MoveWindow(rcClient); + } + } + + void OnTimer(UINT_PTR nIDEvent) + { + if (1 != nIDEvent) + return; + + KillTimer(1); + + CComPtr piWebBrowser; + CComVariant v; + + //::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + m_wndIE.QueryControl(&piWebBrowser); + + if (piWebBrowser) + { + piWebBrowser->put_RegisterAsDropTarget( VARIANT_FALSE ); + piWebBrowser->put_Silent( VARIANT_TRUE ); + piWebBrowser->Navigate(CComBSTR(m_strUrl), &v, &v, &v, &v); + } + + //::CoUninitialize(); + } + + void _CreateIEControl(HWND hWnd) + { + CRect rcClient; + + GetClientRect(rcClient); + + m_wndIE.Create(m_hWnd, rcClient, NULL, WS_CHILD | WS_CLIPCHILDREN); + + m_wndIE.CreateControl(L"Shell.Explorer"); + m_wndIE.SetDlgCtrlID(IDYES); + + AtlAdviseSinkMap(this, TRUE); + } + + BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) + { + CComPtr pWebBrowser; + m_wndIE.QueryControl(&pWebBrowser); + + if (pWebBrowser) + { + IServiceProvider* pServiceProvider = NULL; + if (SUCCEEDED(pWebBrowser->QueryInterface( + IID_IServiceProvider, + (void**)&pServiceProvider))) + { + IOleWindow* pWindow = NULL; + if (SUCCEEDED(pServiceProvider->QueryService( + SID_SShellBrowser, + IID_IOleWindow, + (void**)&pWindow))) + { + HWND hwndBrowser = NULL; + if (SUCCEEDED(pWindow->GetWindow(&hwndBrowser))) + { + OutputDebugString(_T("Ϣ")); + + HWND hwnd = NULL; + hwnd = ::FindWindowEx(hwndBrowser,NULL,TEXT("Shell DocObject View"),NULL); + if (hwnd) + { + HWND hIE = ::FindWindowEx(hwnd,NULL,TEXT("Internet Explorer_Server"),NULL); + + if ( zDelta < 0 ) + { + ::SendMessage(hIE, WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN,0),0); + } + else + { + ::SendMessage(hIE, WM_VSCROLL, MAKEWPARAM(SB_LINEUP,0),0); + } + + } + + } + + pWindow->Release(); + } + pServiceProvider->Release(); + } + } + + return FALSE; + } + +public: + BEGIN_MSG_MAP(CWHHtmlContainerWindow) + MSG_WM_DESTROY(OnDestroy) + MSG_WM_ERASEBKGND(OnEraseBkgnd) + MSG_WM_PAINT(OnPaint) + MSG_WM_SIZE(OnSize) + MSG_WM_TIMER(OnTimer) + MSG_WM_MOUSEWHEEL(OnMouseWheel) + REFLECT_NOTIFICATIONS() + END_MSG_MAP() + + BEGIN_SINK_MAP(CWHHtmlContainerWindow) + SINK_ENTRY(IDYES, 252, NavigateComplete2WebAdinfo) + SINK_ENTRY(IDYES, 271, NavigateErrorWebAdinfo) + SINK_ENTRY(IDYES, 273, NewWindow3WebAdinfo) + END_SINK_MAP() +}; + +class CWHEdit + : public CWindowImpl +{ +public: + CWHEdit() + : m_crBg(CLR_DEFAULT) + { + + } + + void SetBkColor(COLORREF crBg) + { + m_crBg = crBg; + + Invalidate(TRUE); + } + +protected: + COLORREF m_crBg; + + HBRUSH OnReflectedCtlColor(CDCHandle dc, HWND /*hWnd*/) + { + if (CLR_DEFAULT == m_crBg) + { + SetMsgHandled(FALSE); + return NULL; + } + + dc.SetBkColor(m_crBg); + + return ::CreateSolidBrush(m_crBg); + } + +public: + BEGIN_MSG_MAP(CWHHtmlContainerWindow) + MSG_OCM_CTLCOLORSTATIC(OnReflectedCtlColor) + MSG_OCM_CTLCOLOREDIT(OnReflectedCtlColor) + END_MSG_MAP() +}; + diff --git a/Client/Client/GUI/LoginWin/BKWinLogin.cpp b/Client/Client/GUI/LoginWin/BKWinLogin.cpp new file mode 100644 index 00000000..a1c24310 --- /dev/null +++ b/Client/Client/GUI/LoginWin/BKWinLogin.cpp @@ -0,0 +1,142 @@ +#include "stdafx.h" +#include "BKWinLogin.h" +#include "..\..\Logic\UserSession\StrMatch.hpp" + +#define TimerID_LoginTimeout 0 + +BEGIN_MSG_MAP_EX_IMP(CLoginWnd) + MSG_BK_NOTIFY(IDC_RICHVIEW_WIN) + CHAIN_MSG_MAP(CBkDialogImpl) + MSG_WM_TIMER(OnTimer) + REFLECT_NOTIFICATIONS_EX() +END_MSG_MAP_IMP(); + +CLoginWnd::CLoginWnd() : CBkDialogImpl(BKDlg_LoginWin),CFrameBase(module_LoginWin) +{ + m_loginState = 0; +} + +VOID CLoginWnd::OnFrameStart( XMessage_FrameStart* pmsg ) +{ + OnShowWnd(NULL); +} + +void CLoginWnd::OnBkBtnClose() +{ + EndDialog(0); + XMessage_ShowRoomListWnd msg; + SendXMessage(&msg); +} + +void CLoginWnd::OnLoginClick() +{ + //Disable(); + //m_loginState = 1; + //SetTimer(TimerID_LoginTimeout,5000); + CString userName; + CString pwd; + CBkWindow* pUsernameEdit = NULL; + CBkWindow* pPwdEdit = NULL; + pUsernameEdit = m_richView.FindChildByCmdID(DlgControl_LoginWin_Edit_UserName); + pPwdEdit = m_richView.FindChildByCmdID(DlgControl_LoginWin_Edit_PassWord); + if (pUsernameEdit && pPwdEdit) + { + userName = pUsernameEdit->GetInnerText(); + pwd = pPwdEdit->GetInnerText(); + if (IsStringMatch(userName.GetString()) && + IsStringMatch(pwd.GetString(), MATCH_TYPE_PWD)) + { + Disable(); + m_loginState = 1; + SetTimer(TimerID_LoginTimeout,5000); + + XMessage_Login msg; + msg.username = userName; + msg.pwd = pwd; + SendXMessage(&msg); + } + else + { + MessageBox(TEXT("Чû")); + } + } +} + +VOID CLoginWnd::OnLoginResult( XMessage_Login_Result* pMsg ) +{ + if (pMsg && m_loginState==1) + { + if (pMsg->success == TRUE) + { + MessageBox(_T("ɹ½!")); + OnBkBtnClose(); + } + else + { + MessageBox(_T("½ʧ!")); + } + m_loginState = 2; + Enable(); + } +} + +VOID CLoginWnd::Disable() +{ + CBkWindow* pUsernameEdit = NULL; + pUsernameEdit = m_richView.FindChildByCmdID(DlgControl_LoginWin_Edit_UserName); + if (pUsernameEdit) + { + pUsernameEdit->ModifyState(BkWndState_Disable,0); + } + CBkWindow* pPwdEdit = NULL; + pPwdEdit = m_richView.FindChildByCmdID(DlgControl_LoginWin_Edit_PassWord); + if (pPwdEdit) + { + pPwdEdit->ModifyState(BkWndState_Disable,0); + } + CBkWindow* pLoginBtn = NULL; + pLoginBtn = m_richView.FindChildByCmdID(DlgControl_LoginWin_Button_Login); + if (pLoginBtn) + { + pLoginBtn->ModifyState(BkWndState_Disable,0); + } +} + +VOID CLoginWnd::Enable() +{ + CBkWindow* pUsernameEdit = NULL; + pUsernameEdit = m_richView.FindChildByCmdID(DlgControl_LoginWin_Edit_UserName); + if (pUsernameEdit) + { + pUsernameEdit->ModifyState(0,BkWndState_Disable); + } + CBkWindow* pPwdEdit = NULL; + pPwdEdit = m_richView.FindChildByCmdID(DlgControl_LoginWin_Edit_PassWord); + if (pPwdEdit) + { + pPwdEdit->ModifyState(0,BkWndState_Disable); + } + CBkWindow* pLoginBtn = NULL; + pLoginBtn = m_richView.FindChildByCmdID(DlgControl_LoginWin_Button_Login); + if (pLoginBtn) + { + pLoginBtn->ModifyState(0,BkWndState_Disable); + pLoginBtn->NotifyInvalidate(); + } +} + +VOID CLoginWnd::OnTimer( UINT_PTR id ) +{ + if (m_loginState == 1) + { + KillTimer(id); + MessageBox(_T("½ʱ")); + } + m_loginState = 0; + Enable(); +} + +VOID CLoginWnd::OnShowWnd( XMessage_ShowLogin* pmsg ) +{ + DoModal(); +} diff --git a/Client/Client/GUI/LoginWin/BKWinLogin.h b/Client/Client/GUI/LoginWin/BKWinLogin.h new file mode 100644 index 00000000..ec529b2c --- /dev/null +++ b/Client/Client/GUI/LoginWin/BKWinLogin.h @@ -0,0 +1,38 @@ +#pragma once +#include "../BKWin/wtlhelper/whwindow.h" +#include "../../net/INet.h" +#include "../FrameWork/FrameBase.hpp" + +class CLoginWnd:public CBkDialogImpl + ,public CFrameBase +{ +public: + CLoginWnd(); +public: + void OnBkBtnClose(); + void OnLoginClick(); + +protected: + VOID Disable(); + VOID Enable(); + VOID OnTimer(UINT_PTR id); + VOID OnFrameStart(XMessage_FrameStart* pmsg); + VOID OnShowWnd(XMessage_ShowLogin* pmsg); + VOID OnLoginResult(XMessage_Login_Result* pMsg); +protected: + INT m_loginState; + +public: + BK_NOTIFY_MAP(IDC_RICHVIEW_WIN) + BK_NOTIFY_ID_COMMAND(DlgControl_LoginWin_ImgBtn_Close, OnBkBtnClose) + BK_NOTIFY_ID_COMMAND(DlgControl_LoginWin_Button_Login, OnLoginClick) + BK_NOTIFY_MAP_END() + + BEGIN_MSG_MAP_EX_DECLARE(CLoginWnd) + + Begin_XMessage(CLoginWnd) + OnXMessage(XMessage_FrameStart,OnFrameStart) + OnXMessage(XMessage_ShowLogin,OnShowWnd) + OnXMessage(XMessage_Login_Result,OnLoginResult); + End_XMessage() +}; \ No newline at end of file diff --git a/Client/Client/GUI/RoomListWin/BKWinRoomList.cpp b/Client/Client/GUI/RoomListWin/BKWinRoomList.cpp new file mode 100644 index 00000000..bb3bcf4a --- /dev/null +++ b/Client/Client/GUI/RoomListWin/BKWinRoomList.cpp @@ -0,0 +1,98 @@ +#include "stdafx.h" +#include "BKWinRoomList.h" + +#define TimerID_LoginTimeout 0 + +BEGIN_MSG_MAP_EX_IMP(CRoomListWnd) + MSG_BK_NOTIFY(IDC_RICHVIEW_WIN) + MSG_WM_INITDIALOG(OnInitDialog) + CHAIN_MSG_MAP(CBkDialogImpl) + NOTIFY_CODE_HANDLER(NM_DBLCLK, OnListItemDblClick) + REFLECT_NOTIFICATIONS_EX() +END_MSG_MAP_IMP(); + + + +void CRoomListWnd::OnBkBtnClose() +{ + EndDialog(0); +} + +void CRoomListWnd::OnShowWnd( XMessage* pmsg ) +{ + DoModal(); +} + + +LRESULT CRoomListWnd::OnInitDialog(HWND hWnd, LPARAM lparam) +{ + if(m_wndListCtrl.Create( + GetViewHWND(), NULL, NULL, + WS_VISIBLE | WS_CHILD | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SINGLESEL , + 0, DlgControl_RoomListWin_Realwnd, NULL) == NULL){ + return S_FALSE; + } + XMessage_GetRoomList msg; + SendXMessage(&msg); + _ColumnInit(); + + return S_OK; +} + + +LRESULT CRoomListWnd::_ColumnInit() +{ + m_wndListCtrl.InsertColumn(0, _T("ID"), LVCFMT_LEFT, 50); + m_wndListCtrl.InsertColumn(1, _T("dz"), LVCFMT_LEFT, 270); + m_wndListCtrl.InsertColumn(2, _T("״̬"), LVCFMT_LEFT, 80); + + return S_OK; +} + +LRESULT CRoomListWnd::OnListItemDblClick(int idRealWnd, LPNMHDR pnmh, BOOL& bHandled) +{ + LPNMITEMACTIVATE lpnmItem = (LPNMITEMACTIVATE)pnmh; + + if(1001 == idRealWnd){ // б + CString strCheckBox; + if(m_wndListCtrl.InSubItemCheckBox(lpnmItem->ptAction, lpnmItem->iItem)){ + strCheckBox.Format(_T("CHECKBOX CHANGED: %d"), !m_wndListCtrl.GetCheckState(lpnmItem->iItem)); + MessageBox(strCheckBox, NULL, MB_OK); + } + + //char strListItem[30]; + if(m_wndListCtrl.GetSelectedIndex() == lpnmItem->iItem){ + //sprintf(strListItem, "Clicked id: %d", lpnmItem->iItem); + //MessageBoxA(NULL, strListItem, "", MB_OK); + EndDialog(0); + XMessage_ShowClassroom msg; + SendXMessage(&msg); + } + + } + + bHandled = FALSE; + return S_OK; +} + +LRESULT CRoomListWnd::OnGetRoomListResult( XMessage *pmsg ) +{ + XMessage_GetRoomList_Result *pResult = dynamic_cast(pmsg); + if(pResult) + { + int nItem = 0; + CString buf; + for(int i = 0; i < pResult->roomNameList.size(); i++) + { + buf.Format(_T("%d"), pResult->roomIdList[i]); + nItem = m_wndListCtrl.Append(buf); + m_wndListCtrl.AppendSubItem(nItem, CString(pResult->roomNameList[i].c_str())); + buf.Format(_T("%d"), pResult->roomStateList[i]); + m_wndListCtrl.AppendSubItem(nItem, buf); + } + return S_OK; + } + + return S_FALSE; +} + diff --git a/Client/Client/GUI/RoomListWin/BKWinRoomList.h b/Client/Client/GUI/RoomListWin/BKWinRoomList.h new file mode 100644 index 00000000..3317b800 --- /dev/null +++ b/Client/Client/GUI/RoomListWin/BKWinRoomList.h @@ -0,0 +1,38 @@ +#pragma once +#include "../../GUI/BKWin/wtlhelper/whwindow.h" +#include "../../net/INet.h" +#include "../FrameWork/FrameBase.hpp" + +class CRoomListWnd : public CBkDialogImpl + ,public CFrameBase +{ +public: + CRoomListWnd::CRoomListWnd() : CBkDialogImpl(BKDlg_RoomListWin),CFrameBase(module_RoomListWin) + { + } + + +public: + void OnBkBtnClose(); + void OnShowWnd(XMessage* pmsg); + LRESULT OnInitDialog(HWND hWnd, LPARAM lparam); + LRESULT OnListItemDblClick(int idRealWnd, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnGetRoomListResult(XMessage *pmsg); + +private: + CListViewCtrlEx m_wndListCtrl; + +private: + LRESULT _ColumnInit(); + +public: + BK_NOTIFY_MAP(IDC_RICHVIEW_WIN) + BK_NOTIFY_ID_COMMAND(DlgControl_RoomListWin_ImgBtn_Close, OnBkBtnClose) + BK_NOTIFY_MAP_END() + + BEGIN_MSG_MAP_EX_DECLARE(CRoomListWnd) + Begin_XMessage(CRoomListWnd) + OnXMessage(XMessage_ShowRoomListWnd,OnShowWnd) + OnXMessage(XMessage_GetRoomList_Result, OnGetRoomListResult) + End_XMessage() +}; \ No newline at end of file diff --git a/Client/Client/GUI/RoomWin/BKWinClassroom.cpp b/Client/Client/GUI/RoomWin/BKWinClassroom.cpp new file mode 100644 index 00000000..b530acc8 --- /dev/null +++ b/Client/Client/GUI/RoomWin/BKWinClassroom.cpp @@ -0,0 +1,28 @@ +#include "stdafx.h" +#include "BKWinClassroom.h" + +#define TimerID_LoginTimeout 0 + +BEGIN_MSG_MAP_EX_IMP(CClassroomWnd) + MSG_BK_NOTIFY(IDC_RICHVIEW_WIN) + MSG_WM_INITDIALOG(OnInitDialog) + CHAIN_MSG_MAP(CBkDialogImpl) + REFLECT_NOTIFICATIONS_EX() +END_MSG_MAP_IMP(); + +void CClassroomWnd::OnBkBtnClose() +{ + EndDialog(0); +} + +VOID CClassroomWnd::OnShowWnd( XMessage* pmsg ) +{ + DoModal(); +} + +LRESULT CClassroomWnd::OnInitDialog(HWND hWnd, LPARAM lparam) +{ + MessageBox(_T("ʼ.")); + + return 0; +} \ No newline at end of file diff --git a/Client/Client/GUI/RoomWin/BKWinClassroom.h b/Client/Client/GUI/RoomWin/BKWinClassroom.h new file mode 100644 index 00000000..3f50efab --- /dev/null +++ b/Client/Client/GUI/RoomWin/BKWinClassroom.h @@ -0,0 +1,34 @@ +#pragma once +#include "../../GUI/BKWin/wtlhelper/whwindow.h" +#include "../../net/INet.h" +#include "../FrameWork/FrameBase.hpp" + +class CClassroomWnd : public CBkDialogImpl, + public CFrameBase +{ +public: + CClassroomWnd::CClassroomWnd() : CBkDialogImpl(BKDlg_ClassroomWin), + CFrameBase(module_ClassroomWin) + { + } + +public: + void OnBkBtnClose(); + void OnShowWnd(XMessage* pmsg); + LRESULT OnInitDialog(HWND hWnd, LPARAM lparam); + +protected: + +protected: + +public: + BK_NOTIFY_MAP(IDC_RICHVIEW_WIN) + BK_NOTIFY_ID_COMMAND(DlgControl_ClassroomWin_ImgBtn_Close, OnBkBtnClose) + BK_NOTIFY_MAP_END() + + + BEGIN_MSG_MAP_EX_DECLARE(CClassroomWnd) + Begin_XMessage(CClassroomWnd) + OnXMessage(XMessage_ShowClassroom,OnShowWnd) + End_XMessage() +}; \ No newline at end of file diff --git a/Client/Client/GUI/bkwinres.rc2 b/Client/Client/GUI/bkwinres.rc2 new file mode 100644 index 00000000..aa179db6 --- /dev/null +++ b/Client/Client/GUI/bkwinres.rc2 @@ -0,0 +1,68 @@ +#pragma once + +DEFINE_XML(IDR_XML_SKIN_DEF, 100, "res/def_skin.xml") +DEFINE_XML(IDR_BK_STYLE_DEF, 101, "res\\def_style.xml") +DEFINE_XML(IDR_BK_STRING_DEF, 102, "res\\def_string.xml") +DEFINE_XML(IDR_BK_MAIN_DIALOG, 103, "res\\dlg_main.xml") +DEFINE_XML(IDR_BK_MESSAGEBOX, 105, "res\\dlg_msgbox.xml") +DEFINE_XML(IDR_BK_RUNOPT_LIST, 128, "res\\dlg_runopt_list.xml") +DEFINE_XML(IDR_BK_RUNOPT_IGNORE_DLG, 134, "res\\dlg_runopt_ignore.xml") +DEFINE_XML(IDR_BK_MESSAGEBOX2, 150, "res\\dlg_msgbox2.xml") +DEFINE_XML(IDR_BK_SYSOPT_SETTING_DLG, 152, "res\\dlg_sysopt_setting.xml") + +// dlgfile ǩļ +DEFINE_XML(IDR_BK_DLGFILE_OPT, 504, "res\\dlgfile_opt.xml") +DEFINE_XML(IDR_BK_DLGFILE_FOOT, 508, "res\\dlgfile_foot.xml") +DEFINE_XML(IDR_BK_DLGFILE_HEADER, 509, "res\\dlgfile_header.xml") + +DEFINE_XML(IDR_BK_MORE_BKWIN, 600, "res\\dlg_more_bkwin.xml") + + +////////////////////////////////////////////////////////////////////////// +// ICON + +DEFINE_ICO(IDI_BEIKESAFE, 100, "res\\beikesafe.ico") +DEFINE_ICO(IDI_SMALL, 101, "res\\small.ico") + +////////////////////////////////////////////////////////////////////////// +// PNG +DEFINE_PNG(IDP_PNG_STATUS15, 40, "res\\status_icon.png") +DEFINE_PNG(IDP_PNG_EXAM_STATUS15, 41, "res\\exam_status_icon.png") +DEFINE_PNG(IDB_BTN_SYS_CLOSE_PNG, 44, "res\\btn_sys_close.png") +DEFINE_PNG(IDB_BTN_SYS_MAXIMIZE_PNG, 46, "res\\btn_sys_maximize.png") +DEFINE_PNG(IDB_BTN_SYS_MINIMIZE_PNG, 47, "res\\btn_sys_minimize.png") +DEFINE_PNG(IDB_BTN_SYS_RESTORE_PNG, 48, "res\\btn_sys_restore.png") +DEFINE_BMP(IDB_MSGBOX_BG, 4, "res\\msgbox_bg.bmp") +DEFINE_BMP(IDB_TAB_NORMAL, 6, "res\\tab_normal.bmp") +DEFINE_BMP(IDB_STATUS_40, 15, "res\\status_40.bmp") +DEFINE_BMP(IDB_TAB_LEFT, 16, "res\\tab_left.bmp") +DEFINE_BMP(IDB_TAB_LEFT_SPLITTER, 17, "res\\tab_left_splitter.bmp") +DEFINE_BMP(IDB_BTN_VIRSCAN_BG, 27, "res\\btn_virscan_bg.bmp") +DEFINE_BMP(IDP_BG_MSGBOX_BODY, 29, "res\\msgbox_body_bg.bmp") +DEFINE_BMP(IDB_BTN_SYS_CLOSE, 101, "res\\btn_sys_close.bmp") +DEFINE_BMP(IDB_BTN_SYS_MAXIMIZE, 103, "res\\btn_sys_maximize.bmp") +DEFINE_BMP(IDB_BTN_SYS_MINIMIZE, 104, "res\\btn_sys_minimize.bmp") +DEFINE_BMP(IDB_BTN_SYS_RESTORE, 105, "res\\btn_sys_restore.bmp") +DEFINE_BMP(IDB_FRAME_PANEL_GRAY, 106, "res\\frame_panel_gray.bmp") +DEFINE_BMP(IDB_FRAME_PANEL, 107, "res\\frame_panel.bmp") +DEFINE_BMP(IDB_STATUS_ICON, 111, "res\\status_icon.bmp") +DEFINE_BMP(IDB_SCAN_RESULT_LIST_BAR, 122, "res\\scan_result_list_bar.bmp") +DEFINE_PNG(IDP_LITTLE_LOGO, 201, "res\\little_logo.png") +DEFINE_BMP(IDB_BITMAP_LISTCTRL_HEADER, 210, "res\\listctrl_header.bmp") +DEFINE_BMP(IDB_BITMAP_MINUS_PLUS, 212, "res\\minus_plus.bmp") +DEFINE_BMP(IDB_BITMAP_LISTCTRL_CHECK, 211, "res\\listctrl_check.bmp") +DEFINE_BMP(IDB_BITMAP_LISTCTRL_RADIO, 213, "res\\listctrl_radio.bmp") +DEFINE_PNG(IDP_ROOMLIST_PANE, 214, "res\\frame_roomlistpane.png") +DEFINE_PNG(IDP_LOADINFO_TIP, 8020, "res\\loadinfo_tip_softmgr.png") +DEFINE_BMP(IDB_SOFTMGR_CLEAR_BK, 8034, "res\\clear_bk.bmp") +DEFINE_BMP(IDB_SYSOPT_LIST_HEADERBK, 8035, "res\\sysopt_listbk.bmp") +DEFINE_BMP(IDB_LOADINFO_DLGBK, 8036, "res\\loadinfo_dlgbk.bmp") + +////////////////////////////////////////////////////////////////////////// +// +DEFINE_BMP(IDB_RUNOPT_STATUS, 20007, "res\\stat_runopt.bmp") +DEFINE_PNG(IDP_RUNOPT_LOADING_TIP, 20008, "res\\loading_runopt.png") +DEFINE_BMP(IDB_RUNOPT_LIST_HEADER, 20010, "res\\runopt_listheader.bmp") +DEFINE_BMP(IDB_RUNOPT_PANEL_DELAY, 20011, "res\\loaddlg_panel.bmp") +DEFINE_PNG(IDP_RUNOPT_STARTUPTIME_SETTING, 20012, "res\\startuptime_setting.png") +DEFINE_PNG(IDP_RUNOPT_IGNORE_TIP, 20013, "res\\ignore_tip.png") \ No newline at end of file diff --git a/Client/Client/Logic/UserSession/ILogin.h b/Client/Client/Logic/UserSession/ILogin.h new file mode 100644 index 00000000..9cb7d4ea --- /dev/null +++ b/Client/Client/Logic/UserSession/ILogin.h @@ -0,0 +1,15 @@ +#pragma once +#include "IModule.h" + +interface ILogin : public IModule +{ +public: + // ָҪʾĵ½˻ + virtual ResultCode SetAccount(LPCTSTR userName)=0; + // ǰ½ûû½usernameǿ + virtual ResultCode GetCurrentUser(CString& userName,CString& cookie)=0; + // ½ + virtual ResultCode Login(LPCTSTR username,LPCTSTR pwd)=0; + // עĿǰǵûƣԿԲû + virtual ResultCode Logout(LPCTSTR username=NULL)=0; +}; \ No newline at end of file diff --git a/Client/Client/Logic/UserSession/LoginImpl.cpp b/Client/Client/Logic/UserSession/LoginImpl.cpp new file mode 100644 index 00000000..e1f8d6b4 --- /dev/null +++ b/Client/Client/Logic/UserSession/LoginImpl.cpp @@ -0,0 +1,119 @@ +#include "StdAfx.h" +#include +#include "LoginImpl.h" + +CLoginImpl::CLoginImpl(void) : CFrameBase(module_LoginData) +{ + m_frame = NULL; +} + +CLoginImpl::~CLoginImpl(void) +{ +} + +ResultCode CLoginImpl::Run() +{ + netHelper.AddFilter(MSG_AnswerLogin_Id,this); + netHelper.StartListen(); + return Result_Success; +} + +ResultCode CLoginImpl::Terminate() +{ + netHelper.StopListen(); + return Result_Success; +} + +ResultCode CLoginImpl::SetAccount( LPCTSTR userName ) +{ + return Result_Success; +} + +ResultCode CLoginImpl::Initialize( IModule* UpperFrame ) +{ + m_frame = dynamic_cast(UpperFrame); + ATLASSERT(m_frame); + return Result_Success; +} + +ResultCode CLoginImpl::UnInitialize() +{ + return Result_Success; +} + +ResultCode CLoginImpl::Logout( LPCTSTR username/*=NULL*/ ) +{ + return Result_Success; +} + +ResultCode CLoginImpl::GetCurrentUser(CString& username,CString& cookie) +{ + return Result_NotImpl; +} + +VOID CLoginImpl::OnLogin( XMessage_Login* pMsg ) +{ + if (CheckLoginRequest(pMsg)) + { + Login(pMsg->username,pMsg->pwd); + } +} + +BOOL CLoginImpl::CheckLoginRequest( XMessage_Login* pMsg ) +{ + CString& userName = pMsg->username; + CString& pwd = pMsg->pwd; + XMessage_LoginError error; + if (userName.GetLength() == 0) + { + error.result = Result_UserName_LengthError; + } + else if (userName.Find(_T("sparta"))) + { + error.result = Result_UserName_InvalidChar; + } + else if (pwd.GetLength() == 0) + { + error.result = Result_Pwd_LengthError; + } + + SendXMessage(&error); + return ResultSucceeded(error.result); +} + +ResultCode CLoginImpl::Login( LPCTSTR username,LPCTSTR pwd ) +{ + INetCenter* pNetCenter = NULL; + Global->GetINetCenter(&pNetCenter); + if (pNetCenter) + { + MSG_RequestLogin netMsg; + char buffer[30]; + wcstombs(buffer, username, sizeof(buffer)); + netMsg.SetAccountNumber(buffer); + wcstombs(buffer, pwd, sizeof(buffer)); + netMsg.SetPassword(buffer); + pNetCenter->SendServer(netMsg); + return Result_Success; + } + return Result_Fail; +} + +ResultCode CLoginImpl::OnNetMessage( const CMessage &msg ) +{ + switch(msg.MsgId()) + { + case MSG_AnswerLogin_Id: + MSG_AnswerLogin msgReal(msg); + XMessage_Login_Result loginResult; + uint8 result; + msgReal.GetLoginResult(result); + loginResult.success = !result; + msgReal.GetToken(loginResult.userToken); + msgReal.GetATLGUID(loginResult.guid); + SendXMessage(&loginResult); + break; + } + return Result_Success; +} + diff --git a/Client/Client/Logic/UserSession/LoginImpl.h b/Client/Client/Logic/UserSession/LoginImpl.h new file mode 100644 index 00000000..8c30c808 --- /dev/null +++ b/Client/Client/Logic/UserSession/LoginImpl.h @@ -0,0 +1,37 @@ +#pragma once +#include "ILogin.h" +#include "../../FrameWork/FrameBase.hpp" +#include "../../net/INet.h" + +class CLoginImpl + : public ILogin + , public CFrameBase + , public INetListener +{ +public: + CLoginImpl(void); + ~CLoginImpl(void); +public: + virtual ResultCode Initialize(IModule* UpperFrame=NULL); + virtual ResultCode UnInitialize(); + virtual ResultCode Run(); + virtual ResultCode Terminate(); + virtual ResultCode SetAccount(LPCTSTR userName); + virtual ResultCode Login(LPCTSTR username,LPCTSTR pwd); + virtual ResultCode GetCurrentUser(CString& userName,CString& cookie); + virtual ResultCode Logout(LPCTSTR username=NULL); + + virtual ResultCode OnNetMessage(const CMessage &msg); +protected: + VOID OnLogin(XMessage_Login* pMsg); + BOOL CheckLoginRequest(XMessage_Login* pMsg); + +private: + IFrameWork* m_frame; + CNetListenerHelper netHelper; +public: + Begin_XMessage(CLoginImpl) + OnXMessage(XMessage_Login,OnLogin) + End_XMessage() +}; + diff --git a/Client/Client/Logic/UserSession/StrMatch.hpp b/Client/Client/Logic/UserSession/StrMatch.hpp new file mode 100644 index 00000000..41a5fa3f --- /dev/null +++ b/Client/Client/Logic/UserSession/StrMatch.hpp @@ -0,0 +1,35 @@ +/** + * file: StrMatch.hpp - For Checking the legitimacy of a string + * + * Date: 2012/11/24 + * + * Author: rookie2 + */ + +#pragma once + +#include +#include + +const unsigned short MATCH_TYPE_NAME = 0xfe; +const unsigned short MATCH_TYPE_PWD = 0xff; + +/** + * : ַ֤Ƿƥʽ + * @param str: ַ֤ + * @param matchType: ָĬʽ,ʹԶʽʱֵΪNULL + * @param regEex: regular expression, Զʽ + * @return: ַƥʽtrue, 򷵻false + */ +bool IsStringMatch(std::wstring str, + const unsigned short matchType = MATCH_TYPE_NAME, + std::wstring regExp = L"^[a-zA-Z0-9_]{5,20}$") +{ + std::wregex exp(regExp); + if (MATCH_TYPE_PWD == matchType) + { + exp.assign(L"^[\\@A-Za-z0-9_\\!\\#\\$\\%\\^\\&\\*\\.\\~]{6,20}$"); + } + + return std::regex_match(str, exp); +} \ No newline at end of file diff --git a/Client/Client/Logic/UserSession/usersessionTest.cpp b/Client/Client/Logic/UserSession/usersessionTest.cpp new file mode 100644 index 00000000..5432959d --- /dev/null +++ b/Client/Client/Logic/UserSession/usersessionTest.cpp @@ -0,0 +1,83 @@ +#ifdef CPPTEST +#include "stdafx.h" +#include "TestClassHeader.h" + +class CUserSessionTest : public CTestBase +{ + CPPUNIT_TEST_SUITE( CUserSessionTest ); + CPPUNIT_TEST( TestLoginRequest ); + CPPUNIT_TEST_SUITE_END(); + +public: + UINT m_testCount; + BOOL m_receivedResult; + BOOL m_expectResult; + CUserSessionTest():CTestBase() + , m_testCount(0) + , m_receivedResult(FALSE) + , m_expectResult(FALSE) + {} + + Begin_XMessage(CUserSessionTest) + OnXMessage(XMessage_LoginError,OnLoginError); + OnXMessage(XMessage_Login_Result,OnLoginResult); + End_XMessage(); + + VOID TestLoginRequest() + { + INetCenter* pNetCenter=NULL; + Global->GetINetCenter(&pNetCenter); + CPPUNIT_ASSERT(pNetCenter); + if (!pNetCenter) + { + return; + } + + XMessage_Login msg; + msg.username = _T(""); + msg.pwd = _T(""); + SendXMessage(&msg); + + msg.username = _T("123"); + SendXMessage(&msg); + + msg.username = _T("sparta"); + SendXMessage(&msg); + + MSG_AnswerLogin netMsg; + netMsg.SetLoginResult(0); + netMsg.SetToken(1); + netMsg.SetATLGUID("aaaaaaaaaaaaaa"); + m_expectResult = TRUE; + pNetCenter->MockReceive(&netMsg); + + netMsg.SetLoginResult(1); + netMsg.SetToken(2); + netMsg.SetATLGUID("bbbbbbbbbbbbbbbbbbbb"); + m_expectResult = FALSE; + pNetCenter->MockReceive(&netMsg); + + CPPUNIT_ASSERT(m_testCount == 3); + CPPUNIT_ASSERT(m_receivedResult); + } + + VOID OnLoginError( XMessage_LoginError* msg ) + { + if (ResultFailed(msg->result)) + { + ++m_testCount; + } + CPPUNIT_ASSERT(ResultFailed(msg->result)); + } + + VOID OnLoginResult( XMessage_Login_Result* msg) + { + CPPUNIT_ASSERT(msg->success == m_expectResult); + m_receivedResult = TRUE; + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION ( CUserSessionTest ); +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CUserSessionTest, "testUserSession"); + +#endif \ No newline at end of file diff --git a/Client/Client/Logic/room/IRoomMgr.h b/Client/Client/Logic/room/IRoomMgr.h new file mode 100644 index 00000000..f2d52ccb --- /dev/null +++ b/Client/Client/Logic/room/IRoomMgr.h @@ -0,0 +1,20 @@ +#pragma once +#include +#include "IModule.h" +#include "Room.h" +#include "../../net/INet.h" + + +typedef int RoomID; +// 房间列表 +typedef std::vector RoomList; + +interface IRoomMgr : public IModule +{ +public: + virtual ResultCode Show(BOOL bShow=TRUE)=0; + virtual ResultCode CreateRoom(RoomID& id)=0; + virtual ResultCode GetRoom(RoomID id,CRoomBase* room)=0; + virtual ResultCode GetRoomList()=0; + virtual ResultCode FreeRoom(RoomID id)=0; +}; diff --git a/Client/Client/Logic/room/Room.cpp b/Client/Client/Logic/room/Room.cpp new file mode 100644 index 00000000..ff5e2ffe --- /dev/null +++ b/Client/Client/Logic/room/Room.cpp @@ -0,0 +1,106 @@ +#include "stdafx.h" +#include "room.h" + +CRoomBase::CRoomBase() : CFrameBase(module_ClassroomWinData) +{ + +} + +CRoomBase::CRoomBase( CString ID ) : CFrameBase(module_ClassroomWinData) +{ + +} + +CRoomBase::~CRoomBase() +{ + +} + +void CRoomBase::SetID( CString id ) +{ + +} + +CString CRoomBase::GetID() +{ + return _T(""); +} + +void CRoomBase::SetName( CString name ) +{ + +} + +CString CRoomBase::GetName() +{ + return _T(""); +} + +void CRoomBase::SetGuestLimitCount( int count ) +{ + +} + +int CRoomBase::GetGuestLimitCount() +{ + return 0; +} + +void CRoomBase::SetEnable( BOOL isEnable/*=TRUE*/ ) +{ + +} + +BOOL CRoomBase::IsEnable() +{ + return 0; +} + +int CRoomBase::GetLock() +{ + return 0; +} + +BOOL CRoomBase::ReleaseLock( int token ) +{ + return 0; +} + +void CRoomBase::SetCreateTime( CTime time ) +{ + +} + +CTime CRoomBase::GetCreateTime() +{ + return CTime(); +} + +HRESULT CRoomBase::SetRoomOwner( UserID userID ) +{ + return E_NOTIMPL; +} + +UserID CRoomBase::GetRoomOwner() +{ + return _T(""); +} + +HRESULT CRoomBase::AddGuest( UserID userID ) +{ + return E_NOTIMPL; +} + +HRESULT CRoomBase::RemoveGuest( UserID userID ) +{ + return E_NOTIMPL; +} + +HRESULT CRoomBase::Free() +{ + return E_NOTIMPL; +} + + +////////////////////////////////////////////////////////////////////////// + diff --git a/Client/Client/Logic/room/Room.h b/Client/Client/Logic/room/Room.h new file mode 100644 index 00000000..78250f26 --- /dev/null +++ b/Client/Client/Logic/room/Room.h @@ -0,0 +1,60 @@ +#pragma once +// 巿 +#include "../../FrameWork/FrameBase.hpp" +#include +#include + +typedef CString UserID; + +class CRoomBase : public CFrameBase +{ +public: + CRoomBase(); + CRoomBase(CString ID); + ~CRoomBase(); +public: + virtual void SetID(CString id); + virtual CString GetID(); + virtual void SetName(CString name); + virtual CString GetName(); + virtual void SetGuestLimitCount(int count); + virtual int GetGuestLimitCount(); + virtual void SetEnable(BOOL isEnable=TRUE); + virtual BOOL IsEnable(); + // .ڼ䲻κֵ.صֵڽ + virtual int GetLock(); + // + virtual BOOL ReleaseLock(int token); + virtual void SetCreateTime(CTime time); + virtual CTime GetCreateTime(); + + // û + // ÷Ƿ֮һ + virtual HRESULT SetRoomOwner(UserID userID); + virtual UserID GetRoomOwner(); + virtual HRESULT AddGuest(UserID userID); + // ˳ʱԶΪȵ½û + virtual HRESULT RemoveGuest(UserID userID); + // رշǿû˳ + virtual HRESULT Free(); + + Begin_XMessage(CRoomBase) + End_XMessage() + +private: + CRoomBase(const CRoomBase&) : CFrameBase(module_ClassroomWinData) {}; + CRoomBase& operator=(const CRoomBase&){return *this;}; + +protected: + // ˽нṹ塢typedefȶ崦 + + // ˽к崦: + // void _Test(); +protected: + // Ա +}; + +class CRoom_CPP : public CRoomBase +{ +public: +}; diff --git a/Client/Client/Logic/room/RoomMgr.cpp b/Client/Client/Logic/room/RoomMgr.cpp new file mode 100644 index 00000000..56431a1f --- /dev/null +++ b/Client/Client/Logic/room/RoomMgr.cpp @@ -0,0 +1,92 @@ +#include "stdafx.h" +#include "RoomMgr.h" + +CRoomMgr::CRoomMgr() : CFrameBase(module_RoomListData) +{ + m_frame = NULL; +} + +CRoomMgr::~CRoomMgr() +{ + +} + +ResultCode CRoomMgr::Initialize( IModule* UpperFrame/*=NULL*/ ) +{ + m_frame = dynamic_cast(UpperFrame); + ATLASSERT(m_frame); + return Result_Success; +} + +ResultCode CRoomMgr::UnInitialize() +{ + return Result_Success; +} + +ResultCode CRoomMgr::Run() +{ + netHelper.AddFilter(MSG_AnswerClassList_Id, this); + netHelper.StartListen(); + return Result_Success; +} + +ResultCode CRoomMgr::Terminate() +{ + netHelper.StopListen(); + return Result_Success; +} + +ResultCode CRoomMgr::CreateRoom( RoomID& id ) +{ + return Result_NotImpl; +} + +ResultCode CRoomMgr::GetRoom( RoomID id,CRoomBase* room ) +{ + return Result_NotImpl; +} + +ResultCode CRoomMgr::FreeRoom( RoomID id ) +{ + return Result_NotImpl; +} + +ResultCode CRoomMgr::Show( BOOL bShow/*=TRUE*/ ) +{ + return Result_Success; +} + +ResultCode CRoomMgr::GetRoomList() +{ + INetCenter *pNetCenter = NULL; + Global->GetINetCenter(&pNetCenter); + if(pNetCenter) + { + MSG_RequestClassList netMsg; + pNetCenter->SendServer(netMsg); + return Result_Success; + } + return Result_Fail; +} + +VOID CRoomMgr::OnGetRoomList( XMessage *pMsg ) +{ + GetRoomList(); +} + +ResultCode CRoomMgr::OnNetMessage( const CMessage &msg ) +{ + switch(msg.MsgId()) + { + case MSG_AnswerClassList_Id: + MSG_AnswerClassList msgReal(msg); + XMessage_GetRoomList_Result result; + msgReal.GetRoomIdList(result.roomIdList); + msgReal.GetRoomNameList(result.roomNameList); + msgReal.GetRoomStateList(result.roomStateList); + SendXMessage(&result); + break; + } + return Result_Success; +} + diff --git a/Client/Client/Logic/room/RoomMgr.h b/Client/Client/Logic/room/RoomMgr.h new file mode 100644 index 00000000..3496be1e --- /dev/null +++ b/Client/Client/Logic/room/RoomMgr.h @@ -0,0 +1,35 @@ +#pragma once +#include "IRoomMgr.h" +#include "../../FrameWork/FrameBase.hpp" + +class CRoomMgr : public IRoomMgr + , public CFrameBase + , INetListener +{ +public: + CRoomMgr(); + ~CRoomMgr(); +public: + ResultCode Initialize(IModule* UpperFrame=NULL); + ResultCode UnInitialize(); + ResultCode Run(); + ResultCode Terminate(); + + ResultCode Show(BOOL bShow=TRUE); + ResultCode CreateRoom(RoomID& id); + ResultCode GetRoom(RoomID id,CRoomBase* room); + ResultCode GetRoomList(); + ResultCode FreeRoom(RoomID id); + + ResultCode OnNetMessage(const CMessage &msg); + + VOID OnGetRoomList(XMessage *pMsg); + + Begin_XMessage(CRoomMgr) + OnXMessage(XMessage_GetRoomList, OnGetRoomList) + End_XMessage() + +private: + IFrameWork *m_frame; + CNetListenerHelper netHelper; +}; diff --git a/Client/Client/Logic/room/roommgrTest.cpp b/Client/Client/Logic/room/roommgrTest.cpp new file mode 100644 index 00000000..e1fd535e --- /dev/null +++ b/Client/Client/Logic/room/roommgrTest.cpp @@ -0,0 +1,63 @@ +#ifdef CPPTEST + +#include "stdafx.h" +#include +#include "TestClassHeader.h" + +class CRoomMgrTest : public CTestBase +{ + CPPUNIT_TEST_SUITE(CRoomMgrTest); + CPPUNIT_TEST(TestGetRoomList); + CPPUNIT_TEST_SUITE_END(); + +public: + std::vector roomIdList; + std::vector roomNameList; + std::vector roomState; + + CRoomMgrTest() : CTestBase() + { + } + + Begin_XMessage(CRoomMgrTest) + OnXMessage(XMessage_GetRoomList_Result, OnGetRoomListResult); + End_XMessage(); + + VOID TestGetRoomList() + { + INetCenter* pNetCenter=NULL; + Global->GetINetCenter(&pNetCenter); + CPPUNIT_ASSERT(pNetCenter); + if(!pNetCenter) + { + return; + } + + MSG_AnswerClassList netMsg; + roomIdList.push_back(1); + roomNameList.push_back("a"); + roomState.push_back(0); + + roomIdList.push_back(2); + roomNameList.push_back("b"); + roomState.push_back(1); + + netMsg.SetRoomIdList(roomIdList); + netMsg.SetRoomNameList(roomNameList); + netMsg.SetRoomStateList(roomState); + + pNetCenter->MockReceive(&netMsg); + } + + VOID OnGetRoomListResult(XMessage_GetRoomList_Result *pmsg) + { + CPPUNIT_ASSERT(roomIdList == pmsg->roomIdList); + CPPUNIT_ASSERT(roomNameList == pmsg->roomNameList); + CPPUNIT_ASSERT(roomState == pmsg->roomStateList); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(CRoomMgrTest); +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CRoomMgrTest, "testRoomMgr"); + +#endif \ No newline at end of file diff --git a/Client/Client/Resource.rc b/Client/Client/Resource.rc new file mode 100644 index 00000000..3687bbf3 Binary files /dev/null and b/Client/Client/Resource.rc differ diff --git a/VNOC/VNOC/config.xml b/Client/Client/Resource/config.xml similarity index 96% rename from VNOC/VNOC/config.xml rename to Client/Client/Resource/config.xml index 618a5913..6968fa23 100644 --- a/VNOC/VNOC/config.xml +++ b/Client/Client/Resource/config.xml @@ -1,17 +1,17 @@ - - - - - - - - - 1 - - - Courier New - This is Test - - - -root + + + + + + + + + 1 + + + Courier New + This is Test + + + +root diff --git a/VNOC/VNOC/Config.cpp b/Client/Client/config/Config.cpp similarity index 84% rename from VNOC/VNOC/Config.cpp rename to Client/Client/config/Config.cpp index f2525174..b4c461f6 100644 --- a/VNOC/VNOC/Config.cpp +++ b/Client/Client/config/Config.cpp @@ -1,437 +1,436 @@ -#include "StdAfx.h" -#include "Config.h" -#include "../util/util.h" - -////////////////////////////////////////////////////////////////////////// -// ConfigNode -ConfigNode::ConfigNode() -{ -} - -ConfigNode::~ConfigNode() -{ -// attr.clear(); -// ConfigBranchs::iterator i; -// for (i=branch.begin(); i!=branch.end(); ++i) -// { -// ConfigVec::iterator j; -// for (j=i->second.begin(); j!=i->second.end(); ++j) -// { -// delete &(*j); -// } -// } -} - -ConfigNode& CConfig::GetNode(UINT index) -{ - ASSERT(index < m_vec.size()); - if (index < m_vec.size()) - { - return *m_vec[index]; - } - return emptyNode; -} - -ConfigNode& CConfig::operator [](UINT index) -{ - return GetNode(index); -} - -BOOL ConfigNode::GetAttribute(LPCTSTR key,CString& value) -{ - value.Empty(); - AttributeMap::iterator i; - i = attr.find(key); - if (i != attr.end()) - { - value = i->second; - return TRUE; - } - return FALSE; -} - -BOOL ConfigNode::GetAttribute(LPCTSTR key,int& value) -{ - CString attrValue; - if (GetAttribute(key,attrValue)) - { - value = _ttoi(attrValue); - return TRUE; - } - return FALSE; -} - -BOOL ConfigNode::GetAttribute(LPCTSTR key,UINT& value) -{ - CString attrValue; - if (GetAttribute(key,attrValue)) - { - value = (UINT)_ttoi(attrValue); - return TRUE; - } - return FALSE; -} - -BOOL ConfigNode::GetAttribute(LPCTSTR key,double& value) -{ - CString attrValue; - if (GetAttribute(key,attrValue)) - { - value = _ttof(attrValue); - return TRUE; - } - return FALSE; -} - -VOID ConfigNode::SetAttribute(LPCTSTR key,LPCTSTR value) -{ - ATLASSERT(value); - if (value) - { - attr[key] = value; - } -} - -VOID ConfigNode::SetAttribute(LPCTSTR key,int value) -{ - CString str; - str.Format(_T("%d"),value); - SetAttribute(key,str); -} - -VOID ConfigNode::SetAttribute(LPCTSTR key,UINT value) -{ - SetAttribute(key,(int)value); -} - -VOID ConfigNode::SetAttribute(LPCTSTR key,double value) -{ - CString str; - str.Format(_T("%lf"),value); - SetAttribute(key,str); -} - -////////////////////////////////////////////////////////////////////////// -// CConfig - -void CConfig::xPath(LPCTSTR cfgPath) -{ - CString tempStr = cfgPath; - LPTSTR thePath = tempStr.GetBuffer(tempStr.GetLength()); - ASSERT(thePath); - if (thePath) - { - LPCTSTR currPos = thePath; - LPCTSTR startPos = thePath; - do - { - if (*thePath == ConfigPathSplit) - { - *thePath = _T('\0'); - path.push_back(startPos); - ++thePath; - while(*thePath == ConfigPathSplit) - { //ֹд˶'/' - ++thePath; - } - startPos = thePath; - } - else if(*thePath == _T('\0')) - { - path.push_back(startPos); - startPos = thePath; - } - else - { - ++thePath; - } - } while (*startPos); - } - tempStr.ReleaseBuffer(0);; -} - -CConfig::CConfig() -{} - -CConfig::CConfig(LPCTSTR path) -{ - xPath(path); -} - -CConfig::~CConfig() -{ -} - -BOOL CConfig::Get(LPCTSTR path) -{ - if (path) - { - xPath(path); - } - IConfig *pConf=NULL; - Global->GetIConfig(&pConf); - if (pConf) - { - HRESULT hr = pConf->Get(this->path,m_vec); - return SUCCEEDED(hr); - } - return FALSE; -} - -UINT CConfig::Count() -{ - return m_vec.size(); -} - -////////////////////////////////////////////////////////////////////////// -// CConfigImpl - -CConfigImpl::CConfigImpl(void) -{ -} - -CConfigImpl::~CConfigImpl(void) -{ -} - -HRESULT CConfigImpl::Initialize( IModule* UpperFrame/*=NULL*/ ) -{ - Global->Log(LogFile_Config,_T("ʼ")); - return S_OK; -} - -HRESULT CConfigImpl::UnInitialize() -{ - Global->Log(LogFile_Config,_T("ʼ")); - _Clear(); - return S_OK; -} - -HRESULT CConfigImpl::Run() -{ - Global->Log(LogFile_Config,_T("Configģ")); - return S_OK; -} - -HRESULT CConfigImpl::Terminate() -{ - Global->Log(LogFile_Config,_T("Configģֹ")); - return S_OK; -} - -HRESULT CConfigImpl::LoadConfigFromXML( LPCTSTR filePath ) -{ - Global->Log(LogFile_Config,_T("ʼXML")); - TiXmlDocument doc; - doc.Clear(); - BOOL bRet = doc.LoadFile(CStringA(filePath)); // ӵֻ֧UTF8 - assert(bRet && "xmlļ쳣"); - if (bRet) - { - m_filePath = filePath; - Global->Log(LogFile_Config,_T("ļسɹ")); - CLogPrefix p(LogFile_Config,_T("[XML]")); - CLogIndent i(LogFile_Config); - bRet = _ParseXML(doc.RootElement(),m_rootNode); - } - Global->Log(LogFile_Config,_T("XMLع")); - return bRet? S_OK:S_FALSE; -} - -// roottreeRoot.branch -BOOL CConfigImpl::_ParseXML(TiXmlNode *root,ConfigNode& treeRoot) -{ - CLogIndent li(LogFile_Config); - TiXmlNode *curr = root; - - while(curr) - { - ConfigVec& i = treeRoot.branch[CString(curr->Value())]; - - ConfigNode newNode; - - _ParseXMLNode(curr,newNode); - if (curr->FirstChild()) - { - _ParseXML(curr->FirstChild(),newNode); - } - i.push_back(newNode); - - curr = curr->NextSibling(); - } - assert(root && "ڵΪ"); - return TRUE; -} - -BOOL CConfigImpl::_ParseXMLNode( TiXmlNode *tiNode,ConfigNode& node ) -{ - CLogIndent i(LogFile_Config); - - int type = tiNode->Type(); - Global->Logf(LogFile_Config,_T("õ(value = %s,type = %d)"),CString(tiNode->ValueStr().c_str()),type); - node.value = tiNode->ValueStr().c_str(); - switch(type) - { - case TiXmlNode::TINYXML_ELEMENT: - TiXmlAttribute *attr = tiNode->ToElement()->FirstAttribute(); - if (attr) - { - Global->Log(LogFile_Config,_T("(Attributes:"),FALSE,FALSE); - while(attr) - { - Global->Lognf(LogFile_Config,_T("|%s:%s|"),CString(attr->Name()),CString(attr->Value())); - node.attr.insert(std::make_pair(CString(attr->Name()), CString(attr->Value()))); - attr = attr->Next(); - } - Global->Log(LogFile_Config,_T(")"),FALSE,FALSE); - } - } - Global->Log(LogFile_Config,_T("\n"),FALSE,FALSE); - return TRUE; -} - -HRESULT CConfigImpl::SaveConfigToXML( LPCTSTR filePath ) -{ - if (filePath == NULL) - { - filePath = m_filePath; - } - TiXmlDocument doc; - if (!doc.RootElement()) - { - TiXmlElement rootElement("root"); // ֵҪддһ - doc.InsertEndChild(rootElement); - } - doc.RootElement()->Clear(); - Global->Log(LogFile_Config,_T("XML.")); - BOOL bRet = _CreateXML(doc,m_rootNode); - Global->Logf(LogFile_Config,_T("XML%s.\n"),bRet? _T("ɹ"): _T("ʧ")); - if (bRet) - { - bool bRet = doc.SaveFile(CStringA(filePath)); - } - return bRet? S_OK: E_FAIL; -} - -BOOL CConfigImpl::_CreateXML(TiXmlNode& tree,const ConfigNode& root ) -{ - CLogPrefix lp(LogFile_Config,_T("CreateTree")); - - ConfigBranchs::const_iterator i; - for (i=root.branch.begin(); i!=root.branch.end(); ++i) - { - ConfigVec::const_iterator j; - for (j=i->second.begin(); j!=i->second.end(); ++j) - { - TiXmlNode* pNode=NULL; - BOOL bRet = _CreateXMLNode(&pNode,*j); - _CreateXML(*pNode,*j); - if (bRet && pNode) - { - tree.InsertEndChild(*pNode); - delete pNode; - } - } - } - return TRUE; -} - -BOOL CConfigImpl::_CreateXMLNode(TiXmlNode **node,const ConfigNode& root) -{ - if (!node) - { - return FALSE; - } - ATLASSERT(!*node); - ATLASSERT(!root.value.IsEmpty()); - if (!root.value.IsEmpty()) - { - if (root.branch.empty() && root.attr.empty()) - { - *node = new TiXmlText(CStringA(root.value)); - Global->PtrAssert(*node); - } - else - { - *node = new TiXmlElement(CStringA(root.value)); - Global->PtrAssert(*node); - TiXmlElement* element = (*node)->ToElement(); - - AttributeMap::const_iterator i; - for (i=root.attr.begin(); i!=root.attr.end(); ++i) - { - element->SetAttribute(CStringA(i->first),CStringA(i->second)); - } - } - return TRUE; - } - return FALSE; -} - -HRESULT CConfigImpl::Get(const ConfigPath& path,ConfigPtrVec& node ) -{ - Util::CAutoCS ac(m_cs); - CLogPrefix lp(LogFile_Config,_T("[Config]")); - BOOL bRet = _Find(path,node); - if (bRet) - { - Global->Logf(LogFile_Config,_T("ȡֵɹ.")); - return S_OK; - } - else - { - Global->Log(LogFile_Config,_T("ȡʧܣڽڵ")); - return E_FAIL; - } -} - -BOOL CConfigImpl::_Find( ConfigPath path,ConfigPtrVec& vec,BOOL createIfNotExist/*=FALSE*/ ) -{ - if (path.empty()) - { - return FALSE; - } - ConfigPath::iterator i; - ConfigNode *pCurr = &m_rootNode; - - ConfigBranchs::iterator j; - for(i=path.begin(); i!=path.end(); ++i) - { - j = pCurr->branch.find(*i); - if (j == pCurr->branch.end()) - { - if (createIfNotExist) - { - ConfigNode node; - node.value = *i; - pCurr->branch[*i].push_back(node); - } - else - { - return FALSE; - } - } - pCurr = &((j->second)[0]); - } - ConfigVec::iterator iVec; - for(iVec=j->second.begin(); iVec!=j->second.end(); ++iVec) - { - vec.push_back(&(*iVec)); - } - return TRUE; -} - -VOID CConfigImpl::_Clear() -{ - m_rootNode.branch.clear(); -} - -HRESULT CConfigImpl::AddMonitor( ConfigPath path,IConfigMonitor* pMonitor ) -{ - return S_OK; -} - -HRESULT CConfigImpl::RemoveMonitor( IConfigMonitor* pMonitor ) -{ - return S_OK; -} +#include "StdAfx.h" +#include "Config.h" + +////////////////////////////////////////////////////////////////////////// +// ConfigNode +ConfigNode::ConfigNode() +{ +} + +ConfigNode::~ConfigNode() +{ +// attr.clear(); +// ConfigBranchs::iterator i; +// for (i=branch.begin(); i!=branch.end(); ++i) +// { +// ConfigVec::iterator j; +// for (j=i->second.begin(); j!=i->second.end(); ++j) +// { +// delete &(*j); +// } +// } +} + +ConfigNode& CConfig::GetNode(UINT index) +{ + ATLASSERT(index < m_vec.size()); + if (index < m_vec.size()) + { + return *m_vec[index]; + } + return emptyNode; +} + +ConfigNode& CConfig::operator [](UINT index) +{ + return GetNode(index); +} + +BOOL ConfigNode::GetAttribute(LPCTSTR key,CString& value) +{ + value.Empty(); + AttributeMap::iterator i; + i = attr.find(key); + if (i != attr.end()) + { + value = i->second; + return TRUE; + } + return FALSE; +} + +BOOL ConfigNode::GetAttribute(LPCTSTR key,int& value) +{ + CString attrValue; + if (GetAttribute(key,attrValue)) + { + value = _ttoi(attrValue); + return TRUE; + } + return FALSE; +} + +BOOL ConfigNode::GetAttribute(LPCTSTR key,UINT& value) +{ + CString attrValue; + if (GetAttribute(key,attrValue)) + { + value = (UINT)_ttoi(attrValue); + return TRUE; + } + return FALSE; +} + +BOOL ConfigNode::GetAttribute(LPCTSTR key,double& value) +{ + CString attrValue; + if (GetAttribute(key,attrValue)) + { + value = _ttof(attrValue); + return TRUE; + } + return FALSE; +} + +VOID ConfigNode::SetAttribute(LPCTSTR key,LPCTSTR value) +{ + ATLASSERT(value); + if (value) + { + attr[key] = value; + } +} + +VOID ConfigNode::SetAttribute(LPCTSTR key,int value) +{ + CString str; + str.Format(_T("%d"),value); + SetAttribute(key,str); +} + +VOID ConfigNode::SetAttribute(LPCTSTR key,UINT value) +{ + SetAttribute(key,(int)value); +} + +VOID ConfigNode::SetAttribute(LPCTSTR key,double value) +{ + CString str; + str.Format(_T("%lf"),value); + SetAttribute(key,str); +} + +////////////////////////////////////////////////////////////////////////// +// CConfig + +void CConfig::xPath(LPCTSTR cfgPath) +{ + CString tempStr = cfgPath; + LPTSTR thePath = tempStr.GetBuffer(tempStr.GetLength()); + ATLASSERT(thePath); + if (thePath) + { + LPCTSTR currPos = thePath; + LPCTSTR startPos = thePath; + do + { + if (*thePath == ConfigPathSplit) + { + *thePath = _T('\0'); + path.push_back(startPos); + ++thePath; + while(*thePath == ConfigPathSplit) + { //ֹд˶'/' + ++thePath; + } + startPos = thePath; + } + else if(*thePath == _T('\0')) + { + path.push_back(startPos); + startPos = thePath; + } + else + { + ++thePath; + } + } while (*startPos); + } + tempStr.ReleaseBuffer(0);; +} + +CConfig::CConfig() +{} + +CConfig::CConfig(LPCTSTR path) +{ + xPath(path); +} + +CConfig::~CConfig() +{ +} + +BOOL CConfig::Get(LPCTSTR path) +{ + if (path) + { + xPath(path); + } + IConfig *pConf=NULL; + Global->GetIConfig(&pConf); + if (pConf) + { + ResultCode hr = pConf->Get(this->path,m_vec); + return SUCCEEDED(hr); + } + return FALSE; +} + +UINT CConfig::Count() +{ + return m_vec.size(); +} + +////////////////////////////////////////////////////////////////////////// +// CConfigImpl + +CConfigImpl::CConfigImpl(void) +{ +} + +CConfigImpl::~CConfigImpl(void) +{ +} + +ResultCode CConfigImpl::Initialize( IModule* UpperFrame/*=NULL*/ ) +{ + Global->Log(LogFile_Config,_T("ʼ")); + return Result_Success; +} + +ResultCode CConfigImpl::UnInitialize() +{ + Global->Log(LogFile_Config,_T("ʼ")); + _Clear(); + return Result_Success; +} + +ResultCode CConfigImpl::Run() +{ + Global->Log(LogFile_Config,_T("Configģ")); + return Result_Success; +} + +ResultCode CConfigImpl::Terminate() +{ + Global->Log(LogFile_Config,_T("Configģֹ")); + return Result_Success; +} + +ResultCode CConfigImpl::LoadConfigFromXML( LPCTSTR filePath ) +{ + Global->Log(LogFile_Config,_T("ʼXML")); + TiXmlDocument doc; + doc.Clear(); + BOOL bRet = doc.LoadFile(CStringA(filePath)); // ӵֻ֧UTF8 + ATLASSERT(bRet && "xmlļ쳣"); + if (bRet) + { + m_filePath = filePath; + Global->Log(LogFile_Config,_T("ļسɹ")); + CLogPrefix p(LogFile_Config,_T("[XML]")); + CLogIndent i(LogFile_Config); + bRet = _ParseXML(doc.RootElement(),m_rootNode); + } + Global->Log(LogFile_Config,_T("XMLع")); + return bRet? Result_Success:Result_Fail; +} + +// roottreeRoot.branch +BOOL CConfigImpl::_ParseXML(TiXmlNode *root,ConfigNode& treeRoot) +{ + CLogIndent li(LogFile_Config); + TiXmlNode *curr = root; + + while(curr) + { + ConfigVec& i = treeRoot.branch[CString(curr->Value())]; + + ConfigNode newNode; + + _ParseXMLNode(curr,newNode); + if (curr->FirstChild()) + { + _ParseXML(curr->FirstChild(),newNode); + } + i.push_back(newNode); + + curr = curr->NextSibling(); + } + ATLASSERT(root && "ڵΪ"); + return TRUE; +} + +BOOL CConfigImpl::_ParseXMLNode( TiXmlNode *tiNode,ConfigNode& node ) +{ + CLogIndent i(LogFile_Config); + + int type = tiNode->Type(); + Global->Logf(LogFile_Config,_T("õ(value = %s,type = %d)"),CString(tiNode->ValueTStr().c_str()),type); + node.value = tiNode->ValueTStr().c_str(); + switch(type) + { + case TiXmlNode::ELEMENT: + TiXmlAttribute *attr = tiNode->ToElement()->FirstAttribute(); + if (attr) + { + Global->Log(LogFile_Config,_T("(Attributes:"),FALSE,FALSE); + while(attr) + { + Global->Lognf(LogFile_Config,_T("|%s:%s|"),CString(attr->Name()),CString(attr->Value())); + node.attr.insert(std::make_pair(CString(attr->Name()), CString(attr->Value()))); + attr = attr->Next(); + } + Global->Log(LogFile_Config,_T(")"),FALSE,FALSE); + } + } + Global->Log(LogFile_Config,_T("\n"),FALSE,FALSE); + return TRUE; +} + +ResultCode CConfigImpl::SaveConfigToXML( LPCTSTR filePath ) +{ + if (filePath == NULL) + { + filePath = m_filePath; + } + TiXmlDocument doc; + if (!doc.RootElement()) + { + TiXmlElement rootElement("root"); // ֵҪддһ + doc.InsertEndChild(rootElement); + } + doc.RootElement()->Clear(); + Global->Log(LogFile_Config,_T("XML.")); + BOOL bRet = _CreateXML(doc,m_rootNode); + Global->Logf(LogFile_Config,_T("XML%s.\n"),bRet? _T("ɹ"): _T("ʧ")); + if (bRet) + { + bool bRet = doc.SaveFile(CStringA(filePath)); + } + return bRet? Result_Success: Result_Fail; +} + +BOOL CConfigImpl::_CreateXML(TiXmlNode& tree,const ConfigNode& root ) +{ + CLogPrefix lp(LogFile_Config,_T("CreateTree")); + + ConfigBranchs::const_iterator i; + for (i=root.branch.begin(); i!=root.branch.end(); ++i) + { + ConfigVec::const_iterator j; + for (j=i->second.begin(); j!=i->second.end(); ++j) + { + TiXmlNode* pNode=NULL; + BOOL bRet = _CreateXMLNode(&pNode,*j); + _CreateXML(*pNode,*j); + if (bRet && pNode) + { + tree.InsertEndChild(*pNode); + delete pNode; + } + } + } + return TRUE; +} + +BOOL CConfigImpl::_CreateXMLNode(TiXmlNode **node,const ConfigNode& root) +{ + if (!node) + { + return FALSE; + } + ATLASSERT(!*node); + ATLASSERT(!root.value.IsEmpty()); + if (!root.value.IsEmpty()) + { + if (root.branch.empty() && root.attr.empty()) + { + *node = new TiXmlText(CStringA(root.value)); + Global->PtrAssert(*node); + } + else + { + *node = new TiXmlElement(CStringA(root.value)); + Global->PtrAssert(*node); + TiXmlElement* element = (*node)->ToElement(); + + AttributeMap::const_iterator i; + for (i=root.attr.begin(); i!=root.attr.end(); ++i) + { + element->SetAttribute(CStringA(i->first),CStringA(i->second)); + } + } + return TRUE; + } + return FALSE; +} + +ResultCode CConfigImpl::Get(const ConfigPath& path,ConfigPtrVec& node ) +{ + Util::CAutoCS ac(m_cs); + CLogPrefix lp(LogFile_Config,_T("[Config]")); + BOOL bRet = _Find(path,node); + if (bRet) + { + Global->Logf(LogFile_Config,_T("ȡֵɹ.")); + return Result_Success; + } + else + { + Global->Log(LogFile_Config,_T("ȡʧܣڽڵ")); + return Result_Fail; + } +} + +BOOL CConfigImpl::_Find( ConfigPath path,ConfigPtrVec& vec,BOOL createIfNotExist/*=FALSE*/ ) +{ + if (path.empty()) + { + return FALSE; + } + ConfigPath::iterator i; + ConfigNode *pCurr = &m_rootNode; + + ConfigBranchs::iterator j; + for(i=path.begin(); i!=path.end(); ++i) + { + j = pCurr->branch.find(*i); + if (j == pCurr->branch.end()) + { + if (createIfNotExist) + { + ConfigNode node; + node.value = *i; + pCurr->branch[*i].push_back(node); + } + else + { + return FALSE; + } + } + pCurr = &((j->second)[0]); + } + ConfigVec::iterator iVec; + for(iVec=j->second.begin(); iVec!=j->second.end(); ++iVec) + { + vec.push_back(&(*iVec)); + } + return TRUE; +} + +VOID CConfigImpl::_Clear() +{ + m_rootNode.branch.clear(); +} + +ResultCode CConfigImpl::AddMonitor( ConfigPath path,IConfigMonitor* pMonitor ) +{ + return Result_Success; +} + +ResultCode CConfigImpl::RemoveMonitor( IConfigMonitor* pMonitor ) +{ + return Result_Success; +} diff --git a/VNOC/VNOC/Config.h b/Client/Client/config/Config.h similarity index 55% rename from VNOC/VNOC/Config.h rename to Client/Client/config/Config.h index b769f9fb..b991d808 100644 --- a/VNOC/VNOC/Config.h +++ b/Client/Client/config/Config.h @@ -1,37 +1,37 @@ -#pragma once -#include "../../TinyXML/tinyxml.h" -#include -#include -#include -#include "IConfig.h" - -class CConfigImpl : public IConfig -{ -public: - CConfigImpl(void); - ~CConfigImpl(void); -public: - STDMETHOD( Initialize(IModule* UpperFrame=NULL) ); - STDMETHOD( UnInitialize() ); - STDMETHOD( Run() ); - STDMETHOD( Terminate() ); - STDMETHOD( LoadConfigFromXML(LPCTSTR filePath) ); - STDMETHOD( SaveConfigToXML(LPCTSTR filePath=NULL) ); - STDMETHOD( Get(const ConfigPath& path,ConfigPtrVec& node) ); - STDMETHOD( AddMonitor(ConfigPath path,IConfigMonitor* pMonitor)); - STDMETHOD( RemoveMonitor(IConfigMonitor* pMonitor) ); - BOOL RegisterConfigNodeOwner(); -private: - BOOL _ParseXML(TiXmlNode *root,ConfigNode& treeRoot); - BOOL _ParseXMLNode(TiXmlNode *node,ConfigNode& cfg); - - BOOL _CreateXML(TiXmlNode& tree,const ConfigNode& root); - BOOL _CreateXMLNode(TiXmlNode **node,const ConfigNode& root); - - BOOL _Find(ConfigPath path,ConfigPtrVec& vec,BOOL createIfNotExist=FALSE); - VOID _Clear(); -private: - CString m_filePath; - ConfigNode m_rootNode; - ATL::CCriticalSection m_cs; -}; +#pragma once +#include "TinyXML/tinyxml.h" +#include +#include +#include +#include "IConfig.h" + +class CConfigImpl : public IConfig +{ +public: + CConfigImpl(void); + ~CConfigImpl(void); +public: + virtual ResultCode Initialize(IModule* UpperFrame=NULL); + virtual ResultCode UnInitialize(); + virtual ResultCode Run(); + virtual ResultCode Terminate(); + virtual ResultCode LoadConfigFromXML(LPCTSTR filePath); + virtual ResultCode SaveConfigToXML(LPCTSTR filePath=NULL); + virtual ResultCode Get(const ConfigPath& path,ConfigPtrVec& node); + virtual ResultCode AddMonitor(ConfigPath path,IConfigMonitor* pMonitor); + virtual ResultCode RemoveMonitor(IConfigMonitor* pMonitor); + BOOL RegisterConfigNodeOwner(); +private: + BOOL _ParseXML(TiXmlNode *root,ConfigNode& treeRoot); + BOOL _ParseXMLNode(TiXmlNode *node,ConfigNode& cfg); + + BOOL _CreateXML(TiXmlNode& tree,const ConfigNode& root); + BOOL _CreateXMLNode(TiXmlNode **node,const ConfigNode& root); + + BOOL _Find(ConfigPath path,ConfigPtrVec& vec,BOOL createIfNotExist=FALSE); + VOID _Clear(); +private: + CString m_filePath; + ConfigNode m_rootNode; + ATL::CCriticalSection m_cs; +}; diff --git a/VNOC/VNOC/ConfigDefine.h b/Client/Client/config/ConfigDefine.h similarity index 92% rename from VNOC/VNOC/ConfigDefine.h rename to Client/Client/config/ConfigDefine.h index ee178c7b..2ac17dd8 100644 --- a/VNOC/VNOC/ConfigDefine.h +++ b/Client/Client/config/ConfigDefine.h @@ -1,11 +1,12 @@ -#pragma once - -#include -#include -#include -#include - -// ڵײַͨȡģֱʹַʽ -typedef std::map AttributeMap; -typedef std::vector ConfigPath; - +#pragma once + +#include +#include +#include +#include +#include + +// ڵײַͨȡģֱʹַʽ +typedef std::map AttributeMap; +typedef std::vector ConfigPath; + diff --git a/VNOC/VNOC/IConfig.h b/Client/Client/config/IConfig.h similarity index 66% rename from VNOC/VNOC/IConfig.h rename to Client/Client/config/IConfig.h index a9b3b83c..204cee79 100644 --- a/VNOC/VNOC/IConfig.h +++ b/Client/Client/config/IConfig.h @@ -1,93 +1,84 @@ -#pragma once -#include "IModule.h" -#include "ConfigDefine.h" -#include "ILanguage.h" - -class ConfigNode; - -typedef std::vector ConfigVec; -typedef std::vector ConfigPtrVec; -typedef std::map ConfigBranchs; - -class ConfigNode -{ -public: - CString value; - AttributeMap attr; // Ա - ConfigBranchs branch; // - - virtual BOOL GetAttribute(LPCTSTR key,CString& value); - virtual BOOL GetAttribute(LPCTSTR key,int& value); - virtual BOOL GetAttribute(LPCTSTR key,UINT& value); - virtual BOOL GetAttribute(LPCTSTR key,double& value); - virtual VOID SetAttribute(LPCTSTR key,LPCTSTR value); - virtual VOID SetAttribute(LPCTSTR key,int value); - virtual VOID SetAttribute(LPCTSTR key,UINT value); - virtual VOID SetAttribute(LPCTSTR key,double value); - - ConfigNode(); - ~ConfigNode(); -}; - -class CConfig -{ -public: - CConfig(); - CConfig(LPCTSTR path); - ~CConfig(); - - // xml· - ConfigPath path; - - // 趨path֮Getȡ - // ֶpathpathԲ - BOOL Get(LPCTSTR path=NULL); - - // ڵ - UINT Count(); - // ȡڵ㡣ʱһpathӦcountڵ㡣 - // жԸõ޸Ķõġ - // indexΧһսڵ - ConfigNode& GetNode(UINT index=0); - ConfigNode& operator[](UINT index); - // ͨԲҵһϵĽڵ㡣 - ConfigNode& GetNodeByAttr(LPCTSTR key,LPCTSTR value); - ConfigNode& GetNodeByAttr(LPCTSTR key,int value); - ConfigNode& GetNodeByAttr(LPCTSTR key,double value); -private: - void xPath(LPCTSTR path); - ConfigPtrVec m_vec; - ConfigNode emptyNode; -}; - -interface IConfigMonitor -{ - STDMETHOD( ConfigChanged(const ConfigNode& node) = 0 ); - // һ߼û - STDMETHOD( LanguageChanged(CString language) = 0); -}; - -// ԶڴУʱȡҪʱ仺ûжʧ -interface IConfig : public IModule -{ -public: - STDMETHOD( LoadConfigFromXML(LPCTSTR filePath) = 0 ); - STDMETHOD( SaveConfigToXML(LPCTSTR filePath=NULL) = 0 ); // Ĭϴʱļ - - ////////////////////////////////////////////////////////////////////////// - // ӿڲҪֱʹãCConfig˷װ - // ֵ: - // E_FAIL ڸýڵ㡣 - // S_OK ˳ȡ - STDMETHOD( Get(const ConfigPath& path,ConfigPtrVec& node) = 0 ); - - // Ӽӡһýڵκνڵ㱻޸ģõ֪ͨ - STDMETHOD( AddMonitor(ConfigPath path,IConfigMonitor* pMonitor) = 0 ); - //! ǰһҪɾȻ - STDMETHOD( RemoveMonitor(IConfigMonitor* pMonitor) = 0 ); - // ֪ͨı䡣ݹ֪ͨ -}; - -////////////////////////////////////////////////////////////////////////// -// -#include "Config.inl" +#pragma once +#include "IModule.h" +#include "ConfigDefine.h" + +class ConfigNode; + +typedef std::vector ConfigVec; +typedef std::vector ConfigPtrVec; +typedef std::map ConfigBranchs; + +class ConfigNode +{ +public: + CString value; + AttributeMap attr; // Ա + ConfigBranchs branch; // + + virtual BOOL GetAttribute(LPCTSTR key,CString& value); + virtual BOOL GetAttribute(LPCTSTR key,int& value); + virtual BOOL GetAttribute(LPCTSTR key,UINT& value); + virtual BOOL GetAttribute(LPCTSTR key,double& value); + virtual VOID SetAttribute(LPCTSTR key,LPCTSTR value); + virtual VOID SetAttribute(LPCTSTR key,int value); + virtual VOID SetAttribute(LPCTSTR key,UINT value); + virtual VOID SetAttribute(LPCTSTR key,double value); + + ConfigNode(); + ~ConfigNode(); +}; + +class CConfig +{ +public: + CConfig(); + CConfig(LPCTSTR path); + ~CConfig(); + + // xml· + ConfigPath path; + + // 趨path֮Getȡ + // ֶpathpathԲ + BOOL Get(LPCTSTR path=NULL); + + // ڵ + UINT Count(); + // ȡڵ㡣ʱһpathӦcountڵ㡣 + // жԸõ޸Ķõġ + // indexΧһսڵ + ConfigNode& GetNode(UINT index=0); + ConfigNode& operator[](UINT index); + // ͨԲҵһϵĽڵ㡣 + ConfigNode& GetNodeByAttr(LPCTSTR key,LPCTSTR value); + ConfigNode& GetNodeByAttr(LPCTSTR key,int value); + ConfigNode& GetNodeByAttr(LPCTSTR key,double value); +private: + void xPath(LPCTSTR path); + ConfigPtrVec m_vec; + ConfigNode emptyNode; +}; + +interface IConfigMonitor +{ + virtual ResultCode ConfigChanged(const ConfigNode& node)=0; + // һ߼û + virtual ResultCode LanguageChanged(CString language)=0; +}; + +// ԶڴУʱȡҪʱ仺ûжʧ +interface IConfig : public IModule +{ +public: + virtual ResultCode LoadConfigFromXML(LPCTSTR filePath)=0; + virtual ResultCode SaveConfigToXML(LPCTSTR filePath=NULL)=0; + + // ҪֱʹãCConfig˷װ + virtual ResultCode Get(const ConfigPath& path,ConfigPtrVec& node)=0; + + virtual ResultCode AddMonitor(ConfigPath path,IConfigMonitor* pMonitor)=0; + virtual ResultCode RemoveMonitor(IConfigMonitor* pMonitor)=0; +}; + +////////////////////////////////////////////////////////////////////////// +// diff --git a/Client/Client/include/Error.hpp b/Client/Client/include/Error.hpp new file mode 100644 index 00000000..446febba --- /dev/null +++ b/Client/Client/include/Error.hpp @@ -0,0 +1,34 @@ +#pragma once +// ȫֵĴ + +#define ResultSucceeded(result) ((result&0xffffff00)? FALSE: TRUE) +#define ResultFailed(result) ((result&0xffffff00)? TRUE: FALSE) + +// ÿһԤ1024 +enum ResultCode +{ + Result_Success = 0, + Result_Fault = 1, // ok,but not good + ////////////////////////////////////////////////////////////////////////// + // + Result_Unknown = 256, + Result_NotSet, + Result_FatalError, + Result_Fail, + Result_InvalidParam, + Result_NotFound, + Result_NotImpl, + ////////////////////////////////////////////////////////////////////////// + // ˺ + Result_UserName_LengthError=1024, + Result_UserName_InvalidChar, + + Result_Pwd_LengthError = 1536, + Result_Pwd_InvalidChar, + + ////////////////////////////////////////////////////////////////////////// + // ̬ + Result_DynamicError = 0x80000000, + + Result_MaxID = 0xffffffff, +}; diff --git a/Client/Client/include/IModule.h b/Client/Client/include/IModule.h new file mode 100644 index 00000000..0c680258 --- /dev/null +++ b/Client/Client/include/IModule.h @@ -0,0 +1,26 @@ +#pragma once +#include "Error.hpp" + +interface IModule +{ +public: + // UpperFrameṩϲĽӿ + virtual ResultCode Initialize(IModule* UpperFrame=NULL) = 0 ; + virtual ResultCode UnInitialize() = 0; + + virtual ResultCode Run() = 0; + virtual ResultCode Terminate() = 0 ; + //! Terminate֮ģ飬ӦͨRunٴáUnInitializeģ򲻿 +}; + +// תӿ +template +void GetiModule(IModule* pBase,retType** pRet) +{ + ATLASSERT(pBase); ATLASSERT(pRet); + if (pRet && pBase) + { + *pRet = dynamic_cast(pBase); + ATLASSERT(pRet); + } +} \ No newline at end of file diff --git a/VNOC/VNOC/IRefCountImpl.h b/Client/Client/include/IRefCountImpl.h similarity index 93% rename from VNOC/VNOC/IRefCountImpl.h rename to Client/Client/include/IRefCountImpl.h index 07625dc9..9cf95288 100644 --- a/VNOC/VNOC/IRefCountImpl.h +++ b/Client/Client/include/IRefCountImpl.h @@ -1,28 +1,28 @@ -#pragma once -#include "unknwn.h" - -class IRefCountImpl : public IUnknown -{ -public: - IRefCountImpl() : m_refCount(0){} - virtual ~IRefCountImpl(){} - virtual ULONG STDMETHODCALLTYPE AddRef() - { - return InterlockedIncrement(&m_refCount); - } - virtual ULONG STDMETHODCALLTYPE Release() - { - unsigned long ul = 0; - if ((ul = InterlockedDecrement(&m_refCount)) == 0) - { - delete this; - } - return ul; - } - virtual HRESULT STDMETHODCALLTYPE QueryInterface(const IID &,void **) - { - return E_NOTIMPL; - } -private: - LONG m_refCount; +#pragma once +#include "unknwn.h" + +class IRefCountImpl : public IUnknown +{ +public: + IRefCountImpl() : m_refCount(0){} + virtual ~IRefCountImpl(){} + virtual ULONG STDMETHODCALLTYPE AddRef() + { + return InterlockedIncrement(&m_refCount); + } + virtual ULONG STDMETHODCALLTYPE Release() + { + unsigned long ul = 0; + if ((ul = InterlockedDecrement(&m_refCount)) == 0) + { + delete this; + } + return ul; + } + virtual HRESULT STDMETHODCALLTYPE QueryInterface(const IID &,void **) + { + return E_NOTIMPL; + } +protected: + LONG m_refCount; }; \ No newline at end of file diff --git a/Client/Client/include/TestClassHeader.h b/Client/Client/include/TestClassHeader.h new file mode 100644 index 00000000..ef98d5dd --- /dev/null +++ b/Client/Client/include/TestClassHeader.h @@ -0,0 +1,31 @@ +#include "../FrameWork/FrameBase.hpp" + +#include +#include + +enum TestUnitID +{ + TestUnit_Begin = module_CppTest_PrivateModule_Begin, + TestUnit_UserSession, + TestUnit_RoomMgr, + TestUnit_End = module_CppTest_PrivateModule_End +}; + +template +class CTestBase : public CppUnit::TestFixture ,public CFrameBase +{ +public: + void setUp() + { + IFrameWork* pFrameWork=NULL; + Global->GetIFrameModule(&pFrameWork); + pFrameWork->RegisterModule(this); + } + void tearDown() + { + IFrameWork* pFrameWork=NULL; + Global->GetIFrameModule(&pFrameWork); + pFrameWork->RemoveModule(this); + } + CTestBase():CFrameBase((FrameModule)(UINT)TID){}; +}; diff --git a/Client/Client/include/XMessage.hpp b/Client/Client/include/XMessage.hpp new file mode 100644 index 00000000..8435bb29 --- /dev/null +++ b/Client/Client/include/XMessage.hpp @@ -0,0 +1,93 @@ +#pragma once +#include "../FrameWork/FrameBase.hpp" +#include "../../../NMessage/MessageDef.h" +using namespace VNOC::Message::Define; + +////////////////////////////////////////////////////////////////////////// +// Messages + +// ϢȡģϢб +struct XMessage_GetListenList : public XMessage +{ + ImTheMessageOf(XMessage_GetListenList); + + std::list msgIDList; +}; + +////////////////////////////////////////////////////////////////////////// +// ½ + +struct XMessage_Login : public XMessage +{ + ImTheMessageOf(XMessage_Login); + + CString username; + CString pwd; +}; + +struct XMessage_LoginError : public XMessage +{ + ImTheMessageOf(XMessage_LoginError); + + ResultCode result; +}; + +struct XMessage_Login_Result : public XMessage +{ + ImTheMessageOf(XMessage_Login_Result); + + BOOL success; + uint32 userToken; + std::string guid; +}; + +struct XMessage_ShowLogin : public XMessage +{ + ImTheMessageOf(XMessage_ShowLogin); +}; + +////////////////////////////////////////////////////////////////////////// +// + +struct XMessage_ShowRoomListWnd : public XMessage +{ + ImTheMessageOf(XMessage_ShowRoomListWnd); +}; + + +struct XMessage_ShowRoomListWnd_Result : public XMessage +{ + ImTheMessageOf(XMessage_ShowRoomListWnd_Result); +}; + +struct XMessage_GetRoomList : public XMessage +{ + ImTheMessageOf(XMessage_GetRoomList); +}; + +struct XMessage_GetRoomList_Result : public XMessage +{ + ImTheMessageOf(XMessage_GetRoomList_Result); + + std::vector roomIdList; + std::vector roomNameList; + std::vector roomStateList; +}; + +struct XMessage_ShowClassroom : public XMessage +{ + ImTheMessageOf(XMessage_ShowClassroom); +}; + +////////////////////////////////////////////////////////////////////////// +// Framework + +struct XMessage_FrameStart : public XMessage +{ + ImTheMessageOf(XMessage_FrameStart); +}; + +struct XMessage_StartTest : public XMessage +{ + ImTheMessageOf(XMessage_StartTest); +}; \ No newline at end of file diff --git a/Client/Client/include/stdafx.h b/Client/Client/include/stdafx.h new file mode 100644 index 00000000..03e64824 --- /dev/null +++ b/Client/Client/include/stdafx.h @@ -0,0 +1,48 @@ +#pragma once + +#define _SECURE_ATL 1 +#define NOLAYERS + +// Windows Header Files: +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +// C RunTime Header Files +#include +#include +#include +#include + + +// TODO: reference additional headers your program requires here + +#include +#include +#include +#include + +#define _WTL_NO_CSTRING + +#include "../../../ThirdLibs/TinyXML/tinyxml.h" + +#include "../GUI/BKWin/wtl/atlapp.h" +#include "../GUI/BKWin/wtl/atlframe.h" +#include "../GUI/BKWin/wtl/atlctrls.h" +#include "../GUI/BKWin/wtl/atlctrlx.h" +#include "../GUI/BKWin/wtl/atldlgs.h" +#include "../GUI/BKWin/wtl/atlcrack.h" +#include "../GUI/BKWin/wtl/atlmisc.h" + +#include "../GUI/BKWin/bkwin/bkatldefine.h" +#include "../GUI/BKWin/bkwin/bklistview.h" +#include "../GUI/BKWin/bkwin/bkdlgview.h" +#include "../GUI/BKWin/bkwin/bkwnddlgfile.h" +#include "../GUI/BKWin/bkres/bkres.h" +#include "../GUI/BKWin/bkwin/ListViewCtrlEx.h" + +#include "../FrameWork/IGlobal.h" +#include "../util/util.h" +#include "XMessage.hpp" +using namespace VNOC::Message::Define; \ No newline at end of file diff --git a/Client/Client/net/INet.h b/Client/Client/net/INet.h new file mode 100644 index 00000000..57b76f10 --- /dev/null +++ b/Client/Client/net/INet.h @@ -0,0 +1,35 @@ +#pragma once +#include +#include "IModule.h" +#include "../../../NMessage/MessageUnion.h" +#include "../../../NMessage/CMessage.h" +using namespace VNOC::Message; + + +interface INetListener +{ + virtual ResultCode OnNetMessage(const CMessage &msg)=0; +}; + +interface INetCenter: public IModule +{ + virtual ResultCode IsServerConnected()=0; + virtual ResultCode SendServer(const CMessage &helper)=0; + virtual ResultCode Send(LPCTSTR ipv4Addr,DWORD port,const CMessage& netMsg)=0; + virtual ResultCode SetListener(VMsg msgType,INetListener *listener)=0; + virtual ResultCode RemoveListener(VMsg msgType,INetListener *listener)=0; + virtual ResultCode MockReceive(const CMessage *mockMsg)=0; +}; + +class CNetListenerHelper +{ +public: + CNetListenerHelper(); + ~CNetListenerHelper(); +public: + void AddFilter(VMsg msgType,INetListener *listener); + void StartListen(); + void StopListen(); +private: + std::vector > m_vec; +}; \ No newline at end of file diff --git a/VNOC/VNOC/NET.cpp b/Client/Client/net/Net.cpp similarity index 56% rename from VNOC/VNOC/NET.cpp rename to Client/Client/net/Net.cpp index eaaf1003..572fb9a6 100644 --- a/VNOC/VNOC/NET.cpp +++ b/Client/Client/net/Net.cpp @@ -1,234 +1,253 @@ -#include "stdafx.h" -#include "Net.h" -#include "../../Message/PackMessage.h" -#include "../../Message/MessageParser.h" -#include "../util/util.h" -#include "IConfig.h" - -#include - -////////////////////////////////////////////////////////////////////////// - -CNetCenter::CNetCenter() -{ - ZeroMemory(&m_wsaData,sizeof(m_wsaData)); -} - -CNetCenter::~CNetCenter() -{ - -} - -HRESULT CNetCenter::Initialize( IModule* UpperFrame/*=NULL*/ ) -{ - m_isConnected = FALSE; - WSAStartup(MAKEWORD(2,2),&m_wsaData); - m_serverSocket.Create(0,SOCK_STREAM); - return S_OK; -} - -HRESULT CNetCenter::UnInitialize() -{ - m_serverSocket.Close(); - WSACleanup(); - return S_OK; -} - -HRESULT CNetCenter::Run() -{ - m_serverSocket.SetListener(dynamic_cast(this)); - return S_OK; -} - -HRESULT CNetCenter::Terminate() -{ - // ر - return S_OK; -} - -HRESULT CNetCenter::_GetServerAddress() -{ - CConfig cfg(_T("VNOC/Net/ServerAddress")); - cfg.Get(); - ConfigNode node = cfg.GetNode(); - - m_serverPort = 0; - - if ( node.GetAttribute(_T("ServerIP"),m_serverIP) - && node.GetAttribute(_T("ServerPort"),m_serverPort)) - { - if (!m_serverIP.IsEmpty()) - { - return S_OK; - } - } - Global->CriticalError(_T("ļ𻵣޷ȡַ.")); - return E_FAIL; -} - -HRESULT CNetCenter::_ConnectServer() -{ - if (m_serverIP.IsEmpty()) - { - _GetServerAddress(); - } - if (m_serverIP.IsEmpty()) - { - return E_INVALIDARG; - } - BOOL bSuccess = m_serverSocket.Connect(m_serverIP,m_serverPort); - if (!bSuccess && m_serverSocket.GetLastError()!=WSAEWOULDBLOCK) - { - Global->Logf(LogFile_Net,_T("ӷʧ.%d\n"),m_serverSocket.GetLastError()); - return E_FAIL; - } - Global->Logf(LogFile_Net,_T("ӷɹ,%d\n"),m_serverSocket.GetLastError()); - m_isConnected = TRUE; - return S_OK; -} - -HRESULT CNetCenter::IsServerConnected() -{ - return m_isConnected? S_OK: E_FAIL; -} - -HRESULT CNetCenter::SendServer( const CMessage &helper ) -{ - if (!m_isConnected) - { - _ConnectServer(); - } - PackMessage packer; - int len = packer.GetMessageLen(&helper); - CBuffer buffer; - buffer.Alloc(len); - packer.Pack(&helper,buffer.GetBuffer(),len); - m_serverSocket.Send(buffer.GetBuffer(),len); - return S_OK; -} - -HRESULT CNetCenter::SetListener( MSGTYPE msgType,INetListener *listener ) -{ - Util::CAutoCS ac(m_cs); - m_listeners[msgType].push_back(listener); - return S_OK; -} - -HRESULT CNetCenter::RemoveListener( MSGTYPE msgType,INetListener *listener ) -{ - Util::CAutoCS ac(m_cs); - auto si = m_listeners.find(msgType); - if (si != m_listeners.end()) - { - auto i = std::find(si->second.begin(),si->second.end(),listener); - do - { - si->second.erase(i); - i = std::find(si->second.begin(),si->second.end(),listener); - } while (i != si->second.end()); - } - return S_OK; -} - -HRESULT CNetCenter::Send( LPCTSTR ipv4Addr,DWORD port,const CMessage& netMsg ) -{ - return S_OK; -} - -////////////////////////////////////////////////////////////////////////// - -void CNetCenter::OnAccept( int nErrorCode,CAsyncSocket* pSock ) -{ - Global->Log(LogFile_Net,_T("OnAccept")); -} - -void CNetCenter::OnClose( int nErrorCode,CAsyncSocket* pSock ) -{ - Global->Log(LogFile_Net,_T("OnClose")); -} - -void CNetCenter::OnConnect( int nErrorCode,CAsyncSocket* pSock ) -{ - Global->Log(LogFile_Net,_T("OnConnect")); -} - -void CNetCenter::OnOutOfBandData( int nErrorCode,CAsyncSocket* pSock ) -{ - Global->Log(LogFile_Net,_T("OnOutOfBandData")); -} - -void CNetCenter::OnReceive( int nErrorCode,CAsyncSocket* pSock ) -{ - Global->PtrAssert(pSock); - CBuffer buffer; - buffer.Alloc(1024); - int length = pSock->Receive(buffer.GetBuffer(),1024); - Global->Logf(LogFile_Net,_T("OnReceive, size:%d\n"),length); - - CMessageParser parser; - CMessage *pMsg=NULL; - pMsg = parser.Parse(buffer.GetBuffer(),length); - if (pMsg) - { - _DispatchMessage(pMsg); - delete pMsg; - } -} - -void CNetCenter::OnSend( int nErrorCode,CAsyncSocket* pSock ) -{ - Global->Log(LogFile_Net,_T("OnSend")); -} - -void CNetCenter::_DispatchMessage( const CMessage* pMsg ) -{ - Util::CAutoCS ac(m_cs); - auto i = m_listeners.find((MSGTYPE)pMsg->GetMessageType()); - if ( i != m_listeners.end()) - { - auto ii = i->second.begin(); - for (; ii!=i->second.end();++ii) - { - (*ii)->OnMessage(*pMsg); - } - } -} - -////////////////////////////////////////////////////////////////////////// - -CNetListenerHelper::CNetListenerHelper() -{ -} - -CNetListenerHelper::~CNetListenerHelper() -{ -} - -void CNetListenerHelper::AddFilter(MSGTYPE msgType,INetListener *listener) -{ - m_vec.push_back(std::make_pair(msgType,listener)); -} - -void CNetListenerHelper::StartListen() -{ - INetCenter *pCenter=NULL; - Global->GetINetCenter(&pCenter); - Global->PtrAssert(pCenter); - - for(auto i=m_vec.begin(); i!=m_vec.end(); ++i) - { - pCenter->SetListener(i->first,i->second); - } -} - -void CNetListenerHelper::StopListen() -{ - INetCenter *pCenter=NULL; - Global->GetINetCenter(&pCenter); - Global->PtrAssert(pCenter); - - for(auto i=m_vec.begin(); i!=m_vec.end(); ++i) - { - pCenter->RemoveListener(i->first,i->second); - } -} +#include "stdafx.h" +#include "Net.h" +#include "../../../NMessage/Message2Pack.h" +#include "../../../NMessage/Message2Parser.h" +#include "../../../NMessage/ParserMessageXML.h" + +#include + +////////////////////////////////////////////////////////////////////////// + +CNetCenter::CNetCenter() +{ + ZeroMemory(&m_wsaData,sizeof(m_wsaData)); +} + +CNetCenter::~CNetCenter() +{ + +} + +ResultCode CNetCenter::Initialize( IModule* UpperFrame/*=NULL*/ ) +{ + m_isConnected = FALSE; + WSAStartup(MAKEWORD(2,2),&m_wsaData); + m_serverSocket.Create(0,SOCK_STREAM); + return Result_Success; +} + +ResultCode CNetCenter::UnInitialize() +{ + m_serverSocket.Close(); + WSACleanup(); + return Result_Success; +} + +ResultCode CNetCenter::Run() +{ + m_serverSocket.SetListener(dynamic_cast(this)); + return Result_Success; +} + +ResultCode CNetCenter::Terminate() +{ + // ر + return Result_Success; +} + +ResultCode CNetCenter::_GetServerAddress() +{ + CConfig cfg(_T("VNOC/Net/ServerAddress")); + cfg.Get(); + ConfigNode node = cfg.GetNode(); + + m_serverPort = 0; + + if ( node.GetAttribute(_T("ServerIP"),m_serverIP) + && node.GetAttribute(_T("ServerPort"),m_serverPort)) + { + if (!m_serverIP.IsEmpty()) + { + return Result_Success; + } + } + Global->CriticalError(_T("ļ𻵣޷ȡַ.")); + return Result_Fail; +} + +ResultCode CNetCenter::_ConnectServer() +{ + if (m_serverIP.IsEmpty()) + { + _GetServerAddress(); + } + if (m_serverIP.IsEmpty()) + { + return Result_InvalidParam; + } + BOOL bSuccess = m_serverSocket.Connect(m_serverIP,m_serverPort); + if (!bSuccess && m_serverSocket.GetLastError()!=WSAEWOULDBLOCK) + { + Global->Logf(LogFile_Net,_T("ӷʧ.%d\n"),m_serverSocket.GetLastError()); + return Result_Fail; + } + Global->Logf(LogFile_Net,_T("ӷɹ,%d\n"),m_serverSocket.GetLastError()); + m_isConnected = TRUE; + return Result_Success; +} + +ResultCode CNetCenter::IsServerConnected() +{ + return m_isConnected? Result_Success: Result_Fail; +} + +ResultCode CNetCenter::SendServer( const CMessage &helper ) +{ + if (!m_isConnected) + { + _ConnectServer(); + } + CMessage2Pack packer; + int len; + packer.GetPackSize(&helper, len); + CBufferMessage buffer; + buffer.Alloc(len); + packer.PackMessage(&helper, buffer); + m_serverSocket.Send(buffer.GetBuffer(),len); + return Result_Success; +} + +ResultCode CNetCenter::SetListener( VMsg msgType,INetListener *listener ) +{ + Util::CAutoCS ac(m_cs); + m_listeners[msgType].push_back(listener); + return Result_Success; +} + +ResultCode CNetCenter::RemoveListener( VMsg msgType,INetListener *listener ) +{ + Util::CAutoCS ac(m_cs); + auto si = m_listeners.find(msgType); + if (si != m_listeners.end()) + { + auto i = std::find(si->second.begin(),si->second.end(),listener); + do + { + si->second.erase(i); + i = std::find(si->second.begin(),si->second.end(),listener); + } while (i != si->second.end()); + } + return Result_Success; +} + +ResultCode CNetCenter::Send( LPCTSTR ipv4Addr,DWORD port,const CMessage& netMsg ) +{ + return Result_Success; +} + +////////////////////////////////////////////////////////////////////////// + +void CNetCenter::OnAccept( int nErrorCode,CAsyncSocketEx* pSock ) +{ + Global->Log(LogFile_Net,_T("OnAccept")); +} + +void CNetCenter::OnClose( int nErrorCode,CAsyncSocketEx* pSock ) +{ + Global->Log(LogFile_Net,_T("OnClose")); +} + +void CNetCenter::OnConnect( int nErrorCode,CAsyncSocketEx* pSock ) +{ + Global->Log(LogFile_Net,_T("OnConnect")); +} + +void CNetCenter::OnOutOfBandData( int nErrorCode,CAsyncSocketEx* pSock ) +{ + Global->Log(LogFile_Net,_T("OnOutOfBandData")); +} + +void CNetCenter::OnReceive( int nErrorCode,CAsyncSocketEx* pSock ) +{ + Global->PtrAssert(pSock); + CBufferMessage buffer; + buffer.Alloc(1024); + int length = pSock->Receive(buffer.GetBuffer(),1024); + Global->Logf(LogFile_Net,_T("OnReceive, size:%d\n"),length); + + CMessage2Parser parser; + CMessage msg(parser.GetMsgType(buffer)); + + if (parser.Parser(&msg, buffer) == MsgStatus_Ok) + { + _DispatchMessage(msg); + } +} + +void CNetCenter::OnSend( int nErrorCode,CAsyncSocketEx* pSock ) +{ + Global->Log(LogFile_Net,_T("OnSend")); +} + +void CNetCenter::_DispatchMessage( const CMessage &msg ) +{ + Util::CAutoCS ac(m_cs); + auto i = m_listeners.find(VMsg(msg.MsgId())); + if ( i != m_listeners.end()) + { + auto ii = i->second.begin(); + for (; ii!=i->second.end();++ii) + { + (*ii)->OnNetMessage(msg); + } + } +} + +void CNetCenter::OnPackReady(const CBufferMessage &buffer ) +{ + Global->Logf(LogFile_Net,_T("OnPackReady, size:%d\n"),buffer.GetSize()); + CMessage2Parser parser; + CMessage msg(parser.GetMsgType(buffer)); + if(parser.Parser(&msg, buffer) == MsgStatus_Ok) + { + _DispatchMessage(msg); + } +} + +ResultCode CNetCenter::MockReceive( const CMessage *mockMsg ) +{ + if (mockMsg) + { + _DispatchMessage(*mockMsg); + } + return Result_Success; +} + +////////////////////////////////////////////////////////////////////////// + +CNetListenerHelper::CNetListenerHelper() +{ +} + +CNetListenerHelper::~CNetListenerHelper() +{ +} + +void CNetListenerHelper::AddFilter(VMsg msgType,INetListener *listener) +{ + m_vec.push_back(std::make_pair(msgType,listener)); +} + +void CNetListenerHelper::StartListen() +{ + INetCenter *pCenter=NULL; + Global->GetINetCenter(&pCenter); + Global->PtrAssert(pCenter); + + for(auto i=m_vec.begin(); i!=m_vec.end(); ++i) + { + pCenter->SetListener(i->first,i->second); + } +} + +void CNetListenerHelper::StopListen() +{ + INetCenter *pCenter=NULL; + Global->GetINetCenter(&pCenter); + Global->PtrAssert(pCenter); + + for(auto i=m_vec.begin(); i!=m_vec.end(); ++i) + { + pCenter->RemoveListener(i->first,i->second); + } +} diff --git a/Client/Client/net/Net.h b/Client/Client/net/Net.h new file mode 100644 index 00000000..0ed6b171 --- /dev/null +++ b/Client/Client/net/Net.h @@ -0,0 +1,49 @@ +#pragma once + +#include "INet.h" +#include "socket/VNOCSocket.h" + +#include +#include + +class CNetCenter : public INetCenter + ,public IVNOCSocketListener +{ +public: + CNetCenter(); + ~CNetCenter(); +public: + virtual ResultCode Initialize(IModule* UpperFrame=NULL); + virtual ResultCode UnInitialize(); + virtual ResultCode Run(); + virtual ResultCode Terminate(); + + virtual ResultCode IsServerConnected(); + virtual ResultCode SendServer(const CMessage &helper); + virtual ResultCode Send(LPCTSTR ipv4Addr,DWORD port,const CMessage& netMsg); + virtual ResultCode SetListener(VMsg msgType,INetListener *listener); + virtual ResultCode RemoveListener(VMsg msgType,INetListener *listener); + virtual ResultCode MockReceive(const CMessage *mockMsg); + +VNOC_Private: + virtual void OnAccept (int nErrorCode,CAsyncSocketEx* pSock); + virtual void OnClose (int nErrorCode,CAsyncSocketEx* pSock); + virtual void OnConnect (int nErrorCode,CAsyncSocketEx* pSock); + virtual void OnOutOfBandData (int nErrorCode,CAsyncSocketEx* pSock); + virtual void OnReceive (int nErrorCode,CAsyncSocketEx* pSock); + virtual void OnSend (int nErrorCode,CAsyncSocketEx* pSock); + virtual void OnPackReady(const CBufferMessage &buffer); +private: + ResultCode _GetServerAddress(); + ResultCode _ConnectServer(); + void _DispatchMessage(const CMessage &msg); +private: + CString m_serverIP; + UINT m_serverPort; + BOOL m_isConnected; + + CVNOCSocket m_serverSocket; + WSADATA m_wsaData; + std::map > m_listeners; + ATL::CCriticalSection m_cs; +}; diff --git a/Client/Client/net/Socket/AsyncSocketEx.cpp b/Client/Client/net/Socket/AsyncSocketEx.cpp new file mode 100644 index 00000000..c6151312 --- /dev/null +++ b/Client/Client/net/Socket/AsyncSocketEx.cpp @@ -0,0 +1,1046 @@ +/*CAsyncSocketEx by Tim Kosse (Tim.Kosse@gmx.de) + Version 1.2 (2003-03-28) +-------------------------------------------------------- + +Introduction: +------------- + +CAsyncSocketEx is a replacement for the MFC class CAsyncSocket. +This class was written because CAsyncSocket is not the fastest WinSock +wrapper and it's very hard to add new functionality to CAsyncSocket +derived classes. This class offers the same functionality as CAsyncSocket. +Also, CAsyncSocketEx offers some enhancements which were not possible with +CAsyncSocket without some tricks. + +How do I use it? +---------------- +Basically exactly like CAsyncSocket. +To use CAsyncSocketEx, just replace all occurrences of CAsyncSocket in your +code with CAsyncSocketEx, if you did not enhance CAsyncSocket yourself in +any way, you won't have to change anything else in your code. + +Why is CAsyncSocketEx faster? +----------------------------- + +CAsyncSocketEx is slightly faster when dispatching notification event messages. +First have a look at the way CAsyncSocket works. For each thread that uses +CAsyncSocket, a window is created. CAsyncSocket calls WSAAsyncSelect with +the handle of that window. Until here, CAsyncSocketEx works the same way. +But CAsyncSocket uses only one window message (WM_SOCKET_NOTIFY) for all +sockets within one thread. When the window recieve WM_SOCKET_NOTIFY, wParam +contains the socket handle and the window looks up an CAsyncSocket instance +using a map. CAsyncSocketEx works differently. It's helper window uses a +wide range of different window messages (WM_USER through 0xBFFF) and passes +a different message to WSAAsyncSelect for each socket. When a message in +the specified range is received, CAsyncSocketEx looks up the pointer to a +CAsyncSocketEx instance in an Array using the index of message - WM_USER. +As you can see, CAsyncSocketEx uses the helper window in a more efficient +way, as it don't have to use the slow maps to lookup it's own instance. +Still, speed increase is not very much, but it may be noticeable when using +a lot of sockets at the same time. +Please note that the changes do not affect the raw data throughput rate, +CAsyncSocketEx only dispatches the notification messages faster. + +What else does CAsyncSocketEx offer? +------------------------------------ + +CAsyncSocketEx offers a flexible layer system. One example is the proxy layer. +Just create an instance of the proxy layer, configure it and add it to the layer +chain of your CAsyncSocketEx instance. After that, you can connect through +proxies. +Benefit: You don't have to change much to use the layer system. +Another layer that is currently in development is the SSL layer to establish +SSL encrypted connections. + +License +------- + +Feel free to use this class, as long as you don't claim that you wrote it +and this copyright notice stays intact in the source files. +If you use this class in commercial applications, please send a short message +to tim.kosse@gmx.de +*/ + +#include "stdafx.h" +#include "AsyncSocketEx.h" +#include "wtypes.h" +#include "oleauto.h" +#include "atlconv.h" + +#ifndef NOLAYERS +#include "AsyncSocketExLayer.h" +#endif //NOLAYERS + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#endif + +#ifndef CCRITICALSECTIONWRAPPERINCLUDED +class CCriticalSectionWrapper +{ +public: + CCriticalSectionWrapper() + { + InitializeCriticalSection(&m_criticalSection); + } + + ~CCriticalSectionWrapper() + { + DeleteCriticalSection(&m_criticalSection); + } + + void Lock() + { + EnterCriticalSection(&m_criticalSection); + } + void Unlock() + { + LeaveCriticalSection(&m_criticalSection); + } +protected: + CRITICAL_SECTION m_criticalSection; +}; +#define CCRITICALSECTIONWRAPPERINCLUDED +#endif + +CCriticalSectionWrapper CAsyncSocketEx::m_sGlobalCriticalSection; +CAsyncSocketEx::t_AsyncSocketExThreadDataList *CAsyncSocketEx::m_spAsyncSocketExThreadDataList=0; + +#ifndef _AFX +#ifndef VERIFY +#define VERIFY(x) (void(x)) +#endif //VERIFY +#ifndef ASSERT +#define ASSERT(x) +#endif //ASSERT +#endif //_AFX + +///////////////////////////// +//Helper Window class +#define WM_SOCKETEX_NOTIFY (WM_USER+2) +#define MAX_SOCKETS (0xBFFF-WM_SOCKETEX_NOTIFY+1) + +class CAsyncSocketExHelperWindow +{ +public: + CAsyncSocketExHelperWindow() + { + //Initialize data + m_pAsyncSocketExWindowData=new t_AsyncSocketExWindowData[512]; //Reserve space for 512 active sockets + memset(m_pAsyncSocketExWindowData, 0, 512*sizeof(t_AsyncSocketExWindowData)); + m_nWindowDataSize=512; + m_nSocketCount=0; + m_nWindowDataPos=0; + + //Create window + WNDCLASSEX wndclass; + wndclass.cbSize=sizeof wndclass; + wndclass.style=0; + wndclass.lpfnWndProc=WindowProc; + wndclass.cbClsExtra=0; + wndclass.cbWndExtra=0; + wndclass.hInstance=GetModuleHandle(0); + wndclass.hIcon=0; + wndclass.hCursor=0; + wndclass.hbrBackground=0; + wndclass.lpszMenuName=0; + wndclass.lpszClassName=_T("CAsyncSocketEx Helper Window"); + wndclass.hIconSm=0; + + RegisterClassEx(&wndclass); + + m_hWnd=CreateWindow(_T("CAsyncSocketEx Helper Window"), _T("CAsyncSocketEx Helper Window"), 0, 0, 0, 0, 0, 0, 0, 0, GetModuleHandle(0)); + ASSERT(m_hWnd); +#ifdef WIN64 +#pragma message("sockEx not support X64") +#else + SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this); +#endif + }; + + virtual ~CAsyncSocketExHelperWindow() + { + //Clean up socket storage + delete [] m_pAsyncSocketExWindowData; + m_pAsyncSocketExWindowData=0; + m_nWindowDataSize=0; + m_nSocketCount=0; + + //Destroy window + if (m_hWnd) + { + DestroyWindow(m_hWnd); + m_hWnd=0; + } + } + + //Adds a socket to the list of attached sockets + BOOL AddSocket(CAsyncSocketEx *pSocket, int &nSocketIndex) + { + ASSERT(pSocket); + if (!m_nWindowDataSize) + { + ASSERT(!m_nSocketCount); + m_nWindowDataSize=512; + m_pAsyncSocketExWindowData=new t_AsyncSocketExWindowData[512]; //Reserve space for 512 active sockets + memset(m_pAsyncSocketExWindowData, 0, 512*sizeof(t_AsyncSocketExWindowData)); + } + + if (nSocketIndex!=-1) + { + ASSERT(m_pAsyncSocketExWindowData); + ASSERT(m_nWindowDataSize>nSocketIndex); + ASSERT(m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket==pSocket); + ASSERT(m_nSocketCount); + return TRUE; + } + + //Increase socket storage if too small + if (m_nSocketCount>=(m_nWindowDataSize-10)) + { + int nOldWindowDataSize=m_nWindowDataSize; + ASSERT(m_nWindowDataSizeMAX_SOCKETS) + m_nWindowDataSize=MAX_SOCKETS; + t_AsyncSocketExWindowData *tmp=m_pAsyncSocketExWindowData; + m_pAsyncSocketExWindowData = new t_AsyncSocketExWindowData[m_nWindowDataSize]; + memcpy(m_pAsyncSocketExWindowData, tmp, nOldWindowDataSize * sizeof(t_AsyncSocketExWindowData)); + memset(m_pAsyncSocketExWindowData+nOldWindowDataSize, 0, (m_nWindowDataSize-nOldWindowDataSize)*sizeof(t_AsyncSocketExWindowData)); + delete [] tmp; + } + + //Search for free slot + for (int i=m_nWindowDataPos;i<(m_nWindowDataSize+m_nWindowDataPos);i++) + { + if (!m_pAsyncSocketExWindowData[i%m_nWindowDataSize].m_pSocket) + { + m_pAsyncSocketExWindowData[i%m_nWindowDataSize].m_pSocket=pSocket; + nSocketIndex=i%m_nWindowDataSize; + m_nWindowDataPos=(i+1)%m_nWindowDataSize; + m_nSocketCount++; + return TRUE; + } + } + + //No slot found, maybe there are too much sockets! + return FALSE; + } + + //Removes a socket from the socket storage + BOOL RemoveSocket(CAsyncSocketEx *pSocket, int &nSocketIndex) + { + ASSERT(pSocket); + if (nSocketIndex==-1) + return TRUE; + + ASSERT(m_pAsyncSocketExWindowData); + ASSERT(m_nWindowDataSize>0); + ASSERT(m_nSocketCount>0); + ASSERT(m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket==pSocket); + m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket=0; + nSocketIndex=-1; + m_nSocketCount--; + + return TRUE; + } + + //Processes event notifications sent by the sockets or the layers + static LRESULT CALLBACK WindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) + { + if (message>=WM_SOCKETEX_NOTIFY) + { + //Verify parameters + ASSERT(hWnd); + CAsyncSocketExHelperWindow *pWnd=NULL; +#ifdef WIN64 +#pragma message("sockEx not support X64") +#else + pWnd = (CAsyncSocketExHelperWindow *)GetWindowLong(hWnd, GWL_USERDATA); +#endif + ASSERT(pWnd); + + if (message(WM_SOCKETEX_NOTIFY+pWnd->m_nWindowDataSize)) //Index is within socket storage + { + //Lookup socket and verify if it's valid + CAsyncSocketEx *pSocket=pWnd->m_pAsyncSocketExWindowData[message-WM_SOCKETEX_NOTIFY].m_pSocket; + SOCKET hSocket=wParam; + if (!pSocket) + return 0; + if (hSocket==INVALID_SOCKET) + return 0; + if (pSocket->m_SocketData.hSocket!=hSocket) + return 0; + + int nEvent=lParam&0xFFFF; + int nErrorCode=lParam>>16; + + //Dispatch notification +#ifndef NOLAYERS + if (!pSocket->m_pFirstLayer) + { +#endif //NOLAYERS + //Dispatch to CAsyncSocketEx instance + switch (nEvent) + { + case FD_READ: + { + DWORD nBytes; + if (!pSocket->IOCtl(FIONREAD, &nBytes)) + nErrorCode = WSAGetLastError(); + if (nBytes != 0 || nErrorCode != 0) + pSocket->OnReceive(nErrorCode); + } + break; + case FD_FORCEREAD: //Forceread does not check if there's data waiting + pSocket->OnReceive(nErrorCode); + break; + case FD_WRITE: + pSocket->OnSend(nErrorCode); + break; + case FD_CONNECT: + pSocket->OnConnect(nErrorCode); + break; + case FD_ACCEPT: + pSocket->OnAccept(nErrorCode); + break; + case FD_CLOSE: + pSocket->OnClose(nErrorCode); + break; + } + } +#ifndef NOLAYERS + else //Dispatch notification to the lowest layer + { + if (nEvent==FD_READ) + { + DWORD nBytes; + if (!pSocket->IOCtl(FIONREAD, &nBytes)) + nErrorCode = WSAGetLastError(); + if (nBytes != 0 || nErrorCode != 0) + pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode); + } + else + pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode); + } + } +#endif //NOLAYERS + return 0; + } +#ifndef NOLAYERS + else if (message==WM_USER) //Notification event sent by a layer + { + //Verify parameters, lookup socket and notification message + if (!wParam) + return 0; + CAsyncSocketEx *pSocket=(CAsyncSocketEx *)wParam; + CAsyncSocketExLayer::t_LayerNotifyMsg *pMsg=(CAsyncSocketExLayer::t_LayerNotifyMsg *)lParam; + if (pSocket->m_SocketData.hSocket==INVALID_SOCKET) + { + delete pMsg; + return 0; + } + int nEvent=pMsg->lEvent&0xFFFF; + int nErrorCode=pMsg->lEvent>>16; + + //Dispatch to layer + if (pMsg->pLayer) + pMsg->pLayer->CallEvent(nEvent, nErrorCode); + else + { + //Dispatch to socket class + switch (nEvent) + { + case FD_READ: + if (pSocket->m_lEvent&FD_READ) + pSocket->OnReceive(nErrorCode); + break; + case FD_FORCEREAD: + if (pSocket->m_lEvent&FD_FORCEREAD) + pSocket->OnReceive(nErrorCode); + break; + case FD_WRITE: + if (pSocket->m_lEvent&FD_WRITE) + pSocket->OnSend(nErrorCode); + break; + case FD_CONNECT: + if (pSocket->m_lEvent&FD_CONNECT) + pSocket->OnConnect(nErrorCode); + break; + case FD_ACCEPT: + if (pSocket->m_lEvent&FD_ACCEPT) + pSocket->OnAccept(nErrorCode); + break; + case FD_CLOSE: + if (pSocket->m_lEvent&FD_CLOSE) + pSocket->OnClose(nErrorCode); + break; + } + } + delete pMsg; + return 0; + } +#endif //NOLAYERS + else if (message == WM_USER+1) + { + //WSAAsyncGetHostByName reply + + //Verify parameters + ASSERT(hWnd); + CAsyncSocketExHelperWindow *pWnd=NULL; +#ifdef WIN64 +#pragma message("sockEx not support X64") +#else + pWnd = (CAsyncSocketExHelperWindow *)GetWindowLong(hWnd, GWL_USERDATA); +#endif + ASSERT(pWnd); + + CAsyncSocketEx *pSocket; + int i=0; + for (i=0; im_nWindowDataSize; i++) + { + pSocket = pWnd->m_pAsyncSocketExWindowData[i].m_pSocket; + if (pSocket && pSocket->m_hAsyncGetHostByNameHandle && + pSocket->m_hAsyncGetHostByNameHandle == (HANDLE)wParam) + break; + } + if (i == pWnd->m_nWindowDataSize) + return 0; + + int nErrorCode = lParam >> 16; + int len = lParam % 0xFFFF; + if (nErrorCode) + { + pSocket->OnConnect(nErrorCode); + return 0; + } + + SOCKADDR_IN sockAddr; + memset(&sockAddr,0,sizeof(sockAddr)); + sockAddr.sin_family=AF_INET; + sockAddr.sin_addr.s_addr = ((LPIN_ADDR)((LPHOSTENT)pSocket->m_pAsyncGetHostByNameBuffer)->h_addr)->s_addr; + + sockAddr.sin_port = htons(pSocket->m_nAsyncGetHostByNamePort); + + BOOL res = pSocket->Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr)); + delete [] pSocket->m_pAsyncGetHostByNameBuffer; + pSocket->m_pAsyncGetHostByNameBuffer=0; + pSocket->m_hAsyncGetHostByNameHandle=0; + + if (!res) + if (GetLastError()!=WSAEWOULDBLOCK) + pSocket->OnConnect(GetLastError()); + return 0; + } + return DefWindowProc(hWnd, message, wParam, lParam); + } + + HWND CAsyncSocketExHelperWindow::GetHwnd() + { + return m_hWnd; + } + +private: + HWND m_hWnd; + struct t_AsyncSocketExWindowData + { + CAsyncSocketEx *m_pSocket; + } *m_pAsyncSocketExWindowData; + int m_nWindowDataSize; + int m_nWindowDataPos; + int m_nSocketCount; +}; + +////////////////////////////////////////////////////////////////////// +// Konstruktion/Destruktion +////////////////////////////////////////////////////////////////////// + +CAsyncSocketEx::CAsyncSocketEx() +{ + m_SocketData.hSocket=INVALID_SOCKET; + m_SocketData.nSocketIndex=-1; + m_pLocalAsyncSocketExThreadData=0; +#ifndef NOLAYERS + m_pFirstLayer=0; + m_pLastLayer=0; +#endif //NOLAYERS + m_pAsyncGetHostByNameBuffer = NULL; + m_hAsyncGetHostByNameHandle = NULL; +} + +CAsyncSocketEx::~CAsyncSocketEx() +{ + Close(); + FreeAsyncSocketExInstance(); +} + +BOOL CAsyncSocketEx::Create( UINT nSocketPort /*=0*/, int nSocketType /*=SOCK_STREAM*/, long lEvent /*=FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE*/, LPCTSTR lpszSocketAddress /*=NULL*/ ) +{ + ASSERT(GetSocketHandle()==INVALID_SOCKET); + + //Close the socket, although this should not happen + if (GetSocketHandle() != INVALID_SOCKET) + { + WSASetLastError(WSAEALREADY); + return FALSE; + } + + BOOL res=InitAsyncSocketExInstance(); + ASSERT(res); + if (!res) + { + WSASetLastError(WSANOTINITIALISED); + return FALSE; + } + +#ifndef NOLAYERS + if (m_pFirstLayer) + return m_pFirstLayer->Create(nSocketPort, nSocketType, lEvent, lpszSocketAddress); + else +#endif //NOLAYERS + { + SOCKET hSocket=socket(AF_INET, nSocketType, 0); + if (hSocket==INVALID_SOCKET) + return FALSE; + m_SocketData.hSocket=hSocket; + AttachHandle(hSocket); + if (!AsyncSelect(lEvent)) + { + Close(); + return FALSE; + } +#ifndef NOLAYERS + if (m_pFirstLayer) + { + if (WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE) ) + { + Close(); + return FALSE; + } + } +#endif //NOLAYERS + + if (!Bind(nSocketPort, lpszSocketAddress)) + { + Close(); + return FALSE; + } + return TRUE; + } +} + + + +void CAsyncSocketEx::OnReceive(int nErrorCode) +{ +} + +void CAsyncSocketEx::OnSend(int nErrorCode) +{ +} + +void CAsyncSocketEx::OnConnect(int nErrorCode) +{ +} + +void CAsyncSocketEx::OnAccept(int nErrorCode) +{ +} + +void CAsyncSocketEx::OnClose(int nErrorCode) +{ +} + +BOOL CAsyncSocketEx::Bind(UINT nSocketPort, LPCTSTR lpszSocketAddress) +{ + USES_CONVERSION; + + SOCKADDR_IN sockAddr; + memset(&sockAddr,0,sizeof(sockAddr)); + + LPSTR lpszAscii = T2A((LPTSTR)lpszSocketAddress); + sockAddr.sin_family = AF_INET; + + if (lpszAscii == NULL) + sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); + else + { + DWORD lResult = inet_addr(lpszAscii); + if (lResult == INADDR_NONE) + { + WSASetLastError(WSAEINVAL); + return FALSE; + } + sockAddr.sin_addr.s_addr = lResult; + } + + sockAddr.sin_port = htons((u_short)nSocketPort); + + return Bind((SOCKADDR*)&sockAddr, sizeof(sockAddr)); +} + +BOOL CAsyncSocketEx::Bind(const SOCKADDR* lpSockAddr, int nSockAddrLen) +{ + if (!bind(m_SocketData.hSocket, lpSockAddr, nSockAddrLen)) + return TRUE; + else + return FALSE; +} + +void CAsyncSocketEx::AttachHandle(SOCKET hSocket) +{ + ASSERT(m_pLocalAsyncSocketExThreadData); + VERIFY(m_pLocalAsyncSocketExThreadData->m_pHelperWindow->AddSocket(this, m_SocketData.nSocketIndex)); +} + +void CAsyncSocketEx::DetachHandle(SOCKET hSocket) +{ + ASSERT(m_pLocalAsyncSocketExThreadData); + if (!m_pLocalAsyncSocketExThreadData) + return; + ASSERT(m_pLocalAsyncSocketExThreadData->m_pHelperWindow); + if (!m_pLocalAsyncSocketExThreadData->m_pHelperWindow) + return; + VERIFY(m_pLocalAsyncSocketExThreadData->m_pHelperWindow->RemoveSocket(this, m_SocketData.nSocketIndex)); +} + +void CAsyncSocketEx::Close() +{ +#ifndef NOLAYERS + if (m_pFirstLayer) + m_pFirstLayer->Close(); +#endif //NOLAYERS + if (m_SocketData.hSocket != INVALID_SOCKET) + { + VERIFY(closesocket(m_SocketData.hSocket)!=SOCKET_ERROR); + DetachHandle(m_SocketData.hSocket); + m_SocketData.hSocket=INVALID_SOCKET; + } +#ifndef NOLAYERS + RemoveAllLayers(); +#endif //NOLAYERS + delete [] m_pAsyncGetHostByNameBuffer; + m_pAsyncGetHostByNameBuffer = NULL; + if (m_hAsyncGetHostByNameHandle) + WSACancelAsyncRequest(m_hAsyncGetHostByNameHandle); + m_hAsyncGetHostByNameHandle = NULL; +} + +BOOL CAsyncSocketEx::InitAsyncSocketExInstance() +{ + //Check if already initialized + if (m_pLocalAsyncSocketExThreadData) + return TRUE; + + DWORD id=GetCurrentThreadId(); + + m_sGlobalCriticalSection.Lock(); + + //Get thread specific data + if (m_spAsyncSocketExThreadDataList) + { + t_AsyncSocketExThreadDataList *pList=m_spAsyncSocketExThreadDataList; + while (pList) + { + ASSERT(pList->pThreadData); + ASSERT(pList->pThreadData->nInstanceCount>0); + + if (pList->pThreadData->nThreadId==id) + { + m_pLocalAsyncSocketExThreadData=pList->pThreadData; + m_pLocalAsyncSocketExThreadData->nInstanceCount++; + break; + } + pList=pList->pNext; + } + //Current thread yet has no sockets + if (!pList) + { + //Initialize data for current thread + pList=new t_AsyncSocketExThreadDataList; + pList->pNext=m_spAsyncSocketExThreadDataList; + m_spAsyncSocketExThreadDataList=pList; + m_pLocalAsyncSocketExThreadData=new t_AsyncSocketExThreadData; + m_pLocalAsyncSocketExThreadData->nInstanceCount=1; + m_pLocalAsyncSocketExThreadData->nThreadId=id; + m_pLocalAsyncSocketExThreadData->m_pHelperWindow=new CAsyncSocketExHelperWindow; + m_spAsyncSocketExThreadDataList->pThreadData=m_pLocalAsyncSocketExThreadData; + } + } + else + { //No thread has instances of CAsyncSocketEx; Initialize data + m_spAsyncSocketExThreadDataList=new t_AsyncSocketExThreadDataList; + m_spAsyncSocketExThreadDataList->pNext=0; + m_pLocalAsyncSocketExThreadData=new t_AsyncSocketExThreadData; + m_pLocalAsyncSocketExThreadData->nInstanceCount=1; + m_pLocalAsyncSocketExThreadData->nThreadId=id; + m_pLocalAsyncSocketExThreadData->m_pHelperWindow=new CAsyncSocketExHelperWindow; + m_spAsyncSocketExThreadDataList->pThreadData=m_pLocalAsyncSocketExThreadData; + } + m_sGlobalCriticalSection.Unlock(); + return TRUE; +} + +void CAsyncSocketEx::FreeAsyncSocketExInstance() +{ + //Check if already freed + if (!m_pLocalAsyncSocketExThreadData) + return; + + DWORD id=m_pLocalAsyncSocketExThreadData->nThreadId; + m_sGlobalCriticalSection.Lock(); + + ASSERT(m_spAsyncSocketExThreadDataList); + t_AsyncSocketExThreadDataList *pList=m_spAsyncSocketExThreadDataList; + t_AsyncSocketExThreadDataList *pPrev=0; + + //Serach for data for current thread and decrease instance count + while (pList) + { + ASSERT(pList->pThreadData); + ASSERT(pList->pThreadData->nInstanceCount>0); + + if (pList->pThreadData->nThreadId==id) + { + ASSERT(m_pLocalAsyncSocketExThreadData==pList->pThreadData); + m_pLocalAsyncSocketExThreadData->nInstanceCount--; + + //Freeing last instance? + //If so, destroy helper window + if (!m_pLocalAsyncSocketExThreadData->nInstanceCount) + { + delete m_pLocalAsyncSocketExThreadData->m_pHelperWindow; + delete m_pLocalAsyncSocketExThreadData; + if (pPrev) + pPrev->pNext=pList->pNext; + else + m_spAsyncSocketExThreadDataList=pList->pNext; + delete pList; + break; + } + + break; + } + pPrev=pList; + pList=pList->pNext; + ASSERT(pList); + } + + m_sGlobalCriticalSection.Unlock(); +} + +int CAsyncSocketEx::Receive(void* lpBuf, int nBufLen, int nFlags /*=0*/) +{ +#ifndef NOLAYERS + if (m_pFirstLayer) + return m_pFirstLayer->Receive(lpBuf, nBufLen, nFlags); + else +#endif //NOLAYERS + return recv(m_SocketData.hSocket, (LPSTR)lpBuf, nBufLen, nFlags); +} + + +int CAsyncSocketEx::Send(const void* lpBuf, int nBufLen, int nFlags /*=0*/) +{ +#ifndef NOLAYERS + if (m_pFirstLayer) + return m_pFirstLayer->Send(lpBuf, nBufLen, nFlags); + else +#endif //NOLAYERS + return send(m_SocketData.hSocket, (LPSTR)lpBuf, nBufLen, nFlags); +} + +BOOL CAsyncSocketEx::Connect(LPCTSTR lpszHostAddress, UINT nHostPort) +{ +#ifndef NOLAYERS + if (m_pFirstLayer) + return m_pFirstLayer->Connect(lpszHostAddress, nHostPort); + else +#endif //NOLAYERS + { + USES_CONVERSION; + + ASSERT(lpszHostAddress != NULL); + + SOCKADDR_IN sockAddr; + memset(&sockAddr,0,sizeof(sockAddr)); + + LPSTR lpszAscii = T2A((LPTSTR)lpszHostAddress); + sockAddr.sin_family = AF_INET; + sockAddr.sin_addr.s_addr = inet_addr(lpszAscii); + + if (sockAddr.sin_addr.s_addr == INADDR_NONE) + { + m_pAsyncGetHostByNameBuffer=new char[MAXGETHOSTSTRUCT]; + + m_nAsyncGetHostByNamePort=nHostPort; + + m_hAsyncGetHostByNameHandle=WSAAsyncGetHostByName(GetHelperWindowHandle(), WM_USER+1, lpszAscii, m_pAsyncGetHostByNameBuffer, MAXGETHOSTSTRUCT); + if (!m_hAsyncGetHostByNameHandle) + return FALSE; + + WSASetLastError(WSAEWOULDBLOCK); + return TRUE; + } + + sockAddr.sin_port = htons((u_short)nHostPort); + + return CAsyncSocketEx::Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr)); + } +} + +BOOL CAsyncSocketEx::Connect( const SOCKADDR* lpSockAddr, int nSockAddrLen ) +{ +#ifndef NOLAYERS + if (m_pFirstLayer) + return m_pFirstLayer->Connect(lpSockAddr, nSockAddrLen); + else +#endif //NOLAYERS + return SOCKET_ERROR!=connect(m_SocketData.hSocket, lpSockAddr, nSockAddrLen); +} + + +#ifdef _AFX +BOOL CAsyncSocketEx::GetPeerName( CString& rPeerAddress, UINT& rPeerPort ) +{ +#ifndef NOLAYERS + if (m_pFirstLayer) + return m_pFirstLayer->GetPeerName(rPeerAddress, rPeerPort); +#endif NOLAYERS + + SOCKADDR_IN sockAddr; + memset(&sockAddr, 0, sizeof(sockAddr)); + + int nSockAddrLen = sizeof(sockAddr); + BOOL bResult = GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen); + if (bResult) + { + rPeerPort = ntohs(sockAddr.sin_port); + rPeerAddress = inet_ntoa(sockAddr.sin_addr); + } + return bResult; +} +#endif //AFX + +BOOL CAsyncSocketEx::GetPeerName( SOCKADDR* lpSockAddr, int* lpSockAddrLen ) +{ +#ifndef NOLAYERS + if (m_pFirstLayer) + return m_pFirstLayer->GetPeerName(lpSockAddr, lpSockAddrLen); +#endif //NOLAYERS + + if ( !getpeername(m_SocketData.hSocket, lpSockAddr, lpSockAddrLen) ) + return TRUE; + else + return FALSE; +} + +#ifdef _AFX +BOOL CAsyncSocketEx::GetSockName(CString& rSocketAddress, UINT& rSocketPort) +{ + SOCKADDR_IN sockAddr; + memset(&sockAddr, 0, sizeof(sockAddr)); + + int nSockAddrLen = sizeof(sockAddr); + BOOL bResult = GetSockName((SOCKADDR*)&sockAddr, &nSockAddrLen); + if (bResult) + { + rSocketPort = ntohs(sockAddr.sin_port); + rSocketAddress = inet_ntoa(sockAddr.sin_addr); + } + return bResult; +} +#endif + +BOOL CAsyncSocketEx::GetSockName( SOCKADDR* lpSockAddr, int* lpSockAddrLen ) +{ + if ( !getsockname(m_SocketData.hSocket, lpSockAddr, lpSockAddrLen) ) + return TRUE; + else + return FALSE; +} + +BOOL CAsyncSocketEx::ShutDown( int nHow /*=sends*/ ) +{ +#ifndef NOLAYERS + if (m_pFirstLayer) + { + return m_pFirstLayer->ShutDown(); + } + else +#endif + { + if ( !shutdown(m_SocketData.hSocket, nHow) ) + return TRUE; + else + return FALSE; + } +} + +SOCKET CAsyncSocketEx::Detach( ) +{ + SOCKET socket=m_SocketData.hSocket; + DetachHandle(socket); + m_SocketData.hSocket=INVALID_SOCKET; + return socket; +} + +BOOL CAsyncSocketEx::Attach( SOCKET hSocket, long lEvent /*= FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE*/ ) +{ + if (hSocket==INVALID_SOCKET || !hSocket) + return FALSE; + + VERIFY(InitAsyncSocketExInstance()); + m_SocketData.hSocket=hSocket; + AttachHandle(hSocket); + + return AsyncSelect(lEvent); +} + +BOOL CAsyncSocketEx::AsyncSelect( long lEvent /*= FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE*/ ) +{ + ASSERT(m_pLocalAsyncSocketExThreadData); + m_lEvent=lEvent; +#ifndef NOLAYERS + if (!m_pFirstLayer) +#endif //NOLAYERS + { + if ( !WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, lEvent) ) + return TRUE; + else + return FALSE; + } + return TRUE; +} + +BOOL CAsyncSocketEx::Listen( int nConnectionBacklog /*=5*/ ) +{ +#ifndef NOLAYERS + if (m_pFirstLayer) + return m_pFirstLayer->Listen(nConnectionBacklog); +#endif //NOLAYERS + + if (!listen(m_SocketData.hSocket, nConnectionBacklog)) + return TRUE; + else + return FALSE; +} + +BOOL CAsyncSocketEx::Accept( CAsyncSocketEx& rConnectedSocket, SOCKADDR* lpSockAddr /*=NULL*/, int* lpSockAddrLen /*=NULL*/ ) +{ + ASSERT(rConnectedSocket.m_SocketData.hSocket == INVALID_SOCKET); +#ifndef NOLAYERS + if (m_pFirstLayer) + { + return m_pFirstLayer->Accept(rConnectedSocket, lpSockAddr, lpSockAddrLen); + } + else +#endif //NOLAYERS + { + SOCKET hTemp = accept(m_SocketData.hSocket, lpSockAddr, lpSockAddrLen); + + if (hTemp == INVALID_SOCKET) + return FALSE; + VERIFY(rConnectedSocket.InitAsyncSocketExInstance()); + rConnectedSocket.m_SocketData.hSocket=hTemp; + rConnectedSocket.AttachHandle(hTemp); + } + return TRUE; +} + +BOOL CAsyncSocketEx::IOCtl( long lCommand, DWORD* lpArgument ) +{ + return ioctlsocket(m_SocketData.hSocket, lCommand, lpArgument) != SOCKET_ERROR; +} + +int CAsyncSocketEx::GetLastError() +{ + return WSAGetLastError(); +} + +BOOL CAsyncSocketEx::TriggerEvent(long lEvent) +{ + if (m_SocketData.hSocket==INVALID_SOCKET) + return FALSE; + + ASSERT(m_pLocalAsyncSocketExThreadData); + ASSERT(m_pLocalAsyncSocketExThreadData->m_pHelperWindow); + ASSERT(m_SocketData.nSocketIndex!=-1); + +#ifndef NOLAYERS + if (m_pFirstLayer) + { + CAsyncSocketExLayer::t_LayerNotifyMsg *pMsg=new CAsyncSocketExLayer::t_LayerNotifyMsg; + pMsg->lEvent=lEvent%0xFFFF; + pMsg->pLayer=0; + BOOL res=PostMessage(GetHelperWindowHandle(), WM_USER, (WPARAM)this, (LPARAM)pMsg); + if (!res) + delete pMsg; + return res; + } + else +#endif //NOLAYERS + return PostMessage(GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, m_SocketData.hSocket, lEvent%0xFFFF); + +} + +SOCKET CAsyncSocketEx::GetSocketHandle() +{ + return m_SocketData.hSocket; +} + +HWND CAsyncSocketEx::GetHelperWindowHandle() +{ + if (!m_pLocalAsyncSocketExThreadData) + return 0; + if (!m_pLocalAsyncSocketExThreadData->m_pHelperWindow) + return 0; + return m_pLocalAsyncSocketExThreadData->m_pHelperWindow->GetHwnd(); +} + +#ifndef NOLAYERS +BOOL CAsyncSocketEx::AddLayer(CAsyncSocketExLayer *pLayer) +{ + ASSERT(pLayer); + if (m_SocketData.hSocket!=INVALID_SOCKET) + return FALSE; + if (m_pFirstLayer) + { + ASSERT(m_pLastLayer); + m_pLastLayer=m_pLastLayer->AddLayer(pLayer, this); + return m_pLastLayer?TRUE:FALSE; + } + else + { + ASSERT(!m_pLastLayer); + pLayer->Init(0, this); + m_pFirstLayer=pLayer; + m_pLastLayer=m_pFirstLayer; + } + + return TRUE; +} + +void CAsyncSocketEx::RemoveAllLayers() +{ + m_pFirstLayer=0; + m_pLastLayer=0; +} + +int CAsyncSocketEx::OnLayerCallback(const CAsyncSocketExLayer *pLayer, int nType, int nParam1, int nParam2) +{ + ASSERT(pLayer); + return 1; +} +#endif //NOLAYERS + +BOOL CAsyncSocketEx::GetSockOpt(int nOptionName, void* lpOptionValue, int* lpOptionLen, int nLevel /*=SOL_SOCKET*/) +{ + return (SOCKET_ERROR != getsockopt(m_SocketData.hSocket, nLevel, nOptionName, (LPSTR)lpOptionValue, lpOptionLen)); +} + +BOOL CAsyncSocketEx::SetSockOpt(int nOptionName, const void* lpOptionValue, int nOptionLen, int nLevel /*=SOL_SOCKET*/) +{ + return (SOCKET_ERROR != setsockopt(m_SocketData.hSocket, nLevel, nOptionName, (LPSTR)lpOptionValue, nOptionLen)); +} diff --git a/Client/Client/net/Socket/AsyncSocketEx.h b/Client/Client/net/Socket/AsyncSocketEx.h new file mode 100644 index 00000000..330b54c7 --- /dev/null +++ b/Client/Client/net/Socket/AsyncSocketEx.h @@ -0,0 +1,275 @@ +/*CAsyncSocketEx by Tim Kosse (Tim.Kosse@gmx.de) + Version 1.2 (2003-03-28) +-------------------------------------------------------- + +Introduction: +------------- + +CAsyncSocketEx is a replacement for the MFC class CAsyncSocket. +This class was written because CAsyncSocket is not the fastest WinSock +wrapper and it's very hard to add new functionality to CAsyncSocket +derived classes. This class offers the same functionality as CAsyncSocket. +Also, CAsyncSocketEx offers some enhancements which were not possible with +CAsyncSocket without some tricks. + +How do I use it? +---------------- +Basically exactly like CAsyncSocket. +To use CAsyncSocketEx, just replace all occurrences of CAsyncSocket in your +code with CAsyncSocketEx. If you did not enhance CAsyncSocket yourself in +any way, you won't have to change anything else in your code. + +Why is CAsyncSocketEx faster? +----------------------------- + +CAsyncSocketEx is slightly faster when dispatching notification event messages. +First have a look at the way CAsyncSocket works. For each thread that uses +CAsyncSocket, a window is created. CAsyncSocket calls WSAAsyncSelect with +the handle of that window. Until here, CAsyncSocketEx works the same way. +But CAsyncSocket uses only one window message (WM_SOCKET_NOTIFY) for all +sockets within one thread. When the window recieve WM_SOCKET_NOTIFY, wParam +contains the socket handle and the window looks up an CAsyncSocket instance +using a map. CAsyncSocketEx works differently. It's helper window uses a +wide range of different window messages (WM_USER through 0xBFFF) and passes +a different message to WSAAsyncSelect for each socket. When a message in +the specified range is received, CAsyncSocketEx looks up the pointer to a +CAsyncSocketEx instance in an Array using the index of message - WM_USER. +As you can see, CAsyncSocketEx uses the helper window in a more efficient +way, as it don't have to use the slow maps to lookup it's own instance. +Still, speed increase is not very much, but it may be noticeable when using +a lot of sockets at the same time. +Please note that the changes do not affect the raw data throughput rate, +CAsyncSocketEx only dispatches the notification messages faster. + +What else does CAsyncSocketEx offer? +------------------------------------ + +CAsyncSocketEx offers a flexible layer system. One example is the proxy layer. +Just create an instance of the proxy layer, configure it and add it to the layer +chain of your CAsyncSocketEx instance. After that, you can connect through +proxies. +Benefit: You don't have to change much to use the layer system. +Another layer that is currently in development is the SSL layer to establish +SSL encrypted connections. + +License +------- + +Feel free to use this class, as long as you don't claim that you wrote it +and this copyright notice stays intact in the source files. +If you use this class in commercial applications, please send a short message +to tim.kosse@gmx.de +*/ + +#if !defined(AFX_ASYNCSOCKETEX_H__AA9E4531_63B1_442F_9A71_09B2FEEDF34E__INCLUDED_) +#define AFX_ASYNCSOCKETEX_H__AA9E4531_63B1_442F_9A71_09B2FEEDF34E__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define FD_FORCEREAD (1<<15) + +#include "winsock.h" + +class CAsyncSocketExHelperWindow; + +#ifndef NOLAYERS +class CAsyncSocketExLayer; +#endif //NOLAYERS +class CCriticalSectionWrapper; +class CAsyncSocketEx +{ +public: + /////////////////////////////////////// + //Functions that imitate CAsyncSocket// + /////////////////////////////////////// + + //Construction + //------------ + + //Constructs a CAsyncSocketEx object. + CAsyncSocketEx(); + virtual ~CAsyncSocketEx(); + + //Creates a socket. + BOOL Create(UINT nSocketPort = 0, int nSocketType = SOCK_STREAM, + long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE, + LPCTSTR lpszSocketAddress = NULL ); + + + //Attributes + //--------- + + //Attaches a socket handle to a CAsyncSocketEx object. + BOOL Attach( SOCKET hSocket, + long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | + FD_CONNECT | FD_CLOSE ); + + //Detaches a socket handle from a CAsyncSocketEx object. + SOCKET Detach( ); + + //Gets the error status for the last operation that failed. + static int GetLastError(); + + //Gets the address of the peer socket to which the socket is connected. +#ifdef _AFX + BOOL GetPeerName( CString& rPeerAddress, UINT& rPeerPort ); +#endif + BOOL GetPeerName( SOCKADDR* lpSockAddr, int* lpSockAddrLen ); + + //Gets the local name for a socket. +#ifdef _AFX + BOOL GetSockName( CString& rSocketAddress, UINT& rSocketPort ); +#endif + BOOL GetSockName( SOCKADDR* lpSockAddr, int* lpSockAddrLen ); + + //Retrieves a socket option. + BOOL GetSockOpt(int nOptionName, void* lpOptionValue, int* lpOptionLen, int nLevel = SOL_SOCKET); + + //Sets a socket option. + BOOL SetSockOpt(int nOptionName, const void* lpOptionValue, int nOptionLen, int nLevel = SOL_SOCKET); + + + //Operations + //---------- + + //Accepts a connection on the socket. + virtual BOOL Accept( CAsyncSocketEx& rConnectedSocket, SOCKADDR* lpSockAddr = NULL, int* lpSockAddrLen = NULL ); + + //Requests event notification for the socket. + BOOL AsyncSelect( long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE ); + + //Associates a local address with the socket. + BOOL Bind(UINT nSocketPort, LPCTSTR lpszSocketAddress); + BOOL Bind(const SOCKADDR* lpSockAddr, int nSockAddrLen); + + //Closes the socket. + virtual void Close(); + + //Establishes a connection to a peer socket. + virtual BOOL Connect(LPCTSTR lpszHostAddress, UINT nHostPort); + virtual BOOL Connect( const SOCKADDR* lpSockAddr, int nSockAddrLen ); + + //Controls the mode of the socket. + BOOL IOCtl( long lCommand, DWORD* lpArgument ); + + //Establishes a socket to listen for incoming connection requests. + BOOL Listen( int nConnectionBacklog = 5 ); + + //Receives data from the socket. + virtual int Receive(void* lpBuf, int nBufLen, int nFlags=0); + + //Sends data to a connected socket. + virtual int Send(const void* lpBuf, int nBufLen, int nFlags=0); + + //Disables Send and/or Receive calls on the socket. + BOOL ShutDown( int nHow = sends ); + enum { receives = 0, sends = 1, both = 2 }; + + //Overridable Notification Functions + //---------------------------------- + + //Notifies a listening socket that it can accept pending connection requests by calling Accept. + virtual void OnAccept(int nErrorCode); + + //Notifies a socket that the socket connected to it has closed. + virtual void OnClose(int nErrorCode); + + //Notifies a connecting socket that the connection attempt is complete, whether successfully or in error. + virtual void OnConnect(int nErrorCode); + + //Notifies a listening socket that there is data to be retrieved by calling Receive. + virtual void OnReceive(int nErrorCode); + + //Notifies a socket that it can send data by calling Send. + virtual void OnSend(int nErrorCode); + + //////////////////////// + //Additional functions// + //////////////////////// + +#ifndef NOLAYERS + //Resets layer chain. + void RemoveAllLayers(); + + //Attaches a new layer to the socket. + BOOL AddLayer(CAsyncSocketExLayer *pLayer); +#endif //NOLAYERS + + //Returns the handle of the socket. + SOCKET GetSocketHandle(); + + //Trigers an event on the socket + // Any combination of FD_READ, FD_WRITE, FD_CLOSE, FD_ACCEPT, FD_CONNECT and FD_FORCEREAD is valid for lEvent. + BOOL TriggerEvent(long lEvent); + +protected: + //Strucure to hold the socket data + struct t_AsyncSocketExData + { + SOCKET hSocket; //Socket handle + int nSocketIndex; //Index of socket, required by CAsyncSocketExHelperWindow + } m_SocketData; + + //If using layers, only the events specified with m_lEvent will send to the event handlers. + long m_lEvent; + + //AsyncGetHostByName + char *m_pAsyncGetHostByNameBuffer; //Buffer for hostend structure + HANDLE m_hAsyncGetHostByNameHandle; //TaskHandle + int m_nAsyncGetHostByNamePort; //Port to connect to + + //Returns the handle of the helper window + HWND GetHelperWindowHandle(); + + //Attaches socket handle to helper window + void AttachHandle(SOCKET hSocket); + + //Detaches socket handle to helper window + void DetachHandle(SOCKET hSocket); + + //Critical section for thread synchronization + static CCriticalSectionWrapper m_sGlobalCriticalSection; + + //Pointer to the data of the local thread + struct t_AsyncSocketExThreadData + { + CAsyncSocketExHelperWindow *m_pHelperWindow; + int nInstanceCount; + DWORD nThreadId; + } *m_pLocalAsyncSocketExThreadData; + + //List of the data structures for all threads + static struct t_AsyncSocketExThreadDataList + { + t_AsyncSocketExThreadDataList *pNext; + t_AsyncSocketExThreadData *pThreadData; + } *m_spAsyncSocketExThreadDataList; + + //Initializes Thread data and helper window, fills m_pLocalAsyncSocketExThreadData + BOOL InitAsyncSocketExInstance(); + + //Destroys helper window after last instance of CAsyncSocketEx in current thread has been closed + void FreeAsyncSocketExInstance(); + +#ifndef NOLAYERS + //Layer chain + CAsyncSocketExLayer *m_pFirstLayer; + CAsyncSocketExLayer *m_pLastLayer; + + friend CAsyncSocketExLayer; + + //Called by the layers to notify application of some events + virtual int OnLayerCallback(const CAsyncSocketExLayer *pLayer, int nType, int nParam1, int nParam2); +#endif //NOLAYERS + + friend CAsyncSocketExHelperWindow; +}; + +#ifndef NOLAYERS +#define LAYERCALLBACK_STATECHANGE 0 +#define LAYERCALLBACK_LAYERSPECIFIC 1 +#endif //NOLAYERS + +#endif // !defined(AFX_ASYNCSOCKETEX_H__AA9E4531_63B1_442F_9A71_09B2FEEDF34E__INCLUDED_) diff --git a/Client/Client/net/Socket/ISocket.h b/Client/Client/net/Socket/ISocket.h new file mode 100644 index 00000000..ad00fcc1 --- /dev/null +++ b/Client/Client/net/Socket/ISocket.h @@ -0,0 +1,22 @@ +#pragma once +#include "../../util/CBuffer.h" +#include "../../../NMessage/BufferMessage.h" + +class CAsyncSocketEx; + +interface ISocketListener +{ +public: + virtual void OnAccept (int nErrorCode,CAsyncSocketEx* pSock) =0; + virtual void OnClose (int nErrorCode,CAsyncSocketEx* pSock) =0; + virtual void OnConnect (int nErrorCode,CAsyncSocketEx* pSock) =0; + virtual void OnOutOfBandData (int nErrorCode,CAsyncSocketEx* pSock) =0; + virtual void OnReceive (int nErrorCode,CAsyncSocketEx* pSock) =0; + virtual void OnSend (int nErrorCode,CAsyncSocketEx* pSock) =0; +}; + +interface IVNOCSocketListener : public ISocketListener +{ +public: + virtual void OnPackReady(const CBufferMessage &buffer) = 0; +}; diff --git a/Client/Client/net/Socket/SockWnd.cpp b/Client/Client/net/Socket/SockWnd.cpp new file mode 100644 index 00000000..97fc415e --- /dev/null +++ b/Client/Client/net/Socket/SockWnd.cpp @@ -0,0 +1,38 @@ +#include "SockWnd.h" +#include "../../util/util.h" + +CSocketWnd::CSocketWnd() +{ + _InitThread(); +} + +CSocketWnd::~CSocketWnd() +{ + +} + +void CSocketWnd::_InitThread() +{ + m_thread.Start(); +} + +BOOL CSocketWnd::RegisterSocket( SOCKET sock,ISocketWinListener* listener ) +{ + Util::CAutoCS ac(m_cs); + m_listeners[sock] = listener; + return TRUE; +} + +VOID CSocketWnd::RemoveSocket( SOCKET sock ) +{ + Util::CAutoCS ac(m_cs); + auto i = m_listeners.find(sock); + if (i != m_listeners.end()) + { + m_listeners.erase(i); + } +} + +void CSocketWnd::_AddSocket( SOCKET sock ) +{ +} diff --git a/Client/Client/net/Socket/SockWnd.h b/Client/Client/net/Socket/SockWnd.h new file mode 100644 index 00000000..0a7c8114 --- /dev/null +++ b/Client/Client/net/Socket/SockWnd.h @@ -0,0 +1,28 @@ +#include +#include +#include +#include "../../util/TaskThread.h" + +interface ISocketWinListener +{ +public: + ; +}; + +class CSocketWnd +{ +public: + CSocketWnd(); + ~CSocketWnd(); +public: + BOOL RegisterSocket(SOCKET sock,ISocketWinListener* listener); + VOID RemoveSocket(SOCKET sock); +private: + void _InitThread(); + void _AddSocket(SOCKET sock); +private: + typedef std::map SocketListenerMap; + ATL::CCriticalSection m_cs; + Thread::CTaskWinThread m_thread; + SocketListenerMap m_listeners; +}; \ No newline at end of file diff --git a/Client/Client/net/Socket/VNOCSocket.cpp b/Client/Client/net/Socket/VNOCSocket.cpp new file mode 100644 index 00000000..76bef96e --- /dev/null +++ b/Client/Client/net/Socket/VNOCSocket.cpp @@ -0,0 +1,120 @@ +#include "stdafx.h" +#include "VNOCSocket.h" +#include "../../../../NMessage/Message2Parser.h" +#include "../../../../NMessage/BufferMessage.h" +#include "../../util/util.h" + +CSocketImpl::CSocketImpl(ISocketListener *pListener) : m_listener(pListener) +{ +} + +CSocketImpl::~CSocketImpl() +{ +} + +void CSocketImpl::OnAccept(int nErrorCode) +{ + if (m_listener) + { + m_listener->OnAccept(nErrorCode,this); + } + CAsyncSocketEx::OnAccept(nErrorCode); +} + +void CSocketImpl::OnClose(int nErrorCode) +{ + if (m_listener) + { + m_listener->OnClose(nErrorCode,this); + } + CAsyncSocketEx::OnClose(nErrorCode); +} + +void CSocketImpl::OnConnect(int nErrorCode) +{ + if (m_listener) + { + m_listener->OnConnect(nErrorCode,this); + } + CAsyncSocketEx::OnConnect(nErrorCode); +} + +void CSocketImpl::OnOutOfBandData(int nErrorCode) +{ + if (m_listener) + { + m_listener->OnOutOfBandData(nErrorCode,this); + } + //CAsyncSocketEx::OnOutOfBandData(nErrorCode); +} + +void CSocketImpl::OnReceive(int nErrorCode) +{ + if (m_listener) + { + m_listener->OnReceive(nErrorCode,this); + } + CAsyncSocketEx::OnReceive(nErrorCode); +} + +void CSocketImpl::OnSend(int nErrorCode) +{ + if (m_listener) + { + m_listener->OnSend(nErrorCode,this); + } + CAsyncSocketEx::OnSend(nErrorCode); +} + +void CSocketImpl::SetListener( ISocketListener *pListener ) +{ + m_listener = pListener; +} + +////////////////////////////////////////////////////////////////////////// + +CVNOCSocket::CVNOCSocket( ISocketListener *pListener/*=NULL*/ ) + :CSocketImpl(pListener) +{ + +} + +CVNOCSocket::~CVNOCSocket() +{ +} + +void CVNOCSocket::OnReceive( int nErrorCode ) +{ + int length = 0; + Util::CAutoCS ac(m_cs); + length = ((CAsyncSocketEx*)this)->Receive(m_buffer.AllocAppend(1024),1024); + if (FAILED(length)) + { + Global->Logf(LogFile_Net,_T("Socket󣬴:%d"),GetLastError()); + Global->CriticalError(_T("Socket쳣޷")); + return; + } + m_buffer.AccomplishAppend(length); + _TryParse(); +} + +VOID CVNOCSocket::_TryParse() +{ // bufferݰ + CBufferMessage buffer; + buffer.Attach(m_buffer.GetBuffer(), + CMessage2Parser::GetMessageLen(m_buffer.GetBuffer(), m_buffer.GetSize())); + CMessage2Parser parser; + if(parser.IsVaild(buffer)) + { + IVNOCSocketListener *pListener=NULL; + pListener = dynamic_cast(m_listener); + if (pListener) + { + pListener->OnPackReady(buffer); + } + m_buffer.Get(NULL, buffer.GetSize()); + } + buffer.Detach(); +} + +////////////////////////////////////////////////////////////////////////// diff --git a/VNOC/VNOC/VNOCSocket.h b/Client/Client/net/Socket/VNOCSocket.h similarity index 82% rename from VNOC/VNOC/VNOCSocket.h rename to Client/Client/net/Socket/VNOCSocket.h index 47c1e7f1..bcafe7cc 100644 --- a/VNOC/VNOC/VNOCSocket.h +++ b/Client/Client/net/Socket/VNOCSocket.h @@ -1,38 +1,40 @@ -#pragma once - -#include "ISocket.h" -#include "GlobalDefine.h" -#include "../util/CBuffer.h" - -#include -#include - -class CSocketImpl : public CAsyncSocket -{ -public: - CSocketImpl(ISocketListener *pListener=NULL); - virtual ~CSocketImpl(); - virtual void OnAccept(int nErrorCode); - virtual void OnClose(int nErrorCode); - virtual void OnConnect(int nErrorCode); - virtual void OnOutOfBandData(int nErrorCode); - virtual void OnReceive(int nErrorCode); - virtual void OnSend(int nErrorCode); - void SetListener(ISocketListener *pListener); // һʵֻһ -private: - ISocketListener *m_listener; -}; - -class CVNOCSocket: public CSocketImpl -{ -public: - CVNOCSocket(ISocketListener *pListener=NULL); - virtual ~CVNOCSocket(); - virtual void OnReceive(int nErrorCode); -private: - VOID _TryParse(); -private: - CAutoStreamBuffer m_buffer; - CCriticalSection m_cs; -}; - +#pragma once + +#include "stdafx.h" + +#define NOLAYERS +#include "AsyncSocketEx.h" +#include "ISocket.h" +#include "../../util/CBuffer.h" + +#include + +class CSocketImpl : public CAsyncSocketEx +{ +public: + CSocketImpl(ISocketListener *pListener=NULL); + virtual ~CSocketImpl(); + virtual void OnAccept(int nErrorCode); + virtual void OnClose(int nErrorCode); + virtual void OnConnect(int nErrorCode); + virtual void OnOutOfBandData(int nErrorCode); + virtual void OnReceive(int nErrorCode); + virtual void OnSend(int nErrorCode); + void SetListener(ISocketListener *pListener); // һʵֻһ +protected: + ISocketListener *m_listener; +}; + +class CVNOCSocket: public CSocketImpl +{ +public: + CVNOCSocket(ISocketListener *pListener=NULL); + virtual ~CVNOCSocket(); + virtual void OnReceive(int nErrorCode); +private: + VOID _TryParse(); +private: + CAutoStreamBuffer m_buffer; + CCriticalSection m_cs; +}; + diff --git a/Client/Client/postDispatch.bat b/Client/Client/postDispatch.bat new file mode 100644 index 00000000..c12974ad --- /dev/null +++ b/Client/Client/postDispatch.bat @@ -0,0 +1,8 @@ +@echo off +setlocal EnableDelayedExpansion + +@xcopy /f/c/y "Resource/*" "../%1" > nul +@xcopy /f/c/y "../../ThirdLibs/VisualLeakDetector/bin/Win32" "../%1" > nul + +:gEnd +@echo "Post Dispatch OK!" \ No newline at end of file diff --git a/Client/Client/preLink.bat b/Client/Client/preLink.bat new file mode 100644 index 00000000..dd3d8b2f --- /dev/null +++ b/Client/Client/preLink.bat @@ -0,0 +1,7 @@ +@echo off + +@xcopy /e/c/y "../../ThirdLibs/VisualLeakDetector/bin/%2" "%1" > nul +@xcopy /e/c/y "../../ThirdLibs/scintilla/bin" "%1" > nul + +:gEnd +@echo "PreLink Event OK! " \ No newline at end of file diff --git a/Client/Client/resource.h b/Client/Client/resource.h new file mode 100644 index 00000000..7ca31da7 --- /dev/null +++ b/Client/Client/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Resource.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/VNOC/util/BLog.cpp b/Client/Client/util/BLog.cpp similarity index 94% rename from VNOC/util/BLog.cpp rename to Client/Client/util/BLog.cpp index 788f3134..b0f4124d 100644 --- a/VNOC/util/BLog.cpp +++ b/Client/Client/util/BLog.cpp @@ -1,268 +1,268 @@ -#include "BLog.h" -#include "util.h" - -namespace blog -{ - CBLog::CBLog(void) - { - m_indent = 0; - } - - CBLog::~CBLog(void) - { - LogDeviceListType::iterator i; - i = m_logDevice.begin(); - while (i != m_logDevice.end()) - { - i->second->Close(); - delete i->second; - ++i; - } - } - - void CBLog::AddDevice( BLOG_TYPE type,CLogDeviceBase* device ) - { - m_cs.Enter(); - if (m_logDevice.find(type) != m_logDevice.end()) - { - delete m_logDevice[type]; - } - m_logDevice.insert(std::make_pair(type,device)); - m_cs.Leave(); - } - - void CBLog::Log( DWORD deviceMask,LPCTSTR strlog,BOOL info/*=TRUE*/,BOOL autoEndLine/*=TRUE*/ ) - { - CString logText; - if (info) - { - _AddInfo(logText); - _AddPrefix(logText); - logText += _T('|'); - logText += _T('\t'); - _AddIndent(logText); - } - logText += strlog; - if (autoEndLine) - { - logText += _T('\n'); - } - - m_cs.Enter(); - LogDeviceListType::iterator i; - i = m_logDevice.begin(); - while (i != m_logDevice.end()) - { - if (deviceMask & i->first) - { - i->second->Write(logText); - } - ++i; - } - m_cs.Leave(); - } - - void CBLog::Logf( DWORD deviceMask,LPCTSTR fmt,... ) - { - CString strFormat; - va_list vlist; - va_start(vlist,fmt); - strFormat.Format(fmt,vlist); - va_end(vlist); - return Log(deviceMask,strFormat,TRUE,FALSE); - } - - void CBLog::_AddIndent(CString &strLog) - { - if (m_indent) - { - strLog += _T(" "); - } - for (UINT n=0; nsecond,threadID); - } - else - { - strLog.AppendFormat(_T("%d \t"), threadID); - } - } - - void CBLog::_AddPrefix( CString &strLog ) - { - PrefixVectorType::iterator i; - i = m_Prefix.begin(); - if (i == m_Prefix.end()) - { - return; - } - while (i != m_Prefix.end()) - { - strLog += *i++; - if (i != m_Prefix.end()) - { - strLog +=_T("::"); - } - } - //strLog += _T(" \t"); - } - - void CBLog::AddPrefix( LPCTSTR strPrefix ) - { - ATLASSERT(strPrefix); - if (strPrefix) - { - m_Prefix.push_back(strPrefix); - } - } - - void CBLog::RemoveLastPrefix() - { - if (!m_Prefix.empty()) - { - m_Prefix.pop_back(); - } - } - - CLogDeviceBase* CBLog::GetDevice( BLOG_TYPE type ) - { - LogDeviceListType::iterator i; - i = m_logDevice.find(type); - if (i != m_logDevice.end()) - { - return i->second; - } - return NULL; - } - - CLogDeviceBase* CBLog::RemoveDevice( BLOG_TYPE type ) - { - LogDeviceListType::iterator i; - i = m_logDevice.find(type); - if ( i != m_logDevice.end()) - { - CLogDeviceBase* pBase = i->second; - m_logDevice.erase(i); - return pBase; - } - return NULL; - } - - void CBLog::SetThreadName( DWORD threadID,LPCTSTR name ) - { - ThreadNameMap::iterator i; - i = m_threadNameMap.find(threadID); - if ( i != m_threadNameMap.end()) - { - i->second = name; - } - else - { - m_threadNameMap.insert(std::make_pair(threadID,name)); - } - } - - - BOOL CLogDeviceFile::Open(LPCTSTR param) - { - m_fp = NULL; - CString logFile; - if (param) - { - logFile = param; - errno_t err = _tfopen_s(&m_fp,logFile,_T("at+")); - if (m_fp) - { - CTime currTime = CTime::GetCurrentTime(); - _ftprintf_s(m_fp,_T("-----------------------------------\nLog Generated At %s\n"),currTime.Format(TIME_FORMAT_STRING)); - } - } - return m_fp!=NULL; - } - - void CLogDeviceFile::Close() - { - if (m_fp) - { - fclose(m_fp); m_fp = NULL; - } - } - - void CLogDeviceFile::Write( LPCTSTR strLog ) - { - if (strLog && m_fp) - { - _ftprintf_s(m_fp,_T("%s"),strLog); - } - } - - void CLogDeviceFile::flush() - { - if (m_fp) - { - fflush(m_fp); - } - } - - - CLogDeviceConsole::CLogDeviceConsole() : m_free_console_on_close(false) - , m_handle(NULL) - , m_default_attr(0) - { - - } - - BOOL CLogDeviceConsole::Open(LPCTSTR param) - { - if (::AllocConsole()) - { - m_free_console_on_close = true; - } - m_handle = ::GetStdHandle(STD_OUTPUT_HANDLE); - if (is_handle_valid(m_handle)) - { - CONSOLE_SCREEN_BUFFER_INFO csbi; - GetConsoleScreenBufferInfo(m_handle, &csbi); - m_default_attr = csbi.wAttributes; - return TRUE; - } - return FALSE; - } - - void CLogDeviceConsole::Close() - { - if (m_free_console_on_close) - { - ::FreeConsole(); - m_handle = NULL; - } - } - - void CLogDeviceConsole::Write( LPCTSTR strLog ) - { - if (!is_handle_valid(m_handle)) return; - DWORD wrote; - ::WriteConsole(m_handle, strLog, static_cast(_tcslen(strLog)), &wrote, NULL); - } - +#include "BLog.h" +#include "util.h" + +namespace blog +{ + CBLog::CBLog(void) + { + m_indent = 0; + } + + CBLog::~CBLog(void) + { + LogDeviceListType::iterator i; + i = m_logDevice.begin(); + while (i != m_logDevice.end()) + { + i->second->Close(); + delete i->second; + ++i; + } + } + + void CBLog::AddDevice( BLOG_TYPE type,CLogDeviceBase* device ) + { + m_cs.Enter(); + if (m_logDevice.find(type) != m_logDevice.end()) + { + delete m_logDevice[type]; + } + m_logDevice.insert(std::make_pair(type,device)); + m_cs.Leave(); + } + + void CBLog::Log( DWORD deviceMask,LPCTSTR strlog,BOOL info/*=TRUE*/,BOOL autoEndLine/*=TRUE*/ ) + { + CString logText; + if (info) + { + _AddInfo(logText); + _AddPrefix(logText); + logText += _T('|'); + logText += _T('\t'); + _AddIndent(logText); + } + logText += strlog; + if (autoEndLine) + { + logText += _T('\n'); + } + + m_cs.Enter(); + LogDeviceListType::iterator i; + i = m_logDevice.begin(); + while (i != m_logDevice.end()) + { + if (deviceMask & i->first) + { + i->second->Write(logText); + } + ++i; + } + m_cs.Leave(); + } + + void CBLog::Logf( DWORD deviceMask,LPCTSTR fmt,... ) + { + CString strFormat; + va_list vlist; + va_start(vlist,fmt); + strFormat.Format(fmt,vlist); + va_end(vlist); + return Log(deviceMask,strFormat,TRUE,FALSE); + } + + void CBLog::_AddIndent(CString &strLog) + { + if (m_indent) + { + strLog += _T(" "); + } + for (UINT n=0; nsecond,threadID); + } + else + { + strLog.AppendFormat(_T("%d \t"), threadID); + } + } + + void CBLog::_AddPrefix( CString &strLog ) + { + PrefixVectorType::iterator i; + i = m_Prefix.begin(); + if (i == m_Prefix.end()) + { + return; + } + while (i != m_Prefix.end()) + { + strLog += *i++; + if (i != m_Prefix.end()) + { + strLog +=_T("::"); + } + } + //strLog += _T(" \t"); + } + + void CBLog::AddPrefix( LPCTSTR strPrefix ) + { + ATLASSERT(strPrefix); + if (strPrefix) + { + m_Prefix.push_back(strPrefix); + } + } + + void CBLog::RemoveLastPrefix() + { + if (!m_Prefix.empty()) + { + m_Prefix.pop_back(); + } + } + + CLogDeviceBase* CBLog::GetDevice( BLOG_TYPE type ) + { + LogDeviceListType::iterator i; + i = m_logDevice.find(type); + if (i != m_logDevice.end()) + { + return i->second; + } + return NULL; + } + + CLogDeviceBase* CBLog::RemoveDevice( BLOG_TYPE type ) + { + LogDeviceListType::iterator i; + i = m_logDevice.find(type); + if ( i != m_logDevice.end()) + { + CLogDeviceBase* pBase = i->second; + m_logDevice.erase(i); + return pBase; + } + return NULL; + } + + void CBLog::SetThreadName( DWORD threadID,LPCTSTR name ) + { + ThreadNameMap::iterator i; + i = m_threadNameMap.find(threadID); + if ( i != m_threadNameMap.end()) + { + i->second = name; + } + else + { + m_threadNameMap.insert(std::make_pair(threadID,name)); + } + } + + + BOOL CLogDeviceFile::Open(LPCTSTR param) + { + m_fp = NULL; + CString logFile; + if (param) + { + logFile = param; + errno_t err = _tfopen_s(&m_fp,logFile,_T("at+")); + if (m_fp) + { + CTime currTime = CTime::GetCurrentTime(); + _ftprintf_s(m_fp,_T("-----------------------------------\nLog Generated At %s\n"),currTime.Format(TIME_FORMAT_STRING)); + } + } + return m_fp!=NULL; + } + + void CLogDeviceFile::Close() + { + if (m_fp) + { + fclose(m_fp); m_fp = NULL; + } + } + + void CLogDeviceFile::Write( LPCTSTR strLog ) + { + if (strLog && m_fp) + { + _ftprintf_s(m_fp,_T("%s"),strLog); + } + } + + void CLogDeviceFile::flush() + { + if (m_fp) + { + fflush(m_fp); + } + } + + + CLogDeviceConsole::CLogDeviceConsole() : m_free_console_on_close(false) + , m_handle(NULL) + , m_default_attr(0) + { + + } + + BOOL CLogDeviceConsole::Open(LPCTSTR param) + { + if (::AllocConsole()) + { + m_free_console_on_close = true; + } + m_handle = ::GetStdHandle(STD_OUTPUT_HANDLE); + if (is_handle_valid(m_handle)) + { + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(m_handle, &csbi); + m_default_attr = csbi.wAttributes; + return TRUE; + } + return FALSE; + } + + void CLogDeviceConsole::Close() + { + if (m_free_console_on_close) + { + ::FreeConsole(); + m_handle = NULL; + } + } + + void CLogDeviceConsole::Write( LPCTSTR strLog ) + { + if (!is_handle_valid(m_handle)) return; + DWORD wrote; + ::WriteConsole(m_handle, strLog, static_cast(_tcslen(strLog)), &wrote, NULL); + } + } \ No newline at end of file diff --git a/VNOC/util/BLog.h b/Client/Client/util/BLog.h similarity index 95% rename from VNOC/util/BLog.h rename to Client/Client/util/BLog.h index 04369621..ae1ddd88 100644 --- a/VNOC/util/BLog.h +++ b/Client/Client/util/BLog.h @@ -1,166 +1,166 @@ -#pragma once -#include "vector" -#include "map" -#include "time.h" -#include "atlstr.h" -#include "atlsync.h" -#include - -// ˱׼(file)жһɣҪӶ壬static_castǿת -enum BLOG_TYPE -{ - BLOG_NOLOG = 0, - BLOG_DBGVIEW = 1, - BLOG_FILE = 2, - BLOG_CONSOLE = 4 -}; - -#define TIME_FORMAT_STRING _T("%Y-%m-%d %H:%M:%S") - -namespace blog -{ - class CLogDeviceBase - { - public: - virtual ~CLogDeviceBase(){}; - virtual BOOL Open(LPCTSTR param=NULL) = 0; - virtual void Close() = 0; - virtual void Write(LPCTSTR strLog) = 0; - virtual void flush() = 0; - }; - - typedef std::map LogDeviceListType; - typedef std::vector PrefixVectorType; - typedef std::map ThreadNameMap; - - class CBLog - { - public: - CBLog(void); - ~CBLog(void); - public: - void SetThreadName(DWORD threadID,LPCTSTR name); - - void Log(DWORD deviceMask,LPCTSTR strlog,BOOL info=TRUE,BOOL autoEndLine=TRUE); - void Logf(DWORD deviceMask,LPCTSTR fmt,...); - - void AddDevice(BLOG_TYPE type,CLogDeviceBase* device); - CLogDeviceBase* GetDevice(BLOG_TYPE type); - CLogDeviceBase* RemoveDevice(BLOG_TYPE type); - - void AddPrefix(LPCTSTR strPrefix); - void RemoveLastPrefix(); - - void IncreaseIndent(){++m_indent;}; - void DecreaseIndent(){if(m_indent)--m_indent;}; - - private: - void _AddInfo(CString &strLog); - void _AddPrefix(CString &strLog); - void _AddIndent(CString &strlog); - private: - DWORD m_indent; - LogDeviceListType m_logDevice; - PrefixVectorType m_Prefix; - ThreadNameMap m_threadNameMap; - ATL::CCriticalSection m_cs; - }; - - class CLogDeviceFile:public CLogDeviceBase - { - public: - virtual BOOL Open(LPCTSTR param=NULL); - virtual void Close(); - virtual void Write(LPCTSTR strLog); - virtual void flush(); - private: - CString m_file; - FILE *m_fp; - }; - - class CLogDeviceDBGView:public CLogDeviceBase - { - public: - virtual BOOL Open(LPCTSTR param=NULL){return TRUE;}; - virtual void Close(){}; - virtual void Write(LPCTSTR strLog) - { - ::OutputDebugString(strLog); - }; - virtual void flush(){}; - }; - - class CLogDeviceMem : public CLogDeviceBase - { - public: - virtual BOOL Open(LPCTSTR param=NULL){return TRUE;}; - virtual void Close(){}; - virtual void Write(LPCTSTR strLog) - { - m_log += strLog; - }; - virtual void flush(){}; - - void get_log(std::wstring& str){str = CStringW(m_log);}; - - private: - CString m_log; - }; - - - class CLogDeviceConsole : public CLogDeviceBase - { - public: - CLogDeviceConsole(); - - virtual BOOL Open(LPCTSTR param=NULL); - virtual void Close(); - virtual void flush(){} - - virtual void Write(LPCTSTR strLog); - - protected: - HANDLE m_handle; - WORD m_default_attr; - bool m_free_console_on_close; - bool padding[1]; - - private: - static bool is_handle_valid(HANDLE handle) - { - return (handle != NULL && handle != INVALID_HANDLE_VALUE); - } - }; -} - -namespace blog -{ - class CAutoBLogIndent - { - public: - CAutoBLogIndent(CBLog *theLog) : m_theLog(NULL) - { - if (theLog) - { - m_theLog = theLog; - theLog->IncreaseIndent(); - } - }; - ~CAutoBLogIndent() - { - if (m_theLog) - { - m_theLog->DecreaseIndent(); - } - } - CBLog *m_theLog; - }; - - class CAutoBLogPrefix - { - public: - CAutoBLogPrefix(CBLog *theLog,LPCTSTR text){if(theLog){m_theLog=theLog;theLog->AddPrefix(text);}} - ~CAutoBLogPrefix(){m_theLog->RemoveLastPrefix();} - CBLog *m_theLog; - }; -} +#pragma once +#include "vector" +#include "map" +#include "time.h" +#include "atlstr.h" +#include "atlsync.h" +#include + +// ˱׼(file)жһɣҪӶ壬static_castǿת +enum BLOG_TYPE +{ + BLOG_NOLOG = 0, + BLOG_DBGVIEW = 1, + BLOG_FILE = 2, + BLOG_CONSOLE = 4 +}; + +#define TIME_FORMAT_STRING _T("%Y-%m-%d %H:%M:%S") + +namespace blog +{ + class CLogDeviceBase + { + public: + virtual ~CLogDeviceBase(){}; + virtual BOOL Open(LPCTSTR param=NULL) = 0; + virtual void Close() = 0; + virtual void Write(LPCTSTR strLog) = 0; + virtual void flush() = 0; + }; + + typedef std::map LogDeviceListType; + typedef std::vector PrefixVectorType; + typedef std::map ThreadNameMap; + + class CBLog + { + public: + CBLog(void); + ~CBLog(void); + public: + void SetThreadName(DWORD threadID,LPCTSTR name); + + void Log(DWORD deviceMask,LPCTSTR strlog,BOOL info=TRUE,BOOL autoEndLine=TRUE); + void Logf(DWORD deviceMask,LPCTSTR fmt,...); + + void AddDevice(BLOG_TYPE type,CLogDeviceBase* device); + CLogDeviceBase* GetDevice(BLOG_TYPE type); + CLogDeviceBase* RemoveDevice(BLOG_TYPE type); + + void AddPrefix(LPCTSTR strPrefix); + void RemoveLastPrefix(); + + void IncreaseIndent(){++m_indent;}; + void DecreaseIndent(){if(m_indent)--m_indent;}; + + private: + void _AddInfo(CString &strLog); + void _AddPrefix(CString &strLog); + void _AddIndent(CString &strlog); + private: + DWORD m_indent; + LogDeviceListType m_logDevice; + PrefixVectorType m_Prefix; + ThreadNameMap m_threadNameMap; + ATL::CCriticalSection m_cs; + }; + + class CLogDeviceFile:public CLogDeviceBase + { + public: + virtual BOOL Open(LPCTSTR param=NULL); + virtual void Close(); + virtual void Write(LPCTSTR strLog); + virtual void flush(); + private: + CString m_file; + FILE *m_fp; + }; + + class CLogDeviceDBGView:public CLogDeviceBase + { + public: + virtual BOOL Open(LPCTSTR param=NULL){return TRUE;}; + virtual void Close(){}; + virtual void Write(LPCTSTR strLog) + { + ::OutputDebugString(strLog); + }; + virtual void flush(){}; + }; + + class CLogDeviceMem : public CLogDeviceBase + { + public: + virtual BOOL Open(LPCTSTR param=NULL){return TRUE;}; + virtual void Close(){}; + virtual void Write(LPCTSTR strLog) + { + m_log += strLog; + }; + virtual void flush(){}; + + void get_log(std::wstring& str){str = CStringW(m_log);}; + + private: + CString m_log; + }; + + + class CLogDeviceConsole : public CLogDeviceBase + { + public: + CLogDeviceConsole(); + + virtual BOOL Open(LPCTSTR param=NULL); + virtual void Close(); + virtual void flush(){} + + virtual void Write(LPCTSTR strLog); + + protected: + HANDLE m_handle; + WORD m_default_attr; + bool m_free_console_on_close; + bool padding[1]; + + private: + static bool is_handle_valid(HANDLE handle) + { + return (handle != NULL && handle != INVALID_HANDLE_VALUE); + } + }; +} + +namespace blog +{ + class CAutoBLogIndent + { + public: + CAutoBLogIndent(CBLog *theLog) : m_theLog(NULL) + { + if (theLog) + { + m_theLog = theLog; + theLog->IncreaseIndent(); + } + }; + ~CAutoBLogIndent() + { + if (m_theLog) + { + m_theLog->DecreaseIndent(); + } + } + CBLog *m_theLog; + }; + + class CAutoBLogPrefix + { + public: + CAutoBLogPrefix(CBLog *theLog,LPCTSTR text){if(theLog){m_theLog=theLog;theLog->AddPrefix(text);}} + ~CAutoBLogPrefix(){m_theLog->RemoveLastPrefix();} + CBLog *m_theLog; + }; +} diff --git a/VNOC/util/CBuffer.cpp b/Client/Client/util/CBuffer.cpp similarity index 91% rename from VNOC/util/CBuffer.cpp rename to Client/Client/util/CBuffer.cpp index ab34d532..117e2ee9 100644 --- a/VNOC/util/CBuffer.cpp +++ b/Client/Client/util/CBuffer.cpp @@ -1,315 +1,318 @@ -#include "CBuffer.h" -#include "stdio.h" -#include -#include - -CBuffer::CBuffer( LPCTSTR _debug/*=NULL*/ ) -{ -#ifndef _DEBUG - UNREFERENCED_PARAMETER(_debug); -#endif - m_pBuf=NULL; - m_bufSize=0; - m_attached = FALSE; -#ifdef _DEBUG - m_debug = _debug; -#endif -} - -CBuffer::~CBuffer() -{ - _free(); -} - -BYTE* CBuffer::Alloc( DWORD size ) -{ - void *pTemp = realloc(m_pBuf,size+1); - if (pTemp != NULL) - { - m_pBuf = (BYTE*)pTemp; - m_bufSize = size; - m_pBuf[size]=0; - } - return m_pBuf; -} - -BYTE* CBuffer::GetBuffer() const -{ - return m_pBuf; -} - -DWORD CBuffer::GetSize() const -{ - return m_bufSize; -} - -const BYTE* CBuffer::Copy( const void* src,DWORD len ) -{ - Alloc(len); - if (m_pBuf) - { - ::memcpy(m_pBuf,src,len); - m_bufSize=len; - } - return *this; -} - -const BYTE* CBuffer::Copy( const CBuffer& src ) -{ - return Copy(src,src.GetSize()); -} - -DWORD CBuffer::Write( void* p,DWORD size,DWORD startPos ) -{ - if (startPos >= m_bufSize || p==NULL || m_pBuf==NULL) - { - return 0; - } - if (startPos + size >= m_bufSize) - { - size = m_bufSize-startPos-1; - } - if (size) - { - ::memcpy(m_pBuf+startPos,p,size); - } - return size; -} - -CBuffer::operator const BYTE*() const -{ - return m_pBuf; -} - -void CBuffer::_free() -{ - if (m_attached) - { - m_attached = FALSE; - m_pBuf = NULL; - m_bufSize = 0; - return; - } - if(m_pBuf) - { - free(m_pBuf); - m_pBuf = NULL; - m_bufSize = 0; - } -} - -void CBuffer::memset( byte value/*=0*/ ) -{ - ::memset(m_pBuf,value,m_bufSize); -} - -BOOL CBuffer::WriteToFile( LPCTSTR filePath ) const -{ - FILE* fp=NULL; - _tfopen_s(&fp,filePath,TEXT("wb")); - if (fp) - { - size_t temp; - temp = fwrite(GetBuffer(),GetSize(),1,fp); - ATLASSERT(temp == 1); - fclose(fp); - return TRUE; - } - return FALSE; -} - -VOID CBuffer::Clear() -{ - _free(); -} - -VOID CBuffer::Attach( void* buffer,size_t bufsize ) -{ - ATLASSERT(buffer); - if (buffer && bufsize) - { - _free(); - m_attached = TRUE; - m_pBuf = (BYTE*)buffer; - m_bufSize = (DWORD)bufsize; - } -} - -VOID CBuffer::Detach() -{ - _free(); -} - -////////////////////////////////////////////////////////////////////////// - -CStreamBuffer::CStreamBuffer() -{ - m_writePos = 0; - m_readPos = 0; -} - -CStreamBuffer::~CStreamBuffer() -{ -} - -DWORD CStreamBuffer::Append( const void *pData,DWORD dataSize ) -{ - if (m_writePos >= m_bufSize || pData==NULL || m_pBuf==NULL) - { - return 0; - } - if (m_writePos+dataSize > m_bufSize) - { - dataSize = m_bufSize-m_writePos-1; - } - if (dataSize) - { - ::memcpy(m_pBuf+m_writePos,pData,dataSize); - m_writePos += dataSize; - } - return dataSize; -} - -DWORD CStreamBuffer::Get( void *pOut,DWORD bytesToRead ) -{ - if (m_pBuf==NULL || pOut==NULL || bytesToRead==0) - { - return 0; - } - if (bytesToRead+m_readPos >= m_writePos) - { - bytesToRead = m_writePos-m_readPos; - } - if (bytesToRead) - { - ::memcpy(pOut,GetBuffer() + m_readPos,bytesToRead); - m_readPos += bytesToRead; - } - return bytesToRead; -} - -void CStreamBuffer::ResetWritePos() -{ - m_writePos = 0; -} - -void CStreamBuffer::ResetReadPos() -{ - m_readPos = 0; -} - -////////////////////////////////////////////////////////////////////////// - - - -CAutoStreamBuffer::CAutoStreamBuffer() -{ - m_writePos = 0; - m_readPos = 0; - m_referenceSize = 1024; - m_readTimes = 0; -} - -CAutoStreamBuffer::~CAutoStreamBuffer() -{ - -} - -VOID CAutoStreamBuffer::SetReferenceSize( DWORD size ) -{ - m_referenceSize = size; -} - -VOID CAutoStreamBuffer::Append( const void *pData,DWORD dataSize ) -{ - _CheckBuffer(dataSize); - memcpy(m_pBuf+m_writePos,pData,dataSize); - m_writePos += dataSize; -} - -BYTE* CAutoStreamBuffer::AllocAppend( DWORD dataSize ) -{ - _CheckBuffer(dataSize); - return (BYTE*)m_writePos; -} - -BOOL CAutoStreamBuffer::AccomplishAppend( DWORD dataSize/*=0*/ ) -{ - if (dataSize) - { - ATLASSERT(m_writePos+dataSize < m_bufSize); - m_writePos += dataSize; - return TRUE; - } - else - { - DWORD nPos = m_writePos; - for(; nPos 8) - { - ATLASSERT(m_writePos > m_readPos); - DWORD used = m_writePos-1-m_readPos; - if (m_readPos > 1024) // too far,moveto front - { - memcpy(m_pBuf,m_pBuf+m_readPos,used); - m_writePos = used+1; - m_readPos = 0; - } - if (used < m_bufSize/16) - { - DWORD newSize = m_referenceSize; - if (newSize < used) - { - newSize = used; - } - Alloc(newSize); - } - } -} - -DWORD CAutoStreamBuffer::Get( void *pOut,DWORD bytesToRead ) -{ - if (bytesToRead+m_readPos >= m_writePos) - { - bytesToRead = m_writePos-m_readPos; - } - memcpy(pOut,m_pBuf+m_readPos,bytesToRead); - m_readPos += bytesToRead; - _TryReorganize(); - return bytesToRead; -} - -void CAutoStreamBuffer::ResetWritePos() -{ - m_writePos = 0; -} - -void CAutoStreamBuffer::ResetReadPos() -{ - m_readPos = 0; -} +#include "CBuffer.h" +#include "stdio.h" +#include +#include + +CBuffer::CBuffer( LPCTSTR _debug/*=NULL*/ ) +{ +#ifndef _DEBUG + UNREFERENCED_PARAMETER(_debug); +#endif + m_pBuf=NULL; + m_bufSize=0; + m_attached = FALSE; +#ifdef _DEBUG + m_debug = _debug; +#endif +} + +CBuffer::~CBuffer() +{ + _free(); +} + +BYTE* CBuffer::Alloc( DWORD size ) +{ + void *pTemp = realloc(m_pBuf,size+1); + if (pTemp != NULL) + { + m_pBuf = (BYTE*)pTemp; + m_bufSize = size; + m_pBuf[size]=0; + } + return m_pBuf; +} + +BYTE* CBuffer::GetBuffer() const +{ + return m_pBuf; +} + +DWORD CBuffer::GetSize() const +{ + return m_bufSize; +} + +const BYTE* CBuffer::Copy( const void* src,DWORD len ) +{ + Alloc(len); + if (m_pBuf) + { + ::memcpy(m_pBuf,src,len); + m_bufSize=len; + } + return *this; +} + +const BYTE* CBuffer::Copy( const CBuffer& src ) +{ + return Copy(src,src.GetSize()); +} + +DWORD CBuffer::Write( void* p,DWORD size,DWORD startPos ) +{ + if (startPos >= m_bufSize || p==NULL || m_pBuf==NULL) + { + return 0; + } + if (startPos + size >= m_bufSize) + { + size = m_bufSize-startPos-1; + } + if (size) + { + ::memcpy(m_pBuf+startPos,p,size); + } + return size; +} + +CBuffer::operator const BYTE*() const +{ + return m_pBuf; +} + +void CBuffer::_free() +{ + if (m_attached) + { + m_attached = FALSE; + m_pBuf = NULL; + m_bufSize = 0; + return; + } + if(m_pBuf) + { + free(m_pBuf); + m_pBuf = NULL; + m_bufSize = 0; + } +} + +void CBuffer::memset( byte value/*=0*/ ) +{ + ::memset(m_pBuf,value,m_bufSize); +} + +BOOL CBuffer::WriteToFile( LPCTSTR filePath ) const +{ + FILE* fp=NULL; + _tfopen_s(&fp,filePath,TEXT("wb")); + if (fp) + { + size_t temp; + temp = fwrite(GetBuffer(),GetSize(),1,fp); + ATLASSERT(temp == 1); + fclose(fp); + return TRUE; + } + return FALSE; +} + +VOID CBuffer::Clear() +{ + _free(); +} + +VOID CBuffer::Attach( void* buffer,size_t bufsize ) +{ + ATLASSERT(buffer); + if (buffer && bufsize) + { + _free(); + m_attached = TRUE; + m_pBuf = (BYTE*)buffer; + m_bufSize = (DWORD)bufsize; + } +} + +VOID CBuffer::Detach() +{ + _free(); +} + +////////////////////////////////////////////////////////////////////////// + +CStreamBuffer::CStreamBuffer() +{ + m_writePos = 0; + m_readPos = 0; +} + +CStreamBuffer::~CStreamBuffer() +{ +} + +DWORD CStreamBuffer::Append( const void *pData,DWORD dataSize ) +{ + if (m_writePos >= m_bufSize || pData==NULL || m_pBuf==NULL) + { + return 0; + } + if (m_writePos+dataSize > m_bufSize) + { + dataSize = m_bufSize-m_writePos-1; + } + if (dataSize) + { + ::memcpy(m_pBuf+m_writePos,pData,dataSize); + m_writePos += dataSize; + } + return dataSize; +} + +DWORD CStreamBuffer::Get( void *pOut,DWORD bytesToRead ) +{ + if (m_pBuf==NULL || pOut==NULL || bytesToRead==0) + { + return 0; + } + if (bytesToRead+m_readPos >= m_writePos) + { + bytesToRead = m_writePos-m_readPos; + } + if (bytesToRead) + { + ::memcpy(pOut,GetBuffer() + m_readPos,bytesToRead); + m_readPos += bytesToRead; + } + return bytesToRead; +} + +void CStreamBuffer::ResetWritePos() +{ + m_writePos = 0; +} + +void CStreamBuffer::ResetReadPos() +{ + m_readPos = 0; +} + +////////////////////////////////////////////////////////////////////////// + + + +CAutoStreamBuffer::CAutoStreamBuffer() +{ + m_writePos = 0; + m_readPos = 0; + m_referenceSize = 1024; + m_readTimes = 0; +} + +CAutoStreamBuffer::~CAutoStreamBuffer() +{ + +} + +VOID CAutoStreamBuffer::SetReferenceSize( DWORD size ) +{ + m_referenceSize = size; +} + +VOID CAutoStreamBuffer::Append( const void *pData,DWORD dataSize ) +{ + _CheckBuffer(dataSize); + memcpy(m_pBuf+m_writePos,pData,dataSize); + m_writePos += dataSize; +} + +BYTE* CAutoStreamBuffer::AllocAppend( DWORD dataSize ) +{ + _CheckBuffer(dataSize); + return m_pBuf+m_writePos; +} + +BOOL CAutoStreamBuffer::AccomplishAppend( DWORD dataSize/*=0*/ ) +{ + if (dataSize) + { + ATLASSERT(m_writePos+dataSize < m_bufSize); + m_writePos += dataSize; + return TRUE; + } + else + { + DWORD nPos = m_writePos; + for(; nPos m_bufSize) + { + Alloc(m_writePos + requestSize + 16); + } +} + +void CAutoStreamBuffer::_TryReorganize() +{ + ++m_readTimes; + if (m_readTimes > 8) + { + ATLASSERT(m_writePos > m_readPos); + DWORD used = m_writePos-1-m_readPos; + if (m_readPos > 1024) // too far,moveto front + { + memcpy(m_pBuf,m_pBuf+m_readPos,used); + m_writePos = used+1; + m_readPos = 0; + } + if (used < m_bufSize/16) + { + DWORD newSize = m_referenceSize; + if (newSize < used) + { + newSize = used; + } + Alloc(newSize); + } + } +} + +DWORD CAutoStreamBuffer::Get( void *pOut,DWORD bytesToRead ) +{ + if (bytesToRead+m_readPos >= m_writePos) + { + bytesToRead = m_writePos-m_readPos; + } + if (pOut) + { + memcpy(pOut,m_pBuf+m_readPos,bytesToRead); + } + m_readPos += bytesToRead; + _TryReorganize(); + return bytesToRead; +} + +void CAutoStreamBuffer::ResetWritePos() +{ + m_writePos = 0; +} + +void CAutoStreamBuffer::ResetReadPos() +{ + m_readPos = 0; +} diff --git a/VNOC/util/CBuffer.h b/Client/Client/util/CBuffer.h similarity index 95% rename from VNOC/util/CBuffer.h rename to Client/Client/util/CBuffer.h index 04cb0663..cf9de143 100644 --- a/VNOC/util/CBuffer.h +++ b/Client/Client/util/CBuffer.h @@ -1,105 +1,105 @@ -#pragma once -#include - -// ̰߳ȫάʻӻ⹦ -class CBuffer -{ -public: - CBuffer(LPCTSTR _debug=NULL); // ڼ¼һǣ׷ͷŵʱĴ - ~CBuffer(); -public: - // 䡣ʹԭûͷҲû - BYTE* Alloc(DWORD size); - - // - VOID Clear(); - - // ȡڴָ롣 - BYTE* GetBuffer() const; - - // ȡС - DWORD GetSize() const; - - // - const BYTE* Copy(const void* src,DWORD len); - const BYTE* Copy(const CBuffer& src); - - // йڴռ - VOID Attach(void* buffer,size_t bufsize); - VOID Detach(); - - // дļ - BOOL WriteToFile(LPCTSTR filePath) const; - - // ֵ - void memset(byte value=0); - DWORD Write(void* p,DWORD size,DWORD startPos=0); - - operator const BYTE* () const; -private: - void operator =(const CBuffer &src); - void _free(); -protected: - BYTE* m_pBuf; - DWORD m_bufSize; - BOOL m_attached; -#ifdef _DEBUG - LPCTSTR m_debug; -#endif -}; - -#define ConstReferenceBuffer const CBuffer& // -#define BufferIn CBuffer // ߸䡢ͷ -#define BufferOut CBuffer // ߸ͷš - -// ܵBuffer,̶bufferС -class CStreamBuffer : public CBuffer -{ -public: - CStreamBuffer(); - ~CStreamBuffer(); -public: - // д,ʵдֽ - DWORD Append(const void *pData,DWORD dataSize); - - // ȡ,ʵʶȡֽ - DWORD Get(void *pOut,DWORD bytesToRead); - void ResetWritePos(); - void ResetReadPos(); -private: - void operator =(const CStreamBuffer &src); - volatile DWORD m_writePos; // дλãǸ± - DWORD m_readPos; -}; - -// ܵBuffer,ԶbufferС -class CAutoStreamBuffer : public CBuffer -{ -public: - CAutoStreamBuffer(); - ~CAutoStreamBuffer(); -public: - // 趨һοbufferС - VOID SetReferenceSize(DWORD size); - - // д - VOID Append(const void *pData,DWORD dataSize); - // һbufferд룬δAccomplishAppendǰDzд - BYTE* AllocAppend(DWORD dataSize); - // δָСʱ\0Ϊβ - BOOL AccomplishAppend(DWORD dataSize=0); - - // ȡ - DWORD Get(void *pOut,DWORD bytesToRead); - void ResetWritePos(); - void ResetReadPos(); -private: - void _CheckBuffer(DWORD requestSize); - void _TryReorganize(); -private: - void operator =(const CAutoStreamBuffer &src); - DWORD m_referenceSize; - volatile DWORD m_writePos; // дλãǸ± - DWORD m_readPos; - DWORD m_readTimes; -}; +#pragma once +#include + +// ̰߳ȫάʻӻ⹦ +class CBuffer +{ +public: + CBuffer(LPCTSTR _debug=NULL); // ڼ¼һǣ׷ͷŵʱĴ + ~CBuffer(); +public: + // 䡣ʹԭûͷҲû + BYTE* Alloc(DWORD size); + + // + VOID Clear(); + + // ȡڴָ롣 + BYTE* GetBuffer() const; + + // ȡС + DWORD GetSize() const; + + // + const BYTE* Copy(const void* src,DWORD len); + const BYTE* Copy(const CBuffer& src); + + // йڴռ + VOID Attach(void* buffer,size_t bufsize); + VOID Detach(); + + // дļ + BOOL WriteToFile(LPCTSTR filePath) const; + + // ֵ + void memset(byte value=0); + DWORD Write(void* p,DWORD size,DWORD startPos=0); + + operator const BYTE* () const; +private: + void operator =(const CBuffer &src); + void _free(); +protected: + BYTE* m_pBuf; + DWORD m_bufSize; + BOOL m_attached; +#ifdef _DEBUG + LPCTSTR m_debug; +#endif +}; + +#define ConstReferenceBuffer const CBuffer& // +#define BufferIn CBuffer // ߸䡢ͷ +#define BufferOut CBuffer // ߸ͷš + +// ܵBuffer,̶bufferС +class CStreamBuffer : public CBuffer +{ +public: + CStreamBuffer(); + ~CStreamBuffer(); +public: + // д,ʵдֽ + DWORD Append(const void *pData,DWORD dataSize); + + // ȡ,ʵʶȡֽ + DWORD Get(void *pOut,DWORD bytesToRead); + void ResetWritePos(); + void ResetReadPos(); +private: + void operator =(const CStreamBuffer &src); + volatile DWORD m_writePos; // дλãǸ± + DWORD m_readPos; +}; + +// ܵBuffer,ԶbufferС +class CAutoStreamBuffer : public CBuffer +{ +public: + CAutoStreamBuffer(); + ~CAutoStreamBuffer(); +public: + // 趨һοbufferС + VOID SetReferenceSize(DWORD size); + + // д + VOID Append(const void *pData,DWORD dataSize); + // һbufferд룬δAccomplishAppendǰDzд + BYTE* AllocAppend(DWORD dataSize); + // δָСʱ\0Ϊβ + BOOL AccomplishAppend(DWORD dataSize=0); + + // ȡ + DWORD Get(void *pOut,DWORD bytesToRead); + void ResetWritePos(); + void ResetReadPos(); +private: + void _CheckBuffer(DWORD requestSize); + void _TryReorganize(); +private: + void operator =(const CAutoStreamBuffer &src); + DWORD m_referenceSize; + volatile DWORD m_writePos; // дλãǸ± + DWORD m_readPos; + DWORD m_readTimes; +}; diff --git a/Client/Client/util/DbgHelper.hpp b/Client/Client/util/DbgHelper.hpp new file mode 100644 index 00000000..5819bb31 --- /dev/null +++ b/Client/Client/util/DbgHelper.hpp @@ -0,0 +1,36 @@ +#pragma once + +#pragma pack(push,8) +struct ThreadNameInfo +{ + DWORD dwType; + LPCSTR szName; + DWORD dwThreadID; + DWORD dwFlags; +}; +#pragma pack(pop) + +/** õǰ߳ +* ͨһ쳣õ洢ʾ߳ +* \param dwThreadID ߳ID, -1ʾǰ߳ +* \param pszThreadName ߳ +*/ +inline void SetThreadNameToDebugInfo(DWORD dwThreadID, LPCSTR pszThreadName) +{ + if (!::IsDebuggerPresent()) return; + + if (dwThreadID == -1) + { + dwThreadID = ::GetCurrentThreadId(); + } + + struct ThreadNameInfo info = {0x1000, pszThreadName, dwThreadID, 0}; + + __try + { + RaiseException(0x406D1388, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info); + } + __except(EXCEPTION_CONTINUE_EXECUTION) + { + } +} \ No newline at end of file diff --git a/Client/Client/util/IRefCountImpl.h b/Client/Client/util/IRefCountImpl.h new file mode 100644 index 00000000..27862c34 --- /dev/null +++ b/Client/Client/util/IRefCountImpl.h @@ -0,0 +1,28 @@ +#pragma once +#include "unknwn.h" + +class IRefCountImpl : public IUnknown +{ +public: + IRefCountImpl() : m_refCount(0){} + virtual ~IRefCountImpl(){} + virtual ULONG STDMETHODCALLTYPE AddRef() + { + return InterlockedIncrement(&m_refCount); + } + virtual ULONG STDMETHODCALLTYPE Release() + { + unsigned long ul = 0; + if ((ul = InterlockedDecrement(&m_refCount)) == 0) + { + delete this; + } + return ul; + } + virtual HRESULT STDMETHODCALLTYPE QueryInterface(const IID &,void **) + { + return E_NOTIMPL; + } +public: + LONG m_refCount; +}; \ No newline at end of file diff --git a/VNOC/util/MD5.cpp b/Client/Client/util/MD5.cpp similarity index 97% rename from VNOC/util/MD5.cpp rename to Client/Client/util/MD5.cpp index ca96b9dc..d7b75440 100644 --- a/VNOC/util/MD5.cpp +++ b/Client/Client/util/MD5.cpp @@ -1,576 +1,575 @@ -// MD5Checksum.cpp: implementation of the MD5Checksum class. -// -////////////////////////////////////////////////////////////////////// -#include "stdafx.h" - -/**************************************************************************************** -This software is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. -Incorporation of this statement is a condition of use; please see the RSA -Data Security Inc copyright notice below:- - -Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All -rights reserved. - -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - -These notices must be retained in any copies of any part of this -documentation and/or software. - -Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - -These notices must be retained in any copies of any part of this -documentation and/or software. -*****************************************************************************************/ - -/**************************************************************************************** -This implementation of the RSA MD5 Algorithm was written by Langfine Ltd -(www.langfine.com). - -Langfine Ltd makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - -In addition to the above, Langfine make no warrant or assurances regarding the -accuracy of this implementation of the MD5 checksum algorithm nor any assurances regarding -its suitability for any purposes. - -This implementation may be used freely provided that Langfine is credited -in a copyright or similar notices (eg, RSA MD5 Algorithm implemented by Langfine -Ltd.) and provided that the RSA Data Security notices are complied with. -*/ - -#include "windows.h" -#include "atlstr.h" -#include "MD5.h" -#include "MD5ChecksumDefines.h" - - -/***************************************************************************************** -FUNCTION: CMD5Checksum::GetMD5 -DETAILS: static, public -DESCRIPTION: Gets the MD5 checksum for a specified file -RETURNS: CString : the hexadecimal MD5 checksum for the specified file -ARGUMENTS: CString& strFilePath : the full pathname of the specified file -NOTES: Provides an interface to the CMD5Checksum class. 'strFilePath' name should - hold the full pathname of the file, eg C:\My Documents\Arcticle.txt. - NB. If any problems occur with opening or reading this file, a CFileException - will be thrown; callers of this function should be ready to catch this - exception. -*****************************************************************************************/ -/* -CString CMD5Checksum::GetMD5(const CString& strFilePath) -{ - //open the file as a binary file in readonly mode, denying write access - CFile File(strFilePath, CFile::modeRead | CFile::shareDenyWrite | CFile::typeBinary); - - //the file has been successfully opened, so now get and return its checksum - return GetMD5(File); -} - -*/ -/***************************************************************************************** -FUNCTION: CMD5Checksum::GetMD5 -DETAILS: static, public -DESCRIPTION: Gets the MD5 checksum for a specified file -RETURNS: CString : the hexadecimal MD5 checksum for the specified file -ARGUMENTS: CFile& File : the specified file -NOTES: Provides an interface to the CMD5Checksum class. 'File' should be open in - binary readonly mode before calling this function. - NB. Callers of this function should be ready to catch any CFileException - thrown by the CFile functions -*****************************************************************************************/ -/* -CString CMD5Checksum::GetMD5(CFile& File) -{ - try - { - CMD5Checksum MD5Checksum; //checksum object - int nLength = 0; //number of bytes read from the file - const int nBufferSize = 1024; //checksum the file in blocks of 1024 bytes - BYTE Buffer[nBufferSize]; //buffer for data read from the file - - //checksum the file in blocks of 1024 bytes - while ((nLength = File.Read( Buffer, nBufferSize )) > 0 ) - { - MD5Checksum.Update( Buffer, nLength ); - } - - //finalise the checksum and return it - return MD5Checksum.Final(); - } - - //report any file exceptions in debug mode only - catch (CFileException* e ) - { - TRACE0("CMD5Checksum::GetMD5: CFileException caught"); - throw e; - } -} -*/ - -/***************************************************************************************** -FUNCTION: CMD5Checksum::GetMD5 -DETAILS: static, public -DESCRIPTION: Gets the MD5 checksum for data in a BYTE array -RETURNS: CString : the hexadecimal MD5 checksum for the specified data -ARGUMENTS: BYTE* pBuf : pointer to the BYTE array - UINT nLength : number of BYTEs of data to be checksumed -NOTES: Provides an interface to the CMD5Checksum class. Any data that can - be cast to a BYTE array of known length can be checksummed by this - function. Typically, CString and char arrays will be checksumed, - although this function can be used to check the integrity of any BYTE array. - A buffer of zero length can be checksummed; all buffers of zero length - will return the same checksum. -*****************************************************************************************/ -CString CMD5Checksum::GetMD5(BYTE* pBuf, UINT nLength) -{ - //calculate and return the checksum - CMD5Checksum MD5Checksum; - MD5Checksum.Update(pBuf, nLength); - return MD5Checksum.Final(); -} - -BOOL CMD5Checksum::GetMD5(LPCTSTR path, CString& md5) -{ - if(NULL == path || !PathFileExists(path)) - { - ATLASSERT(FALSE); - return FALSE; - } - - CMD5Checksum MD5Checksum; //checksum object - int nLength = 0; //number of bytes read from the file - const int nBufferSize = 1024; //checksum the file in blocks of 1024 bytes - BYTE Buffer[nBufferSize] = {0}; //buffer for data read from the file - - HANDLE hFile = CreateFile(path, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (hFile == INVALID_HANDLE_VALUE) - { - return FALSE; - } - - //checksum the file in blocks of 1024 bytes - DWORD dwBytesRead = 0; - while(ReadFile(hFile, Buffer, nBufferSize, &dwBytesRead, NULL) && dwBytesRead > 0) - { - MD5Checksum.Update(Buffer, dwBytesRead ); - } - CloseHandle(hFile); - - //finalise the checksum and return it - md5 = MD5Checksum.Final(); - return TRUE; -} - - - - -/***************************************************************************************** -FUNCTION: CMD5Checksum::RotateLeft -DETAILS: private -DESCRIPTION: Rotates the bits in a 32 bit DWORD left by a specified amount -RETURNS: The rotated DWORD -ARGUMENTS: DWORD x : the value to be rotated - int n : the number of bits to rotate by -*****************************************************************************************/ -DWORD CMD5Checksum::RotateLeft(DWORD x, int n) -{ - //check that DWORD is 4 bytes long - true in Visual C++ 6 and 32 bit Windows - // sizeof(x); - - //rotate and return x - return (x << n) | (x >> (32-n)); -} - - -/***************************************************************************************** -FUNCTION: CMD5Checksum::FF -DETAILS: protected -DESCRIPTION: Implementation of basic MD5 transformation algorithm -RETURNS: none -ARGUMENTS: DWORD &A, B, C, D : Current (partial) checksum - DWORD X : Input data - DWORD S : MD5_SXX Transformation constant - DWORD T : MD5_TXX Transformation constant -NOTES: None -*****************************************************************************************/ -void CMD5Checksum::FF( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T) -{ - DWORD F = (B & C) | (~B & D); - A += F + X + T; - A = RotateLeft(A, S); - A += B; -} - - -/***************************************************************************************** -FUNCTION: CMD5Checksum::GG -DETAILS: protected -DESCRIPTION: Implementation of basic MD5 transformation algorithm -RETURNS: none -ARGUMENTS: DWORD &A, B, C, D : Current (partial) checksum - DWORD X : Input data - DWORD S : MD5_SXX Transformation constant - DWORD T : MD5_TXX Transformation constant -NOTES: None -*****************************************************************************************/ -void CMD5Checksum::GG( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T) -{ - DWORD G = (B & D) | (C & ~D); - A += G + X + T; - A = RotateLeft(A, S); - A += B; -} - - -/***************************************************************************************** -FUNCTION: CMD5Checksum::HH -DETAILS: protected -DESCRIPTION: Implementation of basic MD5 transformation algorithm -RETURNS: none -ARGUMENTS: DWORD &A, B, C, D : Current (partial) checksum - DWORD X : Input data - DWORD S : MD5_SXX Transformation constant - DWORD T : MD5_TXX Transformation constant -NOTES: None -*****************************************************************************************/ -void CMD5Checksum::HH( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T) -{ - DWORD H = (B ^ C ^ D); - A += H + X + T; - A = RotateLeft(A, S); - A += B; -} - - -/***************************************************************************************** -FUNCTION: CMD5Checksum::II -DETAILS: protected -DESCRIPTION: Implementation of basic MD5 transformation algorithm -RETURNS: none -ARGUMENTS: DWORD &A, B, C, D : Current (partial) checksum - DWORD X : Input data - DWORD S : MD5_SXX Transformation constant - DWORD T : MD5_TXX Transformation constant -NOTES: None -*****************************************************************************************/ -void CMD5Checksum::II( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T) -{ - DWORD I = (C ^ (B | ~D)); - A += I + X + T; - A = RotateLeft(A, S); - A += B; -} - - -/***************************************************************************************** -FUNCTION: CMD5Checksum::ByteToDWord -DETAILS: private -DESCRIPTION: Transfers the data in an 8 bit array to a 32 bit array -RETURNS: void -ARGUMENTS: DWORD* Output : the 32 bit (unsigned long) destination array - BYTE* Input : the 8 bit (unsigned char) source array - UINT nLength : the number of 8 bit data items in the source array -NOTES: Four BYTES from the input array are transferred to each DWORD entry - of the output array. The first BYTE is transferred to the bits (0-7) - of the output DWORD, the second BYTE to bits 8-15 etc. - The algorithm assumes that the input array is a multiple of 4 bytes long - so that there is a perfect fit into the array of 32 bit words. -*****************************************************************************************/ -void CMD5Checksum::ByteToDWord(DWORD* Output, BYTE* Input, UINT nLength) -{ - //entry invariants -// ASSERT( nLength % 4 == 0 ); -// ASSERT( AfxIsValidAddress(Output, nLength/4, TRUE) ); -// ASSERT( AfxIsValidAddress(Input, nLength, FALSE) ); - - //initialisations - UINT i=0; //index to Output array - UINT j=0; //index to Input array - - //transfer the data by shifting and copying - for ( ; j < nLength; i++, j += 4) - { - Output[i] = (ULONG)Input[j] | - (ULONG)Input[j+1] << 8 | - (ULONG)Input[j+2] << 16 | - (ULONG)Input[j+3] << 24; - } -} - -/***************************************************************************************** -FUNCTION: CMD5Checksum::Transform -DETAILS: protected -DESCRIPTION: MD5 basic transformation algorithm; transforms 'm_lMD5' -RETURNS: void -ARGUMENTS: BYTE Block[64] -NOTES: An MD5 checksum is calculated by four rounds of 'Transformation'. - The MD5 checksum currently held in m_lMD5 is merged by the - transformation process with data passed in 'Block'. -*****************************************************************************************/ -void CMD5Checksum::Transform(BYTE Block[64]) -{ - //initialise local data with current checksum - ULONG a = m_lMD5[0]; - ULONG b = m_lMD5[1]; - ULONG c = m_lMD5[2]; - ULONG d = m_lMD5[3]; - - //copy BYTES from input 'Block' to an array of ULONGS 'X' - ULONG X[16]; - ByteToDWord( X, Block, 64 ); - - //Perform Round 1 of the transformation - FF (a, b, c, d, X[ 0], MD5_S11, MD5_T01); - FF (d, a, b, c, X[ 1], MD5_S12, MD5_T02); - FF (c, d, a, b, X[ 2], MD5_S13, MD5_T03); - FF (b, c, d, a, X[ 3], MD5_S14, MD5_T04); - FF (a, b, c, d, X[ 4], MD5_S11, MD5_T05); - FF (d, a, b, c, X[ 5], MD5_S12, MD5_T06); - FF (c, d, a, b, X[ 6], MD5_S13, MD5_T07); - FF (b, c, d, a, X[ 7], MD5_S14, MD5_T08); - FF (a, b, c, d, X[ 8], MD5_S11, MD5_T09); - FF (d, a, b, c, X[ 9], MD5_S12, MD5_T10); - FF (c, d, a, b, X[10], MD5_S13, MD5_T11); - FF (b, c, d, a, X[11], MD5_S14, MD5_T12); - FF (a, b, c, d, X[12], MD5_S11, MD5_T13); - FF (d, a, b, c, X[13], MD5_S12, MD5_T14); - FF (c, d, a, b, X[14], MD5_S13, MD5_T15); - FF (b, c, d, a, X[15], MD5_S14, MD5_T16); - - //Perform Round 2 of the transformation - GG (a, b, c, d, X[ 1], MD5_S21, MD5_T17); - GG (d, a, b, c, X[ 6], MD5_S22, MD5_T18); - GG (c, d, a, b, X[11], MD5_S23, MD5_T19); - GG (b, c, d, a, X[ 0], MD5_S24, MD5_T20); - GG (a, b, c, d, X[ 5], MD5_S21, MD5_T21); - GG (d, a, b, c, X[10], MD5_S22, MD5_T22); - GG (c, d, a, b, X[15], MD5_S23, MD5_T23); - GG (b, c, d, a, X[ 4], MD5_S24, MD5_T24); - GG (a, b, c, d, X[ 9], MD5_S21, MD5_T25); - GG (d, a, b, c, X[14], MD5_S22, MD5_T26); - GG (c, d, a, b, X[ 3], MD5_S23, MD5_T27); - GG (b, c, d, a, X[ 8], MD5_S24, MD5_T28); - GG (a, b, c, d, X[13], MD5_S21, MD5_T29); - GG (d, a, b, c, X[ 2], MD5_S22, MD5_T30); - GG (c, d, a, b, X[ 7], MD5_S23, MD5_T31); - GG (b, c, d, a, X[12], MD5_S24, MD5_T32); - - //Perform Round 3 of the transformation - HH (a, b, c, d, X[ 5], MD5_S31, MD5_T33); - HH (d, a, b, c, X[ 8], MD5_S32, MD5_T34); - HH (c, d, a, b, X[11], MD5_S33, MD5_T35); - HH (b, c, d, a, X[14], MD5_S34, MD5_T36); - HH (a, b, c, d, X[ 1], MD5_S31, MD5_T37); - HH (d, a, b, c, X[ 4], MD5_S32, MD5_T38); - HH (c, d, a, b, X[ 7], MD5_S33, MD5_T39); - HH (b, c, d, a, X[10], MD5_S34, MD5_T40); - HH (a, b, c, d, X[13], MD5_S31, MD5_T41); - HH (d, a, b, c, X[ 0], MD5_S32, MD5_T42); - HH (c, d, a, b, X[ 3], MD5_S33, MD5_T43); - HH (b, c, d, a, X[ 6], MD5_S34, MD5_T44); - HH (a, b, c, d, X[ 9], MD5_S31, MD5_T45); - HH (d, a, b, c, X[12], MD5_S32, MD5_T46); - HH (c, d, a, b, X[15], MD5_S33, MD5_T47); - HH (b, c, d, a, X[ 2], MD5_S34, MD5_T48); - - //Perform Round 4 of the transformation - II (a, b, c, d, X[ 0], MD5_S41, MD5_T49); - II (d, a, b, c, X[ 7], MD5_S42, MD5_T50); - II (c, d, a, b, X[14], MD5_S43, MD5_T51); - II (b, c, d, a, X[ 5], MD5_S44, MD5_T52); - II (a, b, c, d, X[12], MD5_S41, MD5_T53); - II (d, a, b, c, X[ 3], MD5_S42, MD5_T54); - II (c, d, a, b, X[10], MD5_S43, MD5_T55); - II (b, c, d, a, X[ 1], MD5_S44, MD5_T56); - II (a, b, c, d, X[ 8], MD5_S41, MD5_T57); - II (d, a, b, c, X[15], MD5_S42, MD5_T58); - II (c, d, a, b, X[ 6], MD5_S43, MD5_T59); - II (b, c, d, a, X[13], MD5_S44, MD5_T60); - II (a, b, c, d, X[ 4], MD5_S41, MD5_T61); - II (d, a, b, c, X[11], MD5_S42, MD5_T62); - II (c, d, a, b, X[ 2], MD5_S43, MD5_T63); - II (b, c, d, a, X[ 9], MD5_S44, MD5_T64); - - //add the transformed values to the current checksum - m_lMD5[0] += a; - m_lMD5[1] += b; - m_lMD5[2] += c; - m_lMD5[3] += d; -} - - -/***************************************************************************************** -CONSTRUCTOR: CMD5Checksum -DESCRIPTION: Initialises member data -ARGUMENTS: None -NOTES: None -*****************************************************************************************/ -CMD5Checksum::CMD5Checksum() -{ - // zero members - memset( m_lpszBuffer, 0, 64 ); - m_nCount[0] = m_nCount[1] = 0; - - // Load magic state initialization constants - m_lMD5[0] = MD5_INIT_STATE_0; - m_lMD5[1] = MD5_INIT_STATE_1; - m_lMD5[2] = MD5_INIT_STATE_2; - m_lMD5[3] = MD5_INIT_STATE_3; -} - -/***************************************************************************************** -FUNCTION: CMD5Checksum::DWordToByte -DETAILS: private -DESCRIPTION: Transfers the data in an 32 bit array to a 8 bit array -RETURNS: void -ARGUMENTS: BYTE* Output : the 8 bit destination array - DWORD* Input : the 32 bit source array - UINT nLength : the number of 8 bit data items in the source array -NOTES: One DWORD from the input array is transferred into four BYTES - in the output array. The first (0-7) bits of the first DWORD are - transferred to the first output BYTE, bits bits 8-15 are transferred from - the second BYTE etc. - - The algorithm assumes that the output array is a multiple of 4 bytes long - so that there is a perfect fit of 8 bit BYTES into the 32 bit DWORDs. -*****************************************************************************************/ -void CMD5Checksum::DWordToByte(BYTE* Output, DWORD* Input, UINT nLength ) -{ - //entry invariants -// ASSERT( nLength % 4 == 0 ); -// ASSERT( AfxIsValidAddress(Output, nLength, TRUE) ); -// ASSERT( AfxIsValidAddress(Input, nLength/4, FALSE) ); - - //transfer the data by shifting and copying - UINT i = 0; - UINT j = 0; - for ( ; j < nLength; i++, j += 4) - { - Output[j] = (UCHAR)(Input[i] & 0xff); - Output[j+1] = (UCHAR)((Input[i] >> 8) & 0xff); - Output[j+2] = (UCHAR)((Input[i] >> 16) & 0xff); - Output[j+3] = (UCHAR)((Input[i] >> 24) & 0xff); - } -} - - -/***************************************************************************************** -FUNCTION: CMD5Checksum::Final -DETAILS: protected -DESCRIPTION: Implementation of main MD5 checksum algorithm; ends the checksum calculation. -RETURNS: CString : the final hexadecimal MD5 checksum result -ARGUMENTS: None -NOTES: Performs the final MD5 checksum calculation ('Update' does most of the work, - this function just finishes the calculation.) -*****************************************************************************************/ -CString CMD5Checksum::Final() -{ - //Save number of bits - BYTE Bits[8]; - DWordToByte( Bits, m_nCount, 8 ); - - //Pad out to 56 mod 64. - UINT nIndex = (UINT)((m_nCount[0] >> 3) & 0x3f); - UINT nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex); - Update( PADDING, nPadLen ); - - //Append length (before padding) - Update( Bits, 8 ); - - //Store final state in 'lpszMD5' - const int nMD5Size = 16; - unsigned char lpszMD5[ nMD5Size ]; - DWordToByte( lpszMD5, m_lMD5, nMD5Size ); - - //Convert the hexadecimal checksum to a CString - CString strMD5; - for ( int i=0; i < nMD5Size; i++) - { - CString Str; - if (lpszMD5[i] == 0) { - Str = CString("00"); - } - else if (lpszMD5[i] <= 15) { - Str.Format(TEXT("0%x"),lpszMD5[i]); - } - else { - Str.Format(TEXT("%x"),lpszMD5[i]); - } - - ATLASSERT(Str.GetLength() == 2); - strMD5 += Str; - } - ATLASSERT( strMD5.GetLength() == 32 ); - return strMD5; -} - - -/***************************************************************************************** -FUNCTION: CMD5Checksum::Update -DETAILS: protected -DESCRIPTION: Implementation of main MD5 checksum algorithm -RETURNS: void -ARGUMENTS: BYTE* Input : input block - UINT nInputLen : length of input block -NOTES: Computes the partial MD5 checksum for 'nInputLen' bytes of data in 'Input' -*****************************************************************************************/ -void CMD5Checksum::Update( BYTE* Input, ULONG nInputLen ) -{ - //Compute number of bytes mod 64 - UINT nIndex = (UINT)((m_nCount[0] >> 3) & 0x3F); - - //Update number of bits - if ( ( m_nCount[0] += nInputLen << 3 ) < ( nInputLen << 3) ) - { - m_nCount[1]++; - } - m_nCount[1] += (nInputLen >> 29); - - //Transform as many times as possible. - UINT i=0; - UINT nPartLen = 64 - nIndex; - if (nInputLen >= nPartLen) - { - memcpy( &m_lpszBuffer[nIndex], Input, nPartLen ); - Transform( m_lpszBuffer ); - for (i = nPartLen; i + 63 < nInputLen; i += 64) - { - Transform( &Input[i] ); - } - nIndex = 0; - } - else - { - i = 0; - } - - // Buffer remaining input - memcpy( &m_lpszBuffer[nIndex], &Input[i], nInputLen-i); -} - - +// MD5Checksum.cpp: implementation of the MD5Checksum class. +// +////////////////////////////////////////////////////////////////////// + +/**************************************************************************************** +This software is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. +Incorporation of this statement is a condition of use; please see the RSA +Data Security Inc copyright notice below:- + +Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All +rights reserved. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + +Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. +*****************************************************************************************/ + +/**************************************************************************************** +This implementation of the RSA MD5 Algorithm was written by Langfine Ltd +(www.langfine.com). + +Langfine Ltd makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +In addition to the above, Langfine make no warrant or assurances regarding the +accuracy of this implementation of the MD5 checksum algorithm nor any assurances regarding +its suitability for any purposes. + +This implementation may be used freely provided that Langfine is credited +in a copyright or similar notices (eg, RSA MD5 Algorithm implemented by Langfine +Ltd.) and provided that the RSA Data Security notices are complied with. +*/ + +#include "windows.h" +#include "atlstr.h" +#include "MD5.h" +#include "MD5ChecksumDefines.h" + + +/***************************************************************************************** +FUNCTION: CMD5Checksum::GetMD5 +DETAILS: static, public +DESCRIPTION: Gets the MD5 checksum for a specified file +RETURNS: CString : the hexadecimal MD5 checksum for the specified file +ARGUMENTS: CString& strFilePath : the full pathname of the specified file +NOTES: Provides an interface to the CMD5Checksum class. 'strFilePath' name should + hold the full pathname of the file, eg C:\My Documents\Arcticle.txt. + NB. If any problems occur with opening or reading this file, a CFileException + will be thrown; callers of this function should be ready to catch this + exception. +*****************************************************************************************/ +/* +CString CMD5Checksum::GetMD5(const CString& strFilePath) +{ + //open the file as a binary file in readonly mode, denying write access + CFile File(strFilePath, CFile::modeRead | CFile::shareDenyWrite | CFile::typeBinary); + + //the file has been successfully opened, so now get and return its checksum + return GetMD5(File); +} + +*/ +/***************************************************************************************** +FUNCTION: CMD5Checksum::GetMD5 +DETAILS: static, public +DESCRIPTION: Gets the MD5 checksum for a specified file +RETURNS: CString : the hexadecimal MD5 checksum for the specified file +ARGUMENTS: CFile& File : the specified file +NOTES: Provides an interface to the CMD5Checksum class. 'File' should be open in + binary readonly mode before calling this function. + NB. Callers of this function should be ready to catch any CFileException + thrown by the CFile functions +*****************************************************************************************/ +/* +CString CMD5Checksum::GetMD5(CFile& File) +{ + try + { + CMD5Checksum MD5Checksum; //checksum object + int nLength = 0; //number of bytes read from the file + const int nBufferSize = 1024; //checksum the file in blocks of 1024 bytes + BYTE Buffer[nBufferSize]; //buffer for data read from the file + + //checksum the file in blocks of 1024 bytes + while ((nLength = File.Read( Buffer, nBufferSize )) > 0 ) + { + MD5Checksum.Update( Buffer, nLength ); + } + + //finalise the checksum and return it + return MD5Checksum.Final(); + } + + //report any file exceptions in debug mode only + catch (CFileException* e ) + { + TRACE0("CMD5Checksum::GetMD5: CFileException caught"); + throw e; + } +} +*/ + +/***************************************************************************************** +FUNCTION: CMD5Checksum::GetMD5 +DETAILS: static, public +DESCRIPTION: Gets the MD5 checksum for data in a BYTE array +RETURNS: CString : the hexadecimal MD5 checksum for the specified data +ARGUMENTS: BYTE* pBuf : pointer to the BYTE array + UINT nLength : number of BYTEs of data to be checksumed +NOTES: Provides an interface to the CMD5Checksum class. Any data that can + be cast to a BYTE array of known length can be checksummed by this + function. Typically, CString and char arrays will be checksumed, + although this function can be used to check the integrity of any BYTE array. + A buffer of zero length can be checksummed; all buffers of zero length + will return the same checksum. +*****************************************************************************************/ +CString CMD5Checksum::GetMD5(BYTE* pBuf, UINT nLength) +{ + //calculate and return the checksum + CMD5Checksum MD5Checksum; + MD5Checksum.Update(pBuf, nLength); + return MD5Checksum.Final(); +} + +BOOL CMD5Checksum::GetMD5(LPCTSTR path, CString& md5) +{ + if(NULL == path || !PathFileExists(path)) + { + ATLASSERT(FALSE); + return FALSE; + } + + CMD5Checksum MD5Checksum; //checksum object + int nLength = 0; //number of bytes read from the file + const int nBufferSize = 1024; //checksum the file in blocks of 1024 bytes + BYTE Buffer[nBufferSize] = {0}; //buffer for data read from the file + + HANDLE hFile = CreateFile(path, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + return FALSE; + } + + //checksum the file in blocks of 1024 bytes + DWORD dwBytesRead = 0; + while(ReadFile(hFile, Buffer, nBufferSize, &dwBytesRead, NULL) && dwBytesRead > 0) + { + MD5Checksum.Update(Buffer, dwBytesRead ); + } + CloseHandle(hFile); + + //finalise the checksum and return it + md5 = MD5Checksum.Final(); + return TRUE; +} + + + + +/***************************************************************************************** +FUNCTION: CMD5Checksum::RotateLeft +DETAILS: private +DESCRIPTION: Rotates the bits in a 32 bit DWORD left by a specified amount +RETURNS: The rotated DWORD +ARGUMENTS: DWORD x : the value to be rotated + int n : the number of bits to rotate by +*****************************************************************************************/ +DWORD CMD5Checksum::RotateLeft(DWORD x, int n) +{ + //check that DWORD is 4 bytes long - true in Visual C++ 6 and 32 bit Windows + // sizeof(x); + + //rotate and return x + return (x << n) | (x >> (32-n)); +} + + +/***************************************************************************************** +FUNCTION: CMD5Checksum::FF +DETAILS: protected +DESCRIPTION: Implementation of basic MD5 transformation algorithm +RETURNS: none +ARGUMENTS: DWORD &A, B, C, D : Current (partial) checksum + DWORD X : Input data + DWORD S : MD5_SXX Transformation constant + DWORD T : MD5_TXX Transformation constant +NOTES: None +*****************************************************************************************/ +void CMD5Checksum::FF( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T) +{ + DWORD F = (B & C) | (~B & D); + A += F + X + T; + A = RotateLeft(A, S); + A += B; +} + + +/***************************************************************************************** +FUNCTION: CMD5Checksum::GG +DETAILS: protected +DESCRIPTION: Implementation of basic MD5 transformation algorithm +RETURNS: none +ARGUMENTS: DWORD &A, B, C, D : Current (partial) checksum + DWORD X : Input data + DWORD S : MD5_SXX Transformation constant + DWORD T : MD5_TXX Transformation constant +NOTES: None +*****************************************************************************************/ +void CMD5Checksum::GG( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T) +{ + DWORD G = (B & D) | (C & ~D); + A += G + X + T; + A = RotateLeft(A, S); + A += B; +} + + +/***************************************************************************************** +FUNCTION: CMD5Checksum::HH +DETAILS: protected +DESCRIPTION: Implementation of basic MD5 transformation algorithm +RETURNS: none +ARGUMENTS: DWORD &A, B, C, D : Current (partial) checksum + DWORD X : Input data + DWORD S : MD5_SXX Transformation constant + DWORD T : MD5_TXX Transformation constant +NOTES: None +*****************************************************************************************/ +void CMD5Checksum::HH( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T) +{ + DWORD H = (B ^ C ^ D); + A += H + X + T; + A = RotateLeft(A, S); + A += B; +} + + +/***************************************************************************************** +FUNCTION: CMD5Checksum::II +DETAILS: protected +DESCRIPTION: Implementation of basic MD5 transformation algorithm +RETURNS: none +ARGUMENTS: DWORD &A, B, C, D : Current (partial) checksum + DWORD X : Input data + DWORD S : MD5_SXX Transformation constant + DWORD T : MD5_TXX Transformation constant +NOTES: None +*****************************************************************************************/ +void CMD5Checksum::II( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T) +{ + DWORD I = (C ^ (B | ~D)); + A += I + X + T; + A = RotateLeft(A, S); + A += B; +} + + +/***************************************************************************************** +FUNCTION: CMD5Checksum::ByteToDWord +DETAILS: private +DESCRIPTION: Transfers the data in an 8 bit array to a 32 bit array +RETURNS: void +ARGUMENTS: DWORD* Output : the 32 bit (unsigned long) destination array + BYTE* Input : the 8 bit (unsigned char) source array + UINT nLength : the number of 8 bit data items in the source array +NOTES: Four BYTES from the input array are transferred to each DWORD entry + of the output array. The first BYTE is transferred to the bits (0-7) + of the output DWORD, the second BYTE to bits 8-15 etc. + The algorithm assumes that the input array is a multiple of 4 bytes long + so that there is a perfect fit into the array of 32 bit words. +*****************************************************************************************/ +void CMD5Checksum::ByteToDWord(DWORD* Output, BYTE* Input, UINT nLength) +{ + //entry invariants +// ASSERT( nLength % 4 == 0 ); +// ASSERT( AfxIsValidAddress(Output, nLength/4, TRUE) ); +// ASSERT( AfxIsValidAddress(Input, nLength, FALSE) ); + + //initialisations + UINT i=0; //index to Output array + UINT j=0; //index to Input array + + //transfer the data by shifting and copying + for ( ; j < nLength; i++, j += 4) + { + Output[i] = (ULONG)Input[j] | + (ULONG)Input[j+1] << 8 | + (ULONG)Input[j+2] << 16 | + (ULONG)Input[j+3] << 24; + } +} + +/***************************************************************************************** +FUNCTION: CMD5Checksum::Transform +DETAILS: protected +DESCRIPTION: MD5 basic transformation algorithm; transforms 'm_lMD5' +RETURNS: void +ARGUMENTS: BYTE Block[64] +NOTES: An MD5 checksum is calculated by four rounds of 'Transformation'. + The MD5 checksum currently held in m_lMD5 is merged by the + transformation process with data passed in 'Block'. +*****************************************************************************************/ +void CMD5Checksum::Transform(BYTE Block[64]) +{ + //initialise local data with current checksum + ULONG a = m_lMD5[0]; + ULONG b = m_lMD5[1]; + ULONG c = m_lMD5[2]; + ULONG d = m_lMD5[3]; + + //copy BYTES from input 'Block' to an array of ULONGS 'X' + ULONG X[16]; + ByteToDWord( X, Block, 64 ); + + //Perform Round 1 of the transformation + FF (a, b, c, d, X[ 0], MD5_S11, MD5_T01); + FF (d, a, b, c, X[ 1], MD5_S12, MD5_T02); + FF (c, d, a, b, X[ 2], MD5_S13, MD5_T03); + FF (b, c, d, a, X[ 3], MD5_S14, MD5_T04); + FF (a, b, c, d, X[ 4], MD5_S11, MD5_T05); + FF (d, a, b, c, X[ 5], MD5_S12, MD5_T06); + FF (c, d, a, b, X[ 6], MD5_S13, MD5_T07); + FF (b, c, d, a, X[ 7], MD5_S14, MD5_T08); + FF (a, b, c, d, X[ 8], MD5_S11, MD5_T09); + FF (d, a, b, c, X[ 9], MD5_S12, MD5_T10); + FF (c, d, a, b, X[10], MD5_S13, MD5_T11); + FF (b, c, d, a, X[11], MD5_S14, MD5_T12); + FF (a, b, c, d, X[12], MD5_S11, MD5_T13); + FF (d, a, b, c, X[13], MD5_S12, MD5_T14); + FF (c, d, a, b, X[14], MD5_S13, MD5_T15); + FF (b, c, d, a, X[15], MD5_S14, MD5_T16); + + //Perform Round 2 of the transformation + GG (a, b, c, d, X[ 1], MD5_S21, MD5_T17); + GG (d, a, b, c, X[ 6], MD5_S22, MD5_T18); + GG (c, d, a, b, X[11], MD5_S23, MD5_T19); + GG (b, c, d, a, X[ 0], MD5_S24, MD5_T20); + GG (a, b, c, d, X[ 5], MD5_S21, MD5_T21); + GG (d, a, b, c, X[10], MD5_S22, MD5_T22); + GG (c, d, a, b, X[15], MD5_S23, MD5_T23); + GG (b, c, d, a, X[ 4], MD5_S24, MD5_T24); + GG (a, b, c, d, X[ 9], MD5_S21, MD5_T25); + GG (d, a, b, c, X[14], MD5_S22, MD5_T26); + GG (c, d, a, b, X[ 3], MD5_S23, MD5_T27); + GG (b, c, d, a, X[ 8], MD5_S24, MD5_T28); + GG (a, b, c, d, X[13], MD5_S21, MD5_T29); + GG (d, a, b, c, X[ 2], MD5_S22, MD5_T30); + GG (c, d, a, b, X[ 7], MD5_S23, MD5_T31); + GG (b, c, d, a, X[12], MD5_S24, MD5_T32); + + //Perform Round 3 of the transformation + HH (a, b, c, d, X[ 5], MD5_S31, MD5_T33); + HH (d, a, b, c, X[ 8], MD5_S32, MD5_T34); + HH (c, d, a, b, X[11], MD5_S33, MD5_T35); + HH (b, c, d, a, X[14], MD5_S34, MD5_T36); + HH (a, b, c, d, X[ 1], MD5_S31, MD5_T37); + HH (d, a, b, c, X[ 4], MD5_S32, MD5_T38); + HH (c, d, a, b, X[ 7], MD5_S33, MD5_T39); + HH (b, c, d, a, X[10], MD5_S34, MD5_T40); + HH (a, b, c, d, X[13], MD5_S31, MD5_T41); + HH (d, a, b, c, X[ 0], MD5_S32, MD5_T42); + HH (c, d, a, b, X[ 3], MD5_S33, MD5_T43); + HH (b, c, d, a, X[ 6], MD5_S34, MD5_T44); + HH (a, b, c, d, X[ 9], MD5_S31, MD5_T45); + HH (d, a, b, c, X[12], MD5_S32, MD5_T46); + HH (c, d, a, b, X[15], MD5_S33, MD5_T47); + HH (b, c, d, a, X[ 2], MD5_S34, MD5_T48); + + //Perform Round 4 of the transformation + II (a, b, c, d, X[ 0], MD5_S41, MD5_T49); + II (d, a, b, c, X[ 7], MD5_S42, MD5_T50); + II (c, d, a, b, X[14], MD5_S43, MD5_T51); + II (b, c, d, a, X[ 5], MD5_S44, MD5_T52); + II (a, b, c, d, X[12], MD5_S41, MD5_T53); + II (d, a, b, c, X[ 3], MD5_S42, MD5_T54); + II (c, d, a, b, X[10], MD5_S43, MD5_T55); + II (b, c, d, a, X[ 1], MD5_S44, MD5_T56); + II (a, b, c, d, X[ 8], MD5_S41, MD5_T57); + II (d, a, b, c, X[15], MD5_S42, MD5_T58); + II (c, d, a, b, X[ 6], MD5_S43, MD5_T59); + II (b, c, d, a, X[13], MD5_S44, MD5_T60); + II (a, b, c, d, X[ 4], MD5_S41, MD5_T61); + II (d, a, b, c, X[11], MD5_S42, MD5_T62); + II (c, d, a, b, X[ 2], MD5_S43, MD5_T63); + II (b, c, d, a, X[ 9], MD5_S44, MD5_T64); + + //add the transformed values to the current checksum + m_lMD5[0] += a; + m_lMD5[1] += b; + m_lMD5[2] += c; + m_lMD5[3] += d; +} + + +/***************************************************************************************** +CONSTRUCTOR: CMD5Checksum +DESCRIPTION: Initialises member data +ARGUMENTS: None +NOTES: None +*****************************************************************************************/ +CMD5Checksum::CMD5Checksum() +{ + // zero members + memset( m_lpszBuffer, 0, 64 ); + m_nCount[0] = m_nCount[1] = 0; + + // Load magic state initialization constants + m_lMD5[0] = MD5_INIT_STATE_0; + m_lMD5[1] = MD5_INIT_STATE_1; + m_lMD5[2] = MD5_INIT_STATE_2; + m_lMD5[3] = MD5_INIT_STATE_3; +} + +/***************************************************************************************** +FUNCTION: CMD5Checksum::DWordToByte +DETAILS: private +DESCRIPTION: Transfers the data in an 32 bit array to a 8 bit array +RETURNS: void +ARGUMENTS: BYTE* Output : the 8 bit destination array + DWORD* Input : the 32 bit source array + UINT nLength : the number of 8 bit data items in the source array +NOTES: One DWORD from the input array is transferred into four BYTES + in the output array. The first (0-7) bits of the first DWORD are + transferred to the first output BYTE, bits bits 8-15 are transferred from + the second BYTE etc. + + The algorithm assumes that the output array is a multiple of 4 bytes long + so that there is a perfect fit of 8 bit BYTES into the 32 bit DWORDs. +*****************************************************************************************/ +void CMD5Checksum::DWordToByte(BYTE* Output, DWORD* Input, UINT nLength ) +{ + //entry invariants +// ASSERT( nLength % 4 == 0 ); +// ASSERT( AfxIsValidAddress(Output, nLength, TRUE) ); +// ASSERT( AfxIsValidAddress(Input, nLength/4, FALSE) ); + + //transfer the data by shifting and copying + UINT i = 0; + UINT j = 0; + for ( ; j < nLength; i++, j += 4) + { + Output[j] = (UCHAR)(Input[i] & 0xff); + Output[j+1] = (UCHAR)((Input[i] >> 8) & 0xff); + Output[j+2] = (UCHAR)((Input[i] >> 16) & 0xff); + Output[j+3] = (UCHAR)((Input[i] >> 24) & 0xff); + } +} + + +/***************************************************************************************** +FUNCTION: CMD5Checksum::Final +DETAILS: protected +DESCRIPTION: Implementation of main MD5 checksum algorithm; ends the checksum calculation. +RETURNS: CString : the final hexadecimal MD5 checksum result +ARGUMENTS: None +NOTES: Performs the final MD5 checksum calculation ('Update' does most of the work, + this function just finishes the calculation.) +*****************************************************************************************/ +CString CMD5Checksum::Final() +{ + //Save number of bits + BYTE Bits[8]; + DWordToByte( Bits, m_nCount, 8 ); + + //Pad out to 56 mod 64. + UINT nIndex = (UINT)((m_nCount[0] >> 3) & 0x3f); + UINT nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex); + Update( PADDING, nPadLen ); + + //Append length (before padding) + Update( Bits, 8 ); + + //Store final state in 'lpszMD5' + const int nMD5Size = 16; + unsigned char lpszMD5[ nMD5Size ]; + DWordToByte( lpszMD5, m_lMD5, nMD5Size ); + + //Convert the hexadecimal checksum to a CString + CString strMD5; + for ( int i=0; i < nMD5Size; i++) + { + CString Str; + if (lpszMD5[i] == 0) { + Str = CString("00"); + } + else if (lpszMD5[i] <= 15) { + Str.Format(TEXT("0%x"),lpszMD5[i]); + } + else { + Str.Format(TEXT("%x"),lpszMD5[i]); + } + + ATLASSERT(Str.GetLength() == 2); + strMD5 += Str; + } + ATLASSERT( strMD5.GetLength() == 32 ); + return strMD5; +} + + +/***************************************************************************************** +FUNCTION: CMD5Checksum::Update +DETAILS: protected +DESCRIPTION: Implementation of main MD5 checksum algorithm +RETURNS: void +ARGUMENTS: BYTE* Input : input block + UINT nInputLen : length of input block +NOTES: Computes the partial MD5 checksum for 'nInputLen' bytes of data in 'Input' +*****************************************************************************************/ +void CMD5Checksum::Update( BYTE* Input, ULONG nInputLen ) +{ + //Compute number of bytes mod 64 + UINT nIndex = (UINT)((m_nCount[0] >> 3) & 0x3F); + + //Update number of bits + if ( ( m_nCount[0] += nInputLen << 3 ) < ( nInputLen << 3) ) + { + m_nCount[1]++; + } + m_nCount[1] += (nInputLen >> 29); + + //Transform as many times as possible. + UINT i=0; + UINT nPartLen = 64 - nIndex; + if (nInputLen >= nPartLen) + { + memcpy( &m_lpszBuffer[nIndex], Input, nPartLen ); + Transform( m_lpszBuffer ); + for (i = nPartLen; i + 63 < nInputLen; i += 64) + { + Transform( &Input[i] ); + } + nIndex = 0; + } + else + { + i = 0; + } + + // Buffer remaining input + memcpy( &m_lpszBuffer[nIndex], &Input[i], nInputLen-i); +} + + diff --git a/VNOC/util/MD5.h b/Client/Client/util/MD5.h similarity index 97% rename from VNOC/util/MD5.h rename to Client/Client/util/MD5.h index 6aef54ef..c1e801a2 100644 --- a/VNOC/util/MD5.h +++ b/Client/Client/util/MD5.h @@ -1,329 +1,329 @@ -// MD5Checksum.h: interface for the MD5Checksum class. -// -////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_MD5CHECKSUM_H__2BC7928E_4C15_11D3_B2EE_A4A60E20D2C3__INCLUDED_) -#define AFX_MD5CHECKSUM_H__2BC7928E_4C15_11D3_B2EE_A4A60E20D2C3__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - - -/**************************************************************************************** -This software is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. -Incorporation of this statement is a condition of use; please see the RSA -Data Security Inc copyright notice below:- - -Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All -rights reserved. - -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - -These notices must be retained in any copies of any part of this -documentation and/or software. - -Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - -These notices must be retained in any copies of any part of this -documentation and/or software. -*****************************************************************************************/ - -/**************************************************************************************** -This implementation of the RSA MD5 Algorithm was written by Langfine Ltd. - -Langfine Ltd makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - -In addition to the above, Langfine make no warrant or assurances regarding the -accuracy of this implementation of the MD5 checksum algorithm nor any assurances regarding -its suitability for any purposes. - -This implementation may be used freely provided that Langfine is credited -in a copyright or similar notices (eg, RSA MD5 Algorithm implemented by Langfine -Ltd.) and provided that the RSA Data Security notices are complied with. - -Langfine may be contacted at mail@langfine.com -*/ - -/***************************************************************************************** -CLASS: CMD5Checksum -DESCRIPTION: Implements the "RSA Data Security, Inc. MD5 Message-Digest Algorithm". -NOTES: Calculates the RSA MD5 checksum for a file or congiguous array of data. - -Below are extracts from a memo on The MD5 Message-Digest Algorithm by R. Rivest of MIT -Laboratory for Computer Science and RSA Data Security, Inc., April 1992. - - 1. Executive Summary - This document describes the MD5 message-digest algorithm. The - algorithm takes as input a message of arbitrary length and produces - as output a 128-bit "fingerprint" or "message digest" of the input. - It is conjectured that it is computationally infeasible to produce - two messages having the same message digest, or to produce any - message having a given prespecified target message digest. The MD5 - algorithm is intended for digital signature applications, where a - large file must be "compressed" in a secure manner before being - encrypted with a private (secret) key under a public-key cryptosystem - such as RSA. - - The MD5 algorithm is designed to be quite fast on 32-bit machines. In - addition, the MD5 algorithm does not require any large substitution - tables; the algorithm can be coded quite compactly. - The MD5 algorithm is an extension of the MD4 message-digest algorithm - 1,2]. MD5 is slightly slower than MD4, but is more "conservative" in - design. MD5 was designed because it was felt that MD4 was perhaps - being adopted for use more quickly than justified by the existing - critical review; because MD4 was designed to be exceptionally fast, - it is "at the edge" in terms of risking successful cryptanalytic - attack. MD5 backs off a bit, giving up a little in speed for a much - greater likelihood of ultimate security. It incorporates some - suggestions made by various reviewers, and contains additional - optimizations. The MD5 algorithm is being placed in the public domain - for review and possible adoption as a standard. - - - 2. Terminology and Notation - In this document a "word" is a 32-bit quantity and a "byte" is an - eight-bit quantity. A sequence of bits can be interpreted in a - natural manner as a sequence of bytes, where each consecutive group - of eight bits is interpreted as a byte with the high-order (most - significant) bit of each byte listed first. Similarly, a sequence of - bytes can be interpreted as a sequence of 32-bit words, where each - consecutive group of four bytes is interpreted as a word with the - low-order (least significant) byte given first. - Let x_i denote "x sub i". If the subscript is an expression, we - surround it in braces, as in x_{i+1}. Similarly, we use ^ for - superscripts (exponentiation), so that x^i denotes x to the i-th power. - Let the symbol "+" denote addition of words (i.e., modulo-2^32 - addition). Let X <<< s denote the 32-bit value obtained by circularly - shifting (rotating) X left by s bit positions. Let not(X) denote the - bit-wise complement of X, and let X v Y denote the bit-wise OR of X - and Y. Let X xor Y denote the bit-wise XOR of X and Y, and let XY - denote the bit-wise AND of X and Y. - - - 3. MD5 Algorithm Description - We begin by supposing that we have a b-bit message as input, and that - we wish to find its message digest. Here b is an arbitrary - nonnegative integer; b may be zero, it need not be a multiple of - eight, and it may be arbitrarily large. We imagine the bits of the - message written down as follows: m_0 m_1 ... m_{b-1} - The following five steps are performed to compute the message digest - of the message. - - 3.1 Step 1. Append Padding Bits - The message is "padded" (extended) so that its length (in bits) is - congruent to 448, modulo 512. That is, the message is extended so - that it is just 64 bits shy of being a multiple of 512 bits long. - Padding is always performed, even if the length of the message is - already congruent to 448, modulo 512. - Padding is performed as follows: a single "1" bit is appended to the - message, and then "0" bits are appended so that the length in bits of - the padded message becomes congruent to 448, modulo 512. In all, at - least one bit and at most 512 bits are appended. - - 3.2 Step 2. Append Length - A 64-bit representation of b (the length of the message before the - padding bits were added) is appended to the result of the previous - step. In the unlikely event that b is greater than 2^64, then only - the low-order 64 bits of b are used. (These bits are appended as two - 32-bit words and appended low-order word first in accordance with the - previous conventions.) - At this point the resulting message (after padding with bits and with - b) has a length that is an exact multiple of 512 bits. Equivalently, - this message has a length that is an exact multiple of 16 (32-bit) - words. Let M[0 ... N-1] denote the words of the resulting message, - where N is a multiple of 16. - - 3.3 Step 3. Initialize MD Buffer - A four-word buffer (A,B,C,D) is used to compute the message digest. - Here each of A, B, C, D is a 32-bit register. These registers are - initialized to the following values in hexadecimal, low-order bytes first): - word A: 01 23 45 67 word B: 89 ab cd ef - word C: fe dc ba 98 word D: 76 54 32 10 - - 3.4 Step 4. Process Message in 16-Word Blocks - We first define four auxiliary functions that each take as input - three 32-bit words and produce as output one 32-bit word. - F(X,Y,Z) = XY v not(X) Z G(X,Y,Z) = XZ v Y not(Z) - H(X,Y,Z) = X xor Y xor Z I(X,Y,Z) = Y xor (X v not(Z)) - In each bit position F acts as a conditional: if X then Y else Z. - The function F could have been defined using + instead of v since XY - and not(X)Z will never have 1's in the same bit position.) It is - interesting to note that if the bits of X, Y, and Z are independent - and unbiased, the each bit of F(X,Y,Z) will be independent and unbiased. - The functions G, H, and I are similar to the function F, in that they - act in "bitwise parallel" to produce their output from the bits of X, - Y, and Z, in such a manner that if the corresponding bits of X, Y, - and Z are independent and unbiased, then each bit of G(X,Y,Z), - H(X,Y,Z), and I(X,Y,Z) will be independent and unbiased. Note that - the function H is the bit-wise "xor" or "parity" function of its inputs. - This step uses a 64-element table T[1 ... 64] constructed from the - sine function. Let T[i] denote the i-th element of the table, which - is equal to the integer part of 4294967296 times abs(sin(i)), where i - is in radians. The elements of the table are given in the appendix. - Do the following: - - //Process each 16-word block. - For i = 0 to N/16-1 do // Copy block i into X. - For j = 0 to 15 do - Set X[j] to M[i*16+j]. - end //of loop on j - - // Save A as AA, B as BB, C as CC, and D as DD. - AA = A BB = B - CC = C DD = D - - // Round 1. - // Let [abcd k s i] denote the operation - // a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). - // Do the following 16 operations. - [ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4] - [ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8] - [ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12] - [ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16] - - // Round 2. - // Let [abcd k s i] denote the operation - // a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). - // Do the following 16 operations. - [ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20] - [ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24] - [ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28] - [ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32] - - // Round 3. - // Let [abcd k s t] denote the operation - // a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). - // Do the following 16 operations. - [ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36] - [ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40] - [ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44] - [ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48] - - // Round 4. - // Let [abcd k s t] denote the operation - // a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). - // Do the following 16 operations. - [ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52] - [ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56] - [ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60] - [ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64] - - // Then perform the following additions. (That is increment each - // of the four registers by the value it had before this block - // was started.) - A = A + AA B = B + BB C = C + CC D = D + DD - - end // of loop on i - - 3.5 Step 5. Output - The message digest produced as output is A, B, C, D. That is, we - begin with the low-order byte of A, and end with the high-order byte of D. - This completes the description of MD5. - - Summary - The MD5 message-digest algorithm is simple to implement, and provides - a "fingerprint" or message digest of a message of arbitrary length. - It is conjectured that the difficulty of coming up with two messages - having the same message digest is on the order of 2^64 operations, - and that the difficulty of coming up with any message having a given - message digest is on the order of 2^128 operations. The MD5 algorithm - has been carefully scrutinized for weaknesses. It is, however, a - relatively new algorithm and further security analysis is of course - justified, as is the case with any new proposal of this sort. - - - 5. Differences Between MD4 and MD5 - The following are the differences between MD4 and MD5: - 1. A fourth round has been added. - 2. Each step now has a unique additive constant. - 3. The function g in round 2 was changed from (XY v XZ v YZ) to - (XZ v Y not(Z)) to make g less symmetric. - 4. Each step now adds in the result of the previous step. This - promotes a faster "avalanche effect". - 5. The order in which input words are accessed in rounds 2 and - 3 is changed, to make these patterns less like each other. - 6. The shift amounts in each round have been approximately - optimized, to yield a faster "avalanche effect." The shifts in - different rounds are distinct. - - References - [1] Rivest, R., "The MD4 Message Digest Algorithm", RFC 1320, MIT and - RSA Data Security, Inc., April 1992. - [2] Rivest, R., "The MD4 message digest algorithm", in A.J. Menezes - and S.A. Vanstone, editors, Advances in Cryptology - CRYPTO '90 - Proceedings, pages 303-311, Springer-Verlag, 1991. - [3] CCITT Recommendation X.509 (1988), "The Directory - - Authentication Framework."APPENDIX A - Reference Implementation - - - The level of security discussed in this memo is considered to be - sufficient for implementing very high security hybrid digital- - signature schemes based on MD5 and a public-key cryptosystem. - Author's Address - Ronald L. Rivest Massachusetts Institute of Technology - Laboratory for Computer Science NE43-324 545 Technology Square - Cambridge, MA 02139-1986 Phone: (617) 253-5880 - EMail: rivest@theory.lcs.mit.edu - -*****************************************************************************************/ -class CMD5Checksum -{ -public: - //interface functions for the RSA MD5 calculation - static CString GetMD5(BYTE* pBuf, UINT nLength); -// static CString GetMD5(CFile& File); -// static CString GetMD5(const CString& strFilePath); - static BOOL GetMD5(LPCTSTR path, CString& md5); - -protected: - //constructor/destructor - CMD5Checksum(); - virtual ~CMD5Checksum() {}; - - //RSA MD5 implementation - void Transform(BYTE Block[64]); - void Update(BYTE* Input, ULONG nInputLen); - CString Final(); - inline DWORD RotateLeft(DWORD x, int n); - inline void FF( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T); - inline void GG( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T); - inline void HH( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T); - inline void II( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T); - - //utility functions - void DWordToByte(BYTE* Output, DWORD* Input, UINT nLength); - void ByteToDWord(DWORD* Output, BYTE* Input, UINT nLength); - -private: - BYTE m_lpszBuffer[64]; //input buffer - ULONG m_nCount[2]; //number of bits, modulo 2^64 (lsb first) - ULONG m_lMD5[4]; //MD5 checksum -}; - -#endif // !defined(AFX_MD5CHECKSUM_H__2BC7928E_4C15_11D3_B2EE_A4A60E20D2C3__INCLUDED_) - - - - - - +// MD5Checksum.h: interface for the MD5Checksum class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_MD5CHECKSUM_H__2BC7928E_4C15_11D3_B2EE_A4A60E20D2C3__INCLUDED_) +#define AFX_MD5CHECKSUM_H__2BC7928E_4C15_11D3_B2EE_A4A60E20D2C3__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +/**************************************************************************************** +This software is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. +Incorporation of this statement is a condition of use; please see the RSA +Data Security Inc copyright notice below:- + +Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All +rights reserved. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + +Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. +*****************************************************************************************/ + +/**************************************************************************************** +This implementation of the RSA MD5 Algorithm was written by Langfine Ltd. + +Langfine Ltd makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +In addition to the above, Langfine make no warrant or assurances regarding the +accuracy of this implementation of the MD5 checksum algorithm nor any assurances regarding +its suitability for any purposes. + +This implementation may be used freely provided that Langfine is credited +in a copyright or similar notices (eg, RSA MD5 Algorithm implemented by Langfine +Ltd.) and provided that the RSA Data Security notices are complied with. + +Langfine may be contacted at mail@langfine.com +*/ + +/***************************************************************************************** +CLASS: CMD5Checksum +DESCRIPTION: Implements the "RSA Data Security, Inc. MD5 Message-Digest Algorithm". +NOTES: Calculates the RSA MD5 checksum for a file or congiguous array of data. + +Below are extracts from a memo on The MD5 Message-Digest Algorithm by R. Rivest of MIT +Laboratory for Computer Science and RSA Data Security, Inc., April 1992. + + 1. Executive Summary + This document describes the MD5 message-digest algorithm. The + algorithm takes as input a message of arbitrary length and produces + as output a 128-bit "fingerprint" or "message digest" of the input. + It is conjectured that it is computationally infeasible to produce + two messages having the same message digest, or to produce any + message having a given prespecified target message digest. The MD5 + algorithm is intended for digital signature applications, where a + large file must be "compressed" in a secure manner before being + encrypted with a private (secret) key under a public-key cryptosystem + such as RSA. + + The MD5 algorithm is designed to be quite fast on 32-bit machines. In + addition, the MD5 algorithm does not require any large substitution + tables; the algorithm can be coded quite compactly. + The MD5 algorithm is an extension of the MD4 message-digest algorithm + 1,2]. MD5 is slightly slower than MD4, but is more "conservative" in + design. MD5 was designed because it was felt that MD4 was perhaps + being adopted for use more quickly than justified by the existing + critical review; because MD4 was designed to be exceptionally fast, + it is "at the edge" in terms of risking successful cryptanalytic + attack. MD5 backs off a bit, giving up a little in speed for a much + greater likelihood of ultimate security. It incorporates some + suggestions made by various reviewers, and contains additional + optimizations. The MD5 algorithm is being placed in the public domain + for review and possible adoption as a standard. + + + 2. Terminology and Notation + In this document a "word" is a 32-bit quantity and a "byte" is an + eight-bit quantity. A sequence of bits can be interpreted in a + natural manner as a sequence of bytes, where each consecutive group + of eight bits is interpreted as a byte with the high-order (most + significant) bit of each byte listed first. Similarly, a sequence of + bytes can be interpreted as a sequence of 32-bit words, where each + consecutive group of four bytes is interpreted as a word with the + low-order (least significant) byte given first. + Let x_i denote "x sub i". If the subscript is an expression, we + surround it in braces, as in x_{i+1}. Similarly, we use ^ for + superscripts (exponentiation), so that x^i denotes x to the i-th power. + Let the symbol "+" denote addition of words (i.e., modulo-2^32 + addition). Let X <<< s denote the 32-bit value obtained by circularly + shifting (rotating) X left by s bit positions. Let not(X) denote the + bit-wise complement of X, and let X v Y denote the bit-wise OR of X + and Y. Let X xor Y denote the bit-wise XOR of X and Y, and let XY + denote the bit-wise AND of X and Y. + + + 3. MD5 Algorithm Description + We begin by supposing that we have a b-bit message as input, and that + we wish to find its message digest. Here b is an arbitrary + nonnegative integer; b may be zero, it need not be a multiple of + eight, and it may be arbitrarily large. We imagine the bits of the + message written down as follows: m_0 m_1 ... m_{b-1} + The following five steps are performed to compute the message digest + of the message. + + 3.1 Step 1. Append Padding Bits + The message is "padded" (extended) so that its length (in bits) is + congruent to 448, modulo 512. That is, the message is extended so + that it is just 64 bits shy of being a multiple of 512 bits long. + Padding is always performed, even if the length of the message is + already congruent to 448, modulo 512. + Padding is performed as follows: a single "1" bit is appended to the + message, and then "0" bits are appended so that the length in bits of + the padded message becomes congruent to 448, modulo 512. In all, at + least one bit and at most 512 bits are appended. + + 3.2 Step 2. Append Length + A 64-bit representation of b (the length of the message before the + padding bits were added) is appended to the result of the previous + step. In the unlikely event that b is greater than 2^64, then only + the low-order 64 bits of b are used. (These bits are appended as two + 32-bit words and appended low-order word first in accordance with the + previous conventions.) + At this point the resulting message (after padding with bits and with + b) has a length that is an exact multiple of 512 bits. Equivalently, + this message has a length that is an exact multiple of 16 (32-bit) + words. Let M[0 ... N-1] denote the words of the resulting message, + where N is a multiple of 16. + + 3.3 Step 3. Initialize MD Buffer + A four-word buffer (A,B,C,D) is used to compute the message digest. + Here each of A, B, C, D is a 32-bit register. These registers are + initialized to the following values in hexadecimal, low-order bytes first): + word A: 01 23 45 67 word B: 89 ab cd ef + word C: fe dc ba 98 word D: 76 54 32 10 + + 3.4 Step 4. Process Message in 16-Word Blocks + We first define four auxiliary functions that each take as input + three 32-bit words and produce as output one 32-bit word. + F(X,Y,Z) = XY v not(X) Z G(X,Y,Z) = XZ v Y not(Z) + H(X,Y,Z) = X xor Y xor Z I(X,Y,Z) = Y xor (X v not(Z)) + In each bit position F acts as a conditional: if X then Y else Z. + The function F could have been defined using + instead of v since XY + and not(X)Z will never have 1's in the same bit position.) It is + interesting to note that if the bits of X, Y, and Z are independent + and unbiased, the each bit of F(X,Y,Z) will be independent and unbiased. + The functions G, H, and I are similar to the function F, in that they + act in "bitwise parallel" to produce their output from the bits of X, + Y, and Z, in such a manner that if the corresponding bits of X, Y, + and Z are independent and unbiased, then each bit of G(X,Y,Z), + H(X,Y,Z), and I(X,Y,Z) will be independent and unbiased. Note that + the function H is the bit-wise "xor" or "parity" function of its inputs. + This step uses a 64-element table T[1 ... 64] constructed from the + sine function. Let T[i] denote the i-th element of the table, which + is equal to the integer part of 4294967296 times abs(sin(i)), where i + is in radians. The elements of the table are given in the appendix. + Do the following: + + //Process each 16-word block. + For i = 0 to N/16-1 do // Copy block i into X. + For j = 0 to 15 do + Set X[j] to M[i*16+j]. + end //of loop on j + + // Save A as AA, B as BB, C as CC, and D as DD. + AA = A BB = B + CC = C DD = D + + // Round 1. + // Let [abcd k s i] denote the operation + // a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). + // Do the following 16 operations. + [ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4] + [ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8] + [ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12] + [ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16] + + // Round 2. + // Let [abcd k s i] denote the operation + // a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). + // Do the following 16 operations. + [ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20] + [ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24] + [ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28] + [ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32] + + // Round 3. + // Let [abcd k s t] denote the operation + // a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). + // Do the following 16 operations. + [ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36] + [ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40] + [ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44] + [ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48] + + // Round 4. + // Let [abcd k s t] denote the operation + // a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). + // Do the following 16 operations. + [ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52] + [ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56] + [ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60] + [ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64] + + // Then perform the following additions. (That is increment each + // of the four registers by the value it had before this block + // was started.) + A = A + AA B = B + BB C = C + CC D = D + DD + + end // of loop on i + + 3.5 Step 5. Output + The message digest produced as output is A, B, C, D. That is, we + begin with the low-order byte of A, and end with the high-order byte of D. + This completes the description of MD5. + + Summary + The MD5 message-digest algorithm is simple to implement, and provides + a "fingerprint" or message digest of a message of arbitrary length. + It is conjectured that the difficulty of coming up with two messages + having the same message digest is on the order of 2^64 operations, + and that the difficulty of coming up with any message having a given + message digest is on the order of 2^128 operations. The MD5 algorithm + has been carefully scrutinized for weaknesses. It is, however, a + relatively new algorithm and further security analysis is of course + justified, as is the case with any new proposal of this sort. + + + 5. Differences Between MD4 and MD5 + The following are the differences between MD4 and MD5: + 1. A fourth round has been added. + 2. Each step now has a unique additive constant. + 3. The function g in round 2 was changed from (XY v XZ v YZ) to + (XZ v Y not(Z)) to make g less symmetric. + 4. Each step now adds in the result of the previous step. This + promotes a faster "avalanche effect". + 5. The order in which input words are accessed in rounds 2 and + 3 is changed, to make these patterns less like each other. + 6. The shift amounts in each round have been approximately + optimized, to yield a faster "avalanche effect." The shifts in + different rounds are distinct. + + References + [1] Rivest, R., "The MD4 Message Digest Algorithm", RFC 1320, MIT and + RSA Data Security, Inc., April 1992. + [2] Rivest, R., "The MD4 message digest algorithm", in A.J. Menezes + and S.A. Vanstone, editors, Advances in Cryptology - CRYPTO '90 + Proceedings, pages 303-311, Springer-Verlag, 1991. + [3] CCITT Recommendation X.509 (1988), "The Directory - + Authentication Framework."APPENDIX A - Reference Implementation + + + The level of security discussed in this memo is considered to be + sufficient for implementing very high security hybrid digital- + signature schemes based on MD5 and a public-key cryptosystem. + Author's Address + Ronald L. Rivest Massachusetts Institute of Technology + Laboratory for Computer Science NE43-324 545 Technology Square + Cambridge, MA 02139-1986 Phone: (617) 253-5880 + EMail: rivest@theory.lcs.mit.edu + +*****************************************************************************************/ +class CMD5Checksum +{ +public: + //interface functions for the RSA MD5 calculation + static CString GetMD5(BYTE* pBuf, UINT nLength); +// static CString GetMD5(CFile& File); +// static CString GetMD5(const CString& strFilePath); + static BOOL GetMD5(LPCTSTR path, CString& md5); + +protected: + //constructor/destructor + CMD5Checksum(); + virtual ~CMD5Checksum() {}; + + //RSA MD5 implementation + void Transform(BYTE Block[64]); + void Update(BYTE* Input, ULONG nInputLen); + CString Final(); + inline DWORD RotateLeft(DWORD x, int n); + inline void FF( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T); + inline void GG( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T); + inline void HH( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T); + inline void II( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T); + + //utility functions + void DWordToByte(BYTE* Output, DWORD* Input, UINT nLength); + void ByteToDWord(DWORD* Output, BYTE* Input, UINT nLength); + +private: + BYTE m_lpszBuffer[64]; //input buffer + ULONG m_nCount[2]; //number of bits, modulo 2^64 (lsb first) + ULONG m_lMD5[4]; //MD5 checksum +}; + +#endif // !defined(AFX_MD5CHECKSUM_H__2BC7928E_4C15_11D3_B2EE_A4A60E20D2C3__INCLUDED_) + + + + + + diff --git a/VNOC/util/MD5ChecksumDefines.h b/Client/Client/util/MD5ChecksumDefines.h similarity index 97% rename from VNOC/util/MD5ChecksumDefines.h rename to Client/Client/util/MD5ChecksumDefines.h index 669be75d..81c7bac3 100644 --- a/VNOC/util/MD5ChecksumDefines.h +++ b/Client/Client/util/MD5ChecksumDefines.h @@ -1,106 +1,106 @@ -//MD5ChecksumDefines.h : MD5 Checksum constants - -//Magic initialization constants -#define MD5_INIT_STATE_0 0x67452301 -#define MD5_INIT_STATE_1 0xefcdab89 -#define MD5_INIT_STATE_2 0x98badcfe -#define MD5_INIT_STATE_3 0x10325476 - -//Constants for Transform routine. -#define MD5_S11 7 -#define MD5_S12 12 -#define MD5_S13 17 -#define MD5_S14 22 -#define MD5_S21 5 -#define MD5_S22 9 -#define MD5_S23 14 -#define MD5_S24 20 -#define MD5_S31 4 -#define MD5_S32 11 -#define MD5_S33 16 -#define MD5_S34 23 -#define MD5_S41 6 -#define MD5_S42 10 -#define MD5_S43 15 -#define MD5_S44 21 - -//Transformation Constants - Round 1 -#define MD5_T01 0xd76aa478 //Transformation Constant 1 -#define MD5_T02 0xe8c7b756 //Transformation Constant 2 -#define MD5_T03 0x242070db //Transformation Constant 3 -#define MD5_T04 0xc1bdceee //Transformation Constant 4 -#define MD5_T05 0xf57c0faf //Transformation Constant 5 -#define MD5_T06 0x4787c62a //Transformation Constant 6 -#define MD5_T07 0xa8304613 //Transformation Constant 7 -#define MD5_T08 0xfd469501 //Transformation Constant 8 -#define MD5_T09 0x698098d8 //Transformation Constant 9 -#define MD5_T10 0x8b44f7af //Transformation Constant 10 -#define MD5_T11 0xffff5bb1 //Transformation Constant 11 -#define MD5_T12 0x895cd7be //Transformation Constant 12 -#define MD5_T13 0x6b901122 //Transformation Constant 13 -#define MD5_T14 0xfd987193 //Transformation Constant 14 -#define MD5_T15 0xa679438e //Transformation Constant 15 -#define MD5_T16 0x49b40821 //Transformation Constant 16 - -//Transformation Constants - Round 2 -#define MD5_T17 0xf61e2562 //Transformation Constant 17 -#define MD5_T18 0xc040b340 //Transformation Constant 18 -#define MD5_T19 0x265e5a51 //Transformation Constant 19 -#define MD5_T20 0xe9b6c7aa //Transformation Constant 20 -#define MD5_T21 0xd62f105d //Transformation Constant 21 -#define MD5_T22 0x02441453 //Transformation Constant 22 -#define MD5_T23 0xd8a1e681 //Transformation Constant 23 -#define MD5_T24 0xe7d3fbc8 //Transformation Constant 24 -#define MD5_T25 0x21e1cde6 //Transformation Constant 25 -#define MD5_T26 0xc33707d6 //Transformation Constant 26 -#define MD5_T27 0xf4d50d87 //Transformation Constant 27 -#define MD5_T28 0x455a14ed //Transformation Constant 28 -#define MD5_T29 0xa9e3e905 //Transformation Constant 29 -#define MD5_T30 0xfcefa3f8 //Transformation Constant 30 -#define MD5_T31 0x676f02d9 //Transformation Constant 31 -#define MD5_T32 0x8d2a4c8a //Transformation Constant 32 - -//Transformation Constants - Round 3 -#define MD5_T33 0xfffa3942 //Transformation Constant 33 -#define MD5_T34 0x8771f681 //Transformation Constant 34 -#define MD5_T35 0x6d9d6122 //Transformation Constant 35 -#define MD5_T36 0xfde5380c //Transformation Constant 36 -#define MD5_T37 0xa4beea44 //Transformation Constant 37 -#define MD5_T38 0x4bdecfa9 //Transformation Constant 38 -#define MD5_T39 0xf6bb4b60 //Transformation Constant 39 -#define MD5_T40 0xbebfbc70 //Transformation Constant 40 -#define MD5_T41 0x289b7ec6 //Transformation Constant 41 -#define MD5_T42 0xeaa127fa //Transformation Constant 42 -#define MD5_T43 0xd4ef3085 //Transformation Constant 43 -#define MD5_T44 0x04881d05 //Transformation Constant 44 -#define MD5_T45 0xd9d4d039 //Transformation Constant 45 -#define MD5_T46 0xe6db99e5 //Transformation Constant 46 -#define MD5_T47 0x1fa27cf8 //Transformation Constant 47 -#define MD5_T48 0xc4ac5665 //Transformation Constant 48 - -//Transformation Constants - Round 4 -#define MD5_T49 0xf4292244 //Transformation Constant 49 -#define MD5_T50 0x432aff97 //Transformation Constant 50 -#define MD5_T51 0xab9423a7 //Transformation Constant 51 -#define MD5_T52 0xfc93a039 //Transformation Constant 52 -#define MD5_T53 0x655b59c3 //Transformation Constant 53 -#define MD5_T54 0x8f0ccc92 //Transformation Constant 54 -#define MD5_T55 0xffeff47d //Transformation Constant 55 -#define MD5_T56 0x85845dd1 //Transformation Constant 56 -#define MD5_T57 0x6fa87e4f //Transformation Constant 57 -#define MD5_T58 0xfe2ce6e0 //Transformation Constant 58 -#define MD5_T59 0xa3014314 //Transformation Constant 59 -#define MD5_T60 0x4e0811a1 //Transformation Constant 60 -#define MD5_T61 0xf7537e82 //Transformation Constant 61 -#define MD5_T62 0xbd3af235 //Transformation Constant 62 -#define MD5_T63 0x2ad7d2bb //Transformation Constant 63 -#define MD5_T64 0xeb86d391 //Transformation Constant 64 - - -//Null data (except for first BYTE) used to finalise the checksum calculation -static unsigned char PADDING[64] = { - 0x80, 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - +//MD5ChecksumDefines.h : MD5 Checksum constants + +//Magic initialization constants +#define MD5_INIT_STATE_0 0x67452301 +#define MD5_INIT_STATE_1 0xefcdab89 +#define MD5_INIT_STATE_2 0x98badcfe +#define MD5_INIT_STATE_3 0x10325476 + +//Constants for Transform routine. +#define MD5_S11 7 +#define MD5_S12 12 +#define MD5_S13 17 +#define MD5_S14 22 +#define MD5_S21 5 +#define MD5_S22 9 +#define MD5_S23 14 +#define MD5_S24 20 +#define MD5_S31 4 +#define MD5_S32 11 +#define MD5_S33 16 +#define MD5_S34 23 +#define MD5_S41 6 +#define MD5_S42 10 +#define MD5_S43 15 +#define MD5_S44 21 + +//Transformation Constants - Round 1 +#define MD5_T01 0xd76aa478 //Transformation Constant 1 +#define MD5_T02 0xe8c7b756 //Transformation Constant 2 +#define MD5_T03 0x242070db //Transformation Constant 3 +#define MD5_T04 0xc1bdceee //Transformation Constant 4 +#define MD5_T05 0xf57c0faf //Transformation Constant 5 +#define MD5_T06 0x4787c62a //Transformation Constant 6 +#define MD5_T07 0xa8304613 //Transformation Constant 7 +#define MD5_T08 0xfd469501 //Transformation Constant 8 +#define MD5_T09 0x698098d8 //Transformation Constant 9 +#define MD5_T10 0x8b44f7af //Transformation Constant 10 +#define MD5_T11 0xffff5bb1 //Transformation Constant 11 +#define MD5_T12 0x895cd7be //Transformation Constant 12 +#define MD5_T13 0x6b901122 //Transformation Constant 13 +#define MD5_T14 0xfd987193 //Transformation Constant 14 +#define MD5_T15 0xa679438e //Transformation Constant 15 +#define MD5_T16 0x49b40821 //Transformation Constant 16 + +//Transformation Constants - Round 2 +#define MD5_T17 0xf61e2562 //Transformation Constant 17 +#define MD5_T18 0xc040b340 //Transformation Constant 18 +#define MD5_T19 0x265e5a51 //Transformation Constant 19 +#define MD5_T20 0xe9b6c7aa //Transformation Constant 20 +#define MD5_T21 0xd62f105d //Transformation Constant 21 +#define MD5_T22 0x02441453 //Transformation Constant 22 +#define MD5_T23 0xd8a1e681 //Transformation Constant 23 +#define MD5_T24 0xe7d3fbc8 //Transformation Constant 24 +#define MD5_T25 0x21e1cde6 //Transformation Constant 25 +#define MD5_T26 0xc33707d6 //Transformation Constant 26 +#define MD5_T27 0xf4d50d87 //Transformation Constant 27 +#define MD5_T28 0x455a14ed //Transformation Constant 28 +#define MD5_T29 0xa9e3e905 //Transformation Constant 29 +#define MD5_T30 0xfcefa3f8 //Transformation Constant 30 +#define MD5_T31 0x676f02d9 //Transformation Constant 31 +#define MD5_T32 0x8d2a4c8a //Transformation Constant 32 + +//Transformation Constants - Round 3 +#define MD5_T33 0xfffa3942 //Transformation Constant 33 +#define MD5_T34 0x8771f681 //Transformation Constant 34 +#define MD5_T35 0x6d9d6122 //Transformation Constant 35 +#define MD5_T36 0xfde5380c //Transformation Constant 36 +#define MD5_T37 0xa4beea44 //Transformation Constant 37 +#define MD5_T38 0x4bdecfa9 //Transformation Constant 38 +#define MD5_T39 0xf6bb4b60 //Transformation Constant 39 +#define MD5_T40 0xbebfbc70 //Transformation Constant 40 +#define MD5_T41 0x289b7ec6 //Transformation Constant 41 +#define MD5_T42 0xeaa127fa //Transformation Constant 42 +#define MD5_T43 0xd4ef3085 //Transformation Constant 43 +#define MD5_T44 0x04881d05 //Transformation Constant 44 +#define MD5_T45 0xd9d4d039 //Transformation Constant 45 +#define MD5_T46 0xe6db99e5 //Transformation Constant 46 +#define MD5_T47 0x1fa27cf8 //Transformation Constant 47 +#define MD5_T48 0xc4ac5665 //Transformation Constant 48 + +//Transformation Constants - Round 4 +#define MD5_T49 0xf4292244 //Transformation Constant 49 +#define MD5_T50 0x432aff97 //Transformation Constant 50 +#define MD5_T51 0xab9423a7 //Transformation Constant 51 +#define MD5_T52 0xfc93a039 //Transformation Constant 52 +#define MD5_T53 0x655b59c3 //Transformation Constant 53 +#define MD5_T54 0x8f0ccc92 //Transformation Constant 54 +#define MD5_T55 0xffeff47d //Transformation Constant 55 +#define MD5_T56 0x85845dd1 //Transformation Constant 56 +#define MD5_T57 0x6fa87e4f //Transformation Constant 57 +#define MD5_T58 0xfe2ce6e0 //Transformation Constant 58 +#define MD5_T59 0xa3014314 //Transformation Constant 59 +#define MD5_T60 0x4e0811a1 //Transformation Constant 60 +#define MD5_T61 0xf7537e82 //Transformation Constant 61 +#define MD5_T62 0xbd3af235 //Transformation Constant 62 +#define MD5_T63 0x2ad7d2bb //Transformation Constant 63 +#define MD5_T64 0xeb86d391 //Transformation Constant 64 + + +//Null data (except for first BYTE) used to finalise the checksum calculation +static unsigned char PADDING[64] = { + 0x80, 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + diff --git a/VNOC/util/Performance.h b/Client/Client/util/Performance.h similarity index 95% rename from VNOC/util/Performance.h rename to Client/Client/util/Performance.h index e2be1b1e..ca4a438b 100644 --- a/VNOC/util/Performance.h +++ b/Client/Client/util/Performance.h @@ -1,50 +1,50 @@ -#pragma once -#include "time.h" -#include "vector" -#include "atlstr.h" -#include "windows.h" -#include "atlsync.h" -#include "IRefCountImpl.h" -#include "atlsync.h" - -#define PerfDefine(_text) Performance::CPerformance _perf(_text); -#define PerfMileStone(_text) _perf.MileStone(_text); -#define PerfPause _perf.Pause(); -#define PerfResume _perf.Resume(); - -namespace Performance -{ - typedef std::pair TimeStamp; - typedef std::vector > MileStonesVec; - - // ͳʱ - class CPerformance : public IRefCountImpl - { - public: - CPerformance(LPCTSTR text=NULL,BOOL threadSafe=FALSE,LPCTSTR logFile=NULL); - ~CPerformance(); - public: - // ͣʱ - void Pause(); - // ʱ - void Resume(); - // ̱ - void MileStone(LPCTSTR text=NULL); - private: - void _Enter(); - void _Leave(); - void _CheckFlag(); - private: - BOOL m_bEnable; - MileStonesVec m_vec; - MileStonesVec::value_type m_curr; - BOOL m_bPaused; - CString m_taskName; - CString m_logFile; - BOOL m_threadSafe; - ATL::CCriticalSection m_cs; - }; - -} - +#pragma once +#include "time.h" +#include "vector" +#include "atlstr.h" +#include "windows.h" +#include "atlsync.h" +#include "IRefCountImpl.h" +#include "atlsync.h" + +#define PerfDefine(_text) Performance::CPerformance _perf(_text); +#define PerfMileStone(_text) _perf.MileStone(_text); +#define PerfPause _perf.Pause(); +#define PerfResume _perf.Resume(); + +namespace Performance +{ + typedef std::pair TimeStamp; + typedef std::vector > MileStonesVec; + + // ͳʱ + class CPerformance : public IRefCountImpl + { + public: + CPerformance(LPCTSTR text=NULL,BOOL threadSafe=FALSE,LPCTSTR logFile=NULL); + ~CPerformance(); + public: + // ͣʱ + void Pause(); + // ʱ + void Resume(); + // ̱ + void MileStone(LPCTSTR text=NULL); + private: + void _Enter(); + void _Leave(); + void _CheckFlag(); + private: + BOOL m_bEnable; + MileStonesVec m_vec; + MileStonesVec::value_type m_curr; + BOOL m_bPaused; + CString m_taskName; + CString m_logFile; + BOOL m_threadSafe; + ATL::CCriticalSection m_cs; + }; + +} + #include "Performance.inl" \ No newline at end of file diff --git a/VNOC/VNOC/Performance.inl b/Client/Client/util/Performance.inl similarity index 94% rename from VNOC/VNOC/Performance.inl rename to Client/Client/util/Performance.inl index bb59ac4b..f32b57f8 100644 --- a/VNOC/VNOC/Performance.inl +++ b/Client/Client/util/Performance.inl @@ -1,139 +1,139 @@ - -#include "util.h" - -namespace Performance -{ - - inline CPerformance::CPerformance( LPCTSTR text/*=NULL*/,BOOL threadSafe/*=FALSE*/,LPCTSTR logFile ) - { - _CheckFlag(); - if (m_bEnable) - { - m_vec.reserve(16); // ڴʱģݶô - m_bPaused = FALSE; - m_taskName = text; - if (!logFile) - { - m_logFile = L"Performance"; - } - else - { - m_logFile = logFile; - } - - QueryPerformanceCounter(&m_curr.first.first); - } - } - - inline CPerformance::~CPerformance() - { - if (m_bEnable) - { - MileStone(); - - CString log; - double total = 0; - double useTime; - LARGE_INTEGER freq; - freq.QuadPart = 0; - QueryPerformanceFrequency(&freq); - double dfreq = freq.QuadPart==0? 1: static_cast(freq.QuadPart); - - MileStonesVec::iterator i = m_vec.begin(); - if (i!=m_vec.end() && i+1 == m_vec.end()) - { - total = ((i->first.second.QuadPart - i->first.first.QuadPart) - / dfreq)*1000; - } - else - { - while (i != m_vec.end()) - { - LONGLONG during = i->first.second.QuadPart - i->first.first.QuadPart; - useTime = (during/dfreq)*1000; - - log.AppendFormat(_T("\t\t%s : %.6lfms\n") - , (i->second.IsEmpty()? (i+1==m_vec.end()? _T("ʣ"): _T("N/A")): i->second) - , useTime); - total += useTime; - ++i; - } - } - CString head; - head.Format(_T(" ͳ: %-50s\tʱ%lfms\n"),m_taskName,total); - head += log; - head += L"\n"; - //global::log2(m_logFile,head); - } - } - - inline void CPerformance::Pause() - { - if (m_bEnable) - { - _Enter(); - QueryPerformanceCounter(&m_curr.first.second); - m_bPaused = TRUE; - _Leave(); - } - } - - inline void CPerformance::Resume() - { - if (m_bEnable) - { - _Enter(); - m_bPaused = FALSE; - LARGE_INTEGER tm; - QueryPerformanceCounter(&tm); - tm.QuadPart += m_curr.first.second.QuadPart - m_curr.first.first.QuadPart; - m_curr.first.first = tm; - _Leave(); - } - } - - inline void CPerformance::MileStone( LPCTSTR text/*=NULL*/ ) - { - if (m_bEnable) - { - if (m_bPaused) - { - ATLASSERT(FALSE && "step with paused task"); - } - else - { - _Enter(); - QueryPerformanceCounter(&m_curr.first.second); - m_curr.second = text; - m_vec.push_back(m_curr); - m_curr.second.Empty(); - - QueryPerformanceCounter(&m_curr.first.first); - _Leave(); - } - } - } - - inline void CPerformance::_Enter() - { - if (m_threadSafe) - { - m_cs.Enter(); - } - } - - inline void CPerformance::_Leave() - { - if (m_threadSafe) - { - m_cs.Leave(); - } - } - - inline void CPerformance::_CheckFlag() - { - m_bEnable = TRUE; - } - -} - + +#include "util.h" + +namespace Performance +{ + + inline CPerformance::CPerformance( LPCTSTR text/*=NULL*/,BOOL threadSafe/*=FALSE*/,LPCTSTR logFile ) + { + _CheckFlag(); + if (m_bEnable) + { + m_vec.reserve(16); // ڴʱģݶô + m_bPaused = FALSE; + m_taskName = text; + if (!logFile) + { + m_logFile = L"Performance"; + } + else + { + m_logFile = logFile; + } + + QueryPerformanceCounter(&m_curr.first.first); + } + } + + inline CPerformance::~CPerformance() + { + if (m_bEnable) + { + MileStone(); + + CString log; + double total = 0; + double useTime; + LARGE_INTEGER freq; + freq.QuadPart = 0; + QueryPerformanceFrequency(&freq); + double dfreq = freq.QuadPart==0? 1: static_cast(freq.QuadPart); + + MileStonesVec::iterator i = m_vec.begin(); + if (i!=m_vec.end() && i+1 == m_vec.end()) + { + total = ((i->first.second.QuadPart - i->first.first.QuadPart) + / dfreq)*1000; + } + else + { + while (i != m_vec.end()) + { + LONGLONG during = i->first.second.QuadPart - i->first.first.QuadPart; + useTime = (during/dfreq)*1000; + + log.AppendFormat(_T("\t\t%s : %.6lfms\n") + , (i->second.IsEmpty()? (i+1==m_vec.end()? _T("ʣ"): _T("N/A")): i->second) + , useTime); + total += useTime; + ++i; + } + } + CString head; + head.Format(_T(" ͳ: %-50s\tʱ%lfms\n"),m_taskName,total); + head += log; + head += L"\n"; + //global::log2(m_logFile,head); + } + } + + inline void CPerformance::Pause() + { + if (m_bEnable) + { + _Enter(); + QueryPerformanceCounter(&m_curr.first.second); + m_bPaused = TRUE; + _Leave(); + } + } + + inline void CPerformance::Resume() + { + if (m_bEnable) + { + _Enter(); + m_bPaused = FALSE; + LARGE_INTEGER tm; + QueryPerformanceCounter(&tm); + tm.QuadPart += m_curr.first.second.QuadPart - m_curr.first.first.QuadPart; + m_curr.first.first = tm; + _Leave(); + } + } + + inline void CPerformance::MileStone( LPCTSTR text/*=NULL*/ ) + { + if (m_bEnable) + { + if (m_bPaused) + { + ATLASSERT(FALSE && "step with paused task"); + } + else + { + _Enter(); + QueryPerformanceCounter(&m_curr.first.second); + m_curr.second = text; + m_vec.push_back(m_curr); + m_curr.second.Empty(); + + QueryPerformanceCounter(&m_curr.first.first); + _Leave(); + } + } + } + + inline void CPerformance::_Enter() + { + if (m_threadSafe) + { + m_cs.Enter(); + } + } + + inline void CPerformance::_Leave() + { + if (m_threadSafe) + { + m_cs.Leave(); + } + } + + inline void CPerformance::_CheckFlag() + { + m_bEnable = TRUE; + } + +} + diff --git a/Client/Client/util/TLS.cpp b/Client/Client/util/TLS.cpp new file mode 100644 index 00000000..be68858e --- /dev/null +++ b/Client/Client/util/TLS.cpp @@ -0,0 +1,28 @@ +#include "TLS.h" +#include + +CTLS::CTLS( LPCTSTR helpString ) +{ + m_helpString = helpString; + m_tlsIndex = TlsAlloc(); + if (m_tlsIndex == 0xffffffff) + { + ATLASSERT(FALSE && "TLSError"); + throw helpString; + } +} + +CTLS::~CTLS() +{ + TlsFree(m_tlsIndex); +} + +void CTLS::Set( LPVOID value ) +{ + TlsSetValue(m_tlsIndex,value); +} + +LPVOID CTLS::Get() +{ + return TlsGetValue(m_tlsIndex); +} diff --git a/Client/Client/util/TLS.h b/Client/Client/util/TLS.h new file mode 100644 index 00000000..4d25f7ec --- /dev/null +++ b/Client/Client/util/TLS.h @@ -0,0 +1,15 @@ +#pragma once +#include + +class CTLS +{ +public: + CTLS(LPCTSTR helpString); + ~CTLS(); +public: + void Set(LPVOID value); + LPVOID Get(); +private: + DWORD m_tlsIndex; + CString m_helpString; +}; diff --git a/VNOC/util/TaskThread.cpp b/Client/Client/util/TaskThread.cpp similarity index 53% rename from VNOC/util/TaskThread.cpp rename to Client/Client/util/TaskThread.cpp index 318cb5bf..c5b2b031 100644 --- a/VNOC/util/TaskThread.cpp +++ b/Client/Client/util/TaskThread.cpp @@ -1,144 +1,255 @@ -#include "stdafx.h" -#include "TaskThread.h" - -VOID _BackendTaskThreadEntry( LPVOID param ) -{ - Thread::CTaskThread* p=static_cast(param); - if (p) - { - p->ThreadPrepare(); - p->ThreadMain(); - } - p->OnThreadQuit(); -} - - -namespace Thread -{ - CTaskThread::CTaskThread( BOOL bStartNow ) : m_taskListLock(3000) - { - m_bAlive = FALSE; - m_bForceQuit = FALSE; - m_bPaused = TRUE; - m_hThread = 0; - m_newTaskAvaliable.Create(NULL,FALSE,FALSE,NULL); - if (bStartNow) - { - Start(); - } - m_performance.MileStone(_T("")); - } - - VOID CTaskThread::Start() - { - if (!IsAlive()) - { - _beginthread(_BackendTaskThreadEntry,0,this); - } - } - - CTaskThread::~CTaskThread( VOID ) - { - m_performance.MileStone(_T("ʼ")); - m_bAlive = FALSE; - m_newTaskAvaliable.Set(); - WaitForSingleObject(m_hThread,10000); - CloseHandle(m_hThread); - m_performance.MileStone(_T("")); - } - - VOID CTaskThread::OnThreadQuit() - { - m_bAlive = FALSE; // ϵ϶ѾFALSE - } - - VOID CTaskThread::PostEmergentTask( CTask * pTask ) - { - Util::CAutoTimedCS Guard(m_taskListLock); - if (Guard.IsTimedOut()) - { - return; - } - m_taskList.push_front(pTask); - m_newTaskAvaliable.Set(); - } - - VOID CTaskThread::PostTask( Thread::CTask * pTask ) - { - Util::CAutoTimedCS Guard(m_taskListLock); - if (Guard.IsTimedOut()) - { - return; - } - m_taskList.push_back(pTask); - m_newTaskAvaliable.Set(); - } - - VOID CTaskThread::ThreadPrepare() - { - m_hThread = GetCurrentThread(); - m_bAlive = TRUE; - m_bPaused = FALSE; - } - - VOID CTaskThread::ThreadMain() - { - BOOL bQuit; - Thread::CTask *p; - TaskList::iterator i; - do - { - bQuit = FALSE; - while(!bQuit) - { - p = NULL; - m_taskListLock.Enter(); - i = m_taskList.begin(); - if (i == m_taskList.end()) - { // - bQuit = TRUE; - } - else - { - p = *i; - m_taskList.pop_front(); - } - m_taskListLock.Leave(); - if (p) - { - p->Run(); //ִ - delete p; - } - } - WaitForSingleObject(m_newTaskAvaliable,INFINITE); - while (m_bPaused) - { - WaitForSingleObject(m_newTaskAvaliable,INFINITE); - } - if (!m_bAlive) - { - if (m_bForceQuit) - { - break; - } - } - } while (1); - } - - INT CTaskThread::WaitingTaskNumber() - { - return static_cast(m_taskList.size()); - } - - VOID CTaskThread::Pause() - { - m_bPaused = TRUE; - } - - VOID CTaskThread::Resume() - { - m_bPaused = FALSE; - m_newTaskAvaliable.Set(); - } - -} \ No newline at end of file +#include "TaskThread.h" + +VOID _BackendTaskThreadEntry( LPVOID param ) +{ + Thread::CTaskThread* p=static_cast(param); + if (p) + { + p->ThreadPrepare(); + p->ThreadMain(); + } + p->OnThreadQuit(); +} + + +namespace Thread +{ + CTaskThread::CTaskThread( BOOL bStartNow ) : m_taskListLock(3000) + { + m_bAlive = FALSE; + m_bForceQuit = FALSE; + m_bPaused = TRUE; + m_hThread = 0; + m_newTaskAvaliable.Create(NULL,FALSE,FALSE,NULL); + if (bStartNow) + { + Start(); + } + m_performance.MileStone(_T("")); + } + + VOID CTaskThread::Start() + { + if (!IsAlive()) + { + _beginthread(_BackendTaskThreadEntry,0,this); + } + } + + CTaskThread::~CTaskThread( VOID ) + { + m_performance.MileStone(_T("ʼ")); + m_bAlive = FALSE; + m_newTaskAvaliable.Set(); + WaitForSingleObject(m_hThread,10000); + CloseHandle(m_hThread); + m_performance.MileStone(_T("")); + } + + VOID CTaskThread::OnThreadQuit() + { + m_bAlive = FALSE; // ϵ϶ѾFALSE + } + + VOID CTaskThread::PostEmergentTask( CTask * pTask ) + { + Util::CAutoTimedCS Guard(m_taskListLock); + if (Guard.IsTimedOut()) + { + return; + } + m_taskList.push_front(pTask); + m_newTaskAvaliable.Set(); + } + + VOID CTaskThread::PostTask( Thread::CTask * pTask ) + { + Util::CAutoTimedCS Guard(m_taskListLock); + if (Guard.IsTimedOut()) + { + return; + } + m_taskList.push_back(pTask); + m_newTaskAvaliable.Set(); + } + + VOID CTaskThread::ThreadPrepare() + { + m_hThread = GetCurrentThread(); + m_bAlive = TRUE; + m_bPaused = FALSE; + } + + VOID CTaskThread::ThreadMain() + { + BOOL bQuit; + Thread::CTask *p; + TaskList::iterator i; + do + { + bQuit = FALSE; + while(!bQuit) + { + p = NULL; + m_taskListLock.Enter(); + i = m_taskList.begin(); + if (i == m_taskList.end()) + { // + bQuit = TRUE; + } + else + { + p = *i; + m_taskList.pop_front(); + } + m_taskListLock.Leave(); + if (p) + { + p->Run(); //ִ + delete p; + } + } + WaitForSingleObject(m_newTaskAvaliable,INFINITE); + while (m_bPaused) + { + WaitForSingleObject(m_newTaskAvaliable,INFINITE); + } + if (!m_bAlive) + { + if (m_bForceQuit) + { + break; + } + } + } while (1); + } + + INT CTaskThread::WaitingTaskNumber() + { + return static_cast(m_taskList.size()); + } + + VOID CTaskThread::Pause() + { + m_bPaused = TRUE; + } + + VOID CTaskThread::Resume() + { + m_bPaused = FALSE; + m_newTaskAvaliable.Set(); + } + + + +} + +////////////////////////////////////////////////////////////////////////// + +namespace Thread +{ + VOID _BackendTaskWinThreadEntry( LPVOID param ) + { + Thread::CTaskWinThread* p=static_cast(param); + if (p) + { + p->ThreadPrepare(); + p->ThreadMain(); + } + p->OnThreadQuit(); + } + + CTaskWinThread::CTaskWinThread( BOOL bStartNow/*=TRUE*/ ) : m_taskListLock(3000) + { + m_bAlive = FALSE; + m_bForceQuit = FALSE; + m_bPaused = TRUE; + m_hThread = 0; + m_newTaskAvaliable.Create(NULL,FALSE,FALSE,NULL); + if (bStartNow) + { + Start(); + } + m_performance.MileStone(_T("")); + } + + CTaskWinThread::~CTaskWinThread( VOID ) + { + m_performance.MileStone(_T("ʼ")); + m_bAlive = FALSE; + m_newTaskAvaliable.Set(); + WaitForSingleObject(m_hThread,10000); + CloseHandle(m_hThread); + m_performance.MileStone(_T("")); + } + + VOID CTaskWinThread::Start() + { + if (!IsAlive()) + { + _beginthread(_BackendTaskThreadEntry,0,this); + } + } + + VOID CTaskWinThread::Pause() + { + m_bPaused = TRUE; + } + + VOID CTaskWinThread::Resume() + { + m_bPaused = FALSE; + m_newTaskAvaliable.Set(); + } + + VOID CTaskWinThread::PostTask( CTask * pTask ) + { + Util::CAutoTimedCS Guard(m_taskListLock); + if (Guard.IsTimedOut()) + { + return; + } + m_taskList.push_back(pTask); + m_newTaskAvaliable.Set(); + } + + INT CTaskWinThread::WaitingTaskNumber() + { + return static_cast(m_taskList.size()); + } + + VOID CTaskWinThread::OnThreadQuit() + { + m_bAlive = FALSE; // ϵ϶ѾFALSE + } + + VOID CTaskWinThread::ThreadPrepare() + { + m_hThread = GetCurrentThread(); + m_bAlive = TRUE; + m_bPaused = FALSE; + } + + VOID CTaskWinThread::PostEmergentTask( CTask * pTask ) + { + Util::CAutoTimedCS Guard(m_taskListLock); + if (Guard.IsTimedOut()) + { + return; + } + m_taskList.push_front(pTask); + m_newTaskAvaliable.Set(); + } + + VOID CTaskWinThread::ThreadMain() + { + m_hWnd = CreateWindow(_T(""),_T(""),WS_OVERLAPPED, + 0,0,0,0,HWND_MESSAGE,0,0,0); + if (m_hWnd == INVALID_HANDLE_VALUE) + { + ATLASSERT(FALSE && "Create SocketWindow Fail"); + } + MessageBox(NULL,_T("ddd"),0,0); + } + +} diff --git a/VNOC/util/TaskThread.h b/Client/Client/util/TaskThread.h similarity index 51% rename from VNOC/util/TaskThread.h rename to Client/Client/util/TaskThread.h index 515b6c58..2b6e517f 100644 --- a/VNOC/util/TaskThread.h +++ b/Client/Client/util/TaskThread.h @@ -1,51 +1,96 @@ -#pragma once -#include "ThreadDefine.h" -#include "queue" -#include "list" -#include "atlstr.h" -#include "util.h" -#include "Performance.h" - -VOID _BackendTaskThreadEntry(LPVOID param); - -namespace Thread -{ - typedef std::list TaskList; - - class CTaskThread - { - public: - CTaskThread(BOOL bStartNow=TRUE); - ~CTaskThread(VOID); - - public: - VOID Start(); - VOID Pause(); - VOID Resume(); - VOID SetForceQuit(BOOL bForceSuspendThreadWhenDestruct){m_bForceQuit = bForceSuspendThreadWhenDestruct;}; - HANDLE GetThreadHandle() const { return m_hThread; } - BOOL IsAlive() const { return m_bAlive; } - - // 뱣֤߳Ѿ(캯trueùStart) - VOID PostEmergentTask(CTask * pTask); - VOID PostTask(CTask * pTask); - INT WaitingTaskNumber(); - - _private: - VOID OnThreadQuit(); - VOID ThreadPrepare(); - VOID ThreadMain(); - private: - Util::CTimedCriticalSection m_taskListLock; - volatile BOOL m_bAlive; - volatile BOOL m_bForceQuit; - volatile BOOL m_bPaused; - HANDLE m_hThread; - ATL::CEvent m_newTaskAvaliable; - TaskList m_taskList; - - Performance::CPerformance m_performance; - private: - DISALLOW_COPY_AND_ASSIGN(CTaskThread); - }; +#pragma once +#include "ThreadDefine.h" +#include "queue" +#include "list" +#include "atlstr.h" +#include "util.h" +#include "Performance.h" + +VOID _BackendTaskThreadEntry(LPVOID param); + +namespace Thread +{ + typedef std::list TaskList; + + class CTaskThread + { + public: + CTaskThread(BOOL bStartNow=TRUE); + ~CTaskThread(VOID); + + public: + VOID Start(); + VOID Pause(); + VOID Resume(); + VOID SetForceQuit(BOOL bForceSuspendThreadWhenDestruct){m_bForceQuit = bForceSuspendThreadWhenDestruct;}; + HANDLE GetThreadHandle() const { return m_hThread; } + BOOL IsAlive() const { return m_bAlive; } + + // 뱣֤߳Ѿ(캯trueùStart) + VOID PostEmergentTask(CTask * pTask); + VOID PostTask(CTask * pTask); + INT WaitingTaskNumber(); + + _private: + VOID OnThreadQuit(); + VOID ThreadPrepare(); + VOID ThreadMain(); + private: + Util::CTimedCriticalSection m_taskListLock; + volatile BOOL m_bAlive; + volatile BOOL m_bForceQuit; + volatile BOOL m_bPaused; + HANDLE m_hThread; + ATL::CEvent m_newTaskAvaliable; + TaskList m_taskList; + + Performance::CPerformance m_performance; + private: + DISALLOW_COPY_AND_ASSIGN(CTaskThread); + }; +} + +//TODO: ӦCTaskThreadһչʱϢѭʱȴ + +namespace Thread +{ + typedef std::list TaskList; + + class CTaskWinThread + { + public: + CTaskWinThread(BOOL bStartNow=TRUE); + ~CTaskWinThread(VOID); + + public: + VOID Start(); + VOID Pause(); + VOID Resume(); + VOID SetForceQuit(BOOL bForceSuspendThreadWhenDestruct){m_bForceQuit = bForceSuspendThreadWhenDestruct;}; + HANDLE GetThreadHandle() const { return m_hThread; } + BOOL IsAlive() const { return m_bAlive; } + + // 뱣֤߳Ѿ(캯trueùStart) + VOID PostTask(CTask * pTask); + VOID PostEmergentTask(CTask * pTask); + INT WaitingTaskNumber(); + + _private: + VOID OnThreadQuit(); + VOID ThreadPrepare(); + VOID ThreadMain(); + private: + Util::CTimedCriticalSection m_taskListLock; + volatile BOOL m_bAlive; + volatile BOOL m_bForceQuit; + volatile BOOL m_bPaused; + HANDLE m_hThread; + HWND m_hWnd; + ATL::CEvent m_newTaskAvaliable; + TaskList m_taskList; + + Performance::CPerformance m_performance; + private: + DISALLOW_COPY_AND_ASSIGN(CTaskWinThread); + }; } \ No newline at end of file diff --git a/VNOC/util/ThreadDefine.h b/Client/Client/util/ThreadDefine.h similarity index 96% rename from VNOC/util/ThreadDefine.h rename to Client/Client/util/ThreadDefine.h index 290df839..53cdc704 100644 --- a/VNOC/util/ThreadDefine.h +++ b/Client/Client/util/ThreadDefine.h @@ -1,452 +1,452 @@ -#pragma once -#define WIN32_LEAN_AND_MEAN -#include "windows.h" - -namespace Thread -{ - class Tuple0 - { - public: - }; - - template - class Tuple1 - { - public: - Tuple1(): arg(T1()) { } - - Tuple1(const T1& t1) - { - arg = t1; - } - T1 arg; - }; - - template - class Tuple2 - { - public: - Tuple2() : arg1(T1()), arg2(T2()) { } - - Tuple2(const T1& t1, const T2& t2) - { - arg1 = t1; - arg2 = t2; - } - T1 arg1; - T2 arg2; - }; - - template - class Tuple3 - { - public: - Tuple3() : arg1(T1()), arg2(T2()), arg3(T3()) { } - - Tuple3(const T1& t1, const T2& t2, const T3& t3) - { - arg1 = t1; - arg2 = t2; - arg3 = t3; - } - T1 arg1; - T2 arg2; - T3 arg3; - }; - - template - class Tuple4 - { - public: - Tuple4() : arg1(T1()), arg2(T2()), arg3(T3()), arg4(T4()) { } - - Tuple4(const T1& t1,const T2& t2,const T3& t3, const T4& t4) - { - arg1 = t1; - arg2 = t2; - arg3 = t3; - arg4 = t4; - } - T1 arg1; - T2 arg2; - T3 arg3; - T4 arg4; - }; - - template - class Tuple5 - { - public: - Tuple5() : arg1(T1()), arg2(T2()), arg3(T3()), arg4(T4()), arg5(T5()) { } - - Tuple5(const T1& t1,const T2& t2,const T3& t3, const T4& t4, const T5& t5) - { - arg1 = t1; - arg2 = t2; - arg3 = t3; - arg4 = t4; - arg5 = t5; - } - T1 arg1; - T2 arg2; - T3 arg3; - T4 arg4; - T5 arg5; - }; - - template - class Tuple6 - { - public: - Tuple6() : arg1(T1()), arg2(T2()), arg3(T3()), arg4(T4()), arg5(T5()), arg6(T6()) { } - - Tuple6(const T1& t1,const T2& t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6) - { - arg1 = t1; - arg2 = t2; - arg3 = t3; - arg4 = t4; - arg5 = t5; - arg6 = t6; - } - T1 arg1; - T2 arg2; - T3 arg3; - T4 arg4; - T5 arg5; - T6 arg6; - }; - - template - class Tuple7 - { - public: - Tuple7() : arg1(T1()), arg2(T2()), arg3(T3()), arg4(T4()), arg5(T5()), arg6(T6()), arg7(T7()) { } - - Tuple7(const T1& t1,const T2& t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7) - { - arg1 = t1; - arg2 = t2; - arg3 = t3; - arg4 = t4; - arg5 = t5; - arg6 = t6; - arg7 = t7; - } - T1 arg1; - T2 arg2; - T3 arg3; - T4 arg4; - T5 arg5; - T6 arg6; - T7 arg7; - }; - - template - class Tuple8 - { - public: - Tuple8() : arg1(T1()), arg2(T2()), arg3(T3()), arg4(T4()), arg5(T5()), arg6(T6()), arg7(T7()), arg8(T8()) { } - - Tuple8(const T1& t1,const T2& t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8) - { - arg1 = t1; - arg2 = t2; - arg3 = t3; - arg4 = t4; - arg5 = t5; - arg6 = t6; - arg7 = t7; - arg8 = t8; - } - T1 arg1; - T2 arg2; - T3 arg3; - T4 arg4; - T5 arg5; - T6 arg6; - T7 arg7; - T8 arg8; - }; - - template - class Tuple9 - { - public: - Tuple9() : arg1(T1()), arg2(T2()), arg3(T3()), arg4(T4()), arg5(T5()), arg6(T6()), arg7(T7()), arg8(T8()), arg9(T9()) { } - - Tuple9(const T1& t1,const T2& t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8, const T9& t9) - { - arg1 = t1; - arg2 = t2; - arg3 = t3; - arg4 = t4; - arg5 = t5; - arg6 = t6; - arg7 = t7; - arg8 = t8; - arg9 = t9; - } - T1 arg1; - T2 arg2; - T3 arg3; - T4 arg4; - T5 arg5; - T6 arg6; - T7 arg7; - T8 arg8; - T9 arg9; - }; - - inline Tuple0 * GetTuple() - { - return new Tuple0; - } - - template - Tuple1 * GetTuple(const T1 &t1) - { - return new Tuple1(t1); - } - - template - Tuple2 * GetTuple(const T1 &t1, const T2 &t2) - { - return new Tuple2(t1, t2); - } - - template - Tuple3 * GetTuple(const T1 &t1, const T2 &t2, const T3& t3) - { - return new Tuple3(t1, t2, t3); - } - - template - Tuple4 * GetTuple(const T1 &t1, const T2 &t2,const T3& t3, const T4& t4) - { - return new Tuple4(t1, t2, t3, t4); - } - - template - Tuple5 * GetTuple(const T1 &t1, const T2 &t2,const T3& t3, const T4& t4, const T5& t5) - { - return new Tuple5(t1, t2, t3, t4, t5); - } - - template - Tuple6 * GetTuple(const T1 &t1, const T2 &t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6) - { - return new Tuple6(t1, t2, t3, t4, t5, t6); - } - - template - Tuple7 * GetTuple(const T1 &t1, const T2 &t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7) - { - return new Tuple7(t1, t2, t3, t4, t5, t6, t7); - } - - template - Tuple8 * GetTuple(const T1 &t1, const T2 &t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8) - { - return new Tuple8(t1, t2, t3, t4, t5, t6, t7, t8); - } - - template - Tuple9 * GetTuple(const T1 &t1, const T2 &t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8, const T9& t9) - { - return new Tuple9(t1, t2, t3, t4, t5, t6, t7, t8, t9); - } - - class CTask - { - public: - CTask(VOID) {} - virtual ~CTask(VOID) {} - - public: - virtual VOID Run() = 0; - }; - - template - VOID RunFunction(TObj* pObj, TpFunc pFunc , TParam* param) - { - - } - - template - class CPtrTaskBase : public Thread::CTask - { - public: - CPtrTaskBase(TObj * pObj) : m_pObj(pObj) - { - } - virtual ~CPtrTaskBase() - { - } - - VOID SetObj(TObj * pObj) - { - m_pObj = pObj; - } - - protected: - TObj* m_pObj; - }; - - template - class CPtrTask : public CPtrTaskBase - { - public: - CPtrTask(TObj* pObj, TpFunc pFunc , TParam* param) - : CPtrTaskBase(pObj) - { - m_pFunc = pFunc; - m_param = param; - } - ~CPtrTask() - { - if (m_param) - { - delete m_param; - } - } - VOID Run() - { - RunFunction(m_pObj, m_pFunc, m_param ); - } - private: - TpFunc m_pFunc; - TParam* m_param; - }; - - template - VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple0* pTuple0) - { - (pObj->*pFunc)(); - } - - template - VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple1* pTuple1) - { - (pObj->*pFunc)(pTuple1->arg); - } - - template - VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple2* pTuple2) - { - (pObj->*pFunc)(pTuple2->arg1, pTuple2->arg2); - } - - template - VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple3* pTuple3) - { - (pObj->*pFunc)(pTuple3->arg1, pTuple3->arg2, pTuple3->arg3); - } - - template - VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple4* pTuple4) - { - (pObj->*pFunc)(pTuple4->arg1, pTuple4->arg2, pTuple4->arg3, pTuple4->arg4); - } - - template - VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple5* pTuple5) - { - (pObj->*pFunc)(pTuple5->arg1, pTuple5->arg2, pTuple5->arg3, pTuple5->arg4, pTuple5->arg5); - } - - template - VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple6* pTuple6) - { - (pObj->*pFunc)(pTuple6->arg1, pTuple6->arg2, pTuple6->arg3, pTuple6->arg4, pTuple6->arg5, pTuple6->arg6); - } - - template - VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple7* pTuple7) - { - (pObj->*pFunc)(pTuple7->arg1, pTuple7->arg2, pTuple7->arg3, pTuple7->arg4, pTuple7->arg5, pTuple7->arg6, pTuple7->arg7); - } - - template - VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple8* pTuple8) - { - (pObj->*pFunc)(pTuple8->arg1, pTuple8->arg2, pTuple8->arg3, pTuple8->arg4, pTuple8->arg5, pTuple8->arg6, pTuple8->arg7, pTuple8->arg8); - } - - template - VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple9* pTuple9) - { - (pObj->*pFunc)(pTuple9->arg1, pTuple9->arg2, pTuple9->arg3, pTuple9->arg4, pTuple9->arg5, pTuple9->arg6, pTuple9->arg7, pTuple9->arg8, pTuple9->arg9); - } - - // 0 - template - CTask* CreatePtrTask(TObj* pObj, TpFunc func) - { - return new CPtrTask< TObj , TpFunc , Tuple0>( pObj, func, GetTuple()); - } - - // 1 - template - CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1) - { - return new CPtrTask >(pObj, func, GetTuple(t1)); - } - - // 2 - template - CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2) - { - return new CPtrTask >(pObj, func, GetTuple(t1, t2)); - } - - // 3 - template - CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2, const T3&t3) - { - return new CPtrTask >(pObj, func, GetTuple(t1, t2,t3)); - } - - // 4 - template - CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2, const T3&t3, const T4&t4) - { - return new CPtrTask >(pObj, func, GetTuple(t1, t2, t3, t4)); - } - - // 5 - template - CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2, const T3&t3, const T4&t4, const T5& t5) - { - return new CPtrTask >(pObj, func, GetTuple(t1, t2, t3, t4, t5)); - } - - // 6 - template - CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2, const T3&t3, const T4&t4, const T5& t5, const T6& t6) - { - return new CPtrTask >(pObj, func, GetTuple(t1, t2, t3, t4, t5, t6)); - } - - // 7 - template - CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2, const T3&t3, const T4&t4, const T5& t5, const T6& t6, const T7& t7) - { - return new CPtrTask >(pObj, func, GetTuple(t1, t2, t3, t4, t5, t6, t7)); - } - - // 8 - template - CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2, const T3&t3, const T4&t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8) - { - return new CPtrTask >(pObj, func, GetTuple(t1, t2, t3, t4, t5, t6, t7, t8)); - } - - // 9 - template - CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2, const T3&t3, const T4&t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8, const T9& t9) - { - return new CPtrTask >(pObj, func, GetTuple(t1, t2, t3, t4, t5, t6, t7, t8, t9)); - } - +#pragma once +#define WIN32_LEAN_AND_MEAN +#include "windows.h" + +namespace Thread +{ + class Tuple0 + { + public: + }; + + template + class Tuple1 + { + public: + Tuple1(): arg(T1()) { } + + Tuple1(const T1& t1) + { + arg = t1; + } + T1 arg; + }; + + template + class Tuple2 + { + public: + Tuple2() : arg1(T1()), arg2(T2()) { } + + Tuple2(const T1& t1, const T2& t2) + { + arg1 = t1; + arg2 = t2; + } + T1 arg1; + T2 arg2; + }; + + template + class Tuple3 + { + public: + Tuple3() : arg1(T1()), arg2(T2()), arg3(T3()) { } + + Tuple3(const T1& t1, const T2& t2, const T3& t3) + { + arg1 = t1; + arg2 = t2; + arg3 = t3; + } + T1 arg1; + T2 arg2; + T3 arg3; + }; + + template + class Tuple4 + { + public: + Tuple4() : arg1(T1()), arg2(T2()), arg3(T3()), arg4(T4()) { } + + Tuple4(const T1& t1,const T2& t2,const T3& t3, const T4& t4) + { + arg1 = t1; + arg2 = t2; + arg3 = t3; + arg4 = t4; + } + T1 arg1; + T2 arg2; + T3 arg3; + T4 arg4; + }; + + template + class Tuple5 + { + public: + Tuple5() : arg1(T1()), arg2(T2()), arg3(T3()), arg4(T4()), arg5(T5()) { } + + Tuple5(const T1& t1,const T2& t2,const T3& t3, const T4& t4, const T5& t5) + { + arg1 = t1; + arg2 = t2; + arg3 = t3; + arg4 = t4; + arg5 = t5; + } + T1 arg1; + T2 arg2; + T3 arg3; + T4 arg4; + T5 arg5; + }; + + template + class Tuple6 + { + public: + Tuple6() : arg1(T1()), arg2(T2()), arg3(T3()), arg4(T4()), arg5(T5()), arg6(T6()) { } + + Tuple6(const T1& t1,const T2& t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6) + { + arg1 = t1; + arg2 = t2; + arg3 = t3; + arg4 = t4; + arg5 = t5; + arg6 = t6; + } + T1 arg1; + T2 arg2; + T3 arg3; + T4 arg4; + T5 arg5; + T6 arg6; + }; + + template + class Tuple7 + { + public: + Tuple7() : arg1(T1()), arg2(T2()), arg3(T3()), arg4(T4()), arg5(T5()), arg6(T6()), arg7(T7()) { } + + Tuple7(const T1& t1,const T2& t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7) + { + arg1 = t1; + arg2 = t2; + arg3 = t3; + arg4 = t4; + arg5 = t5; + arg6 = t6; + arg7 = t7; + } + T1 arg1; + T2 arg2; + T3 arg3; + T4 arg4; + T5 arg5; + T6 arg6; + T7 arg7; + }; + + template + class Tuple8 + { + public: + Tuple8() : arg1(T1()), arg2(T2()), arg3(T3()), arg4(T4()), arg5(T5()), arg6(T6()), arg7(T7()), arg8(T8()) { } + + Tuple8(const T1& t1,const T2& t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8) + { + arg1 = t1; + arg2 = t2; + arg3 = t3; + arg4 = t4; + arg5 = t5; + arg6 = t6; + arg7 = t7; + arg8 = t8; + } + T1 arg1; + T2 arg2; + T3 arg3; + T4 arg4; + T5 arg5; + T6 arg6; + T7 arg7; + T8 arg8; + }; + + template + class Tuple9 + { + public: + Tuple9() : arg1(T1()), arg2(T2()), arg3(T3()), arg4(T4()), arg5(T5()), arg6(T6()), arg7(T7()), arg8(T8()), arg9(T9()) { } + + Tuple9(const T1& t1,const T2& t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8, const T9& t9) + { + arg1 = t1; + arg2 = t2; + arg3 = t3; + arg4 = t4; + arg5 = t5; + arg6 = t6; + arg7 = t7; + arg8 = t8; + arg9 = t9; + } + T1 arg1; + T2 arg2; + T3 arg3; + T4 arg4; + T5 arg5; + T6 arg6; + T7 arg7; + T8 arg8; + T9 arg9; + }; + + inline Tuple0 * GetTuple() + { + return new Tuple0; + } + + template + Tuple1 * GetTuple(const T1 &t1) + { + return new Tuple1(t1); + } + + template + Tuple2 * GetTuple(const T1 &t1, const T2 &t2) + { + return new Tuple2(t1, t2); + } + + template + Tuple3 * GetTuple(const T1 &t1, const T2 &t2, const T3& t3) + { + return new Tuple3(t1, t2, t3); + } + + template + Tuple4 * GetTuple(const T1 &t1, const T2 &t2,const T3& t3, const T4& t4) + { + return new Tuple4(t1, t2, t3, t4); + } + + template + Tuple5 * GetTuple(const T1 &t1, const T2 &t2,const T3& t3, const T4& t4, const T5& t5) + { + return new Tuple5(t1, t2, t3, t4, t5); + } + + template + Tuple6 * GetTuple(const T1 &t1, const T2 &t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6) + { + return new Tuple6(t1, t2, t3, t4, t5, t6); + } + + template + Tuple7 * GetTuple(const T1 &t1, const T2 &t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7) + { + return new Tuple7(t1, t2, t3, t4, t5, t6, t7); + } + + template + Tuple8 * GetTuple(const T1 &t1, const T2 &t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8) + { + return new Tuple8(t1, t2, t3, t4, t5, t6, t7, t8); + } + + template + Tuple9 * GetTuple(const T1 &t1, const T2 &t2,const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8, const T9& t9) + { + return new Tuple9(t1, t2, t3, t4, t5, t6, t7, t8, t9); + } + + class CTask + { + public: + CTask(VOID) {} + virtual ~CTask(VOID) {} + + public: + virtual VOID Run() = 0; + }; + + template + VOID RunFunction(TObj* pObj, TpFunc pFunc , TParam* param) + { + + } + + template + class CPtrTaskBase : public Thread::CTask + { + public: + CPtrTaskBase(TObj * pObj) : m_pObj(pObj) + { + } + virtual ~CPtrTaskBase() + { + } + + VOID SetObj(TObj * pObj) + { + m_pObj = pObj; + } + + protected: + TObj* m_pObj; + }; + + template + class CPtrTask : public CPtrTaskBase + { + public: + CPtrTask(TObj* pObj, TpFunc pFunc , TParam* param) + : CPtrTaskBase(pObj) + { + m_pFunc = pFunc; + m_param = param; + } + ~CPtrTask() + { + if (m_param) + { + delete m_param; + } + } + VOID Run() + { + RunFunction(m_pObj, m_pFunc, m_param ); + } + private: + TpFunc m_pFunc; + TParam* m_param; + }; + + template + VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple0* pTuple0) + { + (pObj->*pFunc)(); + } + + template + VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple1* pTuple1) + { + (pObj->*pFunc)(pTuple1->arg); + } + + template + VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple2* pTuple2) + { + (pObj->*pFunc)(pTuple2->arg1, pTuple2->arg2); + } + + template + VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple3* pTuple3) + { + (pObj->*pFunc)(pTuple3->arg1, pTuple3->arg2, pTuple3->arg3); + } + + template + VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple4* pTuple4) + { + (pObj->*pFunc)(pTuple4->arg1, pTuple4->arg2, pTuple4->arg3, pTuple4->arg4); + } + + template + VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple5* pTuple5) + { + (pObj->*pFunc)(pTuple5->arg1, pTuple5->arg2, pTuple5->arg3, pTuple5->arg4, pTuple5->arg5); + } + + template + VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple6* pTuple6) + { + (pObj->*pFunc)(pTuple6->arg1, pTuple6->arg2, pTuple6->arg3, pTuple6->arg4, pTuple6->arg5, pTuple6->arg6); + } + + template + VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple7* pTuple7) + { + (pObj->*pFunc)(pTuple7->arg1, pTuple7->arg2, pTuple7->arg3, pTuple7->arg4, pTuple7->arg5, pTuple7->arg6, pTuple7->arg7); + } + + template + VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple8* pTuple8) + { + (pObj->*pFunc)(pTuple8->arg1, pTuple8->arg2, pTuple8->arg3, pTuple8->arg4, pTuple8->arg5, pTuple8->arg6, pTuple8->arg7, pTuple8->arg8); + } + + template + VOID RunFunction(TObj* pObj, TpFunc pFunc, Tuple9* pTuple9) + { + (pObj->*pFunc)(pTuple9->arg1, pTuple9->arg2, pTuple9->arg3, pTuple9->arg4, pTuple9->arg5, pTuple9->arg6, pTuple9->arg7, pTuple9->arg8, pTuple9->arg9); + } + + // 0 + template + CTask* CreatePtrTask(TObj* pObj, TpFunc func) + { + return new CPtrTask< TObj , TpFunc , Tuple0>( pObj, func, GetTuple()); + } + + // 1 + template + CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1) + { + return new CPtrTask >(pObj, func, GetTuple(t1)); + } + + // 2 + template + CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2) + { + return new CPtrTask >(pObj, func, GetTuple(t1, t2)); + } + + // 3 + template + CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2, const T3&t3) + { + return new CPtrTask >(pObj, func, GetTuple(t1, t2,t3)); + } + + // 4 + template + CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2, const T3&t3, const T4&t4) + { + return new CPtrTask >(pObj, func, GetTuple(t1, t2, t3, t4)); + } + + // 5 + template + CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2, const T3&t3, const T4&t4, const T5& t5) + { + return new CPtrTask >(pObj, func, GetTuple(t1, t2, t3, t4, t5)); + } + + // 6 + template + CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2, const T3&t3, const T4&t4, const T5& t5, const T6& t6) + { + return new CPtrTask >(pObj, func, GetTuple(t1, t2, t3, t4, t5, t6)); + } + + // 7 + template + CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2, const T3&t3, const T4&t4, const T5& t5, const T6& t6, const T7& t7) + { + return new CPtrTask >(pObj, func, GetTuple(t1, t2, t3, t4, t5, t6, t7)); + } + + // 8 + template + CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2, const T3&t3, const T4&t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8) + { + return new CPtrTask >(pObj, func, GetTuple(t1, t2, t3, t4, t5, t6, t7, t8)); + } + + // 9 + template + CTask* CreatePtrTask(TObj* pObj, TpFunc func, const T1& t1, const T2&t2, const T3&t3, const T4&t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8, const T9& t9) + { + return new CPtrTask >(pObj, func, GetTuple(t1, t2, t3, t4, t5, t6, t7, t8, t9)); + } + } // end namespace \ No newline at end of file diff --git a/Client/Client/util/bind.hpp b/Client/Client/util/bind.hpp new file mode 100644 index 00000000..5ca2925b --- /dev/null +++ b/Client/Client/util/bind.hpp @@ -0,0 +1,40 @@ +#pragma once +////////////////////////////////////////////////////////////////////////// +// C++09߰汾bindʵ + +template +struct invoker_base { + virtual R invoke(Args...) = 0; + virtual ~invoker_base() { } +}; + +template +struct functor_invoker : public invoker_base +{ + explicit functor_invoker(F f) : f(f) { } + R invoke(Args... args) { return f(args...); } +private: + F f; +}; + +template +class function; + +template +class function +{ +public: + template + function(F f) : invoker(0) + { + invoker = new functor_invoker(f); + } + + R operator()(Args... args) const + { + return invoker->invoke(args...); + } + +private: + invoker_base* invoker; +}; \ No newline at end of file diff --git a/VNOC/util/util.cpp b/Client/Client/util/util.cpp similarity index 83% rename from VNOC/util/util.cpp rename to Client/Client/util/util.cpp index 678592e3..c9dfcaec 100644 --- a/VNOC/util/util.cpp +++ b/Client/Client/util/util.cpp @@ -1,576 +1,702 @@ -#include "stdafx.h" -#include "util.h" -#include "MD5.h" - -namespace Util -{ - // ڻUtilʹõĿɸõ - class CUtilData - { - public: - CUtilData() - { - m_pIMalloc = NULL; - SHGetMalloc(&m_pIMalloc); - }; - ~CUtilData() - { - if(m_pIMalloc) - { - m_pIMalloc->Release(); - } - } - public: - LPMALLOC GetLPMALLOC() - { - if (!m_pIMalloc) - { - SHGetMalloc(&m_pIMalloc); - } - return m_pIMalloc; - } - private: - IMalloc *m_pIMalloc; - }Data; -} - -std::wstring Util::String::StringA2W( std::string strA ) -{ - const char *szStr = strA.c_str(); - std::wstring wszStr; - if( NULL == szStr ) - { - return wszStr; - } - DWORD iSize = ::MultiByteToWideChar( CP_ACP, 0, szStr, -1, NULL, 0 ); - wchar_t* p = new wchar_t[iSize+10]; - memset( p, 0, (iSize+10)*sizeof(wchar_t) ); - iSize = ::MultiByteToWideChar( CP_ACP, 0, szStr, -1, p, iSize); - wszStr = p; - delete p; - return wszStr; -} - -std::string Util::String::StringW2A( std::wstring strW ) -{ - const wchar_t *wszStr = strW.c_str(); - std::string szStr; - if( NULL == wszStr ) - { - return szStr; - } - DWORD iSize = ::WideCharToMultiByte( CP_ACP, 0, wszStr, -1, NULL, 0 ,NULL,NULL); - char* p = new char[iSize+10]; - memset( p, 0, (iSize+10)*sizeof(char) ); - iSize = ::WideCharToMultiByte( CP_ACP, 0, wszStr, -1, p, iSize,NULL,NULL); - szStr = p; - delete p; - return szStr; -} - -std::wstring Util::String::StringToWstringNoConvert(std::string strA) -{ - std::wstring strW; - wchar_t *wp; - strW.resize(strA.length()); - wp = const_cast(strW.data()); - memcpy(wp,strA.data(),strA.length()); - return strW; -} - -CStringA Util::String::UnicodeToGBK( CStringW unicode ) -{ - CStringA strGBK = ""; - DWORD dwMinSize = 0; - dwMinSize = WideCharToMultiByte(936, NULL, unicode, unicode.GetLength(),NULL, 0, NULL, FALSE); - strGBK.GetBufferSetLength(dwMinSize); - LPSTR lpszStr = strGBK.GetBuffer(); - INT ok = WideCharToMultiByte(936, NULL, unicode, unicode.GetLength(), lpszStr, dwMinSize, NULL, FALSE); - strGBK.ReleaseBuffer(); - return strGBK; -} - -CStringW Util::String::GBKToUnicode( CStringA gbk ) -{ - CStringW strUnicode; - DWORD dwMinSize = 0; - dwMinSize = MultiByteToWideChar(936, NULL, gbk, gbk.GetLength(),NULL, 0); - strUnicode.GetBufferSetLength(dwMinSize); - LPWSTR lpszStr = strUnicode.GetBuffer(); - INT ok = MultiByteToWideChar(936, NULL, gbk, gbk.GetLength(), lpszStr, dwMinSize); - strUnicode.ReleaseBuffer(); - return strUnicode; -} - -char Util::GetHex( UINT num,BOOL bUpperWord/*=TRUE*/ ) -{ - return num<10? num+'0': num-10+'A'; -} - -inline char Util::FromHex(const char x) -{ - return isdigit(x) ? x-'0' : x-'A'+10; -} - - -wchar_t Util::GetHexW( UINT num,BOOL bUpperWord/*=TRUE*/ ) -{ - return num<10? num+L'0': num-10+L'A'; -} - -CStringA Util::String::Unicode2UTF8(const wchar_t* pUnicode) -{ - ATLASSERT(NULL != pUnicode); - - int targetLen = WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)pUnicode, -1, NULL, 0, NULL, NULL); - - char* pTargetData = new char[targetLen+1]; - memset(pTargetData, 0, targetLen+1); - WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)pUnicode, -1, (char *)pTargetData, targetLen, NULL, NULL); - - CStringA strRet(pTargetData); - delete pTargetData; - return strRet; -} - -CStringW Util::String::UTF82Unicode(const char* pChar) -{ - ATLASSERT(NULL != pChar); - - int targetLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pChar, -1, NULL, 0); - - WCHAR* pTargetData = new WCHAR[targetLen+1]; - memset(pTargetData, 0, (targetLen+1) * sizeof(WCHAR)); - MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pChar, -1, (WCHAR*)pTargetData, targetLen); - - CStringW strRet(pTargetData); - delete pTargetData; - return strRet; -} - - - -CStringW Util::String::Unicode_URLDecode(const char* pStr) -{ - return UTF82Unicode(PHP_URLDecode(pStr)); -} - -CStringW Util::String::Unicode_URLDecode(const wchar_t* pStr) -{ - return UTF82Unicode(PHP_URLDecode(CStringA(pStr))); -} - -CStringA Util::String::PHP_URLDecode( const CStringA& src ) -{ - CStringA decodeURL; - for(int i = 0; i < src.GetLength(); i++) - { - unsigned char ch = 0; - if(src[i]=='%') - { - ATLASSERT(i + 2 < src.GetLength()); - - unsigned char c1 = src[i + 1]; - unsigned char c2 = src[i + 2]; - ch = ((FromHex(c1) << 4) & 0xf0); - ch |= (FromHex(c2) & 0x0f); - i += 2; - } - else if(src[i] == '+') - { - ch = ' '; - } - else - { - ch = src[i]; - } - decodeURL += (unsigned char)ch; - } - - return decodeURL; -} - -CString Util::String::PHP_URLEncode( const CStringA& src ) -{ - CString encodeURL; - - for(int i = 0; i < src.GetLength(); i++) - { - unsigned char c = src.GetAt(i); - if (c == ' ') - { - encodeURL += L'+'; - } - else if ((c < '0' && c != '-' && c != '.') || - (c < 'A' && c > '9') || - (c > 'Z' && c < 'a' && c != '_') || - (c > 'z')) - { - encodeURL += '%'; - encodeURL += GetHex((c & 0xf0) >> 4); - encodeURL += GetHex(c & 0x0f); - } - else - { - encodeURL += c; - } - } - return encodeURL; -} - -BOOL Util::Base64::Encode( ConstReferenceBuffer src,BufferOut &dest ) -{ - BOOL bRet = FALSE; - - if (src==NULL) - { - return FALSE; - } - DWORD dwInputLen = src.GetSize(); - DWORD dwOutputLen = (dwInputLen / 3 + ((dwInputLen % 3)? 1: 0)) * 4 + 1; - - // - const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - //ֵ - - BYTE* data = src.GetBuffer(); - CStringA destStr; - UINT LineLength; - LineLength = 0; - for(int i=0;i<(int)(dwInputLen / 3);i++) - { - destStr += EncodeTable[data[0] >> 2]; - destStr += EncodeTable[((data[0] << 4) | (data[1] >> 4)) & 0x3F]; - destStr += EncodeTable[((data[1] << 2) | (data[2] >> 6)) & 0x3F]; - destStr += EncodeTable[data[2] & 0x3F]; - data += 3; - LineLength += 4; - if(LineLength==76) - { - destStr += "\r\n"; - LineLength=0; - } - } - //ʣݽб - int Mod=dwInputLen % 3; - if(Mod==1) - { - destStr += EncodeTable[(data[0] & 0xFC) >> 2]; - destStr += EncodeTable[((data[0] & 0x03) << 4)]; - destStr += "=="; - } - else if(Mod==2) - { - destStr += EncodeTable[(data[0] & 0xFC) >> 2]; - destStr += EncodeTable[((data[0] & 0x03) << 4) | ((data[1] & 0xF0) >> 4)]; - destStr += EncodeTable[((data[1] & 0x0F) << 2)]; - destStr += "="; - } - dest.Copy(destStr.GetBuffer(destStr.GetLength()),destStr.GetLength()); - destStr.ReleaseBuffer(destStr.GetLength()); - return TRUE; -} - -BOOL Util::MD5::HashMD5( ConstReferenceBuffer buffer,CString &md5 ) -{ - md5 = CMD5Checksum::GetMD5(buffer.GetBuffer(),buffer.GetSize()); - return !md5.IsEmpty(); -} - -BOOL Util::MD5::GetFileMD5( LPCTSTR path, CString& md5 ) -{ - return CMD5Checksum::GetMD5(path, md5); -} - -BOOL Util::Filesys::ForceCreateDir( LPCTSTR path ) -{ -#define MAX_URL 2048 -#define WIN_DIR_SEP_SYM _T("\\") - TCHAR Dir[MAX_URL+1] = {0}; - int nNeed; - LPCTSTR p,pLast; - - _ASSERT( path ); - - pLast = path; - while( NULL!=*pLast ) - { - p=_tcsstr(pLast,WIN_DIR_SEP_SYM); - if( NULL==p ) return FALSE; - nNeed=int(p-path); - if(nNeed>0) - { - memset( Dir,0,sizeof(Dir) ); - _tcsncpy_s( Dir,MAX_URL,path,nNeed ); - BOOL b = CreateDirectory(Dir,NULL); - if (!b) - { - // - // ѴڣôŴĿ¼Դ - // ܾʣĿ¼ܾʣĿ¼δأҲ - // ֮д󡣡 - } - } - p++; - pLast=p; - } - return TRUE; -#undef MAX_URL -#undef WIN_DIR_SEP_SYM -} - -BOOL Util::Filesys::GetSpecialPath( DWORD dwSpecDirID,CString &path ) -{ - BOOL bResult = FALSE; - LPITEMIDLIST pidl; - LPMALLOC pShellMalloc=Util::Data.GetLPMALLOC(); - - if(pShellMalloc != NULL) - { - if(SUCCEEDED(SHGetSpecialFolderLocation(NULL,dwSpecDirID,&pidl))) - { - if(SHGetPathFromIDList(pidl,path.GetBuffer(MAX_PATH))) - { - bResult = TRUE; - } - path.ReleaseBuffer(); - pShellMalloc->Free(pidl); - } - } - return bResult; -} - -bool Util::Filesys::IsFileInUse( LPCTSTR path ) -{ - ATLASSERT(NULL != path); - if(!PathFileExists(path)) - { - return false; - } - - HANDLE handle = CreateFile(path, GENERIC_READ | GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - bool ret = (INVALID_HANDLE_VALUE == handle); - if(!ret) - { - CloseHandle(handle); - } - return ret; -} - -void Util::Time::Time_tToFileTime(time_t t, LPFILETIME pft) -{ - ATLASSERT(NULL != pft); - - // Note that LONGLONG is a 64-bit value - LONGLONG ll; - - ll = Int32x32To64(t, 10000000) + 116444736000000000; - pft->dwLowDateTime = (DWORD)ll; - pft->dwHighDateTime = (DWORD)(ll >> 32); -} - -void Util::Time::FileTimeToTime_t(FILETIME ft, time_t* t) -{ - ATLASSERT(NULL != t); - - LONGLONG ll; - - ULARGE_INTEGER ui; - ui.LowPart = ft.dwLowDateTime; - ui.HighPart = ft.dwHighDateTime; - ll = (LONGLONG(ft.dwHighDateTime) << 32) + ft.dwLowDateTime; - *t = ((LONGLONG)(ui.QuadPart - 116444736000000000) / 10000000); -} - -void Util::Time::Time_tToSystemTime(time_t t, LPSYSTEMTIME pst) -{ - ATLASSERT(NULL != pst); - - FILETIME ft; - Time_tToFileTime(t, &ft); - FileTimeToSystemTime(&ft, pst); -} - -void Util::Time::SystemTimeToTime_t(SYSTEMTIME st, time_t* t) -{ - ATLASSERT(NULL != t); - - FILETIME ft; - SystemTimeToFileTime(&st, &ft); - FileTimeToTime_t(ft, t); -} - -std::wstring Util::Time::TmtToString( tm time ) -{ - CStringW strRes; - strRes.Format(L"%d%d%d%d%d",time.tm_year,time.tm_mon,time.tm_mday,time.tm_hour,time.tm_min,time.tm_sec); - return std::wstring(strRes); -} -__int64 Util::Num::CombineToINT64(DWORD dwHight, DWORD dwLow) -{ - return __int64((__int64(dwHight) << 32) + dwLow); -} - -unsigned __int64 Util::Num::CombineToUINT64(DWORD dwHight, DWORD dwLow) -{ - return unsigned __int64((unsigned __int64(dwHight) << 32) + dwLow); -} - -std::wstring Util::Size::FormatSize(__int64 nSize) -{ - CStringW strRes; - if (nSize=Size_KB && nSize=Size_MB && nSize=Size_GB && nSize=Size_TB) - { - int nSizeGB = (int)(nSize/Size_KB); - strRes.Format(L"%.2f T", (double)nSizeGB/(double)Size_GB); - } - return strRes.GetString(); -} - - -bool Util::Filesys::CheckFileName( const wchar_t * str ) -{ - while(*str != L'\0') - { - if( - *str == L'/' || - *str == L'\\'|| - *str == L';' || - *str == L':' || - *str == L'*' || - *str == L'?' || - *str == L'\"'|| - *str == L'<' || - *str == L'>' - ) - return false; - ++str; - } - return true; -} - -bool Util::Filesys::GetDirFromPath( LPCTSTR path,int &endposIndex ) -{ - int length = (int)_tcslen(path); - for (int n=length-1; n>=0; --n) - { - if (path[n]==L'\\' || path[n]==L'/') - { - endposIndex = n; - return true; - } - } - endposIndex = 0; - return false; -} - -UINT Util::String::ToUINT( LPCTSTR lpstr ) -{ - ATLASSERT(lpstr); - DWORD dw = 0; - if (lpstr) - { - while(*lpstr) - { - dw *= 10; - dw += *lpstr - '0'; - ++lpstr; - } - } - return dw; -} - -namespace Util -{ - CAutoCS::CAutoCS( ::ATL::CCriticalSection &cs ) :m_cs(cs) - { - m_cs.Enter(); - } - CAutoCS::~CAutoCS() - { - m_cs.Leave(); - } - - - CTimedCriticalSection::CTimedCriticalSection( UINT waitTime /*= 1000*/ ) : m_waitTime(waitTime) - { - m_hEvent = CreateEvent(NULL,FALSE,FALSE,NULL); - ATLASSERT(m_hEvent); - m_bTimeout = FALSE; - } - CTimedCriticalSection::~CTimedCriticalSection() - { - if (m_hEvent) - { - CloseHandle(m_hEvent); - } - } - BOOL CTimedCriticalSection::Enter() - { - ATLASSERT(m_hEvent); - DWORD dw = WaitForSingleObject(m_hEvent,m_waitTime); - m_bTimeout = (dw==WAIT_TIMEOUT); - return m_bTimeout; - } - BOOL CTimedCriticalSection::Try() - { - ATLASSERT(m_hEvent); - DWORD dw = WaitForSingleObject(m_hEvent,0); - m_bTimeout = (dw==WAIT_TIMEOUT); - return m_bTimeout; - } - VOID CTimedCriticalSection::Leave() - { - ATLASSERT(m_hEvent); - SetEvent(m_hEvent); - } - BOOL CTimedCriticalSection::IsTimedOut() - { - return m_bTimeout; - } - - - CAutoTimedCS::CAutoTimedCS( CTimedCriticalSection &cs ) :m_cs(cs) - { - m_cs.Enter(); - } - BOOL CAutoTimedCS::IsTimedOut() - { - return m_cs.IsTimedOut(); - } - CAutoTimedCS::~CAutoTimedCS() - { - m_cs.Leave(); - } - - CAutoIndex::CAutoIndex() - { - m_index = 0; - } - CAutoIndex::~CAutoIndex() - {} - UINT CAutoIndex::Get(UINT increase) - { - UINT ret = m_index; - m_index += increase; // - return ret; - } +#include "util.h" +#include "MD5.h" + +namespace Util +{ + // ڻUtilʹõĿɸõ + class CUtilData + { + public: + CUtilData() + { + m_pIMalloc = NULL; + SHGetMalloc(&m_pIMalloc); + }; + ~CUtilData() + { + if(m_pIMalloc) + { + m_pIMalloc->Release(); + } + } + public: + LPMALLOC GetLPMALLOC() + { + if (!m_pIMalloc) + { + SHGetMalloc(&m_pIMalloc); + } + return m_pIMalloc; + } + private: + IMalloc *m_pIMalloc; + }Data; +} + +std::wstring Util::String::StringA2W( std::string strA ) +{ + const char *szStr = strA.c_str(); + std::wstring wszStr; + if( NULL == szStr ) + { + return wszStr; + } + DWORD iSize = ::MultiByteToWideChar( CP_ACP, 0, szStr, -1, NULL, 0 ); + wchar_t* p = new wchar_t[iSize+10]; + memset( p, 0, (iSize+10)*sizeof(wchar_t) ); + iSize = ::MultiByteToWideChar( CP_ACP, 0, szStr, -1, p, iSize); + wszStr = p; + delete p; + return wszStr; +} + +std::string Util::String::StringW2A( std::wstring strW ) +{ + const wchar_t *wszStr = strW.c_str(); + std::string szStr; + if( NULL == wszStr ) + { + return szStr; + } + DWORD iSize = ::WideCharToMultiByte( CP_ACP, 0, wszStr, -1, NULL, 0 ,NULL,NULL); + char* p = new char[iSize+10]; + memset( p, 0, (iSize+10)*sizeof(char) ); + iSize = ::WideCharToMultiByte( CP_ACP, 0, wszStr, -1, p, iSize,NULL,NULL); + szStr = p; + delete p; + return szStr; +} + +std::wstring Util::String::StringToWstringNoConvert(std::string strA) +{ + std::wstring strW; + wchar_t *wp; + strW.resize(strA.length()); + wp = const_cast(strW.data()); + memcpy(wp,strA.data(),strA.length()); + return strW; +} + +CStringA Util::String::UnicodeToGBK( CStringW unicode ) +{ + CStringA strGBK = ""; + DWORD dwMinSize = 0; + dwMinSize = WideCharToMultiByte(936, NULL, unicode, unicode.GetLength(),NULL, 0, NULL, FALSE); + strGBK.GetBufferSetLength(dwMinSize); + LPSTR lpszStr = strGBK.GetBuffer(); + INT ok = WideCharToMultiByte(936, NULL, unicode, unicode.GetLength(), lpszStr, dwMinSize, NULL, FALSE); + strGBK.ReleaseBuffer(); + return strGBK; +} + +CStringW Util::String::GBKToUnicode( CStringA gbk ) +{ + CStringW strUnicode; + DWORD dwMinSize = 0; + dwMinSize = MultiByteToWideChar(936, NULL, gbk, gbk.GetLength(),NULL, 0); + strUnicode.GetBufferSetLength(dwMinSize); + LPWSTR lpszStr = strUnicode.GetBuffer(); + INT ok = MultiByteToWideChar(936, NULL, gbk, gbk.GetLength(), lpszStr, dwMinSize); + strUnicode.ReleaseBuffer(); + return strUnicode; +} + +char Util::GetHex( UINT num,BOOL bUpperWord/*=TRUE*/ ) +{ + return num<10? num+'0': num-10+'A'; +} + +inline char Util::FromHex(const char x) +{ + return isdigit(x) ? x-'0' : x-'A'+10; +} + + +wchar_t Util::GetHexW( UINT num,BOOL bUpperWord/*=TRUE*/ ) +{ + return num<10? num+L'0': num-10+L'A'; +} + +CStringA Util::String::Unicode2UTF8(const wchar_t* pUnicode) +{ + ATLASSERT(NULL != pUnicode); + + int targetLen = WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)pUnicode, -1, NULL, 0, NULL, NULL); + + char* pTargetData = new char[targetLen+1]; + memset(pTargetData, 0, targetLen+1); + WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)pUnicode, -1, (char *)pTargetData, targetLen, NULL, NULL); + + CStringA strRet(pTargetData); + delete pTargetData; + return strRet; +} + +CStringW Util::String::UTF82Unicode(const char* pChar) +{ + ATLASSERT(NULL != pChar); + + int targetLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pChar, -1, NULL, 0); + + WCHAR* pTargetData = new WCHAR[targetLen+1]; + memset(pTargetData, 0, (targetLen+1) * sizeof(WCHAR)); + MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pChar, -1, (WCHAR*)pTargetData, targetLen); + + CStringW strRet(pTargetData); + delete pTargetData; + return strRet; +} + + + +CStringW Util::String::Unicode_URLDecode(const char* pStr) +{ + return UTF82Unicode(PHP_URLDecode(pStr)); +} + +CStringW Util::String::Unicode_URLDecode(const wchar_t* pStr) +{ + return UTF82Unicode(PHP_URLDecode(CStringA(pStr))); +} + +CStringA Util::String::PHP_URLDecode( const CStringA& src ) +{ + CStringA decodeURL; + for(int i = 0; i < src.GetLength(); i++) + { + unsigned char ch = 0; + if(src[i]=='%') + { + ATLASSERT(i + 2 < src.GetLength()); + + unsigned char c1 = src[i + 1]; + unsigned char c2 = src[i + 2]; + ch = ((FromHex(c1) << 4) & 0xf0); + ch |= (FromHex(c2) & 0x0f); + i += 2; + } + else if(src[i] == '+') + { + ch = ' '; + } + else + { + ch = src[i]; + } + decodeURL += (unsigned char)ch; + } + + return decodeURL; +} + +CString Util::String::PHP_URLEncode( const CStringA& src ) +{ + CString encodeURL; + + for(int i = 0; i < src.GetLength(); i++) + { + unsigned char c = src.GetAt(i); + if (c == ' ') + { + encodeURL += L'+'; + } + else if ((c < '0' && c != '-' && c != '.') || + (c < 'A' && c > '9') || + (c > 'Z' && c < 'a' && c != '_') || + (c > 'z')) + { + encodeURL += '%'; + encodeURL += GetHex((c & 0xf0) >> 4); + encodeURL += GetHex(c & 0x0f); + } + else + { + encodeURL += c; + } + } + return encodeURL; +} + +BOOL Util::Base64::Encode( ConstReferenceBuffer src,BufferOut &dest ) +{ + BOOL bRet = FALSE; + + if (src==NULL) + { + return FALSE; + } + DWORD dwInputLen = src.GetSize(); + DWORD dwOutputLen = (dwInputLen / 3 + ((dwInputLen % 3)? 1: 0)) * 4 + 1; + + // + const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + //ֵ + + BYTE* data = src.GetBuffer(); + CStringA destStr; + UINT LineLength; + LineLength = 0; + for(int i=0;i<(int)(dwInputLen / 3);i++) + { + destStr += EncodeTable[data[0] >> 2]; + destStr += EncodeTable[((data[0] << 4) | (data[1] >> 4)) & 0x3F]; + destStr += EncodeTable[((data[1] << 2) | (data[2] >> 6)) & 0x3F]; + destStr += EncodeTable[data[2] & 0x3F]; + data += 3; + LineLength += 4; + if(LineLength==76) + { + destStr += "\r\n"; + LineLength=0; + } + } + //ʣݽб + int Mod=dwInputLen % 3; + if(Mod==1) + { + destStr += EncodeTable[(data[0] & 0xFC) >> 2]; + destStr += EncodeTable[((data[0] & 0x03) << 4)]; + destStr += "=="; + } + else if(Mod==2) + { + destStr += EncodeTable[(data[0] & 0xFC) >> 2]; + destStr += EncodeTable[((data[0] & 0x03) << 4) | ((data[1] & 0xF0) >> 4)]; + destStr += EncodeTable[((data[1] & 0x0F) << 2)]; + destStr += "="; + } + dest.Copy(destStr.GetBuffer(destStr.GetLength()),destStr.GetLength()); + destStr.ReleaseBuffer(destStr.GetLength()); + return TRUE; +} + +BOOL Util::MD5::HashMD5( ConstReferenceBuffer buffer,CString &md5 ) +{ + md5 = CMD5Checksum::GetMD5(buffer.GetBuffer(),buffer.GetSize()); + return !md5.IsEmpty(); +} + +BOOL Util::MD5::GetFileMD5( LPCTSTR path, CString& md5 ) +{ + return CMD5Checksum::GetMD5(path, md5); +} + +BOOL Util::Filesys::ForceCreateDir( LPCTSTR path ) +{ +#define MAX_URL 2048 +#define WIN_DIR_SEP_SYM _T("\\") + TCHAR Dir[MAX_URL+1] = {0}; + int nNeed; + LPCTSTR p,pLast; + + _ASSERT( path ); + + pLast = path; + while( NULL!=*pLast ) + { + p=_tcsstr(pLast,WIN_DIR_SEP_SYM); + if( NULL==p ) return FALSE; + nNeed=int(p-path); + if(nNeed>0) + { + memset( Dir,0,sizeof(Dir) ); + _tcsncpy_s( Dir,MAX_URL,path,nNeed ); + BOOL b = CreateDirectory(Dir,NULL); + if (!b) + { + // + // ѴڣôŴĿ¼Դ + // ܾʣĿ¼ܾʣĿ¼δأҲ + // ֮д󡣡 + } + } + p++; + pLast=p; + } + return TRUE; +#undef MAX_URL +#undef WIN_DIR_SEP_SYM +} + +BOOL Util::Filesys::GetSpecialPath( DWORD dwSpecDirID,CString &path ) +{ + BOOL bResult = FALSE; + LPITEMIDLIST pidl; + LPMALLOC pShellMalloc=Util::Data.GetLPMALLOC(); + + if(pShellMalloc != NULL) + { + if(SUCCEEDED(SHGetSpecialFolderLocation(NULL,dwSpecDirID,&pidl))) + { + if(SHGetPathFromIDList(pidl,path.GetBuffer(MAX_PATH))) + { + bResult = TRUE; + } + path.ReleaseBuffer(); + pShellMalloc->Free(pidl); + } + } + return bResult; +} + +bool Util::Filesys::IsFileInUse( LPCTSTR path ) +{ + ATLASSERT(NULL != path); + if(!PathFileExists(path)) + { + return false; + } + + HANDLE handle = CreateFile(path, GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + bool ret = (INVALID_HANDLE_VALUE == handle); + if(!ret) + { + CloseHandle(handle); + } + return ret; +} + +void Util::Time::Time_tToFileTime(time_t t, LPFILETIME pft) +{ + ATLASSERT(NULL != pft); + + // Note that LONGLONG is a 64-bit value + LONGLONG ll; + + ll = Int32x32To64(t, 10000000) + 116444736000000000; + pft->dwLowDateTime = (DWORD)ll; + pft->dwHighDateTime = (DWORD)(ll >> 32); +} + +void Util::Time::FileTimeToTime_t(FILETIME ft, time_t* t) +{ + ATLASSERT(NULL != t); + + LONGLONG ll; + + ULARGE_INTEGER ui; + ui.LowPart = ft.dwLowDateTime; + ui.HighPart = ft.dwHighDateTime; + ll = (LONGLONG(ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + *t = ((LONGLONG)(ui.QuadPart - 116444736000000000) / 10000000); +} + +void Util::Time::Time_tToSystemTime(time_t t, LPSYSTEMTIME pst) +{ + ATLASSERT(NULL != pst); + + FILETIME ft; + Time_tToFileTime(t, &ft); + FileTimeToSystemTime(&ft, pst); +} + +void Util::Time::SystemTimeToTime_t(SYSTEMTIME st, time_t* t) +{ + ATLASSERT(NULL != t); + + FILETIME ft; + SystemTimeToFileTime(&st, &ft); + FileTimeToTime_t(ft, t); +} + +std::wstring Util::Time::TmtToString( tm time ) +{ + CStringW strRes; + strRes.Format(L"%d%d%d%d%d",time.tm_year,time.tm_mon,time.tm_mday,time.tm_hour,time.tm_min,time.tm_sec); + return std::wstring(strRes); +} +__int64 Util::Num::CombineToINT64(DWORD dwHight, DWORD dwLow) +{ + return __int64((__int64(dwHight) << 32) + dwLow); +} + +unsigned __int64 Util::Num::CombineToUINT64(DWORD dwHight, DWORD dwLow) +{ + return unsigned __int64((unsigned __int64(dwHight) << 32) + dwLow); +} + +std::wstring Util::Size::FormatSize(__int64 nSize) +{ + CStringW strRes; + if (nSize=Size_KB && nSize=Size_MB && nSize=Size_GB && nSize=Size_TB) + { + int nSizeGB = (int)(nSize/Size_KB); + strRes.Format(L"%.2f T", (double)nSizeGB/(double)Size_GB); + } + return strRes.GetString(); +} + + +bool Util::Filesys::CheckFileName( const wchar_t * str ) +{ + while(*str != L'\0') + { + if( + *str == L'/' || + *str == L'\\'|| + *str == L';' || + *str == L':' || + *str == L'*' || + *str == L'?' || + *str == L'\"'|| + *str == L'<' || + *str == L'>' + ) + return false; + ++str; + } + return true; +} + +bool Util::Filesys::GetDirFromPath( LPCTSTR path,int &endposIndex ) +{ + int length = (int)_tcslen(path); + for (int n=length-1; n>=0; --n) + { + if (path[n]==L'\\' || path[n]==L'/') + { + endposIndex = n; + return true; + } + } + endposIndex = 0; + return false; +} + +BOOL Util::Filesys::SplitPath( LPCTSTR dirPath,CString& dir,CString& fileName ) +{ + CString strDirPath = dirPath; + int pos; + if (GetDirFromPath(strDirPath,pos)) + { + dir = strDirPath.Left(pos); + fileName = strDirPath.Right(strDirPath.GetLength()-pos-1); + FormatDirPathString(dir); + FormatPathString(fileName); + return TRUE; + } + return FALSE; +} +void Util::Filesys::FormatPathString( CString& strDirRoot ,BOOL slashOrNot) +{ + if (strDirRoot.IsEmpty()) + { + return; + } + FormatPathSplit(strDirRoot,slashOrNot); +} + +void Util::Filesys::FormatDirPathString( CString& strDirRoot ,BOOL slashOrNot) +{ + FormatPathString(strDirRoot,slashOrNot); + if (strDirRoot.Right(1) != (slashOrNot? _T('/'): _T('\\'))) + { + strDirRoot += (slashOrNot? _T('/'): _T('\\')); + } +} + +std::wstring Util::Filesys::AutoRenameLocalPathIfExists(const std::wstring& path) +{ + std::wstring new_path = path; + + ATL::CString str_path = path.c_str(); + int pos = str_path.ReverseFind(L'.'); + if(-1 == pos) + { + pos = str_path.GetLength(); + } + + int index = 2; + while(PathFileExists(new_path.c_str())) + { + ATL::CString str_new_path = path.c_str(); + ATL::CString strFormat; + strFormat.Format(L"(%d)", index++); + str_new_path.Insert(pos, strFormat); + + new_path = str_new_path; + } + + return new_path; +} + +void Util::Filesys::FormatPathSplit(CString& strPath,BOOL slashOrNot) +{ + LPCTSTR bef,aft,dblaft; + if (slashOrNot) + { + bef = _T("\\"); + aft = _T("/"); + dblaft = _T("//"); + } + else + { + bef = _T("/"); + aft = _T("\\"); + dblaft = _T("\\\\"); + } + strPath.Replace(bef,aft); + while(-1 != strPath.Find(dblaft)) + { + strPath.Replace(dblaft,aft); + } +} + +BOOL Util::Filesys::MakeSurePathFileValid( CString& path ) +{ + if (path.IsEmpty()) + { + return FALSE; + } + if (!PathFileExists(path)) + { + return TRUE; + } + CString extName; + CString forePath; + CString dir; + CString filename; + SplitPath(path,dir,filename); + if (!PathFileExists(dir)) + { + ForceCreateDir(dir); + if (!PathFileExists(dir)) + { + return FALSE; + } + } + int nPos = path.ReverseFind(_T('.')); + if (nPos == -1) + { + forePath = path; + } + else + { + forePath = path.Left(nPos); + extName = path.Right(path.GetLength()-nPos); + } + CString tryPath; + int indexCount = 2; + do + { + tryPath.Format(_T("%s(%d)%s"),forePath,indexCount,extName); + ++indexCount; + } while (PathFileExists(tryPath) && indexCount= CHAR_MAX) + { + return FALSE; + } + path = tryPath; + return TRUE; +} + +UINT Util::String::ToUINT( LPCTSTR lpstr ) +{ + ATLASSERT(lpstr); + DWORD dw = 0; + if (lpstr) + { + while(*lpstr) + { + dw *= 10; + dw += *lpstr - '0'; + ++lpstr; + } + } + return dw; +} + +namespace Util +{ + CAutoCS::CAutoCS( ::ATL::CCriticalSection &cs ) :m_cs(cs) + { + m_cs.Enter(); + } + CAutoCS::~CAutoCS() + { + m_cs.Leave(); + } + + + CTimedCriticalSection::CTimedCriticalSection( UINT waitTime /*= 1000*/ ) : m_waitTime(waitTime) + { + m_hEvent = CreateEvent(NULL,FALSE,FALSE,NULL); + ATLASSERT(m_hEvent); + m_bTimeout = FALSE; + } + CTimedCriticalSection::~CTimedCriticalSection() + { + if (m_hEvent) + { + CloseHandle(m_hEvent); + } + } + BOOL CTimedCriticalSection::Enter() + { + ATLASSERT(m_hEvent); + DWORD dw = WaitForSingleObject(m_hEvent,m_waitTime); + m_bTimeout = (dw==WAIT_TIMEOUT); + return m_bTimeout; + } + BOOL CTimedCriticalSection::Try() + { + ATLASSERT(m_hEvent); + DWORD dw = WaitForSingleObject(m_hEvent,0); + m_bTimeout = (dw==WAIT_TIMEOUT); + return m_bTimeout; + } + VOID CTimedCriticalSection::Leave() + { + ATLASSERT(m_hEvent); + SetEvent(m_hEvent); + } + BOOL CTimedCriticalSection::IsTimedOut() + { + return m_bTimeout; + } + + + CAutoTimedCS::CAutoTimedCS( CTimedCriticalSection &cs ) :m_cs(cs) + { + m_cs.Enter(); + } + BOOL CAutoTimedCS::IsTimedOut() + { + return m_cs.IsTimedOut(); + } + CAutoTimedCS::~CAutoTimedCS() + { + m_cs.Leave(); + } + + CAutoIndex::CAutoIndex() + { + m_index = 0; + } + CAutoIndex::~CAutoIndex() + {} + UINT CAutoIndex::Get(UINT increase) + { + UINT ret = m_index; + m_index += increase; // + return ret; + } } \ No newline at end of file diff --git a/VNOC/util/util.h b/Client/Client/util/util.h similarity index 85% rename from VNOC/util/util.h rename to Client/Client/util/util.h index aec45596..02ef48ed 100644 --- a/VNOC/util/util.h +++ b/Client/Client/util/util.h @@ -1,149 +1,160 @@ -#pragma once -#include "CBuffer.h" -#define WIN32_LEAN_AND_MEAN -#include "windows.h" -#include "memory.h" -#include "stdlib.h" -#include "string" -#include "atlsync.h" -#include "shlobj.h" - -#define EMPTYSTR _T("") - -template -class CGlobalPtrContainer -{ -public: - CGlobalPtrContainer(T* p=NULL):m_p(p){}; - ~CGlobalPtrContainer(){delete p;}; - void Set(T* p){m_p=p;} - T* Get(){return m_p;}; -private: - T* m_p; -}; - -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) -#define _private public - -////////////////////////////////////////////////////////////////////////// -const int Size_KB = 1024; -const int Size_MB = 1024*1024; -const int Size_GB = 1024*1024*1024; -const __int64 Size_KBLL = 1024; -const __int64 Size_TB = Size_KBLL*Size_KBLL*Size_KBLL*Size_KBLL; - -namespace Util -{ - char FromHex(const char x); - char GetHex(UINT num,BOOL bUpperWord=TRUE); - wchar_t GetHexW(UINT num,BOOL bUpperWord=TRUE); - namespace String - { - CStringW Unicode_URLDecode(const char* pStr); - CStringW Unicode_URLDecode(const wchar_t* pStr); - CStringW Unicode_URLEncode(const wchar_t* pStr); - CStringA Unicode2UTF8(const wchar_t* pUnicode); - CStringW UTF82Unicode(const char* pChar); - - CStringA UnicodeToGBK(CStringW unicode); - CStringW GBKToUnicode(CStringA gbk); - CString PHP_URLEncode(const CStringA& src); - CStringA PHP_URLDecode(const CStringA& src ); - std::wstring StringA2W(std::string strA); - std::string StringW2A(std::wstring strW); - // תĽcharתΪwchar_t - std::wstring StringToWstringNoConvert(std::string strA); - UINT ToUINT(LPCTSTR lpstr); - } - namespace Base64 - { - BOOL Encode(ConstReferenceBuffer src,BufferOut &dest); - } - namespace MD5 - { - BOOL HashMD5(ConstReferenceBuffer buffer,CString &md5); - BOOL GetFileMD5(LPCTSTR path, CString& md5); - } - namespace Filesys - { - BOOL ForceCreateDir(LPCTSTR path); - // ȡϵͳ·.CSIDL_APPDATA - BOOL GetSpecialPath(DWORD dwSpecDirID,CString &path); - bool FindFileAttribute(const wchar_t* path, WIN32_FIND_DATA& findFileData); - bool CheckFileName(const wchar_t * str); - bool GetDirFromPath(LPCTSTR path,int &endposIndex);// ȡ·еĿ¼ - //BOOL PathFileExists(LPCTSTR path); // WindowsAPI - bool IsFileInUse(LPCTSTR path); - } - - namespace Time - { - void Time_tToFileTime(time_t t, LPFILETIME pft); - void Time_tToSystemTime(time_t t, LPSYSTEMTIME pst); - void FileTimeToTime_t(FILETIME ft, time_t* t); - void SystemTimeToTime_t(SYSTEMTIME st, time_t* t); - std::wstring TmtToString(tm time); - } - - namespace Num - { - __int64 CombineToINT64(DWORD dwHight, DWORD dwLow); - unsigned __int64 CombineToUINT64(DWORD dwHight, DWORD dwLow); - } - - namespace Size - { - std::wstring FormatSize(__int64 nSize); - } -} - -namespace Util -{ - class CAutoCS - { - public: - CAutoCS(::ATL::CCriticalSection &cs);; - ~CAutoCS(); - private: - ::ATL::CCriticalSection& m_cs; - }; - - // ȴʱ޵ٽ - class CTimedCriticalSection : public CRITICAL_SECTION - { - public: - CTimedCriticalSection(UINT waitTime = 1000); - ~CTimedCriticalSection(); - BOOL Enter();; - BOOL Try(); - VOID Leave(); - BOOL IsTimedOut(); - private: - BOOL m_bTimeout; - UINT m_waitTime; - HANDLE m_hEvent; - }; - - class CAutoTimedCS - { - public: - CAutoTimedCS(CTimedCriticalSection &cs);; - ~CAutoTimedCS(); - BOOL IsTimedOut(); - private: - CTimedCriticalSection& m_cs; - }; - - // ԶõID - class CAutoIndex - { - public: - CAutoIndex(); - ~CAutoIndex(); - UINT Get(UINT increase = 1); // һӼ - private: - UINT m_index; - }; +#pragma once +#include "CBuffer.h" +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include + +#define EMPTYSTR _T("") + +template +class CGlobalPtrContainer +{ +public: + CGlobalPtrContainer(T* p=NULL):m_p(p){}; + ~CGlobalPtrContainer(){delete p;}; + void Set(T* p){m_p=p;} + T* Get(){return m_p;}; +private: + T* m_p; +}; + +#ifndef DISALLOW_COPY_AND_ASSIGN +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) +#endif + +#define _private public + +////////////////////////////////////////////////////////////////////////// +const int Size_KB = 1024; +const int Size_MB = 1024*1024; +const int Size_GB = 1024*1024*1024; +const __int64 Size_KBLL = 1024; +const __int64 Size_TB = Size_KBLL*Size_KBLL*Size_KBLL*Size_KBLL; + +namespace Util +{ + char FromHex(const char x); + char GetHex(UINT num,BOOL bUpperWord=TRUE); + wchar_t GetHexW(UINT num,BOOL bUpperWord=TRUE); + namespace String + { + CStringW Unicode_URLDecode(const char* pStr); + CStringW Unicode_URLDecode(const wchar_t* pStr); + CStringW Unicode_URLEncode(const wchar_t* pStr); + CStringA Unicode2UTF8(const wchar_t* pUnicode); + CStringW UTF82Unicode(const char* pChar); + + CStringA UnicodeToGBK(CStringW unicode); + CStringW GBKToUnicode(CStringA gbk); + CString PHP_URLEncode(const CStringA& src); + CStringA PHP_URLDecode(const CStringA& src ); + std::wstring StringA2W(std::string strA); + std::string StringW2A(std::wstring strW); + // תĽcharתΪwchar_t + std::wstring StringToWstringNoConvert(std::string strA); + UINT ToUINT(LPCTSTR lpstr); + } + namespace Base64 + { + BOOL Encode(ConstReferenceBuffer src,BufferOut &dest); + } + namespace MD5 + { + BOOL HashMD5(ConstReferenceBuffer buffer,CString &md5); + BOOL GetFileMD5(LPCTSTR path, CString& md5); + } + namespace Filesys + { + BOOL ForceCreateDir(LPCTSTR path); + // ȡϵͳ·.CSIDL_APPDATA + BOOL GetSpecialPath(DWORD dwSpecDirID,CString &path); + bool FindFileAttribute(const wchar_t* path, WIN32_FIND_DATA& findFileData); + bool CheckFileName(const wchar_t * str); + bool GetDirFromPath(LPCTSTR path,int &endposIndex);// ȡ·еĿ¼ + BOOL SplitPath(LPCTSTR dirPath,CString& dir,CString& fileName); + //BOOL PathFileExists(LPCTSTR path); // WindowsAPI + bool IsFileInUse(LPCTSTR path); + + void FormatPathSplit(CString& strPath,BOOL slashOrNot=TRUE); + void FormatPathString( CString& strDirRoot,BOOL slashOrNot=TRUE ); + void FormatDirPathString( CString& strDirRoot,BOOL slashOrNot=TRUE ); + BOOL MakeSurePathFileValid(CString& path); + std::wstring AutoRenameLocalPathIfExists(const std::wstring& path); + } + + namespace Time + { + void Time_tToFileTime(time_t t, LPFILETIME pft); + void Time_tToSystemTime(time_t t, LPSYSTEMTIME pst); + void FileTimeToTime_t(FILETIME ft, time_t* t); + void SystemTimeToTime_t(SYSTEMTIME st, time_t* t); + std::wstring TmtToString(tm time); + } + + namespace Num + { + __int64 CombineToINT64(DWORD dwHight, DWORD dwLow); + unsigned __int64 CombineToUINT64(DWORD dwHight, DWORD dwLow); + } + + namespace Size + { + std::wstring FormatSize(__int64 nSize); + } +} + +namespace Util +{ + class CAutoCS + { + public: + CAutoCS(::ATL::CCriticalSection &cs);; + ~CAutoCS(); + private: + ::ATL::CCriticalSection& m_cs; + }; + + // ȴʱ޵ٽ + class CTimedCriticalSection : public CRITICAL_SECTION + { + public: + CTimedCriticalSection(UINT waitTime = 1000); + ~CTimedCriticalSection(); + BOOL Enter();; + BOOL Try(); + VOID Leave(); + BOOL IsTimedOut(); + private: + BOOL m_bTimeout; + UINT m_waitTime; + HANDLE m_hEvent; + }; + + class CAutoTimedCS + { + public: + CAutoTimedCS(CTimedCriticalSection &cs);; + ~CAutoTimedCS(); + BOOL IsTimedOut(); + private: + CTimedCriticalSection& m_cs; + }; + + // ԶõID + class CAutoIndex + { + public: + CAutoIndex(); + ~CAutoIndex(); + UINT Get(UINT increase = 1); // һӼ + private: + UINT m_index; + }; } \ No newline at end of file diff --git a/Client/VNOC.sln b/Client/VNOC.sln new file mode 100644 index 00000000..1eab746a --- /dev/null +++ b/Client/VNOC.sln @@ -0,0 +1,46 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cppunit", "..\cppunit-1.12.1\src\cppunit\cppunit.vcxproj", "{9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Client", "Client\Client.vcxproj", "{8E8644B5-86CF-4286-9276-8710E6EE974C}" + ProjectSection(ProjectDependencies) = postProject + {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E} = {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + CppTest|Win32 = CppTest|Win32 + CppTest|x64 = CppTest|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.CppTest|Win32.ActiveCfg = Debug|Win32 + {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.CppTest|Win32.Build.0 = Debug|Win32 + {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.CppTest|x64.ActiveCfg = Template|x64 + {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.CppTest|x64.Build.0 = Template|x64 + {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.Debug|Win32.ActiveCfg = Debug|Win32 + {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.Debug|Win32.Build.0 = Debug|Win32 + {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.Debug|x64.ActiveCfg = Debug|x64 + {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.Debug|x64.Build.0 = Debug|x64 + {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.Release|Win32.ActiveCfg = Release|Win32 + {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.Release|Win32.Build.0 = Release|Win32 + {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.Release|x64.ActiveCfg = Release|x64 + {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.Release|x64.Build.0 = Release|x64 + {8E8644B5-86CF-4286-9276-8710E6EE974C}.CppTest|Win32.ActiveCfg = CppTest|Win32 + {8E8644B5-86CF-4286-9276-8710E6EE974C}.CppTest|Win32.Build.0 = CppTest|Win32 + {8E8644B5-86CF-4286-9276-8710E6EE974C}.CppTest|x64.ActiveCfg = CppTest|Win32 + {8E8644B5-86CF-4286-9276-8710E6EE974C}.Debug|Win32.ActiveCfg = Debug|Win32 + {8E8644B5-86CF-4286-9276-8710E6EE974C}.Debug|Win32.Build.0 = Debug|Win32 + {8E8644B5-86CF-4286-9276-8710E6EE974C}.Debug|x64.ActiveCfg = Debug|Win32 + {8E8644B5-86CF-4286-9276-8710E6EE974C}.Release|Win32.ActiveCfg = Release|Win32 + {8E8644B5-86CF-4286-9276-8710E6EE974C}.Release|Win32.Build.0 = Release|Win32 + {8E8644B5-86CF-4286-9276-8710E6EE974C}.Release|x64.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Client/res/ClassroomWin.xml b/Client/res/ClassroomWin.xml new file mode 100644 index 00000000..a765f9c1 --- /dev/null +++ b/Client/res/ClassroomWin.xml @@ -0,0 +1,16 @@ + + + +
+ + 教室 + +
+
+
+ + + +
+ + diff --git a/Client/res/LoginWin.xml b/Client/res/LoginWin.xml new file mode 100644 index 00000000..7698c982 --- /dev/null +++ b/Client/res/LoginWin.xml @@ -0,0 +1 @@ +
VNOC
\ No newline at end of file diff --git a/Client/res/LoginWin_Body.xml b/Client/res/LoginWin_Body.xml new file mode 100644 index 00000000..e3ca09b8 --- /dev/null +++ b/Client/res/LoginWin_Body.xml @@ -0,0 +1 @@ + 帐号: 密码: 记住密码 自动登录 状态: \ No newline at end of file diff --git a/Client/res/RoomListWin.xml b/Client/res/RoomListWin.xml new file mode 100644 index 00000000..2530b1bb --- /dev/null +++ b/Client/res/RoomListWin.xml @@ -0,0 +1,43 @@ + + +
+ + + + + 教室列表 + +
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/Client/res/beikesafe.ico b/Client/res/beikesafe.ico new file mode 100644 index 00000000..ce8854aa Binary files /dev/null and b/Client/res/beikesafe.ico differ diff --git a/Client/res/big_logo.png b/Client/res/big_logo.png new file mode 100644 index 00000000..affe4e5a Binary files /dev/null and b/Client/res/big_logo.png differ diff --git a/Client/res/btn_sys_close.bmp b/Client/res/btn_sys_close.bmp new file mode 100644 index 00000000..80a887ff Binary files /dev/null and b/Client/res/btn_sys_close.bmp differ diff --git a/Client/res/btn_sys_close.png b/Client/res/btn_sys_close.png new file mode 100644 index 00000000..6baf1740 Binary files /dev/null and b/Client/res/btn_sys_close.png differ diff --git a/Client/res/btn_sys_maximize.bmp b/Client/res/btn_sys_maximize.bmp new file mode 100644 index 00000000..a7895b16 Binary files /dev/null and b/Client/res/btn_sys_maximize.bmp differ diff --git a/Client/res/btn_sys_maximize.png b/Client/res/btn_sys_maximize.png new file mode 100644 index 00000000..d27a2edc Binary files /dev/null and b/Client/res/btn_sys_maximize.png differ diff --git a/Client/res/btn_sys_minimize.bmp b/Client/res/btn_sys_minimize.bmp new file mode 100644 index 00000000..6c4cd42b Binary files /dev/null and b/Client/res/btn_sys_minimize.bmp differ diff --git a/Client/res/btn_sys_minimize.png b/Client/res/btn_sys_minimize.png new file mode 100644 index 00000000..7eab567c Binary files /dev/null and b/Client/res/btn_sys_minimize.png differ diff --git a/Client/res/btn_sys_restore.bmp b/Client/res/btn_sys_restore.bmp new file mode 100644 index 00000000..0261d1fd Binary files /dev/null and b/Client/res/btn_sys_restore.bmp differ diff --git a/Client/res/btn_sys_restore.png b/Client/res/btn_sys_restore.png new file mode 100644 index 00000000..cb0a6c8d Binary files /dev/null and b/Client/res/btn_sys_restore.png differ diff --git a/Client/res/btn_tab.bmp b/Client/res/btn_tab.bmp new file mode 100644 index 00000000..eb213bab Binary files /dev/null and b/Client/res/btn_tab.bmp differ diff --git a/Client/res/btn_virscan_bg.bmp b/Client/res/btn_virscan_bg.bmp new file mode 100644 index 00000000..23b57cdc Binary files /dev/null and b/Client/res/btn_virscan_bg.bmp differ diff --git a/Client/res/clear_bk.bmp b/Client/res/clear_bk.bmp new file mode 100644 index 00000000..a5d4be15 Binary files /dev/null and b/Client/res/clear_bk.bmp differ diff --git a/Client/res/clear_panel.bmp b/Client/res/clear_panel.bmp new file mode 100644 index 00000000..5515a076 Binary files /dev/null and b/Client/res/clear_panel.bmp differ diff --git a/Client/res/def_skin.xml b/Client/res/def_skin.xml new file mode 100644 index 00000000..334d5111 --- /dev/null +++ b/Client/res/def_skin.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + 用户名: + 编辑框 + 密码: + + + + + diff --git a/Client/res/dlg_msgbox.xml b/Client/res/dlg_msgbox.xml new file mode 100644 index 00000000..da69241e --- /dev/null +++ b/Client/res/dlg_msgbox.xml @@ -0,0 +1,18 @@ + +
+ %str1% +
+
+ +
+ + + + + + + + 下次不再提示 + + +
diff --git a/Client/res/dlg_msgbox2.xml b/Client/res/dlg_msgbox2.xml new file mode 100644 index 00000000..c036da2d --- /dev/null +++ b/Client/res/dlg_msgbox2.xml @@ -0,0 +1,18 @@ + +
+ %str1% +
+
+ +
+ + + + + + + + 下次不再提示 + + +
diff --git a/Client/res/dlg_runopt_ignore.xml b/Client/res/dlg_runopt_ignore.xml new file mode 100644 index 00000000..a2000a72 --- /dev/null +++ b/Client/res/dlg_runopt_ignore.xml @@ -0,0 +1,21 @@ + +
+ + 开机加速 - 已忽略的优化项 + +
+ + + +
+ + + 以下启动项将不会在“一键优化”及“体检”功能中提示 + 全选 + + + + 没有忽略项 + + +
diff --git a/Client/res/dlg_runopt_list.xml b/Client/res/dlg_runopt_list.xml new file mode 100644 index 00000000..82b2d26d --- /dev/null +++ b/Client/res/dlg_runopt_list.xml @@ -0,0 +1,17 @@ + + + + + + + + 正在加载,请稍候... + + + + + + + + + diff --git a/Client/res/dlg_sysopt_setting.xml b/Client/res/dlg_sysopt_setting.xml new file mode 100644 index 00000000..d8bdec6f --- /dev/null +++ b/Client/res/dlg_sysopt_setting.xml @@ -0,0 +1,25 @@ + +
+ 金山卫士-开机提示设置 +
+
+
+ + + + + + 仅在以下特定场景下提示(推荐) + 每次使用过“开机加速”后第一次开机时提示 + 开机速度较慢时提示 + 每次开机都提示开机时间 + 不进行开机时间提示 + + + + + + + +
+ diff --git a/Client/res/dlgfile_foot.xml b/Client/res/dlgfile_foot.xml new file mode 100644 index 00000000..07ee1dc3 --- /dev/null +++ b/Client/res/dlgfile_foot.xml @@ -0,0 +1,41 @@ +主程序版本: + + + + + + + 正在检测新版本 + + + + 检测到新版本 + 立即升级 + + + + + 正在升级 + + + + + + + 正在连接云引擎 ... + + + + 云引擎连接成功 + + + + 云引擎连接失败,请检查网络 + + + + 您使用的是非官方版本,不能连接云引擎 + \ No newline at end of file diff --git a/Client/res/dlgfile_header.xml b/Client/res/dlgfile_header.xml new file mode 100644 index 00000000..145b7844 --- /dev/null +++ b/Client/res/dlgfile_header.xml @@ -0,0 +1,5 @@ + +VNOC + + + diff --git a/Client/res/dlgfile_opt.xml b/Client/res/dlgfile_opt.xml new file mode 100644 index 00000000..e2a59564 --- /dev/null +++ b/Client/res/dlgfile_opt.xml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Client/res/exam_status_icon.png b/Client/res/exam_status_icon.png new file mode 100644 index 00000000..56c3f18f Binary files /dev/null and b/Client/res/exam_status_icon.png differ diff --git a/Client/res/frame_panel.bmp b/Client/res/frame_panel.bmp new file mode 100644 index 00000000..6b969755 Binary files /dev/null and b/Client/res/frame_panel.bmp differ diff --git a/Client/res/frame_panel_gray.bmp b/Client/res/frame_panel_gray.bmp new file mode 100644 index 00000000..76074728 Binary files /dev/null and b/Client/res/frame_panel_gray.bmp differ diff --git a/Client/res/frame_roomlistpane.png b/Client/res/frame_roomlistpane.png new file mode 100644 index 00000000..f8cf2b20 Binary files /dev/null and b/Client/res/frame_roomlistpane.png differ diff --git a/Client/res/ignore_tip.png b/Client/res/ignore_tip.png new file mode 100644 index 00000000..049b1222 Binary files /dev/null and b/Client/res/ignore_tip.png differ diff --git a/Client/res/listctrl_check.bmp b/Client/res/listctrl_check.bmp new file mode 100644 index 00000000..e3e89558 Binary files /dev/null and b/Client/res/listctrl_check.bmp differ diff --git a/Client/res/listctrl_combo.bmp b/Client/res/listctrl_combo.bmp new file mode 100644 index 00000000..7f602f16 Binary files /dev/null and b/Client/res/listctrl_combo.bmp differ diff --git a/Client/res/listctrl_header.bmp b/Client/res/listctrl_header.bmp new file mode 100644 index 00000000..0fb31d08 Binary files /dev/null and b/Client/res/listctrl_header.bmp differ diff --git a/Client/res/listctrl_radio.bmp b/Client/res/listctrl_radio.bmp new file mode 100644 index 00000000..0a0bc94e Binary files /dev/null and b/Client/res/listctrl_radio.bmp differ diff --git a/Client/res/little_logo.png b/Client/res/little_logo.png new file mode 100644 index 00000000..d05df0d6 Binary files /dev/null and b/Client/res/little_logo.png differ diff --git a/Client/res/loaddlg_panel.bmp b/Client/res/loaddlg_panel.bmp new file mode 100644 index 00000000..c71ac209 Binary files /dev/null and b/Client/res/loaddlg_panel.bmp differ diff --git a/Client/res/loadinfo_dlgbk.bmp b/Client/res/loadinfo_dlgbk.bmp new file mode 100644 index 00000000..f49b7a5f Binary files /dev/null and b/Client/res/loadinfo_dlgbk.bmp differ diff --git a/Client/res/loadinfo_tip_softmgr.png b/Client/res/loadinfo_tip_softmgr.png new file mode 100644 index 00000000..f2a477b4 Binary files /dev/null and b/Client/res/loadinfo_tip_softmgr.png differ diff --git a/Client/res/loading_runopt.png b/Client/res/loading_runopt.png new file mode 100644 index 00000000..f2a477b4 Binary files /dev/null and b/Client/res/loading_runopt.png differ diff --git a/Client/res/minus_plus.bmp b/Client/res/minus_plus.bmp new file mode 100644 index 00000000..a281f65f Binary files /dev/null and b/Client/res/minus_plus.bmp differ diff --git a/Client/res/msgbox_bg.bmp b/Client/res/msgbox_bg.bmp new file mode 100644 index 00000000..1027e13f Binary files /dev/null and b/Client/res/msgbox_bg.bmp differ diff --git a/Client/res/msgbox_body_bg.bmp b/Client/res/msgbox_body_bg.bmp new file mode 100644 index 00000000..a8559e65 Binary files /dev/null and b/Client/res/msgbox_body_bg.bmp differ diff --git a/Client/res/runopt_listheader.bmp b/Client/res/runopt_listheader.bmp new file mode 100644 index 00000000..aa1546d0 Binary files /dev/null and b/Client/res/runopt_listheader.bmp differ diff --git a/Client/res/scan_result_list_bar.bmp b/Client/res/scan_result_list_bar.bmp new file mode 100644 index 00000000..b7174318 Binary files /dev/null and b/Client/res/scan_result_list_bar.bmp differ diff --git a/Client/res/small.ico b/Client/res/small.ico new file mode 100644 index 00000000..6b94d5ac Binary files /dev/null and b/Client/res/small.ico differ diff --git a/Client/res/startuptime_setting.png b/Client/res/startuptime_setting.png new file mode 100644 index 00000000..70e9e815 Binary files /dev/null and b/Client/res/startuptime_setting.png differ diff --git a/Client/res/stat_runopt.bmp b/Client/res/stat_runopt.bmp new file mode 100644 index 00000000..9f5582c8 Binary files /dev/null and b/Client/res/stat_runopt.bmp differ diff --git a/Client/res/status_40.bmp b/Client/res/status_40.bmp new file mode 100644 index 00000000..d6dd47fd Binary files /dev/null and b/Client/res/status_40.bmp differ diff --git a/Client/res/status_icon.bmp b/Client/res/status_icon.bmp new file mode 100644 index 00000000..c2d22d5f Binary files /dev/null and b/Client/res/status_icon.bmp differ diff --git a/Client/res/status_icon.png b/Client/res/status_icon.png new file mode 100644 index 00000000..dfac1106 Binary files /dev/null and b/Client/res/status_icon.png differ diff --git a/Client/res/sysopt_listbk.bmp b/Client/res/sysopt_listbk.bmp new file mode 100644 index 00000000..69cdd0cd Binary files /dev/null and b/Client/res/sysopt_listbk.bmp differ diff --git a/Client/res/tab_left.bmp b/Client/res/tab_left.bmp new file mode 100644 index 00000000..afb11a8d Binary files /dev/null and b/Client/res/tab_left.bmp differ diff --git a/Client/res/tab_left_splitter.bmp b/Client/res/tab_left_splitter.bmp new file mode 100644 index 00000000..cd40d8a1 Binary files /dev/null and b/Client/res/tab_left_splitter.bmp differ diff --git a/Client/res/tab_normal.bmp b/Client/res/tab_normal.bmp new file mode 100644 index 00000000..e30aac9d Binary files /dev/null and b/Client/res/tab_normal.bmp differ diff --git a/Client/res/tab_normal_ex.bmp b/Client/res/tab_normal_ex.bmp new file mode 100644 index 00000000..68fb5e87 Binary files /dev/null and b/Client/res/tab_normal_ex.bmp differ diff --git a/Message/BaseMessage.cpp b/Message/BaseMessage.cpp new file mode 100644 index 00000000..ff7275f7 --- /dev/null +++ b/Message/BaseMessage.cpp @@ -0,0 +1,375 @@ + + +#include "BaseMessage.h" + + +uint byteToInt(const byte* in_byte,size_t len) +{ + byte tmpByte[4] = {0}; + if (in_byte == NULL) + { + return 0; + } + + for (int index = 0; index < (int)len; index++) + { + tmpByte[index] = in_byte[index]; + } + + uint* lpDataLen = NULL; + lpDataLen = (uint *)tmpByte; + return (*lpDataLen); +} + +void IntTobyte(int in_int,byte* out_byte) +{ + if (out_byte == NULL) + { + return; + } + for(int i = 0; i < 4; i++) + { + out_byte[i]=(byte)(in_int>>(24-i*8)); + } +} + + +int CMessage::GetMessageType() const +{ + return _MessageType(m_Command); +} + +bool CMessage::GetBeginTab() const +{ + return m_Begin; +} + +bool CMessage::GetEndTab() const +{ + return m_End; +} + +byte CMessage::GetCommand() const +{ + return m_Command; +} + +byte CMessage::GetComListLen(uint in_index) const +{ + return m_ComListLen[in_index]; +} + +uint CMessage::GetSerial() const +{ + return BigLittleSwap16(byteToInt(m_Serial,2)); +} + +const byte* CMessage::GetGUID() const +{ + return m_GUID; +} + +const byte* CMessage::GetComCommandList(uint in_index)const +{ + return (byte*)(m_ComCommandList[in_index].second.data()); +} + +uint CMessage::GetVerify() const +{ + return m_Verify; +} + +uint CMessage::GetObligate() const +{ + return m_Obligate; +} + +uint CMessage::GetVersion() const +{ + return m_Ver; +} + +uint CMessage::GetCmlCount() const +{ + return m_CmlCount; +} + +uint CMessage::GetDataLen() const +{ + return m_Len; +} + + +// Set + +bool CMessage::SetCommand(byte in_byte) +{ + m_Command = in_byte; + return true; +} + + +bool CMessage::SetComListLen(byte* in_byte_ptr,int CmlCount) +{ + if (in_byte_ptr != NULL) + { + if (CmlCount != 0) + { + m_ComListLen.clear(); + for (int index = 0; index < (CmlCount * 4); index++) + { + m_ComListLen.push_back(in_byte_ptr[index]); + } + } + else + { + m_ComListLen.clear(); + } + } + else + { + m_ComListLen.resize(CmlCount * 4); + } + return true; +} + +bool CMessage::SetSerial(ushort in_short) +{ + byte tmpbyte[4] = {0}; + if (m_Serial != NULL) + { + IntTobyte(in_short,tmpbyte); + //ȡ2λ + for(int i = 2,Pos = 0; i < 4;Pos++,i++) + { + m_Serial[Pos] = tmpbyte[i]; + } + return true; + } + return false; +} + + +bool CMessage::SetGUID(byte* in_byte_ptr) +{ + if (in_byte_ptr != NULL) + { + memset(m_GUID,0,16); + memcpy(m_GUID,in_byte_ptr,16); + return true; + } + return false; +} + + +bool CMessage::SetComCommandList(int ComCount) +{ + if (ComCount == 0) + { + m_ComCommandList.clear(); + return true; + } + + m_ComCommandList.clear(); + m_ComCommandList.resize(ComCount); + return true; +} + + +bool CMessage::SetVerify(uint in_Int) +{ + m_Verify = in_Int; + return true; +} + +bool CMessage::SetObligate(uint in_Int) +{ + m_Obligate = in_Int; + return true; +} + +bool CMessage::SetVersion(uint in_Int) +{ + m_Ver = in_Int; + return true; +} + +bool CMessage::SetCmlCount(uint in_Int) +{ + m_CmlCount = in_Int; + return true; +} + +bool CMessage::SetDataLen(uint in_Int) +{ + m_Len = in_Int; + return true; +} + + + +int CMessage::_MessageType(byte in_Comand) const +{ + int _type = 0; + switch(in_Comand) + { + case MSG_AVC_COM: _type = MSG_AVC_TYPE; + break; + case MSG_ALI_COM: _type = MSG_ALI_TYPE; + break; + + case MSG_RVC_COM: _type = MSG_RVC_TYPE; + break; + case MSG_RLI_COM: _type = MSG_RLI_TYPE; + break; + + case MSG_RPS_COM: _type = MSG_RPS_TYPE; + break; + case MSG_APS_COM: _type = MSG_APS_TYPE; + break; + + case MSG_RCL_COM: _type = MSG_RCL_TYPE; + break; + case MSG_ACL_COM: _type = MSG_ACL_TYPE; + break; + } + return _type; +} + +void CMessage::_Initialization() +{ + memset(m_GUID,0,16); + memset(m_Serial,0,2); + m_Begin = false; + m_End = false; + m_CmlCount = 0; + m_Obligate = 0; + m_Ver = 0; + m_Verify = 0; + //m_Serial = 0; + m_Len = 0; + m_Command = 0; + m_Error = 0; +} + +void CMessage::_Close() +{ + // +} + + +int CMessage::MateParam( std::string in_str ) const +{ + auto iter = m_ParamMate.find(in_str); + if (iter != m_ParamMate.end()) + { + return iter->second; + } + return -1; +} + +void CMessage::SetParam( int Pos,byte in_Param_byte ) +{ + if (Pos == -1) + { + return; + } + //ȴŽ + CMessage::SetParamLen(Pos,1); + m_ComCommandList[Pos].second.clear(); + m_ComCommandList[Pos].second.push_back(in_Param_byte); +} + +void CMessage::SetParam( int Pos,const byte* in_Param_byte_Ptr,uint len ) +{ + if (Pos == -1) + { + return; + } + SetParamLen(Pos,len); + if (in_Param_byte_Ptr == NULL) + { + return; + } + m_ComCommandList[Pos].second.clear(); + for (int index = 0; index < (int)len; index++) + { + m_ComCommandList[Pos].second.push_back(in_Param_byte_Ptr[index]); + } +} + +void CMessage::SetParam( int Pos,uint in_Param_int ) +{ + if (Pos == -1) + { + return; + } + SetParamLen(Pos,4); + byte tmpByte[4] = {0}; + IntTobyte(in_Param_int,tmpByte); + + m_ComCommandList[Pos].second.clear(); + + for (int index = 0; index < 4; index++) + { + m_ComCommandList[Pos].second.push_back(tmpByte[index]); + } +} + +uint CMessage::GetParamLen( uint int_index ) const +{ + if (int_index > m_ComCommandList.size()) + { + return -1; + } + + return m_ComCommandList[int_index].first; +} + + + +void CMessage::SetParamLen( uint int_index, int int_Value ) +{ + if (int_index > m_ComCommandList.size()) + { + return; + } + + m_ComCommandList[int_index].first = int_Value; + +} + +const byte* CMessage::GetParam( int int_index ) const +{ + if (int_index == -1) + { + return 0; + } + if (int_index > (int)m_ComCommandList.size()) + { + return 0; + } + + return ((const byte*)m_ComCommandList[int_index].second.data()); +} + + + +void CMessage::InitiaPack( int in_ComType, int in_ComNum ) +{ + m_CmlCount = in_ComNum; + m_Command = in_ComType; + SetDataLen(0); + SetVersion(MSG_VER); + SetSerial(0x00); + SetCommand(m_Command); + SetObligate(0); + SetCmlCount(m_CmlCount); + SetVerify(0); + //òȿռ + SetComListLen( 0, m_CmlCount ); + //òռ + SetComCommandList(m_CmlCount); +} + + diff --git a/Message/BaseMessage.h b/Message/BaseMessage.h new file mode 100644 index 00000000..10f47866 --- /dev/null +++ b/Message/BaseMessage.h @@ -0,0 +1,231 @@ + +#ifndef VNOC_MSG_CMESSAGE +#define VNOC_MSG_CMESSAGE + +#include "MessageDef.h" +/* +class MakeParam +{ +public: + + int MateParam( std::string in_str ) + { + + return -1; + } + + EnumFunList& returnParamMakeObject(){ return m_ParamComList;} + +private: + + EnumFunList m_ParamComList; +}; +*/ + +uint byteToInt(const byte* in_byte,size_t len); + +void IntTobyte(int in_int,byte* out_byte); + + +class CMessage +{ +public: + + friend class CMessageParser; + friend class PackMessage; + + CMessage(){ + _Initialization(); + } + + virtual ~CMessage(){ + _Close(); + } + //ȡϢ + int GetMessageType() const; + + +public: + + bool GetBeginTab() const ; + + bool GetEndTab() const; + + byte GetCommand() const; + + byte GetComListLen(uint in_index) const; + + uint GetSerial() const; + + const byte* GetGUID() const; + + const byte* GetComCommandList(uint in_index) const; + + + uint GetVerify() const; + + uint GetObligate() const; + + uint GetVersion() const; + + uint GetCmlCount() const; + + uint GetDataLen() const; + + + // Set + + bool SetCommand(byte in_byte); + + bool SetSerial(ushort in_short); + + bool SetGUID(byte* in_byte_ptr); + + bool SetComCommandList(int ComCount); + + bool SetComListLen(byte* in_byte_ptr,int CmlCount); + + bool SetVerify(uint in_Int); + + bool SetObligate(uint in_Int); + + bool SetVersion(uint in_Int); + + bool SetCmlCount(uint in_Int); + + bool SetDataLen(uint in_Int); + +protected: + + //ģ庯⴦ + + template + void SetParam( uint Pos,const std::vector PeopleList) + { + if (Pos == -1) + { + return; + } + if (PeopleList.empty()) + { + return; + } + byte tmpByte[4] = {0}; + uint PeopleLen = PeopleList.size(); + byte* tmpParam = new byte[PeopleLen * sizeof(Type)]; + memset(tmpParam,0,PeopleLen * sizeof(Type)); + int tmpInt = 0; + for (int index = 0,ParamPos = 0; index < (int)PeopleLen;index++) + { + IntTobyte(PeopleList[index],tmpByte); + for (int i = 0; i < sizeof(Type); (i++,ParamPos++)) + { + tmpParam[ParamPos] = tmpByte[i]; + } + memset(tmpByte,0,4); + } + SetParam(Pos,tmpParam,PeopleLen * sizeof(Type)); + if (tmpParam != NULL) + { + delete[] tmpParam; + tmpParam = NULL; + } + } + + + template + Type GetParam(uint int_index,std::vector& PeopleList) const + { + if (int_index != -1) + { + std::vector > ComTmpList; + if (m_ComCommandList[int_index].second.size() == 0) + { + return 1; + } + if ((m_ComCommandList[int_index].second.size() % sizeof(Type) ) != 0) + { + return 1; + } + ComTmpList.resize(((int)m_ComCommandList[int_index].second.size() / sizeof(Type))); + for (int i = 0,index = 0;index < (int)(m_ComCommandList[int_index].second.size() / sizeof(Type)) ;index++) + { + for (int j = 0; j < sizeof(Type); (i++,j++)) + { + ComTmpList[index].push_back(m_ComCommandList[int_index].second[i]); + } + } + + for (int i = 0; i < (int)ComTmpList.size(); i++) + { + byte* tempBytes = new byte[sizeof(Type)]; + memset(tempBytes,0,sizeof(Type)); + for (int j=0; j m_ComListLen; + //б IJ͸ݾָ + std::vector > > m_ComCommandList; + byte m_Command; //ָ ָעݰĹ + byte m_Serial[2]; // ָı + byte m_GUID[16]; //GUID ṩû֤ + //DWORD dwType; //Ϣ + + + uint m_Verify; //Ч Ԥ + + uint m_Obligate; //Ԥռ + uint m_Ver; //汾 ־VNOCЭİ汾 + uint m_CmlCount; // IJ͸ݾָ + uint m_Len; //峤 4ֽڣָijȣԸݽ + + // + int m_Error; + +private: + + void _Initialization(); + void _Close(); +}; + + +#endif \ No newline at end of file diff --git a/Message/MSG_ACI.h b/Message/MSG_ACI.h new file mode 100644 index 00000000..cbdf2f33 --- /dev/null +++ b/Message/MSG_ACI.h @@ -0,0 +1,107 @@ + + + +#ifndef VNOC_MSG_ACI +#define VNOC_MSG_ACI + +#include "BaseMessage.h" + +class MSG_ACI: public CMessage +{ +public: + + MSG_ACI(){ + //0x21 + BEGIN_PARAM_LIST + ADD_PARAM_LIST("RoomID") + ADD_PARAM_LIST("RoomType") + ADD_PARAM_LIST("RoomName") + ADD_PARAM_LIST("RoomRank") + ADD_PARAM_LIST("RoomState") + ADD_PARAM_LIST("RoomPassword") + ADD_PARAM_LIST("RoomPeopleNumMax") + ADD_PARAM_LIST("RoomPeopleNum") + ADD_PARAM_LIST("RoomPeopleList") + ADD_PARAM_LIST("RoomManageID") + INIT_PARAM_OBJEDT(MSG_ACI_COM) + END_PARAM_LIST + } + + virtual ~MSG_ACI(){} + +public: + + //ȡIDҪȡϢķID + uint GetRoomID() const + GetParam_t_int_r("RoomID",4); + + uint GetRoomType() const + GetParam_t_int_r("RoomType",4); + + const byte* GetRoomName() const + GetParam_t_r("RoomName"); + + uint GetRoomRank() const + GetParam_t_int_r("RoomRank",4); + + uint GetRoomState() const + GetParam_t_int_r("RoomState",4); + + const byte* GetRoomPassword() const + GetParam_t_r("RoomPassword"); + + uint GetRoomPeopleNumMax() const + GetParam_t_int_r("RoomPeopleNumMax",4); + + uint GetRoomPeopleNum() const + GetParam_t_int_r("RoomPeopleNum",4); + + int GetRoomPeopleList(std::vector& PeopleList) const + GetParam_t_tamp_r("RoomPeopleList",int,PeopleList); + + uint GetRoomManageID() const + GetParam_t_int_r("RoomManageID",4); + + void SetRoomID(uint in_int) + SetParam_t("RoomID",in_int); + + void SetRoomType(uint in_int) + SetParam_t("RoomType",in_int); + + void SetRoomName(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("RoomName",in_byte_ptr,len); + + void SetRoomRank(uint in_int) + SetParam_t("RoomRank",in_int); + + void SetRoomState(uint in_int) + SetParam_t("RoomState",in_int); + + void SetRoomPassword(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("RoomPassword",in_byte_ptr,len); + + void SetRoomPeopleNumMax(uint in_int) + SetParam_t("RoomPeopleNumMax",in_int); + + void SetRoomPeopleNum(uint in_int) + SetParam_t("RoomPeopleNum",in_int); + + void SetRoomPeopleList(std::vector PeopleList) + SetParam_t_tamp("RoomPeopleList",int,PeopleList); + + void SetRoomManageID(uint in_int) + SetParam_t("RoomManageID",in_int); + + int GetRoomNameLen() const + GetParamLen_t_r("RoomName"); + + int GetRoomPasswordLen() const + GetParamLen_t_r("RoomPassword"); + + int GetPeopleListSize() const{ + return (CMessage::GetParamLen(8) / 4); + } +}; + + +#endif \ No newline at end of file diff --git a/Message/MSG_ACL.h b/Message/MSG_ACL.h new file mode 100644 index 00000000..42c4ac12 --- /dev/null +++ b/Message/MSG_ACL.h @@ -0,0 +1,34 @@ + + +#ifndef VNOC_ACL +#define VNOC_ACL + +#include "BaseMessage.h" + +class MSG_ACL:public CMessage +{ +public: + MSG_ACL(){ + //0x1F + BEGIN_PARAM_LIST + ADD_PARAM_LIST("RoomList") + INIT_PARAM_OBJEDT(MSG_ACL_COM) + END_PARAM_LIST + } + virtual ~MSG_ACL(){} + +public: + + int GetRoomList(std::vector& RoomList) const + GetParam_t_tamp_r("RoomList",int,RoomList); + + void SetRoomList(std::vector RoomList) + SetParam_t_tamp("RoomList",int,RoomList); + + int GetRoomListSize() const{ + return (CMessage::GetParamLen(0) / 4); + } + +}; + +#endif \ No newline at end of file diff --git a/Message/MSG_ACS.h b/Message/MSG_ACS.h new file mode 100644 index 00000000..cf81d1a7 --- /dev/null +++ b/Message/MSG_ACS.h @@ -0,0 +1,36 @@ +#ifndef VNOC_MSG_ACS +#define VNOC_MSG_ACS + +#include "BaseMessage.h" +//ACS(༶Ϣ֪ͬͨȷ) + +class MSG_ACS:public CMessage +{ + +public: + + MSG_ACS(){ + //0x1A + BEGIN_PARAM_LIST + ADD_PARAM_LIST("MessageSynchro") + INIT_PARAM_OBJEDT(MSG_ACS_COM) + END_PARAM_LIST + } + + virtual ~MSG_ACS(){} + +public: + //༶Ϣ֪ͬͨ + const byte* GetMessageSynchro() const + GetParam_t_r("MessageSynchro"); + + void SetMessageSynchro(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("MessageSynchro",in_byte_ptr,len); + + int GetMessageSynchroLen() const + GetParamLen_t_r("MessageSynchro"); + +}; + + +#endif \ No newline at end of file diff --git a/Message/MSG_ALI.h b/Message/MSG_ALI.h new file mode 100644 index 00000000..478406c5 --- /dev/null +++ b/Message/MSG_ALI.h @@ -0,0 +1,54 @@ + + +#ifndef VNOC_MSG_ALI +#define VNOC_MSG_ALI + +#include "BaseMessage.h" + +//ALI(¼Ӧ) +class MSG_ALI:public CMessage +{ + +public: + + MSG_ALI(){ + //0x17 + BEGIN_PARAM_LIST + ADD_PARAM_LIST("LoginResult") + ADD_PARAM_LIST("Token") + ADD_PARAM_LIST("ATLGUID") + INIT_PARAM_OBJEDT(MSG_ALI_COM) + END_PARAM_LIST + } + + virtual ~MSG_ALI(){} + +public: + //¼1ֽڣ־˴ε¼Ľ + uint GetLoginResult() const + GetParam_t_byte_r_int("LoginResult",1); + //Ƴȣ4ֽڣ0x00 00 00 10ûʺűijȣλΪֽ + uint GetToken() const + GetParam_t_byte_r_int("Token",4); + //ƣ16ֽڣһGUID ʺ֤ͨɣͨݰͻˣָ֮ڰͷϴ + const byte* GetATLGUID() const + GetParam_t_r("ATLGUID"); + + void SetLoginResult(byte in_byte) + SetParam_t("LoginResult",in_byte); + + void SetToken(const byte* in_byte_ptr,size_t len = 4) + SetParam_t_ptr("Token",in_byte_ptr,len); + + void SetATLGUID(const byte* in_byte_ptr, size_t len = 16) + SetParam_t_ptr("ATLGUID",in_byte_ptr,len); + + + int GetATLGUIDLen() const + GetParamLen_t_r("ATLGUID"); + + int GetTokenLen() const + GetParamLen_t_r("Token"); +}; + +#endif \ No newline at end of file diff --git a/Message/MSG_APG.h b/Message/MSG_APG.h new file mode 100644 index 00000000..a80ba0ca --- /dev/null +++ b/Message/MSG_APG.h @@ -0,0 +1,33 @@ +#ifndef VNOC_MSG_APG +#define VNOC_MSG_APG + + +#include "BaseMessage.h" + +//APG עʺţ +class MSG_APG:public CMessage +{ + +public: + + MSG_APG(){ + //0x13 + BEGIN_PARAM_LIST + ADD_PARAM_LIST("RetTag") + INIT_PARAM_OBJEDT(MSG_APG_COM) + END_PARAM_LIST + } + + virtual ~MSG_APG(){} + +public: + //ر + uint GetRetTag() const + GetParam_t_byte_r_int("RetTag",4); + + void SetRetTag(uint in_int) + SetParam_t("RetTag",in_int); +}; + + +#endif \ No newline at end of file diff --git a/Message/MSG_APS.h b/Message/MSG_APS.h new file mode 100644 index 00000000..d8139c46 --- /dev/null +++ b/Message/MSG_APS.h @@ -0,0 +1,39 @@ + + + +#ifndef VNOC_MSG_APS +#define VNOC_MSG_APS + +#include "BaseMessage.h" +//APS(Ϣ֪ͬͨȷ) + +class MSG_APS:public CMessage +{ + +public: + + MSG_APS(){ + //0x19 + BEGIN_PARAM_LIST + ADD_PARAM_LIST("MessageSynchro") + INIT_PARAM_OBJEDT(MSG_APS_COM) + END_PARAM_LIST + } + + virtual ~MSG_APS(){} + +public: + //Ϣ֪ͬͨ + const byte* GetMessageSynchro() const + GetParam_t_r("MessageSynchro"); + + void SetMessageSynchro(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("MessageSynchro",in_byte_ptr,len); + + int GetMessageSynchroLen() const + GetParamLen_t_r("MessageSynchro"); + +}; + + +#endif \ No newline at end of file diff --git a/Message/MSG_AVC.h b/Message/MSG_AVC.h new file mode 100644 index 00000000..a2fc4e22 --- /dev/null +++ b/Message/MSG_AVC.h @@ -0,0 +1,53 @@ + +#ifndef VNOC_MSG_AVC +#define VNOC_MSG_AVC + +#include "BaseMessage.h" + +//AVC(ȡ֤Ӧ) +class MSG_AVC: public CMessage +{ +public: + + MSG_AVC(){ + //0x15 + BEGIN_PARAM_LIST + ADD_PARAM_LIST("LoginTag") + ADD_PARAM_LIST("CaptchaType") + ADD_PARAM_LIST("Captcha") + INIT_PARAM_OBJEDT(MSG_AVC_COM) + END_PARAM_LIST + } + + virtual ~MSG_AVC(){} + +public: + //ȡ֤1ֽڣ־˴ε¼Ľ + uint GetLoginTag() const + GetParam_t_byte_r_int("LoginTag",1); + //֤ͣ־֤õĺ壬֤Ͷһö٣ + uint GetCaptchaType() const + GetParam_t_byte_r_int("CaptchaType",1); + //֤壺֤峤ȲָСʽͼ + const byte* GetCaptcha() const + GetParam_t_r("Captcha"); + + + void SetLoginTag(byte in_byte) + SetParam_t("LoginTag",in_byte); + + void SetCaptchaType(byte in_byte) + SetParam_t("CaptchaType",in_byte); + + void SetCaptcha(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("Captcha",in_byte_ptr,len); + + + + int GetCaptchaLen() const + GetParamLen_t_r("Captcha"); + +}; + + +#endif \ No newline at end of file diff --git a/Message/MSG_RCI.h b/Message/MSG_RCI.h new file mode 100644 index 00000000..087e1ec3 --- /dev/null +++ b/Message/MSG_RCI.h @@ -0,0 +1,31 @@ + + +#ifndef VNOC_MSG_RCI +#define VNOC_MSG_RCI + +#include "BaseMessage.h" + +class MSG_RCI: public CMessage +{ +public: + + MSG_RCI(){ + //0x20 + BEGIN_PARAM_LIST + ADD_PARAM_LIST("RoomID") + INIT_PARAM_OBJEDT(MSG_RCI_COM) + END_PARAM_LIST + } + + virtual ~MSG_RCI(){} + +public: + //ȡIDҪȡϢķID + uint GetRoomID() const + GetParam_t_byte_r_int("RoomID",4); + + void SetRoomID(uint in_int) + SetParam_t("RoomID",in_int); +}; + +#endif \ No newline at end of file diff --git a/Message/MSG_RCL.h b/Message/MSG_RCL.h new file mode 100644 index 00000000..0725b080 --- /dev/null +++ b/Message/MSG_RCL.h @@ -0,0 +1,26 @@ + +#ifndef VNOC_MSG_RCL +#define VNOC_MSG_RCL + +#include "BaseMessage.h" + +class MSG_RCL:public CMessage +{ +public: + MSG_RCL(){ + //0x1E + BEGIN_PARAM_LIST + //ADD_PARAM_LIST("MachineAddress") + INIT_PARAM_OBJEDT(MSG_RCL_COM) + END_PARAM_LIST + } + + // + //uint GetUserType() const; + + //void SetUserType(uint in_int); + + virtual ~MSG_RCL(){} +}; + +#endif \ No newline at end of file diff --git a/Message/MSG_RLI.h b/Message/MSG_RLI.h new file mode 100644 index 00000000..6d3631a6 --- /dev/null +++ b/Message/MSG_RLI.h @@ -0,0 +1,58 @@ + + +#ifndef VNOC_MSG_RLI +#define VNOC_MSG_RLI + +#include "BaseMessage.h" + +//RLI(¼) +class MSG_RLI:public CMessage +{ + +public: + + MSG_RLI(){ + //0x16 + BEGIN_PARAM_LIST + ADD_PARAM_LIST("VerificationCode") + ADD_PARAM_LIST("AccountNumber") + ADD_PARAM_LIST("Password") + INIT_PARAM_OBJEDT(MSG_RLI_COM) + END_PARAM_LIST + } + virtual ~MSG_RLI(){} + +public: + //֤룺δ֪ȣΪAUTͼƬַɣ˲ڷӦư󶨣һ֤-ӳ䣩 + const byte* GetVerificationCode() const + GetParam_t_r("VerificationCode"); + //ûʺţûʺűĶ + const byte* GetAccountNumber() const + GetParam_t_r("AccountNumber"); + //û룺뾭Ķ + const byte* GetPassword() const + GetParam_t_r("Password"); + + + void SetVerificationCode(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("VerificationCode",in_byte_ptr,len); + + void SetAccountNumber(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("AccountNumber",in_byte_ptr,len); + + void SetPassword(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("Password",in_byte_ptr,len); + + + int GetVerificationCodeLen() const + GetParamLen_t_r("VerificationCode"); + + int GetAccountNumberLen() const + GetParamLen_t_r("AccountNumber"); + + int GetPasswordLen() const + GetParamLen_t_r("Password"); +}; + + +#endif \ No newline at end of file diff --git a/Message/MSG_RPG.h b/Message/MSG_RPG.h new file mode 100644 index 00000000..feb56b6e --- /dev/null +++ b/Message/MSG_RPG.h @@ -0,0 +1,78 @@ +#ifndef VNOC_MSG_RPG +#define VNOC_MSG_RPG + + +#include "BaseMessage.h" + +//RPG עʺţ +class MSG_RPG:public CMessage +{ + +public: + + MSG_RPG(){ + //0x12 + BEGIN_PARAM_LIST + ADD_PARAM_LIST("Rank") + ADD_PARAM_LIST("Nickname") + ADD_PARAM_LIST("Autograph") + ADD_PARAM_LIST("HeadForm") + ADD_PARAM_LIST("HeadPortrait") + ADD_PARAM_LIST("EmailAddress") + INIT_PARAM_OBJEDT(MSG_RPG_COM) + END_PARAM_LIST + } + + virtual ~MSG_RPG(){} + +public: + //ûȨ + uint GetRank() const + GetParam_t_byte_r_int("Rank",1); + //dz + const byte* GetNickname() const + GetParam_t_r("Nickname"); + //ǩ + const byte* GetAutograph() const + GetParam_t_r("Autograph"); + //ͷʽ + uint GetHeadForm() const + GetParam_t_byte_r_int("HeadForm",1); + //ͷ + const byte* GetHeadPortrait() const + GetParam_t_r("HeadPortrait"); + + + void SetRank(byte in_byte) + SetParam_t("Rank",in_byte); + + void SetNickname(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("Nickname",in_byte_ptr,len); + + void SetAutograph(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("Autograph",in_byte_ptr,len); + + void SetHeadForm(byte in_byte) + SetParam_t("HeadForm",in_byte); + + void SetHeadPortrait(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("HeadPortrait",in_byte_ptr,len); + + void SetEmailAddress(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("EmailAddress",in_byte_ptr,len); + + int GetNicknameLen() const + GetParamLen_t_r("Nickname"); + + int GetAutographLen() const + GetParamLen_t_r("Autograph"); + + int GetHeadPortraitLen() const + GetParamLen_t_r("HeadPortrait"); + + int GetEmailAddressLen() const + GetParamLen_t_r("EmailAddress"); +}; + + +#endif \ No newline at end of file diff --git a/Message/MSG_RPS.h b/Message/MSG_RPS.h new file mode 100644 index 00000000..82dace1b --- /dev/null +++ b/Message/MSG_RPS.h @@ -0,0 +1,72 @@ +#ifndef VNOC_MSG_RPS +#define VNOC_MSG_RPS + + +#include "BaseMessage.h" + +//RPS(Ϣ֪ͬͨ) +class MSG_RPS:public CMessage +{ + +public: + + MSG_RPS(){ + //0x18 + BEGIN_PARAM_LIST + ADD_PARAM_LIST("Rank") + ADD_PARAM_LIST("Nickname") + ADD_PARAM_LIST("Autograph") + ADD_PARAM_LIST("HeadForm") + ADD_PARAM_LIST("HeadPortrait") + INIT_PARAM_OBJEDT(MSG_RPS_COM) + END_PARAM_LIST + } + + virtual ~MSG_RPS(){} + +public: + //ûȨ + uint GetRank() const + GetParam_t_byte_r_int("Rank",1); + //dz + const byte* GetNickname() const + GetParam_t_r("Nickname"); + //ǩ + const byte* GetAutograph() const + GetParam_t_r("Autograph"); + //ͷʽ + uint GetHeadForm() const + GetParam_t_byte_r_int("HeadForm",1); + //ͷ + const byte* GetHeadPortrait() const + GetParam_t_r("HeadPortrait"); + + + void SetRank(byte in_byte) + SetParam_t("Rank",in_byte); + + void SetNickname(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("Nickname",in_byte_ptr,len); + + void SetAutograph(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("Autograph",in_byte_ptr,len); + + void SetHeadForm(byte in_byte) + SetParam_t("HeadForm",in_byte); + + void SetHeadPortrait(const byte* in_byte_ptr,size_t len) + SetParam_t_ptr("HeadPortrait",in_byte_ptr,len); + + + int GetNicknameLen() const + GetParamLen_t_r("Nickname"); + + int GetAutographLen() const + GetParamLen_t_r("Autograph"); + + int GetHeadPortraitLen() const + GetParamLen_t_r("HeadPortrait"); +}; + + +#endif \ No newline at end of file diff --git a/Message/MSG_RVC.h b/Message/MSG_RVC.h new file mode 100644 index 00000000..ca290aea --- /dev/null +++ b/Message/MSG_RVC.h @@ -0,0 +1,35 @@ + + +#ifndef VNOC_MSG_RVC +#define VNOC_MSG_RVC + +#include "BaseMessage.h" + +//RVC(ȡ֤) +class MSG_RVC: public CMessage +{ +public: + + MSG_RVC(){ + //0x14 + BEGIN_PARAM_LIST + ADD_PARAM_LIST("MachineAddress") + INIT_PARAM_OBJEDT(MSG_RVC_COM) + END_PARAM_LIST + } + virtual ~MSG_RVC(){} + +public: + //ַ + const byte* GetMachineAddress() const + GetParam_t_r("MachineAddress"); + + void SetMachineAddress(const byte* in_byte_ptr, size_t len) + SetParam_t_ptr("MachineAddress",in_byte_ptr,len); + + int GetMachineAddressLen()const + GetParamLen_t_r("MachineAddress"); +}; + + +#endif \ No newline at end of file diff --git a/Message/MSG_UNION.h b/Message/MSG_UNION.h new file mode 100644 index 00000000..9ad334aa --- /dev/null +++ b/Message/MSG_UNION.h @@ -0,0 +1,19 @@ + + +#include "MSG_ACI.h" +#include "MSG_RCI.h" + +#include "MSG_ACL.h" +#include "MSG_RCL.h" + +#include "MSG_AVC.h" +#include "MSG_RVC.h" + +#include "MSG_APS.h" +#include "MSG_RPS.h" + +#include "MSG_ALI.h" +#include "MSG_RLI.h" + +#include "MSG_APG.h" +#include "MSG_RPG.h" diff --git a/Message/MessageDef.h b/Message/MessageDef.h new file mode 100644 index 00000000..6b6d5c9c --- /dev/null +++ b/Message/MessageDef.h @@ -0,0 +1,146 @@ + + +#ifndef VNOC_MESSAGE_DEF +#define VNOC_MESSAGE_DEF + + +/* +#define MSG_ERROR_BDMISS 1 +#define MSG_ERROR_COMMAND 2 +#define MSG_ERROR_PARAM 3 +#define MSG_ERROR_LEN 4*/ + +#include +#include +#include +#include +#include + +#define MSG_BEGIN 0x56 // 'V' ϢĿʼ +#define MSG_END 0x43 // 'C' ϢĽ +#define MSG_VER 0 //汾 + +#define MSG_CLASS_BEGIN 1 +#define MSG_CLASS_END 1 +#define MSG_CLASS_LEN 4 +#define MSG_CLASS_VER 1 +#define MSG_CLASS_SERIAL 2 +#define MSG_CLASS_GUID 16 +#define MSG_CLASS_COMMAND 1 +#define MSG_CLASS_OBL 4 +#define MSG_CLASS_PARAMCONST 1 +#define MSG_CLASS_VERIFY 2 //Ч δĬΪ2ֽ +#define MSG_CLASS_PARAM 4 + +#define VER_INDEX MSG_CLASS_VER +#define SER_INDEX (MSG_CLASS_VER + MSG_CLASS_SERIAL) +#define LEN_INDEX (MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL) +#define GUID_INDEX (MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL + MSG_CLASS_GUID) +#define COM_INDEX (MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL + MSG_CLASS_COMMAND + MSG_CLASS_GUID) +#define OBL_INDEX (MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL + MSG_CLASS_GUID + MSG_CLASS_COMMAND + MSG_CLASS_OBL) +#define PAC_INDEX (MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL + MSG_CLASS_GUID + MSG_CLASS_COMMAND + MSG_CLASS_OBL + MSG_CLASS_PARAMCONST) + + +enum MSGTYPE +{ + MSGTYPE_NULL, + + MSG_AVC_TYPE, + MSG_RVC_TYPE, + + MSG_ALI_TYPE, + MSG_RLI_TYPE, + + MSG_RPS_TYPE, + MSG_APS_TYPE, + + MSG_ACI_TYPE, + MSG_RCI_TYPE, + + MSG_ACL_TYPE, + MSG_RCL_TYPE, + + MSGTYPE_END +}; + +enum MSGCONMMAND +{ + MSGCONMMAND_NULL, + + MSG_RPG_COM = 0x12, + MSG_APG_COM = 0x13, + + MSG_RVC_COM = 0x14, + MSG_AVC_COM = 0x15, + + MSG_RLI_COM = 0x16, + MSG_ALI_COM = 0x17, + + MSG_RPS_COM = 0x18, + MSG_APS_COM = 0x19, + + MSG_RCI_COM = 0x20, + MSG_ACI_COM = 0x21, + + MSG_ACS_COM = 0x1A, + + + + MSG_RCL_COM = 0x1E, + MSG_ACL_COM = 0x1F, + +}; + +typedef unsigned char byte; +typedef unsigned int uint; +typedef unsigned short ushort; + +typedef std::map EnumFunList; +typedef std::map::iterator EnumFunList_Iterator; + +typedef std::vector ByteArr; + +// ʹС˻ +#define BigLittleSwap16(A) ((((ushort)(A) & 0xff00) >> 8) | \ + (((ushort)(A) & 0x00ff) << 8)) + +// ʹС˻ +#define BigLittleSwap32(A) ((((uint)(A) & 0xff000000) >> 24) | \ + (((uint)(A) & 0x00ff0000) >> 8) | \ + (((uint)(A) & 0x0000ff00) << 8) | \ + (((uint)(A) & 0x000000ff) << 24)) + + + +#define OBJECT_PARAM_LIST m_ParamMate + +#define Mate_Param MateParam + +#define BEGIN_PARAM_LIST int __Param_List_Begin = 0; + +#define ADD_PARAM_LIST(PARAM_NAME) OBJECT_PARAM_LIST[PARAM_NAME] = __Param_List_Begin++; + +#define INIT_PARAM_OBJEDT(COMMAND_TAG) CMessage::InitiaPack(COMMAND_TAG,__Param_List_Begin); + +#define END_PARAM_LIST + +#define SetParam_t_ptr(x,y,z) {SetParam(Mate_Param(x),y,z);} + +#define SetParam_t_tamp(x,y,z) {SetParam(Mate_Param(x),z);} + +#define SetParam_t(x,y) {SetParam(Mate_Param(x),y);} + +#define GetParamLen_t_r(x) {return CMessage::GetParamLen(Mate_Param(x));} + +//#define GetParam_t(x) {GetParam(x);} + +#define GetParam_t_r(x) { return GetParam(Mate_Param(x)); } + +#define GetParam_t_tamp_r(x,y,z) { return GetParam(Mate_Param(x),z); } + +#define GetParam_t_byte_r_int(x,len) { return byteToInt(GetParam(Mate_Param(x)),len); } + +#define GetParam_t_int_r(x,len) { return BigLittleSwap32(byteToInt(GetParam(Mate_Param(x)),len)); } + +#endif + diff --git a/Message/MessageErrorDefine.hpp b/Message/MessageErrorDefine.hpp new file mode 100644 index 00000000..f6aab44f --- /dev/null +++ b/Message/MessageErrorDefine.hpp @@ -0,0 +1,15 @@ +#pragma once +#include +////////////////////////////////////////////////////////////////////////// +// csеĴ붨 + +const wchar_t* GetErrorDescription(MsgErrorCode errCode); + +enum VNOCMessageErrorEnum +{ + MsgError_None, + MsgError_General_NetLinkFail, + MsgError_General_NetLinkTimeout, +}; + + diff --git a/Message/MessageParser.cpp b/Message/MessageParser.cpp index ed6db3fd..0e905aac 100644 --- a/Message/MessageParser.cpp +++ b/Message/MessageParser.cpp @@ -11,43 +11,34 @@ using namespace std; CMessage* CMessageParser::_MessageType() { CMessage* msg_str = NULL; - switch (_GetMessageType()) + switch (m_Instruct) { - case MSG_AVC_TYPE: msg_str = new MSG_AVC; + case MSG_AVC_COM: msg_str = new MSG_AVC; break; - case MSG_ALI_TYPE: msg_str = new MSG_ALI; + case MSG_ALI_COM: msg_str = new MSG_ALI; break; - case MSG_RVC_TYPE: msg_str = new MSG_RVC; + case MSG_RVC_COM: msg_str = new MSG_RVC; break; - case MSG_RLI_TYPE: msg_str = new MSG_RLI; + case MSG_RLI_COM: msg_str = new MSG_RLI; break; - case MSG_RPS_TYPE: msg_str = new MSG_RPS; + case MSG_RPS_COM: msg_str = new MSG_RPS; break; - case MSG_APS_TYPE: msg_str = new MSG_APS; + case MSG_APS_COM: msg_str = new MSG_APS; break; - } - return msg_str; -} - -int CMessageParser::_GetMessageType() -{ - int _type = 0; - switch(m_Instruct) - { - case MSG_AVC_COM: _type = MSG_AVC_TYPE; + case MSG_RPG_COM: msg_str = new MSG_RPG; break; - case MSG_ALI_COM: _type = MSG_ALI_TYPE; + case MSG_APG_COM: msg_str = new MSG_APG; break; - case MSG_RVC_COM: _type = MSG_RVC_TYPE; + case MSG_RCI_COM: msg_str = new MSG_RCI; break; - case MSG_RLI_COM: _type = MSG_RLI_TYPE; + case MSG_ACI_COM: msg_str = new MSG_ACI; break; - case MSG_RPS_COM: _type = MSG_RPS_TYPE; + case MSG_ACL_COM: msg_str = new MSG_ACL; break; - case MSG_APS_COM: _type = MSG_APS_TYPE; + case MSG_RCL_COM: msg_str = new MSG_RCL; break; } - return _type; + return msg_str; } int CMessageParser::_Head(CMessage* _Messsage,byte* lpszData,size_t len) @@ -67,6 +58,8 @@ int CMessageParser::_Head(CMessage* _Messsage,byte* lpszData,size_t len) return -1; } + + if(lpszData[0] != MSG_BEGIN ) { _Messsage->m_Begin = false; @@ -82,12 +75,11 @@ int CMessageParser::_Head(CMessage* _Messsage,byte* lpszData,size_t len) //ȡ CHECLUP_LEN(SER_INDEX + 1, len ); - for (int index = 0; index < 2; index++) + nPos += VER_INDEX + 1;/*ͷǿռ*/ + for (int index = 0; index < 2; index++,nPos++) { - _Messsage->m_Serial[index] = (int)lpszData[SER_INDEX - index]; + _Messsage->m_Serial[index] = (int)lpszData[nPos]; } - //ת մ˴ - LittleSwapBigByte(_Messsage->m_Serial,2); //ȡ峤 ˴ for(nPos = 0;nPos < MSG_CLASS_LEN; nPos++) @@ -102,12 +94,12 @@ int CMessageParser::_Head(CMessage* _Messsage,byte* lpszData,size_t len) CHECLUP_LEN(COM_INDEX + 1, len ); //ȡGUID С˶˴ - for(nPos = 0;nPos < MSG_CLASS_GUID; nPos++) + nPos += 4; + for(int index = 0;index < MSG_CLASS_GUID; nPos++,index++) { - _Messsage->m_GUID[nPos] = lpszData[(GUID_INDEX)- nPos]; + _Messsage->m_GUID[index] = lpszData[ nPos ]; } //ת մ˴ - LittleSwapBigByte(_Messsage->m_GUID,MSG_CLASS_GUID); _Messsage->m_Command = (int)lpszData[COM_INDEX]; @@ -145,12 +137,15 @@ int CMessageParser::_Body(CMessage* _Messsage,byte* lpszData,size_t len) _Messsage->m_ComListLen.clear(); //մ˴ - for(nPos = 0;nPos < (int)(MSG_CLASS_PARAM * _Messsage->m_CmlCount); nPos++) + nPos = PAC_INDEX + 1; + for(int index = 0;index < (int)(MSG_CLASS_PARAM * _Messsage->m_CmlCount); index++,nPos++) { - _Messsage->m_ComListLen.push_back(lpszData[(PAC_INDEX +(MSG_CLASS_PARAM * _Messsage->m_CmlCount)) -nPos]); + _Messsage->m_ComListLen.push_back(lpszData[nPos]); } - int* tmpCmlListLen = new int[_Messsage->m_CmlCount]; + //int* tmpCmlListLen = new int[_Messsage->m_CmlCount]; + std::vector tmpCmlListLen; + tmpCmlListLen.resize(_Messsage->m_CmlCount); byte tmpComlLen[MSG_CLASS_PARAM] = {0}; @@ -167,14 +162,14 @@ int CMessageParser::_Body(CMessage* _Messsage,byte* lpszData,size_t len) { tmpComlLen[index] = _Messsage->m_ComListLen[j]; } - ParamLen += byteToInt(tmpComlLen,4); + ParamLen += BigLittleSwap32(byteToInt(tmpComlLen,4)); memset(tmpComlLen,0,MSG_CLASS_PARAM); } + int j = 0; for(int i = 0;i < (int)(_Messsage->m_CmlCount);i++) { - int j = i * 4; - for (int index = 0; index < MSG_CLASS_PARAM; j++,index++) + for (int index = 0; index < MSG_CLASS_PARAM;j++,index++) { tmpComlLen[index] = _Messsage->m_ComListLen[j]; } @@ -182,38 +177,25 @@ int CMessageParser::_Body(CMessage* _Messsage,byte* lpszData,size_t len) if (tmpComlLen != NULL) { - tmpCmlListLen[i] = byteToInt(tmpComlLen,4); + tmpCmlListLen[i] = BigLittleSwap32(byteToInt(tmpComlLen,4)); //ȡ - CHECLUP_LEN((PAC_INDEX + (MSG_CLASS_PARAM * _Messsage->m_CmlCount) + ParamLen) + 1, len ); + //CHECLUP_LEN((PAC_INDEX + (MSG_CLASS_PARAM * _Messsage->m_CmlCount) + ParamLen) + 1, len ); memset(tmpComlLen,0,MSG_CLASS_PARAM); - _Messsage->m_ComCommandList[i].clear(); + _Messsage->m_ComCommandList[i].second.clear(); if (i == 0) { - TmpIndex = (PAC_INDEX + (MSG_CLASS_PARAM * _Messsage->m_CmlCount) + ParamLen); + TmpIndex = (PAC_INDEX + (MSG_CLASS_PARAM * _Messsage->m_CmlCount)) + 1; } - else + _Messsage->m_ComCommandList[i].first = tmpCmlListLen[i]; + for (int index = 0; index < tmpCmlListLen[i]; index++, TmpIndex++ ) { - ParamPos += tmpCmlListLen[i - 1]; - TmpIndex = ((PAC_INDEX + (MSG_CLASS_PARAM * _Messsage->m_CmlCount) + ParamLen) - ParamPos); - } - - for (int index = 0; index < tmpCmlListLen[i]; index++ ) - { - _Messsage->m_ComCommandList[i].push_back(lpszData[TmpIndex - index]); + _Messsage->m_ComCommandList[i].second.push_back(lpszData[TmpIndex]); VerifyPos++; } - LittleSwapBigByte(&_Messsage->m_ComCommandList[i]); } } - - if (tmpCmlListLen != NULL) - { - delete [] tmpCmlListLen; - tmpCmlListLen = NULL; - } - return VerifyPos; } @@ -281,3 +263,43 @@ CMessage* CMessageParser::Parse(byte* lpszData,size_t len) return m_MessageStr; } + +int CMessageParser::Check( byte* lpszDate,size_t len ) +{ + int Begin = 0; + int End = 0; + int index = 0; + + for(index = 0; index < (int)len;index++) + { + if (lpszDate[index] == MSG_BEGIN) + { + Begin = index; + break; + } + } + index = 0; + if (lpszDate[len - 1] == MSG_END) + { + End = len; + } + else + { + if (len < 2) + { + return -1; + } + else + { + return Check(lpszDate,len - 1); + } + } + + + if ( End == 0 ) + { + return -1; + } + + return End; +} diff --git a/Message/MessageParser.h b/Message/MessageParser.h index 09e1850b..7132e796 100644 --- a/Message/MessageParser.h +++ b/Message/MessageParser.h @@ -2,8 +2,7 @@ #pragma once -#include "MsgDef.h" - +#include "MSG_UNION.h" class CMessageParser { @@ -11,6 +10,7 @@ class CMessageParser CMessageParser(){ m_Instruct = 0; + m_SubPos = 0; } ~CMessageParser(){ @@ -21,11 +21,15 @@ class CMessageParser // CMessage* Parse(byte* lpszData,size_t len); + static int Check(byte* lpszDate,size_t len); //Чij + private: CMessage* m_MessageStr; // + int m_SubPos; + byte m_Instruct; //ָ ָעݰĹ int _Head(CMessage* _Messsage,byte* lpszData,size_t len); @@ -35,7 +39,6 @@ class CMessageParser int _Tail(CMessage* _Messsage,byte* lpszData,int ParamLen,size_t len); CMessage* _MessageType(); - int _GetMessageType(); int _CheckUpLen(int Index,size_t len) { diff --git a/Message/MsgDef.cpp b/Message/MsgDef.cpp deleted file mode 100644 index daf731d6..00000000 --- a/Message/MsgDef.cpp +++ /dev/null @@ -1,827 +0,0 @@ - -#include "MsgDef.h" - -#include - -//CMessageParser - - -using namespace std; - -void LittleSwapBigByte(byte* in_byte_ptr,size_t len) -{ - byte* tmpByte_ptr = new byte[len]; - if (in_byte_ptr != NULL) - { - for (int index = 0,Pos = 1; index < (int)len; index++,Pos++) - { - tmpByte_ptr[index] = in_byte_ptr[len - Pos]; - } - memcpy(in_byte_ptr,tmpByte_ptr,len); - } - delete [] tmpByte_ptr; -} - -void LittleSwapBigByte(ByteArr* arr) -{ - ByteArr tmpArr; - if (!arr->empty()) - { - tmpArr.resize(arr->size()); - std::copy(arr->begin(),arr->end(),tmpArr.begin()); - arr->clear(); - for (int index = 0,Pos = 1; index < (int)tmpArr.size(); index++,Pos++) - { - arr->push_back(tmpArr[tmpArr.size() - Pos]); - } - } -} - -uint byteToInt(const byte* in_byte,size_t len) -{ - byte tmpByte[4] = {0}; - if (in_byte == NULL) - { - return 0; - } - - for (int index = 0; index < (int)len; index++) - { - tmpByte[index] = in_byte[index]; - } - - uint* lpDataLen = NULL; - lpDataLen = (uint *)tmpByte; - return (*lpDataLen); -} - -void IntTobyte(int in_int,byte* out_byte) -{ - if (out_byte == NULL) - { - return; - } - for(int i = 0; i < 4; i++) - { - out_byte[i]=(byte)(in_int>>(24-i*8)); - } -} - - -int CMessage::GetMessageType() const -{ -// if (GetBeginTab() != true || GetEndTab() != true) -// { -// return -1; - // } - - int _type = 0; - switch(m_Command) - { - case MSG_AVC_COM: _type = MSG_AVC_TYPE; - break; - case MSG_ALI_COM: _type = MSG_ALI_TYPE; - break; - case MSG_RVC_COM: _type = MSG_RVC_TYPE; - break; - case MSG_RLI_COM: _type = MSG_RLI_TYPE; - break; - case MSG_RPS_COM: _type = MSG_RPS_TYPE; - break; - case MSG_APS_COM: _type = MSG_APS_TYPE; - break; - } - return _type; -} - -bool CMessage::GetBeginTab() const -{ - return m_Begin; -} - -bool CMessage::GetEndTab() const -{ - return m_Begin; -} - -byte CMessage::GetCommand() const -{ - return m_Command; -} - -byte* CMessage::GetComListLen() const -{ - return (byte*)(m_ComListLen.data()); -} - -uint CMessage::GetSerial() const -{ - return BigLittleSwap16(byteToInt(m_Serial,2)); -} - -const byte* CMessage::GetGUID() const -{ - return m_GUID; -} - -std::vector CMessage::GetComCommandList()const -{ - return m_ComCommandList; -} - -uint CMessage::GetVerify() const -{ - return m_Verify; -} - -uint CMessage::GetObligate() const -{ - return m_Obligate; -} - -uint CMessage::GetVersion() const -{ - return m_Ver; -} - -uint CMessage::GetCmlCount() const -{ - return m_CmlCount; -} - -uint CMessage::GetDataLen() const -{ - return m_Len; -} - - -// Set - -bool CMessage::SetCommand(byte in_byte) -{ - m_Command = in_byte; - return true; -} - - -bool CMessage::SetComListLen(byte* in_byte_ptr,int CmlCount) -{ - if (in_byte_ptr != NULL) - { - if (CmlCount != 0) - { - m_ComListLen.clear(); - for (int index = 0; index < (CmlCount * 4); index++) - { - m_ComListLen.push_back(in_byte_ptr[index]); - } - } - else - { - m_ComListLen.clear(); - } - } - else - { - m_ComListLen.resize(CmlCount * 4); - } - return true; -} - -bool CMessage::SetSerial(ushort in_short) -{ - byte tmpbyte[4] = {0}; - if (m_Serial != NULL) - { - IntTobyte(in_short,tmpbyte); - //ȡ2λ - for(int i = 2,Pos = 0; i < 4;Pos++,i++) - { - m_Serial[Pos] = tmpbyte[i]; - } - return true; - } - return false; -} - - -bool CMessage::SetGUID(byte* in_byte_ptr) -{ - if (in_byte_ptr != NULL) - { - memset(m_GUID,0,16); - memcpy(m_GUID,in_byte_ptr,16); - return true; - } - return false; -} - - -bool CMessage::SetComCommandList(int ComCount) -{ - if (ComCount == 0) - { - m_ComCommandList.clear(); - return true; - } - - m_ComCommandList.clear(); - m_ComCommandList.resize(ComCount); - return true; -} - - -bool CMessage::SetVerify(uint in_Int) -{ - m_Verify = in_Int; - return true; -} - -bool CMessage::SetObligate(uint in_Int) -{ - m_Obligate = in_Int; - return true; -} - -bool CMessage::SetVersion(uint in_Int) -{ - m_Ver = in_Int; - return true; -} - -bool CMessage::SetCmlCount(uint in_Int) -{ - m_CmlCount = in_Int; - return true; -} - -bool CMessage::SetDataLen(uint in_Int) -{ - m_Len = in_Int; - return true; -} - - - -int CMessage::_MessageType() -{ - int _type = 0; - switch(m_Command) - { - case MSG_AVC_COM: _type = MSG_AVC_TYPE; - break; - case MSG_ALI_COM: _type = MSG_ALI_TYPE; - break; - case MSG_RVC_COM: _type = MSG_RVC_TYPE; - break; - case MSG_RLI_COM: _type = MSG_RLI_TYPE; - break; - case MSG_RPS_COM: _type = MSG_RPS_TYPE; - break; - case MSG_APS_COM: _type = MSG_APS_TYPE; - break; - } - return _type; -} - -void CMessage::_Initialization() -{ - memset(m_GUID,0,16); - memset(m_Serial,0,2); - m_Begin = false; - m_End = false; - m_CmlCount = 0; - m_Obligate = 0; - m_Ver = 0; - m_Verify = 0; - //m_Serial = 0; - m_Len = 0; - m_Command = 0; -} - -void CMessage::_Close() -{ - // -} - - -//RVC(ȡ֤) -void MSG_RVC::Initialize() -{ -// if (GetBeginTab() != true || GetEndTab() != true) -// { -// m_Error++; -// } - - if (GetCommand() != m_Command) - { - m_Error++; - } - - if (GetCmlCount() != m_CmlCount) - { - m_Error++; - } - //Ч -// if (strcmp(returnVerify(),"") != 0) -// { -// m_Error++; -// } - -} - -byte* MSG_RVC::GetMachineAddress() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return (byte*)(m_ComCommandList[0].data()); -} - -void MSG_RVC::SetMachineAddress(const byte* in_byte_ptr, size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_MachineAddressLen = len; - m_ComCommandList[0].clear(); - for (int index = 0; index < (int)len; index++) - { - m_ComCommandList[0].push_back(in_byte_ptr[index]); - } -} - -//AVC(ȡ֤Ӧ) -void MSG_AVC::Initialize() -{ -// if (GetBeginTab() != true || GetEndTab() != true) -// { -// m_Error++; -// } - - if (GetCommand() != m_Command) - { - m_Error++; - } - - if (GetCmlCount() != m_CmlCount) - { - m_Error++; - } - //Ч - // if (strcmp(returnVerify(),"") != 0) - // { - // m_Error++; - // } - -} - -uint MSG_AVC::GetLoginTag() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return byteToInt((byte*)(m_ComCommandList[2].data()),1); -} - -uint MSG_AVC::GetCaptchaType() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return byteToInt((byte*)(m_ComCommandList[1].data()),1); -} - -byte* MSG_AVC::GetCaptcha() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return (byte*)(m_ComCommandList[0].data()); -} - - -void MSG_AVC::SetLoginTag(byte in_byte) -{ - //ֻռһֽ - m_ComCommandList[2].clear(); - - m_ComCommandList[2].push_back(in_byte); -} - -void MSG_AVC::SetCaptchaType(byte in_byte) -{ - //ֻռһֽ - m_ComCommandList[1].clear(); - - m_ComCommandList[1].push_back(in_byte); -} - -void MSG_AVC::SetCaptcha(const byte* in_byte_ptr,size_t len) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_CaptchaLen = len; - m_ComCommandList[0].clear(); - - for (int index = 0; index < (int)len; index++) - { - m_ComCommandList[0].push_back(in_byte_ptr[index]); - } -} - -//RLI(¼) -void MSG_RLI::Initialize() -{ -// if (GetBeginTab() != true || GetEndTab() != true) -// { -// m_Error++; -// } - - if (GetCommand() != m_Command) - { - m_Error++; - } - - if (GetCmlCount() != m_CmlCount) - { - m_Error++; - } - //Ч - // if (strcmp(returnVerify(),"") != 0) - // { - // m_Error++; - // } - -} -byte* MSG_RLI::GetVerificationCode() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return (byte*)(m_ComCommandList[2].data()); -} - - -byte* MSG_RLI::GetAccountNumber() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return (byte*)(m_ComCommandList[1].data()); -} - - -byte* MSG_RLI::GetPassword() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return (byte*)(m_ComCommandList[0].data()); -} - -void MSG_RLI::SetVerificationCode(const byte* in_byte_ptr,size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_VerificationCodeLen = len; - m_ComCommandList[2].clear(); - - for (int index = 0; index < (int)len; index++) - { - m_ComCommandList[2].push_back(in_byte_ptr[index]); - } -} - -void MSG_RLI::SetAccountNumber(const byte* in_byte_ptr,size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_AccountNumberLen = len; - m_ComCommandList[1].clear(); - - for (int index = 0; index < (int)len; index++) - { - m_ComCommandList[1].push_back(in_byte_ptr[index]); - } -} - -void MSG_RLI::SetPassword(const byte* in_byte_ptr,size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_PasswordLen = len; - m_ComCommandList[0].clear(); - - for (int index = 0; index < (int)len; index++) - { - m_ComCommandList[0].push_back(in_byte_ptr[index]); - } -} - -//ALI(¼Ӧ) -void MSG_ALI::Initialize() -{ -// if (GetBeginTab() != true || GetEndTab() != true) -// { -// m_Error++; -// } - - if (GetCommand() != m_Command) - { - m_Error++; - } - - if (GetCmlCount() != m_CmlCount) - { - m_Error++; - } - //Ч - // if (strcmp(returnVerify(),"") != 0) - // { - // m_Error++; - // } - -} -uint MSG_ALI::GetLoginResult() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return byteToInt((byte*)(m_ComCommandList[2].data()),1); -} - - -uint MSG_ALI::GetToken() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return byteToInt((byte*)(m_ComCommandList[1].data()),4); -} - - -byte* MSG_ALI::GetATLGUID() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return (byte*)(m_ComCommandList[0].data()); -} - -void MSG_ALI::SetLoginResult( byte in_byte ) -{ - m_ComCommandList[2].clear(); - - m_ComCommandList[2].push_back(in_byte); -} - -void MSG_ALI::SetToken(const byte* in_byte_ptr, size_t len /*= 4*/) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_TokenLen = len; - m_ComCommandList[1].clear(); - - for (int index = 0; index < (int)len; index++) - { - m_ComCommandList[1].push_back(in_byte_ptr[index]); - } -} - -void MSG_ALI::SetATLGUID(const byte* in_byte_ptr, size_t len /*= 16*/ ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_ALTGUIDLen = len; - m_ComCommandList[0].clear(); - - for (int index = 0; index < (int)len; index++) - { - m_ComCommandList[0].push_back(in_byte_ptr[index]); - } -} - - - -//RPS(Ϣ֪ͬͨ) -void MSG_RPS::Initialize() -{ -// if (GetBeginTab() != true || GetEndTab() != true) -// { -// m_Error++; -// } - - if (GetCommand() != m_Command) - { - m_Error++; - } - - if (GetCmlCount() != m_CmlCount) - { - m_Error++; - } - //Ч - // if (strcmp(returnVerify(),"") != 0) - // { - // m_Error++; - // } - -} -uint MSG_RPS::GetRank() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return byteToInt((byte*)(m_ComCommandList[4].data()),1); -} - - -byte* MSG_RPS::GetNickname() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return (byte*)(m_ComCommandList[3].data()); -} - - -byte* MSG_RPS::GetAutograph() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return (byte*)(m_ComCommandList[2].data()); -} - -uint MSG_RPS::GetHeadForm() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return byteToInt((byte*)(m_ComCommandList[1].data()),1); -} - -byte* MSG_RPS::GetHeadPortrait() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return (byte*)(m_ComCommandList[0].data()); -} - -void MSG_RPS::SetRank( byte in_byte ) -{ - - m_ComCommandList[4].clear(); - - m_ComCommandList[4].push_back(in_byte); -} - - -void MSG_RPS::SetNickname(const byte* in_byte_ptr,size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_NicknameLen = len; - m_ComCommandList[3].clear(); - - for (int index = 0; index < (int)len; index++) - { - m_ComCommandList[3].push_back(in_byte_ptr[index]); - } -} - - -void MSG_RPS::SetAutograph(const byte* in_byte_ptr,size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_AutographLen = len; - m_ComCommandList[2].clear(); - - for (int index = 0; index < (int)len; index++) - { - m_ComCommandList[2].push_back(in_byte_ptr[index]); - } -} - -void MSG_RPS::SetHeadForm( byte in_byte ) -{ - m_ComCommandList[1].clear(); - - m_ComCommandList[1].push_back(in_byte); -} - -void MSG_RPS::SetHeadPortrait(const byte* in_byte_ptr,size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_HeadPortraitLen = len; - m_ComCommandList[0].clear(); - - for (int index = 0; index < (int)len; index++) - { - m_ComCommandList[0].push_back(in_byte_ptr[index]); - } -} - - - - -//APS(Ϣ֪ͬͨȷ) -void MSG_APS::Initialize() -{ -// if (GetBeginTab() != true || GetEndTab() != true) -// { -// m_Error++; -// } - - if (GetCommand() != m_Command) - { - m_Error++; - } - - if (GetCmlCount() != m_CmlCount) - { - m_Error++; - } - //Ч - // if (strcmp(returnVerify(),"") != 0) - // { - // m_Error++; - // } - -} -byte* MSG_APS::GetMessageSynchro() const -{ - // Initialize(); - if (m_Error != 0) - { - return 0; - } - return (byte*)(m_ComCommandList[0].data()); -} - -void MSG_APS::SetMessageSynchro(const byte* in_byte_ptr,size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_MessageSynchroLen = len; - m_ComCommandList[0].clear(); - for (int index = 0; index < (int)len; index++) - { - m_ComCommandList[0].push_back(in_byte_ptr[index]); - } -} diff --git a/Message/MsgDef.h b/Message/MsgDef.h deleted file mode 100644 index 41b8400e..00000000 --- a/Message/MsgDef.h +++ /dev/null @@ -1,567 +0,0 @@ - - -#pragma once - - -/* -#define MSG_ERROR_BDMISS 1 -#define MSG_ERROR_COMMAND 2 -#define MSG_ERROR_PARAM 3 -#define MSG_ERROR_LEN 4*/ - -#include -#include -#include -#include - -#define MSG_BEGIN 0x56 // 'V' ϢĿʼ -#define MSG_END 0x43 // 'C' ϢĽ -#define MSG_VER 0 //汾 - -#define MSG_CLASS_BEGIN 1 -#define MSG_CLASS_END 1 -#define MSG_CLASS_LEN 4 -#define MSG_CLASS_VER 1 -#define MSG_CLASS_SERIAL 2 -#define MSG_CLASS_GUID 16 -#define MSG_CLASS_COMMAND 1 -#define MSG_CLASS_OBL 4 -#define MSG_CLASS_PARAMCONST 1 -#define MSG_CLASS_VERIFY 2 //Ч δĬΪ2ֽ -#define MSG_CLASS_PARAM 4 - -#define VER_INDEX MSG_CLASS_VER -#define SER_INDEX (MSG_CLASS_VER + MSG_CLASS_SERIAL) -#define LEN_INDEX (MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL) -#define GUID_INDEX (MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL + MSG_CLASS_GUID) -#define COM_INDEX (MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL + MSG_CLASS_COMMAND + MSG_CLASS_GUID) -#define OBL_INDEX (MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL + MSG_CLASS_GUID + MSG_CLASS_COMMAND + MSG_CLASS_OBL) -#define PAC_INDEX (MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL + MSG_CLASS_GUID + MSG_CLASS_COMMAND + MSG_CLASS_OBL + MSG_CLASS_PARAMCONST) - - -#define MSG_INIT SetDataLen(0);SetVersion(MSG_VER);SetSerial(0x00);SetCommand(m_Command);SetObligate(0);SetCmlCount(m_CmlCount);SetVerify(0); - -enum MSGTYPE -{ - MSGTYPE_NULL, - - MSG_AVC_TYPE, - MSG_RVC_TYPE, - - MSG_ALI_TYPE, - MSG_RLI_TYPE, - - MSG_RPS_TYPE, - MSG_APS_TYPE, - MSGTYPE_END -}; - -enum MSGCONMMAND -{ - MSGCONMMAND_NULL, - - MSG_RVC_COM = 0x14, - MSG_AVC_COM = 0x15, - - MSG_RLI_COM = 0x16, - MSG_ALI_COM = 0x17, - - MSG_RPS_COM = 0x18, - MSG_APS_COM = 0x19, -}; - -typedef unsigned char byte; -typedef unsigned int uint; -typedef unsigned short ushort; - - -typedef std::vector ByteArr; - -// ʹС˻ -#define BigLittleSwap16(A) ((((ushort)(A) & 0xff00) >> 8) | \ - (((ushort)(A) & 0x00ff) << 8)) - -// ʹС˻ -#define BigLittleSwap32(A) ((((uint)(A) & 0xff000000) >> 24) | \ - (((uint)(A) & 0x00ff0000) >> 8) | \ - (((uint)(A) & 0x0000ff00) << 8) | \ - (((uint)(A) & 0x000000ff) << 24)) - - -uint byteToInt(const byte* in_byte,size_t len); - -void IntTobyte(int in_int,byte* out_byte); - -void LittleSwapBigByte(byte* in_byte_ptr,size_t len); - -void LittleSwapBigByte(ByteArr* arr); - -class CMessage -{ -public: - - friend class CMessageParser; - - CMessage(){ - _Initialization(); - } - - virtual ~CMessage(){ - _Close(); - } - //ȡϢ - int GetMessageType() const; - - -public: - - bool GetBeginTab() const ; - - bool GetEndTab() const; - - byte GetCommand() const; - - byte* GetComListLen() const; - - uint GetSerial() const; - - const byte* GetGUID() const; - - std::vector GetComCommandList() const; - - - uint GetVerify() const; - - uint GetObligate() const; - - uint GetVersion() const; - - uint GetCmlCount() const; - - uint GetDataLen() const; - - -// Set - - bool SetCommand(byte in_byte); - - bool SetSerial(ushort in_short); - - bool SetGUID(byte* in_byte_ptr); - - bool SetComCommandList(int ComCount); - - bool SetComListLen(byte* in_byte_ptr,int CmlCount); - - bool SetVerify(uint in_Int); - - bool SetObligate(uint in_Int); - - bool SetVersion(uint in_Int); - - bool SetCmlCount(uint in_Int); - - bool SetDataLen(uint in_Int); - - -protected: - - - bool m_Begin; //ϢĿʼ ͳһַ'V"ASC 0x56 - bool m_End; //ϢĽ ̶ַ'CASC 0x43 - //б 4ֽڣӦNij - std::vector m_ComListLen; - //б IJ͸ݾָ - std::vector m_ComCommandList; - byte m_Command; //ָ ָעݰĹ - byte m_Serial[2]; // ָı - byte m_GUID[16]; //GUID ṩû֤ - //DWORD dwType; //Ϣ - - - uint m_Verify; //Ч Ԥ - - uint m_Obligate; //Ԥռ - uint m_Ver; //汾 ־VNOCЭİ汾 - uint m_CmlCount; // IJ͸ݾָ - uint m_Len; //峤 4ֽڣָijȣԸݽ - -private: - - - void _Initialization(); - void _Close(); - int _MessageType(); -}; - - -//RVC(ȡ֤) -class MSG_RVC: public CMessage -{ -public: - - MSG_RVC(){ - //һ - m_CmlCount = 1; - //0x14 - m_Command = 20; - m_Error = 0; - m_MachineAddressLen = 0; - //Ԥ - MSG_INIT; - //òȿռ - SetComListLen( 0, m_CmlCount ); - //òռ - SetComCommandList(m_CmlCount); - } - //ַ - byte* GetMachineAddress() const; - - void SetMachineAddress(const byte* in_byte_ptr, size_t len); - - int GetMachineAddressLen()const{ - return m_MachineAddressLen; - } - - ~MSG_RVC(){} - -private: - - void Initialize(); - - // - int m_CmlCount; - - //ָ - int m_Command; - - // - int m_Error; - - //MachineAddress - int m_MachineAddressLen; - -}; - -//AVC(ȡ֤Ӧ) -class MSG_AVC: public CMessage -{ -public: - - MSG_AVC(){ - // - m_CmlCount = 3; - //0x15 - m_Command = 21; - m_Error = 0; - m_CaptchaLen =0; - //Ԥ - MSG_INIT; - //òȿռ - SetComListLen( 0, m_CmlCount ); - //òռ - SetComCommandList(m_CmlCount); - } - //ȡ֤1ֽڣ־˴ε¼Ľ - uint GetLoginTag() const; - //֤ͣ־֤õĺ壬֤Ͷһö٣ - uint GetCaptchaType() const; - //֤壺֤峤ȲָСʽͼ - byte* GetCaptcha() const; - - - void SetLoginTag(byte in_byte); - - void SetCaptchaType(byte in_byte); - - void SetCaptcha(const byte* in_byte_ptr,size_t len); - - - // - int GetCaptchaLen() const { - return m_CaptchaLen; - } - - ~MSG_AVC(){} - -private: - - void Initialize(); - - // - int m_CmlCount; - - //ָ - int m_Command; - - // - int m_Error; - - //Captcha - int m_CaptchaLen; - -}; - - -//RLI(¼) -class MSG_RLI:public CMessage -{ - -public: - - MSG_RLI(){ - // - m_CmlCount = 3; - //0x16 - m_Command = 22; - m_Error = 0; - m_VerificationCodeLen = 0; - m_AccountNumberLen = 0; - m_PasswordLen = 0; - //Ԥ - MSG_INIT; - //òȿռ - SetComListLen( 0, m_CmlCount ); - //òռ - SetComCommandList(m_CmlCount); - } - //֤룺δ֪ȣΪAUTͼƬַɣ˲ڷӦư󶨣һ֤-ӳ䣩 - byte* GetVerificationCode() const; - //ûʺţûʺűĶ - byte* GetAccountNumber() const; - //û룺뾭Ķ - byte* GetPassword() const; - - - void SetVerificationCode(const byte* in_byte_ptr,size_t len); - - void SetAccountNumber(const byte* in_byte_ptr,size_t len); - - void SetPassword(const byte* in_byte_ptr,size_t len); - - - int GetVerificationCodeLen() const{ - return m_VerificationCodeLen; - } - - int GetAccountNumberLen() const{ - return m_AccountNumberLen; - } - - int GetPasswordLen() const{ - return m_PasswordLen; - } - - ~MSG_RLI(){} - -private: - - void Initialize(); - - // - int m_CmlCount; - - //ָ - int m_Command; - - // - int m_Error; - - //洢 - int m_VerificationCodeLen; - int m_AccountNumberLen; - int m_PasswordLen; -}; - - -//ALI(¼Ӧ) -class MSG_ALI:public CMessage -{ - -public: - - MSG_ALI(){ - // - m_CmlCount = 3; - //0x17 - m_Command = 23; - m_Error = 0; - m_TokenLen = 0; - m_ALTGUIDLen = 0; - //Ԥ - MSG_INIT; - //òȿռ - SetComListLen( 0, m_CmlCount ); - //òռ - SetComCommandList(m_CmlCount); - } - //¼1ֽڣ־˴ε¼Ľ - uint GetLoginResult() const; - //Ƴȣ4ֽڣ0x00 00 00 10ûʺűijȣλΪֽ - uint GetToken() const; - //ƣ16ֽڣһGUID ʺ֤ͨɣͨݰͻˣָ֮ڰͷϴ - byte* GetATLGUID() const; - - void SetLoginResult(byte in_byte); - - void SetToken(const byte* in_byte_ptr,size_t len = 4); - - void SetATLGUID(const byte* in_byte_ptr, size_t len = 16); - - - int GetATLGUIDLen() const{ - return m_ALTGUIDLen; - } - - int GetTokenLen() const{ - return m_TokenLen; - } - - ~MSG_ALI(){} - -private: - - void Initialize(); - - // - int m_CmlCount; - - //ָ - int m_Command; - - // - int m_Error; - - //TokenLen - int m_TokenLen; - //ATLGUIDLen - int m_ALTGUIDLen; -}; - - -//RPS(Ϣ֪ͬͨ) -class MSG_RPS:public CMessage -{ - -public: - - MSG_RPS(){ - // - m_CmlCount = 5; - //0x18 - m_Command = 24; - m_Error = 0; - m_NicknameLen = 0; - m_AutographLen = 0; - m_HeadPortraitLen = 0; - //Ԥ - MSG_INIT; - //òȿռ - SetComListLen( 0, m_CmlCount ); - //òռ - SetComCommandList(m_CmlCount); - } - //ûȨ - uint GetRank() const; - //dz - byte* GetNickname() const; - //ǩ - byte* GetAutograph() const; - //ͷʽ - uint GetHeadForm() const; - //ͷ - byte* GetHeadPortrait() const; - - void SetRank(byte in_byte); - - void SetNickname(const byte* in_byte_ptr,size_t len); - - void SetAutograph(const byte* in_byte_ptr,size_t len); - - void SetHeadForm(byte in_byte); - - void SetHeadPortrait(const byte* in_byte_ptr,size_t len); - - - int GetNicknameLen() const{ - return m_NicknameLen; - } - - int GetAutographLen() const{ - return m_AutographLen; - } - - int GetHeadPortraitLen() const{ - return m_HeadPortraitLen; - } - - ~MSG_RPS(){} - -private: - - void Initialize(); - - // - int m_CmlCount; - - //ָ - int m_Command; - - // - int m_Error; - - // - int m_NicknameLen; - int m_AutographLen; - int m_HeadPortraitLen; -}; - - -//APS(Ϣ֪ͬͨȷ) -class MSG_APS:public CMessage -{ - -public: - - MSG_APS(){ - // - m_CmlCount = 1; - //0x19 - m_Command = 25; - m_Error = 0; - m_MessageSynchroLen = 0; - //Ԥ - MSG_INIT; - //òȿռ - SetComListLen( 0, m_CmlCount ); - //òռ - SetComCommandList(m_CmlCount); - } - - //Ϣ֪ͬͨ - byte* GetMessageSynchro() const; - - void SetMessageSynchro(const byte* in_byte_ptr,size_t len); - - int GetMessageSynchroLen() const{ - return m_MessageSynchroLen; - } - - ~MSG_APS(){} - -private: - - void Initialize(); - - // - int m_CmlCount; - - //ָ - int m_Command; - - // - int m_Error; - - // - int m_MessageSynchroLen; -}; \ No newline at end of file diff --git a/Message/PackMessage.cpp b/Message/PackMessage.cpp index b559755c..6fae6630 100644 --- a/Message/PackMessage.cpp +++ b/Message/PackMessage.cpp @@ -3,9 +3,7 @@ #include -using namespace std; - -int PackMessage::_Head( CMessage* const msg_clss,byte* buf, size_t len) +int PackMessage::_Head(const CMessage* const msg_clss,byte* buf, size_t len) { //head--------------------- int index = 0; @@ -17,7 +15,7 @@ int PackMessage::_Head( CMessage* const msg_clss,byte* buf, size_t len) } //ð - msg_clss->SetDataLen(len); + //msg_clss->m_Len = len; // if (len < rvc->GetDataLen()) // { @@ -39,15 +37,15 @@ int PackMessage::_Head( CMessage* const msg_clss,byte* buf, size_t len) memset(tmpByte,0,4); IntTobyte(msg_clss->GetSerial(),tmpByte); //Ϊֻ2λ ֻȡλ - CHECKUP_DATALEN(index,len); - for (int i = 2; i < 4; i++,index++) - { - buf[index] = tmpByte[ i ]; - } + CHECKUP_DATALEN(index,len); + for (int i = 2; i < 4; i++,index++) + { + buf[index] = tmpByte[ i ]; + } memset(tmpByte,0,4); - IntTobyte(msg_clss->GetDataLen(),tmpByte); + IntTobyte(len,tmpByte); CHECKUP_DATALEN(index,len); for (int record = 0; record < 4; index++,record++ ) { @@ -78,7 +76,7 @@ int PackMessage::_Head( CMessage* const msg_clss,byte* buf, size_t len) return index; } -int PackMessage::_Tail( CMessage* const msg_clss,byte* buf,int index,size_t len) +int PackMessage::_Tail(const CMessage* const msg_clss,byte* buf,int index,size_t len) { byte tmpByte[4] = {0}; //Tail @@ -88,7 +86,7 @@ int PackMessage::_Tail( CMessage* const msg_clss,byte* buf,int index,size_t len) { return -1; } - memset(tmpByte,0,4); + //memset(tmpByte,0,4); IntTobyte(msg_clss->GetVerify(),tmpByte); //ΪЧԤ2λ ֻȡλ CHECKUP_DATALEN(index,len); @@ -102,361 +100,78 @@ int PackMessage::_Tail( CMessage* const msg_clss,byte* buf,int index,size_t len) return index; } -int PackMessage::_Pack( MSG_RVC* const rvc,byte* buf, size_t len) -{ - byte tmpComLen[4] = {0}; - byte tmpByte[4] = {0}; - - int index = _Head(rvc,buf,len); - //body - byte* ComLenList = new byte[rvc->GetCmlCount() * 4]; - memset(ComLenList,0,rvc->GetCmlCount() * 4); - //ò - //1 - IntTobyte(rvc->GetMachineAddressLen(),tmpComLen); - for (int i = 0; i < 4; i++) - { - ComLenList[i] = tmpComLen[i]; - } - rvc->SetComListLen(ComLenList,rvc->GetCmlCount()); - delete [] ComLenList; - ComLenList = NULL; - // - CHECKUP_DATALEN(index,len); - for (int i = 0; i < (int)(rvc->GetCmlCount() * 4); i++, index++) - { - buf[index] = rvc->GetComListLen()[i]; - } - // - //1 - CHECKUP_DATALEN(index,len); - for (int i = 0; i < rvc->GetMachineAddressLen(); i++, index++) - { - buf[index] = rvc->GetComCommandList()[0][i]; - } - - //Tail - return _Tail(rvc,buf,index,len); -} -int PackMessage::_Pack( MSG_AVC* const avc, byte* buf, size_t len) +int PackMessage::_CreateCommandLenList( byte* buf,int in_index) { - byte tmpComLen[4] = {0}; - byte OneComLen[] = {0x00,0x00,0x00,0x01}; - byte tmpByte[4] = {0}; - - int index = _Head(avc,buf,len); - //body - byte* ComLenList = new byte[avc->GetCmlCount() * 4]; - memset(ComLenList,0,avc->GetCmlCount() * 4); - //ò - //1 - int Pos = 0; - for (; Pos < 4; Pos++) - { - ComLenList[Pos] = OneComLen[Pos]; - } - //2 - for (int i = 0; Pos < 8; Pos++,i++) - { - ComLenList[Pos] = OneComLen[ i ]; - } - //3 - IntTobyte(avc->GetCaptchaLen(),tmpComLen); - for (int i = 0; Pos < 12; Pos++, i++) - { - ComLenList[Pos] = tmpComLen[ i ]; - } - avc->SetComListLen(ComLenList,avc->GetCmlCount()); - delete [] ComLenList; - ComLenList = NULL; - // - CHECKUP_DATALEN(index,len); - for (int i = 0; i < (int)(avc->GetCmlCount() * 4); i++, index++) - { - buf[index] = avc->GetComListLen()[i]; - } - // - //1 - CHECKUP_DATALEN(index,len); - buf[index] = avc->GetComCommandList()[2][0]; - index++; - //2 - CHECKUP_DATALEN(index,len); - buf[index] = avc->GetComCommandList()[1][0]; - index++; - //3 - CHECKUP_DATALEN(index,len); - for (int i = 0; i < avc->GetCaptchaLen(); i++, index++) + //byte* ComLenList = new byte[m_CommandLenList.size() * 4]; + std::vector ComLenList; + ComLenList.resize(m_CommandLenList.size() * 4); + //memset(ComLenList,0,m_CommandLenList.size() * 4); + for (int i = 0,index = 0; i < (int)m_CommandLenList.size();i++) { - buf[index] = avc->GetComCommandList()[0][i]; + byte tmpComLen[4] = {0}; + IntTobyte(m_CommandLenList[i],tmpComLen); + for (int j = 0; j < 4; j++,index++) + { + ComLenList[index] = tmpComLen[j]; + } } - //Tail - return _Tail(avc,buf,index,len); -} - - -int PackMessage::_Pack( MSG_RLI* const rli,byte* buf, size_t len) -{ - byte tmpComLen[4] = {0}; - byte OneComLen[] = {0x00,0x00,0x00,0x01}; - - byte tmpByte[4] = {0}; - - int index = _Head(rli,buf,len); - //body - byte* ComLenList = new byte[rli->GetCmlCount() * 4]; - memset(ComLenList,0,rli->GetCmlCount() * 4); - //ò - //1 - int Pos = 0; - IntTobyte(rli->GetVerificationCodeLen(),tmpComLen); - for (;Pos < 4; Pos++) - { - ComLenList[Pos] = tmpComLen[Pos]; - } - memset(tmpComLen,0,4); - //2 - IntTobyte(rli->GetAccountNumberLen(),tmpComLen); - for (int i = 0; Pos < 8; Pos++,i++) - { - ComLenList[Pos] = tmpComLen[ i ]; - } - memset(tmpComLen,0,4); - //3 - IntTobyte(rli->GetPasswordLen(),tmpComLen); - for (int i = 0; Pos < 12; Pos++,i++) - { - ComLenList[Pos] = tmpComLen[ i ]; - } - memset(tmpComLen,0,4); - rli->SetComListLen(ComLenList,rli->GetCmlCount()); - delete [] ComLenList; - ComLenList = NULL; - // - CHECKUP_DATALEN(index,len); - for (int i = 0; i < (int)(rli->GetCmlCount() * 4); i++, index++) - { - buf[index] = rli->GetComListLen()[i]; - } - // - //1 - CHECKUP_DATALEN(index,len); - for (int i = 0; i < rli->GetVerificationCodeLen(); i++, index++) + // + for (int i = 0; i < (int)(m_CommandLenList.size() * 4);in_index++, i++) { - buf[index] = rli->GetComCommandList()[2][i]; + buf[in_index] = ComLenList[i]; } - //2 - CHECKUP_DATALEN(index,len); - for (int i = 0; i < rli->GetAccountNumberLen(); i++, index++) - { - buf[index] = rli->GetComCommandList()[1][i]; - } - //3 - CHECKUP_DATALEN(index,len); - for (int i = 0; i < rli->GetPasswordLen(); i++, index++) - { - buf[index] = rli->GetComCommandList()[0][i]; - } - - //Tail - return _Tail(rli,buf,index,len); + return in_index; } -int PackMessage::_Pack( MSG_ALI* const ali,byte* buf, size_t len) -{ - byte tmpComLen[4] = {0}; - byte OneComLen[] = {0x00,0x00,0x00,0x01}; - byte tmpByte[4] = {0}; - - int index = _Head(ali,buf,len); - - //body - byte* ComLenList = new byte[ali->GetCmlCount() * 4]; - memset(ComLenList,0,ali->GetCmlCount() * 4); - //ò - //1 - int Pos = 0; - for (; Pos < 4; Pos++) - { - ComLenList[Pos] = OneComLen[Pos]; - } - //2 - IntTobyte(ali->GetTokenLen(),tmpComLen); - for (int i = 0; Pos < 8; Pos++,i++) - { - ComLenList[Pos] = tmpComLen[ i ]; - } - memset(tmpComLen,0,4); - //3 - IntTobyte(ali->GetATLGUIDLen(),tmpComLen); - for (int i = 0; Pos < 12; Pos++, i++) - { - ComLenList[Pos] = tmpComLen[ i ]; - } - memset(tmpComLen,0,4); - ali->SetComListLen(ComLenList,ali->GetCmlCount()); - delete [] ComLenList; - ComLenList = NULL; - // - CHECKUP_DATALEN(index,len); - for (int i = 0; i < (int)(ali->GetCmlCount() * 4); i++, index++) - { - buf[index] = ali->GetComListLen()[i]; - } - // - //1 - CHECKUP_DATALEN(index,len); - buf[index] = ali->GetComCommandList()[2][0]; - index++; - //2 - CHECKUP_DATALEN(index,len); - for (int i = 0; i < ali->GetTokenLen(); i++, index++) - { - buf[index] = ali->GetComCommandList()[1][i]; - } - //3 - CHECKUP_DATALEN(index,len); - for (int i = 0; i < ali->GetTokenLen(); i++, index++) - { - buf[index] = ali->GetComCommandList()[0][i]; - } - - //Tail - return _Tail(ali,buf,index,len); +void PackMessage::_PushCommandLenList( int len ) +{ + m_CommandLenList.push_back(len); } -int PackMessage::_Pack( MSG_RPS* const rps,byte* buf, size_t len) +void PackMessage::_CloseCommandLenList() { - byte tmpComLen[4] = {0}; - byte OneComLen[] = {0x00,0x00,0x00,0x01}; - byte tmpByte[4] = {0}; - - int index = _Head(rps,buf,len); + m_CommandLenList.clear(); +} - //body - byte* ComLenList = new byte[rps->GetCmlCount() * 4]; - memset(ComLenList,0,rps->GetCmlCount() * 4); - //ò - //1 - int Pos = 0; - for (; Pos < 4; Pos++) - { - ComLenList[Pos] = OneComLen[Pos]; - } - //2 - IntTobyte(rps->GetNicknameLen(),tmpComLen); - for (int i = 0; Pos < 8; Pos++, i ++) - { - ComLenList[Pos] = tmpComLen[ i ]; - } - memset(tmpComLen,0,4); - //3 - IntTobyte(rps->GetAutographLen(),tmpComLen); - for (int i = 0; Pos < 12; Pos++,i++) - { - ComLenList[Pos] = tmpComLen[ i ]; - } - memset(tmpComLen,0,4); - //4 - for (int i = 0; Pos < 16; Pos++,i++) - { - ComLenList[Pos] = OneComLen[ i ]; - } - //5 - IntTobyte(rps->GetHeadPortraitLen(),tmpComLen); - for (int i = 0; Pos < 20; Pos++,i++) - { - ComLenList[Pos] = tmpComLen[ i ]; - } - memset(tmpComLen,0,4); - rps->SetComListLen(ComLenList,rps->GetCmlCount()); - delete [] ComLenList; - ComLenList = NULL; - // - CHECKUP_DATALEN(index,len); - for (int i = 0; i < (int)(rps->GetCmlCount() * 4); i++, index++) - { - buf[index] = rps->GetComListLen()[i]; - } - // - //1 - CHECKUP_DATALEN(index,len); - buf[index] = rps->GetComCommandList()[4][0]; - index++; - //2 - CHECKUP_DATALEN(index,len); - for (int i = 0; i < rps->GetNicknameLen(); i++, index++) - { - buf[index] = rps->GetComCommandList()[3][i]; - } - //3 - CHECKUP_DATALEN(index,len); - for (int i = 0; i < rps->GetAutographLen(); i++, index++) +int PackMessage::_PushCommandList(const byte* const in_Command, int len ) +{ + if (in_Command == NULL) { - buf[index] = rps->GetComCommandList()[2][i]; + return -1; } - //4 - CHECKUP_DATALEN(index,len); - buf[index] = rps->GetComCommandList()[1][0]; - index++; - //5 - CHECKUP_DATALEN(index,len); - for (int i = 0; i < rps->GetHeadPortraitLen(); i++, index++) + int index = 0; + for (int i = 0; i < len; i++, index++) { - buf[index] = rps->GetComCommandList()[0][i]; + m_CommandList[CommandListPos].push_back(in_Command[i]); } - - //Tail - return _Tail(rps,buf,index,len); - + //¼ǰбλ + CommandListPos++; + return index; } - -int PackMessage::_Pack( MSG_APS* const aps,byte* buf, size_t len) +int PackMessage::_CreateCommandList( byte* buf,int in_index) { - byte tmpComLen[4] = {0}; - byte OneComLen[] = {0x00,0x00,0x00,0x01}; - byte tmpByte[4] = {0}; - - int index = _Head(aps,buf,len); - //body - byte* ComLenList = new byte[aps->GetCmlCount() * 4]; - memset(ComLenList,0,aps->GetCmlCount() * 4); - //ò - //1 - IntTobyte(aps->GetMessageSynchroLen(),tmpComLen); - int Pos = 0; - for (; Pos < 4; Pos++) - { - ComLenList[Pos] = tmpComLen[Pos]; - } - memset(tmpComLen,0,4); - aps->SetComListLen(ComLenList,aps->GetCmlCount()); - delete [] ComLenList; - ComLenList = NULL; - // - CHECKUP_DATALEN(index,len); - for (int i = 0; i < (int)(aps->GetCmlCount() * 4); i++, index++) - { - buf[index] = aps->GetComListLen()[i]; - } - // - //1 - CHECKUP_DATALEN(index,len); - for (int i = 0; i < aps->GetMessageSynchroLen(); i++, index++) + for (int i = 0; i < (int)m_CommandList.size();i++) { - buf[index] = aps->GetComCommandList()[0][i]; + for (int j = 0; j < (int)m_CommandList[i].size(); in_index++,j++) + { + buf[in_index] = m_CommandList[i][j]; + } } + return in_index; +} - //Tail - return _Tail(aps,buf,index,len); +void PackMessage::_CloseCommandList() +{ + CommandListPos = 0; + m_CommandList.clear(); } //GetMessageLen @@ -468,13 +183,6 @@ int PackMessage::GetMessageLen(const CMessage* const msg) int Param = 0; int PLen = 0; - MSG_AVC* avc; - MSG_RVC* rvc; - MSG_ALI* ali; - MSG_RLI* rli; - MSG_RPS* rps; - MSG_APS* aps; - if (!msg) { return 0; @@ -482,61 +190,38 @@ int PackMessage::GetMessageLen(const CMessage* const msg) PLen = msg->GetCmlCount() * 4; - - switch (msg->GetMessageType()) + + for (int index = 0; index < (int)msg->m_ComCommandList.size(); index++) { - case MSG_AVC_TYPE: - avc = (MSG_AVC*)msg; - Param = avc->GetCaptchaLen() + 1 + 1; - break; - case MSG_RVC_TYPE: - rvc = (MSG_RVC*)msg; - Param = rvc->GetMachineAddressLen(); - break; - case MSG_ALI_TYPE: - ali = (MSG_ALI*)msg; - Param = ali->GetATLGUIDLen() + ali->GetTokenLen() + 1; - break; - case MSG_RLI_TYPE: - rli = (MSG_RLI*)msg; - Param = rli->GetAccountNumberLen() + rli->GetPasswordLen() + rli->GetVerificationCodeLen(); - break; - case MSG_RPS_TYPE: - rps = (MSG_RPS*)msg; - Param = rps->GetNicknameLen() + rps->GetAutographLen() + rps->GetHeadPortraitLen() + 1 + 1; - break; - case MSG_APS_TYPE: - aps = (MSG_APS*)msg; - Param = aps->GetMessageSynchroLen(); - break; + Param += msg->m_ComCommandList[index].first; } + return Param + PLen + Head + Tail; } int PackMessage::Pack(const CMessage* const msg, byte* buf, size_t len ) { - int Result = 0; + int index = _Head(msg,buf,len); + for (int i = 0; i < (int)msg->m_ComCommandList.size(); i++) + { + _PushCommandLenList(msg->m_ComCommandList[i].first); + } + + //б + CHECKUP_DATALEN(index,len); + index = _CreateCommandLenList(buf,index); - switch (msg->GetMessageType()) + m_CommandList.resize(msg->m_ComCommandList.size()); + + for (int i = 0; i < (int)msg->m_ComCommandList.size(); i++) { - case MSG_AVC_TYPE: - Result = _Pack((MSG_AVC*)msg,buf,len); - break; - case MSG_RVC_TYPE: - Result = _Pack((MSG_RVC*)msg,buf,len); - break; - case MSG_ALI_TYPE: - Result = _Pack((MSG_ALI*)msg,buf,len); - break; - case MSG_RLI_TYPE: - Result = _Pack((MSG_RLI*)msg,buf,len); - break; - case MSG_RPS_TYPE: - Result = _Pack((MSG_RPS*)msg,buf,len); - break; - case MSG_APS_TYPE: - Result = _Pack((MSG_APS*)msg,buf,len); - break; + _PushCommandList(msg->GetComCommandList(i),msg->m_ComCommandList[i].second.size()); } - return Result; -} + + //б + CHECKUP_DATALEN(index,len); + index = _CreateCommandList(buf,index); + + //Tail + return _Tail(msg,buf,index,len); +} \ No newline at end of file diff --git a/Message/PackMessage.h b/Message/PackMessage.h index e69f541e..bd6eb08e 100644 --- a/Message/PackMessage.h +++ b/Message/PackMessage.h @@ -2,40 +2,51 @@ #pragma once -#include "MessageParser.h" +#include "MSG_UNION.h" // -#define CHECKUP_DATALEN(Index,DataLen) if(Index >= (int)DataLen){return - 1;} +#define CHECKUP_DATALEN(Index,DataLen) if(Index >= (int)DataLen){return - 1;} class PackMessage { public: - PackMessage(){} + PackMessage(){ + CommandListPos = 0; + } ~PackMessage(){} public: - int Pack( const CMessage* const msg, byte* buf, size_t len); + int Pack(const CMessage* const msg, byte* buf, size_t len); int GetMessageLen(const CMessage* const msg); private: - - int _Pack( MSG_AVC* const avc, byte* buf, size_t len); - int _Pack( MSG_RVC* const rvc, byte* buf, size_t len); + int _Head(const CMessage* const msg_clss,byte* buf, size_t len); - int _Pack( MSG_ALI* const ali, byte* buf, size_t len); + int _Tail(const CMessage* const msg_clss,byte* buf,int index ,size_t len); - int _Pack( MSG_RLI* const rli, byte* buf, size_t len); +private: + + int _CreateCommandLenList( byte* buf, int in_index); + + void _PushCommandLenList(int len); + + void _CloseCommandLenList(); - int _Pack( MSG_APS* const asp, byte* buf, size_t len); + int _PushCommandList(const byte* const in_Command, int len); - int _Pack( MSG_RPS* const rsp, byte* buf, size_t len); + int _CreateCommandList(byte* buf,int in_index); + + void _CloseCommandList(); + +private: - int _Head( CMessage* const msg_clss,byte* buf, size_t len); - int _Tail( CMessage* const msg_clss,byte* buf,int index ,size_t len); + std::vector m_CommandLenList; + std::vector > m_CommandList; + int CommandListPos; }; diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.opensdf b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.opensdf deleted file mode 100644 index 4e5e2cf5..00000000 Binary files a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.opensdf and /dev/null differ diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.sln.old b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.sln.old deleted file mode 100644 index fd20a7f1..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.sln.old +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MessageAutoDispose", "MessageAutoDispose\MessageAutoDispose.vcproj", "{EBCD1CB5-5BDA-4668-AF5D-68C313510D89}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {EBCD1CB5-5BDA-4668-AF5D-68C313510D89}.Debug|Win32.ActiveCfg = Debug|Win32 - {EBCD1CB5-5BDA-4668-AF5D-68C313510D89}.Debug|Win32.Build.0 = Debug|Win32 - {EBCD1CB5-5BDA-4668-AF5D-68C313510D89}.Release|Win32.ActiveCfg = Release|Win32 - {EBCD1CB5-5BDA-4668-AF5D-68C313510D89}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.suo b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.suo deleted file mode 100644 index 214d4993..00000000 Binary files a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.suo and /dev/null differ diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.suo.old b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.suo.old deleted file mode 100644 index 214d4993..00000000 Binary files a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.suo.old and /dev/null differ diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.aps b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.aps deleted file mode 100644 index a8d338b3..00000000 Binary files a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.aps and /dev/null differ diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.cpp b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.cpp deleted file mode 100644 index 2fed6cb9..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// MessageAutoDispose.cpp : ӦóΪ -// - -#include "stdafx.h" -#include "MessageAutoDispose.h" -#include "MessageAutoDisposeDlg.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#endif - - -// CMessageAutoDisposeApp - -BEGIN_MESSAGE_MAP(CMessageAutoDisposeApp, CWinApp) - ON_COMMAND(ID_HELP, &CWinApp::OnHelp) -END_MESSAGE_MAP() - - -// CMessageAutoDisposeApp - -CMessageAutoDisposeApp::CMessageAutoDisposeApp() -{ - // TODO: ڴ˴ӹ룬 - // Ҫijʼ InitInstance -} - - -// Ψһһ CMessageAutoDisposeApp - -CMessageAutoDisposeApp theApp; - - -// CMessageAutoDisposeApp ʼ - -BOOL CMessageAutoDisposeApp::InitInstance() -{ - // һ Windows XP ϵӦó嵥ָҪ - // ʹ ComCtl32.dll 汾 6 ߰汾ÿӻʽ - //Ҫ InitCommonControlsEx()򣬽޷ڡ - INITCOMMONCONTROLSEX InitCtrls; - InitCtrls.dwSize = sizeof(InitCtrls); - // ΪҪӦóʹõ - // ؼࡣ - InitCtrls.dwICC = ICC_WIN95_CLASSES; - InitCommonControlsEx(&InitCtrls); - - CWinApp::InitInstance(); - - AfxEnableControlContainer(); - - // ׼ʼ - // δʹЩܲϣС - // տִļĴСӦƳ - // Ҫضʼ - // ڴ洢õע - // TODO: Ӧʵ޸ĸַ - // ޸Ϊ˾֯ - SetRegistryKey(_T("ӦóɵıӦó")); - - CMessageAutoDisposeDlg dlg; - m_pMainWnd = &dlg; - INT_PTR nResponse = dlg.DoModal(); - if (nResponse == IDOK) - { - // TODO: ڴ˷ôʱ - // ȷرնԻĴ - } - else if (nResponse == IDCANCEL) - { - // TODO: ڴ˷ôʱ - // ȡرնԻĴ - } - - // ڶԻѹرգԽ FALSE Ա˳Ӧó - // ӦóϢá - return FALSE; -} diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.h b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.h deleted file mode 100644 index bd979377..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.h +++ /dev/null @@ -1,31 +0,0 @@ -// MessageAutoDispose.h : PROJECT_NAME Ӧóͷļ -// - -#pragma once - -#ifndef __AFXWIN_H__ - #error "ڰļ֮ǰstdafx.h PCH ļ" -#endif - -#include "resource.h" // - - -// CMessageAutoDisposeApp: -// йشʵ֣ MessageAutoDispose.cpp -// - -class CMessageAutoDisposeApp : public CWinApp -{ -public: - CMessageAutoDisposeApp(); - -// д - public: - virtual BOOL InitInstance(); - -// ʵ - - DECLARE_MESSAGE_MAP() -}; - -extern CMessageAutoDisposeApp theApp; \ No newline at end of file diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.rc b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.rc deleted file mode 100644 index e9365b7d..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.rc +++ /dev/null @@ -1,219 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#ifndef APSTUDIO_INVOKED -#include "targetver.h" -#endif -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// (л񹲺͹) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) -#ifdef _WIN32 -LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED -#pragma code_page(936) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#ifndef APSTUDIO_INVOKED\r\n" - "#include ""targetver.h""\r\n" - "#endif\r\n" - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "#define _AFX_NO_SPLITTER_RESOURCES\r\n" - "#define _AFX_NO_OLE_RESOURCES\r\n" - "#define _AFX_NO_TRACKER_RESOURCES\r\n" - "#define _AFX_NO_PROPERTY_RESOURCES\r\n" - "\r\n" - "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n" - "LANGUAGE 4, 2\r\n" - "#pragma code_page(936)\r\n" - "#include ""res\\MessageAutoDispose.rc2"" // Microsoft Visual C++ ༭Դ\r\n" - "#include ""l.CHS\\afxres.rc"" // ׼\r\n" - "#endif\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDR_MAINFRAME ICON "res\\MessageAutoDispose.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION " MessageAutoDispose" -FONT 9, "MS Shell Dlg", 0, 0, 0x1 -BEGIN - ICON IDR_MAINFRAME,IDC_STATIC,14,14,21,20 - LTEXT "MessageAutoDispose1.0 ",IDC_STATIC,42,14,114,8,SS_NOPREFIX - LTEXT "Copyright (C) 2012",IDC_STATIC,42,26,114,8 - DEFPUSHBUTTON "ȷ",IDOK,113,41,50,14,WS_GROUP -END - -IDD_MESSAGEAUTODISPOSE_DIALOG DIALOGEX 0, 0, 498, 249 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -EXSTYLE WS_EX_APPWINDOW -CAPTION "MessageAutoDispose" -FONT 9, "MS Shell Dlg", 0, 0, 0x1 -BEGIN - GROUPBOX "Ϣб",IDC_STATIC,7,7,127,235 - CONTROL "",IDC_TREE1,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | WS_BORDER | WS_HSCROLL | WS_TABSTOP,14,17,113,217,WS_EX_DLGMODALFRAME - GROUPBOX "",IDC_STATIC,141,7,204,128 - EDITTEXT IDC_ID,184,17,151,15,ES_AUTOHSCROLL - LTEXT "ϢID",IDC_STATIC,149,19,32,11 - EDITTEXT IDC_Note,184,52,150,15,ES_AUTOHSCROLL - LTEXT "עͣ",IDC_STATIC,150,53,29,12 - EDITTEXT IDC_EDIT4,184,34,150,15,ES_AUTOHSCROLL - LTEXT "Ϣ:",IDC_STATIC,148,36,32,12 - GROUPBOX "",IDC_STATIC,142,141,349,101 - CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_NOLABELWRAP | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,150,153,333,72,WS_EX_CLIENTEDGE - GROUPBOX "б",IDC_STATIC,351,7,130,127 - PUSHBUTTON "",IDC_BUTTON1,185,117,44,15 - PUSHBUTTON "½",IDC_BUTTON2,150,226,46,16 - PUSHBUTTON "Button3",IDC_BUTTON3,441,226,50,16 - PUSHBUTTON "޸",IDC_BUTTON4,201,226,46,16 - EDITTEXT IDC_EDIT1,185,73,150,41,ES_AUTOHSCROLL - LTEXT "ע:",IDC_STATIC,151,77,26,21 - CONTROL " IDִʱʾ",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,252,121,86,9 -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,1 - PRODUCTVERSION 1,0,0,1 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "080403a8" - BEGIN - VALUE "CompanyName", "TODO: <˾>" - VALUE "FileDescription", "TODO: <ļ˵>" - VALUE "FileVersion", "1.0.0.1" - VALUE "InternalName", "MessageAutoDispose.exe" - VALUE "LegalCopyright", "TODO: (C) <˾>Ȩ" - VALUE "OriginalFilename", "MessageAutoDispose.exe" - VALUE "ProductName", "TODO: <Ʒ>" - VALUE "ProductVersion", "1.0.0.1" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x804, 936 - END -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_ABOUTBOX, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 163 - TOPMARGIN, 7 - BOTTOMMARGIN, 55 - END - - IDD_MESSAGEAUTODISPOSE_DIALOG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 491 - TOPMARGIN, 7 - BOTTOMMARGIN, 242 - END -END -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE -BEGIN - IDS_ABOUTBOX " MessageAutoDispose(&A)..." -END - -#endif // (л񹲺͹) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// -#define _AFX_NO_SPLITTER_RESOURCES -#define _AFX_NO_OLE_RESOURCES -#define _AFX_NO_TRACKER_RESOURCES -#define _AFX_NO_PROPERTY_RESOURCES - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) -LANGUAGE 4, 2 -#pragma code_page(936) -#include "res\MessageAutoDispose.rc2" // Microsoft Visual C++ ༭Դ -#include "l.CHS\afxres.rc" // ׼ -#endif - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcproj b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcproj deleted file mode 100644 index 797908cd..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcproj +++ /dev/null @@ -1,280 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcproj.Sum-PC.Sum.user b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcproj.Sum-PC.Sum.user deleted file mode 100644 index 593846c4..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcproj.Sum-PC.Sum.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcxproj b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcxproj deleted file mode 100644 index 292da28b..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcxproj +++ /dev/null @@ -1,152 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Template - Win32 - - - - {EBCD1CB5-5BDA-4668-AF5D-68C313510D89} - MessageAutoDispose - MFCProj - - - - Application - Static - Unicode - true - - - Application - Static - MultiByte - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - _DEBUG;%(PreprocessorDefinitions) - false - true - - - Disabled - WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - Use - Level3 - EditAndContinue - - - _DEBUG;%(PreprocessorDefinitions) - 0x0804 - $(IntDir);%(AdditionalIncludeDirectories) - - - true - Windows - MachineX86 - - - - - NDEBUG;%(PreprocessorDefinitions) - false - true - - - MaxSpeed - true - WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions) - false - MultiThreaded - true - Use - Level3 - ProgramDatabase - - - NDEBUG;%(PreprocessorDefinitions) - 0x0804 - $(IntDir);%(AdditionalIncludeDirectories) - - - true - Windows - true - true - MachineX86 - - - - - - - - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcxproj.filters b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcxproj.filters deleted file mode 100644 index 1eab46f3..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcxproj.filters +++ /dev/null @@ -1,65 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - 源文件 - - - 源文件 - - - 源文件 - - - 源文件 - - - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - - - 资源文件 - - - 资源文件 - - - - - - 资源文件 - - - \ No newline at end of file diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcxproj.user b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcxproj.user deleted file mode 100644 index 695b5c78..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.vcxproj.user +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDisposeDlg.cpp b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDisposeDlg.cpp deleted file mode 100644 index 310d020a..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDisposeDlg.cpp +++ /dev/null @@ -1,238 +0,0 @@ -// MessageAutoDisposeDlg.cpp : ʵļ -// - -#include "stdafx.h" -#include "Parser.h" -#include "MessageAutoDispose.h" -#include "MessageAutoDisposeDlg.h" -#include "Parser.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#endif - -MessageAutoDispose m_mad; - -// Ӧó򡰹ڡ˵ CAboutDlg Ի - -class CAboutDlg : public CDialog -{ -public: - CAboutDlg(); - -// Ի - enum { IDD = IDD_ABOUTBOX }; - - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV ֧ - -// ʵ -protected: - DECLARE_MESSAGE_MAP() -}; - -CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) -{ -} - -void CAboutDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); -} - -BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) -END_MESSAGE_MAP() - - -// CMessageAutoDisposeDlg Ի - - - - -CMessageAutoDisposeDlg::CMessageAutoDisposeDlg(CWnd* pParent /*=NULL*/) - : CDialog(CMessageAutoDisposeDlg::IDD, pParent) -{ - m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); -} - -void CMessageAutoDisposeDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Control(pDX, IDC_TREE1, m_Messagelist); - DDX_Control(pDX, IDC_EDIT4, m_EditName); - DDX_Control(pDX, IDC_ID, m_EditID); - DDX_Control(pDX, IDC_LIST1, m_ParamList); - DDX_Control(pDX, IDC_Note, m_EditNote); -} - -BEGIN_MESSAGE_MAP(CMessageAutoDisposeDlg, CDialog) - ON_WM_SYSCOMMAND() - ON_WM_PAINT() - ON_WM_QUERYDRAGICON() - //}}AFX_MSG_MAP - ON_NOTIFY(NM_CLICK, IDC_TREE1, &CMessageAutoDisposeDlg::OnNMClickTree1) - ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, &CMessageAutoDisposeDlg::OnTvnSelchangedTree1) -END_MESSAGE_MAP() - - -// CMessageAutoDisposeDlg Ϣ - -BOOL CMessageAutoDisposeDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // ...˵ӵϵͳ˵С - - // IDM_ABOUTBOX ϵͳΧڡ - ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); - ASSERT(IDM_ABOUTBOX < 0xF000); - - CMenu* pSysMenu = GetSystemMenu(FALSE); - if (pSysMenu != NULL) - { - CString strAboutMenu; - strAboutMenu.LoadString(IDS_ABOUTBOX); - if (!strAboutMenu.IsEmpty()) - { - pSysMenu->AppendMenu(MF_SEPARATOR); - pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); - } - } - - // ô˶ԻͼꡣӦóڲǶԻʱܽԶ - // ִд˲ - SetIcon(m_hIcon, TRUE); // ôͼ - SetIcon(m_hIcon, FALSE); // Сͼ - - // TODO: ڴӶijʼ - //List - m_ParamList.SetExtendedStyle(LVS_EX_GRIDLINES); - m_ParamList.InsertColumn( 0, _T("Ϣ"), LVCFMT_LEFT, 70 ); - m_ParamList.InsertColumn( 1, _T("Ϣ"), LVCFMT_LEFT, 130); - m_ParamList.InsertColumn( 2, _T("˵"), LVCFMT_LEFT, 300); - //Tree - m_CTOS = m_Messagelist.InsertItem(_T("Client -> Server")); - m_STOC = m_Messagelist.InsertItem(_T("Server -> Client")); - m_CTODP= m_Messagelist.InsertItem(_T("Client -> DP")); - m_DPTOC= m_Messagelist.InsertItem(_T("DP -> Client")); - m_mad.Open(_T("MsgDef.h")); - for(int index = 0; index < (int)m_mad.GetMessageList().size();index++) - { - if (m_mad.GetMessageList()[index].Find(_T("_A")) != -1) - { - m_Messagelist.InsertItem(m_mad.GetMessageList()[index],m_CTOS); - } - if (m_mad.GetMessageList()[index].Find(_T("_R")) != -1) - { - m_Messagelist.InsertItem(m_mad.GetMessageList()[index],m_STOC); - } - if (m_mad.GetMessageList()[index].Find(_T("_AQ")) != -1) - { - m_Messagelist.InsertItem(m_mad.GetMessageList()[index],m_CTODP); - } - if (m_mad.GetMessageList()[index].Find(_T("_RQ")) != -1) - { - m_Messagelist.InsertItem(m_mad.GetMessageList()[index],m_DPTOC); - } - } - - return TRUE; // ǽõؼ򷵻 TRUE -} - -void CMessageAutoDisposeDlg::OnSysCommand(UINT nID, LPARAM lParam) -{ - if ((nID & 0xFFF0) == IDM_ABOUTBOX) - { - CAboutDlg dlgAbout; - dlgAbout.DoModal(); - } - else - { - CDialog::OnSysCommand(nID, lParam); - } -} - -// ԻСťҪĴ -// Ƹͼꡣʹĵ/ͼģ͵ MFC Ӧó -// ⽫ɿԶɡ - -void CMessageAutoDisposeDlg::OnPaint() -{ - if (IsIconic()) - { - CPaintDC dc(this); // ڻƵ豸 - - SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); - - // ʹͼڹо - int cxIcon = GetSystemMetrics(SM_CXICON); - int cyIcon = GetSystemMetrics(SM_CYICON); - CRect rect; - GetClientRect(&rect); - int x = (rect.Width() - cxIcon + 1) / 2; - int y = (rect.Height() - cyIcon + 1) / 2; - - // ͼ - dc.DrawIcon(x, y, m_hIcon); - } - else - { - CDialog::OnPaint(); - } -} - -//û϶Сʱϵͳô˺ȡù -//ʾ -HCURSOR CMessageAutoDisposeDlg::OnQueryDragIcon() -{ - return static_cast(m_hIcon); -} - - - -void CMessageAutoDisposeDlg::OnNMClickTree1(NMHDR *pNMHDR, LRESULT *pResult) -{ - // TODO: ڴӿؼ֪ͨ - *pResult = 0; -// CString ctmp; -// ctmp = m_Messagelist.GetItemText(m_Messagelist.GetSelectedItem()); -// if(((ctmp.Find(_T("Client -> Server")) == -1)&&(ctmp.Find(_T("Server -> Client")) == -1))&&((ctmp.Find(_T("Client -> DP")) == -1)&&(ctmp.Find(_T("DP -> Client")) == -1))) -// { -// if (!ctmp.IsEmpty()) -// { -// m_EditName.SetWindowText(ctmp); -// } -// } -} - -void CMessageAutoDisposeDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult) -{ - LPNMTREEVIEW pNMTreeView = reinterpret_cast(pNMHDR); - // TODO: ڴӿؼ֪ͨ - *pResult = 0; - CString ctmp; - int nRow; - //б - m_ParamList.DeleteAllItems(); - ctmp = m_Messagelist.GetItemText(m_Messagelist.GetSelectedItem()); - if(((ctmp.Find(_T("Client -> Server")) == -1)&&(ctmp.Find(_T("Server -> Client")) == -1))&&((ctmp.Find(_T("Client -> DP")) == -1)&&(ctmp.Find(_T("DP -> Client")) == -1))) - { - if (!ctmp.IsEmpty()) - { - m_EditName.SetWindowText(ctmp); - m_EditID.SetWindowText(m_mad.GetID(ctmp)); - m_EditNote.SetWindowText(m_mad.GetNote(ctmp)); - m_mad.GetParam(ctmp); - for (int index = 0; index < (int)m_mad.GetMessageParamType().size();index++) - { - nRow = m_ParamList.InsertItem(0,m_mad.GetMessageParamType()[index]); - m_ParamList.SetItemText(nRow,1,m_mad.GetMessageParam()[index]); - m_ParamList.SetItemText(nRow,2,m_mad.GetMessageParamNote()[index]); - } - } - }else{ - m_EditName.SetWindowText(_T("")); - m_EditID.SetWindowText(_T("")); - m_EditNote.SetWindowText(_T("")); - } -} diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDisposeDlg.h b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDisposeDlg.h deleted file mode 100644 index 5fb3eddc..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MessageAutoDisposeDlg.h +++ /dev/null @@ -1,53 +0,0 @@ -// MessageAutoDisposeDlg.h : ͷļ -// - -#pragma once -#include "afxwin.h" -#include "afxcmn.h" - -// CMessageAutoDisposeDlg Ի -class CMessageAutoDisposeDlg : public CDialog -{ -// -public: - CMessageAutoDisposeDlg(CWnd* pParent = NULL); // ׼캯 - -// Ի - enum { IDD = IDD_MESSAGEAUTODISPOSE_DIALOG }; - - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV ֧ - - -// ʵ -protected: - HICON m_hIcon; - - // ɵϢӳ亯 - virtual BOOL OnInitDialog(); - afx_msg void OnSysCommand(UINT nID, LPARAM lParam); - afx_msg void OnPaint(); - afx_msg HCURSOR OnQueryDragIcon(); - DECLARE_MESSAGE_MAP() -public: - CButton m_OK; - // Ϣб - CTreeCtrl m_Messagelist; -private: - TVINSERTSTRUCT tvInsert; - HTREEITEM m_CTOS; - HTREEITEM m_STOC; - HTREEITEM m_CTODP; - HTREEITEM m_DPTOC; -public: - afx_msg void OnNMClickTree1(NMHDR *pNMHDR, LRESULT *pResult); - // Ϣ - CEdit m_EditName; - afx_msg void OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult); - // ID - CEdit m_EditID; - // б - CListCtrl m_ParamList; - // עͿ... - CEdit m_EditNote; -}; diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MsgDef.cpp b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MsgDef.cpp deleted file mode 100644 index 1c3bac19..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MsgDef.cpp +++ /dev/null @@ -1,822 +0,0 @@ -#pragma once - -#include "MsgDef.h" - - -void LittleSwapBigByte(byte* in_byte_ptr,size_t len) -{ - byte* tmpByte_ptr = new byte[len]; - if (in_byte_ptr != NULL) - { - for (int index = 0,Pos = 1; index < (int)len; index++,Pos++) - { - tmpByte_ptr[index] = in_byte_ptr[len - Pos]; - } - memcpy(in_byte_ptr,tmpByte_ptr,len); - } - delete [] tmpByte_ptr; -} - -uint byteToInt(byte* in_byte,size_t len) -{ - byte tmpByte[4] = {0}; - if (in_byte == NULL) - { - return 0; - } - - for (int index = 0; index < (int)len; index++) - { - tmpByte[index] = in_byte[index]; - } - - uint* lpDataLen = NULL; - lpDataLen = (uint *)tmpByte; - return (*lpDataLen); -} - -void IntTobyte(int in_int,byte* out_byte) -{ - if (out_byte == NULL) - { - return; - } - for(int i = 0; i < 4; i++) - { - out_byte[i]=(byte)(in_int>>(24-i*8)); - } -} - - -int CMessage::GetMessageType() -{ - if (GetBeginTab() != true || GetEndTab() != true) - { - return -1; - } - return _MessageType(); -} - -bool CMessage::GetBeginTab() -{ - return m_Begin; -} - -bool CMessage::GetEndTab() -{ - return m_Begin; -} - -byte CMessage::GetCommand() -{ - return m_Command; -} - -byte* CMessage::GetCmlListLen() -{ - return m_CmlListLen; -} - -uint CMessage::GetSerial() -{ - return BigLittleSwap16(byteToInt(m_Serial,2)); -} - -byte* CMessage::GetGUID() -{ - return m_GUID; -} - -byte** CMessage::GetCmlCommandList() -{ - return m_CmlCommandList; -} - -uint CMessage::GetVerify() -{ - return m_Verify; -} - -uint CMessage::GetObligate() -{ - return m_Obligate; -} - -uint CMessage::GetVersion() -{ - return m_Ver; -} - -uint CMessage::GetCmlCount() -{ - return m_CmlCount; -} - -uint CMessage::GetDataLen() -{ - return m_Len; -} - - -// Set - -bool CMessage::SetCommand(byte in_byte) -{ - m_Command = in_byte; - return true; -} - -bool CMessage::SetCmlListLen(byte* in_byte_ptr,int CmlCount) -{ - if (CmlCount != 0) - { - delete [] m_CmlListLen; - m_CmlListLen = new byte[CmlCount * 4]; - memset(m_CmlListLen,0,CmlCount * 4); - if (in_byte_ptr != NULL) - { - memcpy(m_CmlListLen,in_byte_ptr,CmlCount * 4); - } - return true; - } - return false; -} - - -bool CMessage::SetSerial(ushort in_short) -{ - byte tmpbyte[4] = {0}; - if (m_Serial != NULL) - { - IntTobyte(in_short,tmpbyte); - //ȡ2λ - for(int i = 2,Pos = 0; i < 4;Pos++,i++) - { - m_Serial[Pos] = tmpbyte[i]; - } - return true; - } - return false; -} - - -bool CMessage::SetGUID(byte* in_byte_ptr) -{ - if (in_byte_ptr != NULL) - { - memset(m_GUID,0,16); - memcpy(m_GUID,in_byte_ptr,16); - return true; - } - return false; -} - -bool CMessage::SetCmlCommandList(int CmlCount) -{ - if (CmlCount != 0) - { - for (int count = 0; (int)m_CmlCount < count; count++) - { - if (m_CmlCommandList[count]) - { - delete [] m_CmlCommandList[count]; - m_CmlCommandList[count] = NULL; - } - } - - delete m_CmlCommandList; - m_CmlCommandList = new byte*[CmlCount]; - return true; - } - return false; -} - - -bool CMessage::SetVerify(uint in_Int) -{ - m_Verify = in_Int; - return true; -} - -bool CMessage::SetObligate(uint in_Int) -{ - m_Obligate = in_Int; - return true; -} - -bool CMessage::SetVersion(uint in_Int) -{ - m_Ver = in_Int; - return true; -} - -bool CMessage::SetCmlCount(uint in_Int) -{ - m_CmlCount = in_Int; - return true; -} - -bool CMessage::SetDataLen(uint in_Int) -{ - m_Len = in_Int; - return true; -} - - - -int CMessage::_MessageType() -{ - int _type = 0; - switch(m_Command) - { - case MSG_AVC_COM: _type = MSG_AVC_TYPE; - break; - case MSG_ALI_COM: _type = MSG_ALI_TYPE; - break; - case MSG_RVC_COM: _type = MSG_RVC_TYPE; - break; - case MSG_RLI_COM: _type = MSG_RLI_TYPE; - break; - case MSG_RPS_COM: _type = MSG_RPS_TYPE; - break; - case MSG_APS_COM: _type = MSG_APS_TYPE; - break; - } - return _type; -} - -void CMessage::_Initialization() -{ - memset(m_GUID,0,16); - memset(m_Serial,0,2); - m_Begin = false; - m_End = false; - m_CmlListLen = NULL; - m_CmlCommandList = NULL; - m_CmlCount = 0; - m_Obligate = 0; - m_Ver = 0; - m_Verify = 0; - //m_Serial = 0; - m_Len = 0; - m_Command = 0; -} - -void CMessage::_Close() -{ - if (m_CmlCommandList) - { - for (int count = 0; (int)m_CmlCount < count; count++) - { - if (m_CmlCommandList[count]) - { - delete [] m_CmlCommandList[count]; - m_CmlCommandList[count] = NULL; - } - } - - delete m_CmlCommandList; - m_CmlCommandList = NULL; - } - - if (m_CmlListLen != NULL) - { - delete[] m_CmlListLen; - m_CmlListLen = NULL; - } - - m_CmlCount = NULL; -} - - -//RVC(ȡ֤) -void MSG_RVC::Initialize() -{ -// if (GetBeginTab() != true || GetEndTab() != true) -// { -// m_Error++; -// } - - if (GetCommand() != m_Command) - { - m_Error++; - } - - if (GetCmlCount() != m_CmlCount) - { - m_Error++; - } - //Ч -// if (strcmp(returnVerify(),"") != 0) -// { -// m_Error++; -// } - -} - -byte* MSG_RVC::GetMachineAddress() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return GetCmlCommandList()[0]; -} - -void MSG_RVC::SetMachineAddress( byte* in_byte_ptr, size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_MachineAddressLen = len; - if (GetCmlCommandList()[0] != NULL) - { - GetCmlCommandList()[0] = new byte[len]; - } - memset(GetCmlCommandList()[0],0,len); - memcpy(GetCmlCommandList()[0],in_byte_ptr,16); -} - -//AVC(ȡ֤Ӧ) -void MSG_AVC::Initialize() -{ -// if (GetBeginTab() != true || GetEndTab() != true) -// { -// m_Error++; -// } - - if (GetCommand() != m_Command) - { - m_Error++; - } - - if (GetCmlCount() != m_CmlCount) - { - m_Error++; - } - //Ч - // if (strcmp(returnVerify(),"") != 0) - // { - // m_Error++; - // } - -} - -uint MSG_AVC::GetLoginTag() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return byteToInt(GetCmlCommandList()[2],1); -} - -uint MSG_AVC::GetCaptchaType() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return byteToInt(GetCmlCommandList()[1],1); -} - -byte* MSG_AVC::GetCaptcha() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return GetCmlCommandList()[0]; -} - - -void MSG_AVC::SetLoginTag(byte in_byte) -{ - //ֻռһֽ - if (GetCmlCommandList()[2] != NULL) - { - GetCmlCommandList()[2] = new byte[1]; - } - GetCmlCommandList()[2][0] = in_byte; -} - -void MSG_AVC::SetCaptchaType(byte in_byte) -{ - //ֻռһֽ - if (GetCmlCommandList()[1] != NULL) - { - GetCmlCommandList()[1] = new byte[1]; - } - GetCmlCommandList()[1][0] = in_byte; -} - -void MSG_AVC::SetCaptcha(byte* in_byte_ptr,size_t len) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_CaptchaLen = len; - if (GetCmlCommandList()[0] != NULL) - { - GetCmlCommandList()[0] = new byte[len]; - } - memset(GetCmlCommandList()[0],0,len); - memcpy(GetCmlCommandList()[0],in_byte_ptr,len); -} - -//RLI(¼) -void MSG_RLI::Initialize() -{ -// if (GetBeginTab() != true || GetEndTab() != true) -// { -// m_Error++; -// } - - if (GetCommand() != m_Command) - { - m_Error++; - } - - if (GetCmlCount() != m_CmlCount) - { - m_Error++; - } - //Ч - // if (strcmp(returnVerify(),"") != 0) - // { - // m_Error++; - // } - -} -byte* MSG_RLI::GetVerificationCode() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return GetCmlCommandList()[2]; -} - - -byte* MSG_RLI::GetAccountNumber() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return GetCmlCommandList()[1]; -} - - -byte* MSG_RLI::GetPassword() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return GetCmlCommandList()[0]; -} - -void MSG_RLI::SetVerificationCode( byte* in_byte_ptr,size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_VerificationCodeLen = len; - if (GetCmlCommandList()[2] != NULL) - { - GetCmlCommandList()[2] = new byte[len]; - } - memset(GetCmlCommandList()[2],0,len); - memcpy(GetCmlCommandList()[2],in_byte_ptr,len); -} - -void MSG_RLI::SetAccountNumber( byte* in_byte_ptr,size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_AccountNumberLen = len; - if (GetCmlCommandList()[1] != NULL) - { - GetCmlCommandList()[1] = new byte[len]; - } - memset(GetCmlCommandList()[1],0,len); - memcpy(GetCmlCommandList()[1],in_byte_ptr,len); -} - -void MSG_RLI::SetPassword( byte* in_byte_ptr,size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_PasswordLen = len; - if (GetCmlCommandList()[0] != NULL) - { - GetCmlCommandList()[0] = new byte[len]; - } - memset(GetCmlCommandList()[0],0,len); - memcpy(GetCmlCommandList()[0],in_byte_ptr,len); -} - -//ALI(¼Ӧ) -void MSG_ALI::Initialize() -{ -// if (GetBeginTab() != true || GetEndTab() != true) -// { -// m_Error++; -// } - - if (GetCommand() != m_Command) - { - m_Error++; - } - - if (GetCmlCount() != m_CmlCount) - { - m_Error++; - } - //Ч - // if (strcmp(returnVerify(),"") != 0) - // { - // m_Error++; - // } - -} -uint MSG_ALI::GetLoginResult() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return byteToInt(GetCmlCommandList()[2],1); -} - - -uint MSG_ALI::GetToken() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return byteToInt(GetCmlCommandList()[1],4); -} - - -byte* MSG_ALI::GetATLGUID() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return GetCmlCommandList()[0]; -} - -void MSG_ALI::SetLoginResult( byte in_byte ) -{ - if (GetCmlCommandList()[2] != NULL) - { - GetCmlCommandList()[2] = new byte[1]; - } - GetCmlCommandList()[2][0] = in_byte; -} - -void MSG_ALI::SetToken( byte* in_byte_ptr, size_t len /*= 4*/) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_TokenLen = len; - if (GetCmlCommandList()[1] != NULL) - { - GetCmlCommandList()[1] = new byte[len]; - } - memset(GetCmlCommandList()[1],0,len); - memcpy(GetCmlCommandList()[1],in_byte_ptr,len); -} - -void MSG_ALI::SetATLGUID( byte* in_byte_ptr, size_t len /*= 16*/ ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_ALTGUIDLen = len; - if (GetCmlCommandList()[0] != NULL) - { - GetCmlCommandList()[0] = new byte[len]; - } - memset(GetCmlCommandList()[0],0,len); - memcpy(GetCmlCommandList()[0],in_byte_ptr,len); -} - - - -//RPS(Ϣ֪ͬͨ) -void MSG_RPS::Initialize() -{ -// if (GetBeginTab() != true || GetEndTab() != true) -// { -// m_Error++; -// } - - if (GetCommand() != m_Command) - { - m_Error++; - } - - if (GetCmlCount() != m_CmlCount) - { - m_Error++; - } - //Ч - // if (strcmp(returnVerify(),"") != 0) - // { - // m_Error++; - // } - -} -uint MSG_RPS::GetRank() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return byteToInt(GetCmlCommandList()[4],1); -} - - -byte* MSG_RPS::GetNickname() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return GetCmlCommandList()[3]; -} - - -byte* MSG_RPS::GetAutograph() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return GetCmlCommandList()[2]; -} - -uint MSG_RPS::GetHeadForm() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return byteToInt(GetCmlCommandList()[1],1); -} - -byte* MSG_RPS::GetHeadPortrait() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return GetCmlCommandList()[0]; -} - -void MSG_RPS::SetRank( byte in_byte ) -{ - if (GetCmlCommandList()[4] != NULL) - { - GetCmlCommandList()[4] = new byte[1]; - } - GetCmlCommandList()[4][0] = in_byte; -} - - -void MSG_RPS::SetNickname( byte* in_byte_ptr,size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_NicknameLen = len; - if (GetCmlCommandList()[3] != NULL) - { - GetCmlCommandList()[3] = new byte[len]; - } - memset(GetCmlCommandList()[3],0,len); - memcpy(GetCmlCommandList()[3],in_byte_ptr,len); -} - - -void MSG_RPS::SetAutograph( byte* in_byte_ptr,size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_AutographLen = len; - if (GetCmlCommandList()[2] != NULL) - { - GetCmlCommandList()[2] = new byte[len]; - } - memset(GetCmlCommandList()[2],0,len); - memcpy(GetCmlCommandList()[2],in_byte_ptr,len); -} - -void MSG_RPS::SetHeadForm( byte in_byte ) -{ - if (GetCmlCommandList()[1] != NULL) - { - GetCmlCommandList()[1] = new byte[1]; - } - GetCmlCommandList()[1][0] = in_byte; -} - -void MSG_RPS::SetHeadPortrait( byte* in_byte_ptr,size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_HeadPortraitLen = len; - if (GetCmlCommandList()[0] != NULL) - { - GetCmlCommandList()[0] = new byte[len]; - } - memset(GetCmlCommandList()[0],0,len); - memcpy(GetCmlCommandList()[0],in_byte_ptr,len); -} - - - - -//APS(Ϣ֪ͬͨȷ) -void MSG_APS::Initialize() -{ -// if (GetBeginTab() != true || GetEndTab() != true) -// { -// m_Error++; -// } - - if (GetCommand() != m_Command) - { - m_Error++; - } - - if (GetCmlCount() != m_CmlCount) - { - m_Error++; - } - //Ч - // if (strcmp(returnVerify(),"") != 0) - // { - // m_Error++; - // } - -} -byte* MSG_APS::GetMessageSynchro() -{ - Initialize(); - if (m_Error != 0) - { - return 0; - } - return GetCmlCommandList()[0]; -} - -void MSG_APS::SetMessageSynchro( byte* in_byte_ptr,size_t len ) -{ - if (in_byte_ptr == NULL) - { - return; - } - m_MessageSynchroLen = len; - if (GetCmlCommandList()[0] != NULL) - { - GetCmlCommandList()[0] = new byte[len]; - } - memset(GetCmlCommandList()[0],0,len); - memcpy(GetCmlCommandList()[0],in_byte_ptr,len); -} diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MsgDef.h b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MsgDef.h deleted file mode 100644 index 4391052d..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/MsgDef.h +++ /dev/null @@ -1,585 +0,0 @@ - -#pragma once - - -/* -#define MSG_ERROR_BDMISS 1 -#define MSG_ERROR_COMMAND 2 -#define MSG_ERROR_PARAM 3 -#define MSG_ERROR_LEN 4*/ - -#include - - -#define MSG_BEGIN 0x55 // 'V' ϢĿʼ -#define MSG_END 0x43 // 'C' ϢĽ -#define MSG_VER 0 //汾 - -#define MSG_CLASS_BEGIN 1 -#define MSG_CLASS_END 1 -#define MSG_CLASS_LEN 4 -#define MSG_CLASS_VER 1 -#define MSG_CLASS_SERIAL 2 -#define MSG_CLASS_GUID 16 -#define MSG_CLASS_COMMAND 1 -#define MSG_CLASS_OBL 4 -#define MSG_CLASS_PARAMCONST 1 -#define MSG_CLASS_VERIFY 2 //Ч δĬΪ2ֽ -#define MSG_CLASS_PARAM 4 - -#define VER_INDEX MSG_CLASS_VER -#define SER_INDEX MSG_CLASS_VER + MSG_CLASS_SERIAL -#define LEN_INDEX MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL -#define GUID_INDEX MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL + MSG_CLASS_GUID -#define COM_INDEX MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL + MSG_CLASS_COMMAND + MSG_CLASS_GUID -#define OBL_INDEX MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL + MSG_CLASS_GUID + MSG_CLASS_COMMAND + MSG_CLASS_OBL -#define PAC_INDEX MSG_CLASS_LEN + MSG_CLASS_VER + MSG_CLASS_SERIAL + MSG_CLASS_GUID + MSG_CLASS_COMMAND + MSG_CLASS_OBL + MSG_CLASS_PARAMCONST - -//$ MSGTYPE -enum MSGTYPE -{ - MSGTYPE_NULL, - MSG_AVC_TYPE, - MSG_RVC_TYPE, - MSG_ALI_TYPE, - MSG_RLI_TYPE, - MSG_RPS_TYPE, - MSG_APS_TYPE, -}; - -//$ MSGCONMMAND -enum MSGCONMMAND -{ - MSGCONMMAND_NULL, - MSG_RVC_COM = 0x14, - MSG_AVC_COM = 0x15, - MSG_RLI_COM = 0x16, - MSG_ALI_COM = 0x17, - MSG_RPS_COM = 0x18, - MSG_APS_COM = 0x19, -}; - - -typedef unsigned char byte; -typedef unsigned int uint; -typedef unsigned short ushort; - -// ʹС˻ -#define BigLittleSwap16(A) ((((ushort)(A) & 0xff00) >> 8) | \ - (((ushort)(A) & 0x00ff) << 8)) - -// ʹС˻ -#define BigLittleSwap32(A) ((((uint)(A) & 0xff000000) >> 24) | \ - (((uint)(A) & 0x00ff0000) >> 8) | \ - (((uint)(A) & 0x0000ff00) << 8) | \ - (((uint)(A) & 0x000000ff) << 24)) - - -uint byteToInt(byte* in_byte,size_t len); - -void IntTobyte(int in_int,byte* out_byte); - -void LittleSwapBigByte(byte* in_byte_ptr,size_t len); - - -class CMessage -{ -public: - - friend class CMessageParser; - - CMessage(){ - _Initialization(); - } - - ~CMessage(){ - _Close(); - } - //ȡϢ - int GetMessageType(); - - -public: - - bool GetBeginTab(); - - bool GetEndTab(); - - byte GetCommand(); - - byte* GetCmlListLen(); - - uint GetSerial(); - - byte* GetGUID(); - - byte** GetCmlCommandList(); - - uint GetVerify(); - - uint GetObligate(); - - uint GetVersion(); - - uint GetCmlCount(); - - uint GetDataLen(); - - -// Set - - bool SetCommand(byte in_byte); - - bool SetCmlListLen(byte* in_byte_ptr,int CmlCount); - - bool SetSerial(ushort in_short); - - bool SetGUID(byte* in_byte_ptr); - - bool SetCmlCommandList(int CmlCount); - - bool SetVerify(uint in_Int); - - bool SetObligate(uint in_Int); - - bool SetVersion(uint in_Int); - - bool SetCmlCount(uint in_Int); - - bool SetDataLen(uint in_Int); - - -private: - - - bool m_Begin; //ϢĿʼ ͳһַ'V"ASC 0x55 - bool m_End; //ϢĽ ̶ַ'CASC 0x43 - - byte m_Command; //ָ ָעݰĹ - byte* m_CmlListLen; //б 4ֽڣӦNij - byte m_Serial[2]; // ָı - byte m_GUID[16]; //GUID ṩû֤ - byte** m_CmlCommandList; //б IJ͸ݾָ - //DWORD dwType; //Ϣ - - - uint m_Verify; //Ч Ԥ - - uint m_Obligate; //Ԥռ - uint m_Ver; //汾 ־VNOCЭİ汾 - uint m_CmlCount; // IJ͸ݾָ - uint m_Len; //峤 4ֽڣָijȣԸݽ - -private: - - - void _Initialization(); - void _Close(); - int _MessageType(); -}; - - -//RVC(ȡ֤) -class MSG_RVC: public CMessage -{ -public: - - MSG_RVC(){ - //һ - m_CmlCount = 1; - //0x14 - m_Command = 20; - m_Error = 0; - - //Ԥ - SetDataLen(0); - SetVersion(MSG_VER); - SetSerial(0x00); - SetCommand(m_Command); - SetObligate(0); - SetCmlCount(m_CmlCount); - SetVerify(0); - //òȿռ - SetCmlListLen(0,m_CmlCount); - //òռ - SetCmlCommandList(m_CmlCount); - } - //ַ - byte* GetMachineAddress(); - - void SetMachineAddress(byte* in_byte_ptr, size_t len); - - int GetMachineAddressLen(){ - return m_MachineAddressLen; - } - - ~MSG_RVC(){} - -private: - - void Initialize(); - - //ַ - //byte* m_MachineAddress; - - // - int m_CmlCount; - - //ָ - int m_Command; - - // - int m_Error; - - //MachineAddress - int m_MachineAddressLen; - -}; - -//AVC(ȡ֤Ӧ) -class MSG_AVC: public CMessage -{ -public: - - MSG_AVC(){ - // - m_CmlCount = 3; - //0x15 - m_Command = 21; - m_Error = 0; - - //Ԥ - SetDataLen(0); - SetVersion(MSG_VER); - SetSerial(0x00); - SetCommand(m_Command); - SetObligate(0); - SetCmlCount(m_CmlCount); - SetVerify(0); - //òȿռ - SetCmlListLen(0,m_CmlCount); - //òռ - SetCmlCommandList(m_CmlCount); - } - //ȡ֤1ֽڣ־˴ε¼Ľ - uint GetLoginTag(); - //֤ͣ־֤õĺ壬֤Ͷһö٣ - uint GetCaptchaType(); - //֤壺֤峤ȲָСʽͼ - byte* GetCaptcha(); - - - void SetLoginTag(byte in_byte); - - void SetCaptchaType(byte in_byte); - - void SetCaptcha(byte* in_byte_ptr,size_t len); - - - // - int GetCaptchaLen(){ - return m_CaptchaLen; - } - - ~MSG_AVC(){} - -private: - - void Initialize(); - - // - int m_CmlCount; - - //ָ - int m_Command; - - // - int m_Error; - - //Captcha - int m_CaptchaLen; - -}; - - -//RLI(¼) -class MSG_RLI:public CMessage -{ - -public: - - MSG_RLI(){ - // - m_CmlCount = 3; - //0x16 - m_Command = 22; - m_Error = 0; - - //Ԥ - SetDataLen(0); - SetVersion(MSG_VER); - SetSerial(0x00); - SetCommand(m_Command); - SetObligate(0); - SetCmlCount(m_CmlCount); - SetVerify(0); - //òȿռ - SetCmlListLen(0,m_CmlCount); - //òռ - SetCmlCommandList(m_CmlCount); - } - //֤룺δ֪ȣΪAUTͼƬַɣ˲ڷӦư󶨣һ֤-ӳ䣩 - byte* GetVerificationCode(); - //ûʺţûʺűĶ - byte* GetAccountNumber(); - //û룺뾭Ķ - byte* GetPassword(); - - - void SetVerificationCode(byte* in_byte_ptr,size_t len); - - void SetAccountNumber(byte* in_byte_ptr,size_t len); - - void SetPassword(byte* in_byte_ptr,size_t len); - - - int GetVerificationCodeLen(){ - return m_VerificationCodeLen; - } - - int GetAccountNumberLen(){ - return m_AccountNumberLen; - } - - int GetPasswordLen(){ - return m_PasswordLen; - } - - ~MSG_RLI(){} - -private: - - void Initialize(); - - // - int m_CmlCount; - - //ָ - int m_Command; - - // - int m_Error; - - //洢 - int m_VerificationCodeLen; - int m_AccountNumberLen; - int m_PasswordLen; -}; - - -//ALI(¼Ӧ) -class MSG_ALI:public CMessage -{ - -public: - - MSG_ALI(){ - // - m_CmlCount = 3; - //0x17 - m_Command = 23; - m_Error = 0; - - //Ԥ - SetDataLen(0); - SetVersion(MSG_VER); - SetSerial(0x00); - SetCommand(m_Command); - SetObligate(0); - SetCmlCount(m_CmlCount); - SetVerify(0); - //òȿռ - SetCmlListLen(0,m_CmlCount); - //òռ - SetCmlCommandList(m_CmlCount); - } - //¼1ֽڣ־˴ε¼Ľ - uint GetLoginResult(); - //Ƴȣ4ֽڣ0x00 00 00 10ûʺűijȣλΪֽ - uint GetToken(); - //ƣ16ֽڣһGUID ʺ֤ͨɣͨݰͻˣָ֮ڰͷϴ - byte* GetATLGUID(); - - void SetLoginResult(byte in_byte); - - void SetToken(byte* in_byte_ptr,size_t len = 4); - - void SetATLGUID(byte* in_byte_ptr, size_t len = 16); - - - int GetATLGUIDLen(){ - return m_ALTGUIDLen; - } - - int GetTokenLen(){ - return m_TokenLen; - } - - ~MSG_ALI(){} - -private: - - void Initialize(); - - // - int m_CmlCount; - - //ָ - int m_Command; - - // - int m_Error; - - //TokenLen - int m_TokenLen; - //ATLGUIDLen - int m_ALTGUIDLen; -}; - - -//RPS(Ϣ֪ͬͨ) -class MSG_RPS:public CMessage -{ - -public: - - MSG_RPS(){ - // - m_CmlCount = 5; - //0x18 - m_Command = 24; - m_Error = 0; - - //Ԥ - SetDataLen(0); - SetVersion(MSG_VER); - SetSerial(0x00); - SetCommand(m_Command); - SetObligate(0); - SetCmlCount(m_CmlCount); - SetVerify(0); - //òȿռ - SetCmlListLen(0,m_CmlCount); - //òռ - SetCmlCommandList(m_CmlCount); - } - //ûȨ - uint GetRank(); - //dz - byte* GetNickname(); - //ǩ - byte* GetAutograph(); - //ͷʽ - uint GetHeadForm(); - //ͷ - byte* GetHeadPortrait(); - - void SetRank(byte in_byte); - - void SetNickname(byte* in_byte_ptr,size_t len); - - void SetAutograph(byte* in_byte_ptr,size_t len); - - void SetHeadForm(byte in_byte); - - void SetHeadPortrait(byte* in_byte_ptr,size_t len); - - - int GetNicknameLen(){ - return m_NicknameLen; - } - - int GetAutographLen(){ - return m_AutographLen; - } - - int GetHeadPortraitLen(){ - return m_HeadPortraitLen; - } - - ~MSG_RPS(){} - -private: - - void Initialize(); - - // - int m_CmlCount; - - //ָ - int m_Command; - - // - int m_Error; - - // - int m_NicknameLen; - int m_AutographLen; - int m_HeadPortraitLen; -}; - - -//APS(Ϣ֪ͬͨȷ) -class MSG_APS:public CMessage -{ - -public: - - MSG_APS(){ - // - m_CmlCount = 1; - //0x19 - m_Command = 25; - m_Error = 0; - - //Ԥ - SetDataLen(0); - SetVersion(MSG_VER); - SetSerial(0x00); - SetCommand(m_Command); - SetObligate(0); - SetCmlCount(m_CmlCount); - SetVerify(0); - //òȿռ - SetCmlListLen(0,m_CmlCount); - //òռ - SetCmlCommandList(m_CmlCount); - } - - //Ϣ֪ͬͨ - byte* GetMessageSynchro(); - - void SetMessageSynchro(byte* in_byte_ptr,size_t len); - - int GetMessageSynchroLen(){ - return m_MessageSynchroLen; - } - - ~MSG_APS(){} - -private: - - void Initialize(); - - // - int m_CmlCount; - - //ָ - int m_Command; - - // - int m_Error; - - // - int m_MessageSynchroLen; -}; \ No newline at end of file diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/Parser.cpp b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/Parser.cpp deleted file mode 100644 index 0a3f15c0..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/Parser.cpp +++ /dev/null @@ -1,205 +0,0 @@ - -#pragma once - -#include "stdafx.h" -#include "Parser.h" -#include -#include -#include -using namespace std; - -int MessageAutoDispose::Open(TCHAR* Path) -{ - int Command = 0; - ifstream file; - string line; - if (Path == NULL) - { - return -1; - } - file.open(Path); - if (!file){ - return -1; - } - for (;getline(file,line); m_LineMax++) - { - CString ctemporary=CA2CT(line.c_str(), CP_ACP); - //MSGTYPE - if ((ctemporary.Find(_T("enum")) != -1) && (ctemporary.Find(_T("MSGTYPE")) != -1)) - { - m_MSGTYPE = m_LineMax; - } - //MSGCONMMAND - if ((ctemporary.Find(_T("enum")) != -1) && (ctemporary.Find(_T("MSGCONMMAND")) != -1)) - { - m_MSGCONMMAND = m_LineMax; - } - if ((ctemporary.Find(_T("class")) != -1) && (ctemporary.Find(_T("public CMessage")) != -1)) - { - m_MsgConst.push_back(m_LineMax); - m_MsgNote.push_back(m_LineMax - 1); - } - m_ListIndex.push_back(m_LineMax); - m_ListString.push_back(ctemporary); - } - _Analysis(); - return 0; -} - -void MessageAutoDispose::_Analysis() -{ - CString ctmp; - //MSGTYPE - ctmp = m_ListString[m_MSGTYPE]; - if (ctmp.Find(_T("{")) == -1) - { - ctmp.Empty(); - ctmp.FreeExtra(); - ctmp = m_ListString[m_MSGTYPE + 1]; - if (ctmp.Find(_T("{")) == -1) - { - return; - } - } - for (int index = m_MSGTYPE + 1;ctmp.Find(_T("}")) == -1; index++) - { - ctmp.Empty(); - ctmp.FreeExtra(); - ctmp = m_ListString[index]; - if (((ctmp.Find(_T("{")) == -1)&&((ctmp.Find(_T("}")))&&(ctmp.IsEmpty() == 0)))) - { - m_MSGTYPE_List.push_back(m_ListString[index]); - } - } - //MSGCONMMAND - ctmp = m_ListString[m_MSGCONMMAND]; - if (ctmp.Find(_T("{")) == -1) - { - ctmp.Empty(); - ctmp.FreeExtra(); - ctmp = m_ListString[m_MSGCONMMAND + 1]; - if (ctmp.Find(_T("{")) == -1) - { - return; - } - } - for (int index = m_MSGCONMMAND + 1;ctmp.Find(_T("}")) == -1; index++) - { - ctmp.Empty(); - ctmp.FreeExtra(); - ctmp = m_ListString[index]; - if (((ctmp.Find(_T("{")) == -1)&&((ctmp.Find(_T("}")))&&(ctmp.IsEmpty() == 0)))) - { - m_MSGCONMMAND_List.push_back(m_ListString[index]); - } - } - - //Ϣ - ctmp.Empty(); - ctmp.FreeExtra(); - for(int index = 0;index < (int)m_MsgConst.size(); index++) - { - ctmp = m_ListString[m_MsgConst[index]]; - if (ctmp.IsEmpty() == 0) - { - ctmp.TrimLeft(_T("class")); - ctmp.TrimRight(_T("public CMessage")); - ctmp.Remove(_T(' ')); - ctmp.Remove(_T(':')); - ctmp.Remove(_T(' ')); - m_Msg_List.push_back(ctmp); - } - } - -} - -CString MessageAutoDispose::GetID(CString cStr) -{ - CString ctmp; - cStr = cStr + _T("_COM"); - for (int index = 0; index < (int)m_MSGCONMMAND_List.size();index++) - { - if (m_MSGCONMMAND_List[index].Find(cStr) != -1) - { - ctmp = m_MSGCONMMAND_List[index]; - ctmp.Replace(cStr,_T(" ")); - ctmp.Remove(_T(' ')); - ctmp.Remove(_T('=')); - ctmp.Remove(_T(',')); - ctmp.Remove(_T(' ')); - break; - } - } - return ctmp; -} - -int MessageAutoDispose::SetID(byte in_byte) -{ - return 0; -} - -int MessageAutoDispose::GetParam( CString cStr ) -{ - CString ctmp; - CString cType; - CString cName; - m_Msg_Param_List.clear(); - m_Msg_ParamType_List.clear(); - m_Msg_ParamNote_List.clear(); - int Pos = 0; - for (int index = 0; index < (int)m_MSGCONMMAND_List.size();index++) - { - if (m_Msg_List[index].Find(cStr) != -1) - { - for (int in_index = 0; in_index < (int)(m_ListString.size() - m_MsgConst[index]);in_index++) - { - ctmp = m_ListString[m_MsgConst[index] + in_index]; - Pos = ctmp.Find(_T("Get")); - if (Pos != -1) - { - //ȡ - cName = ctmp.Mid(Pos + 3 ); - cName.Remove(_T('(')); - cName.Remove(_T(')')); - cName.Remove(_T(';')); - cName.Remove(_T(' ')); - cName.Remove(_T('{')); - cName.Remove(_T(' ')); - if (cName.Right(3) != (_T("Len"))) - { - //ȡ - cType = ctmp.Left(Pos); - cType.Remove(_T(' ')); - cType.Remove(_T(' ')); - m_Msg_ParamType_List.push_back(cType); - m_Msg_Param_List.push_back(cName); - //ȡע - m_Msg_ParamNote_List.push_back(m_ListString[m_MsgConst[index] + (in_index - 1)]); - } - - } - if (ctmp.Find(_T("};")) != -1) - { - break; - } - } - break; - } - } - return 0; -} - -CString MessageAutoDispose::GetNote( CString cStr ) -{ - CString ctmp; - cStr = cStr + _T("_COM"); - for (int index = 0; index < (int)m_MSGCONMMAND_List.size();index++) - { - if (m_MSGCONMMAND_List[index].Find(cStr) != -1) - { - ctmp = m_ListString[m_MsgNote[index - 1]]; - break; - } - } - return ctmp; -} diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/Parser.h b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/Parser.h deleted file mode 100644 index e9cabf3d..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/Parser.h +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include -#include - - -class MessageAutoDispose -{ -public: - MessageAutoDispose(){ - m_LineMax = 0; - } - - ~MessageAutoDispose(){ - - } - - int Open(TCHAR* Path); - - int GetParam(CString cStr); - - //int SetParam(CString cStr); - - CString GetNote(CString cStr); - - CString GetID(CString cStr); - - int SetID(byte in_byte); - - std::vector GetMessageParam(){ - return m_Msg_Param_List; - } - - std::vector GetMessageParamNote(){ - return m_Msg_ParamNote_List; - } - - std::vector GetMessageParamType(){ - return m_Msg_ParamType_List; - } - - std::vector GetMessageList(){ - return m_Msg_List; - } - -private: - - void _Analysis(); - - CStdioFile m_File; - // - std::vector m_ListString; - std::vector m_ListIndex; - std::vector m_MSGTYPE_List; - std::vector m_MSGCONMMAND_List; - std::vector m_Msg_List; - std::vector m_Msg_ParamType_List; - std::vector m_Msg_Param_List; - std::vector m_Msg_ParamNote_List; - std::vector m_MsgConst; - std::vector m_MsgNote; - int m_LineMax; - int m_MSGTYPE; - int m_MSGCONMMAND; - LPTSTR* m_Buffer; - //void _Close(); -}; - - diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/ReadMe.txt b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/ReadMe.txt deleted file mode 100644 index d85cf7eb..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/ReadMe.txt +++ /dev/null @@ -1,70 +0,0 @@ -================================================================================ -MICROSOFT : MessageAutoDispose Ŀ -=============================================================================== - -ӦóΪ MessageAutoDispose Ӧó򡣴Ӧó򲻽ʾ Microsoft Ļʹ÷ΪдӦó㡣 - -ļҪ MessageAutoDispose Ӧóÿļݡ - -MessageAutoDispose.vcproj -ʹӦóɵ VC++ ĿĿļ -ɸļ Visual C++ İ汾ϢԼйʹӦóѡƽ̨úĿܵϢ - -MessageAutoDispose.h -ӦóҪͷļĿضͷļ( Resource.h) CMessageAutoDisposeApp Ӧóࡣ - -MessageAutoDispose.cpp -ǰӦó CMessageAutoDisposeApp ҪӦóԴļ - -MessageAutoDispose.rc -dzʹõ Microsoft Windows Դб RES Ŀ¼д洢ͼꡢλͼ͹ꡣļֱ Microsoft Visual C++ нб༭ĿԴλ 2052 С - -res\MessageAutoDispose.ico -ӦóͼͼļͼҪԴļ MessageAutoDispose.rc С - -res\MessageAutoDispose.rc2 -ļ Microsoft Visual C++ нб༭ԴӦýԴ༭༭ԴڴļС - - -///////////////////////////////////////////////////////////////////////////// - -Ӧó򵼴һԻ: - -MessageAutoDisposeDlg.hMessageAutoDisposeDlg.cpp - Ի -Щļ CMessageAutoDisposeDlg ࡣඨӦóԻΪöԻģλ MessageAutoDispose.rc Уļ Microsoft Visual C++ нб༭ - - -///////////////////////////////////////////////////////////////////////////// - -: - -ActiveX ؼ -Ӧóʹ ActiveX ؼ֧֡ - -///////////////////////////////////////////////////////////////////////////// - -׼ļ: - -StdAfx.hStdAfx.cpp -ЩļΪ MessageAutoDispose.pch Ԥͷ (PCH) ļΪ StdAfx.obj Ԥļ - -Resource.h -DZ׼ͷļµԴ ID -Microsoft Visual C++ ȡ´ļ - -MessageAutoDispose.manifest - Ӧó嵥ļ Windows XP Ӧó - ض汾г򼯵ԡسʹô - Ϣӳ򼯻ʵij򼯻 - Ӧó˽ϢӦó嵥Ϊ·ַΪ - Ӧóִļװͬļеⲿ .manifest ļ - ҲԴʽڸÿִļС -///////////////////////////////////////////////////////////////////////////// - -ע: - -ӦóʹáTODO:ָʾӦӻԶԴ벿֡ - -Ӧóڹ DLL ʹ MFCҪ·Щ MFC DLLӦóõϵͳĵǰòͬҪ·ӦıػԴ MFC90XXX.DLLйĸϢμ MSDN ĵй Redistributing Visual C++ applications (· Visual C++ Ӧó)½ڡ - -///////////////////////////////////////////////////////////////////////////// diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/res/MessageAutoDispose.ico b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/res/MessageAutoDispose.ico deleted file mode 100644 index 8a84ca3d..00000000 Binary files a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/res/MessageAutoDispose.ico and /dev/null differ diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/res/MessageAutoDispose.rc2 b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/res/MessageAutoDispose.rc2 deleted file mode 100644 index 1d0e01aa..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/res/MessageAutoDispose.rc2 +++ /dev/null @@ -1,13 +0,0 @@ -// -// MessageAutoDispose.RC2 - Microsoft Visual C++ ֱӱ༭Դ -// - -#ifdef APSTUDIO_INVOKED -#error ļ Microsoft Visual C++ ༭ -#endif //APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// ڴ˴ֶ༭Դ... - -///////////////////////////////////////////////////////////////////////////// diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/resource.h b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/resource.h deleted file mode 100644 index 8299acc2..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/resource.h +++ /dev/null @@ -1,31 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by MessageAutoDispose.rc -// -#define IDM_ABOUTBOX 0x0010 -#define IDD_ABOUTBOX 100 -#define IDS_ABOUTBOX 101 -#define IDD_MESSAGEAUTODISPOSE_DIALOG 102 -#define IDR_MAINFRAME 128 -#define IDC_TREE1 1000 -#define IDC_ID 1001 -#define IDC_Note 1002 -#define IDC_EDIT4 1004 -#define IDC_LIST1 1011 -#define IDC_BUTTON1 1012 -#define IDC_BUTTON2 1013 -#define IDC_BUTTON3 1014 -#define IDC_BUTTON4 1015 -#define IDC_EDIT1 1016 -#define IDC_CHECK1 1017 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 129 -#define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 1018 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/stdafx.cpp b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/stdafx.cpp deleted file mode 100644 index 0acae05c..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/stdafx.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// stdafx.cpp : ֻ׼ļԴļ -// MessageAutoDispose.pch ΪԤͷ -// stdafx.obj ԤϢ - -#include "stdafx.h" - - diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/stdafx.h b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/stdafx.h deleted file mode 100644 index 781f9964..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/stdafx.h +++ /dev/null @@ -1,57 +0,0 @@ -// stdafx.h : ׼ϵͳļİļ -// Ǿʹõĵ -// ضĿİļ - -#pragma once - -#ifndef _SECURE_ATL -#define _SECURE_ATL 1 -#endif - -#ifndef VC_EXTRALEAN -#define VC_EXTRALEAN // Windows ͷųʹõ -#endif - -#include "targetver.h" - -#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // ijЩ CString 캯ʽ - -// ر MFC ijЩɷĺԵľϢ -#define _AFX_ALL_WARNINGS - -#include // MFC ͱ׼ -#include // MFC չ - - -#include // MFC Զ - - - -#ifndef _AFX_NO_OLE_SUPPORT -#include // MFC Internet Explorer 4 ؼ֧ -#endif -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC Windows ؼ֧ -#endif // _AFX_NO_AFXCMN_SUPPORT - - - - - - - - - -#ifdef _UNICODE -#if defined _M_IX86 -#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") -#elif defined _M_IA64 -#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") -#elif defined _M_X64 -#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") -#else -#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") -#endif -#endif - - diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/targetver.h b/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/targetver.h deleted file mode 100644 index 356cdb9e..00000000 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose/targetver.h +++ /dev/null @@ -1,26 +0,0 @@ - -#pragma once - -// º궨Ҫƽ̨Ҫƽ̨ -// ǾӦó蹦ܵ WindowsInternet Explorer ȲƷ -// 汾ָͨ汾Ͱ汾ƽ̨пõĹܣ -// - -// ҪԵָ汾ƽ̨޸ж塣 -// йزͬƽ̨ӦֵϢο MSDN -#ifndef WINVER // ָҪƽ̨ Windows Vista -#define WINVER 0x0600 // ֵΪӦֵ Windows 汾 -#endif - -#ifndef _WIN32_WINNT // ָҪƽ̨ Windows Vista -#define _WIN32_WINNT 0x0600 // ֵΪӦֵ Windows 汾 -#endif - -#ifndef _WIN32_WINDOWS // ָҪƽ̨ Windows 98 -#define _WIN32_WINDOWS 0x0410 // ֵΪʵֵ Windows Me ߰汾 -#endif - -#ifndef _WIN32_IE // ָҪƽ̨ Internet Explorer 7.0 -#define _WIN32_IE 0x0700 // ֵΪӦֵ IE 汾 -#endif - diff --git a/MessageAutoDispose/MessageAutoDispose/UpgradeLog.XML b/MessageAutoDispose/MessageAutoDispose/UpgradeLog.XML deleted file mode 100644 index 129fde09..00000000 --- a/MessageAutoDispose/MessageAutoDispose/UpgradeLog.XML +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/MessageAutoDispose/MessageAutoDispose/_UpgradeReport_Files/UpgradeReport.css b/MessageAutoDispose/MessageAutoDispose/_UpgradeReport_Files/UpgradeReport.css deleted file mode 100644 index 3411f632..00000000 --- a/MessageAutoDispose/MessageAutoDispose/_UpgradeReport_Files/UpgradeReport.css +++ /dev/null @@ -1,207 +0,0 @@ -BODY -{ - BACKGROUND-COLOR: white; - FONT-FAMILY: "Verdana", sans-serif; - FONT-SIZE: 100%; - MARGIN-LEFT: 0px; - MARGIN-TOP: 0px -} -P -{ - FONT-FAMILY: "Verdana", sans-serif; - FONT-SIZE: 70%; - LINE-HEIGHT: 12pt; - MARGIN-BOTTOM: 0px; - MARGIN-LEFT: 10px; - MARGIN-TOP: 10px -} -.note -{ - BACKGROUND-COLOR: #ffffff; - COLOR: #336699; - FONT-FAMILY: "Verdana", sans-serif; - FONT-SIZE: 100%; - MARGIN-BOTTOM: 0px; - MARGIN-LEFT: 0px; - MARGIN-TOP: 0px; - PADDING-RIGHT: 10px -} -.infotable -{ - BACKGROUND-COLOR: #f0f0e0; - BORDER-BOTTOM: #ffffff 0px solid; - BORDER-COLLAPSE: collapse; - BORDER-LEFT: #ffffff 0px solid; - BORDER-RIGHT: #ffffff 0px solid; - BORDER-TOP: #ffffff 0px solid; - FONT-SIZE: 70%; - MARGIN-LEFT: 10px -} -.issuetable -{ - BACKGROUND-COLOR: #ffffe8; - BORDER-COLLAPSE: collapse; - COLOR: #000000; - FONT-SIZE: 100%; - MARGIN-BOTTOM: 10px; - MARGIN-LEFT: 13px; - MARGIN-TOP: 0px -} -.issuetitle -{ - BACKGROUND-COLOR: #ffffff; - BORDER-BOTTOM: #dcdcdc 1px solid; - BORDER-TOP: #dcdcdc 1px; - COLOR: #003366; - FONT-WEIGHT: normal -} -.header -{ - BACKGROUND-COLOR: #cecf9c; - BORDER-BOTTOM: #ffffff 1px solid; - BORDER-LEFT: #ffffff 1px solid; - BORDER-RIGHT: #ffffff 1px solid; - BORDER-TOP: #ffffff 1px solid; - COLOR: #000000; - FONT-WEIGHT: bold -} -.issuehdr -{ - BACKGROUND-COLOR: #E0EBF5; - BORDER-BOTTOM: #dcdcdc 1px solid; - BORDER-TOP: #dcdcdc 1px solid; - COLOR: #000000; - FONT-WEIGHT: normal -} -.issuenone -{ - BACKGROUND-COLOR: #ffffff; - BORDER-BOTTOM: 0px; - BORDER-LEFT: 0px; - BORDER-RIGHT: 0px; - BORDER-TOP: 0px; - COLOR: #000000; - FONT-WEIGHT: normal -} -.content -{ - BACKGROUND-COLOR: #e7e7ce; - BORDER-BOTTOM: #ffffff 1px solid; - BORDER-LEFT: #ffffff 1px solid; - BORDER-RIGHT: #ffffff 1px solid; - BORDER-TOP: #ffffff 1px solid; - PADDING-LEFT: 3px -} -.issuecontent -{ - BACKGROUND-COLOR: #ffffff; - BORDER-BOTTOM: #dcdcdc 1px solid; - BORDER-TOP: #dcdcdc 1px solid; - PADDING-LEFT: 3px -} -A:link -{ - COLOR: #cc6633; - TEXT-DECORATION: underline -} -A:visited -{ - COLOR: #cc6633; -} -A:active -{ - COLOR: #cc6633; -} -A:hover -{ - COLOR: #cc3300; - TEXT-DECORATION: underline -} -H1 -{ - BACKGROUND-COLOR: #003366; - BORDER-BOTTOM: #336699 6px solid; - COLOR: #ffffff; - FONT-SIZE: 130%; - FONT-WEIGHT: normal; - MARGIN: 0em 0em 0em -20px; - PADDING-BOTTOM: 8px; - PADDING-LEFT: 30px; - PADDING-TOP: 16px -} -H2 -{ - COLOR: #000000; - FONT-SIZE: 80%; - FONT-WEIGHT: bold; - MARGIN-BOTTOM: 3px; - MARGIN-LEFT: 10px; - MARGIN-TOP: 20px; - PADDING-LEFT: 0px -} -H3 -{ - COLOR: #000000; - FONT-SIZE: 80%; - FONT-WEIGHT: bold; - MARGIN-BOTTOM: -5px; - MARGIN-LEFT: 10px; - MARGIN-TOP: 20px -} -H4 -{ - COLOR: #000000; - FONT-SIZE: 70%; - FONT-WEIGHT: bold; - MARGIN-BOTTOM: 0px; - MARGIN-TOP: 15px; - PADDING-BOTTOM: 0px -} -UL -{ - COLOR: #000000; - FONT-SIZE: 70%; - LIST-STYLE: square; - MARGIN-BOTTOM: 0pt; - MARGIN-TOP: 0pt -} -OL -{ - COLOR: #000000; - FONT-SIZE: 70%; - LIST-STYLE: square; - MARGIN-BOTTOM: 0pt; - MARGIN-TOP: 0pt -} -LI -{ - LIST-STYLE: square; - MARGIN-LEFT: 0px -} -.expandable -{ - CURSOR: hand -} -.expanded -{ - color: black -} -.collapsed -{ - DISPLAY: none -} -.foot -{ -BACKGROUND-COLOR: #ffffff; -BORDER-BOTTOM: #cecf9c 1px solid; -BORDER-TOP: #cecf9c 2px solid -} -.settings -{ -MARGIN-LEFT: 25PX; -} -.help -{ -TEXT-ALIGN: right; -margin-right: 10px; -} diff --git a/MessageAutoDispose/MessageAutoDispose/_UpgradeReport_Files/UpgradeReport.xslt b/MessageAutoDispose/MessageAutoDispose/_UpgradeReport_Files/UpgradeReport.xslt deleted file mode 100644 index 93ac0765..00000000 --- a/MessageAutoDispose/MessageAutoDispose/_UpgradeReport_Files/UpgradeReport.xslt +++ /dev/null @@ -1,232 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- 解决方案: - 项目: - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - src - - - - - - - - - - - - -
文件名状态错误警告
- javascript:document.images[''].click()src - - - - 已转换 - - - - 已转换 - -
- - 个文件 - - - 1 个文件 - - - 已转换:
- 未转换: -
-
-
- - - - : - - - - - - - - - 转换报告 - <xsl:if test="Properties/Property[@Name='LogNumber']"> - <xsl:value-of select="Properties/Property[@Name='LogNumber']/@Value"/> - </xsl:if> - - - - -

转换报告 -

- -

- 转换时间:
-

- - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - -
- 转换设置 -

- - -
-
diff --git a/MessageAutoDispose/MessageAutoDispose/_UpgradeReport_Files/UpgradeReport_Minus.gif b/MessageAutoDispose/MessageAutoDispose/_UpgradeReport_Files/UpgradeReport_Minus.gif deleted file mode 100644 index 17751cb2..00000000 Binary files a/MessageAutoDispose/MessageAutoDispose/_UpgradeReport_Files/UpgradeReport_Minus.gif and /dev/null differ diff --git a/MessageAutoDispose/MessageAutoDispose/_UpgradeReport_Files/UpgradeReport_Plus.gif b/MessageAutoDispose/MessageAutoDispose/_UpgradeReport_Files/UpgradeReport_Plus.gif deleted file mode 100644 index f6009ca3..00000000 Binary files a/MessageAutoDispose/MessageAutoDispose/_UpgradeReport_Files/UpgradeReport_Plus.gif and /dev/null differ diff --git a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.sln b/MessageProduce/MessageProduce/MessageProduce.sln similarity index 52% rename from MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.sln rename to MessageProduce/MessageProduce/MessageProduce.sln index a07baa99..68dedaf6 100644 --- a/MessageAutoDispose/MessageAutoDispose/MessageAutoDispose.sln +++ b/MessageProduce/MessageProduce/MessageProduce.sln @@ -1,20 +1,20 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MessageAutoDispose", "MessageAutoDispose\MessageAutoDispose.vcxproj", "{EBCD1CB5-5BDA-4668-AF5D-68C313510D89}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {EBCD1CB5-5BDA-4668-AF5D-68C313510D89}.Debug|Win32.ActiveCfg = Debug|Win32 - {EBCD1CB5-5BDA-4668-AF5D-68C313510D89}.Debug|Win32.Build.0 = Debug|Win32 - {EBCD1CB5-5BDA-4668-AF5D-68C313510D89}.Release|Win32.ActiveCfg = Release|Win32 - {EBCD1CB5-5BDA-4668-AF5D-68C313510D89}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MessageProduce", "MessageProduce\MessageProduce.vcxproj", "{8A6DBD27-1BDF-4B2E-A935-9A5652D0C25E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8A6DBD27-1BDF-4B2E-A935-9A5652D0C25E}.Debug|Win32.ActiveCfg = Debug|Win32 + {8A6DBD27-1BDF-4B2E-A935-9A5652D0C25E}.Debug|Win32.Build.0 = Debug|Win32 + {8A6DBD27-1BDF-4B2E-A935-9A5652D0C25E}.Release|Win32.ActiveCfg = Release|Win32 + {8A6DBD27-1BDF-4B2E-A935-9A5652D0C25E}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/MessageProduce/MessageProduce/MessageProduce/Dispose.hpp b/MessageProduce/MessageProduce/MessageProduce/Dispose.hpp new file mode 100644 index 00000000..a55994e2 --- /dev/null +++ b/MessageProduce/MessageProduce/MessageProduce/Dispose.hpp @@ -0,0 +1,353 @@ +#ifndef VNOC_PRODUCE_DISPOSE +#define VNOC_PRODUCE_DISPOSE + +#include "../../../NMessage/ParserMessageXML.h" +#include "MessageFile.h" +#include +#include + +#define MESSAGE_TAMPLATE_NAME_TAG "?Name" +#define MESSAGE_TAMPLATE_ID_TAG "?Id" +#define MESSAGE_TAMPLATE_REGISTERPORT_TAG "?RegisterPort" +#define MESSAGE_TAMPLATE_REGISTERPORT "RegisterPort" +#define MESSAGE_TAMPLATE_PARAM_TAG_SET "?SetParam" +#define MESSAGE_TAMPLATE_PARAM_TAG_GET "?GetParam" + +using namespace VNOC::Message::Define; + +namespace VNOC +{ +namespace Message +{ + +void ConvertTypeToStr(int IdType, std::string& strType) +{ + switch (IdType) + { + case VNOC::Message::MsgDataType_String: + strType = "std::string"; + break; + case VNOC::Message::MsgDataType_Uint8: + strType = "uint8"; + break; + case VNOC::Message::MsgDataType_Uint16: + strType = "uint16"; + break; + case VNOC::Message::MsgDataType_Uint32: + strType = "uint32"; + break; + default: + strType = "void"; + } +} + +void ConvertTypeToMsgDataValue(int IdType, std::string& strType) +{ + switch (IdType) + { + case VNOC::Message::MsgDataType_String: + strType = "StringData"; + break; + case VNOC::Message::MsgDataType_Uint8: + strType = "NumData"; + break; + case VNOC::Message::MsgDataType_Uint16: + strType = "NumData"; + break; + case VNOC::Message::MsgDataType_Uint32: + strType = "NumData"; + break; + default: + strType = "void"; + } +} + +void ConvertToStyle(int IdType, std::string& strType) +{ + switch (IdType) + { + case VNOC::Message::MsgDataType_String: + strType = "ToStr"; + break; + case VNOC::Message::MsgDataType_Uint8: + strType = "ToUInt8"; + break; + case VNOC::Message::MsgDataType_Uint16: + strType = "ToUInt16"; + break; + case VNOC::Message::MsgDataType_Uint32: + strType = "ToUInt32"; + break; + default: + strType = "void"; + } +} + +void ConvertTypeToIdName(int IdType, std::string& strType) +{ + switch (IdType) + { + case VNOC::Message::MsgDataType_String: + strType = "MsgDataType_String"; + break; + case VNOC::Message::MsgDataType_Uint8: + strType = "MsgDataType_Uint8"; + break; + case VNOC::Message::MsgDataType_Uint16: + strType = "MsgDataType_Uint16"; + break; + case VNOC::Message::MsgDataType_Uint32: + strType = "MsgDataType_Uint32"; + break; + default: + strType = "0"; + } +} + +void ConvertMTypeToIdName(int IdType, std::string& strType) +{ + switch (IdType) + { + case VNOC::Message::MsgDataMType_List: + strType = "MsgDataMType_List"; + break; + case VNOC::Message::MsgDataMType_Data: + strType = "MsgDataMType_Data"; + break; + default: + strType = "0"; + } +} + +void DisposeName( + const std::string& strTamplate, + std::string& strSrc, + const std::string& strName, + const std::string& strValue, + bool Isall + ) +{ + int TagPos = strTamplate.find(strName); + if (TagPos == std::string::npos) + { + return; + } + int NameLen = strName.length(); + std::string strFirst, strSecond; + strFirst.resize(TagPos); + strSecond.resize(strTamplate.length() - (TagPos + NameLen)); + std::copy(strTamplate.begin(), strTamplate.begin() + TagPos, strFirst.begin()); + std::copy(strTamplate.begin() + (TagPos + NameLen), strTamplate.end(), strSecond.begin()); + strSrc.clear(); + strSrc += strFirst; + strSrc += strValue; + strSrc += strSecond; + //ݹ滻 + if (Isall == true) + { + DisposeName(strSrc, strSrc, strName, strValue, Isall); + } +} + +void DisposePort( + VNOC::Message::XMLItem* Item, + std::string& strParam + ) +{ + std::string strType, strMType; + ConvertTypeToIdName(Item->GetType(), strType); + ConvertMTypeToIdName(Item->GetMType() , strMType); + strParam += MESSAGE_TAMPLATE_REGISTERPORT; + strParam += "(\""; + strParam += Item->GetName(); + strParam += "\", "; + strParam += strMType; + strParam += ", "; + strParam += strType; + strParam += ");"; +}; + +void DisposeParam( + VNOC::Message::XMLItem* Item, + const std::string& strPattern, + std::string& strParam + ) +{ + strParam = " "; + strParam += "MsgStatus "; + strParam += strPattern; + strParam += Item->GetName(); + strParam += "("; + if (strPattern == "Set") + { + strParam += "const "; + } + std::string strParamType; + if (Item->GetMType() == VNOC::Message::MsgDataMType_Data) + { + ConvertTypeToStr(Item->GetType(), strParamType); + if (strParamType != "std::string") + { + strParam += "Define::" + strParamType; + } + else + { + strParam += strParamType; + } + } + else if (Item->GetMType() == VNOC::Message::MsgDataMType_List) + { + ConvertTypeToStr(Item->GetType(), strParamType); + strParam += "std::vector<"; + if (strParamType != "std::string") + { + strParam += "Define::" + strParamType; + } + else + { + strParam += strParamType; + } + strParam += ">"; + } + strParam += "& "; + strParam += "Value"; + if (strPattern == "Set") + { + strParam += ")"; + } + else + { + strParam += ") const"; + } + strParam += "\n"; + strParam += " "; + strParam += "{"; + strParam += "\n"; + strParam += " "; + if (strPattern == "Get") + { + std::string strParamToStyle; + if (Item->GetMType() == VNOC::Message::MsgDataMType_Data) + { + strParam += "MsgDataValue* pReadValue = NULL;"; + strParam += "\n "; + strParam += "Read("; + } + else if (Item->GetMType() == VNOC::Message::MsgDataMType_List) + { + strParam += "ArrayData* pReadValueArr = NULL;"; + strParam += "\n "; + strParam += "ReadArr("; + } + strParam += "\""; + strParam += Item->GetName(); + strParam += "\""; + strParam += ", "; + if (Item->GetMType() == VNOC::Message::MsgDataMType_Data) + { + ConvertToStyle(Item->GetType(),strParamToStyle); + strParam += "pReadValue);\n"; + strParam += " "; + strParam += "return "; + strParam += "pReadValue->"; + strParam += strParamToStyle; + strParam += "(Value);"; + } + else if (Item->GetMType() == VNOC::Message::MsgDataMType_List) + { + ConvertTypeToStr(Item->GetType(), strParamType); + strParam += "pReadValueArr);\n "; + strParam += "pReadValueArr->GetArr_vec<"; + if (strParamType != "std::string") + { + strParam += "Define::" + strParamType; + } + else + { + strParam += strParamType; + } + strParam += ">(Value);\n"; + strParam += " "; + strParam += "return MsgStatus_Ok;"; + } + } + else if (strPattern == "Set") + { + if (Item->GetMType() == VNOC::Message::MsgDataMType_Data) + { + strParam += "return "; + strParam += "Write("; + } + else if (Item->GetMType() == VNOC::Message::MsgDataMType_List) + { + ConvertTypeToStr(Item->GetType(), strParamType); + strParam += "ArrayData* ValueArr = new ArrayData;"; + strParam += "\n "; + strParam += "ValueArr->Push<"; + if (strParamType != "std::string") + { + strParam += "Define::" + strParamType; + } + else + { + strParam += strParamType; + } + strParam += ">(Value);"; + strParam += "\n "; + strParam += "return "; + strParam += "WriteArr("; + } + strParam += "\""; + strParam += Item->GetName(); + strParam += "\""; + strParam += ", "; + if (Item->GetMType() == VNOC::Message::MsgDataMType_Data) + { + std::string strMsgDataValueType; + strParam += "new "; + ConvertTypeToMsgDataValue(Item->GetType(), strMsgDataValueType); + strParam += strMsgDataValueType; + strParam += "(Value)"; + } + else if (Item->GetMType() == VNOC::Message::MsgDataMType_List) + { + strParam += "ValueArr"; + } + strParam += ");"; + } + strParam += "\n"; + strParam += " "; + strParam += "}"; +} + +bool ProduceFile(const char* lpTargetPath, const std::string& strBuffer) +{ + if (!lpTargetPath) + { + return false; + } + VNOC::Message::CMessageFile file; + if (file.Open(lpTargetPath, VNOC::Message::UNIN_F_ATO_W)) + { + return false; + } + //UTF8 ͷ 0xEFBBBF + uint8 UTF8Head[3] = {0}; + UTF8Head[0] = 0xEF; + UTF8Head[1] = 0xBB; + UTF8Head[2] = 0xBF; + if (file.Write((void*)UTF8Head, 1, 3) < 0) + { + return false; + } + if (file.Write((void*)strBuffer.c_str(), 1, strBuffer.length()) < 0) + { + return false; + } + return true; +} + +} +} + +#endif \ No newline at end of file diff --git a/MessageProduce/MessageProduce/MessageProduce/MessageFile.cpp b/MessageProduce/MessageProduce/MessageProduce/MessageFile.cpp new file mode 100644 index 00000000..f9d384e6 --- /dev/null +++ b/MessageProduce/MessageProduce/MessageProduce/MessageFile.cpp @@ -0,0 +1,131 @@ +#include "MessageFile.h" + +namespace VNOC +{ +namespace Message +{ + +int CMessageFile::Open(const TCHAR* lpszPath, MessageFileType fType) +{ + if (!lpszPath) + { + return -1; + } + if (_tfopen_s(&m_File, lpszPath, returnFileType(fType)) != 0) + { + return -1; + } + if (m_File == NULL) + { + return -1; + } + return 0; +} + +void CMessageFile::Close() +{ + if (m_File != NULL) + { + fclose(m_File); + m_File = NULL; + } +} + +int CMessageFile::Read(void* vbuffe, uint32 nCount, uint32 nSize) +{ + if (!vbuffe || !m_File) + { + return -1; + } + if (fread(vbuffe, nSize, nCount, m_File) == 0) + { + return -1; + } + return 0; +} + +int CMessageFile::Write(void* vbuffe, uint32 nCount, uint32 nSize) +{ + if (!vbuffe || !m_File) + { + return -1; + } + if (fwrite(vbuffe, nSize, nCount, m_File) == 0) + { + return -1; + } + return 0; +} + +void CMessageFile::Seek(int nPos,int nLen) +{ + if (m_File) + { + fseek(m_File, nLen, nPos); + } +} + +long CMessageFile::returnFilePrtPos() +{ + if (!m_File) + { + return -1; + } + return (ftell(m_File)); +} + +TCHAR* CMessageFile::returnFileType(MessageFileType fTpye) +{ + switch (fTpye) + { + case UNIN_F_R: return (_T("r")); + case UNIN_F_W: return (_T("w")); + case UNIN_F_A: return (_T("a")); + case UNIN_F_ATO_A: return (_T("a+")); + case UNIN_F_ATO_R: return (_T("r+")); + case UNIN_F_ATO_W: return (_T("w+")); + } + return 0; +} + +int CMessageFile::returnSeekType(MessageFileType fType) +{ + switch (fType) + { + case UNIN_F_SK_SET: return SEEK_SET; + case UNIN_F_SK_CUR: return SEEK_CUR; + case UNIN_F_SK_END: return SEEK_END; + } + return -1; +} + +FILE* CMessageFile::returnFilePrt() +{ + return m_File; +} + +int CMessageFile::GetFileSize() +{ + if (returnFilePrt() == NULL) + { + return -1; + } + int FileSize = 0; + int OldPos = returnFilePrtPos(); //浱ǰλá + Seek(UNIN_F_SK_END,0); + FileSize = ftell(returnFilePrt()); + Seek(UNIN_F_SK_SET,OldPos); + return FileSize; +} + +CMessageFile::CMessageFile() : m_File(0) +{ +} + +CMessageFile::~CMessageFile() +{ + Close(); +} + +} +} \ No newline at end of file diff --git a/MessageProduce/MessageProduce/MessageProduce/MessageFile.h b/MessageProduce/MessageProduce/MessageProduce/MessageFile.h new file mode 100644 index 00000000..eb993c5c --- /dev/null +++ b/MessageProduce/MessageProduce/MessageProduce/MessageFile.h @@ -0,0 +1,79 @@ +#ifndef VNOC_C_MESSAGE_FILE +#define VNOC_C_MESSAGE_FILE + +#include +#include +#include + +typedef unsigned int uint32; + +namespace VNOC +{ +namespace Message +{ + +typedef enum _MessageFileType +{ + SFILETYPE_NULL, + UNIN_F_R, + UNIN_F_W, + UNIN_F_A, + UNIN_F_ATO_A, + UNIN_F_ATO_R, + UNIN_F_ATO_W, +}MessageFileType; + +typedef enum _MessageFileSeekType +{ + UNIN_F_SK_SET, + UNIN_F_SK_CUR, + UNIN_F_SK_END, +}MessageFileSeekType; + +class CMessageFile +{ +public: + CMessageFile(); + virtual ~CMessageFile();; + + ///> open file + int Open(const TCHAR* lpszPath, MessageFileType fType); + + ///> write file + ///> *first open one file + int Write(void* vbuffe, uint32 nCount, uint32 nSize); + + ///> move file_prt + ///> * UNIN_F_SET + ///> * UNIN_F_CUR + ///> * UNIN_F_END + void Seek(int nPos, int nLen); + + ///> Read file + ///> *first open one file + int Read(void* vbuffe, uint32 nCount, uint32 nSize); + + ///> shut down + ///> close the already open files + void Close(); + + int GetFileSize(); + +protected: + + TCHAR* returnFileType(MessageFileType fTpye); + + int returnSeekType(MessageFileType fType); + + long returnFilePrtPos(); + + FILE* returnFilePrt(); + +private: + FILE* m_File; +}; + +} +} + +#endif \ No newline at end of file diff --git a/MyNetClient/MyNetClient.vcxproj b/MessageProduce/MessageProduce/MessageProduce/MessageProduce.vcxproj similarity index 67% rename from MyNetClient/MyNetClient.vcxproj rename to MessageProduce/MessageProduce/MessageProduce/MessageProduce.vcxproj index a4eadda1..4cfd5f51 100644 --- a/MyNetClient/MyNetClient.vcxproj +++ b/MessageProduce/MessageProduce/MessageProduce/MessageProduce.vcxproj @@ -1,88 +1,81 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {BF0C816A-FB56-47B1-84BB-881F6E320887} - Win32Proj - MyNetClient - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - true - true - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + + {8A6DBD27-1BDF-4B2E-A935-9A5652D0C25E} + MessageProduce + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + + + true + true + true + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MessageProduce/MessageProduce/MessageProduce/MessageProduce.vcxproj.filters b/MessageProduce/MessageProduce/MessageProduce/MessageProduce.vcxproj.filters new file mode 100644 index 00000000..217c7c3a --- /dev/null +++ b/MessageProduce/MessageProduce/MessageProduce/MessageProduce.vcxproj.filters @@ -0,0 +1,66 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {17c480fe-b060-471c-825c-f59cdf6ac549} + + + + + 源文件 + + + 头文件 + + + 头文件\TinyXml + + + 头文件\TinyXml + + + 头文件\TinyXml + + + 头文件\TinyXml + + + 头文件 + + + 头文件 + + + + + 头文件 + + + 头文件 + + + 头文件\TinyXml + + + 头文件\TinyXml + + + 头文件 + + + 头文件 + + + \ No newline at end of file diff --git a/MessageProduce/MessageProduce/MessageProduce/NMsgTamplate.msg b/MessageProduce/MessageProduce/MessageProduce/NMsgTamplate.msg new file mode 100644 index 00000000..9adabace --- /dev/null +++ b/MessageProduce/MessageProduce/MessageProduce/NMsgTamplate.msg @@ -0,0 +1,40 @@ +#ifndef VNOC_C_MESSAGE_?Name +#define VNOC_C_MESSAGE_?Name +#include "MessageDef.h" +#include "CMessage.h" +#include "MsgDataValue/StringData.h" +#include "MsgDataValue/NumData.hpp" + +///> Generate by MessageProduse. DO NOT EDIT! + +namespace VNOC +{ +namespace Message +{ + +class ?Name : public CMessage +{ +public: + ?Name() + { + ?RegisterPort + InitializeMessage(?Id); + } + + ?Name(const CMessage& Msg) + { + ?RegisterPort + CMessage::Copy(Msg, ?Id); + } + + virtual ~?Name(){} + +?SetParam + +?GetParam +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/MessageProduce/MessageProduce/MessageProduce/main.cpp b/MessageProduce/MessageProduce/MessageProduce/main.cpp new file mode 100644 index 00000000..36dbeb50 --- /dev/null +++ b/MessageProduce/MessageProduce/MessageProduce/main.cpp @@ -0,0 +1,223 @@ +#include +#include "Dispose.hpp" + +#define MAX_ENUM_LEN 46 + +bool DisposeMessage( + const char* lpszXMLPtah, + const char* lpTargetPath, + const char* lpszTamplatePath); + +int main(int argc, char **argv) +{ + int oCommand = 0; + char* lpszTamplatePath = NULL; + if (argc > 0) + { + if ((argv[1][0] == '-') && (argv[1][1] == 'h')) + { + std::cout<<">>>>>>>>>> command [-p] pathXml targetpath"<>>>>>>>>> Path Err"< vecUnion; + std::vector vecUnionId; + char* lpszTamplate = new char[file.GetFileSize() + 1]; + memset(lpszTamplate, 0, file.GetFileSize() + 1); + file.Read(lpszTamplate, 1, file.GetFileSize()); + strTamplate = lpszTamplate; + if (VNOC::Message::ParserMessageXML::Instance().LoadFile(lpszXMLPtah) == VNOC::Message::MsgStatus_Ok) + { + for (auto Itr = VNOC::Message::ParserMessageXML::Instance().ObjectBegin(); + Itr != VNOC::Message::ParserMessageXML::Instance().ObjectEnd(); + Itr++) + { + std::string strParamPort; + std::string strGetParam, strSetParam; + VNOC::Message::XMLObject* obj = &(Itr->second); + std::string strSrc; + bool TopLine = false; + VNOC::Message::DisposeName(strTamplate, strSrc, MESSAGE_TAMPLATE_NAME_TAG, Itr->second.GetName(), true); + VNOC::Message::DisposeName(strSrc, strSrc, MESSAGE_TAMPLATE_ID_TAG, Itr->second.GetName() + ("_Id"), true); + for (auto ItrItem = obj->ParamBegin(); ItrItem != obj->ParamEnd(); ItrItem++) + { + std::string strTmp; + VNOC::Message::DisposePort(&ItrItem->second, strTmp); + if (TopLine != false) + { + strParamPort += "\n"; + strParamPort += "\n"; + strParamPort += " "; + } + strParamPort += strTmp; + VNOC::Message::DisposeParam(&ItrItem->second, "Get", strTmp); + if (TopLine != false) + { + strGetParam += "\n"; + strGetParam += "\n"; + } + strGetParam += strTmp; + VNOC::Message::DisposeParam(&ItrItem->second, "Set", strTmp); + if (TopLine != false) + { + strSetParam += "\n"; + strSetParam += "\n"; + } + strSetParam += strTmp; + TopLine = true; + } + strParamPort += "\n"; + VNOC::Message::DisposeName(strSrc, strSrc, MESSAGE_TAMPLATE_REGISTERPORT_TAG, strParamPort, true); + VNOC::Message::DisposeName(strSrc, strSrc, MESSAGE_TAMPLATE_PARAM_TAG_SET, strSetParam, false); + VNOC::Message::DisposeName(strSrc, strSrc, MESSAGE_TAMPLATE_PARAM_TAG_GET, strGetParam, false); + std::string strTargetPath = lpTargetPath; + if (!strTargetPath.empty()) + { + strTargetPath += "/"; + strTargetPath += obj->GetName(); + strTargetPath += ".h"; + vecUnion.push_back(obj->GetName()); + vecUnionId.push_back(obj->GetId()); + if (VNOC::Message::ProduceFile(strTargetPath.c_str(), strSrc)) + { + std::cout<<">>>>>>>>>> Produse -------> "<GetName()<>>>>>>>>> Produse -------> MessageUnion.h"<>>>>>>>>> Produse -------> MessageUnionDef.h"<>>>>>>>>> Produse -------> MessageUnionFunDef.h"< - -namespace VNOC_CLIENT{ - - enum CONNECT_TYPE - { - CLIENT_TO_CLIENT, - CLIENT_TO_SERVER, - }; - -#define WM_NETMSG WM_USER+1 -#define VNOC_SERVER_PORT 9999 -#define VNOC_SERVER_ADDR "111.111.111.111" - - typedef int ConnectType; - - class CClientConnection - { - public: - CClientConnection(); - CClientConnection(HWND hwnd); - ~CClientConnection(void); - - void Create(/*int ConnectType = CLIENT_TO_SERVER,*/ const char* addr = VNOC_SERVER_ADDR, - int port = VNOC_SERVER_PORT , - long lEvent = FD_READ); - int Connect(); - - SOCKET GetSocket(); - ConnectType GetConnType(); - sockaddr_in GetAddrOfSockAddr(); - char* GetAddrOfString(); - - void ReleaseSocket(); - - private: - long m_lEvent; - bool m_bConnected; - HWND m_hwnd; - ConnectType m_nConnectType; - sockaddr_in m_SockAddr; - SOCKET m_sSocket; - }; - -}; \ No newline at end of file diff --git a/MyNetClient/MsgDef.h b/MyNetClient/MsgDef.h deleted file mode 100644 index e950a525..00000000 --- a/MyNetClient/MsgDef.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -struct MSG_GENERIC -{ - DWORD dwType; //Ϣ - int nLen; //Ϣȣְʱ -}; \ No newline at end of file diff --git a/MyNetClient/MyNetClient.vcxproj.filters b/MyNetClient/MyNetClient.vcxproj.filters deleted file mode 100644 index f36f77e4..00000000 --- a/MyNetClient/MyNetClient.vcxproj.filters +++ /dev/null @@ -1,36 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - 头文件 - - - 头文件 - - - - - 源文件 - - - 源文件 - - - 源文件 - - - \ No newline at end of file diff --git a/MyNetClient/MyNetClient.vcxproj.user b/MyNetClient/MyNetClient.vcxproj.user deleted file mode 100644 index 695b5c78..00000000 --- a/MyNetClient/MyNetClient.vcxproj.user +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/MyNetClient/NetClient.cpp b/MyNetClient/NetClient.cpp deleted file mode 100644 index 9e89dc7e..00000000 --- a/MyNetClient/NetClient.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "NetClient.h" - -namespace VNOC_CLIENT{ - - -CNetClient::~CNetClient(void) -{ -} - -int CNetClient::InitClient() -{ - return WSAStartup(MAKEWORD(2,2),&m_wsaData); -} - -int CNetClient::Send( CClientConnection connect,const VOID* pbuf, int size ) -{ - int nSentSum = 0;//ֽܷ - int nSent = 0;//ǰֽ - char* p; - p = (char*)malloc(size); - memcpy(p,pbuf,size); - - if (connect.GetConnType() == CLIENT_TO_SERVER) - { - while(nSentSum < size) - { - nSent = ::send(connect.GetSocket(),p + nSentSum, size-nSentSum, 0); - if(nSent < 0) - { - return nSent; - } - else - { - nSentSum += nSent; - } - } - } - else - { - sockaddr_in add = connect.GetAddrOfSockAddr(); - while(nSentSum < size) - { - nSent = ::sendto(connect.GetSocket(),p + nSentSum, size-nSentSum,0,(sockaddr*)&(add),sizeof(add)); - if(nSent < 0) - { - return nSent; - } - else - { - nSentSum += nSent; - } - } - } - - return nSentSum; -} - -LRESULT CNetClient::NetMsgProc( HWND hwnd, UINT uMsg, WPARAM wParam/*׽*/, LPARAM lParam ) -{ - - return 0; -} - -CClientConnection* CNetClient::CreateConn( int nPort, const char* szAddr, const char* szId, long lEvent ) -{ - CClientConnection* pConn = new CClientConnection(m_hwnd); - pConn->Create(szAddr,nPort,lEvent); - - std::pair pair = std::make_pair(pConn,szId); - m_ConnMap.insert(pair); - - return pConn; -} - - - -}//namespace VNOC_CLIENT \ No newline at end of file diff --git a/MyNetClient/NetClient.h b/MyNetClient/NetClient.h deleted file mode 100644 index 3d4275e6..00000000 --- a/MyNetClient/NetClient.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************** - created: 2012/01/08 - created: 8:1:2012 6:23 - filename: D:\vnoc\trunk\VNOC\MyNetClient\NetClient.h - file path: D:\vnoc\trunk\VNOC\MyNetClient - file base: NetClient - file ext: h - author: - - purpose: ͻ࣬ӷ(ͻ) -*********************************************************************/ - -#pragma once -#include -#pragma comment(lib,"WS2_32") -#include -#include - -#include "ClientConnection.h" - -namespace VNOC_CLIENT{ - -class CNetClient -{ -public: - CNetClient(); - explicit CNetClient( HWND hwnd ) :m_hwnd(hwnd){}; - ~CNetClient(); - - int InitClient(); - LRESULT NetMsgProc(HWND hwnd, UINT uMsg, WPARAM wParam/*׽*/, LPARAM lParam); - CClientConnection* CreateConn(int nPort, const char* szAddr, const char* szId, long lEvent); - - int Send( CClientConnection connect,const VOID* pbuf, int nsize ); - -private: - HWND m_hwnd; - WSADATA m_wsaData; - std::map m_ConnMap; -}; - -}; \ No newline at end of file diff --git a/MyNetClient/NetClientTest.cpp b/MyNetClient/NetClientTest.cpp deleted file mode 100644 index b032d857..00000000 --- a/MyNetClient/NetClientTest.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "ClientConnection.h" -#include "NetClient.h" - -int main(int argc, TCHAR* argv[]) -{ - VNOC_CLIENT::CClientConnection connection; - connection.Create(); - return 0; -} diff --git a/NMessage/BufferMessage.cpp b/NMessage/BufferMessage.cpp new file mode 100644 index 00000000..0dce8c2e --- /dev/null +++ b/NMessage/BufferMessage.cpp @@ -0,0 +1,123 @@ +#include "BufferMessage.h" +#include + +namespace VNOC +{ +namespace Message +{ + +using namespace Define; + +CBufferMessage::CBufferMessage() + : m_attachtag(false) + , m_Size(0) + , m_pBuffer(NULL) +{ +} + +CBufferMessage::~CBufferMessage() +{ + _Free(); +} + +uint8* CBufferMessage::Alloc(IN uint32 nSize) +{ + void* ptmp = realloc(m_pBuffer, nSize); + if (ptmp != NULL) + { + m_pBuffer = (uint8*)ptmp; + m_Size = nSize; + } + return m_pBuffer; +} + +uint8* CBufferMessage::GetBuffer() const +{ + return m_pBuffer; +} + +uint32 CBufferMessage::GetSize() const +{ + return m_Size; +} + +const CBufferMessage& CBufferMessage::Copy( + IN const void* Src, + IN uint32 nSize + ) +{ + if (nSize > m_Size) + { + Alloc(nSize); + m_Size = nSize; + } + SetValue(0); + if (m_pBuffer != NULL) + { + ::memcpy(m_pBuffer, Src, nSize); + } + return *this; +} + +const CBufferMessage& CBufferMessage::Copy(IN const CBufferMessage& Src) +{ + CBufferMessage::Copy(Src.GetBuffer(), Src.GetSize()); + return *this; +} + +void CBufferMessage::Attach(IN void* lpBuff, IN uint32 nSize) +{ + if ((lpBuff != NULL) || nSize > 0) + { + _Free(); + m_attachtag = true; + m_pBuffer = (uint8*)lpBuff; + m_Size = nSize; + } +} + +void CBufferMessage::_Free() +{ + if (m_attachtag) + { + m_attachtag = false; + m_pBuffer = NULL; + m_Size = 0; + } + if (m_pBuffer != NULL) + { + ::free(m_pBuffer); + m_pBuffer = NULL; + m_Size = 0; + } +} + +void CBufferMessage::Detach() +{ + _Free(); +} + +void CBufferMessage::Clear() +{ + _Free(); +} + +void CBufferMessage::SetValue(IN uint8 Value) +{ + if (m_pBuffer != NULL) + { + ::memset(m_pBuffer, Value, m_Size); + } +} + +bool CBufferMessage::Empty() +{ + if (!m_pBuffer && !m_attachtag) + { + return true; + } + return false; +} + +}// namespace Message +}// namespace VNOC \ No newline at end of file diff --git a/NMessage/BufferMessage.h b/NMessage/BufferMessage.h new file mode 100644 index 00000000..b103846a --- /dev/null +++ b/NMessage/BufferMessage.h @@ -0,0 +1,50 @@ +#ifndef VNOC_C_MESSAGE_BUFFER +#define VNOC_C_MESSAGE_BUFFER + +#include "MessageDef.h" + +namespace VNOC +{ +namespace Message +{ + +class CBufferMessage +{ +public: + CBufferMessage(); + virtual ~CBufferMessage(); + + Define::uint8* Alloc(IN Define::uint32 nSize); + + Define::uint8* GetBuffer() const; + + Define::uint32 GetSize() const; + + const CBufferMessage& Copy(IN const void* Src, Define::uint32 nSize); + + const CBufferMessage& Copy(IN const CBufferMessage& Src); + + void SetValue(Define::uint8 Value); + + void Attach(IN void* lpBuff, IN Define::uint32 nSize); + + void Detach(); + + void Clear(); + + bool Empty(); + +private: + void _Free(); + +private: + DISALLOW_COPY_AND_ASSIGN(CBufferMessage); + Define::uint32 m_Size; + Define::uint8* m_pBuffer; + bool m_attachtag; +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/CMessage.cpp b/NMessage/CMessage.cpp new file mode 100644 index 00000000..dc290b16 --- /dev/null +++ b/NMessage/CMessage.cpp @@ -0,0 +1,288 @@ +#include "CMessage.h" + +namespace VNOC +{ +namespace Message +{ + +using namespace VNOC::Message::Define; + +MsgStatus CMessage::Read( + IN const MsgDataName& name, + OUT MsgDataValue*& value + ) const +{ + if (IsRegister(name)) + { + auto tmpItr = m_mapMsgData.find(name); + if (tmpItr != m_mapMsgData.end()) + { + value = tmpItr->second; + return MsgStatus_Ok; + } + } + return MsgStatus_Err; +} + +MsgStatus CMessage::ReadArr( + IN const MsgDataName& name, + OUT ArrayData*& value + ) const +{ + if (IsRegister(name)) + { + auto tmpItr = m_mapMsgDataArr.find(name); + if (tmpItr != m_mapMsgDataArr.end()) + { + value = tmpItr->second; + return MsgStatus_Ok; + } + } + return MsgStatus_Err; +} + +MsgStatus CMessage::Write( + IN const MsgDataName& name, + IN MsgDataValue* pValue + ) +{ + if (IsRegister(name)) + { + auto itFind = m_mapMsgData.find(name); + if (itFind == m_mapMsgData.end()) + { + return MsgStatus_Err; + } + delete itFind->second; + itFind->second = pValue; + return MsgStatus_Ok; + } + return MsgStatus_Err; +} + +MsgStatus CMessage::WriteArr( + IN const MsgDataName& name, + IN ArrayData* pValue + ) +{ + if (IsRegister(name)) + { + auto itFind = m_mapMsgDataArr.find(name); + if (itFind == m_mapMsgDataArr.end()) + { + return MsgStatus_Err; + } + delete itFind->second; + itFind->second = pValue; + return MsgStatus_Ok; + } + return MsgStatus_Err; +} + +CMessage::CMessage() : m_MsgId(0) +{ + +} + +CMessage::CMessage( int nId ) +{ + m_MsgId = nId; + _InitDataMap(); +} + +void CMessage::InitializeMessage( int nId ) +{ + m_MsgId = nId; + _InitDataMap(); +} + +bool CMessage::IsRegister(const MsgDataName& name) const +{ + auto tmpItr = m_mapPort.find(name); + if (tmpItr != m_mapPort.end()) + { + return true; + } + return false; +} + +void CMessage::RegisterPort( + const Define::MsgDataName& strName, + const Define::MsgMType& strMType, + const Define::MsgType& strType + ) +{ + m_mapPort[strName] = std::make_pair(strMType, strType); +} + +std::map >::const_iterator CMessage::PortBegin() const +{ + return m_mapPort.begin(); +} + +std::map >::const_iterator CMessage::PortEnd() const +{ + return m_mapPort.end(); +} + +CMessage::~CMessage() +{ + _ReleaseMap(); +} + +bool CMessage::IsValid() const +{ + if (m_MsgId == 0) + { + return false; + } + return true; +} + +void CMessage::_InitDataMap() +{ + if (!m_mapPort.empty()) + { + auto it = m_mapPort.begin(); + for (; it != m_mapPort.end(); ++it) + { + if (it->second.first == MsgDataMType_Data) + { + m_mapMsgData[it->first] = NULL; + } + if (it->second.first == MsgDataMType_List) + { + m_mapMsgDataArr[it->first] = NULL; + } + } + } +} + +void CMessage::_ReleaseMap() +{ + auto itData = m_mapMsgData.begin(); + for (; itData != m_mapMsgData.end(); ++ itData) + { + delete itData->second; + } + m_mapMsgData.clear(); + auto itList = m_mapMsgDataArr.begin(); + for (; itList != m_mapMsgDataArr.end(); ++ itList) + { + delete itList->second; + } + m_mapMsgDataArr.clear(); +} + +int CMessage::MsgId() const +{ + return m_MsgId; +} + +CMessage& CMessage::CopyPort(const CMessage& lhs) +{ + m_MsgId = lhs.MsgId(); + for (auto It = lhs.PortBegin(); It != lhs.PortEnd(); It++) + { + m_mapPort[It->first] = It->second; + } + m_mapMsgData.clear(); + auto it = m_mapPort.begin(); + for (; it != m_mapPort.end(); ++it) + { + if (it->second.first == MsgDataMType_Data) + { + m_mapMsgData[it->first] = NULL; + } + if (it->second.first == MsgDataMType_List) + { + m_mapMsgDataArr[it->first] = NULL; + } + } + return (*this); +} + +CMessage& CMessage::Copy(const CMessage& lhs, int MessageId /* = 0 */) +{ + if (MessageId = 0) + { + InitializeMessage(lhs.MsgId()); + } + else + { + InitializeMessage(MessageId); + } + MsgDataValue* lpReadValue = NULL; + ArrayData* lpReadValueArr = NULL; + m_mapMsgData.clear(); + m_mapMsgDataArr.clear(); + m_mapPort.clear(); + CopyPort(lhs); + for (auto It = lhs.PortBegin(); It != lhs.PortEnd(); It++) + { + switch (It->second.first) + { + case MsgDataMType_Data: + lhs.Read(It->first, lpReadValue); + switch (It->second.second) + { + case MsgDataType_String: + if (lpReadValue != NULL) + { + std::string strValute; + lpReadValue->ToStr(strValute); + Write(It->first, new StringData(strValute)); + } + break; + case MsgDataType_Uint8: + if (lpReadValue != NULL) + { + uint8 NumValute = 0; + lpReadValue->ToUInt8(NumValute); + Write(It->first, new NumData(NumValute)); + } + break; + case MsgDataType_Uint16: + if (lpReadValue != NULL) + { + uint16 NumValute = 0; + lpReadValue->ToUInt16(NumValute); + Write(It->first, new NumData(NumValute)); + } + break; + case MsgDataType_Uint32: + if (lpReadValue != NULL) + { + uint32 NumValute = 0; + lpReadValue->ToUInt32(NumValute); + Write(It->first, new NumData(NumValute)); + } + break; + } + break; + case MsgDataMType_List: + lhs.ReadArr(It->first, lpReadValueArr); + if (lpReadValueArr != NULL) + { + ArrayData* lpWriteArr = new ArrayData; + for (auto ArrIt = lpReadValueArr->Begin(); + ArrIt != lpReadValueArr->End(); + ArrIt++ + ) + { + lpWriteArr->Push((*ArrIt)); + } + WriteArr(It->first, lpWriteArr); + } + break; + } + } + return (*this); +} + +}// namespace Message +}// namespace VNOC diff --git a/NMessage/CMessage.h b/NMessage/CMessage.h new file mode 100644 index 00000000..a576dc1d --- /dev/null +++ b/NMessage/CMessage.h @@ -0,0 +1,76 @@ +#ifndef VNOC_C_MESSAGE_BASE +#define VNOC_C_MESSAGE_BASE + +#include "IBaseMessage.h" +#include +#include "MessageDef.h" + +namespace VNOC +{ +namespace Message +{ + +class CMessage : public IMessage +{ +public: + CMessage(int nId); + virtual ~CMessage(); + + virtual MsgStatus Read( + IN const Define::MsgDataName& name, + OUT MsgDataValue*& value) const; + + virtual MsgStatus ReadArr( + IN const Define::MsgDataName& name, + OUT ArrayData*& value) const; + + virtual int MsgId() const; + + virtual MsgStatus Write( + IN const Define::MsgDataName& name, + IN MsgDataValue* pValue); + + virtual MsgStatus WriteArr( + IN const Define::MsgDataName& name, + IN ArrayData* pValue); + + virtual bool IsValid() const; + + CMessage& Copy(const CMessage& lhs, int MessageId = 0); + + CMessage& CopyPort(const CMessage& lhs); + + std::map >::const_iterator PortBegin() const; + + std::map >::const_iterator PortEnd() const; + +protected: + CMessage(); + + void InitializeMessage(int nId); + + bool IsRegister(const Define::MsgDataName& name) const; + + virtual void RegisterPort( + const Define::MsgDataName& strName, + const Define::MsgMType& strMType, + const Define::MsgType& strType); + +private: + void _InitDataMap(); + void _ReleaseMap(); + + std::map > m_mapPort; + std::map m_mapMsgData; + std::map m_mapMsgDataArr; + Define::uint32 m_MsgId; +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/IBaseMessage.h b/NMessage/IBaseMessage.h new file mode 100644 index 00000000..d2057b34 --- /dev/null +++ b/NMessage/IBaseMessage.h @@ -0,0 +1,45 @@ +#ifndef VNOC_I_MESSAGE_BASE +#define VNOC_I_MESSAGE_BASE + +#include "IWriteMessage.h" +#include "IReadMessage.h" + +namespace VNOC +{ +namespace Message +{ + +class IMessage + : public IReadMessage + , public IWriteMessage +{ +public: + IMessage(){} + virtual ~IMessage(){} + +public: + virtual MsgStatus Read( + IN const Define::MsgDataName& name, + OUT MsgDataValue*& value) const = 0; + + virtual MsgStatus ReadArr( + IN const Define::MsgDataName& name, + OUT ArrayData*& value) const = 0; + + virtual int MsgId() const = 0; + + virtual MsgStatus Write( + IN const Define::MsgDataName& name, + IN MsgDataValue* pValue) = 0; + + virtual MsgStatus WriteArr( + IN const Define::MsgDataName& name, + IN ArrayData* pValue) = 0; + + virtual bool IsValid() const = 0; +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/IReadMessage.h b/NMessage/IReadMessage.h new file mode 100644 index 00000000..4c7fc395 --- /dev/null +++ b/NMessage/IReadMessage.h @@ -0,0 +1,36 @@ +#ifndef VNOC_I_MESSAGE_READ +#define VNOC_I_MESSAGE_READ + +#include "MessageDef.h" +#include "MsgDataValue/MsgDataValue.h" +#include "MsgDataValue/ArrayData.h" + +namespace VNOC +{ +namespace Message +{ + +class ArrayData; + +class IReadMessage +{ +public: + IReadMessage(){} + virtual ~IReadMessage(){} + +public: + virtual MsgStatus Read( + IN const Define::MsgDataName& name, + OUT MsgDataValue*& value) const = 0; + + virtual MsgStatus ReadArr( + IN const Define::MsgDataName& name, + OUT ArrayData*& value) const = 0; + + virtual int MsgId() const = 0; +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/IWriteMessage.h b/NMessage/IWriteMessage.h new file mode 100644 index 00000000..1a8f7c07 --- /dev/null +++ b/NMessage/IWriteMessage.h @@ -0,0 +1,34 @@ +#ifndef VNOC_I_MESSAGE_WRITE +#define VNOC_I_MESSAGE_WRITE + +#include "MessageDef.h" +#include "MsgDataValue/MsgDataValue.h" +#include "MsgDataValue/ArrayData.h" + +namespace VNOC +{ +namespace Message +{ + +class ArrayData; + +class IWriteMessage +{ +public: + IWriteMessage(){} + virtual ~IWriteMessage(){} + +public: + virtual MsgStatus Write( + IN const Define::MsgDataName& name, + IN MsgDataValue* pValue) = 0; + + virtual MsgStatus WriteArr( + IN const Define::MsgDataName& name, + IN ArrayData* pValue) = 0; +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MSG_AnswerClassInfo.h b/NMessage/MSG_AnswerClassInfo.h new file mode 100644 index 00000000..15088df8 --- /dev/null +++ b/NMessage/MSG_AnswerClassInfo.h @@ -0,0 +1,181 @@ +#ifndef VNOC_C_MESSAGE_MSG_AnswerClassInfo +#define VNOC_C_MESSAGE_MSG_AnswerClassInfo +#include "MessageDef.h" +#include "CMessage.h" +#include "MsgDataValue/StringData.h" +#include "MsgDataValue/NumData.hpp" + +///> Generate by MessageProduse. DO NOT EDIT! + +namespace VNOC +{ +namespace Message +{ + +class MSG_AnswerClassInfo : public CMessage +{ +public: + MSG_AnswerClassInfo() + { + RegisterPort("RoomID", MsgDataMType_Data, MsgDataType_Uint32); + + RegisterPort("RoomManageId", MsgDataMType_Data, MsgDataType_Uint32); + + RegisterPort("RoomName", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("RoomPassword", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("RoomPeopleListId", MsgDataMType_List, MsgDataType_Uint32); + + RegisterPort("RoomPeopleNumMax", MsgDataMType_Data, MsgDataType_Uint32); + + RegisterPort("RoomRank", MsgDataMType_Data, MsgDataType_Uint32); + + RegisterPort("RoomState", MsgDataMType_Data, MsgDataType_Uint32); + + RegisterPort("RoomType", MsgDataMType_Data, MsgDataType_Uint32); + + InitializeMessage(MSG_AnswerClassInfo_Id); + } + + MSG_AnswerClassInfo(const CMessage& Msg) + { + RegisterPort("RoomID", MsgDataMType_Data, MsgDataType_Uint32); + + RegisterPort("RoomManageId", MsgDataMType_Data, MsgDataType_Uint32); + + RegisterPort("RoomName", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("RoomPassword", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("RoomPeopleListId", MsgDataMType_List, MsgDataType_Uint32); + + RegisterPort("RoomPeopleNumMax", MsgDataMType_Data, MsgDataType_Uint32); + + RegisterPort("RoomRank", MsgDataMType_Data, MsgDataType_Uint32); + + RegisterPort("RoomState", MsgDataMType_Data, MsgDataType_Uint32); + + RegisterPort("RoomType", MsgDataMType_Data, MsgDataType_Uint32); + + CMessage::Copy(Msg, MSG_AnswerClassInfo_Id); + } + + virtual ~MSG_AnswerClassInfo(){} + + MsgStatus SetRoomID(const Define::uint32& Value) + { + return Write("RoomID", new NumData(Value)); + } + + MsgStatus SetRoomManageId(const Define::uint32& Value) + { + return Write("RoomManageId", new NumData(Value)); + } + + MsgStatus SetRoomName(const std::string& Value) + { + return Write("RoomName", new StringData(Value)); + } + + MsgStatus SetRoomPassword(const std::string& Value) + { + return Write("RoomPassword", new StringData(Value)); + } + + MsgStatus SetRoomPeopleListId(const std::vector& Value) + { + ArrayData* ValueArr = new ArrayData; + ValueArr->Push(Value); + return WriteArr("RoomPeopleListId", ValueArr); + } + + MsgStatus SetRoomPeopleNumMax(const Define::uint32& Value) + { + return Write("RoomPeopleNumMax", new NumData(Value)); + } + + MsgStatus SetRoomRank(const Define::uint32& Value) + { + return Write("RoomRank", new NumData(Value)); + } + + MsgStatus SetRoomState(const Define::uint32& Value) + { + return Write("RoomState", new NumData(Value)); + } + + MsgStatus SetRoomType(const Define::uint32& Value) + { + return Write("RoomType", new NumData(Value)); + } + + MsgStatus GetRoomID(Define::uint32& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("RoomID", pReadValue); + return pReadValue->ToUInt32(Value); + } + + MsgStatus GetRoomManageId(Define::uint32& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("RoomManageId", pReadValue); + return pReadValue->ToUInt32(Value); + } + + MsgStatus GetRoomName(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("RoomName", pReadValue); + return pReadValue->ToStr(Value); + } + + MsgStatus GetRoomPassword(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("RoomPassword", pReadValue); + return pReadValue->ToStr(Value); + } + + MsgStatus GetRoomPeopleListId(std::vector& Value) const + { + ArrayData* pReadValueArr = NULL; + ReadArr("RoomPeopleListId", pReadValueArr); + pReadValueArr->GetArr_vec(Value); + return MsgStatus_Ok; + } + + MsgStatus GetRoomPeopleNumMax(Define::uint32& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("RoomPeopleNumMax", pReadValue); + return pReadValue->ToUInt32(Value); + } + + MsgStatus GetRoomRank(Define::uint32& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("RoomRank", pReadValue); + return pReadValue->ToUInt32(Value); + } + + MsgStatus GetRoomState(Define::uint32& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("RoomState", pReadValue); + return pReadValue->ToUInt32(Value); + } + + MsgStatus GetRoomType(Define::uint32& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("RoomType", pReadValue); + return pReadValue->ToUInt32(Value); + } +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MSG_AnswerClassList.h b/NMessage/MSG_AnswerClassList.h new file mode 100644 index 00000000..489d5bc2 --- /dev/null +++ b/NMessage/MSG_AnswerClassList.h @@ -0,0 +1,91 @@ +#ifndef VNOC_C_MESSAGE_MSG_AnswerClassList +#define VNOC_C_MESSAGE_MSG_AnswerClassList +#include "MessageDef.h" +#include "CMessage.h" +#include "MsgDataValue/StringData.h" +#include "MsgDataValue/NumData.hpp" + +///> Generate by MessageProduse. DO NOT EDIT! + +namespace VNOC +{ +namespace Message +{ + +class MSG_AnswerClassList : public CMessage +{ +public: + MSG_AnswerClassList() + { + RegisterPort("RoomIdList", MsgDataMType_List, MsgDataType_Uint32); + + RegisterPort("RoomNameList", MsgDataMType_List, MsgDataType_String); + + RegisterPort("RoomStateList", MsgDataMType_List, MsgDataType_Uint32); + + InitializeMessage(MSG_AnswerClassList_Id); + } + + MSG_AnswerClassList(const CMessage& Msg) + { + RegisterPort("RoomIdList", MsgDataMType_List, MsgDataType_Uint32); + + RegisterPort("RoomNameList", MsgDataMType_List, MsgDataType_String); + + RegisterPort("RoomStateList", MsgDataMType_List, MsgDataType_Uint32); + + CMessage::Copy(Msg, MSG_AnswerClassList_Id); + } + + virtual ~MSG_AnswerClassList(){} + + MsgStatus SetRoomIdList(const std::vector& Value) + { + ArrayData* ValueArr = new ArrayData; + ValueArr->Push(Value); + return WriteArr("RoomIdList", ValueArr); + } + + MsgStatus SetRoomNameList(const std::vector& Value) + { + ArrayData* ValueArr = new ArrayData; + ValueArr->Push(Value); + return WriteArr("RoomNameList", ValueArr); + } + + MsgStatus SetRoomStateList(const std::vector& Value) + { + ArrayData* ValueArr = new ArrayData; + ValueArr->Push(Value); + return WriteArr("RoomStateList", ValueArr); + } + + MsgStatus GetRoomIdList(std::vector& Value) const + { + ArrayData* pReadValueArr = NULL; + ReadArr("RoomIdList", pReadValueArr); + pReadValueArr->GetArr_vec(Value); + return MsgStatus_Ok; + } + + MsgStatus GetRoomNameList(std::vector& Value) const + { + ArrayData* pReadValueArr = NULL; + ReadArr("RoomNameList", pReadValueArr); + pReadValueArr->GetArr_vec(Value); + return MsgStatus_Ok; + } + + MsgStatus GetRoomStateList(std::vector& Value) const + { + ArrayData* pReadValueArr = NULL; + ReadArr("RoomStateList", pReadValueArr); + pReadValueArr->GetArr_vec(Value); + return MsgStatus_Ok; + } +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MSG_AnswerLogin.h b/NMessage/MSG_AnswerLogin.h new file mode 100644 index 00000000..70f80de5 --- /dev/null +++ b/NMessage/MSG_AnswerLogin.h @@ -0,0 +1,82 @@ +#ifndef VNOC_C_MESSAGE_MSG_AnswerLogin +#define VNOC_C_MESSAGE_MSG_AnswerLogin +#include "MessageDef.h" +#include "CMessage.h" +#include "MsgDataValue/StringData.h" +#include "MsgDataValue/NumData.hpp" + +///> Generate by MessageProduse. DO NOT EDIT! + +namespace VNOC +{ +namespace Message +{ + +class MSG_AnswerLogin : public CMessage +{ +public: + MSG_AnswerLogin() + { + RegisterPort("ATLGUID", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("LoginResult", MsgDataMType_Data, MsgDataType_Uint8); + + RegisterPort("Token", MsgDataMType_Data, MsgDataType_Uint32); + + InitializeMessage(MSG_AnswerLogin_Id); + } + + MSG_AnswerLogin(const CMessage& Msg) + { + RegisterPort("ATLGUID", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("LoginResult", MsgDataMType_Data, MsgDataType_Uint8); + + RegisterPort("Token", MsgDataMType_Data, MsgDataType_Uint32); + + CMessage::Copy(Msg, MSG_AnswerLogin_Id); + } + + virtual ~MSG_AnswerLogin(){} + + MsgStatus SetATLGUID(const std::string& Value) + { + return Write("ATLGUID", new StringData(Value)); + } + + MsgStatus SetLoginResult(const Define::uint8& Value) + { + return Write("LoginResult", new NumData(Value)); + } + + MsgStatus SetToken(const Define::uint32& Value) + { + return Write("Token", new NumData(Value)); + } + + MsgStatus GetATLGUID(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("ATLGUID", pReadValue); + return pReadValue->ToStr(Value); + } + + MsgStatus GetLoginResult(Define::uint8& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("LoginResult", pReadValue); + return pReadValue->ToUInt8(Value); + } + + MsgStatus GetToken(Define::uint32& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("Token", pReadValue); + return pReadValue->ToUInt32(Value); + } +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MSG_AnswerProfileSync.h b/NMessage/MSG_AnswerProfileSync.h new file mode 100644 index 00000000..87848712 --- /dev/null +++ b/NMessage/MSG_AnswerProfileSync.h @@ -0,0 +1,50 @@ +#ifndef VNOC_C_MESSAGE_MSG_AnswerProfileSync +#define VNOC_C_MESSAGE_MSG_AnswerProfileSync +#include "MessageDef.h" +#include "CMessage.h" +#include "MsgDataValue/StringData.h" +#include "MsgDataValue/NumData.hpp" + +///> Generate by MessageProduse. DO NOT EDIT! + +namespace VNOC +{ +namespace Message +{ + +class MSG_AnswerProfileSync : public CMessage +{ +public: + MSG_AnswerProfileSync() + { + RegisterPort("MessageSynchro", MsgDataMType_Data, MsgDataType_String); + + InitializeMessage(MSG_AnswerProfileSync_Id); + } + + MSG_AnswerProfileSync(const CMessage& Msg) + { + RegisterPort("MessageSynchro", MsgDataMType_Data, MsgDataType_String); + + CMessage::Copy(Msg, MSG_AnswerProfileSync_Id); + } + + virtual ~MSG_AnswerProfileSync(){} + + MsgStatus SetMessageSynchro(const std::string& Value) + { + return Write("MessageSynchro", new StringData(Value)); + } + + MsgStatus GetMessageSynchro(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("MessageSynchro", pReadValue); + return pReadValue->ToStr(Value); + } +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MSG_AnswerRegister.h b/NMessage/MSG_AnswerRegister.h new file mode 100644 index 00000000..18c8db30 --- /dev/null +++ b/NMessage/MSG_AnswerRegister.h @@ -0,0 +1,50 @@ +#ifndef VNOC_C_MESSAGE_MSG_AnswerRegister +#define VNOC_C_MESSAGE_MSG_AnswerRegister +#include "MessageDef.h" +#include "CMessage.h" +#include "MsgDataValue/StringData.h" +#include "MsgDataValue/NumData.hpp" + +///> Generate by MessageProduse. DO NOT EDIT! + +namespace VNOC +{ +namespace Message +{ + +class MSG_AnswerRegister : public CMessage +{ +public: + MSG_AnswerRegister() + { + RegisterPort("RetTag", MsgDataMType_Data, MsgDataType_Uint32); + + InitializeMessage(MSG_AnswerRegister_Id); + } + + MSG_AnswerRegister(const CMessage& Msg) + { + RegisterPort("RetTag", MsgDataMType_Data, MsgDataType_Uint32); + + CMessage::Copy(Msg, MSG_AnswerRegister_Id); + } + + virtual ~MSG_AnswerRegister(){} + + MsgStatus SetRetTag(const Define::uint32& Value) + { + return Write("RetTag", new NumData(Value)); + } + + MsgStatus GetRetTag(Define::uint32& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("RetTag", pReadValue); + return pReadValue->ToUInt32(Value); + } +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MSG_AnswerVerificationCode.h b/NMessage/MSG_AnswerVerificationCode.h new file mode 100644 index 00000000..f8fca3af --- /dev/null +++ b/NMessage/MSG_AnswerVerificationCode.h @@ -0,0 +1,82 @@ +#ifndef VNOC_C_MESSAGE_MSG_AnswerVerificationCode +#define VNOC_C_MESSAGE_MSG_AnswerVerificationCode +#include "MessageDef.h" +#include "CMessage.h" +#include "MsgDataValue/StringData.h" +#include "MsgDataValue/NumData.hpp" + +///> Generate by MessageProduse. DO NOT EDIT! + +namespace VNOC +{ +namespace Message +{ + +class MSG_AnswerVerificationCode : public CMessage +{ +public: + MSG_AnswerVerificationCode() + { + RegisterPort("Captcha", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("CaptchaType", MsgDataMType_Data, MsgDataType_Uint8); + + RegisterPort("LoginTag", MsgDataMType_Data, MsgDataType_Uint8); + + InitializeMessage(MSG_AnswerVerificationCode_Id); + } + + MSG_AnswerVerificationCode(const CMessage& Msg) + { + RegisterPort("Captcha", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("CaptchaType", MsgDataMType_Data, MsgDataType_Uint8); + + RegisterPort("LoginTag", MsgDataMType_Data, MsgDataType_Uint8); + + CMessage::Copy(Msg, MSG_AnswerVerificationCode_Id); + } + + virtual ~MSG_AnswerVerificationCode(){} + + MsgStatus SetCaptcha(const std::string& Value) + { + return Write("Captcha", new StringData(Value)); + } + + MsgStatus SetCaptchaType(const Define::uint8& Value) + { + return Write("CaptchaType", new NumData(Value)); + } + + MsgStatus SetLoginTag(const Define::uint8& Value) + { + return Write("LoginTag", new NumData(Value)); + } + + MsgStatus GetCaptcha(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("Captcha", pReadValue); + return pReadValue->ToStr(Value); + } + + MsgStatus GetCaptchaType(Define::uint8& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("CaptchaType", pReadValue); + return pReadValue->ToUInt8(Value); + } + + MsgStatus GetLoginTag(Define::uint8& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("LoginTag", pReadValue); + return pReadValue->ToUInt8(Value); + } +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MSG_RequestClassInfo.h b/NMessage/MSG_RequestClassInfo.h new file mode 100644 index 00000000..e1bb4222 --- /dev/null +++ b/NMessage/MSG_RequestClassInfo.h @@ -0,0 +1,50 @@ +#ifndef VNOC_C_MESSAGE_MSG_RequestClassInfo +#define VNOC_C_MESSAGE_MSG_RequestClassInfo +#include "MessageDef.h" +#include "CMessage.h" +#include "MsgDataValue/StringData.h" +#include "MsgDataValue/NumData.hpp" + +///> Generate by MessageProduse. DO NOT EDIT! + +namespace VNOC +{ +namespace Message +{ + +class MSG_RequestClassInfo : public CMessage +{ +public: + MSG_RequestClassInfo() + { + RegisterPort("RoomID", MsgDataMType_Data, MsgDataType_Uint32); + + InitializeMessage(MSG_RequestClassInfo_Id); + } + + MSG_RequestClassInfo(const CMessage& Msg) + { + RegisterPort("RoomID", MsgDataMType_Data, MsgDataType_Uint32); + + CMessage::Copy(Msg, MSG_RequestClassInfo_Id); + } + + virtual ~MSG_RequestClassInfo(){} + + MsgStatus SetRoomID(const Define::uint32& Value) + { + return Write("RoomID", new NumData(Value)); + } + + MsgStatus GetRoomID(Define::uint32& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("RoomID", pReadValue); + return pReadValue->ToUInt32(Value); + } +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MSG_RequestClassList.h b/NMessage/MSG_RequestClassList.h new file mode 100644 index 00000000..f433ed9d --- /dev/null +++ b/NMessage/MSG_RequestClassList.h @@ -0,0 +1,50 @@ +#ifndef VNOC_C_MESSAGE_MSG_RequestClassList +#define VNOC_C_MESSAGE_MSG_RequestClassList +#include "MessageDef.h" +#include "CMessage.h" +#include "MsgDataValue/StringData.h" +#include "MsgDataValue/NumData.hpp" + +///> Generate by MessageProduse. DO NOT EDIT! + +namespace VNOC +{ +namespace Message +{ + +class MSG_RequestClassList : public CMessage +{ +public: + MSG_RequestClassList() + { + RegisterPort("UserType", MsgDataMType_Data, MsgDataType_Uint32); + + InitializeMessage(MSG_RequestClassList_Id); + } + + MSG_RequestClassList(const CMessage& Msg) + { + RegisterPort("UserType", MsgDataMType_Data, MsgDataType_Uint32); + + CMessage::Copy(Msg, MSG_RequestClassList_Id); + } + + virtual ~MSG_RequestClassList(){} + + MsgStatus SetUserType(const Define::uint32& Value) + { + return Write("UserType", new NumData(Value)); + } + + MsgStatus GetUserType(Define::uint32& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("UserType", pReadValue); + return pReadValue->ToUInt32(Value); + } +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MSG_RequestLogin.h b/NMessage/MSG_RequestLogin.h new file mode 100644 index 00000000..c110485c --- /dev/null +++ b/NMessage/MSG_RequestLogin.h @@ -0,0 +1,82 @@ +#ifndef VNOC_C_MESSAGE_MSG_RequestLogin +#define VNOC_C_MESSAGE_MSG_RequestLogin +#include "MessageDef.h" +#include "CMessage.h" +#include "MsgDataValue/StringData.h" +#include "MsgDataValue/NumData.hpp" + +///> Generate by MessageProduse. DO NOT EDIT! + +namespace VNOC +{ +namespace Message +{ + +class MSG_RequestLogin : public CMessage +{ +public: + MSG_RequestLogin() + { + RegisterPort("AccountNumber", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("Password", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("VerificationCode", MsgDataMType_Data, MsgDataType_String); + + InitializeMessage(MSG_RequestLogin_Id); + } + + MSG_RequestLogin(const CMessage& Msg) + { + RegisterPort("AccountNumber", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("Password", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("VerificationCode", MsgDataMType_Data, MsgDataType_String); + + CMessage::Copy(Msg, MSG_RequestLogin_Id); + } + + virtual ~MSG_RequestLogin(){} + + MsgStatus SetAccountNumber(const std::string& Value) + { + return Write("AccountNumber", new StringData(Value)); + } + + MsgStatus SetPassword(const std::string& Value) + { + return Write("Password", new StringData(Value)); + } + + MsgStatus SetVerificationCode(const std::string& Value) + { + return Write("VerificationCode", new StringData(Value)); + } + + MsgStatus GetAccountNumber(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("AccountNumber", pReadValue); + return pReadValue->ToStr(Value); + } + + MsgStatus GetPassword(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("Password", pReadValue); + return pReadValue->ToStr(Value); + } + + MsgStatus GetVerificationCode(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("VerificationCode", pReadValue); + return pReadValue->ToStr(Value); + } +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MSG_RequestProfileSync.h b/NMessage/MSG_RequestProfileSync.h new file mode 100644 index 00000000..2a98a7ef --- /dev/null +++ b/NMessage/MSG_RequestProfileSync.h @@ -0,0 +1,114 @@ +#ifndef VNOC_C_MESSAGE_MSG_RequestProfileSync +#define VNOC_C_MESSAGE_MSG_RequestProfileSync +#include "MessageDef.h" +#include "CMessage.h" +#include "MsgDataValue/StringData.h" +#include "MsgDataValue/NumData.hpp" + +///> Generate by MessageProduse. DO NOT EDIT! + +namespace VNOC +{ +namespace Message +{ + +class MSG_RequestProfileSync : public CMessage +{ +public: + MSG_RequestProfileSync() + { + RegisterPort("Autograph", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("HeadForm", MsgDataMType_Data, MsgDataType_Uint8); + + RegisterPort("HeadPortrait", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("Nickname", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("Rank", MsgDataMType_Data, MsgDataType_Uint8); + + InitializeMessage(MSG_RequestProfileSync_Id); + } + + MSG_RequestProfileSync(const CMessage& Msg) + { + RegisterPort("Autograph", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("HeadForm", MsgDataMType_Data, MsgDataType_Uint8); + + RegisterPort("HeadPortrait", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("Nickname", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("Rank", MsgDataMType_Data, MsgDataType_Uint8); + + CMessage::Copy(Msg, MSG_RequestProfileSync_Id); + } + + virtual ~MSG_RequestProfileSync(){} + + MsgStatus SetAutograph(const std::string& Value) + { + return Write("Autograph", new StringData(Value)); + } + + MsgStatus SetHeadForm(const Define::uint8& Value) + { + return Write("HeadForm", new NumData(Value)); + } + + MsgStatus SetHeadPortrait(const std::string& Value) + { + return Write("HeadPortrait", new StringData(Value)); + } + + MsgStatus SetNickname(const std::string& Value) + { + return Write("Nickname", new StringData(Value)); + } + + MsgStatus SetRank(const Define::uint8& Value) + { + return Write("Rank", new NumData(Value)); + } + + MsgStatus GetAutograph(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("Autograph", pReadValue); + return pReadValue->ToStr(Value); + } + + MsgStatus GetHeadForm(Define::uint8& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("HeadForm", pReadValue); + return pReadValue->ToUInt8(Value); + } + + MsgStatus GetHeadPortrait(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("HeadPortrait", pReadValue); + return pReadValue->ToStr(Value); + } + + MsgStatus GetNickname(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("Nickname", pReadValue); + return pReadValue->ToStr(Value); + } + + MsgStatus GetRank(Define::uint8& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("Rank", pReadValue); + return pReadValue->ToUInt8(Value); + } +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MSG_RequestRegister.h b/NMessage/MSG_RequestRegister.h new file mode 100644 index 00000000..318b690b --- /dev/null +++ b/NMessage/MSG_RequestRegister.h @@ -0,0 +1,130 @@ +#ifndef VNOC_C_MESSAGE_MSG_RequestRegister +#define VNOC_C_MESSAGE_MSG_RequestRegister +#include "MessageDef.h" +#include "CMessage.h" +#include "MsgDataValue/StringData.h" +#include "MsgDataValue/NumData.hpp" + +///> Generate by MessageProduse. DO NOT EDIT! + +namespace VNOC +{ +namespace Message +{ + +class MSG_RequestRegister : public CMessage +{ +public: + MSG_RequestRegister() + { + RegisterPort("Autograph", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("EmailAddress", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("HeadForm", MsgDataMType_Data, MsgDataType_Uint8); + + RegisterPort("HeadPortrait", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("Nickname", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("Rank", MsgDataMType_Data, MsgDataType_Uint8); + + InitializeMessage(MSG_RequestRegister_Id); + } + + MSG_RequestRegister(const CMessage& Msg) + { + RegisterPort("Autograph", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("EmailAddress", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("HeadForm", MsgDataMType_Data, MsgDataType_Uint8); + + RegisterPort("HeadPortrait", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("Nickname", MsgDataMType_Data, MsgDataType_String); + + RegisterPort("Rank", MsgDataMType_Data, MsgDataType_Uint8); + + CMessage::Copy(Msg, MSG_RequestRegister_Id); + } + + virtual ~MSG_RequestRegister(){} + + MsgStatus SetAutograph(const std::string& Value) + { + return Write("Autograph", new StringData(Value)); + } + + MsgStatus SetEmailAddress(const std::string& Value) + { + return Write("EmailAddress", new StringData(Value)); + } + + MsgStatus SetHeadForm(const Define::uint8& Value) + { + return Write("HeadForm", new NumData(Value)); + } + + MsgStatus SetHeadPortrait(const std::string& Value) + { + return Write("HeadPortrait", new StringData(Value)); + } + + MsgStatus SetNickname(const std::string& Value) + { + return Write("Nickname", new StringData(Value)); + } + + MsgStatus SetRank(const Define::uint8& Value) + { + return Write("Rank", new NumData(Value)); + } + + MsgStatus GetAutograph(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("Autograph", pReadValue); + return pReadValue->ToStr(Value); + } + + MsgStatus GetEmailAddress(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("EmailAddress", pReadValue); + return pReadValue->ToStr(Value); + } + + MsgStatus GetHeadForm(Define::uint8& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("HeadForm", pReadValue); + return pReadValue->ToUInt8(Value); + } + + MsgStatus GetHeadPortrait(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("HeadPortrait", pReadValue); + return pReadValue->ToStr(Value); + } + + MsgStatus GetNickname(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("Nickname", pReadValue); + return pReadValue->ToStr(Value); + } + + MsgStatus GetRank(Define::uint8& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("Rank", pReadValue); + return pReadValue->ToUInt8(Value); + } +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MSG_RequestVerificationCode.h b/NMessage/MSG_RequestVerificationCode.h new file mode 100644 index 00000000..fb4b3a77 --- /dev/null +++ b/NMessage/MSG_RequestVerificationCode.h @@ -0,0 +1,50 @@ +#ifndef VNOC_C_MESSAGE_MSG_RequestVerificationCode +#define VNOC_C_MESSAGE_MSG_RequestVerificationCode +#include "MessageDef.h" +#include "CMessage.h" +#include "MsgDataValue/StringData.h" +#include "MsgDataValue/NumData.hpp" + +///> Generate by MessageProduse. DO NOT EDIT! + +namespace VNOC +{ +namespace Message +{ + +class MSG_RequestVerificationCode : public CMessage +{ +public: + MSG_RequestVerificationCode() + { + RegisterPort("MachineAddress", MsgDataMType_Data, MsgDataType_String); + + InitializeMessage(MSG_RequestVerificationCode_Id); + } + + MSG_RequestVerificationCode(const CMessage& Msg) + { + RegisterPort("MachineAddress", MsgDataMType_Data, MsgDataType_String); + + CMessage::Copy(Msg, MSG_RequestVerificationCode_Id); + } + + virtual ~MSG_RequestVerificationCode(){} + + MsgStatus SetMachineAddress(const std::string& Value) + { + return Write("MachineAddress", new StringData(Value)); + } + + MsgStatus GetMachineAddress(std::string& Value) const + { + MsgDataValue* pReadValue = NULL; + Read("MachineAddress", pReadValue); + return pReadValue->ToStr(Value); + } +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/Message2Pack.cpp b/NMessage/Message2Pack.cpp new file mode 100644 index 00000000..b7930935 --- /dev/null +++ b/NMessage/Message2Pack.cpp @@ -0,0 +1,598 @@ +#include "Message2Pack.h" + +namespace VNOC +{ +namespace Message +{ + +using namespace VNOC::Message::Define; + +CMessage2Pack::CMessage2Pack() +{ + +} + +CMessage2Pack::~CMessage2Pack() +{ + +} + +/************************************************************************ + +PackڴṹΪ + +ͷ | ܴСuint32 | msg iduint32 | +Ϊdataxml˳ +uint | uint8 | uint16 | uint32 | +string | : uint32 | ַ | +array | Ԫظ : uint32 | sǰ + +************************************************************************/ + +MsgStatus CMessage2Pack::GetPackSize(const CMessage* pMsg, int& nSize ) +{ + if (!pMsg) + { + return MsgStatus_Err; + } + int nId = pMsg->MsgId(); + if (nId == 0) + { + return MsgStatus_Err; + } + int nLen = MSG_HEAD_LEN + MSG_TAIL_LEN; ///> ܴС+msg id + int nAdd = 0; + MsgDataValue* pReadStr = NULL; + auto it = pMsg->PortBegin(); + for (; it != pMsg->PortEnd(); ++it) + { + switch (it->second.first) + { + case MsgDataMType_Data: + nAdd = _GetDataSize(it->first, it->second.second, pMsg); + if (nAdd == 0) + { + return MsgStatus_Err; + } + nLen += nAdd; + break; + case MsgDataMType_List: + nAdd = _GetArrSize(it->first, it->second.second, pMsg); + if (nAdd == 0) + { + return MsgStatus_Err; + } + nLen += nAdd + MSG_CLASS_PARAM_COUNT; + break; + default: + return MsgStatus_Err; + } + } + nSize = nLen; + return MsgStatus_Ok; +} + +MsgStatus CMessage2Pack::PackMessage(const CMessage* pMsg, CBufferMessage& pBuf) +{ + if (!pMsg) + { + return MsgStatus_Err; + } + int PackSize = 0; + if (GetPackSize(pMsg, PackSize) != MsgStatus_Ok) + { + return MsgStatus_Err; + } + uint8* Buff = pBuf.Alloc(PackSize); + if (Buff == NULL) + { + return MsgStatus_Err; + } + int nId = pMsg->MsgId(); + if (nId == 0) + { + return MsgStatus_Err; + } + int nPackPos = _PackHead(nId,pBuf); + std::vector vecParamLen; + std::vector > vecParamList; + for (auto It = pMsg->PortBegin(); It != pMsg->PortEnd(); It++) + { + switch (It->second.first) + { + case MsgDataMType_Data: + _PushMessageDataParam(It->second.second, pMsg,It->first, vecParamLen, vecParamList); + break; + case MsgDataMType_List: + _PushMessageListParam(It->second.second, pMsg,It->first, vecParamLen, vecParamList); + break; + default: + return MsgStatus_Err; + } + } + if (_PackParam(pMsg, pBuf, nPackPos, vecParamLen, vecParamList) != MsgStatus_Ok) + { + return MsgStatus_Err; + } + _PackTail(nPackPos, pBuf); + return MsgStatus_Ok; +} + +int CMessage2Pack::_GetDataSize(const Define::MsgDataName& strName, MsgDataType eType,const CMessage* pMsg ) +{ + MsgDataValue* pReadStr = NULL; + switch (eType) + { + case MsgDataType_String: + if (pMsg->Read(strName, pReadStr) == MsgStatus_Ok) + return _GetStringSize(pReadStr); + break; + case MsgDataType_Uint8: + return 1; + break; + case MsgDataType_Uint16: + return 2; + break; + case MsgDataType_Uint32: + return 4; + break; + } + return 0; +} + +int CMessage2Pack::_GetStringSize( MsgDataValue* pReadStr ) +{ + std::string strData; + if (pReadStr && pReadStr->ToStr(strData) == MsgStatus_Ok) + { + if (strData.empty()) + { + return 4 + 1; + } + else + { + return 4 + strData.size(); + } + } + else + { + return 4 + 1; + } + return 0; +} + +int CMessage2Pack::_GetArrSize(const Define::MsgDataName& strName, MsgDataType eType,const CMessage* pMsg ) +{ + int nSize = 0; + int nAdd = 0; + ArrayData* pReadArr = NULL; + if (pMsg->ReadArr(strName, pReadArr) == MsgStatus_Ok) + { + switch (eType) + { + case MsgDataType_String: + if (pReadArr == NULL) + { + return 1; + } + for (std::vector::const_iterator it = pReadArr->Begin(); + it != pReadArr->End(); + ++it) + { + nAdd = _GetStringSize(static_cast(*it)); + if (nAdd == 0) + { + return 0; + } + nSize += nAdd; + } + break; + case MsgDataType_Uint8: + if (pReadArr == NULL) + { + return 1; + } + nSize = pReadArr->Size(); + break; + case MsgDataType_Uint16: + if (pReadArr == NULL) + { + return 2 * 1; + } + nSize = 2 * pReadArr->Size(); + break; + case MsgDataType_Uint32: + if (pReadArr == NULL) + { + return 4 * 1; + } + nSize = 4 * pReadArr->Size(); + break; + } + } + return nSize; +} + +MsgStatus CMessage2Pack::_PushMessageDataParam( + MsgDataType eType, + const CMessage* pMsg, + std::string ParamName, + std::vector& vecParamLen, + std::vector >& vecParamList + ) +{ + MsgDataValue* pReadValue = NULL; + std::string strParam; + uint8* pByteParam = NULL; + uint8 uint8Param = 0; + uint16 uint16Param = 0; + uint32 uint32Param = 0; + int strParamLen = 0; + std::vector vecParam; + pMsg->Read(ParamName, pReadValue); + if (pReadValue == NULL) + { + return _Occupy(eType, vecParamLen, vecParamList); + } + switch (eType) + { + case MsgDataType_String: + pReadValue->ToStr(strParam); + strParamLen = strParam.size(); + if (strParamLen == 0) + { + strParamLen = 1; + vecParam.push_back(MsgPack_Unk); + } + else + { + pReadValue->ToStr(strParam); + vecParam.resize(strParamLen); + std::copy(strParam.begin(), strParam.end(), vecParam.begin()); + } + vecParamLen.push_back(strParamLen); + vecParamList.push_back(vecParam); + break; + case MsgDataType_Uint8: + vecParamLen.push_back(sizeof(uint8)); + pReadValue->ToUInt8(uint8Param); + vecParam.push_back(uint8Param); + vecParamList.push_back(vecParam); + break; + case MsgDataType_Uint16: + vecParamLen.push_back(sizeof(uint16)); + pReadValue->ToUInt16(uint16Param); + pByteParam = (uint8*)&uint16Param; + for (int index = 0; index < sizeof(uint16); index++) + { + vecParam.push_back(pByteParam[index]); + } + vecParamList.push_back(vecParam); + break; + case MsgDataType_Uint32: + vecParamLen.push_back(sizeof(uint32)); + pReadValue->ToUInt32(uint32Param); + pByteParam = (uint8*)&uint32Param; + for (int index = 0; index < sizeof(uint32); index++) + { + vecParam.push_back(pByteParam[index]); + } + vecParamList.push_back(vecParam); + break; + default: + return MsgStatus_Err; + } + return MsgStatus_Ok; +} + +MsgStatus CMessage2Pack::_PushMessageListParam( + MsgDataType eType, + const CMessage* pMsg, + std::string ParamName, + std::vector& vecParamLen, + std::vector >& vecParamList + ) +{ + std::vector vecParam; + ArrayData* pReadArrValue = NULL; + std::string strParam; + uint8* pByteParam = NULL; + uint8 uint8Param = 0; + uint16 uint16Param = 0; + uint32 uint32Param = 0; + pMsg->ReadArr(ParamName, pReadArrValue); + if (pReadArrValue == NULL) + { + vecParamLen.push_back(1); + return _Occupy(eType, vecParamLen, vecParamList); + } + else if (pReadArrValue->Empty()) + { + vecParamLen.push_back(1); + return _Occupy(eType, vecParamLen, vecParamList); + } + vecParamLen.push_back(pReadArrValue->Size()); + switch(eType) + { + case MsgDataType_String: + for (auto It = pReadArrValue->Begin(); + It != pReadArrValue->End(); + It++ + ) + { + static_cast(*It)->ToStr(strParam); + if (!strParam.empty()) + { + vecParam.resize(strParam.size()); + vecParamLen.push_back(strParam.size()); + std::copy(strParam.begin(), strParam.end(), vecParam.begin()); + } + else + { + vecParamLen.push_back(1); + } + vecParamList.push_back(vecParam); + vecParam.clear(); + } + break; + case MsgDataType_Uint8: + for (auto It = pReadArrValue->Begin(); + It != pReadArrValue->End(); + It++ + ) + { + static_cast(*It)->ToUInt8(uint8Param); + vecParam.push_back(uint8Param); + vecParamLen.push_back(sizeof(uint8)); + vecParamList.push_back(vecParam); + vecParam.clear(); + } + break; + case MsgDataType_Uint16: + for (auto It = pReadArrValue->Begin(); + It != pReadArrValue->End(); + It++ + ) + { + static_cast(*It)->ToUInt16(uint16Param); + pByteParam = (uint8*)&uint16Param; + for (uint32 index = 0; index < sizeof(uint16); index++) + { + vecParam.push_back(pByteParam[index]); + } + vecParamLen.push_back(sizeof(uint16)); + vecParamList.push_back(vecParam); + vecParam.clear(); + } + break; + case MsgDataType_Uint32: + for (auto It = pReadArrValue->Begin(); + It != pReadArrValue->End(); + It++ + ) + { + static_cast(*It)->ToUInt32(uint32Param); + pByteParam = (uint8*)&uint32Param; + for (uint32 index = 0; index < sizeof(uint32); index++) + { + vecParam.push_back(pByteParam[index]); + } + vecParamLen.push_back(sizeof(uint32)); + vecParamList.push_back(vecParam); + vecParam.clear(); + } + break; + default: + return MsgStatus_Err; + } + return MsgStatus_Ok; +} + +int CMessage2Pack::_PackHead(int PackMsgId, CBufferMessage& pBuf) +{ + int nPackSize = pBuf.GetSize(); + if (nPackSize <= MSG_HEAD_LEN) + { + return 0; + } + uint32 nPackPos = 0; + uint8* pByte = NULL; + uint8* Buff = pBuf.GetBuffer(); + ///>ͷ + Buff[nPackPos] = MSG_BEGIN; + nPackPos++; + ///>汾 һֽڴ洢 + Buff[nPackPos] = MSG_VER; + nPackPos++; + ///>С uint32 + pByte = (uint8*)&nPackSize; + for (uint32 index = 0; index < MSG_CLASS_LEN; index++) + { + Buff[nPackPos] = pByte[index]; + nPackPos++; + } + ///>ϢID uint32 + pByte = (uint8*)&PackMsgId; + for (uint32 index = 0; index < MSG_CLASS_COMMAND; index++) + { + Buff[nPackPos] = pByte[index]; + nPackPos++; + } + return nPackPos; +} + +int CMessage2Pack::_PackTail(int nPackPos,CBufferMessage& pBuf) +{ + if (nPackPos == 0) + { + return 0; + } + uint8* Buff = pBuf.GetBuffer(); + if (pBuf.GetSize() < (uint32)(nPackPos + MSG_TAIL_LEN)) + { + return 0; + } + Buff[nPackPos] = MSG_END; + return nPackPos++; +} + +MsgStatus CMessage2Pack::_PackParam( + const CMessage* pMsg, + CBufferMessage& pBuf, + int& nPackPos, + std::vector& vecParamLen, + std::vector >& vecParamList + ) +{ + if (vecParamLen.empty() || vecParamList.empty()) + { + return MsgStatus_Err; + } + uint8* Buff = pBuf.GetBuffer(); + if (Buff == NULL) + { + return MsgStatus_Err; + } + uint8* pByte = NULL; + uint32 ArrCount = 0; + int nPackParamIndex = 0; + int nPackParamLenIndex = 0; + for (auto It = pMsg->PortBegin(); It != pMsg->PortEnd(); It++) + { + switch (It->second.first) + { + case MsgDataMType_Data: + if (It->second.second == MsgDataType_String) + { + pByte = (uint8*)&vecParamLen[nPackParamLenIndex]; + for (int index = 0; index < sizeof(uint32); index++) + { + Buff[nPackPos] = pByte[index]; + nPackPos++; + } + for (uint32 index = 0; index < vecParamList[nPackParamLenIndex].size(); index++) + { + Buff[nPackPos] = vecParamList[nPackParamIndex][index]; + nPackPos++; + } + } + else if (It->second.second == MsgDataType_Uint8) + { + Buff[nPackPos] = vecParamList[nPackParamIndex][0]; + nPackPos++; + } + else + { + for (int index = 0; + index < vecParamLen[nPackParamLenIndex]; + index++ + ) + { + Buff[nPackPos] = vecParamList[nPackParamIndex][index]; + nPackPos++; + } + } + nPackParamLenIndex++; + nPackParamIndex++; + break; + case MsgDataMType_List: + ///>Ԫظ + ArrCount = vecParamLen[nPackParamLenIndex]; + nPackParamLenIndex++; + if (ArrCount < 0) + { + ArrCount = 0; + } + pByte = (uint8*)&ArrCount; + for (int index = 0; index < sizeof(uint32); index++) + { + Buff[nPackPos] = pByte[index]; + nPackPos++; + } + for (uint32 ArrIndex = 0; ArrIndex < ArrCount; ArrIndex++) + { + if (It->second.second == MsgDataType_String) + { + pByte = (uint8*)&vecParamLen[nPackParamLenIndex]; + for (int index = 0; index < sizeof(uint32); index++) + { + Buff[nPackPos] = pByte[index]; + nPackPos++; + } + if (vecParamList[nPackParamIndex].empty()) + { + Buff[nPackPos] = MsgPack_Unk; + nPackPos++; + } + else + { + for (uint32 index = 0; index < vecParamList[nPackParamIndex].size(); index++) + { + Buff[nPackPos] = vecParamList[nPackParamIndex][index]; + nPackPos++; + } + } + } + else + { + for (int index = 0; + index < vecParamLen[nPackParamLenIndex]; + index++ + ) + { + Buff[nPackPos] = vecParamList[nPackParamIndex][index]; + nPackPos++; + } + } + nPackParamIndex++; + nPackParamLenIndex++; + } + break; + default: + return MsgStatus_Err; + } + } + return MsgStatus_Ok; +} + +MsgStatus CMessage2Pack::_Occupy( + MsgDataType eType, + std::vector& vecParamLen, + std::vector >& vecParamList + ) +{ + std::vector vecParam; + switch (eType) + { + case MsgDataType_String: + vecParamLen.push_back(1); + vecParam.push_back(MsgPack_Unk); + break; + case MsgDataType_Uint8: + vecParamLen.push_back(sizeof(uint8)); + for (int index = 0; index < sizeof(uint8); index++) + { + vecParam.push_back(MsgPack_Unk); + } + break; + case MsgDataType_Uint16: + vecParamLen.push_back(sizeof(uint16)); + for (int index = 0; index < sizeof(uint16); index++) + { + vecParam.push_back(MsgPack_Unk); + } + break; + case MsgDataType_Uint32: + vecParamLen.push_back(sizeof(uint32)); + for (int index = 0; index < sizeof(uint32); index++) + { + vecParam.push_back(MsgPack_Unk); + } + break; + } + vecParamList.push_back(vecParam); + return MsgStatus_Ok; +} + +}// namespace Message +}// namespace VNOC diff --git a/NMessage/Message2Pack.h b/NMessage/Message2Pack.h new file mode 100644 index 00000000..50ec4436 --- /dev/null +++ b/NMessage/Message2Pack.h @@ -0,0 +1,57 @@ +#ifndef VNOC_MESSAGE2PACK +#define VNOC_MESSAGE2PACK + +#include "MessageDef.h" +#include "CMessage.h" +#include "BufferMessage.h" + +namespace VNOC +{ +namespace Message +{ + +///> MSGתPack +class CMessage2Pack +{ +public: + CMessage2Pack(); + ~CMessage2Pack(); + + ///> sizeΪuint8charĸ + MsgStatus GetPackSize(IN const CMessage* pMsg, OUT int& nSize); + MsgStatus PackMessage(IN const CMessage* pMsg, OUT CBufferMessage& pBuf); + +private: + int _GetDataSize(const Define::MsgDataName& strName, MsgDataType eType,const CMessage* pMsg); + int _GetStringSize(MsgDataValue* pReadStr); + int _GetArrSize(const Define::MsgDataName& strName, MsgDataType eType,const CMessage* pMsg); + int _PackHead(int PackMsgId, CBufferMessage& pBuf); + int _PackTail(int nPackPos, CBufferMessage& pBuf); + MsgStatus _PushMessageDataParam( + MsgDataType eType, + const CMessage* pMsg, + std::string ParamName, + std::vector& vecParamLen, + std::vector >& vecParamList); + MsgStatus _PushMessageListParam( + MsgDataType eType, + const CMessage* pMsg, + std::string ParamName, + std::vector& vecParamLen, + std::vector >& vecParamList); + MsgStatus _PackParam( + const CMessage* pMsg, + CBufferMessage& pBuf, + int& nPackPos, + std::vector& vecParamLen, + std::vector >& vecParamList); + MsgStatus _Occupy( + MsgDataType eType, + std::vector& vecParamLen, + std::vector >& vecParamList); +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/Message2Parser.cpp b/NMessage/Message2Parser.cpp new file mode 100644 index 00000000..4a61beef --- /dev/null +++ b/NMessage/Message2Parser.cpp @@ -0,0 +1,288 @@ +#include "Message2Parser.h" +#include "MessageUnionFunDef.h" + +namespace VNOC +{ +namespace Message +{ + +using namespace VNOC::Message::Define; + +bool CMessage2Parser::IsVaild(IN const CBufferMessage& pBuf) +{ + uint8* pData = pBuf.GetBuffer(); + if (pData[0] != MSG_BEGIN) + { + return false; + } + + if (pData[CMessage2Parser::GetMessageLen(pBuf.GetBuffer(), pBuf.GetSize()) - 1] != MSG_END) + { + return false; + } + return true; +} + +MsgStatus CMessage2Parser::Parser( + OUT CMessage* pMsg, + IN const CBufferMessage& pBuf + ) +{ + if (!IsVaild(pBuf)) + { + return MsgStatus_FormatFailure; + } + + if (pBuf.GetSize() == 0) + { + return MsgStatus_Err; + } + RegistrePort(pMsg, CMessage2Parser::GetMsgType(pBuf)); + if (_ParserHead(pMsg, pBuf) != MsgStatus_Ok) + { + return MsgStatus_FormatFailure; + } + if (_ParserParam(pMsg, pBuf) != MsgStatus_Ok) + { + return MsgStatus_Err; + } + return _ParserTail(pMsg, pBuf); +} + +MsgStatus CMessage2Parser::_ParserHead(CMessage* pMsg, const CBufferMessage& pBuf) +{ + uint8* pData = pBuf.GetBuffer(); + uint8 NumByte[4] = {0}; + if (!pData) + { + return MsgStatus_Err; + } + + for (int index = 0; index < MSG_CLASS_LEN; index++) + { + NumByte[index] = pData[MSG_PACKSIZE_INDEX + index]; + } + if (pBuf.GetSize() != _ByteToInt(NumByte)) + { + return MsgStatus_Err; + } + memset(NumByte,0,4); + for (int index = 0; index < MSG_CLASS_COMMAND; index++) + { + NumByte[index] = pData[MSG_COMMAND_INDEX + index]; + } + m_MsgId = _ByteToInt(NumByte); + return MsgStatus_Ok; +} + +MsgStatus CMessage2Parser::_ParserTail(CMessage* pMsg, const CBufferMessage& pBuf) +{ + uint8* pData = pBuf.GetBuffer(); + if (pData[CMessage2Parser::GetMessageLen(pBuf.GetBuffer(), pBuf.GetSize()) - 1] != MSG_END) + { + return MsgStatus_Err; + } + return MsgStatus_Ok; +} + +MsgStatus CMessage2Parser::_ParserParam( CMessage* pMsg, const CBufferMessage& pBuf ) +{ + uint8* pData = pBuf.GetBuffer(); + int nParserIndex = MSG_HEAD_LEN; + std::string strParam; + int ArrSize = 0; + std::vector vecStrParam; + std::vector vecUint8Param; + std::vector vecUint16Param; + std::vector vecUint32Param; + ArrayData* pArrData = NULL; + uint8 NumByte[4] = {0}; + for (auto It = pMsg->PortBegin(); It != pMsg->PortEnd(); It++) + { + pArrData = new ArrayData; + switch (It->second.first) + { + case MsgDataMType_Data: + switch (It->second.second) + { + case MsgDataType_String: + for (int index = 0; index < sizeof(uint32); index++) + { + NumByte[index] = pData[nParserIndex]; + nParserIndex++; + } + for (int index = 0; index < _ByteToInt(NumByte); index++) + { + if ((_ByteToInt(NumByte) == 1) && (pData[nParserIndex] == 0)) + { + nParserIndex++; + break; + } + strParam.push_back(pData[nParserIndex]); + nParserIndex++; + } + pMsg->Write(It->first, new StringData(strParam)); + strParam.clear(); + memset(NumByte, 0, 4); + break; + case MsgDataType_Uint8: + pMsg->Write(It->first, new NumData(pData[nParserIndex])); + nParserIndex++; + break; + case MsgDataType_Uint16: + for (int index = 0; index < sizeof(uint16); index++) + { + NumByte[index] = pData[nParserIndex]; + nParserIndex++; + } + pMsg->Write(It->first, new NumData(_ByteToInt(NumByte))); + memset(NumByte, 0, 4); + break; + case MsgDataType_Uint32: + for (int index = 0; index < sizeof(uint32); index++) + { + NumByte[index] = pData[nParserIndex]; + nParserIndex++; + } + pMsg->Write(It->first, new NumData(_ByteToInt(NumByte))); + memset(NumByte, 0, 4); + break; + } + break; + case MsgDataMType_List: + for (int index = 0; index < sizeof(uint32); index++) + { + NumByte[index] = pData[nParserIndex]; + nParserIndex++; + } + ArrSize = _ByteToInt(NumByte); + memset(NumByte, 0, 4); + + for (int index = 0; index < ArrSize; index++) + { + if (It->second.second == MsgDataType_String) + { + for (int index = 0; index < sizeof(uint32); index++) + { + NumByte[index] = pData[nParserIndex]; + nParserIndex++; + } + for (int index = 0; index < _ByteToInt(NumByte); index++) + { + if ((_ByteToInt(NumByte) == 1) && (pData[nParserIndex] == 0)) + { + nParserIndex++; + break; + } + strParam.push_back(pData[nParserIndex]); + nParserIndex++; + } + vecStrParam.push_back(strParam); + strParam.clear(); + memset(NumByte, 0, 4); + } + else if (It->second.second == MsgDataType_Uint8) + { + vecUint8Param.push_back(pData[nParserIndex]); + nParserIndex++; + } + else if (It->second.second == MsgDataType_Uint16) + { + for (int index = 0; index < sizeof(uint16); index++) + { + NumByte[index] = pData[nParserIndex]; + nParserIndex++; + } + vecUint16Param.push_back(_ByteToInt(NumByte)); + memset(NumByte, 0, 4); + } + else if (It->second.second == MsgDataType_Uint32) + { + for (int index = 0; index < sizeof(uint32); index++) + { + NumByte[index] = pData[nParserIndex]; + nParserIndex++; + } + vecUint32Param.push_back(_ByteToInt(NumByte)); + memset(NumByte, 0, 4); + } + } + if (!vecStrParam.empty()) + { + pArrData->Push(vecStrParam); + vecStrParam.clear(); + } + if (!vecUint8Param.empty()) + { + pArrData->Push(vecUint8Param); + vecUint8Param.clear(); + } + if (!vecUint16Param.empty()) + { + pArrData->Push(vecUint16Param); + vecUint16Param.clear(); + } + if (!vecUint32Param.empty()) + { + pArrData->Push(vecUint32Param); + vecUint32Param.clear(); + } + pMsg->WriteArr(It->first, pArrData); + break; + default: + return MsgStatus_Err; + } + } + return MsgStatus_Ok; +} + +int CMessage2Parser::_ByteToInt(uint8* pData) +{ + uint8 ByteData[4] = {0}; + memcpy(ByteData, pData, 4); + int retint = *(int*)&ByteData; + return retint; +} + +int CMessage2Parser::GetMsgType(IN const CBufferMessage& pBuf) +{ + int MsgID = 0; + uint8* pData = pBuf.GetBuffer(); + uint8 NumByte[4] = {0}; + if (!pData) + { + return MsgStatus_Err; + } + + for (int index = 0; index < MSG_CLASS_COMMAND; index++) + { + NumByte[index] = pData[MSG_COMMAND_INDEX + index]; + } + MsgID = *(int*)&NumByte; + return MsgID; +} + +uint32 CMessage2Parser::GetMessageLen(uint8* pData, uint32 nBufferSize) +{ + if (!pData) + { + return MsgStatus_Err; + } + + if ((MSG_PACKSIZE_INDEX + 4) > nBufferSize) + { + return MsgStatus_Err; + } + + int MsgSize = 0; + uint8 NumByte[4] = {0}; + for (int index = 0; index < MSG_CLASS_LEN; index++) + { + NumByte[index] = pData[MSG_PACKSIZE_INDEX + index]; + } + MsgSize = *(int*)&NumByte; + return MsgSize; +} + +} +} \ No newline at end of file diff --git a/NMessage/Message2Parser.h b/NMessage/Message2Parser.h new file mode 100644 index 00000000..01799823 --- /dev/null +++ b/NMessage/Message2Parser.h @@ -0,0 +1,37 @@ +#ifndef VNOC_MESSAGEPARSER +#define VNOC_MESSAGEPARSER + +#include "MessageDef.h" +#include "BufferMessage.h" +#include "CMessage.h" + +namespace VNOC +{ +namespace Message +{ + +class CMessage2Parser +{ +public: + CMessage2Parser() : m_MsgId(0) {} + virtual ~CMessage2Parser() {} + + MsgStatus Parser(OUT CMessage* pMsg, IN const CBufferMessage& pBuf); + bool IsVaild(IN const CBufferMessage& pBuf); + static Define::uint32 GetMessageLen(Define::uint8* pData, Define::uint32 nBufferSize); + static int GetMsgType(IN const CBufferMessage& pBuf); + +private: + MsgStatus _ParserHead(CMessage* pMsg, const CBufferMessage& pBuf); + MsgStatus _ParserTail(CMessage* pMsg, const CBufferMessage& pBuf); + MsgStatus _ParserParam(CMessage* pMsg, const CBufferMessage& pBuf); + int _ByteToInt(Define::uint8* pData); + +private: + int m_MsgId; +}; + +} +} + +#endif \ No newline at end of file diff --git a/NMessage/MessageDef.h b/NMessage/MessageDef.h new file mode 100644 index 00000000..6818edbe --- /dev/null +++ b/NMessage/MessageDef.h @@ -0,0 +1,125 @@ +#ifndef VNOC_MESSAGE_DEF +#define VNOC_MESSAGE_DEF + +#ifndef IN +#define IN +#define OUT +#endif + +#ifndef EMPTY_TEMPTALE_DEFINE +#define EMPTY_TEMPTALE_DEFINE template<> +#endif + +// ʹС˻ +#define BigLittleSwap16(A) ((((ushort)(A) & 0xff00) >> 8) | \ + (((ushort)(A) & 0x00ff) << 8)) + +// ʹС˻ +#define BigLittleSwap32(A) ((((uint)(A) & 0xff000000) >> 24) | \ + (((uint)(A) & 0x00ff0000) >> 8) | \ + (((uint)(A) & 0x0000ff00) << 8) | \ + (((uint)(A) & 0x000000ff) << 24)) + +#include +#include +#include "MessageUnionDef.h" + +namespace VNOC +{ +namespace Message +{ + +typedef enum _MsgDataType +{ + MsgDataType_Null, + MsgDataType_String, + MsgDataType_Uint8, + MsgDataType_Uint16, + MsgDataType_Uint32, +}MsgDataType; + +typedef enum _MsgDataMType +{ + MsgDataMType_Null, + MsgDataMType_Data, + MsgDataMType_List, +}MsgDataMType; + +namespace Define +{ + +typedef std::string MsgDataName; +typedef MsgDataMType MsgMType; +typedef MsgDataType MsgType; +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef char int8; +typedef short int16; +typedef int int32; + +} +#define MSG_BEGIN 0x56 // 'V' ϢĿʼ +#define MSG_END 0x43 // 'C' ϢĽ +#define MSG_VER 1 // 汾 + +#define MSG_HEAD_LEN 10 +#define MSG_TAIL_LEN 1 + +#define MSG_CLASS_BEGIN 1 +#define MSG_CLASS_END 1 +#define MSG_CLASS_LEN 4 +#define MSG_CLASS_VER 1 +#define MSG_CLASS_SERIAL 2 +#define MSG_CLASS_GUID 16 +#define MSG_CLASS_COMMAND 4 +#define MSG_CLASS_OBL 4 +#define MSG_CLASS_PARAMCONST 1 +#define MSG_CLASS_VERIFY 2 // Ч δĬΪ2ֽ +#define MSG_CLASS_PARAM 4 +#define MSG_CLASS_PARAM_COUNT 4 + +#define MSG_PACKSIZE_INDEX MSG_CLASS_VER + MSG_CLASS_BEGIN +#define MSG_COMMAND_INDEX MSG_PACKSIZE_INDEX + MSG_CLASS_LEN + +#ifndef DISALLOW_COPY_AND_ASSIGN +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&); +#endif + +#ifndef DISALLOW_ASSIGN +#define DISALLOW_ASSIGN(TypeName) \ + void operator=(const TypeName&); +#endif + +#define MsgDataMType_XML_Data "data" +#define MsgDataMType_XML_List "list" + +#define MsgDataObject_XML_Name "name" +#define MsgDataObject_XML_Id "id" +#define MsgDataObject_XML_MType "mtype" +#define MsgDataObject_XML_Type "type" +#define MsgDataObject_XML_Root "vnoc" +#define MsgDataObject_XML_Msg "msg" + +#define MsgDataType_XML_Uint32 "uint32" +#define MsgDataType_XML_Uint16 "uint16" +#define MsgDataType_XML_Uint8 "uint8" +#define MsgDataType_XML_String "string" + +#define MsgPack_Unk 0 + +typedef enum _MsgStatus +{ + MsgStatus_Ok, + MsgStatus_Err, + MsgStatus_Unk, + MsgStatus_FormatFailure, + MsgStatus_TypeErr, +}MsgStatus; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MessageUnion.h b/NMessage/MessageUnion.h new file mode 100644 index 00000000..d4432a70 --- /dev/null +++ b/NMessage/MessageUnion.h @@ -0,0 +1,18 @@ +#ifndef VNOC_D_MESSSAGE_UNION +#define VNOC_D_MESSSAGE_UNION + +#include "MSG_RequestRegister.h " +#include "MSG_AnswerRegister.h " +#include "MSG_RequestVerificationCode.h " +#include "MSG_AnswerVerificationCode.h " +#include "MSG_RequestLogin.h " +#include "MSG_AnswerLogin.h " +#include "MSG_RequestProfileSync.h " +#include "MSG_AnswerProfileSync.h " +#include "MSG_RequestClassList.h " +#include "MSG_AnswerClassList.h " +#include "MSG_RequestClassInfo.h " +#include "MSG_AnswerClassInfo.h " +#include "MessageUnionDef.h " + +#endif \ No newline at end of file diff --git a/NMessage/MessageUnionDef.h b/NMessage/MessageUnionDef.h new file mode 100644 index 00000000..01c26063 --- /dev/null +++ b/NMessage/MessageUnionDef.h @@ -0,0 +1,30 @@ +#ifndef VNOC_D_MESSSAGE_UNION_DEF +#define VNOC_D_MESSSAGE_UNION_DEF + +namespace VNOC +{ +namespace Message +{ + +typedef enum _VMsg +{ + MSG_TYPE_NULL = 0, + MSG_RequestRegister_Id = 2100, + MSG_AnswerRegister_Id = 2101, + MSG_RequestVerificationCode_Id = 3101, + MSG_AnswerVerificationCode_Id = 3102, + MSG_RequestLogin_Id = 4101, + MSG_AnswerLogin_Id = 4102, + MSG_RequestProfileSync_Id = 5101, + MSG_AnswerProfileSync_Id = 5102, + MSG_RequestClassList_Id = 6105, + MSG_AnswerClassList_Id = 6106, + MSG_RequestClassInfo_Id = 6107, + MSG_AnswerClassInfo_Id = 6108, + MSG_TYPE_END, +}VMsg; + +} +} + +#endif \ No newline at end of file diff --git a/NMessage/MessageUnionFunDef.h b/NMessage/MessageUnionFunDef.h new file mode 100644 index 00000000..75bdd4a5 --- /dev/null +++ b/NMessage/MessageUnionFunDef.h @@ -0,0 +1,75 @@ +#ifndef VNOC_D_MESSSAGE_UNIONFUN_DEF +#define VNOC_D_MESSSAGE_UNIONFUN_DEF + +#include "CMessage.h" +#include "MessageUnion.h" + +namespace VNOC +{ +namespace Message +{ + +void RegistrePort(CMessage* pMsg, int nId) +{ + CMessage* pMsgConver = NULL; + switch(nId) + { + case MSG_RequestRegister_Id: + pMsgConver = new MSG_RequestRegister; + pMsg->CopyPort(*pMsgConver); + break; + case MSG_AnswerRegister_Id: + pMsgConver = new MSG_AnswerRegister; + pMsg->CopyPort(*pMsgConver); + break; + case MSG_RequestVerificationCode_Id: + pMsgConver = new MSG_RequestVerificationCode; + pMsg->CopyPort(*pMsgConver); + break; + case MSG_AnswerVerificationCode_Id: + pMsgConver = new MSG_AnswerVerificationCode; + pMsg->CopyPort(*pMsgConver); + break; + case MSG_RequestLogin_Id: + pMsgConver = new MSG_RequestLogin; + pMsg->CopyPort(*pMsgConver); + break; + case MSG_AnswerLogin_Id: + pMsgConver = new MSG_AnswerLogin; + pMsg->CopyPort(*pMsgConver); + break; + case MSG_RequestProfileSync_Id: + pMsgConver = new MSG_RequestProfileSync; + pMsg->CopyPort(*pMsgConver); + break; + case MSG_AnswerProfileSync_Id: + pMsgConver = new MSG_AnswerProfileSync; + pMsg->CopyPort(*pMsgConver); + break; + case MSG_RequestClassList_Id: + pMsgConver = new MSG_RequestClassList; + pMsg->CopyPort(*pMsgConver); + break; + case MSG_AnswerClassList_Id: + pMsgConver = new MSG_AnswerClassList; + pMsg->CopyPort(*pMsgConver); + break; + case MSG_RequestClassInfo_Id: + pMsgConver = new MSG_RequestClassInfo; + pMsg->CopyPort(*pMsgConver); + break; + case MSG_AnswerClassInfo_Id: + pMsgConver = new MSG_AnswerClassInfo; + pMsg->CopyPort(*pMsgConver); + break; + } + if (pMsg != NULL) + { + delete pMsgConver; + } +} + +} +} + +#endif \ No newline at end of file diff --git a/NMessage/MsgDataValue/ArrayData.cpp b/NMessage/MsgDataValue/ArrayData.cpp new file mode 100644 index 00000000..af69edf9 --- /dev/null +++ b/NMessage/MsgDataValue/ArrayData.cpp @@ -0,0 +1,151 @@ +#include "ArrayData.h" + +namespace VNOC +{ +namespace Message +{ + +using namespace Define; + +ArrayData::ArrayData() +{ + +} + +ArrayData::~ArrayData() +{ + +} + +size_t ArrayData::Size() +{ + return m_arrValuePtr.size(); +} + +bool ArrayData::Empty() +{ + return m_arrValuePtr.empty(); +} + +std::vector::const_iterator ArrayData::Begin() const +{ + return m_arrValuePtr.begin(); +} + +std::vector::const_iterator ArrayData::End() const +{ + return m_arrValuePtr.end(); +} + +void ArrayData::Push( MsgDataValue* pValue ) +{ + return m_arrValuePtr.push_back(pValue); +} + + +template<> +void ArrayData::Push( const std::vector& vecArr ) +{ + if (vecArr.empty()) + { + Push(new StringData("")); + return; + } + for (auto It = vecArr.begin(); It != vecArr.end(); It++) + { + Push(new StringData(*It)); + } +} + +template<> +void ArrayData::Push( const std::vector& vecArr ) +{ + if (vecArr.empty()) + { + Push(new NumData(0)); + return; + } + for (auto It = vecArr.begin(); It != vecArr.end(); It++) + { + Push(new NumData(*It)); + } +} + +template<> +void ArrayData::Push( const std::vector& vecArr ) +{ + if (vecArr.empty()) + { + Push(new NumData(0)); + return; + } + for (auto It = vecArr.begin(); It != vecArr.end(); It++) + { + Push(new NumData(*It)); + } +} + +template<> +void ArrayData::Push( const std::vector& vecArr ) +{ + if (vecArr.empty()) + { + Push(new NumData(0)); + return; + } + for (auto It = vecArr.begin(); It != vecArr.end(); It++) + { + Push(new NumData(*It)); + } +} + +template<> +void ArrayData::GetArr_vec( std::vector& vecArr ) +{ + for (auto It = m_arrValuePtr.begin(); It != m_arrValuePtr.end(); It++) + { + std::string strValue; + (*It)->ToStr(strValue); + vecArr.push_back(strValue); + strValue = ""; + } +} + +template<> +void ArrayData::GetArr_vec( std::vector& vecArr ) +{ + for (auto It = m_arrValuePtr.begin(); It != m_arrValuePtr.end(); It++) + { + uint8 strValue; + (*It)->ToUInt8(strValue); + vecArr.push_back(strValue); + strValue = 0; + } +} + +template<> +void ArrayData::GetArr_vec( std::vector& vecArr ) +{ + for (auto It = m_arrValuePtr.begin(); It != m_arrValuePtr.end(); It++) + { + uint16 strValue; + (*It)->ToUInt16(strValue); + vecArr.push_back(strValue); + strValue = 0; + } +} + +template<> +void ArrayData::GetArr_vec( std::vector& vecArr ) +{ + for (auto It = m_arrValuePtr.begin(); It != m_arrValuePtr.end(); It++) + { + uint32 strValue; + (*It)->ToUInt32(strValue); + vecArr.push_back(strValue); + strValue = 0; + } +} + +}// namespace Message +}// namespace VNOC diff --git a/NMessage/MsgDataValue/ArrayData.h b/NMessage/MsgDataValue/ArrayData.h new file mode 100644 index 00000000..1d867e67 --- /dev/null +++ b/NMessage/MsgDataValue/ArrayData.h @@ -0,0 +1,44 @@ +#ifndef VNOC_I_MESSAGE_DATA_ARRAY +#define VNOC_I_MESSAGE_DATA_ARRAY + +#include "../MessageDef.h" +#include "NumData.hpp" +#include "StringData.h" + +namespace VNOC +{ +namespace Message +{ + +class MsgDataValue; + +class ArrayData +{ +public: + ArrayData(); + virtual ~ArrayData(); + + size_t Size(); + + bool Empty(); + + std::vector::const_iterator Begin() const; + + std::vector::const_iterator End() const; + + void Push(IN MsgDataValue* pValue); + + template + void Push(const std::vector& vecArr); + + template + void GetArr_vec(std::vector& vecArr); + +private: + std::vector m_arrValuePtr; +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MsgDataValue/MsgDataValue.cpp b/NMessage/MsgDataValue/MsgDataValue.cpp new file mode 100644 index 00000000..79a7090c --- /dev/null +++ b/NMessage/MsgDataValue/MsgDataValue.cpp @@ -0,0 +1,56 @@ +#include "MsgDataValue.h" + +namespace VNOC +{ +namespace Message +{ + +using namespace Define; + +MsgDataValue::MsgDataValue() +{ + +} + +MsgDataValue::~MsgDataValue() +{ + +} + +MsgStatus MsgDataValue::ToStr(std::string& Value) +{ + return MsgStatus_Unk; +} + +MsgStatus MsgDataValue::ToUInt8(uint8& Value) +{ + return MsgStatus_Unk; +} + +MsgStatus MsgDataValue::ToUInt16(uint16& Value) +{ + return MsgStatus_Unk; +} + +MsgStatus MsgDataValue::ToUInt32(uint32& Value) +{ + return MsgStatus_Unk; +} + +MsgStatus MsgDataValue::ToInt8(int8& Value) +{ + return MsgStatus_Unk; +} + +MsgStatus MsgDataValue::ToInt16(int16& Value) +{ + return MsgStatus_Unk; +} + +MsgStatus MsgDataValue::ToInt32(int32& Value) +{ + return MsgStatus_Unk; +} + +}// namespace Message +}// namespace VNOC diff --git a/NMessage/MsgDataValue/MsgDataValue.h b/NMessage/MsgDataValue/MsgDataValue.h new file mode 100644 index 00000000..0331fa4b --- /dev/null +++ b/NMessage/MsgDataValue/MsgDataValue.h @@ -0,0 +1,35 @@ +#ifndef VNOC_I_MESSAGE_DATA +#define VNOC_I_MESSAGE_DATA + +#include "../MessageDef.h" + +namespace VNOC +{ +namespace Message +{ + +class MsgDataValue +{ +public: + MsgDataValue(); + virtual ~MsgDataValue(); + + virtual MsgStatus ToStr(OUT std::string& Value); + + virtual MsgStatus ToUInt8(OUT Define::uint8& Value); + + virtual MsgStatus ToUInt16(OUT Define::uint16& Value); + + virtual MsgStatus ToUInt32(OUT Define::uint32& Value); + + virtual MsgStatus ToInt8(OUT Define::int8& Value); + + virtual MsgStatus ToInt16(OUT Define::int16& Value); + + virtual MsgStatus ToInt32(OUT Define::int32& Value); +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MsgDataValue/NumData.hpp b/NMessage/MsgDataValue/NumData.hpp new file mode 100644 index 00000000..848ede8b --- /dev/null +++ b/NMessage/MsgDataValue/NumData.hpp @@ -0,0 +1,63 @@ +#ifndef VNOC_C_MESSAGE_UINT +#define VNOC_C_MESSAGE_UINT + +#include "NumData_t.hpp" + +namespace VNOC +{ +namespace Message +{ + +typedef NumData Int8Data; +typedef NumData Int16Data; +typedef NumData Int32Data; +typedef NumData UInt8Data; +typedef NumData UInt16Data; +typedef NumData UInt32Data; + +EMPTY_TEMPTALE_DEFINE +MsgStatus UInt8Data::ToUInt8(Define::uint8& Value) +{ + Value = m_Value; + return MsgStatus_Ok; +} + +EMPTY_TEMPTALE_DEFINE +MsgStatus UInt16Data::ToUInt16(Define::uint16& Value) +{ + Value = m_Value; + return MsgStatus_Ok; +} + +EMPTY_TEMPTALE_DEFINE +MsgStatus UInt32Data::ToUInt32(Define::uint32& Value) +{ + Value = m_Value; + return MsgStatus_Ok; +} + +EMPTY_TEMPTALE_DEFINE +MsgStatus Int8Data::ToInt8(Define::int8& Value) +{ + Value = m_Value; + return MsgStatus_Ok; +} + +EMPTY_TEMPTALE_DEFINE +MsgStatus Int16Data::ToInt16(Define::int16& Value) +{ + Value = m_Value; + return MsgStatus_Ok; +} + +EMPTY_TEMPTALE_DEFINE +MsgStatus Int32Data::ToInt32(Define::int32& Value) +{ + Value = m_Value; + return MsgStatus_Ok; +} + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/MsgDataValue/NumData_t.hpp b/NMessage/MsgDataValue/NumData_t.hpp new file mode 100644 index 00000000..4aeb9427 --- /dev/null +++ b/NMessage/MsgDataValue/NumData_t.hpp @@ -0,0 +1,43 @@ +#ifndef VNOC_C_MESSAGE_UINT_T +#define VNOC_C_MESSAGE_UINT_T + +#include "MsgDataValue.h" + +namespace VNOC +{ +namespace Message +{ + +template +class NumData : public MsgDataValue +{ +public: + NumData(TUIntType Value) : m_Value(Value) {} + virtual ~NumData() {} + + MsgStatus ToUInt8(Define::uint8& Value) {return MsgStatus_Err;} + + MsgStatus ToUInt16(Define::uint16& Value) {return MsgStatus_Err;} + + MsgStatus ToUInt32(Define::uint32& Value) {return MsgStatus_Err;} + + MsgStatus ToInt8(Define::int8& Value) {return MsgStatus_Err;} + + MsgStatus ToInt16(Define::int16& Value) {return MsgStatus_Err;} + + MsgStatus ToInt32(Define::int32& Value) {return MsgStatus_Err;} + + void SetValue(IN TUIntType& Value) + { + m_Value = Value; + } + +private: + DISALLOW_ASSIGN(NumData); + TUIntType m_Value; +}; + +} +} + +#endif \ No newline at end of file diff --git a/NMessage/MsgDataValue/StringData.cpp b/NMessage/MsgDataValue/StringData.cpp new file mode 100644 index 00000000..532795ec --- /dev/null +++ b/NMessage/MsgDataValue/StringData.cpp @@ -0,0 +1,29 @@ +#include "StringData.h" + +namespace VNOC +{ +namespace Message +{ + +void StringData::SetValue(IN const std::string& Value) +{ + m_Value = Value; +} + +MsgStatus StringData::ToStr(OUT std::string& Value) +{ + Value = m_Value; + return MsgStatus_Ok; +} + +StringData::StringData( const std::string& Value ) +{ + SetValue(Value); +} + +StringData::StringData() : m_Value("") +{ +} + +}// namespace Message +}// namespace VNOC diff --git a/NMessage/MsgDataValue/StringData.h b/NMessage/MsgDataValue/StringData.h new file mode 100644 index 00000000..947879c8 --- /dev/null +++ b/NMessage/MsgDataValue/StringData.h @@ -0,0 +1,30 @@ +#ifndef VNOC_I_MESSAGE_DATA_STRING +#define VNOC_I_MESSAGE_DATA_STRING + +#include "MsgDataValue.h" + +namespace VNOC +{ +namespace Message +{ + +class StringData : public MsgDataValue +{ +public: + virtual ~StringData(){} + StringData(); + StringData(const std::string& Value); + + virtual MsgStatus ToStr(OUT std::string& Value); + + void SetValue(IN const std::string& Value); + +private: + DISALLOW_ASSIGN(StringData); + std::string m_Value; +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/NMSG_ACL.h b/NMessage/NMSG_ACL.h new file mode 100644 index 00000000..c50f21b9 --- /dev/null +++ b/NMessage/NMSG_ACL.h @@ -0,0 +1,49 @@ +#ifndef VNOC_C_MESSAGE_NMSG_ACL +#define VNOC_C_MESSAGE_NMSG_ACL +#include "MessageDef.h" +#include "CMessage.h" +#include "MsgDataValue/StringData.h" +#include "MsgDataValue/NumData.hpp" +//测试中文 +///> Generate by MessageProduse. DO NOT EDIT! + +namespace VNOC +{ +namespace Message +{ + +class NMSG_ACL : public CMessage +{ +public: + NMSG_ACL() + { + InitializeMessage("NMSG_ACL"); + } + + NMSG_ACL(const CMessage& Msg) + { + CMessage::Copy(Msg, "NMSG_ACL"); + } + + virtual ~NMSG_ACL(){} + + MsgStatus SetRoomList(const std::vector& Value) + { + ArrayData* ValueArr = new ArrayData; + ValueArr->Push(Value); + return WriteArr("RoomList", ValueArr); + } + + MsgStatus GetRoomList(std::vector& Value) + { + ArrayData* pReadValueArr = NULL; + ReadArr("RoomList", pReadValueArr); + pReadValueArr->GetArr_vec(Value); + return MsgStatus_Ok; + } +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/ParserMessageXML.cpp b/NMessage/ParserMessageXML.cpp new file mode 100644 index 00000000..0307f446 --- /dev/null +++ b/NMessage/ParserMessageXML.cpp @@ -0,0 +1,149 @@ +#include "ParserMessageXML.h" +#include "../ThirdLibs/TinyXML/tinyxml.h" +#include + +namespace VNOC +{ +namespace Message +{ + +ParserMessageXML::ParserMessageXML() +{ + +} + +ParserMessageXML::~ParserMessageXML() +{ + +} + +ParserMessageXML& ParserMessageXML::Instance() +{ + static ParserMessageXML inst; + return inst; +} + +MsgStatus ParserMessageXML::LoadFile(const char* strPath) +{ + if (strPath == NULL) + { + return MsgStatus_Err; + } + TiXmlDocument xmlTiny; + if(xmlTiny.LoadFile(strPath)) + { + return _Parser(xmlTiny) ? MsgStatus_Ok: MsgStatus_Err; + } + return MsgStatus_Err; +} + +bool ParserMessageXML::_Parser(TiXmlDocument& xmlTiny) +{ + TiXmlElement* msg = xmlTiny.RootElement(); + std::string sRootName = msg->Value(); + if (sRootName != MsgDataObject_XML_Root) + { + return false; + } + TiXmlNode* msgNode = xmlTiny.FirstChild(MsgDataObject_XML_Root); + if (msgNode == NULL) + { + return false; + } + for (msg = msgNode->FirstChildElement(); + msg != NULL; + msg = msg->NextSiblingElement()) + { + if (strcmp(msg->Value(),MsgDataObject_XML_Msg) == 0) + { + const char* pName = msg->Attribute(MsgDataObject_XML_Name); + const char* pId = msg->Attribute(MsgDataObject_XML_Id); + if (!pName || !pId) + { + continue; + } + int nId = atoi(pId); + XMLObject objXML(pName, nId); + m_MsgIdList[std::string(pName)] = nId; + TiXmlNode* tmpNode = msg->FirstChild(); + if (tmpNode == NULL) + { + continue; + } + + TiXmlElement* msgItem = NULL; + for (msgItem = tmpNode->ToElement(); + msgItem != NULL; + msgItem = msgItem->NextSiblingElement()) + { + XMLItem ItemXML; + if (msgItem->Attribute(MsgDataObject_XML_MType) != NULL) + { + std::string strMType = msgItem->Attribute(MsgDataObject_XML_MType); + if (strMType == MsgDataMType_XML_Data) + { + ItemXML.SetMType(MsgDataMType_Data); + } + if (strMType == MsgDataMType_XML_List) + { + ItemXML.SetMType(MsgDataMType_List); + } + } + if (msgItem->Attribute(MsgDataObject_XML_Name) != NULL) + { + ItemXML.SetName(msgItem->Attribute(MsgDataObject_XML_Name)); + } + if (msgItem->Attribute(MsgDataObject_XML_Type) != NULL ) + { + std::string strType = msgItem->Attribute(MsgDataObject_XML_Type); + if (strType == MsgDataType_XML_Uint32) + { + ItemXML.SetType(MsgDataType_Uint32); + } + else if (strType == MsgDataType_XML_Uint16) + { + ItemXML.SetType(MsgDataType_Uint16); + } + else if (strType == MsgDataType_XML_Uint8) + { + ItemXML.SetType(MsgDataType_Uint8); + } + else if (strType == MsgDataType_XML_String) + { + ItemXML.SetType(MsgDataType_String); + } + } + objXML.SetItem(ItemXML.GetName(), ItemXML); + } + m_MsgObjectList.insert(std::make_pair(objXML.GetId(), objXML)); + } + } + return true; +} + +XMLObject* ParserMessageXML::GetMsgObject(const std::string& strName) +{ + auto itFind = m_MsgIdList.find(strName); + if (itFind != m_MsgIdList.end()) + { + auto Itr = m_MsgObjectList.find(itFind->second); + if (Itr != m_MsgObjectList.end()) + { + return &(Itr->second); + } + } + return 0; +} + +XMLObject* ParserMessageXML::GetMsgObject(int nId) +{ + auto Itr = m_MsgObjectList.find(nId); + if (Itr != m_MsgObjectList.end()) + { + return &(Itr->second); + } + return 0; +} + +}// namespace Message +}// namespace VNOC \ No newline at end of file diff --git a/NMessage/ParserMessageXML.h b/NMessage/ParserMessageXML.h new file mode 100644 index 00000000..b0861c9e --- /dev/null +++ b/NMessage/ParserMessageXML.h @@ -0,0 +1,50 @@ +#ifndef VNOC_C_MESSAGE_PARSERXML +#define VNOC_C_MESSAGE_PARSERXML + +#include +#include +#include +#include +#include "MessageDef.h" +#include "XMLObject.h" + +class TiXmlDocument; + +namespace VNOC +{ +namespace Message +{ + +class ParserMessageXML +{ +public: + static ParserMessageXML& Instance(); + + virtual ~ParserMessageXML(); + + MsgStatus LoadFile(const char* strPath); + + XMLObject* GetMsgObject(const std::string& strName); + XMLObject* GetMsgObject(int nId); + + std::map::iterator ObjectBegin() + { + return m_MsgObjectList.begin(); + } + std::map::iterator ObjectEnd() + { + return m_MsgObjectList.end(); + } + +private: + ParserMessageXML(); + bool _Parser(TiXmlDocument& xmlTiny); + + std::map m_MsgIdList; + std::map m_MsgObjectList; +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/XMLObject.cpp b/NMessage/XMLObject.cpp new file mode 100644 index 00000000..75bc35e4 --- /dev/null +++ b/NMessage/XMLObject.cpp @@ -0,0 +1,89 @@ +#include "XMLObject.h" + +namespace VNOC +{ +namespace Message +{ + +void XMLItem::SetMType(MsgDataMType strValue) +{ + m_strMType = strValue; +} + +void XMLItem::SetType(MsgDataType strValue) +{ + m_strType = strValue; +} + +void XMLItem::SetName(const std::string& strValue) +{ + m_strName = strValue; +} + +MsgDataMType XMLItem::GetMType() +{ + return m_strMType; +} + +std::string XMLItem::GetName() +{ + return m_strName; +} + +MsgDataType XMLItem::GetType() +{ + return m_strType; +} + +XMLObject::XMLObject(const char* pName, int nId) + : m_strName(pName) + , m_Id(nId) +{ +} + +XMLObject::~XMLObject() +{ +} + +XMLObject::XMLObject(const XMLObject& obj) +{ + m_strName = obj.m_strName; + m_Id = obj.m_Id; + m_mapParamList = obj.m_mapParamList; +} + +XMLItem* XMLObject::GetItem(const std::string& strName) +{ + auto Itr = m_mapParamList.find(strName); + if (Itr != m_mapParamList.end()) + { + return &(Itr->second); + } + return 0; +} + +std::string XMLObject::GetName() +{ + return m_strName; +} + +int XMLObject::GetId() +{ + return m_Id; +} + +MsgStatus XMLObject::SetItem( + IN const std::string& strName, + IN const XMLItem& itemObject + ) +{ + if (strName.empty()) + { + return MsgStatus_Err; + } + m_mapParamList[strName] = itemObject; + return MsgStatus_Ok; +} + +}// namespace Message +}// namespace VNOC \ No newline at end of file diff --git a/NMessage/XMLObject.h b/NMessage/XMLObject.h new file mode 100644 index 00000000..f5bda5ed --- /dev/null +++ b/NMessage/XMLObject.h @@ -0,0 +1,75 @@ +#ifndef VNOC_C_MESSAGE_XMLOBJECT +#define VNOC_C_MESSAGE_XMLOBJECT + +#include +#include +#include +#include "MessageDef.h" + +namespace VNOC +{ +namespace Message +{ + +class XMLItem +{ +public: + XMLItem(){} + virtual ~XMLItem(){} + + MsgDataMType GetMType(); + + MsgDataType GetType(); + + std::string GetName(); + + void SetMType(IN MsgDataMType strValue); + + void SetType(IN MsgDataType strValue); + + void SetName(IN const std::string& strValue); + +private: + std::string m_strName; + MsgDataMType m_strMType; + MsgDataType m_strType; +}; + +class XMLObject +{ +public: + XMLObject(const char* pName, int nId); + + XMLObject(const XMLObject& obj); + + virtual ~XMLObject(); + + std::string GetName(); + + int GetId(); + + XMLItem* GetItem(const std::string& strName); + + MsgStatus SetItem( + IN const std::string& strName, + IN const XMLItem& itemObject); + + std::map::iterator ParamBegin() + { + return m_mapParamList.begin(); + } + std::map::iterator ParamEnd() + { + return m_mapParamList.end(); + } + +private: + int m_Id; + std::string m_strName; + std::map m_mapParamList; +}; + +}// namespace Message +}// namespace VNOC + +#endif \ No newline at end of file diff --git a/NMessage/msgdef.xml b/NMessage/msgdef.xml new file mode 100644 index 00000000..e59c01d5 --- /dev/null +++ b/NMessage/msgdef.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NetService/.gitignore b/NetService/.gitignore deleted file mode 100644 index e210ee7d..00000000 --- a/NetService/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ - -*.sdf \ No newline at end of file diff --git a/NetService/NewMsgdef.xml b/NetService/NewMsgdef.xml new file mode 100644 index 00000000..e59c01d5 --- /dev/null +++ b/NetService/NewMsgdef.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NetService/ServerPostBuild.bat b/NetService/ServerPostBuild.bat index ba150f91..ca696e74 100644 --- a/NetService/ServerPostBuild.bat +++ b/NetService/ServerPostBuild.bat @@ -1,14 +1,18 @@ @echo off setlocal EnableDelayedExpansion +@copy "./vnoc.conf" "./%1/vnoc.conf" + @if "%1"=="RELEASE" goto gRelease cd xcopy /e/c/y "../VisualLeakDetector/bin/win32" "Debug" > nul +xcopy /e/c/y "dll" "Debug" > nul goto gEnd :gRelease @xcopy /e/c/y "../VisualLeakDetector/bin/win32" "Release" > nul +xcopy /e/c/y "dll" "Release" > nul :gEnd @echo "Post Dispatch OK!" \ No newline at end of file diff --git a/NetService/dependencies/libmysql b/NetService/dependencies/libmysql new file mode 160000 index 00000000..6a54a0fe --- /dev/null +++ b/NetService/dependencies/libmysql @@ -0,0 +1 @@ +Subproject commit 6a54a0fe2732965dfe02c5d3b9f6c60e2179263b diff --git a/NetService/dll/libmysql.dll b/NetService/dll/libmysql.dll new file mode 100644 index 00000000..a80f347f Binary files /dev/null and b/NetService/dll/libmysql.dll differ diff --git a/NetService/dll64/libmysql.dll b/NetService/dll64/libmysql.dll new file mode 100644 index 00000000..6f2d2c20 Binary files /dev/null and b/NetService/dll64/libmysql.dll differ diff --git a/NetService/include/Mysql/atomic/gcc_builtins.h b/NetService/include/Mysql/atomic/gcc_builtins.h new file mode 100644 index 00000000..4600a0ef --- /dev/null +++ b/NetService/include/Mysql/atomic/gcc_builtins.h @@ -0,0 +1,38 @@ +/* Copyright (C) 2008 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#define MY_ATOMIC_MODE "atomic_builtins" + +#define make_atomic_add_body(S) \ + v= __sync_fetch_and_add(a, v); +#define make_atomic_swap_body(S) \ + v= __sync_lock_test_and_set(a, v); +#define make_atomic_cas_body(S) \ + int ## S sav; \ + sav= __sync_val_compare_and_swap(a, *cmp, set); \ + if (!(ret= (sav == *cmp))) *cmp= sav; + +#ifdef MY_ATOMIC_MODE_DUMMY +#define make_atomic_load_body(S) ret= *a +#define make_atomic_store_body(S) *a= v +#define MY_ATOMIC_MODE "gcc-builtins-up" + +#else +#define MY_ATOMIC_MODE "gcc-builtins-smp" +#define make_atomic_load_body(S) \ + ret= __sync_fetch_and_or(a, 0); +#define make_atomic_store_body(S) \ + (void) __sync_lock_test_and_set(a, v); +#endif diff --git a/NetService/include/Mysql/atomic/generic-msvc.h b/NetService/include/Mysql/atomic/generic-msvc.h new file mode 100644 index 00000000..a8601e99 --- /dev/null +++ b/NetService/include/Mysql/atomic/generic-msvc.h @@ -0,0 +1,115 @@ +/* Copyright (C) 2006-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _atomic_h_cleanup_ +#define _atomic_h_cleanup_ "atomic/generic-msvc.h" + +/* + We don't implement anything specific for MY_ATOMIC_MODE_DUMMY, always use + intrinsics. + 8 and 16-bit atomics are not implemented, but it can be done if necessary. +*/ + +/* + x86 compilers (both VS2003 or VS2005) never use instrinsics, but generate + function calls to kernel32 instead, even in the optimized build. + We force intrinsics as described in MSDN documentation for + _InterlockedCompareExchange. +*/ +#ifdef _M_IX86 + +#if (_MSC_VER >= 1500) +#include +#else +C_MODE_START +/*Visual Studio 2003 and earlier do not have prototypes for atomic intrinsics*/ +LONG _InterlockedExchange (LONG volatile *Target,LONG Value); +LONG _InterlockedCompareExchange (LONG volatile *Target, LONG Value, LONG Comp); +LONG _InterlockedExchangeAdd (LONG volatile *Addend, LONG Value); +C_MODE_END + +#pragma intrinsic(_InterlockedExchangeAdd) +#pragma intrinsic(_InterlockedCompareExchange) +#pragma intrinsic(_InterlockedExchange) +#endif + +#define InterlockedExchange _InterlockedExchange +#define InterlockedExchangeAdd _InterlockedExchangeAdd +#define InterlockedCompareExchange _InterlockedCompareExchange +/* + No need to do something special for InterlockedCompareExchangePointer + as it is a #define to InterlockedCompareExchange. The same applies to + InterlockedExchangePointer. +*/ +#endif /*_M_IX86*/ + +#define MY_ATOMIC_MODE "msvc-intrinsics" +#define IL_EXCHG_ADD32(X,Y) InterlockedExchangeAdd((volatile LONG *)(X),(Y)) +#define IL_COMP_EXCHG32(X,Y,Z) InterlockedCompareExchange((volatile LONG *)(X),(Y),(Z)) +#define IL_COMP_EXCHGptr InterlockedCompareExchangePointer +#define IL_EXCHG32(X,Y) InterlockedExchange((volatile LONG *)(X),(Y)) +#define IL_EXCHGptr InterlockedExchangePointer +#define make_atomic_add_body(S) \ + v= IL_EXCHG_ADD ## S (a, v) +#define make_atomic_cas_body(S) \ + int ## S initial_cmp= *cmp; \ + int ## S initial_a= IL_COMP_EXCHG ## S (a, set, initial_cmp); \ + if (!(ret= (initial_a == initial_cmp))) *cmp= initial_a; +#define make_atomic_swap_body(S) \ + v= IL_EXCHG ## S (a, v) +#define make_atomic_load_body(S) \ + ret= 0; /* avoid compiler warning */ \ + ret= IL_COMP_EXCHG ## S (a, ret, ret); + +/* + my_yield_processor (equivalent of x86 PAUSE instruction) should be used + to improve performance on hyperthreaded CPUs. Intel recommends to use it in + spin loops also on non-HT machines to reduce power consumption (see e.g + http://softwarecommunity.intel.com/articles/eng/2004.htm) + + Running benchmarks for spinlocks implemented with InterlockedCompareExchange + and YieldProcessor shows that much better performance is achieved by calling + YieldProcessor in a loop - that is, yielding longer. On Intel boxes setting + loop count in the range 200-300 brought best results. + */ +#ifndef YIELD_LOOPS +#define YIELD_LOOPS 200 +#endif + +static __inline int my_yield_processor() +{ + int i; + for(i=0; irw) +#define my_atomic_rwlock_init(name) pthread_mutex_init(& (name)->rw, 0) +#define my_atomic_rwlock_rdlock(name) pthread_mutex_lock(& (name)->rw) +#define my_atomic_rwlock_wrlock(name) pthread_mutex_lock(& (name)->rw) +#define my_atomic_rwlock_rdunlock(name) pthread_mutex_unlock(& (name)->rw) +#define my_atomic_rwlock_wrunlock(name) pthread_mutex_unlock(& (name)->rw) +#define MY_ATOMIC_MODE "mutex" +#ifndef MY_ATOMIC_MODE_RWLOCKS +#define MY_ATOMIC_MODE_RWLOCKS 1 +#endif +#endif + +#define make_atomic_add_body(S) int ## S sav; sav= *a; *a+= v; v=sav; +#define make_atomic_fas_body(S) int ## S sav; sav= *a; *a= v; v=sav; +#define make_atomic_cas_body(S) if ((ret= (*a == *cmp))) *a= set; else *cmp=*a; +#define make_atomic_load_body(S) ret= *a; +#define make_atomic_store_body(S) *a= v; + diff --git a/NetService/include/Mysql/atomic/x86-gcc.h b/NetService/include/Mysql/atomic/x86-gcc.h new file mode 100644 index 00000000..5a34bc22 --- /dev/null +++ b/NetService/include/Mysql/atomic/x86-gcc.h @@ -0,0 +1,69 @@ +/* Copyright (C) 2006 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + XXX 64-bit atomic operations can be implemented using + cmpxchg8b, if necessary. Though I've heard that not all 64-bit + architectures support double-word (128-bit) cas. +*/ + +#ifdef __x86_64__ +# ifdef MY_ATOMIC_NO_XADD +# define MY_ATOMIC_MODE "gcc-amd64" LOCK_prefix "-no-xadd" +# else +# define MY_ATOMIC_MODE "gcc-amd64" LOCK_prefix +# endif +#else +# ifdef MY_ATOMIC_NO_XADD +# define MY_ATOMIC_MODE "gcc-x86" LOCK_prefix "-no-xadd" +# else +# define MY_ATOMIC_MODE "gcc-x86" LOCK_prefix +# endif +#endif + +/* fix -ansi errors while maintaining readability */ +#ifndef asm +#define asm __asm__ +#endif + +#ifndef MY_ATOMIC_NO_XADD +#define make_atomic_add_body(S) \ + asm volatile (LOCK_prefix "; xadd %0, %1;" : "+r" (v) , "+m" (*a)) +#endif +#define make_atomic_fas_body(S) \ + asm volatile ("xchg %0, %1;" : "+r" (v) , "+m" (*a)) +#define make_atomic_cas_body(S) \ + asm volatile (LOCK_prefix "; cmpxchg %3, %0; setz %2;" \ + : "+m" (*a), "+a" (*cmp), "=q" (ret): "r" (set)) + +#ifdef MY_ATOMIC_MODE_DUMMY +#define make_atomic_load_body(S) ret=*a +#define make_atomic_store_body(S) *a=v +#else +/* + Actually 32-bit reads/writes are always atomic on x86 + But we add LOCK_prefix here anyway to force memory barriers +*/ +#define make_atomic_load_body(S) \ + ret=0; \ + asm volatile (LOCK_prefix "; cmpxchg %2, %0" \ + : "+m" (*a), "+a" (ret): "r" (ret)) +#define make_atomic_store_body(S) \ + asm volatile ("; xchg %0, %1;" : "+m" (*a), "+r" (v)) +#endif + +/* TODO test on intel whether the below helps. on AMD it makes no difference */ +//#define LF_BACKOFF ({asm volatile ("rep; nop"); 1; }) + diff --git a/NetService/include/Mysql/base64.h b/NetService/include/Mysql/base64.h new file mode 100644 index 00000000..155d6691 --- /dev/null +++ b/NetService/include/Mysql/base64.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2003 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef __BASE64_H_INCLUDED__ +#define __BASE64_H_INCLUDED__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + Calculate how much memory needed for dst of base64_encode() +*/ +int my_base64_needed_encoded_length(int length_of_data); + +/* + Calculate how much memory needed for dst of base64_decode() +*/ +int my_base64_needed_decoded_length(int length_of_encoded_data); + + +/* + Encode data as a base64 string +*/ +int my_base64_encode(const void *src, size_t src_len, char *dst); + +/* + Decode a base64 string into data +*/ +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr); + + +#ifdef __cplusplus +} +#endif +#endif /* !__BASE64_H_INCLUDED__ */ diff --git a/NetService/include/Mysql/config-win.h b/NetService/include/Mysql/config-win.h new file mode 100644 index 00000000..94577211 --- /dev/null +++ b/NetService/include/Mysql/config-win.h @@ -0,0 +1,392 @@ +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Defines for Win32 to make it compatible for MySQL */ + +#define BIG_TABLES + +/* + Minimal version of Windows we should be able to run on. + Currently Windows 2000 +*/ +#define _WIN32_WINNT 0x0500 + + +#if defined(_MSC_VER) && _MSC_VER >= 1400 +/* Avoid endless warnings about sprintf() etc. being unsafe. */ +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +#include +#include /* chmod() constants*/ +#include +#include +#include +#include +#include +#include +#include /* getpid()*/ + +#define HAVE_SMEM 1 + +#if defined(_WIN64) || defined(WIN64) +#define SYSTEM_TYPE "Win64" +#elif defined(_WIN32) || defined(WIN32) +#define SYSTEM_TYPE "Win32" +#else +#define SYSTEM_TYPE "Windows" +#endif + +#if defined(_M_IA64) +#define MACHINE_TYPE "ia64" +#elif defined(_M_IX86) +#define MACHINE_TYPE "ia32" +#elif defined(_M_ALPHA) +#define MACHINE_TYPE "axp" +#else +#define MACHINE_TYPE "unknown" /* Define to machine type name */ +#endif + +#if !(defined(_WIN64) || defined(WIN64)) +#ifndef _WIN32 +#define _WIN32 /* Compatible with old source */ +#endif +#ifndef __WIN32__ +#define __WIN32__ +#endif +#endif /* _WIN64 */ +#ifndef __WIN__ +#define __WIN__ /* To make it easier in VC++ */ +#endif + +#ifndef MAX_INDEXES +#define MAX_INDEXES 64 +#endif + +/* File and lock constants */ +#ifdef __BORLANDC__ +#define F_RDLCK LK_NBLCK /* read lock */ +#define F_WRLCK LK_NBRLCK /* write lock */ +#define F_UNLCK LK_UNLCK /* remove lock(s) */ +#else +#define F_RDLCK _LK_NBLCK /* read lock */ +#define F_WRLCK _LK_NBRLCK /* write lock */ +#define F_UNLCK _LK_UNLCK /* remove lock(s) */ +#endif + +#define F_EXCLUSIVE 1 /* We have only exclusive locking */ +#define F_TO_EOF (INT_MAX32/2) /* size for lock of all file */ +#define F_OK 0 /* parameter to access() */ +#define W_OK 2 + +#define S_IROTH S_IREAD /* for my_lib */ + +/* for MY_S_ISFIFO() macro from my_lib */ +#if defined (_S_IFIFO) && !defined (S_IFIFO) +#define S_IFIFO _S_IFIFO +#endif + +/* Winsock2 constant (Vista SDK and later)*/ +#define IPPROTO_IPV6 41 +#ifndef IPV6_V6ONLY +#define IPV6_V6ONLY 27 +#endif + +/* + Constants used by chmod. Note, that group/others is ignored + - because unsupported by Windows due to different access control model. +*/ +#define S_IRWXU S_IREAD|S_IWRITE +#define S_IRWXG 0 +#define S_IRWXO 0 +typedef int mode_t; + +#ifdef __BORLANDC__ +#define FILE_BINARY O_BINARY /* my_fopen in binary mode */ +#define O_TEMPORARY 0 +#define O_SHORT_LIVED 0 +#define SH_DENYNO _SH_DENYNO +#else +#define O_BINARY _O_BINARY /* compability with older style names */ +#define FILE_BINARY _O_BINARY /* my_fopen in binary mode */ +#define O_TEMPORARY _O_TEMPORARY +#define O_SHORT_LIVED _O_SHORT_LIVED +#define SH_DENYNO _SH_DENYNO +#endif +#define NO_OPEN_3 /* For my_create() */ + +#define SIGQUIT SIGTERM /* No SIGQUIT */ + +#undef _REENTRANT /* Crashes something for win32 */ +#undef SAFE_MUTEX /* Can't be used on windows */ + +#define LONGLONG_MIN 0x8000000000000000LL +#define LONGLONG_MAX 0x7FFFFFFFFFFFFFFFLL +#define ULONGLONG_MAX 0xFFFFFFFFFFFFFFFFULL + +/* Type information */ + +#if !defined(HAVE_UINT) +#undef HAVE_UINT +#define HAVE_UINT +typedef unsigned short ushort; +typedef unsigned int uint; +#endif /* !defined(HAVE_UINT) */ + +typedef unsigned __int64 ulonglong; /* Microsofts 64 bit types */ +typedef __int64 longlong; +#ifndef HAVE_SIGSET_T +typedef int sigset_t; +#endif +#define longlong_defined +/* + off_t should not be __int64 because of conflicts in header files; + Use my_off_t or os_off_t instead +*/ +#ifndef HAVE_OFF_T +typedef long off_t; +#endif +typedef __int64 os_off_t; +#ifdef _WIN64 +typedef UINT_PTR rf_SetTimer; +#else +typedef uint rf_SetTimer; +#endif + +#ifndef HAVE_SIZE_T +#ifndef _SIZE_T_DEFINED +typedef SIZE_T size_t; +#define _SIZE_T_DEFINED +#endif +#endif + +#ifndef HAVE_SSIZE_T +#ifndef _SSIZE_T_DEFINED +typedef SSIZE_T ssize_t; +#define _SSIZE_T_DEFINED +#endif +#endif + +#define Socket_defined +#define my_socket SOCKET +#define SIGPIPE SIGINT +#define RETQSORTTYPE void +#define QSORT_TYPE_IS_VOID +#define SOCKET_SIZE_TYPE int +#define my_socket_defined +#define byte_defined +#define HUGE_PTR +#define STDCALL __stdcall /* Used by libmysql.dll */ +#define isnan(X) _isnan(X) +#define finite(X) _finite(X) + +#ifndef UNDEF_THREAD_HACK +#define THREAD +#endif +#define VOID_SIGHANDLER +#define SIZEOF_CHAR 1 +#define SIZEOF_INT 4 +#define SIZEOF_LONG 4 +#define SIZEOF_LONG_LONG 8 +#define SIZEOF_OFF_T 8 +#ifdef _WIN64 +#define SIZEOF_CHARP 8 +#else +#define SIZEOF_CHARP 4 +#endif +#define HAVE_BROKEN_NETINET_INCLUDES +#ifdef _WIN32 +#define HAVE_NAMED_PIPE /* We can only create pipes on NT */ +#endif + +/* ERROR is defined in wingdi.h */ +#undef ERROR + +/* We need to close files to break connections on shutdown */ +#ifndef SIGNAL_WITH_VIO_CLOSE +#define SIGNAL_WITH_VIO_CLOSE +#endif + +/* All windows servers should support .sym files */ +#undef USE_SYMDIR +#define USE_SYMDIR + +/* If LOAD DATA LOCAL INFILE should be enabled by default */ +#define ENABLED_LOCAL_INFILE 1 + +/* If query profiling should be enabled by default */ +#define ENABLED_PROFILING 1 + +/* Convert some simple functions to Posix */ + +#define my_sigset(A,B) signal((A),(B)) +#define finite(A) _finite(A) +#define sleep(A) Sleep((A)*1000) +#define popen(A,B) _popen((A),(B)) +#define pclose(A) _pclose(A) + +#ifndef __BORLANDC__ +#define access(A,B) _access(A,B) +#endif + +#if !defined(__cplusplus) +#define inline __inline +#endif /* __cplusplus */ + +#ifdef _WIN64 +#define ulonglong2double(A) ((double) (ulonglong) (A)) +#define my_off_t2double(A) ((double) (my_off_t) (A)) + +#else +inline double ulonglong2double(ulonglong value) +{ + longlong nr=(longlong) value; + if (nr >= 0) + return (double) nr; + return (18446744073709551616.0 + (double) nr); +} +#define my_off_t2double(A) ulonglong2double(A) +#endif /* _WIN64 */ + +inline ulonglong double2ulonglong(double d) +{ + double t= d - (double) 0x8000000000000000ULL; + + if (t >= 0) + return ((ulonglong) t) + 0x8000000000000000ULL; + return (ulonglong) d; +} + +#if SIZEOF_OFF_T > 4 +#define lseek(A,B,C) _lseeki64((A),(longlong) (B),(C)) +#define tell(A) _telli64(A) +#endif + +#define STACK_DIRECTION -1 + +/* Difference between GetSystemTimeAsFileTime() and now() */ +#define OFFSET_TO_EPOCH 116444736000000000ULL + +#define HAVE_PERROR +#define HAVE_VFPRINT +#define HAVE_RENAME /* Have rename() as function */ +#define HAVE_BINARY_STREAMS /* Have "b" flag in streams */ +#define HAVE_LONG_JMP /* Have long jump function */ +#define HAVE_LOCKING /* have locking() call */ +#define HAVE_ERRNO_AS_DEFINE /* errno is a define */ +#define HAVE_STDLIB /* everything is include in this file */ +#define HAVE_MEMCPY +#define HAVE_MEMMOVE +#define HAVE_GETCWD +#define HAVE_TELL +#define HAVE_TZNAME +#define HAVE_PUTENV +#define HAVE_SELECT +#define HAVE_SETLOCALE +#define HAVE_SOCKET /* Giangi */ +#define HAVE_FLOAT_H +#define HAVE_LIMITS_H +#define HAVE_STDDEF_H +#define NO_FCNTL_NONBLOCK /* No FCNTL */ +#define HAVE_ALLOCA +#define HAVE_STRPBRK +#define HAVE_STRSTR +#define HAVE_COMPRESS +#define HAVE_CREATESEMAPHORE +#define HAVE_ISNAN +#define HAVE_FINITE +#define HAVE_QUERY_CACHE +#define SPRINTF_RETURNS_INT +#define HAVE_SETFILEPOINTER +#define HAVE_VIO_READ_BUFF +#if defined(_MSC_VER) && _MSC_VER >= 1400 +/* strnlen() appeared in Studio 2005 */ +#define HAVE_STRNLEN +#endif +#define HAVE_WINSOCK2 + +#define strcasecmp stricmp +#define strncasecmp strnicmp + +#ifndef _WIN32 +#undef FILE_SHARE_DELETE +#define FILE_SHARE_DELETE 0 /* Not implemented on Win 98/ME */ +#endif + +#ifdef NOT_USED +#define HAVE_SNPRINTF /* Gave link error */ +#define _snprintf snprintf +#endif + +#ifdef _MSC_VER +#define HAVE_LDIV /* The optimizer breaks in zortech for ldiv */ +#define HAVE_ANSI_INCLUDE +#define HAVE_SYS_UTIME_H +#define HAVE_STRTOUL +#endif +#define my_reinterpret_cast(A) reinterpret_cast +#define my_const_cast(A) const_cast + + +/* MYSQL OPTIONS */ + +#ifdef _CUSTOMCONFIG_ +#include +#else +#define DEFAULT_MYSQL_HOME "c:\\mysql" +#define DATADIR "c:\\mysql\\data" +#define PACKAGE "mysql" +#define DEFAULT_BASEDIR "C:\\" +#define SHAREDIR "share" +#define DEFAULT_CHARSET_HOME "C:/mysql/" +#endif +#ifndef DEFAULT_HOME_ENV +#define DEFAULT_HOME_ENV MYSQL_HOME +#endif +#ifndef DEFAULT_GROUP_SUFFIX_ENV +#define DEFAULT_GROUP_SUFFIX_ENV MYSQL_GROUP_SUFFIX +#endif + +/* File name handling */ + +#define FN_LIBCHAR '\\' +#define FN_ROOTDIR "\\" +#define FN_DEVCHAR ':' +#define FN_NETWORK_DRIVES /* Uses \\ to indicate network drives */ +#define FN_NO_CASE_SENCE /* Files are not case-sensitive */ +#define OS_FILE_LIMIT UINT_MAX /* No limit*/ + +#define DO_NOT_REMOVE_THREAD_WRAPPERS +#define thread_safe_increment(V,L) InterlockedIncrement((long*) &(V)) +#define thread_safe_decrement(V,L) InterlockedDecrement((long*) &(V)) +/* The following is only used for statistics, so it should be good enough */ +#ifdef _WIN32 /* This should also work on Win98 but .. */ +#define thread_safe_add(V,C,L) InterlockedExchangeAdd((long*) &(V),(C)) +#define thread_safe_sub(V,C,L) InterlockedExchangeAdd((long*) &(V),-(long) (C)) +#endif + +#define shared_memory_buffer_length 16000 +#define default_shared_memory_base_name "MYSQL" + +#define HAVE_SPATIAL 1 +#define HAVE_RTREE_KEYS 1 + +#define HAVE_OPENSSL 1 +#define HAVE_YASSL 1 + +#define COMMUNITY_SERVER 1 +#define ENABLED_PROFILING 1 + +#define HAVE_BOOL 1 diff --git a/NetService/include/Mysql/decimal.h b/NetService/include/Mysql/decimal.h new file mode 100644 index 00000000..530ed9e1 --- /dev/null +++ b/NetService/include/Mysql/decimal.h @@ -0,0 +1,107 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _decimal_h +#define _decimal_h + +typedef enum +{TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR} + decimal_round_mode; +typedef int32 decimal_digit_t; + +typedef struct st_decimal_t { + int intg, frac, len; + my_bool sign; + decimal_digit_t *buf; +} decimal_t; + +int internal_str2dec(const char *from, decimal_t *to, char **end, + my_bool fixed); +int decimal2string(decimal_t *from, char *to, int *to_len, + int fixed_precision, int fixed_decimals, + char filler); +int decimal2ulonglong(decimal_t *from, ulonglong *to); +int ulonglong2decimal(ulonglong from, decimal_t *to); +int decimal2longlong(decimal_t *from, longlong *to); +int longlong2decimal(longlong from, decimal_t *to); +int decimal2double(decimal_t *from, double *to); +int double2decimal(double from, decimal_t *to); +int decimal_actual_fraction(decimal_t *from); +int decimal2bin(decimal_t *from, uchar *to, int precision, int scale); +int bin2decimal(const uchar *from, decimal_t *to, int precision, int scale); + +int decimal_size(int precision, int scale); +int decimal_bin_size(int precision, int scale); +int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, + int param); + +int decimal_intg(decimal_t *from); +int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to); +int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to); +int decimal_cmp(decimal_t *from1, decimal_t *from2); +int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to); +int decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, + int scale_incr); +int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to); +int decimal_round(decimal_t *from, decimal_t *to, int new_scale, + decimal_round_mode mode); +int decimal_is_zero(decimal_t *from); +void max_decimal(int precision, int frac, decimal_t *to); + +#define string2decimal(A,B,C) internal_str2dec((A), (B), (C), 0) +#define string2decimal_fixed(A,B,C) internal_str2dec((A), (B), (C), 1) + +/* set a decimal_t to zero */ + +#define decimal_make_zero(dec) do { \ + (dec)->buf[0]=0; \ + (dec)->intg=1; \ + (dec)->frac=0; \ + (dec)->sign=0; \ + } while(0) + +/* + returns the length of the buffer to hold string representation + of the decimal (including decimal dot, possible sign and \0) +*/ + +#define decimal_string_size(dec) (((dec)->intg ? (dec)->intg : 1) + \ + (dec)->frac + ((dec)->frac > 0) + 2) + +/* negate a decimal */ +#define decimal_neg(dec) do { (dec)->sign^=1; } while(0) + +/* + conventions: + + decimal_smth() == 0 -- everything's ok + decimal_smth() <= 1 -- result is usable, but precision loss is possible + decimal_smth() <= 2 -- result can be unusable, most significant digits + could've been lost + decimal_smth() > 2 -- no result was generated +*/ + +#define E_DEC_OK 0 +#define E_DEC_TRUNCATED 1 +#define E_DEC_OVERFLOW 2 +#define E_DEC_DIV_ZERO 4 +#define E_DEC_BAD_NUM 8 +#define E_DEC_OOM 16 + +#define E_DEC_ERROR 31 +#define E_DEC_FATAL_ERROR 30 + +#endif + diff --git a/NetService/include/Mysql/errmsg.h b/NetService/include/Mysql/errmsg.h new file mode 100644 index 00000000..92d70abb --- /dev/null +++ b/NetService/include/Mysql/errmsg.h @@ -0,0 +1,103 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Error messages for MySQL clients */ +/* (Error messages for the daemon are in sql/share/errmsg.txt) */ + +#ifdef __cplusplus +extern "C" { +#endif +void init_client_errs(void); +void finish_client_errs(void); +extern const char *client_errors[]; /* Error messages */ +#ifdef __cplusplus +} +#endif + +#define CR_MIN_ERROR 2000 /* For easier client code */ +#define CR_MAX_ERROR 2999 +#if !defined(ER) +#define ER(X) client_errors[(X)-CR_MIN_ERROR] +#endif +#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */ + +/* Do not add error numbers before CR_ERROR_FIRST. */ +/* If necessary to add lower numbers, change CR_ERROR_FIRST accordingly. */ +#define CR_ERROR_FIRST 2000 /*Copy first error nr.*/ +#define CR_UNKNOWN_ERROR 2000 +#define CR_SOCKET_CREATE_ERROR 2001 +#define CR_CONNECTION_ERROR 2002 +#define CR_CONN_HOST_ERROR 2003 +#define CR_IPSOCK_ERROR 2004 +#define CR_UNKNOWN_HOST 2005 +#define CR_SERVER_GONE_ERROR 2006 +#define CR_VERSION_ERROR 2007 +#define CR_OUT_OF_MEMORY 2008 +#define CR_WRONG_HOST_INFO 2009 +#define CR_LOCALHOST_CONNECTION 2010 +#define CR_TCP_CONNECTION 2011 +#define CR_SERVER_HANDSHAKE_ERR 2012 +#define CR_SERVER_LOST 2013 +#define CR_COMMANDS_OUT_OF_SYNC 2014 +#define CR_NAMEDPIPE_CONNECTION 2015 +#define CR_NAMEDPIPEWAIT_ERROR 2016 +#define CR_NAMEDPIPEOPEN_ERROR 2017 +#define CR_NAMEDPIPESETSTATE_ERROR 2018 +#define CR_CANT_READ_CHARSET 2019 +#define CR_NET_PACKET_TOO_LARGE 2020 +#define CR_EMBEDDED_CONNECTION 2021 +#define CR_PROBE_SLAVE_STATUS 2022 +#define CR_PROBE_SLAVE_HOSTS 2023 +#define CR_PROBE_SLAVE_CONNECT 2024 +#define CR_PROBE_MASTER_CONNECT 2025 +#define CR_SSL_CONNECTION_ERROR 2026 +#define CR_MALFORMED_PACKET 2027 +#define CR_WRONG_LICENSE 2028 + +/* new 4.1 error codes */ +#define CR_NULL_POINTER 2029 +#define CR_NO_PREPARE_STMT 2030 +#define CR_PARAMS_NOT_BOUND 2031 +#define CR_DATA_TRUNCATED 2032 +#define CR_NO_PARAMETERS_EXISTS 2033 +#define CR_INVALID_PARAMETER_NO 2034 +#define CR_INVALID_BUFFER_USE 2035 +#define CR_UNSUPPORTED_PARAM_TYPE 2036 + +#define CR_SHARED_MEMORY_CONNECTION 2037 +#define CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR 2038 +#define CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR 2039 +#define CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR 2040 +#define CR_SHARED_MEMORY_CONNECT_MAP_ERROR 2041 +#define CR_SHARED_MEMORY_FILE_MAP_ERROR 2042 +#define CR_SHARED_MEMORY_MAP_ERROR 2043 +#define CR_SHARED_MEMORY_EVENT_ERROR 2044 +#define CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR 2045 +#define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2046 +#define CR_CONN_UNKNOW_PROTOCOL 2047 +#define CR_INVALID_CONN_HANDLE 2048 +#define CR_SECURE_AUTH 2049 +#define CR_FETCH_CANCELED 2050 +#define CR_NO_DATA 2051 +#define CR_NO_STMT_METADATA 2052 +#define CR_NO_RESULT_SET 2053 +#define CR_NOT_IMPLEMENTED 2054 +#define CR_SERVER_LOST_EXTENDED 2055 +#define CR_STMT_CLOSED 2056 +#define CR_NEW_STMT_METADATA 2057 +#define CR_ALREADY_CONNECTED 2058 +#define CR_ERROR_LAST /*Copy last error nr:*/ 2058 +/* Add error numbers before CR_ERROR_LAST and change it accordingly. */ + diff --git a/NetService/include/Mysql/hash.h b/NetService/include/Mysql/hash.h new file mode 100644 index 00000000..c1797c82 --- /dev/null +++ b/NetService/include/Mysql/hash.h @@ -0,0 +1,84 @@ +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Dynamic hashing of record with different key-length */ + +#ifndef _hash_h +#define _hash_h +#ifdef __cplusplus +extern "C" { +#endif + +/* + Overhead to store an element in hash + Can be used to approximate memory consumption for a hash + */ +#define HASH_OVERHEAD (sizeof(char*)*2) + +/* flags for hash_init */ +#define HASH_UNIQUE 1 /* hash_insert fails on duplicate key */ + +typedef uchar *(*my_hash_get_key)(const uchar *,size_t*,my_bool); +typedef void (*my_hash_free_key)(void *); +typedef my_bool (*my_hash_walk_action)(void *,void *); + +typedef struct st_hash { + size_t key_offset,key_length; /* Length of key if const length */ + size_t blength; + ulong records; + uint flags; + DYNAMIC_ARRAY array; /* Place for hash_keys */ + my_hash_get_key get_key; + void (*free)(void *); + CHARSET_INFO *charset; +} HASH; + +/* A search iterator state */ +typedef uint HASH_SEARCH_STATE; + +#define my_hash_init(A,B,C,D,E,F,G,H) \ + _my_hash_init(A,0,B,C,D,E,F,G,H CALLER_INFO) +#define my_hash_init2(A,B,C,D,E,F,G,H,I) \ + _my_hash_init(A,B,C,D,E,F,G,H,I CALLER_INFO) +my_bool _my_hash_init(HASH *hash, uint growth_size, CHARSET_INFO *charset, + ulong default_array_elements, size_t key_offset, + size_t key_length, my_hash_get_key get_key, + void (*free_element)(void*), + uint flags CALLER_INFO_PROTO); +void my_hash_free(HASH *tree); +void my_hash_reset(HASH *hash); +uchar *my_hash_element(HASH *hash, ulong idx); +uchar *my_hash_search(const HASH *info, const uchar *key, size_t length); +uchar *my_hash_first(const HASH *info, const uchar *key, size_t length, + HASH_SEARCH_STATE *state); +uchar *my_hash_next(const HASH *info, const uchar *key, size_t length, + HASH_SEARCH_STATE *state); +my_bool my_hash_insert(HASH *info, const uchar *data); +my_bool my_hash_delete(HASH *hash, uchar *record); +my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key, + size_t old_key_length); +void my_hash_replace(HASH *hash, HASH_SEARCH_STATE *state, uchar *new_row); +my_bool my_hash_check(HASH *hash); /* Only in debug library */ +my_bool my_hash_iterate(HASH *hash, my_hash_walk_action action, void *argument); + +#define my_hash_clear(H) bzero((char*) (H), sizeof(*(H))) +#define my_hash_inited(H) ((H)->array.buffer != 0) +#define my_hash_init_opt(A,B,C,D,E,F,G,H) \ + (!my_hash_inited(A) && _my_hash_init(A,0,B,C,D,E,F,G, H CALLER_INFO)) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/NetService/include/Mysql/keycache.h b/NetService/include/Mysql/keycache.h new file mode 100644 index 00000000..0375d109 --- /dev/null +++ b/NetService/include/Mysql/keycache.h @@ -0,0 +1,153 @@ +/* Copyright (C) 2003 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + @file + Key cache API +*/ + +#ifndef _keycache_h +#define _keycache_h +C_MODE_START + +/* declare structures that is used by st_key_cache */ + +struct st_block_link; +typedef struct st_block_link BLOCK_LINK; +struct st_keycache_page; +typedef struct st_keycache_page KEYCACHE_PAGE; +struct st_hash_link; +typedef struct st_hash_link HASH_LINK; + +/* info about requests in a waiting queue */ +typedef struct st_keycache_wqueue +{ + struct st_my_thread_var *last_thread; /* circular list of waiting threads */ +} KEYCACHE_WQUEUE; + +/** Callback called when any block is flushed */ +typedef int (*KEYCACHE_POST_WRITE_CALLBACK)(void *arg, const uchar *buffert, + uint length, my_off_t filepos); + +#define CHANGED_BLOCKS_HASH 128 /* must be power of 2 */ + +/* + The key cache structure + It also contains read-only statistics parameters. +*/ + +typedef struct st_key_cache +{ + my_bool key_cache_inited; + my_bool in_resize; /* true during resize operation */ + my_bool resize_in_flush; /* true during flush of resize operation */ + my_bool can_be_used; /* usage of cache for read/write is allowed */ + size_t key_cache_mem_size; /* specified size of the cache memory */ + uint key_cache_block_size; /* size of the page buffer of a cache block */ + ulong min_warm_blocks; /* min number of warm blocks; */ + ulong age_threshold; /* age threshold for hot blocks */ + ulonglong keycache_time; /* total number of block link operations */ + uint hash_entries; /* max number of entries in the hash table */ + int hash_links; /* max number of hash links */ + int hash_links_used; /* number of hash links currently used */ + int disk_blocks; /* max number of blocks in the cache */ + ulong blocks_used; /* maximum number of concurrently used blocks */ + ulong blocks_unused; /* number of currently unused blocks */ + ulong blocks_changed; /* number of currently dirty blocks */ + ulong warm_blocks; /* number of blocks in warm sub-chain */ + ulong cnt_for_resize_op; /* counter to block resize operation */ + long blocks_available; /* number of blocks available in the LRU chain */ + HASH_LINK **hash_root; /* arr. of entries into hash table buckets */ + HASH_LINK *hash_link_root; /* memory for hash table links */ + HASH_LINK *free_hash_list; /* list of free hash links */ + BLOCK_LINK *free_block_list; /* list of free blocks */ + BLOCK_LINK *block_root; /* memory for block links */ + uchar HUGE_PTR *block_mem; /* memory for block buffers */ + BLOCK_LINK *used_last; /* ptr to the last block of the LRU chain */ + BLOCK_LINK *used_ins; /* ptr to the insertion block in LRU chain */ + pthread_mutex_t cache_lock; /* to lock access to the cache structure */ + KEYCACHE_WQUEUE resize_queue; /* threads waiting during resize operation */ + /* + Waiting for a zero resize count. Using a queue for symmetry though + only one thread can wait here. + */ + KEYCACHE_WQUEUE waiting_for_resize_cnt; + KEYCACHE_WQUEUE waiting_for_hash_link; /* waiting for a free hash link */ + KEYCACHE_WQUEUE waiting_for_block; /* requests waiting for a free block */ + BLOCK_LINK *changed_blocks[CHANGED_BLOCKS_HASH]; /* hash for dirty file bl.*/ + BLOCK_LINK *file_blocks[CHANGED_BLOCKS_HASH]; /* hash for other file bl.*/ + KEYCACHE_POST_WRITE_CALLBACK post_write;/**< Called when flushing any block*/ + + /* + The following variables are and variables used to hold parameters for + initializing the key cache. + */ + + ulonglong param_buff_size; /* size the memory allocated for the cache */ + ulong param_block_size; /* size of the blocks in the key cache */ + ulong param_division_limit; /* min. percentage of warm blocks */ + ulong param_age_threshold; /* determines when hot block is downgraded */ + + /* Statistics variables. These are reset in reset_key_cache_counters(). */ + ulong global_blocks_changed; /* number of currently dirty blocks */ + ulonglong global_cache_w_requests;/* number of write requests (write hits) */ + ulonglong global_cache_write; /* number of writes from cache to files */ + ulonglong global_cache_r_requests;/* number of read requests (read hits) */ + ulonglong global_cache_read; /* number of reads from files to cache */ + + int blocks; /* max number of blocks in the cache */ + my_bool in_init; /* Set to 1 in MySQL during init/resize */ +} KEY_CACHE; + +/* The default key cache */ +extern KEY_CACHE dflt_key_cache_var, *dflt_key_cache; + +extern int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, + size_t use_mem, uint division_limit, + uint age_threshold); +extern int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, + size_t use_mem, uint division_limit, + uint age_threshold); +extern void change_key_cache_param(KEY_CACHE *keycache, uint division_limit, + uint age_threshold); +extern uchar *key_cache_read(KEY_CACHE *keycache, + File file, my_off_t filepos, int level, + uchar *buff, uint length, + uint block_length,int return_buffer); +extern int key_cache_insert(KEY_CACHE *keycache, + File file, my_off_t filepos, int level, + uchar *buff, uint length); +extern int key_cache_write(KEY_CACHE *keycache, + File file, my_off_t filepos, int level, + uchar *buff, uint length, + uint block_length, int force_write, + void *post_write_arg); +extern int flush_key_blocks(KEY_CACHE *keycache, + int file, enum flush_type type); +extern void end_key_cache(KEY_CACHE *keycache, my_bool cleanup); + +/* Functions to handle multiple key caches */ +extern my_bool multi_keycache_init(void); +extern void multi_keycache_free(void); +extern KEY_CACHE *multi_key_cache_search(uchar *key, uint length, + KEY_CACHE *def); +extern my_bool multi_key_cache_set(const uchar *key, uint length, + KEY_CACHE *key_cache); +extern void multi_key_cache_change(KEY_CACHE *old_data, + KEY_CACHE *new_data); +extern int reset_key_cache_counters(const char *name, + KEY_CACHE *key_cache); +C_MODE_END +#endif /* _keycache_h */ diff --git a/NetService/include/Mysql/lf.h b/NetService/include/Mysql/lf.h new file mode 100644 index 00000000..83358aa8 --- /dev/null +++ b/NetService/include/Mysql/lf.h @@ -0,0 +1,260 @@ +/* Copyright (C) 2007-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _lf_h +#define _lf_h + +#include + +/* + Helpers to define both func() and _func(), where + func() is a _func() protected by my_atomic_rwlock_wrlock() +*/ + +#define lock_wrap(f, t, proto_args, args, lock) \ +t _ ## f proto_args; \ +static inline t f proto_args \ +{ \ + t ret; \ + my_atomic_rwlock_wrlock(lock); \ + ret= _ ## f args; \ + my_atomic_rwlock_wrunlock(lock); \ + return ret; \ +} + +#define lock_wrap_void(f, proto_args, args, lock) \ +void _ ## f proto_args; \ +static inline void f proto_args \ +{ \ + my_atomic_rwlock_wrlock(lock); \ + _ ## f args; \ + my_atomic_rwlock_wrunlock(lock); \ +} + +#define nolock_wrap(f, t, proto_args, args) \ +t _ ## f proto_args; \ +static inline t f proto_args \ +{ \ + return _ ## f args; \ +} + +#define nolock_wrap_void(f, proto_args, args) \ +void _ ## f proto_args; \ +static inline void f proto_args \ +{ \ + _ ## f args; \ +} + +/* + wait-free dynamic array, see lf_dynarray.c + + 4 levels of 256 elements each mean 4311810304 elements in an array - it + should be enough for a while +*/ +#define LF_DYNARRAY_LEVEL_LENGTH 256 +#define LF_DYNARRAY_LEVELS 4 + +typedef struct { + void * volatile level[LF_DYNARRAY_LEVELS]; + uint size_of_element; + my_atomic_rwlock_t lock; +} LF_DYNARRAY; + +typedef int (*lf_dynarray_func)(void *, void *); + +void lf_dynarray_init(LF_DYNARRAY *array, uint element_size); +void lf_dynarray_destroy(LF_DYNARRAY *array); + +nolock_wrap(lf_dynarray_value, void *, + (LF_DYNARRAY *array, uint idx), + (array, idx)) +lock_wrap(lf_dynarray_lvalue, void *, + (LF_DYNARRAY *array, uint idx), + (array, idx), + &array->lock) +nolock_wrap(lf_dynarray_iterate, int, + (LF_DYNARRAY *array, lf_dynarray_func func, void *arg), + (array, func, arg)) + +/* + pin manager for memory allocator, lf_alloc-pin.c +*/ + +#define LF_PINBOX_PINS 4 +#define LF_PURGATORY_SIZE 10 + +typedef void lf_pinbox_free_func(void *, void *, void*); + +typedef struct { + LF_DYNARRAY pinarray; + lf_pinbox_free_func *free_func; + void *free_func_arg; + uint free_ptr_offset; + uint32 volatile pinstack_top_ver; /* this is a versioned pointer */ + uint32 volatile pins_in_array; /* number of elements in array */ +} LF_PINBOX; + +typedef struct { + void * volatile pin[LF_PINBOX_PINS]; + LF_PINBOX *pinbox; + void **stack_ends_here; + void *purgatory; + uint32 purgatory_count; + uint32 volatile link; +/* we want sizeof(LF_PINS) to be 64 to avoid false sharing */ +#if SIZEOF_INT*2+SIZEOF_CHARP*(LF_PINBOX_PINS+3) != 64 + char pad[64-sizeof(uint32)*2-sizeof(void*)*(LF_PINBOX_PINS+3)]; +#endif +} LF_PINS; + +/* + shortcut macros to do an atomic_wrlock on a structure that uses pins + (e.g. lf_hash). +*/ +#define lf_rwlock_by_pins(PINS) \ + my_atomic_rwlock_wrlock(&(PINS)->pinbox->pinarray.lock) +#define lf_rwunlock_by_pins(PINS) \ + my_atomic_rwlock_wrunlock(&(PINS)->pinbox->pinarray.lock) + +/* + compile-time assert, to require "no less than N" pins + it's enough if it'll fail on at least one compiler, so + we'll enable it on GCC only, which supports zero-length arrays. +*/ +#if defined(__GNUC__) && defined(MY_LF_EXTRA_DEBUG) +#define LF_REQUIRE_PINS(N) \ + static const char require_pins[LF_PINBOX_PINS-N] \ + __attribute__ ((unused)); \ + static const int LF_NUM_PINS_IN_THIS_FILE= N; +#define _lf_pin(PINS, PIN, ADDR) \ + ( \ + assert(PIN < LF_NUM_PINS_IN_THIS_FILE), \ + my_atomic_storeptr(&(PINS)->pin[PIN], (ADDR)) \ + ) +#else +#define LF_REQUIRE_PINS(N) +#define _lf_pin(PINS, PIN, ADDR) my_atomic_storeptr(&(PINS)->pin[PIN], (ADDR)) +#endif + +#define _lf_unpin(PINS, PIN) _lf_pin(PINS, PIN, NULL) +#define lf_pin(PINS, PIN, ADDR) \ + do { \ + lf_rwlock_by_pins(PINS); \ + _lf_pin(PINS, PIN, ADDR); \ + lf_rwunlock_by_pins(PINS); \ + } while (0) +#define lf_unpin(PINS, PIN) lf_pin(PINS, PIN, NULL) +#define _lf_assert_pin(PINS, PIN) assert((PINS)->pin[PIN] != 0) +#define _lf_assert_unpin(PINS, PIN) assert((PINS)->pin[PIN] == 0) + +void lf_pinbox_init(LF_PINBOX *pinbox, uint free_ptr_offset, + lf_pinbox_free_func *free_func, void * free_func_arg); +void lf_pinbox_destroy(LF_PINBOX *pinbox); + +lock_wrap(lf_pinbox_get_pins, LF_PINS *, + (LF_PINBOX *pinbox), + (pinbox), + &pinbox->pinarray.lock) +lock_wrap_void(lf_pinbox_put_pins, + (LF_PINS *pins), + (pins), + &pins->pinbox->pinarray.lock) +lock_wrap_void(lf_pinbox_free, + (LF_PINS *pins, void *addr), + (pins, addr), + &pins->pinbox->pinarray.lock) + +/* + memory allocator, lf_alloc-pin.c +*/ + +typedef struct st_lf_allocator { + LF_PINBOX pinbox; + uchar * volatile top; + uint element_size; + uint32 volatile mallocs; + void (*constructor)(uchar *); /* called, when an object is malloc()'ed */ + void (*destructor)(uchar *); /* called, when an object is free()'d */ +} LF_ALLOCATOR; + +void lf_alloc_init(LF_ALLOCATOR *allocator, uint size, uint free_ptr_offset); +void lf_alloc_destroy(LF_ALLOCATOR *allocator); +uint lf_alloc_pool_count(LF_ALLOCATOR *allocator); +/* + shortcut macros to access underlying pinbox functions from an LF_ALLOCATOR + see _lf_pinbox_get_pins() and _lf_pinbox_put_pins() +*/ +#define _lf_alloc_free(PINS, PTR) _lf_pinbox_free((PINS), (PTR)) +#define lf_alloc_free(PINS, PTR) lf_pinbox_free((PINS), (PTR)) +#define _lf_alloc_get_pins(A) _lf_pinbox_get_pins(&(A)->pinbox) +#define lf_alloc_get_pins(A) lf_pinbox_get_pins(&(A)->pinbox) +#define _lf_alloc_put_pins(PINS) _lf_pinbox_put_pins(PINS) +#define lf_alloc_put_pins(PINS) lf_pinbox_put_pins(PINS) +#define lf_alloc_direct_free(ALLOC, ADDR) my_free((uchar*)(ADDR), MYF(0)) + +lock_wrap(lf_alloc_new, void *, + (LF_PINS *pins), + (pins), + &pins->pinbox->pinarray.lock) + +/* + extendible hash, lf_hash.c +*/ +#include + +#define LF_HASH_UNIQUE 1 + +/* lf_hash overhead per element (that is, sizeof(LF_SLIST) */ +extern const int LF_HASH_OVERHEAD; + +typedef struct { + LF_DYNARRAY array; /* hash itself */ + LF_ALLOCATOR alloc; /* allocator for elements */ + my_hash_get_key get_key; /* see HASH */ + CHARSET_INFO *charset; /* see HASH */ + uint key_offset, key_length; /* see HASH */ + uint element_size; /* size of memcpy'ed area on insert */ + uint flags; /* LF_HASH_UNIQUE, etc */ + int32 volatile size; /* size of array */ + int32 volatile count; /* number of elements in the hash */ +} LF_HASH; + +void lf_hash_init(LF_HASH *hash, uint element_size, uint flags, + uint key_offset, uint key_length, my_hash_get_key get_key, + CHARSET_INFO *charset); +void lf_hash_destroy(LF_HASH *hash); +int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data); +void *lf_hash_search(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen); +int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen); +/* + shortcut macros to access underlying pinbox functions from an LF_HASH + see _lf_pinbox_get_pins() and _lf_pinbox_put_pins() +*/ +#define _lf_hash_get_pins(HASH) _lf_alloc_get_pins(&(HASH)->alloc) +#define lf_hash_get_pins(HASH) lf_alloc_get_pins(&(HASH)->alloc) +#define _lf_hash_put_pins(PINS) _lf_pinbox_put_pins(PINS) +#define lf_hash_put_pins(PINS) lf_pinbox_put_pins(PINS) +#define lf_hash_search_unpin(PINS) lf_unpin((PINS), 2) +/* + cleanup +*/ + +#undef lock_wrap_void +#undef lock_wrap +#undef nolock_wrap_void +#undef nolock_wrap + +#endif + diff --git a/NetService/include/Mysql/m_ctype.h b/NetService/include/Mysql/m_ctype.h new file mode 100644 index 00000000..33229a33 --- /dev/null +++ b/NetService/include/Mysql/m_ctype.h @@ -0,0 +1,654 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + A better inplementation of the UNIX ctype(3) library. + Notes: my_global.h should be included before ctype.h +*/ + +#ifndef _m_ctype_h +#define _m_ctype_h + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MY_CS_NAME_SIZE 32 +#define MY_CS_CTYPE_TABLE_SIZE 257 +#define MY_CS_TO_LOWER_TABLE_SIZE 256 +#define MY_CS_TO_UPPER_TABLE_SIZE 256 +#define MY_CS_SORT_ORDER_TABLE_SIZE 256 +#define MY_CS_TO_UNI_TABLE_SIZE 256 + +#define CHARSET_DIR "charsets/" + +#define my_wc_t ulong + +typedef struct unicase_info_st +{ + uint16 toupper; + uint16 tolower; + uint16 sort; +} MY_UNICASE_INFO; + + +extern MY_UNICASE_INFO *my_unicase_default[256]; +extern MY_UNICASE_INFO *my_unicase_turkish[256]; + +typedef struct uni_ctype_st +{ + uchar pctype; + uchar *ctype; +} MY_UNI_CTYPE; + +extern MY_UNI_CTYPE my_uni_ctype[256]; + +/* wm_wc and wc_mb return codes */ +#define MY_CS_ILSEQ 0 /* Wrong by sequence: wb_wc */ +#define MY_CS_ILUNI 0 /* Cannot encode Unicode to charset: wc_mb */ +#define MY_CS_TOOSMALL -101 /* Need at least one byte: wc_mb and mb_wc */ +#define MY_CS_TOOSMALL2 -102 /* Need at least two bytes: wc_mb and mb_wc */ +#define MY_CS_TOOSMALL3 -103 /* Need at least three bytes: wc_mb and mb_wc */ +/* These following three are currently not really used */ +#define MY_CS_TOOSMALL4 -104 /* Need at least 4 bytes: wc_mb and mb_wc */ +#define MY_CS_TOOSMALL5 -105 /* Need at least 5 bytes: wc_mb and mb_wc */ +#define MY_CS_TOOSMALL6 -106 /* Need at least 6 bytes: wc_mb and mb_wc */ +/* A helper macros for "need at least n bytes" */ +#define MY_CS_TOOSMALLN(n) (-100-(n)) + +#define MY_SEQ_INTTAIL 1 +#define MY_SEQ_SPACES 2 + + /* My charsets_list flags */ +#define MY_CS_COMPILED 1 /* compiled-in sets */ +#define MY_CS_CONFIG 2 /* sets that have a *.conf file */ +#define MY_CS_INDEX 4 /* sets listed in the Index file */ +#define MY_CS_LOADED 8 /* sets that are currently loaded */ +#define MY_CS_BINSORT 16 /* if binary sort order */ +#define MY_CS_PRIMARY 32 /* if primary collation */ +#define MY_CS_STRNXFRM 64 /* if strnxfrm is used for sort */ +#define MY_CS_UNICODE 128 /* is a charset is full unicode */ +#define MY_CS_READY 256 /* if a charset is initialized */ +#define MY_CS_AVAILABLE 512 /* If either compiled-in or loaded*/ +#define MY_CS_CSSORT 1024 /* if case sensitive sort order */ +#define MY_CS_HIDDEN 2048 /* don't display in SHOW */ +#define MY_CS_PUREASCII 4096 /* if a charset is pure ascii */ +#define MY_CS_NONASCII 8192 /* if not ASCII-compatible */ +#define MY_CHARSET_UNDEFINED 0 + +/* Character repertoire flags */ +#define MY_REPERTOIRE_ASCII 1 /* Pure ASCII U+0000..U+007F */ +#define MY_REPERTOIRE_EXTENDED 2 /* Extended characters: U+0080..U+FFFF */ +#define MY_REPERTOIRE_UNICODE30 3 /* ASCII | EXTENDED: U+0000..U+FFFF */ + +/* Flags for strxfrm */ +#define MY_STRXFRM_LEVEL1 0x00000001 /* for primary weights */ +#define MY_STRXFRM_LEVEL2 0x00000002 /* for secondary weights */ +#define MY_STRXFRM_LEVEL3 0x00000004 /* for tertiary weights */ +#define MY_STRXFRM_LEVEL4 0x00000008 /* fourth level weights */ +#define MY_STRXFRM_LEVEL5 0x00000010 /* fifth level weights */ +#define MY_STRXFRM_LEVEL6 0x00000020 /* sixth level weights */ +#define MY_STRXFRM_LEVEL_ALL 0x0000003F /* Bit OR for the above six */ +#define MY_STRXFRM_NLEVELS 6 /* Number of possible levels*/ + +#define MY_STRXFRM_PAD_WITH_SPACE 0x00000040 /* if pad result with spaces */ +#define MY_STRXFRM_PAD_TO_MAXLEN 0x00000080 /* if pad tail(for filesort) */ + +#define MY_STRXFRM_DESC_LEVEL1 0x00000100 /* if desc order for level1 */ +#define MY_STRXFRM_DESC_LEVEL2 0x00000200 /* if desc order for level2 */ +#define MY_STRXFRM_DESC_LEVEL3 0x00000300 /* if desc order for level3 */ +#define MY_STRXFRM_DESC_LEVEL4 0x00000800 /* if desc order for level4 */ +#define MY_STRXFRM_DESC_LEVEL5 0x00001000 /* if desc order for level5 */ +#define MY_STRXFRM_DESC_LEVEL6 0x00002000 /* if desc order for level6 */ +#define MY_STRXFRM_DESC_SHIFT 8 + +#define MY_STRXFRM_UNUSED_00004000 0x00004000 /* for future extensions */ +#define MY_STRXFRM_UNUSED_00008000 0x00008000 /* for future extensions */ + +#define MY_STRXFRM_REVERSE_LEVEL1 0x00010000 /* if reverse order for level1 */ +#define MY_STRXFRM_REVERSE_LEVEL2 0x00020000 /* if reverse order for level2 */ +#define MY_STRXFRM_REVERSE_LEVEL3 0x00040000 /* if reverse order for level3 */ +#define MY_STRXFRM_REVERSE_LEVEL4 0x00080000 /* if reverse order for level4 */ +#define MY_STRXFRM_REVERSE_LEVEL5 0x00100000 /* if reverse order for level5 */ +#define MY_STRXFRM_REVERSE_LEVEL6 0x00200000 /* if reverse order for level6 */ +#define MY_STRXFRM_REVERSE_SHIFT 16 + + +typedef struct my_uni_idx_st +{ + uint16 from; + uint16 to; + uchar *tab; +} MY_UNI_IDX; + +typedef struct +{ + uint beg; + uint end; + uint mb_len; +} my_match_t; + +enum my_lex_states +{ + MY_LEX_START, MY_LEX_CHAR, MY_LEX_IDENT, + MY_LEX_IDENT_SEP, MY_LEX_IDENT_START, + MY_LEX_REAL, MY_LEX_HEX_NUMBER, MY_LEX_BIN_NUMBER, + MY_LEX_CMP_OP, MY_LEX_LONG_CMP_OP, MY_LEX_STRING, MY_LEX_COMMENT, MY_LEX_END, + MY_LEX_OPERATOR_OR_IDENT, MY_LEX_NUMBER_IDENT, MY_LEX_INT_OR_REAL, + MY_LEX_REAL_OR_POINT, MY_LEX_BOOL, MY_LEX_EOL, MY_LEX_ESCAPE, + MY_LEX_LONG_COMMENT, MY_LEX_END_LONG_COMMENT, MY_LEX_SEMICOLON, + MY_LEX_SET_VAR, MY_LEX_USER_END, MY_LEX_HOSTNAME, MY_LEX_SKIP, + MY_LEX_USER_VARIABLE_DELIMITER, MY_LEX_SYSTEM_VAR, + MY_LEX_IDENT_OR_KEYWORD, + MY_LEX_IDENT_OR_HEX, MY_LEX_IDENT_OR_BIN, MY_LEX_IDENT_OR_NCHAR, + MY_LEX_STRING_OR_DELIMITER +}; + +struct charset_info_st; + + +/* See strings/CHARSET_INFO.txt for information about this structure */ +typedef struct my_collation_handler_st +{ + my_bool (*init)(struct charset_info_st *, void *(*alloc)(size_t)); + /* Collation routines */ + int (*strnncoll)(struct charset_info_st *, + const uchar *, size_t, const uchar *, size_t, my_bool); + int (*strnncollsp)(struct charset_info_st *, + const uchar *, size_t, const uchar *, size_t, + my_bool diff_if_only_endspace_difference); + size_t (*strnxfrm)(struct charset_info_st *, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags); + size_t (*strnxfrmlen)(struct charset_info_st *, size_t); + my_bool (*like_range)(struct charset_info_st *, + const char *s, size_t s_length, + pchar w_prefix, pchar w_one, pchar w_many, + size_t res_length, + char *min_str, char *max_str, + size_t *min_len, size_t *max_len); + int (*wildcmp)(struct charset_info_st *, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape,int w_one, int w_many); + + int (*strcasecmp)(struct charset_info_st *, const char *, const char *); + + uint (*instr)(struct charset_info_st *, + const char *b, size_t b_length, + const char *s, size_t s_length, + my_match_t *match, uint nmatch); + + /* Hash calculation */ + void (*hash_sort)(struct charset_info_st *cs, const uchar *key, size_t len, + ulong *nr1, ulong *nr2); + my_bool (*propagate)(struct charset_info_st *cs, const uchar *str, size_t len); +} MY_COLLATION_HANDLER; + +extern MY_COLLATION_HANDLER my_collation_mb_bin_handler; +extern MY_COLLATION_HANDLER my_collation_8bit_bin_handler; +extern MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler; +extern MY_COLLATION_HANDLER my_collation_ucs2_uca_handler; + +/* Some typedef to make it easy for C++ to make function pointers */ +typedef int (*my_charset_conv_mb_wc)(struct charset_info_st *, my_wc_t *, + const uchar *, const uchar *); +typedef int (*my_charset_conv_wc_mb)(struct charset_info_st *, my_wc_t, + uchar *, uchar *); +typedef size_t (*my_charset_conv_case)(struct charset_info_st *, + char *, size_t, char *, size_t); + + +/* See strings/CHARSET_INFO.txt about information on this structure */ +typedef struct my_charset_handler_st +{ + my_bool (*init)(struct charset_info_st *, void *(*alloc)(size_t)); + /* Multibyte routines */ + uint (*ismbchar)(struct charset_info_st *, const char *, const char *); + uint (*mbcharlen)(struct charset_info_st *, uint c); + size_t (*numchars)(struct charset_info_st *, const char *b, const char *e); + size_t (*charpos)(struct charset_info_st *, const char *b, const char *e, + size_t pos); + size_t (*well_formed_len)(struct charset_info_st *, + const char *b,const char *e, + size_t nchars, int *error); + size_t (*lengthsp)(struct charset_info_st *, const char *ptr, size_t length); + size_t (*numcells)(struct charset_info_st *, const char *b, const char *e); + + /* Unicode conversion */ + my_charset_conv_mb_wc mb_wc; + my_charset_conv_wc_mb wc_mb; + + /* CTYPE scanner */ + int (*ctype)(struct charset_info_st *cs, int *ctype, + const uchar *s, const uchar *e); + + /* Functions for case and sort conversion */ + size_t (*caseup_str)(struct charset_info_st *, char *); + size_t (*casedn_str)(struct charset_info_st *, char *); + + my_charset_conv_case caseup; + my_charset_conv_case casedn; + + /* Charset dependant snprintf() */ + size_t (*snprintf)(struct charset_info_st *, char *to, size_t n, + const char *fmt, + ...) ATTRIBUTE_FORMAT_FPTR(printf, 4, 5); + size_t (*long10_to_str)(struct charset_info_st *, char *to, size_t n, + int radix, long int val); + size_t (*longlong10_to_str)(struct charset_info_st *, char *to, size_t n, + int radix, longlong val); + + void (*fill)(struct charset_info_st *, char *to, size_t len, int fill); + + /* String-to-number conversion routines */ + long (*strntol)(struct charset_info_st *, const char *s, size_t l, + int base, char **e, int *err); + ulong (*strntoul)(struct charset_info_st *, const char *s, size_t l, + int base, char **e, int *err); + longlong (*strntoll)(struct charset_info_st *, const char *s, size_t l, + int base, char **e, int *err); + ulonglong (*strntoull)(struct charset_info_st *, const char *s, size_t l, + int base, char **e, int *err); + double (*strntod)(struct charset_info_st *, char *s, size_t l, char **e, + int *err); + longlong (*strtoll10)(struct charset_info_st *cs, + const char *nptr, char **endptr, int *error); + ulonglong (*strntoull10rnd)(struct charset_info_st *cs, + const char *str, size_t length, + int unsigned_fl, + char **endptr, int *error); + size_t (*scan)(struct charset_info_st *, const char *b, const char *e, + int sq); +} MY_CHARSET_HANDLER; + +extern MY_CHARSET_HANDLER my_charset_8bit_handler; +extern MY_CHARSET_HANDLER my_charset_ucs2_handler; + + +/* See strings/CHARSET_INFO.txt about information on this structure */ +typedef struct charset_info_st +{ + uint number; + uint primary_number; + uint binary_number; + uint state; + const char *csname; + const char *name; + const char *comment; + const char *tailoring; + uchar *ctype; + uchar *to_lower; + uchar *to_upper; + uchar *sort_order; + uint16 *contractions; + uint16 **sort_order_big; + uint16 *tab_to_uni; + MY_UNI_IDX *tab_from_uni; + MY_UNICASE_INFO **caseinfo; + uchar *state_map; + uchar *ident_map; + uint strxfrm_multiply; + uchar caseup_multiply; + uchar casedn_multiply; + uint mbminlen; + uint mbmaxlen; + uint16 min_sort_char; + uint16 max_sort_char; /* For LIKE optimization */ + uchar pad_char; + my_bool escape_with_backslash_is_dangerous; + uchar levels_for_compare; + uchar levels_for_order; + + MY_CHARSET_HANDLER *cset; + MY_COLLATION_HANDLER *coll; + +} CHARSET_INFO; +#define ILLEGAL_CHARSET_INFO_NUMBER (~0U) + + +extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_bin; +extern CHARSET_INFO my_charset_big5_chinese_ci; +extern CHARSET_INFO my_charset_big5_bin; +extern CHARSET_INFO my_charset_cp932_japanese_ci; +extern CHARSET_INFO my_charset_cp932_bin; +extern CHARSET_INFO my_charset_cp1250_czech_ci; +extern CHARSET_INFO my_charset_eucjpms_japanese_ci; +extern CHARSET_INFO my_charset_eucjpms_bin; +extern CHARSET_INFO my_charset_euckr_korean_ci; +extern CHARSET_INFO my_charset_euckr_bin; +extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_filename; +extern CHARSET_INFO my_charset_gb2312_chinese_ci; +extern CHARSET_INFO my_charset_gb2312_bin; +extern CHARSET_INFO my_charset_gbk_chinese_ci; +extern CHARSET_INFO my_charset_gbk_bin; +extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_latin1; +extern CHARSET_INFO my_charset_latin1_german2_ci; +extern CHARSET_INFO my_charset_latin1_bin; +extern CHARSET_INFO my_charset_latin2_czech_ci; +extern CHARSET_INFO my_charset_sjis_japanese_ci; +extern CHARSET_INFO my_charset_sjis_bin; +extern CHARSET_INFO my_charset_tis620_thai_ci; +extern CHARSET_INFO my_charset_tis620_bin; +extern CHARSET_INFO my_charset_ucs2_general_ci; +extern CHARSET_INFO my_charset_ucs2_bin; +extern CHARSET_INFO my_charset_ucs2_unicode_ci; +extern CHARSET_INFO my_charset_ujis_japanese_ci; +extern CHARSET_INFO my_charset_ujis_bin; +extern CHARSET_INFO my_charset_utf16_bin; +extern CHARSET_INFO my_charset_utf16_general_ci; +extern CHARSET_INFO my_charset_utf16_unicode_ci; +extern CHARSET_INFO my_charset_utf32_bin; +extern CHARSET_INFO my_charset_utf32_general_ci; +extern CHARSET_INFO my_charset_utf32_unicode_ci; +extern CHARSET_INFO my_charset_utf8mb3_bin; +extern CHARSET_INFO my_charset_utf8mb3_general_ci; +extern CHARSET_INFO my_charset_utf8mb3_unicode_ci; +extern CHARSET_INFO my_charset_utf8mb4_bin; +extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_utf8mb4_general_ci; +extern CHARSET_INFO my_charset_utf8mb4_unicode_ci; + +#define MY_UTF8MB3 "utf8mb3" +#define MY_UTF8MB4 "utf8" +#define my_charset_utf8_general_ci my_charset_utf8mb4_general_ci +#define my_charset_utf8_bin my_charset_utf8mb4_bin + + +/* declarations for simple charsets */ +extern size_t my_strnxfrm_simple(CHARSET_INFO *, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags); +size_t my_strnxfrmlen_simple(CHARSET_INFO *, size_t); +extern int my_strnncoll_simple(CHARSET_INFO *, const uchar *, size_t, + const uchar *, size_t, my_bool); + +extern int my_strnncollsp_simple(CHARSET_INFO *, const uchar *, size_t, + const uchar *, size_t, + my_bool diff_if_only_endspace_difference); + +extern void my_hash_sort_simple(CHARSET_INFO *cs, + const uchar *key, size_t len, + ulong *nr1, ulong *nr2); + +extern size_t my_lengthsp_8bit(CHARSET_INFO *cs, const char *ptr, size_t length); + +extern uint my_instr_simple(struct charset_info_st *, + const char *b, size_t b_length, + const char *s, size_t s_length, + my_match_t *match, uint nmatch); + + +/* Functions for 8bit */ +extern size_t my_caseup_str_8bit(CHARSET_INFO *, char *); +extern size_t my_casedn_str_8bit(CHARSET_INFO *, char *); +extern size_t my_caseup_8bit(CHARSET_INFO *, char *src, size_t srclen, + char *dst, size_t dstlen); +extern size_t my_casedn_8bit(CHARSET_INFO *, char *src, size_t srclen, + char *dst, size_t dstlen); + +extern int my_strcasecmp_8bit(CHARSET_INFO * cs, const char *, const char *); + +int my_mb_wc_8bit(CHARSET_INFO *cs,my_wc_t *wc, const uchar *s,const uchar *e); +int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e); + +int my_mb_ctype_8bit(CHARSET_INFO *,int *, const uchar *,const uchar *); +int my_mb_ctype_mb(CHARSET_INFO *,int *, const uchar *,const uchar *); + +size_t my_scan_8bit(CHARSET_INFO *cs, const char *b, const char *e, int sq); + +size_t my_snprintf_8bit(struct charset_info_st *, char *to, size_t n, + const char *fmt, ...) + ATTRIBUTE_FORMAT(printf, 4, 5); + +long my_strntol_8bit(CHARSET_INFO *, const char *s, size_t l, int base, + char **e, int *err); +ulong my_strntoul_8bit(CHARSET_INFO *, const char *s, size_t l, int base, + char **e, int *err); +longlong my_strntoll_8bit(CHARSET_INFO *, const char *s, size_t l, int base, + char **e, int *err); +ulonglong my_strntoull_8bit(CHARSET_INFO *, const char *s, size_t l, int base, + char **e, int *err); +double my_strntod_8bit(CHARSET_INFO *, char *s, size_t l,char **e, + int *err); +size_t my_long10_to_str_8bit(CHARSET_INFO *, char *to, size_t l, int radix, + long int val); +size_t my_longlong10_to_str_8bit(CHARSET_INFO *, char *to, size_t l, int radix, + longlong val); + +longlong my_strtoll10_8bit(CHARSET_INFO *cs, + const char *nptr, char **endptr, int *error); +longlong my_strtoll10_ucs2(CHARSET_INFO *cs, + const char *nptr, char **endptr, int *error); + +ulonglong my_strntoull10rnd_8bit(CHARSET_INFO *cs, + const char *str, size_t length, int + unsigned_fl, char **endptr, int *error); +ulonglong my_strntoull10rnd_ucs2(CHARSET_INFO *cs, + const char *str, size_t length, + int unsigned_fl, char **endptr, int *error); + +void my_fill_8bit(CHARSET_INFO *cs, char* to, size_t l, int fill); + +my_bool my_like_range_simple(CHARSET_INFO *cs, + const char *ptr, size_t ptr_length, + pbool escape, pbool w_one, pbool w_many, + size_t res_length, + char *min_str, char *max_str, + size_t *min_length, size_t *max_length); + +my_bool my_like_range_mb(CHARSET_INFO *cs, + const char *ptr, size_t ptr_length, + pbool escape, pbool w_one, pbool w_many, + size_t res_length, + char *min_str, char *max_str, + size_t *min_length, size_t *max_length); + +my_bool my_like_range_ucs2(CHARSET_INFO *cs, + const char *ptr, size_t ptr_length, + pbool escape, pbool w_one, pbool w_many, + size_t res_length, + char *min_str, char *max_str, + size_t *min_length, size_t *max_length); + +my_bool my_like_range_utf16(CHARSET_INFO *cs, + const char *ptr, size_t ptr_length, + pbool escape, pbool w_one, pbool w_many, + size_t res_length, + char *min_str, char *max_str, + size_t *min_length, size_t *max_length); + +my_bool my_like_range_utf32(CHARSET_INFO *cs, + const char *ptr, size_t ptr_length, + pbool escape, pbool w_one, pbool w_many, + size_t res_length, + char *min_str, char *max_str, + size_t *min_length, size_t *max_length); + + +int my_wildcmp_8bit(CHARSET_INFO *, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many); + +int my_wildcmp_bin(CHARSET_INFO *, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many); + +size_t my_numchars_8bit(CHARSET_INFO *, const char *b, const char *e); +size_t my_numcells_8bit(CHARSET_INFO *, const char *b, const char *e); +size_t my_charpos_8bit(CHARSET_INFO *, const char *b, const char *e, size_t pos); +size_t my_well_formed_len_8bit(CHARSET_INFO *, const char *b, const char *e, + size_t pos, int *error); +uint my_mbcharlen_8bit(CHARSET_INFO *, uint c); + + +/* Functions for multibyte charsets */ +extern size_t my_caseup_str_mb(CHARSET_INFO *, char *); +extern size_t my_casedn_str_mb(CHARSET_INFO *, char *); +extern size_t my_caseup_mb(CHARSET_INFO *, char *src, size_t srclen, + char *dst, size_t dstlen); +extern size_t my_casedn_mb(CHARSET_INFO *, char *src, size_t srclen, + char *dst, size_t dstlen); +extern int my_strcasecmp_mb(CHARSET_INFO * cs,const char *, const char *); + +int my_wildcmp_mb(CHARSET_INFO *, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many); +size_t my_numchars_mb(CHARSET_INFO *, const char *b, const char *e); +size_t my_numcells_mb(CHARSET_INFO *, const char *b, const char *e); +size_t my_charpos_mb(CHARSET_INFO *, const char *b, const char *e, size_t pos); +size_t my_well_formed_len_mb(CHARSET_INFO *, const char *b, const char *e, + size_t pos, int *error); +uint my_instr_mb(struct charset_info_st *, + const char *b, size_t b_length, + const char *s, size_t s_length, + my_match_t *match, uint nmatch); + +int my_strnncoll_mb_bin(CHARSET_INFO * cs, + const uchar *s, size_t slen, + const uchar *t, size_t tlen, + my_bool t_is_prefix); + +int my_strnncollsp_mb_bin(CHARSET_INFO *cs, + const uchar *a, size_t a_length, + const uchar *b, size_t b_length, + my_bool diff_if_only_endspace_difference); + +int my_wildcmp_mb_bin(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many); + +int my_strcasecmp_mb_bin(CHARSET_INFO * cs __attribute__((unused)), + const char *s, const char *t); + +void my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)), + const uchar *key, size_t len,ulong *nr1, ulong *nr2); + +size_t my_strnxfrm_mb(CHARSET_INFO *, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags); + +size_t my_strnxfrm_unicode(CHARSET_INFO *, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags); + +int my_wildcmp_unicode(CHARSET_INFO *cs, + const char *str, const char *str_end, + const char *wildstr, const char *wildend, + int escape, int w_one, int w_many, + MY_UNICASE_INFO **weights); + +extern my_bool my_parse_charset_xml(const char *bug, size_t len, + int (*add)(CHARSET_INFO *cs)); +extern char *my_strchr(CHARSET_INFO *cs, const char *str, const char *end, + pchar c); + +my_bool my_propagate_simple(CHARSET_INFO *cs, const uchar *str, size_t len); +my_bool my_propagate_complex(CHARSET_INFO *cs, const uchar *str, size_t len); + + +uint my_string_repertoire(CHARSET_INFO *cs, const char *str, ulong len); +my_bool my_charset_is_ascii_based(CHARSET_INFO *cs); +my_bool my_charset_is_8bit_pure_ascii(CHARSET_INFO *cs); +uint my_charset_repertoire(CHARSET_INFO *cs); + + +uint my_strxfrm_flag_normalize(uint flags, uint nlevels); +void my_strxfrm_desc_and_reverse(uchar *str, uchar *strend, + uint flags, uint level); +size_t my_strxfrm_pad_desc_and_reverse(CHARSET_INFO *cs, + uchar *str, uchar *frmend, uchar *strend, + uint nweights, uint flags, uint level); + +my_bool my_charset_is_ascii_compatible(CHARSET_INFO *cs); + +#define _MY_U 01 /* Upper case */ +#define _MY_L 02 /* Lower case */ +#define _MY_NMR 04 /* Numeral (digit) */ +#define _MY_SPC 010 /* Spacing character */ +#define _MY_PNT 020 /* Punctuation */ +#define _MY_CTR 040 /* Control character */ +#define _MY_B 0100 /* Blank */ +#define _MY_X 0200 /* heXadecimal digit */ + + +#define my_isascii(c) (!((c) & ~0177)) +#define my_toascii(c) ((c) & 0177) +#define my_tocntrl(c) ((c) & 31) +#define my_toprint(c) ((c) | 64) +#define my_toupper(s,c) (char) ((s)->to_upper[(uchar) (c)]) +#define my_tolower(s,c) (char) ((s)->to_lower[(uchar) (c)]) +#define my_isalpha(s, c) (((s)->ctype+1)[(uchar) (c)] & (_MY_U | _MY_L)) +#define my_isupper(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_U) +#define my_islower(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_L) +#define my_isdigit(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_NMR) +#define my_isxdigit(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_X) +#define my_isalnum(s, c) (((s)->ctype+1)[(uchar) (c)] & (_MY_U | _MY_L | _MY_NMR)) +#define my_isspace(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_SPC) +#define my_ispunct(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_PNT) +#define my_isprint(s, c) (((s)->ctype+1)[(uchar) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR | _MY_B)) +#define my_isgraph(s, c) (((s)->ctype+1)[(uchar) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR)) +#define my_iscntrl(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_CTR) + +/* Some macros that should be cleaned up a little */ +#define my_isvar(s,c) (my_isalnum(s,c) || (c) == '_') +#define my_isvar_start(s,c) (my_isalpha(s,c) || (c) == '_') + +#define my_binary_compare(s) ((s)->state & MY_CS_BINSORT) +#define use_strnxfrm(s) ((s)->state & MY_CS_STRNXFRM) +#define my_strnxfrm(cs, d, dl, s, sl) \ + ((cs)->coll->strnxfrm((cs), (d), (dl), (dl), (s), (sl), MY_STRXFRM_PAD_WITH_SPACE)) +#define my_strnncoll(s, a, b, c, d) ((s)->coll->strnncoll((s), (a), (b), (c), (d), 0)) +#define my_like_range(s, a, b, c, d, e, f, g, h, i, j) \ + ((s)->coll->like_range((s), (a), (b), (c), (d), (e), (f), (g), (h), (i), (j))) +#define my_wildcmp(cs,s,se,w,we,e,o,m) ((cs)->coll->wildcmp((cs),(s),(se),(w),(we),(e),(o),(m))) +#define my_strcasecmp(s, a, b) ((s)->coll->strcasecmp((s), (a), (b))) +#define my_charpos(cs, b, e, num) (cs)->cset->charpos((cs), (const char*) (b), (const char *)(e), (num)) + + +#define use_mb(s) ((s)->cset->ismbchar != NULL) +#define my_ismbchar(s, a, b) ((s)->cset->ismbchar((s), (a), (b))) +#ifdef USE_MB +#define my_mbcharlen(s, a) ((s)->cset->mbcharlen((s),(a))) +#else +#define my_mbcharlen(s, a) 1 +#endif + +#define my_caseup_str(s, a) ((s)->cset->caseup_str((s), (a))) +#define my_casedn_str(s, a) ((s)->cset->casedn_str((s), (a))) +#define my_strntol(s, a, b, c, d, e) ((s)->cset->strntol((s),(a),(b),(c),(d),(e))) +#define my_strntoul(s, a, b, c, d, e) ((s)->cset->strntoul((s),(a),(b),(c),(d),(e))) +#define my_strntoll(s, a, b, c, d, e) ((s)->cset->strntoll((s),(a),(b),(c),(d),(e))) +#define my_strntoull(s, a, b, c,d, e) ((s)->cset->strntoull((s),(a),(b),(c),(d),(e))) +#define my_strntod(s, a, b, c, d) ((s)->cset->strntod((s),(a),(b),(c),(d))) + + +/* XXX: still need to take care of this one */ +#ifdef MY_CHARSET_TIS620 +#error The TIS620 charset is broken at the moment. Tell tim to fix it. +#define USE_TIS620 +#include "t_ctype.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _m_ctype_h */ diff --git a/NetService/include/Mysql/m_string.h b/NetService/include/Mysql/m_string.h new file mode 100644 index 00000000..bb8bad4b --- /dev/null +++ b/NetService/include/Mysql/m_string.h @@ -0,0 +1,393 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* There may be prolems include all of theese. Try to test in + configure with ones are needed? */ + +/* This is needed for the definitions of strchr... on solaris */ + +#ifndef _m_string_h +#define _m_string_h +#ifndef __USE_GNU +#define __USE_GNU /* We want to use stpcpy */ +#endif +#if defined(HAVE_STRINGS_H) +#include +#endif +#if defined(HAVE_STRING_H) +#include +#endif + +/* need by my_vsnprintf */ +#include + +#ifdef _AIX +#undef HAVE_BCMP +#endif + +/* This is needed for the definitions of bzero... on solaris */ +#if defined(HAVE_STRINGS_H) +#include +#endif + +/* This is needed for the definitions of memcpy... on solaris */ +#if defined(HAVE_MEMORY_H) && !defined(__cplusplus) +#include +#endif + +#if !defined(HAVE_MEMCPY) && !defined(HAVE_MEMMOVE) +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memset(A,C,B) bfill((A),(B),(C)) +# define memmove(d, s, n) bmove ((d), (s), (n)) +#elif defined(HAVE_MEMMOVE) +# define bmove(d, s, n) memmove((d), (s), (n)) +#else +# define memmove(d, s, n) bmove((d), (s), (n)) /* our bmove */ +#endif + +/* Unixware 7 */ +#if !defined(HAVE_BFILL) +# define bfill(A,B,C) memset((A),(C),(B)) +# define bmove_align(A,B,C) memcpy((A),(B),(C)) +#endif + +#if !defined(HAVE_BCMP) +# define bcopy(s, d, n) memcpy((d), (s), (n)) +# define bcmp(A,B,C) memcmp((A),(B),(C)) +# define bzero(A,B) memset((A),0,(B)) +# define bmove_align(A,B,C) memcpy((A),(B),(C)) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + my_str_malloc() and my_str_free() are assigned to implementations in + strings/alloc.c, but can be overridden in the calling program. + */ +extern void *(*my_str_malloc)(size_t); +extern void (*my_str_free)(void *); + +#if defined(HAVE_STPCPY) +#define strmov(A,B) stpcpy((A),(B)) +#ifndef stpcpy +extern char *stpcpy(char *, const char *); /* For AIX with gcc 2.95.3 */ +#endif +#endif + +/* Declared in int2str() */ +extern char NEAR _dig_vec_upper[]; +extern char NEAR _dig_vec_lower[]; + +#ifdef BAD_STRING_COMPILER +#define strmov(A,B) (memccpy(A,B,0,INT_MAX)-1) +#else +#define strmov_overlapp(A,B) strmov(A,B) +#define strmake_overlapp(A,B,C) strmake(A,B,C) +#endif + +#ifdef BAD_MEMCPY /* Problem with gcc on Alpha */ +#define memcpy_fixed(A,B,C) bmove((A),(B),(C)) +#else +#define memcpy_fixed(A,B,C) memcpy((A),(B),(C)) +#endif + +#if (!defined(USE_BMOVE512) || defined(HAVE_purify)) && !defined(bmove512) +#define bmove512(A,B,C) memcpy(A,B,C) +#endif + + /* Prototypes for string functions */ + +#if !defined(bfill) && !defined(HAVE_BFILL) +extern void bfill(uchar *dst,size_t len,pchar fill); +#endif + +#if !defined(bzero) && !defined(HAVE_BZERO) +extern void bzero(uchar * dst,size_t len); +#endif + +#if !defined(bcmp) && !defined(HAVE_BCMP) +extern size_t bcmp(const uchar *s1,const uchar *s2,size_t len); +#endif +#ifdef HAVE_purify +extern size_t my_bcmp(const uchar *s1,const uchar *s2,size_t len); +#undef bcmp +#define bcmp(A,B,C) my_bcmp((A),(B),(C)) +#define bzero_if_purify(A,B) bzero(A,B) +#else +#define bzero_if_purify(A,B) +#endif /* HAVE_purify */ + +#if defined(_lint) || defined(FORCE_INIT_OF_VARS) +#define LINT_INIT_STRUCT(var) bzero(&var, sizeof(var)) /* No uninitialize-warning */ +#else +#define LINT_INIT_STRUCT(var) +#endif + +#ifndef bmove512 +extern void bmove512(uchar *dst,const uchar *src,size_t len); +#endif + +#if !defined(HAVE_BMOVE) && !defined(bmove) +extern void bmove(uuchar *dst, const uchar *src,size_t len); +#endif + +extern void bmove_upp(uchar *dst,const uchar *src,size_t len); +extern void bchange(uchar *dst,size_t old_len,const uchar *src, + size_t new_len,size_t tot_len); +extern void strappend(char *s,size_t len,pchar fill); +extern char *strend(const char *s); +extern char *strcend(const char *, pchar); +extern char *strfield(char *src,int fields,int chars,int blanks, + int tabch); +extern char *strfill(char * s,size_t len,pchar fill); +extern size_t strinstr(const char *str,const char *search); +extern size_t r_strinstr(const char *str, size_t from, const char *search); +extern char *strkey(char *dst,char *head,char *tail,char *flags); +extern char *strmake(char *dst,const char *src,size_t length); +#ifndef strmake_overlapp +extern char *strmake_overlapp(char *dst,const char *src, size_t length); +#endif + +#ifndef strmov +extern char *strmov(char *dst,const char *src); +#endif +extern char *strnmov(char *dst,const char *src,size_t n); +extern char *strsuff(const char *src,const char *suffix); +extern char *strcont(const char *src,const char *set); +extern char *strxcat _VARARGS((char *dst,const char *src, ...)); +extern char *strxmov _VARARGS((char *dst,const char *src, ...)); +extern char *strxcpy _VARARGS((char *dst,const char *src, ...)); +extern char *strxncat _VARARGS((char *dst,size_t len, const char *src, ...)); +extern char *strxnmov _VARARGS((char *dst,size_t len, const char *src, ...)); +extern char *strxncpy _VARARGS((char *dst,size_t len, const char *src, ...)); + +/* Prototypes of normal stringfunctions (with may ours) */ + +#ifdef WANT_STRING_PROTOTYPES +extern char *strcat(char *, const char *); +extern char *strchr(const char *, pchar); +extern char *strrchr(const char *, pchar); +extern char *strcpy(char *, const char *); +extern int strcmp(const char *, const char *); +#ifndef __GNUC__ +extern size_t strlen(const char *); +#endif +#endif +#ifndef HAVE_STRNLEN +extern size_t strnlen(const char *s, size_t n); +#endif + +#if !defined(__cplusplus) +#ifndef HAVE_STRPBRK +extern char *strpbrk(const char *, const char *); +#endif +#ifndef HAVE_STRSTR +extern char *strstr(const char *, const char *); +#endif +#endif +extern int is_prefix(const char *, const char *); + +/* Conversion routines */ +typedef enum { + MY_GCVT_ARG_FLOAT, + MY_GCVT_ARG_DOUBLE +} my_gcvt_arg_type; + +double my_strtod(const char *str, char **end, int *error); +double my_atof(const char *nptr); +size_t my_fcvt(double x, int precision, char *to, my_bool *error); +size_t my_gcvt(double x, my_gcvt_arg_type type, int width, char *to, + my_bool *error); + +#define NOT_FIXED_DEC 31 + +/* + The longest string my_fcvt can return is 311 + "precision" bytes. + Here we assume that we never cal my_fcvt() with precision >= NOT_FIXED_DEC + (+ 1 byte for the terminating '\0'). +*/ +#define FLOATING_POINT_BUFFER (311 + NOT_FIXED_DEC) + +/* + We want to use the 'e' format in some cases even if we have enough space + for the 'f' one just to mimic sprintf("%.15g") behavior for large integers, + and to improve it for numbers < 10^(-4). + That is, for |x| < 1 we require |x| >= 10^(-15), and for |x| > 1 we require + it to be integer and be <= 10^DBL_DIG for the 'f' format to be used. + We don't lose precision, but make cases like "1e200" or "0.00001" look nicer. +*/ +#define MAX_DECPT_FOR_F_FORMAT DBL_DIG + +/* + The maximum possible field width for my_gcvt() conversion. + (DBL_DIG + 2) significant digits + sign + "." + ("e-NNN" or + MAX_DECPT_FOR_F_FORMAT zeros for cases when |x|<1 and the 'f' format is used). +*/ +#define MY_GCVT_MAX_FIELD_WIDTH (DBL_DIG + 4 + max(5, MAX_DECPT_FOR_F_FORMAT)) + + +extern char *llstr(longlong value,char *buff); +extern char *ullstr(longlong value,char *buff); +#ifndef HAVE_STRTOUL +extern long strtol(const char *str, char **ptr, int base); +extern ulong strtoul(const char *str, char **ptr, int base); +#endif + +extern char *int2str(long val, char *dst, int radix, int upcase); +extern char *int10_to_str(long val,char *dst,int radix); +extern char *str2int(const char *src,int radix,long lower,long upper, + long *val); +longlong my_strtoll10(const char *nptr, char **endptr, int *error); +#if SIZEOF_LONG == SIZEOF_LONG_LONG +#define ll2str(A,B,C,D) int2str((A),(B),(C),(D)) +#define longlong2str(A,B,C) int2str((A),(B),(C),1) +#define longlong10_to_str(A,B,C) int10_to_str((A),(B),(C)) +#undef strtoll +#define strtoll(A,B,C) strtol((A),(B),(C)) +#define strtoull(A,B,C) strtoul((A),(B),(C)) +#ifndef HAVE_STRTOULL +#define HAVE_STRTOULL +#endif +#ifndef HAVE_STRTOLL +#define HAVE_STRTOLL +#endif +#else +#ifdef HAVE_LONG_LONG +extern char *ll2str(longlong val,char *dst,int radix, int upcase); +#define longlong2str(A,B,C) ll2str((A),(B),(C),1) +extern char *longlong10_to_str(longlong val,char *dst,int radix); +#if (!defined(HAVE_STRTOULL) || defined(NO_STRTOLL_PROTO)) +extern longlong strtoll(const char *str, char **ptr, int base); +extern ulonglong strtoull(const char *str, char **ptr, int base); +#endif +#endif +#endif + +/* my_vsnprintf.c */ + +extern size_t my_vsnprintf(char *str, size_t n, + const char *format, va_list ap); +extern size_t my_snprintf(char *to, size_t n, const char *fmt, ...) + ATTRIBUTE_FORMAT(printf, 3, 4); + +#if defined(__cplusplus) +} +#endif + +/* + LEX_STRING -- a pair of a C-string and its length. + (it's part of the plugin API as a MYSQL_LEX_STRING) +*/ + +typedef struct st_mysql_lex_string LEX_STRING; + +#define STRING_WITH_LEN(X) (X), ((size_t) (sizeof(X) - 1)) +#define USTRING_WITH_LEN(X) ((uchar*) X), ((size_t) (sizeof(X) - 1)) +#define C_STRING_WITH_LEN(X) ((char *) (X)), ((size_t) (sizeof(X) - 1)) + +/* A variant with const */ +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string LEX_CSTRING; + +/* A variant with const and unsigned */ +struct st_mysql_const_unsigned_lex_string +{ + const uchar *str; + size_t length; +}; +typedef struct st_mysql_const_unsigned_lex_string LEX_CUSTRING; + +/* SPACE_INT is a word that contains only spaces */ +#if SIZEOF_INT == 4 +#define SPACE_INT 0x20202020 +#elif SIZEOF_INT == 8 +#define SPACE_INT 0x2020202020202020 +#else +#error define the appropriate constant for a word full of spaces +#endif + +/** + Skip trailing space. + + On most systems reading memory in larger chunks (ideally equal to the size of + the chinks that the machine physically reads from memory) causes fewer memory + access loops and hence increased performance. + This is why the 'int' type is used : it's closest to that (according to how + it's defined in C). + So when we determine the amount of whitespace at the end of a string we do + the following : + 1. We divide the string into 3 zones : + a) from the start of the string (__start) to the first multiple + of sizeof(int) (__start_words) + b) from the end of the string (__end) to the last multiple of sizeof(int) + (__end_words) + c) a zone that is aligned to sizeof(int) and can be safely accessed + through an int * + 2. We start comparing backwards from (c) char-by-char. If all we find is + space then we continue + 3. If there are elements in zone (b) we compare them as unsigned ints to a + int mask (SPACE_INT) consisting of all spaces + 4. Finally we compare the remaining part (a) of the string char by char. + This covers for the last non-space unsigned int from 3. (if any) + + This algorithm works well for relatively larger strings, but it will slow + the things down for smaller strings (because of the additional calculations + and checks compared to the naive method). Thus the barrier of length 20 + is added. + + @param ptr pointer to the input string + @param len the length of the string + @return the last non-space character +*/ + +static inline const uchar *skip_trailing_space(const uchar *ptr,size_t len) +{ + const uchar *end= ptr + len; + + if (len > 20) + { + const uchar *end_words= (const uchar *)(intptr) + (((ulonglong)(intptr)end) / SIZEOF_INT * SIZEOF_INT); + const uchar *start_words= (const uchar *)(intptr) + ((((ulonglong)(intptr)ptr) + SIZEOF_INT - 1) / SIZEOF_INT * SIZEOF_INT); + + DBUG_ASSERT(((ulonglong)(intptr)ptr) >= SIZEOF_INT); + if (end_words > ptr) + { + while (end > end_words && end[-1] == 0x20) + end--; + if (end[-1] == 0x20 && start_words < end_words) + while (end > start_words && ((unsigned *)end)[-1] == SPACE_INT) + end -= SIZEOF_INT; + } + } + while (end > ptr && end[-1] == 0x20) + end--; + return (end); +} + +#ifdef SAFEMALLOC +#define TRASH(A,B) bfill(A, B, 0x8F) +#else +#define TRASH(A,B) /* nothing */ +#endif /* SAFEMALLOC */ + +#endif /* _m_string_h */ diff --git a/NetService/include/Mysql/my_aes.h b/NetService/include/Mysql/my_aes.h new file mode 100644 index 00000000..8ea128ca --- /dev/null +++ b/NetService/include/Mysql/my_aes.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2002 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +/* Header file for my_aes.c */ +/* Wrapper to give simple interface for MySQL to AES standard encryption */ + +#include "mysys/rijndael.h" + +C_MODE_START + +#define AES_KEY_LENGTH 128 /* Must be 128 192 or 256 */ + +/* + my_aes_encrypt - Crypt buffer with AES encryption algorithm. + source - Pointer to data for encryption + source_length - size of encryption data + dest - buffer to place encrypted data (must be large enough) + key - Key to be used for encryption + kel_length - Length of the key. Will handle keys of any length + + returns - size of encrypted data, or negative in case of error. +*/ + +int my_aes_encrypt(const char *source, int source_length, char *dest, + const char *key, int key_length); + +/* + my_aes_decrypt - DeCrypt buffer with AES encryption algorithm. + source - Pointer to data for decryption + source_length - size of encrypted data + dest - buffer to place decrypted data (must be large enough) + key - Key to be used for decryption + kel_length - Length of the key. Will handle keys of any length + + returns - size of original data, or negative in case of error. +*/ + + +int my_aes_decrypt(const char *source, int source_length, char *dest, + const char *key, int key_length); + +/* + my_aes_get_size - get size of buffer which will be large enough for encrypted + data + source_length - length of data to be encrypted + + returns - size of buffer required to store encrypted data +*/ + +int my_aes_get_size(int source_length); + +C_MODE_END diff --git a/NetService/include/Mysql/my_alarm.h b/NetService/include/Mysql/my_alarm.h new file mode 100644 index 00000000..dd2d5642 --- /dev/null +++ b/NetService/include/Mysql/my_alarm.h @@ -0,0 +1,58 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + File to include when we want to use alarm or a loop_counter to display + some information when a program is running +*/ +#ifndef _my_alarm_h +#define _my_alarm_h +#ifdef __cplusplus +extern "C" { +#endif + +extern int volatile my_have_got_alarm; +extern ulong my_time_to_wait_for_lock; + +#if defined(HAVE_ALARM) && !defined(NO_ALARM_LOOP) +#include +#define ALARM_VARIABLES uint alarm_old=0; \ + sig_return alarm_signal=0 +#define ALARM_INIT my_have_got_alarm=0 ; \ + alarm_old=(uint) alarm(MY_HOW_OFTEN_TO_ALARM); \ + alarm_signal=signal(SIGALRM,my_set_alarm_variable); +#define ALARM_END (void) signal(SIGALRM,alarm_signal); \ + (void) alarm(alarm_old); +#define ALARM_TEST my_have_got_alarm +#ifdef DONT_REMEMBER_SIGNAL +#define ALARM_REINIT (void) alarm(MY_HOW_OFTEN_TO_ALARM); \ + (void) signal(SIGALRM,my_set_alarm_variable);\ + my_have_got_alarm=0; +#else +#define ALARM_REINIT (void) alarm((uint) MY_HOW_OFTEN_TO_ALARM); \ + my_have_got_alarm=0; +#endif /* DONT_REMEMBER_SIGNAL */ +#else +#define ALARM_VARIABLES long alarm_pos=0,alarm_end_pos=MY_HOW_OFTEN_TO_WRITE-1 +#define ALARM_INIT +#define ALARM_END +#define ALARM_TEST (alarm_pos++ >= alarm_end_pos) +#define ALARM_REINIT alarm_end_pos+=MY_HOW_OFTEN_TO_WRITE +#endif /* HAVE_ALARM */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/NetService/include/Mysql/my_alloc.h b/NetService/include/Mysql/my_alloc.h new file mode 100644 index 00000000..6ade4d08 --- /dev/null +++ b/NetService/include/Mysql/my_alloc.h @@ -0,0 +1,51 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Data structures for mysys/my_alloc.c (root memory allocator) +*/ + +#ifndef _my_alloc_h +#define _my_alloc_h + +#define ALLOC_MAX_BLOCK_TO_DROP 4096 +#define ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP 10 + +typedef struct st_used_mem +{ /* struct for once_alloc (block) */ + struct st_used_mem *next; /* Next block in use */ + size_t left; /* memory left in block */ + size_t size; /* size of block */ +} USED_MEM; + + +typedef struct st_mem_root +{ + USED_MEM *free; /* blocks with free memory in it */ + USED_MEM *used; /* blocks almost without free memory */ + USED_MEM *pre_alloc; /* preallocated block */ + /* if block have less memory it will be put in 'used' list */ + size_t min_malloc; + size_t block_size; /* initial block size */ + unsigned int block_num; /* allocated blocks counter */ + /* + first free block in queue test counter (if it exceed + MAX_BLOCK_USAGE_BEFORE_DROP block will be dropped in 'used' list) + */ + unsigned int first_block_usage; + + void (*error_handler)(void); +} MEM_ROOT; +#endif diff --git a/NetService/include/Mysql/my_atomic.h b/NetService/include/Mysql/my_atomic.h new file mode 100644 index 00000000..40b88956 --- /dev/null +++ b/NetService/include/Mysql/my_atomic.h @@ -0,0 +1,254 @@ +/* Copyright (C) 2006 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + This header defines five atomic operations: + + my_atomic_add#(&var, what) + add 'what' to *var, and return the old value of *var + + my_atomic_fas#(&var, what) + 'Fetch And Store' + store 'what' in *var, and return the old value of *var + + my_atomic_cas#(&var, &old, new) + 'Compare And Swap' + if *var is equal to *old, then store 'new' in *var, and return TRUE + otherwise store *var in *old, and return FALSE + + my_atomic_load#(&var) + return *var + + my_atomic_store#(&var, what) + store 'what' in *var + + '#' is substituted by a size suffix - 8, 16, 32, or ptr + (e.g. my_atomic_add8, my_atomic_fas32, my_atomic_casptr). + + NOTE This operations are not always atomic, so they always must be + enclosed in my_atomic_rwlock_rdlock(lock)/my_atomic_rwlock_rdunlock(lock) + or my_atomic_rwlock_wrlock(lock)/my_atomic_rwlock_wrunlock(lock). + Hint: if a code block makes intensive use of atomic ops, it make sense + to take/release rwlock once for the whole block, not for every statement. + + On architectures where these operations are really atomic, rwlocks will + be optimized away. + 8- and 16-bit atomics aren't implemented for windows (see generic-msvc.h), + but can be added, if necessary. +*/ + +#ifndef my_atomic_rwlock_init + +#define intptr void * + +#ifndef MY_ATOMIC_MODE_RWLOCKS +#include "atomic/nolock.h" +#endif + +#ifndef make_atomic_cas_body +/* nolock.h was not able to generate even a CAS function, fall back */ +#include "atomic/rwlock.h" +#else +/* define missing functions by using the already generated ones */ +#ifndef make_atomic_add_body +#define make_atomic_add_body(S) \ + int ## S tmp=*a; \ + while (!my_atomic_cas ## S(a, &tmp, tmp+v)); \ + v=tmp; +#endif +#ifndef make_atomic_fas_body +#define make_atomic_fas_body(S) \ + int ## S tmp=*a; \ + while (!my_atomic_cas ## S(a, &tmp, v)); \ + v=tmp; +#endif +#ifndef make_atomic_load_body +#define make_atomic_load_body(S) \ + ret= 0; /* avoid compiler warning */ \ + (void)(my_atomic_cas ## S(a, &ret, ret)); +#endif +#ifndef make_atomic_store_body +#define make_atomic_store_body(S) \ + (void)(my_atomic_fas ## S (a, v)); +#endif +#endif + +/* + transparent_union doesn't work in g++ + Bug ? + + Darwin's gcc doesn't want to put pointers in a transparent_union + when built with -arch ppc64. Complains: + warning: 'transparent_union' attribute ignored +*/ +#if defined(__GNUC__) && !defined(__cplusplus) && \ + ! (defined(__APPLE__) && defined(_ARCH_PPC64)) +/* + we want to be able to use my_atomic_xxx functions with + both signed and unsigned integers. But gcc will issue a warning + "passing arg N of `my_atomic_XXX' as [un]signed due to prototype" + if the signedness of the argument doesn't match the prototype, or + "pointer targets in passing argument N of my_atomic_XXX differ in signedness" + if int* is used where uint* is expected (or vice versa). + Let's shut these warnings up +*/ +#define make_transparent_unions(S) \ + typedef union { \ + int ## S i; \ + uint ## S u; \ + } U_ ## S __attribute__ ((transparent_union)); \ + typedef union { \ + int ## S volatile *i; \ + uint ## S volatile *u; \ + } Uv_ ## S __attribute__ ((transparent_union)); +#define uintptr intptr +make_transparent_unions(8) +make_transparent_unions(16) +make_transparent_unions(32) +make_transparent_unions(ptr) +#undef uintptr +#undef make_transparent_unions +#define a U_a.i +#define cmp U_cmp.i +#define v U_v.i +#define set U_set.i +#else +#define U_32 int32 +#define U_ptr intptr +#define Uv_32 int32 +#define Uv_ptr intptr +#define U_a volatile *a +#define U_cmp *cmp +#define U_v v +#define U_set set +#endif /* __GCC__ transparent_union magic */ + +#ifdef HAVE_INLINE + +#define make_atomic_cas(S) \ +STATIC_INLINE int my_atomic_cas ## S(Uv_ ## S U_a, \ + Uv_ ## S U_cmp, U_ ## S U_set) \ +{ \ + int8 ret; \ + make_atomic_cas_body(S); \ + return ret; \ +} + +#define make_atomic_add(S) \ +STATIC_INLINE int ## S my_atomic_add ## S( \ + Uv_ ## S U_a, U_ ## S U_v) \ +{ \ + make_atomic_add_body(S); \ + return v; \ +} + +#define make_atomic_fas(S) \ +STATIC_INLINE int ## S my_atomic_fas ## S( \ + Uv_ ## S U_a, U_ ## S U_v) \ +{ \ + make_atomic_fas_body(S); \ + return v; \ +} + +#define make_atomic_load(S) \ +STATIC_INLINE int ## S my_atomic_load ## S(Uv_ ## S U_a) \ +{ \ + int ## S ret; \ + make_atomic_load_body(S); \ + return ret; \ +} + +#define make_atomic_store(S) \ +STATIC_INLINE void my_atomic_store ## S( \ + Uv_ ## S U_a, U_ ## S U_v) \ +{ \ + make_atomic_store_body(S); \ +} + +#else /* no inline functions */ + +#define make_atomic_add(S) \ +extern int ## S my_atomic_add ## S(Uv_ ## S U_a, U_ ## S U_v); + +#define make_atomic_fas(S) \ +extern int ## S my_atomic_fas ## S(Uv_ ## S U_a, U_ ## S U_v); + +#define make_atomic_cas(S) \ +extern int my_atomic_cas ## S(Uv_ ## S U_a, Uv_ ## S U_cmp, U_ ## S U_set); + +#define make_atomic_load(S) \ +extern int ## S my_atomic_load ## S(Uv_ ## S U_a); + +#define make_atomic_store(S) \ +extern void my_atomic_store ## S(Uv_ ## S U_a, U_ ## S U_v); + +#endif + +make_atomic_cas(32) +make_atomic_cas(ptr) + +make_atomic_add(32) + +make_atomic_load(32) +make_atomic_load(ptr) + +make_atomic_fas(32) +make_atomic_fas(ptr) + +make_atomic_store(32) +make_atomic_store(ptr) + +#ifdef _atomic_h_cleanup_ +#include _atomic_h_cleanup_ +#undef _atomic_h_cleanup_ +#endif + +#undef U_32 +#undef U_ptr +#undef a +#undef cmp +#undef v +#undef set +#undef U_a +#undef U_cmp +#undef U_v +#undef U_set +#undef make_atomic_add +#undef make_atomic_cas +#undef make_atomic_load +#undef make_atomic_store +#undef make_atomic_fas +#undef make_atomic_add_body +#undef make_atomic_cas_body +#undef make_atomic_load_body +#undef make_atomic_store_body +#undef make_atomic_fas_body +#undef intptr + +/* + the macro below defines (as an expression) the code that + will be run in spin-loops. Intel manuals recummend to have PAUSE there. + It is expected to be defined in include/atomic/ *.h files +*/ +#ifndef LF_BACKOFF +#define LF_BACKOFF (1) +#endif + +#define MY_ATOMIC_OK 0 +#define MY_ATOMIC_NOT_1CPU 1 +extern int my_atomic_initialize(); + +#endif + diff --git a/NetService/include/Mysql/my_attribute.h b/NetService/include/Mysql/my_attribute.h new file mode 100644 index 00000000..8309d85f --- /dev/null +++ b/NetService/include/Mysql/my_attribute.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2000-2003 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Helper macros used for setting different __attributes__ + on functions in a portable fashion +*/ + +#ifndef _my_attribute_h +#define _my_attribute_h + +/* + Disable __attribute__() on gcc < 2.7, g++ < 3.4, and non-gcc compilers. + Some forms of __attribute__ are actually supported in earlier versions of + g++, but we just disable them all because we only use them to generate + compilation warnings. +*/ +#ifndef __attribute__ +# if !defined(__GNUC__) +# define __attribute__(A) +# elif GCC_VERSION < 2008 +# define __attribute__(A) +# elif defined(__cplusplus) && GCC_VERSION < 3004 +# define __attribute__(A) +# endif +#endif + +/* + __attribute__((format(...))) is only supported in gcc >= 2.8 and g++ >= 3.4 + But that's already covered by the __attribute__ tests above, so this is + just a convenience macro. +*/ +#ifndef ATTRIBUTE_FORMAT +# define ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n))) +#endif + +/* + + __attribute__((format(...))) on a function pointer is not supported + until gcc 3.1 +*/ +#ifndef ATTRIBUTE_FORMAT_FPTR +# if (GCC_VERSION >= 3001) +# define ATTRIBUTE_FORMAT_FPTR(style, m, n) ATTRIBUTE_FORMAT(style, m, n) +# else +# define ATTRIBUTE_FORMAT_FPTR(style, m, n) +# endif /* GNUC >= 3.1 */ +#endif + + +#endif diff --git a/NetService/include/Mysql/my_base.h b/NetService/include/Mysql/my_base.h new file mode 100644 index 00000000..e228b397 --- /dev/null +++ b/NetService/include/Mysql/my_base.h @@ -0,0 +1,626 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* This file includes constants used with all databases */ + +#ifndef _my_base_h +#define _my_base_h + +#ifndef stdin /* Included first in handler */ +#define CHSIZE_USED +#include +#include /* This includes types */ +#include +#include +#include + +#ifndef EOVERFLOW +#define EOVERFLOW 84 +#endif + +#if !defined(USE_MY_FUNC) && !defined(THREAD) +#include /* For faster code, after test */ +#endif /* USE_MY_FUNC */ +#endif /* stdin */ +#include + +/* The following is bits in the flag parameter to ha_open() */ + +#define HA_OPEN_ABORT_IF_LOCKED 0 /* default */ +#define HA_OPEN_WAIT_IF_LOCKED 1 +#define HA_OPEN_IGNORE_IF_LOCKED 2 +#define HA_OPEN_TMP_TABLE 4 /* Table is a temp table */ +#define HA_OPEN_DELAY_KEY_WRITE 8 /* Don't update index */ +#define HA_OPEN_ABORT_IF_CRASHED 16 +#define HA_OPEN_FOR_REPAIR 32 /* open even if crashed */ +#define HA_OPEN_FROM_SQL_LAYER 64 +#define HA_OPEN_MMAP 128 /* open memory mapped */ +#define HA_OPEN_COPY 256 /* Open copy (for repair) */ +/* Internal temp table, used for temporary results */ +#define HA_OPEN_INTERNAL_TABLE 512 + +/* The following is parameter to ha_rkey() how to use key */ + +/* + We define a complete-field prefix of a key value as a prefix where + the last included field in the prefix contains the full field, not + just some bytes from the start of the field. A partial-field prefix + is allowed to contain only a few first bytes from the last included + field. + + Below HA_READ_KEY_EXACT, ..., HA_READ_BEFORE_KEY can take a + complete-field prefix of a key value as the search + key. HA_READ_PREFIX and HA_READ_PREFIX_LAST could also take a + partial-field prefix, but currently (4.0.10) they are only used with + complete-field prefixes. MySQL uses a padding trick to implement + LIKE 'abc%' queries. + + NOTE that in InnoDB HA_READ_PREFIX_LAST will NOT work with a + partial-field prefix because InnoDB currently strips spaces from the + end of varchar fields! +*/ + +enum ha_rkey_function { + HA_READ_KEY_EXACT, /* Find first record else error */ + HA_READ_KEY_OR_NEXT, /* Record or next record */ + HA_READ_KEY_OR_PREV, /* Record or previous */ + HA_READ_AFTER_KEY, /* Find next rec. after key-record */ + HA_READ_BEFORE_KEY, /* Find next rec. before key-record */ + HA_READ_PREFIX, /* Key which as same prefix */ + HA_READ_PREFIX_LAST, /* Last key with the same prefix */ + HA_READ_PREFIX_LAST_OR_PREV, /* Last or prev key with the same prefix */ + HA_READ_MBR_CONTAIN, + HA_READ_MBR_INTERSECT, + HA_READ_MBR_WITHIN, + HA_READ_MBR_DISJOINT, + HA_READ_MBR_EQUAL +}; + + /* Key algorithm types */ + +enum ha_key_alg { + HA_KEY_ALG_UNDEF= 0, /* Not specified (old file) */ + HA_KEY_ALG_BTREE= 1, /* B-tree, default one */ + HA_KEY_ALG_RTREE= 2, /* R-tree, for spatial searches */ + HA_KEY_ALG_HASH= 3, /* HASH keys (HEAP tables) */ + HA_KEY_ALG_FULLTEXT= 4 /* FULLTEXT (MyISAM tables) */ +}; + + /* Index and table build methods */ + +enum ha_build_method { + HA_BUILD_DEFAULT, + HA_BUILD_ONLINE, + HA_BUILD_OFFLINE +}; + + /* Storage media types */ + +enum ha_storage_media { + HA_SM_DEFAULT= 0, /* Not specified (engine default) */ + HA_SM_DISK= 1, /* DISK storage */ + HA_SM_MEMORY= 2 /* MAIN MEMORY storage */ +}; + + /* The following is parameter to ha_extra() */ + +enum ha_extra_function { + HA_EXTRA_NORMAL=0, /* Optimize for space (def) */ + HA_EXTRA_QUICK=1, /* Optimize for speed */ + HA_EXTRA_NOT_USED=2, + HA_EXTRA_CACHE=3, /* Cache record in HA_rrnd() */ + HA_EXTRA_NO_CACHE=4, /* End caching of records (def) */ + HA_EXTRA_NO_READCHECK=5, /* No readcheck on update */ + HA_EXTRA_READCHECK=6, /* Use readcheck (def) */ + HA_EXTRA_KEYREAD=7, /* Read only key to database */ + HA_EXTRA_NO_KEYREAD=8, /* Normal read of records (def) */ + HA_EXTRA_NO_USER_CHANGE=9, /* No user is allowed to write */ + HA_EXTRA_KEY_CACHE=10, + HA_EXTRA_NO_KEY_CACHE=11, + HA_EXTRA_WAIT_LOCK=12, /* Wait until file is avalably (def) */ + HA_EXTRA_NO_WAIT_LOCK=13, /* If file is locked, return quickly */ + HA_EXTRA_WRITE_CACHE=14, /* Use write cache in ha_write() */ + HA_EXTRA_FLUSH_CACHE=15, /* flush write_record_cache */ + HA_EXTRA_NO_KEYS=16, /* Remove all update of keys */ + HA_EXTRA_KEYREAD_CHANGE_POS=17, /* Keyread, but change pos */ + /* xxxxchk -r must be used */ + HA_EXTRA_REMEMBER_POS=18, /* Remember pos for next/prev */ + HA_EXTRA_RESTORE_POS=19, + HA_EXTRA_REINIT_CACHE=20, /* init cache from current record */ + HA_EXTRA_FORCE_REOPEN=21, /* Datafile have changed on disk */ + HA_EXTRA_FLUSH, /* Flush tables to disk */ + HA_EXTRA_NO_ROWS, /* Don't write rows */ + HA_EXTRA_RESET_STATE, /* Reset positions */ + HA_EXTRA_IGNORE_DUP_KEY, /* Dup keys don't rollback everything*/ + HA_EXTRA_NO_IGNORE_DUP_KEY, + HA_EXTRA_PREPARE_FOR_DROP, + HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */ + HA_EXTRA_PRELOAD_BUFFER_SIZE, /* Set buffer size for preloading */ + /* + On-the-fly switching between unique and non-unique key inserting. + */ + HA_EXTRA_CHANGE_KEY_TO_UNIQUE, + HA_EXTRA_CHANGE_KEY_TO_DUP, + /* + When using HA_EXTRA_KEYREAD, overwrite only key member fields and keep + other fields intact. When this is off (by default) InnoDB will use memcpy + to overwrite entire row. + */ + HA_EXTRA_KEYREAD_PRESERVE_FIELDS, + HA_EXTRA_MMAP, + /* + Ignore if the a tuple is not found, continue processing the + transaction and ignore that 'row'. Needed for idempotency + handling on the slave + + Currently only used by NDB storage engine. Partition handler ignores flag. + */ + HA_EXTRA_IGNORE_NO_KEY, + HA_EXTRA_NO_IGNORE_NO_KEY, + /* + Mark the table as a log table. For some handlers (e.g. CSV) this results + in a special locking for the table. + */ + HA_EXTRA_MARK_AS_LOG_TABLE, + /* + Informs handler that write_row() which tries to insert new row into the + table and encounters some already existing row with same primary/unique + key can replace old row with new row instead of reporting error (basically + it informs handler that we do REPLACE instead of simple INSERT). + Off by default. + */ + HA_EXTRA_WRITE_CAN_REPLACE, + HA_EXTRA_WRITE_CANNOT_REPLACE, + /* + Inform handler that delete_row()/update_row() cannot batch deletes/updates + and should perform them immediately. This may be needed when table has + AFTER DELETE/UPDATE triggers which access to subject table. + These flags are reset by the handler::extra(HA_EXTRA_RESET) call. + */ + HA_EXTRA_DELETE_CANNOT_BATCH, + HA_EXTRA_UPDATE_CANNOT_BATCH, + /* + Inform handler that an "INSERT...ON DUPLICATE KEY UPDATE" will be + executed. This condition is unset by HA_EXTRA_NO_IGNORE_DUP_KEY. + */ + HA_EXTRA_INSERT_WITH_UPDATE, + /* Inform handler that we will do a rename */ + HA_EXTRA_PREPARE_FOR_RENAME, + /* + Special actions for MERGE tables. + */ + HA_EXTRA_ADD_CHILDREN_LIST, + HA_EXTRA_ATTACH_CHILDREN, + HA_EXTRA_IS_ATTACHED_CHILDREN, + HA_EXTRA_DETACH_CHILDREN, + HA_EXTRA_ORDERBY_LIMIT, + HA_EXTRA_NO_ORDERBY_LIMIT, + /* Inform handler we will force a close as part of flush */ + HA_EXTRA_PREPARE_FOR_FORCED_CLOSE, + HA_EXTRA_ALLOW_LOG_DELETE +}; + +/* Compatible option, to be deleted in 6.0 */ +#define HA_EXTRA_PREPARE_FOR_DELETE HA_EXTRA_PREPARE_FOR_DROP + + /* The following is parameter to ha_panic() */ + +enum ha_panic_function { + HA_PANIC_CLOSE, /* Close all databases */ + HA_PANIC_WRITE, /* Unlock and write status */ + HA_PANIC_READ /* Lock and read keyinfo */ +}; + + /* The following is parameter to ha_create(); keytypes */ + +enum ha_base_keytype { + HA_KEYTYPE_END=0, + HA_KEYTYPE_TEXT=1, /* Key is sorted as letters */ + HA_KEYTYPE_BINARY=2, /* Key is sorted as unsigned chars */ + HA_KEYTYPE_SHORT_INT=3, + HA_KEYTYPE_LONG_INT=4, + HA_KEYTYPE_FLOAT=5, + HA_KEYTYPE_DOUBLE=6, + HA_KEYTYPE_NUM=7, /* Not packed num with pre-space */ + HA_KEYTYPE_USHORT_INT=8, + HA_KEYTYPE_ULONG_INT=9, + HA_KEYTYPE_LONGLONG=10, + HA_KEYTYPE_ULONGLONG=11, + HA_KEYTYPE_INT24=12, + HA_KEYTYPE_UINT24=13, + HA_KEYTYPE_INT8=14, + /* Varchar (0-255 bytes) with length packed with 1 byte */ + HA_KEYTYPE_VARTEXT1=15, /* Key is sorted as letters */ + HA_KEYTYPE_VARBINARY1=16, /* Key is sorted as unsigned chars */ + /* Varchar (0-65535 bytes) with length packed with 2 bytes */ + HA_KEYTYPE_VARTEXT2=17, /* Key is sorted as letters */ + HA_KEYTYPE_VARBINARY2=18, /* Key is sorted as unsigned chars */ + HA_KEYTYPE_BIT=19 +}; + +#define HA_MAX_KEYTYPE 31 /* Must be log2-1 */ + +/* + These flags kan be OR:ed to key-flag + Note that these can only be up to 16 bits! +*/ + +#define HA_NOSAME 1 /* Set if not dupplicated records */ +#define HA_PACK_KEY 2 /* Pack string key to previous key */ +#define HA_AUTO_KEY 16 +#define HA_BINARY_PACK_KEY 32 /* Packing of all keys to prev key */ +#define HA_FULLTEXT 128 /* For full-text search */ +#define HA_UNIQUE_CHECK 256 /* Check the key for uniqueness */ +#define HA_SPATIAL 1024 /* For spatial search */ +#define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */ +#define HA_GENERATED_KEY 8192 /* Automaticly generated key */ +#define HA_RTREE_INDEX 16384 /* For RTREE search */ + + /* The combination of the above can be used for key type comparison. */ +#define HA_KEYFLAG_MASK (HA_NOSAME | HA_PACK_KEY | HA_AUTO_KEY | \ + HA_BINARY_PACK_KEY | HA_FULLTEXT | HA_UNIQUE_CHECK | \ + HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY | \ + HA_RTREE_INDEX) + +#define HA_KEY_HAS_PART_KEY_SEG 65536 /* Key contains partial segments */ + + /* Automatic bits in key-flag */ + +#define HA_SPACE_PACK_USED 4 /* Test for if SPACE_PACK used */ +#define HA_VAR_LENGTH_KEY 8 +#define HA_NULL_PART_KEY 64 +#define HA_USES_COMMENT 4096 +#define HA_USES_PARSER 16384 /* Fulltext index uses [pre]parser */ +#define HA_USES_BLOCK_SIZE ((uint) 32768) +#define HA_SORT_ALLOWS_SAME 512 /* Intern bit when sorting records */ +#if MYSQL_VERSION_ID < 0x50200 +/* + Key has a part that can have end space. If this is an unique key + we have to handle it differently from other unique keys as we can find + many matching rows for one key (because end space are not compared) +*/ +#define HA_END_SPACE_KEY 0 /* was: 4096 */ +#else +#error HA_END_SPACE_KEY is obsolete, please remove it +#endif + + + /* These flags can be added to key-seg-flag */ + +#define HA_SPACE_PACK 1 /* Pack space in key-seg */ +#define HA_PART_KEY_SEG 4 /* Used by MySQL for part-key-cols */ +#define HA_VAR_LENGTH_PART 8 +#define HA_NULL_PART 16 +#define HA_BLOB_PART 32 +#define HA_SWAP_KEY 64 +#define HA_REVERSE_SORT 128 /* Sort key in reverse order */ +#define HA_NO_SORT 256 /* do not bother sorting on this keyseg */ +/* + End space in unique/varchar are considered equal. (Like 'a' and 'a ') + Only needed for internal temporary tables. +*/ +#define HA_END_SPACE_ARE_EQUAL 512 +#define HA_BIT_PART 1024 + + /* optionbits for database */ +#define HA_OPTION_PACK_RECORD 1 +#define HA_OPTION_PACK_KEYS 2 +#define HA_OPTION_COMPRESS_RECORD 4 +#define HA_OPTION_LONG_BLOB_PTR 8 /* new ISAM format */ +#define HA_OPTION_TMP_TABLE 16 +#define HA_OPTION_CHECKSUM 32 +#define HA_OPTION_DELAY_KEY_WRITE 64 +#define HA_OPTION_NO_PACK_KEYS 128 /* Reserved for MySQL */ +#define HA_OPTION_CREATE_FROM_ENGINE 256 +#define HA_OPTION_RELIES_ON_SQL_LAYER 512 +#define HA_OPTION_NULL_FIELDS 1024 +#define HA_OPTION_PAGE_CHECKSUM 2048 +#define HA_OPTION_TEMP_COMPRESS_RECORD (1L << 15) /* set by isamchk */ +#define HA_OPTION_READ_ONLY_DATA (1L << 16) /* Set by isamchk */ +#define HA_OPTION_NO_CHECKSUM (1L << 17) +#define HA_OPTION_NO_DELAY_KEY_WRITE (1L << 18) + + /* Bits in flag to create() */ + +#define HA_DONT_TOUCH_DATA 1 /* Don't empty datafile (isamchk) */ +#define HA_PACK_RECORD 2 /* Request packed record format */ +#define HA_CREATE_TMP_TABLE 4 +#define HA_CREATE_CHECKSUM 8 +#define HA_CREATE_KEEP_FILES 16 /* don't overwrite .MYD and MYI */ +#define HA_CREATE_PAGE_CHECKSUM 32 +#define HA_CREATE_DELAY_KEY_WRITE 64 +#define HA_CREATE_RELIES_ON_SQL_LAYER 128 + +/* + The following flags (OR-ed) are passed to handler::info() method. + The method copies misc handler information out of the storage engine + to data structures accessible from MySQL + + Same flags are also passed down to mi_status, myrg_status, etc. +*/ + +/* this one is not used */ +#define HA_STATUS_POS 1 +/* + assuming the table keeps shared actual copy of the 'info' and + local, possibly outdated copy, the following flag means that + it should not try to get the actual data (locking the shared structure) + slightly outdated version will suffice +*/ +#define HA_STATUS_NO_LOCK 2 +/* update the time of the last modification (in handler::update_time) */ +#define HA_STATUS_TIME 4 +/* + update the 'constant' part of the info: + handler::max_data_file_length, max_index_file_length, create_time + sortkey, ref_length, block_size, data_file_name, index_file_name. + handler::table->s->keys_in_use, keys_for_keyread, rec_per_key +*/ +#define HA_STATUS_CONST 8 +/* + update the 'variable' part of the info: + handler::records, deleted, data_file_length, index_file_length, + delete_length, check_time, mean_rec_length +*/ +#define HA_STATUS_VARIABLE 16 +/* + get the information about the key that caused last duplicate value error + update handler::errkey and handler::dupp_ref + see handler::get_dup_key() +*/ +#define HA_STATUS_ERRKEY 32 +/* + update handler::auto_increment_value +*/ +#define HA_STATUS_AUTO 64 + +/* + Errorcodes given by handler functions + + opt_sum_query() assumes these codes are > 1 + Do not add error numbers before HA_ERR_FIRST. + If necessary to add lower numbers, change HA_ERR_FIRST accordingly. +*/ +#define HA_ERR_FIRST 120 /* Copy of first error nr.*/ + +#define HA_ERR_KEY_NOT_FOUND 120 /* Didn't find key on read or update */ +#define HA_ERR_FOUND_DUPP_KEY 121 /* Dupplicate key on write */ +#define HA_ERR_INTERNAL_ERROR 122 /* Internal error */ +#define HA_ERR_RECORD_CHANGED 123 /* Uppdate with is recoverable */ +#define HA_ERR_WRONG_INDEX 124 /* Wrong index given to function */ +#define HA_ERR_CRASHED 126 /* Indexfile is crashed */ +#define HA_ERR_WRONG_IN_RECORD 127 /* Record-file is crashed */ +#define HA_ERR_OUT_OF_MEM 128 /* Record-file is crashed */ +#define HA_ERR_NOT_A_TABLE 130 /* not a MYI file - no signature */ +#define HA_ERR_WRONG_COMMAND 131 /* Command not supported */ +#define HA_ERR_OLD_FILE 132 /* old databasfile */ +#define HA_ERR_NO_ACTIVE_RECORD 133 /* No record read in update() */ +#define HA_ERR_RECORD_DELETED 134 /* A record is not there */ +#define HA_ERR_RECORD_FILE_FULL 135 /* No more room in file */ +#define HA_ERR_INDEX_FILE_FULL 136 /* No more room in file */ +#define HA_ERR_END_OF_FILE 137 /* end in next/prev/first/last */ +#define HA_ERR_UNSUPPORTED 138 /* unsupported extension used */ +#define HA_ERR_TO_BIG_ROW 139 /* Too big row */ +#define HA_WRONG_CREATE_OPTION 140 /* Wrong create option */ +#define HA_ERR_FOUND_DUPP_UNIQUE 141 /* Dupplicate unique on write */ +#define HA_ERR_UNKNOWN_CHARSET 142 /* Can't open charset */ +#define HA_ERR_WRONG_MRG_TABLE_DEF 143 /* conflicting tables in MERGE */ +#define HA_ERR_CRASHED_ON_REPAIR 144 /* Last (automatic?) repair failed */ +#define HA_ERR_CRASHED_ON_USAGE 145 /* Table must be repaired */ +#define HA_ERR_LOCK_WAIT_TIMEOUT 146 +#define HA_ERR_LOCK_TABLE_FULL 147 +#define HA_ERR_READ_ONLY_TRANSACTION 148 /* Updates not allowed */ +#define HA_ERR_LOCK_DEADLOCK 149 +#define HA_ERR_CANNOT_ADD_FOREIGN 150 /* Cannot add a foreign key constr. */ +#define HA_ERR_NO_REFERENCED_ROW 151 /* Cannot add a child row */ +#define HA_ERR_ROW_IS_REFERENCED 152 /* Cannot delete a parent row */ +#define HA_ERR_NO_SAVEPOINT 153 /* No savepoint with that name */ +#define HA_ERR_NON_UNIQUE_BLOCK_SIZE 154 /* Non unique key block size */ +#define HA_ERR_NO_SUCH_TABLE 155 /* The table does not exist in engine */ +#define HA_ERR_TABLE_EXIST 156 /* The table existed in storage engine */ +#define HA_ERR_NO_CONNECTION 157 /* Could not connect to storage engine */ +/* NULLs are not supported in spatial index */ +#define HA_ERR_NULL_IN_SPATIAL 158 +#define HA_ERR_TABLE_DEF_CHANGED 159 /* The table changed in storage engine */ +/* There's no partition in table for given value */ +#define HA_ERR_NO_PARTITION_FOUND 160 +#define HA_ERR_RBR_LOGGING_FAILED 161 /* Row-based binlogging of row failed */ +#define HA_ERR_DROP_INDEX_FK 162 /* Index needed in foreign key constr */ +/* + Upholding foreign key constraints would lead to a duplicate key error + in some other table. +*/ +#define HA_ERR_FOREIGN_DUPLICATE_KEY 163 +/* The table changed in storage engine */ +#define HA_ERR_TABLE_NEEDS_UPGRADE 164 +#define HA_ERR_TABLE_READONLY 165 /* The table is not writable */ + +#define HA_ERR_AUTOINC_READ_FAILED 166 /* Failed to get next autoinc value */ +#define HA_ERR_AUTOINC_ERANGE 167 /* Failed to set row autoinc value */ +#define HA_ERR_GENERIC 168 /* Generic error */ +/* row not actually updated: new values same as the old values */ +#define HA_ERR_RECORD_IS_THE_SAME 169 +/* It is not possible to log this statement */ +#define HA_ERR_LOGGING_IMPOSSIBLE 170 +#define HA_ERR_TABLESPACE_EXIST 171 +/* The event was corrupt, leading to illegal data being read */ +#define HA_ERR_CORRUPT_EVENT 172 +#define HA_ERR_NEW_FILE 173 /* New file format */ +/* The event could not be processed no other handler error happened */ +#define HA_ERR_ROWS_EVENT_APPLY 174 +#define HA_ERR_INITIALIZATION 175 /* Error during initialization */ +#define HA_ERR_FILE_TOO_SHORT 176 /* File too short */ +#define HA_ERR_WRONG_CRC 177 /* Wrong CRC on page */ +#define HA_ERR_LOCK_OR_ACTIVE_TRANSACTION 178 +#define HA_ERR_NO_SUCH_TABLESPACE 179 +#define HA_ERR_TABLESPACE_NOT_EMPTY 180 +#define HA_ERR_TABLESPACE_DATAFILE_EXIST 181 +#define HA_ERR_ROW_NOT_VISIBLE 182 +#define HA_ERR_LAST 182 /* Copy of last error nr */ + +/* Number of different errors */ +#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) + + /* Other constants */ + +#define HA_NAMELEN 64 /* Max length of saved filename */ +#define NO_SUCH_KEY (~(uint)0) /* used as a key no. */ + +typedef ulong key_part_map; +#define HA_WHOLE_KEY (~(key_part_map)0) + + /* Intern constants in databases */ + + /* bits in _search */ +#define SEARCH_FIND 1 +#define SEARCH_NO_FIND 2 +#define SEARCH_SAME 4 +#define SEARCH_BIGGER 8 +#define SEARCH_SMALLER 16 +#define SEARCH_SAVE_BUFF 32 +#define SEARCH_UPDATE 64 +#define SEARCH_PREFIX 128 +#define SEARCH_LAST 256 +#define MBR_CONTAIN 512 +#define MBR_INTERSECT 1024 +#define MBR_WITHIN 2048 +#define MBR_DISJOINT 4096 +#define MBR_EQUAL 8192 +#define MBR_DATA 16384 +#define SEARCH_NULL_ARE_EQUAL 32768 /* NULL in keys are equal */ +#define SEARCH_NULL_ARE_NOT_EQUAL 65536 /* NULL in keys are not equal */ +/* Use this when inserting a key in position order */ +#define SEARCH_INSERT SEARCH_NULL_ARE_NOT_EQUAL*2 +/* Only part of the key is specified while reading */ +#define SEARCH_PART_KEY SEARCH_INSERT*2 +/* Used when user key (key 2) contains transaction id's */ +#define SEARCH_USER_KEY_HAS_TRANSID SEARCH_PART_KEY*2 +/* Used when page key (key 1) contains transaction id's */ +#define SEARCH_PAGE_KEY_HAS_TRANSID SEARCH_USER_KEY_HAS_TRANSID*2 + + /* bits in opt_flag */ +#define QUICK_USED 1 +#define READ_CACHE_USED 2 +#define READ_CHECK_USED 4 +#define KEY_READ_USED 8 +#define WRITE_CACHE_USED 16 +#define OPT_NO_ROWS 32 + + /* bits in update */ +#define HA_STATE_CHANGED 1 /* Database has changed */ +#define HA_STATE_AKTIV 2 /* Has a current record */ +#define HA_STATE_WRITTEN 4 /* Record is written */ +#define HA_STATE_DELETED 8 +#define HA_STATE_NEXT_FOUND 16 /* Next found record (record before) */ +#define HA_STATE_PREV_FOUND 32 /* Prev found record (record after) */ +#define HA_STATE_NO_KEY 64 /* Last read didn't find record */ +#define HA_STATE_KEY_CHANGED 128 +#define HA_STATE_WRITE_AT_END 256 /* set in _ps_find_writepos */ +#define HA_STATE_BUFF_SAVED 512 /* If current keybuff is info->buff */ +#define HA_STATE_ROW_CHANGED 1024 /* To invalide ROW cache */ +#define HA_STATE_EXTEND_BLOCK 2048 +#define HA_STATE_RNEXT_SAME 4096 /* rnext_same occupied lastkey2 */ + +/* myisampack expects no more than 32 field types. */ +enum en_fieldtype { + FIELD_LAST=-1,FIELD_NORMAL,FIELD_SKIP_ENDSPACE,FIELD_SKIP_PRESPACE, + FIELD_SKIP_ZERO,FIELD_BLOB,FIELD_CONSTANT,FIELD_INTERVALL,FIELD_ZERO, + FIELD_VARCHAR,FIELD_CHECK, + FIELD_enum_val_count +}; + +enum data_file_type { + STATIC_RECORD, DYNAMIC_RECORD, COMPRESSED_RECORD, BLOCK_RECORD +}; + +/* For key ranges */ + +/* from -inf */ +#define NO_MIN_RANGE 1 + +/* to +inf */ +#define NO_MAX_RANGE 2 + +/* X < key, i.e. not including the left endpoint */ +#define NEAR_MIN 4 + +/* X > key, i.e. not including the right endpoint */ +#define NEAR_MAX 8 + +/* + This flag means that index is a unique index, and the interval is + equivalent to "AND(keypart_i = const_i)", where all of const_i are not NULLs. +*/ +#define UNIQUE_RANGE 16 + +/* + This flag means that the interval is equivalent to + "AND(keypart_i = const_i)", where not all key parts may be used but all of + const_i are not NULLs. +*/ +#define EQ_RANGE 32 + +/* + This flag has the same meaning as UNIQUE_RANGE, except that for at least + one keypart the condition is "keypart IS NULL". +*/ +#define NULL_RANGE 64 + +#define GEOM_FLAG 128 + +#define SKIP_RANGE 256 +#define EMPTY_RANGE 512 + +typedef struct st_key_range +{ + const uchar *key; + uint length; + key_part_map keypart_map; + enum ha_rkey_function flag; +} key_range; + +typedef struct st_key_multi_range +{ + key_range start_key; + key_range end_key; + char *ptr; /* Free to use by caller (ptr to row etc) */ + uint range_flag; /* key range flags see above */ +} KEY_MULTI_RANGE; + + +/* For number of records */ +#ifdef BIG_TABLES +#define rows2double(A) ulonglong2double(A) +typedef my_off_t ha_rows; +#else +#define rows2double(A) (double) (A) +typedef ulong ha_rows; +#endif + +#define HA_POS_ERROR (~ (ha_rows) 0) +#define HA_OFFSET_ERROR (~ (my_off_t) 0) + +#if SYSTEM_SIZEOF_OFF_T == 4 +#define MAX_FILE_SIZE INT_MAX32 +#else +#define MAX_FILE_SIZE LONGLONG_MAX +#endif + +#define HA_VARCHAR_PACKLENGTH(field_length) ((field_length) < 256 ? 1 :2) + +/* invalidator function reference for Query Cache */ +typedef void (* invalidator_by_filename)(const char * filename); + +#endif /* _my_base_h */ diff --git a/NetService/include/Mysql/my_bit.h b/NetService/include/Mysql/my_bit.h new file mode 100644 index 00000000..2e464e89 --- /dev/null +++ b/NetService/include/Mysql/my_bit.h @@ -0,0 +1,109 @@ +/* + Some useful bit functions +*/ + +C_MODE_START +#ifdef HAVE_INLINE + +extern const char _my_bits_nbits[256]; +extern const uchar _my_bits_reverse_table[256]; + +/* + Find smallest X in 2^X >= value + This can be used to divide a number with value by doing a shift instead +*/ + +STATIC_INLINE uint my_bit_log2(ulong value) +{ + uint bit; + for (bit=0 ; value > 1 ; value>>=1, bit++) ; + return bit; +} + +STATIC_INLINE uint my_count_bits(ulonglong v) +{ +#if SIZEOF_LONG_LONG > 4 + /* The following code is a bit faster on 16 bit machines than if we would + only shift v */ + ulong v2=(ulong) (v >> 32); + return (uint) (uchar) (_my_bits_nbits[(uchar) v] + + _my_bits_nbits[(uchar) (v >> 8)] + + _my_bits_nbits[(uchar) (v >> 16)] + + _my_bits_nbits[(uchar) (v >> 24)] + + _my_bits_nbits[(uchar) (v2)] + + _my_bits_nbits[(uchar) (v2 >> 8)] + + _my_bits_nbits[(uchar) (v2 >> 16)] + + _my_bits_nbits[(uchar) (v2 >> 24)]); +#else + return (uint) (uchar) (_my_bits_nbits[(uchar) v] + + _my_bits_nbits[(uchar) (v >> 8)] + + _my_bits_nbits[(uchar) (v >> 16)] + + _my_bits_nbits[(uchar) (v >> 24)]); +#endif +} + +STATIC_INLINE uint my_count_bits_ushort(ushort v) +{ + return _my_bits_nbits[v]; +} + + +/* + Next highest power of two + + SYNOPSIS + my_round_up_to_next_power() + v Value to check + + RETURN + Next or equal power of 2 + Note: 0 will return 0 + + NOTES + Algorithm by Sean Anderson, according to: + http://graphics.stanford.edu/~seander/bithacks.html + (Orignal code public domain) + + Comments shows how this works with 01100000000000000000000000001011 +*/ + +STATIC_INLINE uint32 my_round_up_to_next_power(uint32 v) +{ + v--; /* 01100000000000000000000000001010 */ + v|= v >> 1; /* 01110000000000000000000000001111 */ + v|= v >> 2; /* 01111100000000000000000000001111 */ + v|= v >> 4; /* 01111111110000000000000000001111 */ + v|= v >> 8; /* 01111111111111111100000000001111 */ + v|= v >> 16; /* 01111111111111111111111111111111 */ + return v+1; /* 10000000000000000000000000000000 */ +} + +STATIC_INLINE uint32 my_clear_highest_bit(uint32 v) +{ + uint32 w=v >> 1; + w|= w >> 1; + w|= w >> 2; + w|= w >> 4; + w|= w >> 8; + w|= w >> 16; + return v & w; +} + +STATIC_INLINE uint32 my_reverse_bits(uint32 key) +{ + return + (_my_bits_reverse_table[ key & 255] << 24) | + (_my_bits_reverse_table[(key>> 8) & 255] << 16) | + (_my_bits_reverse_table[(key>>16) & 255] << 8) | + _my_bits_reverse_table[(key>>24) ]; +} + +#else /* HAVE_INLINE */ +extern uint my_bit_log2(ulong value); +extern uint32 my_round_up_to_next_power(uint32 v); +uint32 my_clear_highest_bit(uint32 v); +uint32 my_reverse_bits(uint32 key); +extern uint my_count_bits(ulonglong v); +extern uint my_count_bits_ushort(ushort v); +#endif /* HAVE_INLINE */ +C_MODE_END diff --git a/NetService/include/Mysql/my_bitmap.h b/NetService/include/Mysql/my_bitmap.h new file mode 100644 index 00000000..d8c9a0c2 --- /dev/null +++ b/NetService/include/Mysql/my_bitmap.h @@ -0,0 +1,182 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _my_bitmap_h_ +#define _my_bitmap_h_ + +#define MY_BIT_NONE (~(uint) 0) + +#include + +typedef uint32 my_bitmap_map; + +typedef struct st_bitmap +{ + my_bitmap_map *bitmap; + uint n_bits; /* number of bits occupied by the above */ + my_bitmap_map last_word_mask; + my_bitmap_map *last_word_ptr; + /* + mutex will be acquired for the duration of each bitmap operation if + thread_safe flag in bitmap_init was set. Otherwise, we optimize by not + acquiring the mutex + */ +#ifdef THREAD + pthread_mutex_t *mutex; +#endif +} MY_BITMAP; + +#ifdef __cplusplus +extern "C" { +#endif +extern void create_last_word_mask(MY_BITMAP *map); +extern my_bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits, + my_bool thread_safe); +extern my_bool bitmap_is_clear_all(const MY_BITMAP *map); +extern my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size); +extern my_bool bitmap_is_set_all(const MY_BITMAP *map); +extern my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2); +extern my_bool bitmap_is_overlapping(const MY_BITMAP *map1, + const MY_BITMAP *map2); +extern my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit); +extern my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit); +extern my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit); +extern uint bitmap_set_next(MY_BITMAP *map); +extern uint bitmap_get_first(const MY_BITMAP *map); +extern uint bitmap_get_first_set(const MY_BITMAP *map); +extern uint bitmap_bits_set(const MY_BITMAP *map); +extern void bitmap_free(MY_BITMAP *map); +extern void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit); +extern void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size); +extern void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2); +extern void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2); +extern void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2); +extern void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2); +extern void bitmap_invert(MY_BITMAP *map); +extern void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2); + +extern uint bitmap_lock_set_next(MY_BITMAP *map); +extern void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit); +#ifdef NOT_USED +extern uint bitmap_lock_bits_set(const MY_BITMAP *map); +extern my_bool bitmap_lock_is_set_all(const MY_BITMAP *map); +extern uint bitmap_lock_get_first(const MY_BITMAP *map); +extern uint bitmap_lock_get_first_set(const MY_BITMAP *map); +extern my_bool bitmap_lock_is_subset(const MY_BITMAP *map1, + const MY_BITMAP *map2); +extern my_bool bitmap_lock_is_prefix(const MY_BITMAP *map, uint prefix_size); +extern my_bool bitmap_lock_is_set(const MY_BITMAP *map, uint bitmap_bit); +extern my_bool bitmap_lock_is_clear_all(const MY_BITMAP *map); +extern my_bool bitmap_lock_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2); +extern void bitmap_lock_set_all(MY_BITMAP *map); +extern void bitmap_lock_clear_all(MY_BITMAP *map); +extern void bitmap_lock_set_bit(MY_BITMAP *map, uint bitmap_bit); +extern void bitmap_lock_flip_bit(MY_BITMAP *map, uint bitmap_bit); +extern void bitmap_lock_set_prefix(MY_BITMAP *map, uint prefix_size); +extern void bitmap_lock_intersect(MY_BITMAP *map, const MY_BITMAP *map2); +extern void bitmap_lock_subtract(MY_BITMAP *map, const MY_BITMAP *map2); +extern void bitmap_lock_union(MY_BITMAP *map, const MY_BITMAP *map2); +extern void bitmap_lock_xor(MY_BITMAP *map, const MY_BITMAP *map2); +extern void bitmap_lock_invert(MY_BITMAP *map); +#endif +/* Fast, not thread safe, bitmap functions */ +#define bitmap_buffer_size(bits) (((bits)+31)/32)*4 +#define no_bytes_in_map(map) (((map)->n_bits + 7)/8) +#define no_words_in_map(map) (((map)->n_bits + 31)/32) +#define bytes_word_aligned(bytes) (4*((bytes + 3)/4)) +#define _bitmap_set_bit(MAP, BIT) (((uchar*)(MAP)->bitmap)[(BIT) / 8] \ + |= (1 << ((BIT) & 7))) +#define _bitmap_flip_bit(MAP, BIT) (((uchar*)(MAP)->bitmap)[(BIT) / 8] \ + ^= (1 << ((BIT) & 7))) +#define _bitmap_clear_bit(MAP, BIT) (((uchar*)(MAP)->bitmap)[(BIT) / 8] \ + &= ~ (1 << ((BIT) & 7))) +#define _bitmap_is_set(MAP, BIT) (uint) (((uchar*)(MAP)->bitmap)[(BIT) / 8] \ + & (1 << ((BIT) & 7))) +/* + WARNING! + + The below symbols are inline functions in DEBUG builds and macros in + non-DEBUG builds. The latter evaluate their 'bit' argument twice. + + NEVER use an increment/decrement operator with the 'bit' argument. + It would work with DEBUG builds, but fails later in production builds! + + FORBIDDEN: bitmap_set_bit($my_bitmap, (field++)->field_index); +*/ +#ifndef DBUG_OFF +static inline void +bitmap_set_bit(MY_BITMAP *map,uint bit) +{ + DBUG_ASSERT(bit < (map)->n_bits); + _bitmap_set_bit(map,bit); +} +static inline void +bitmap_flip_bit(MY_BITMAP *map,uint bit) +{ + DBUG_ASSERT(bit < (map)->n_bits); + _bitmap_flip_bit(map,bit); +} +static inline void +bitmap_clear_bit(MY_BITMAP *map,uint bit) +{ + DBUG_ASSERT(bit < (map)->n_bits); + _bitmap_clear_bit(map,bit); +} +static inline uint +bitmap_is_set(const MY_BITMAP *map,uint bit) +{ + DBUG_ASSERT(bit < (map)->n_bits); + return _bitmap_is_set(map,bit); +} +#else +#define bitmap_set_bit(MAP, BIT) _bitmap_set_bit(MAP, BIT) +#define bitmap_flip_bit(MAP, BIT) _bitmap_flip_bit(MAP, BIT) +#define bitmap_clear_bit(MAP, BIT) _bitmap_clear_bit(MAP, BIT) +#define bitmap_is_set(MAP, BIT) _bitmap_is_set(MAP, BIT) +#endif + +static inline my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) +{ + *(map1)->last_word_ptr|= (map1)->last_word_mask; + *(map2)->last_word_ptr|= (map2)->last_word_mask; + return memcmp((map1)->bitmap, (map2)->bitmap, 4*no_words_in_map((map1)))==0; +} + +#define bitmap_clear_all(MAP) \ + { memset((MAP)->bitmap, 0, 4*no_words_in_map((MAP))); } +#define bitmap_set_all(MAP) \ + (memset((MAP)->bitmap, 0xFF, 4*no_words_in_map((MAP)))) + +/** + check, set and clear a bit of interest of an integer. + + If the bit is out of range @retval -1. Otherwise + bit_is_set @return 0 or 1 reflecting the bit is set or not; + bit_do_set @return 1 (bit is set 1) + bit_do_clear @return 0 (bit is cleared to 0) +*/ + +#define bit_is_set(I,B) (sizeof(I) * CHAR_BIT > (B) ? \ + (((I) & (1ULL << (B))) == 0 ? 0 : 1) : -1) +#define bit_do_set(I,B) (sizeof(I) * CHAR_BIT > (B) ? \ + ((I) |= (1ULL << (B)), 1) : -1) +#define bit_do_clear(I,B) (sizeof(I) * CHAR_BIT > (B) ? \ + ((I) &= ~(1ULL << (B)), 0) : -1) + +#ifdef __cplusplus +} +#endif + +#endif /* _my_bitmap_h_ */ diff --git a/NetService/include/Mysql/my_charsets.h b/NetService/include/Mysql/my_charsets.h new file mode 100644 index 00000000..ecb0de94 --- /dev/null +++ b/NetService/include/Mysql/my_charsets.h @@ -0,0 +1,57 @@ +/* Copyright (C) 2008 Sun Microsystems, Inc. + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Character set configuration (hard-coded) */ +#define HAVE_CHARSET_armscii8 1 +#define HAVE_CHARSET_ascii 1 +#define HAVE_CHARSET_big5 1 +#define HAVE_CHARSET_cp1250 1 +#define HAVE_CHARSET_cp1251 1 +#define HAVE_CHARSET_cp1256 1 +#define HAVE_CHARSET_cp1257 1 +#define HAVE_CHARSET_cp850 1 +#define HAVE_CHARSET_cp852 1 +#define HAVE_CHARSET_cp866 1 +#define HAVE_CHARSET_cp932 1 +#define HAVE_CHARSET_dec8 1 +#define HAVE_CHARSET_eucjpms 1 +#define HAVE_CHARSET_euckr 1 +#define HAVE_CHARSET_gb2312 1 +#define HAVE_CHARSET_gbk 1 +#define HAVE_CHARSET_greek 1 +#define HAVE_CHARSET_hebrew 1 +#define HAVE_CHARSET_hp8 1 +#define HAVE_CHARSET_keybcs2 1 +#define HAVE_CHARSET_koi8r 1 +#define HAVE_CHARSET_koi8u 1 +#define HAVE_CHARSET_latin1 1 +#define HAVE_CHARSET_latin2 1 +#define HAVE_CHARSET_latin5 1 +#define HAVE_CHARSET_latin7 1 +#define HAVE_CHARSET_macce 1 +#define HAVE_CHARSET_macroman 1 +#define HAVE_CHARSET_sjis 1 +#define HAVE_CHARSET_swe7 1 +#define HAVE_CHARSET_tis620 1 +#define HAVE_CHARSET_ucs2 1 +#define HAVE_CHARSET_ujis 1 +#define HAVE_CHARSET_utf16 1 +#define HAVE_CHARSET_utf32 1 +#define HAVE_CHARSET_utf8mb3 1 +#define HAVE_CHARSET_utf8mb4 1 +#define HAVE_UCA_COLLATIONS 1 +#define MYSQL_DEFAULT_CHARSET_NAME "latin1" +#define MYSQL_DEFAULT_COLLATION_NAME "latin1_swedish_ci" +#define USE_MB 1 diff --git a/NetService/include/Mysql/my_config.h b/NetService/include/Mysql/my_config.h new file mode 100644 index 00000000..adea8dbe --- /dev/null +++ b/NetService/include/Mysql/my_config.h @@ -0,0 +1,295 @@ + +/* Headers we may want to use. */ +/* #undef HAVE_ALLOCA_H */ +/* #undef HAVE_ARPA_INET_H */ +/* #undef HAVE_CRYPT_H */ +/* #undef HAVE_DIRENT_H */ +/* #undef HAVE_EXECINFO_H */ +#define HAVE_FCNTL_H 1 +/* #undef HAVE_FENV_H */ +#define HAVE_FLOAT_H 1 +/* #undef HAVE_FPU_CONTROL_H */ +/* #undef HAVE_GRP_H */ +/* #undef HAVE_IEEEFP_H */ +#define HAVE_LIMITS_H 1 +#define HAVE_MALLOC_H 1 +#define HAVE_MEMORY_H 1 +/* #undef HAVE_NETINET_IN_H */ +/* #undef HAVE_PATHS_H */ +/* #undef HAVE_PWD_H */ +/* #undef HAVE_SCHED_H */ +/* #undef HAVE_SELECT_H */ +#define HAVE_STDDEF_H 1 +#define HAVE_STDLIB_H 1 +/* #undef HAVE_STRINGS_H */ +#define HAVE_STRING_H 1 +/* #undef HAVE_SYNCH_H */ +/* #undef HAVE_SYSENT_H */ +/* #undef HAVE_SYS_FPU_H */ +/* #undef HAVE_SYS_IOCTL_H */ +/* #undef HAVE_SYS_IPC_H */ +/* #undef HAVE_SYS_MMAN_H */ +/* #undef HAVE_SYS_PRCTL_H */ +/* #undef HAVE_SYS_SELECT_H */ +/* #undef HAVE_SYS_SHM_H */ +/* #undef HAVE_SYS_SOCKET_H */ +#define HAVE_SYS_STAT_H 1 +/* #undef HAVE_SYS_STREAM_H */ +#define HAVE_SYS_TIMEB_H 1 +#define HAVE_SYS_TYPES_H 1 +/* #undef HAVE_SYS_UN_H */ +/* #undef HAVE_TERMIOS_H */ +/* #undef HAVE_TERMIO_H */ +/* #undef HAVE_UNISTD_H */ +/* #undef HAVE_UTIME_H */ + +/* Functions we may want to use. */ +#define HAVE_ACCESS 1 +/* #undef HAVE_AIOWAIT */ +/* #undef HAVE_ALARM */ +/* #undef HAVE_ALLOCA */ +/* #undef HAVE_BCMP */ +/* #undef HAVE_BFILL */ +/* #undef HAVE_BMOVE */ +/* #undef HAVE_BZERO */ +/* #undef HAVE_CLOCK_GETTIME */ +/* #undef HAVE_COMPRESS */ +/* #undef HAVE_CRYPT */ +/* #undef HAVE_DLERROR */ +/* #undef HAVE_DLOPEN */ +/* #undef HAVE_FCHMOD */ +/* #undef HAVE_FCNTL */ +/* #undef HAVE_FCONVERT */ +/* #undef HAVE_FDATASYNC */ +/* #undef HAVE_FESETROUND */ +/* #undef HAVE_FINITE */ +/* #undef HAVE_FP_EXCEPT */ +/* #undef HAVE_FSEEKO */ +/* #undef HAVE_FSYNC */ +/* #undef HAVE_GETADDRINFO */ +#define HAVE_GETCWD 1 +/* #undef HAVE_GETHOSTBYADDR_R */ +/* #undef HAVE_GETHOSTBYNAME_R */ +/* #undef HAVE_GETHRTIME */ +/* #undef HAVE_GETNAMEINFO */ +/* #undef HAVE_GETPAGESIZE */ +/* #undef HAVE_GETPASS */ +/* #undef HAVE_GETPASSPHRASE */ +/* #undef HAVE_GETPWNAM */ +/* #undef HAVE_GETPWUID */ +/* #undef HAVE_GETRLIMIT */ +/* #undef HAVE_GETRUSAGE */ +/* #undef HAVE_GETWD */ +/* #undef HAVE_GMTIME_R */ +/* #undef HAVE_INITGROUPS */ +/* #undef HAVE_ISNAN */ +#define HAVE_LDIV 1 +/* #undef HAVE_LOCALTIME_R */ +/* #undef HAVE_LOG2 */ +#define HAVE_LONGJMP 1 +/* #undef HAVE_LSTAT */ +/* #undef HAVE_MADVISE */ +/* #undef HAVE_DECL_MADVISE */ +/* #undef HAVE_MALLINFO */ +#define HAVE_MEMCPY 1 +#define HAVE_MEMCPY 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMMOVE 1 +/* #undef HAVE_MKSTEMP */ +/* #undef HAVE_MLOCK */ +/* #undef HAVE_MLOCKALL */ +/* #undef HAVE_MMAP */ +/* #undef HAVE_MMAP64 */ +#define HAVE_PERROR 1 +/* #undef HAVE_POLL */ +/* #undef HAVE_PREAD */ +/* #undef HAVE_PTHREAD_ATTR_CREATE */ +/* #undef HAVE_PTHREAD_ATTR_GETSTACKSIZE */ +/* #undef HAVE_PTHREAD_ATTR_SETPRIO */ +/* #undef HAVE_PTHREAD_ATTR_SETSCHEDPARAM */ +/* #undef HAVE_PTHREAD_ATTR_SETSCOPE */ +/* #undef HAVE_PTHREAD_ATTR_SETSTACKSIZE */ +/* #undef HAVE_PTHREAD_CONDATTR_CREATE */ +/* #undef HAVE_PTHREAD_INIT */ +/* #undef HAVE_PTHREAD_KEY_DELETE */ +/* #undef HAVE_PTHREAD_KEY_DELETE */ +/* #undef HAVE_PTHREAD_KILL */ +/* #undef HAVE_PTHREAD_RWLOCK_RDLOCK */ +/* #undef HAVE_PTHREAD_SETPRIO_NP */ +/* #undef HAVE_PTHREAD_SETSCHEDPARAM */ +/* #undef HAVE_PTHREAD_SIGMASK */ +/* #undef HAVE_PTHREAD_THREADMASK */ +/* #undef HAVE_PTHREAD_YIELD_NP */ +/* #undef HAVE_READDIR_R */ +/* #undef HAVE_READLINK */ +/* #undef HAVE_REALPATH */ +#define HAVE_RENAME 1 +/* #undef HAVE_RINT */ +/* #undef HAVE_SCHED_YIELD */ +/* #undef HAVE_SELECT */ +/* #undef HAVE_SETFD */ +/* #undef HAVE_SETFILEPOINTER */ +/* #undef HAVE_SIGACTION */ +/* #undef HAVE_SIGTHREADMASK */ +/* #undef HAVE_SIGWAIT */ +/* #undef HAVE_SLEEP */ +/* #undef HAVE_SNPRINTF */ +/* #undef HAVE_STPCPY */ +#define HAVE_STRERROR 1 +/* #undef HAVE_STRLCPY */ +#define HAVE_STRNLEN 1 +#define HAVE_STRPBRK 1 +/* #undef HAVE_STRSEP */ +#define HAVE_STRSTR 1 +/* #undef HAVE_STRTOK_R */ +/* #undef HAVE_STRTOK_R */ +#define HAVE_STRTOL 1 +/* #undef HAVE_STRTOLL */ +#define HAVE_STRTOUL 1 +/* #undef HAVE_STRTOULL */ +#define HAVE_TELL 1 +/* #undef HAVE_THR_SETCONCURRENCY */ +/* #undef HAVE_THR_YIELD */ +/* #undef HAVE_VASPRINTF */ +#define HAVE_VSNPRINTF 1 + +/* Symbols we may use */ +/* #undef HAVE_SYS_ERRLIST */ +/* used by stacktrace functions */ +/* #undef HAVE_BSS_START */ + +/* Does "struct timespec" have a "sec" and "nsec" field? */ +/* #undef HAVE_TIMESPEC_TS_SEC */ + +/* Types we may use */ +#define SIZEOF_CHAR 1 +#if SIZEOF_CHAR +# define HAVE_CHAR 1 +#endif + +#define SIZEOF_CHARP 4 +#if SIZEOF_CHARP +# define HAVE_CHARP 1 +#endif + +#define SIZEOF_SHORT 2 +#if SIZEOF_SHORT +# define HAVE_SHORT 1 +#endif + +#define SIZEOF_INT 4 +#if SIZEOF_INT +# define HAVE_INT 1 +#endif + +#define SIZEOF_LONG 4 +#if SIZEOF_LONG +# define HAVE_LONG 1 +#endif + +#define SIZEOF_LONG_LONG 8 +#if SIZEOF_LONG_LONG +# define HAVE_LONG_LONG 1 +#endif + +#define SIZEOF_OFF_T 4 +#if SIZEOF_OFF_T +# define HAVE_OFF_T 1 +#endif + +/* #undef SIZEOF_SIGSET_T */ +#if SIZEOF_SIGSET_T +# define HAVE_SIGSET_T 1 +#endif + +#define SIZEOF_SIZE_T 4 +#if SIZEOF_SIZE_T +# define HAVE_SIZE_T 1 +#endif + +/* #undef SIZEOF_UCHAR */ +#if SIZEOF_UCHAR +# define HAVE_UCHAR 1 +#endif + +/* #undef SIZEOF_UINT */ +#if SIZEOF_UINT +# define HAVE_UINT 1 +#endif + +/* #undef SIZEOF_ULONG */ +#if SIZEOF_ULONG +# define HAVE_ULONG 1 +#endif + +/* #undef SIZEOF_INT8 */ +#if SIZEOF_INT8 +# define HAVE_INT8 1 +#endif +/* #undef SIZEOF_UINT8 */ +#if SIZEOF_UINT8 +# define HAVE_UINT8 1 +#endif + +/* #undef SIZEOF_INT16 */ +#if SIZEOF_INT16 +# define HAVE_INT16 1 +#endif +/* #undef SIZEOF_UINT16 */ +#if SIZEOF_UINT16 +# define HAVE_UINT16 1 +#endif + +/* #undef SIZEOF_INT32 */ +#if SIZEOF_INT32 +# define HAVE_INT32 1 +#endif +/* #undef SIZEOF_UINT32 */ +#if SIZEOF_UINT32 +# define HAVE_UINT32 1 +#endif +/* #undef SIZEOF_U_INT32_T */ +#if SIZEOF_U_INT32_T +# define HAVE_U_INT32_T 1 +#endif + +/* #undef SIZEOF_INT64 */ +#if SIZEOF_INT64 +# define HAVE_INT64 1 +#endif +/* #undef SIZEOF_UINT64 */ +#if SIZEOF_UINT64 +# define HAVE_UINT64 1 +#endif + +/* #undef SIZEOF_SOCKLEN_T */ +#if SIZEOF_SOCKLEN_T +# define HAVE_SOCKLEN_T 1 +#endif + +/* XXX mysql_client_test uses this -- rip it out, please! */ +#define MAX_INDEXES 64 + +#define QSORT_TYPE_IS_VOID 1 +#define RETQSORTTYPE void + +#define SIGNAL_RETURN_TYPE_IS_VOID 1 +#define RETSIGTYPE void + +/* #undef WORDS_BIGENDIAN */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler calls + it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +# define inline +#endif + +#define TIME_WITH_SYS_TIME 1 + +#define STACK_DIRECTION -1 + +#define SHAREDIR "share" +#define THREAD 1 +#define THREAD_SAFE_CLIENT 1 + +#define DEFAULT_CHARSET_HOME "C:/mysql/" diff --git a/NetService/include/Mysql/my_dbug.h b/NetService/include/Mysql/my_dbug.h new file mode 100644 index 00000000..c4a2f881 --- /dev/null +++ b/NetService/include/Mysql/my_dbug.h @@ -0,0 +1,140 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _dbug_h +#define _dbug_h + +#ifdef __cplusplus +extern "C" { +#endif +#if !defined(DBUG_OFF) && !defined(_lint) + +struct _db_stack_frame_ { + const char *func; /* function name of the previous stack frame */ + const char *file; /* filename of the function of previous frame */ + uint level; /* this nesting level, highest bit enables tracing */ + struct _db_stack_frame_ *prev; /* pointer to the previous frame */ +}; + +struct _db_code_state_; +extern my_bool _dbug_on_; +extern my_bool _db_keyword_(struct _db_code_state_ *, const char *, int); +extern int _db_explain_(struct _db_code_state_ *cs, char *buf, size_t len); +extern int _db_explain_init_(char *buf, size_t len); +extern int _db_is_pushed_(void); +extern void _db_setjmp_(void); +extern void _db_longjmp_(void); +extern void _db_process_(const char *name); +extern void _db_push_(const char *control); +extern void _db_pop_(void); +extern void _db_set_(const char *control); +extern void _db_set_init_(const char *control); +extern void _db_enter_(const char *_func_, const char *_file_, uint _line_, + struct _db_stack_frame_ *_stack_frame_); +extern void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_); +extern void _db_pargs_(uint _line_,const char *keyword); +extern void _db_doprnt_ _VARARGS((const char *format,...)) + ATTRIBUTE_FORMAT(printf, 1, 2); +extern void _db_dump_(uint _line_,const char *keyword, + const unsigned char *memory, size_t length); +extern void _db_end_(void); +extern void _db_lock_file_(void); +extern void _db_unlock_file_(void); +extern FILE *_db_fp_(void); +extern void _db_flush_(); + +#define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_; \ + _db_enter_ (a,__FILE__,__LINE__,&_db_stack_frame_) +#define DBUG_LEAVE _db_return_ (__LINE__, &_db_stack_frame_) +#define DBUG_RETURN(a1) do {DBUG_LEAVE; return(a1);} while(0) +#define DBUG_VOID_RETURN do {DBUG_LEAVE; return;} while(0) +#define DBUG_EXECUTE(keyword,a1) \ + do {if (_db_keyword_(0, (keyword), 0)) { a1 }} while(0) +#define DBUG_EXECUTE_IF(keyword,a1) \ + do {if (_db_keyword_(0, (keyword), 1)) { a1 }} while(0) +#define DBUG_EVALUATE(keyword,a1,a2) \ + (_db_keyword_(0,(keyword), 0) ? (a1) : (a2)) +#define DBUG_EVALUATE_IF(keyword,a1,a2) \ + (_db_keyword_(0,(keyword), 1) ? (a1) : (a2)) +#define DBUG_PRINT(keyword,arglist) \ + do {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;} while(0) +#define DBUG_PUSH(a1) _db_push_ (a1) +#define DBUG_POP() _db_pop_ () +#define DBUG_SET(a1) _db_set_ (a1) +#define DBUG_SET_INITIAL(a1) _db_set_init_ (a1) +#define DBUG_PROCESS(a1) _db_process_(a1) +#define DBUG_FILE _db_fp_() +#define DBUG_SETJMP(a1) (_db_setjmp_ (), setjmp (a1)) +#define DBUG_LONGJMP(a1,a2) (_db_longjmp_ (), longjmp (a1, a2)) +#define DBUG_DUMP(keyword,a1,a2) _db_dump_(__LINE__,keyword,a1,a2) +#define DBUG_END() _db_end_ () +#define DBUG_LOCK_FILE _db_lock_file_() +#define DBUG_UNLOCK_FILE _db_unlock_file_() +#define DBUG_ASSERT(A) assert(A) +#define DBUG_EXPLAIN(buf,len) _db_explain_(0, (buf),(len)) +#define DBUG_EXPLAIN_INITIAL(buf,len) _db_explain_init_((buf),(len)) +#define DEBUGGER_OFF do { _dbug_on_= 0; } while(0) +#define DEBUGGER_ON do { _dbug_on_= 1; } while(0) +#define IF_DBUG(A) A +#ifndef __WIN__ +#define DBUG_ABORT() (_db_flush_(), abort()) +#else +/* + Avoid popup with abort/retry/ignore buttons. When BUG#31745 is fixed we can + call abort() instead of _exit(3) (now it would cause a "test signal" popup). +*/ +#include +#define DBUG_ABORT() (_db_flush_(),\ + (void)_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE),\ + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR),\ + _exit(3)) +#endif + +#else /* No debugger */ + +#define DBUG_ENTER(a1) +#define DBUG_LEAVE +#define DBUG_RETURN(a1) do { return(a1); } while(0) +#define DBUG_VOID_RETURN do { return; } while(0) +#define DBUG_EXECUTE(keyword,a1) do { } while(0) +#define DBUG_EXECUTE_IF(keyword,a1) do { } while(0) +#define DBUG_EVALUATE(keyword,a1,a2) (a2) +#define DBUG_EVALUATE_IF(keyword,a1,a2) (a2) +#define DBUG_PRINT(keyword,arglist) do { } while(0) +#define DBUG_PUSH(a1) do { } while(0) +#define DBUG_SET(a1) do { } while(0) +#define DBUG_SET_INITIAL(a1) do { } while(0) +#define DBUG_POP() do { } while(0) +#define DBUG_PROCESS(a1) do { } while(0) +#define DBUG_SETJMP(a1) setjmp(a1) +#define DBUG_LONGJMP(a1) longjmp(a1) +#define DBUG_DUMP(keyword,a1,a2) do { } while(0) +#define DBUG_END() do { } while(0) +#define DBUG_ASSERT(A) do { } while(0) +#define DBUG_LOCK_FILE do { } while(0) +#define DBUG_FILE (stderr) +#define DBUG_UNLOCK_FILE do { } while(0) +#define DBUG_EXPLAIN(buf,len) +#define DBUG_EXPLAIN_INITIAL(buf,len) +#define DEBUGGER_OFF do { } while(0) +#define DEBUGGER_ON do { } while(0) +#define IF_DBUG(A) +#define DBUG_ABORT() abort() + +#endif +#ifdef __cplusplus +} +#endif +#endif diff --git a/NetService/include/Mysql/my_dir.h b/NetService/include/Mysql/my_dir.h new file mode 100644 index 00000000..90d708ac --- /dev/null +++ b/NetService/include/Mysql/my_dir.h @@ -0,0 +1,109 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _my_dir_h +#define _my_dir_h +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MY_DIR_H +#define MY_DIR_H + +#include + + /* Defines for my_dir and my_stat */ + +#define MY_S_IFMT S_IFMT /* type of file */ +#define MY_S_IFDIR S_IFDIR /* directory */ +#define MY_S_IFCHR S_IFCHR /* character special */ +#define MY_S_IFBLK S_IFBLK /* block special */ +#define MY_S_IFREG S_IFREG /* regular */ +#define MY_S_IFIFO S_IFIFO /* fifo */ +#define MY_S_ISUID S_ISUID /* set user id on execution */ +#define MY_S_ISGID S_ISGID /* set group id on execution */ +#define MY_S_ISVTX S_ISVTX /* save swapped text even after use */ +#define MY_S_IREAD S_IREAD /* read permission, owner */ +#define MY_S_IWRITE S_IWRITE /* write permission, owner */ +#define MY_S_IEXEC S_IEXEC /* execute/search permission, owner */ + +#define MY_S_ISDIR(m) (((m) & MY_S_IFMT) == MY_S_IFDIR) +#define MY_S_ISCHR(m) (((m) & MY_S_IFMT) == MY_S_IFCHR) +#define MY_S_ISBLK(m) (((m) & MY_S_IFMT) == MY_S_IFBLK) +#define MY_S_ISREG(m) (((m) & MY_S_IFMT) == MY_S_IFREG) +#define MY_S_ISFIFO(m) (((m) & MY_S_IFMT) == MY_S_IFIFO) + +#define MY_DONT_SORT 512 /* my_lib; Don't sort files */ +#define MY_WANT_STAT 1024 /* my_lib; stat files */ + + /* typedefs for my_dir & my_stat */ + +#ifdef USE_MY_STAT_STRUCT + +typedef struct my_stat +{ + dev_t st_dev; /* major & minor device numbers */ + ino_t st_ino; /* inode number */ + ushort st_mode; /* file permissons (& suid sgid .. bits) */ + short st_nlink; /* number of links to file */ + ushort st_uid; /* user id */ + ushort st_gid; /* group id */ + dev_t st_rdev; /* more major & minor device numbers (???) */ + off_t st_size; /* size of file */ + time_t st_atime; /* time for last read */ + time_t st_mtime; /* time for last contens modify */ + time_t st_ctime; /* time for last inode or contents modify */ +} MY_STAT; + +#else + +#if(_MSC_VER) +#define MY_STAT struct _stati64 /* 64 bit file size */ +#else +#define MY_STAT struct stat /* Orginal struct have what we need */ +#endif + +#endif /* USE_MY_STAT_STRUCT */ + +/* Struct describing one file returned from my_dir */ +typedef struct fileinfo +{ + char *name; + MY_STAT *mystat; +} FILEINFO; + +typedef struct st_my_dir /* Struct returned from my_dir */ +{ + /* + These members are just copies of parts of DYNAMIC_ARRAY structure, + which is allocated right after the end of MY_DIR structure (MEM_ROOT + for storing names is also resides there). We've left them here because + we don't want to change code that uses my_dir. + */ + struct fileinfo *dir_entry; + uint number_off_files; +} MY_DIR; + +extern MY_DIR *my_dir(const char *path,myf MyFlags); +extern void my_dirend(MY_DIR *buffer); +extern MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags); +extern int my_fstat(int filenr, MY_STAT *stat_area, myf MyFlags); + +#endif /* MY_DIR_H */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/NetService/include/Mysql/my_getopt.h b/NetService/include/Mysql/my_getopt.h new file mode 100644 index 00000000..7cbad607 --- /dev/null +++ b/NetService/include/Mysql/my_getopt.h @@ -0,0 +1,86 @@ +/* Copyright (C) 2002-2004 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _my_getopt_h +#define _my_getopt_h + +C_MODE_START + +#define GET_NO_ARG 1 +#define GET_BOOL 2 +#define GET_INT 3 +#define GET_UINT 4 +#define GET_LONG 5 +#define GET_ULONG 6 +#define GET_LL 7 +#define GET_ULL 8 +#define GET_STR 9 +#define GET_STR_ALLOC 10 +#define GET_DISABLED 11 +#define GET_ENUM 12 +#define GET_SET 13 +#define GET_DOUBLE 14 + +#define GET_ASK_ADDR 128 +#define GET_TYPE_MASK 127 + +enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG }; + +struct st_typelib; + +struct my_option +{ + const char *name; /* Name of the option */ + int id; /* unique id or short option */ + const char *comment; /* option comment, for autom. --help */ + uchar **value; /* The variable value */ + uchar **u_max_value; /* The user def. max variable value */ + struct st_typelib *typelib; /* Pointer to possible values */ + ulong var_type; + enum get_opt_arg_type arg_type; + longlong def_value; /* Default value */ + longlong min_value; /* Min allowed value */ + longlong max_value; /* Max allowed value */ + longlong sub_size; /* Subtract this from given value */ + long block_size; /* Value should be a mult. of this */ + void *app_type; /* To be used by an application */ +}; + +typedef my_bool (* my_get_one_option) (int, const struct my_option *, char * ); +typedef void (* my_error_reporter) (enum loglevel level, const char *format, ... ); + +extern char *disabled_my_option; +extern my_bool my_getopt_print_errors; +extern my_bool my_getopt_skip_unknown; +extern my_error_reporter my_getopt_error_reporter; + +extern int handle_options (int *argc, char ***argv, + const struct my_option *longopts, my_get_one_option); +extern void my_cleanup_options(const struct my_option *options); +extern void my_print_help(const struct my_option *options); +extern void my_print_variables(const struct my_option *options); +extern void my_getopt_register_get_addr(uchar ** (*func_addr)(const char *, uint, + const struct my_option *, int *)); + +ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp, + my_bool *fix); +longlong getopt_ll_limit_value(longlong, const struct my_option *, + my_bool *fix); +my_bool getopt_compare_strings(const char *s, const char *t, uint length); + +C_MODE_END + +#endif /* _my_getopt_h */ + diff --git a/NetService/include/Mysql/my_global.h b/NetService/include/Mysql/my_global.h new file mode 100644 index 00000000..131507c0 --- /dev/null +++ b/NetService/include/Mysql/my_global.h @@ -0,0 +1,1616 @@ +/* Copyright (C) 2000-2003 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* This is the include file that should be included 'first' in every C file. */ + +#ifndef _global_h +#define _global_h + +/* + InnoDB depends on some MySQL internals which other plugins should not + need. This is because of InnoDB's foreign key support, "safe" binlog + truncation, and other similar legacy features. + + We define accessors for these internals unconditionally, but do not + expose them in mysql/plugin.h. They are declared in ha_innodb.h for + InnoDB's use. +*/ +#define INNODB_COMPATIBILITY_HOOKS + +#ifdef __CYGWIN__ +/* We use a Unix API, so pretend it's not Windows */ +#undef WIN +#undef WIN32 +#undef _WIN +#undef _WIN32 +#undef _WIN64 +#undef __WIN__ +#undef __WIN32__ +#define HAVE_ERRNO_AS_DEFINE +#endif /* __CYGWIN__ */ + +#if defined(__QNXNTO__) && !defined(FD_SETSIZE) +#define FD_SETSIZE 1024 /* Max number of file descriptor bits in + fd_set, used when calling 'select' + Must be defined before including + "sys/select.h" and "sys/time.h" + */ +#endif + + +/* to make command line shorter we'll define USE_PRAGMA_INTERFACE here */ +#ifdef USE_PRAGMA_IMPLEMENTATION +#define USE_PRAGMA_INTERFACE +#endif + +#if defined(i386) && !defined(__i386__) +#define __i386__ +#endif + +/* Macros to make switching between C and C++ mode easier */ +#ifdef __cplusplus +#define C_MODE_START extern "C" { +#define C_MODE_END } +#define STATIC_CAST(TYPE) static_cast +#else +#define C_MODE_START +#define C_MODE_END +#define STATIC_CAST(TYPE) (TYPE) +#endif + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) +#include +#else +#include +#if defined(__cplusplus) && defined(inline) +#undef inline /* fix configure problem */ +#endif +#endif /* _WIN32... */ + +#include + +/* Make it easier to add conditional code for windows */ +#ifdef __WIN__ +#define IF_WIN(A,B) (A) +#else +#define IF_WIN(A,B) (B) +#endif + +#ifndef EMBEDDED_LIBRARY +#ifdef WITH_NDB_BINLOG +#define HAVE_NDB_BINLOG 1 +#endif +#endif /* !EMBEDDED_LIBRARY */ + +#ifndef EMBEDDED_LIBRARY +#define HAVE_REPLICATION +#define HAVE_EXTERNAL_CLIENT +#endif + +/* Some defines to avoid ifdefs in the code */ +#ifndef NETWARE_YIELD +#define NETWARE_YIELD +#define NETWARE_SET_SCREEN_MODE(A) +#endif + +/* Workaround for _LARGE_FILES and _LARGE_FILE_API incompatibility on AIX */ +#if defined(_AIX) && defined(_LARGE_FILE_API) +#undef _LARGE_FILE_API +#endif + +/* + The macros below are used to allow build of Universal/fat binaries of + MySQL and MySQL applications under darwin. +*/ +#if defined(__APPLE__) && defined(__MACH__) +# undef SIZEOF_CHARP +# undef SIZEOF_SHORT +# undef SIZEOF_INT +# undef SIZEOF_LONG +# undef SIZEOF_LONG_LONG +# undef SIZEOF_OFF_T +# undef WORDS_BIGENDIAN +# define SIZEOF_SHORT 2 +# define SIZEOF_INT 4 +# define SIZEOF_LONG_LONG 8 +# define SIZEOF_OFF_T 8 +# if defined(__i386__) || defined(__ppc__) +# define SIZEOF_CHARP 4 +# define SIZEOF_LONG 4 +# elif defined(__x86_64__) || defined(__ppc64__) +# define SIZEOF_CHARP 8 +# define SIZEOF_LONG 8 +# else +# error Building FAT binary for an unknown architecture. +# endif +# if defined(__ppc__) || defined(__ppc64__) +# define WORDS_BIGENDIAN +# endif +#endif /* defined(__APPLE__) && defined(__MACH__) */ + + +/* + The macros below are borrowed from include/linux/compiler.h in the + Linux kernel. Use them to indicate the likelyhood of the truthfulness + of a condition. This serves two purposes - newer versions of gcc will be + able to optimize for branch predication, which could yield siginficant + performance gains in frequently executed sections of the code, and the + other reason to use them is for documentation +*/ + +#if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96) +#define __builtin_expect(x, expected_value) (x) +#endif + +/** + The semantics of builtin_expect() are that + 1) its two arguments are long + 2) it's likely that they are == + Those of our likely(x) are that x can be bool/int/longlong/pointer. +*/ +#define likely(x) __builtin_expect(((x) != 0),1) +#define unlikely(x) __builtin_expect(((x) != 0),0) + +/* + The macros below are useful in optimising places where it has been + discovered that cache misses stall the process and where a prefetch + of the cache line can improve matters. This is available in GCC 3.1.1 + and later versions. + PREFETCH_READ says that addr is going to be used for reading and that + it is to be kept in caches if possible for a while + PREFETCH_WRITE also says that the item to be cached is likely to be + updated. + The *LOCALITY scripts are also available for experimentation purposes + mostly and should only be used if they are verified to improve matters. + For more input see GCC manual (available in GCC 3.1.1 and later) +*/ + +#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR > 10) +#define PREFETCH_READ(addr) __builtin_prefetch(addr, 0, 3) +#define PREFETCH_WRITE(addr) \ + __builtin_prefetch(addr, 1, 3) +#define PREFETCH_READ_LOCALITY(addr, locality) \ + __builtin_prefetch(addr, 0, locality) +#define PREFETCH_WRITE_LOCALITY(addr, locality) \ + __builtin_prefetch(addr, 1, locality) +#else +#define PREFETCH_READ(addr) +#define PREFETCH_READ_LOCALITY(addr, locality) +#define PREFETCH_WRITE(addr) +#define PREFETCH_WRITE_LOCALITY(addr, locality) +#endif + +/* + The following macro is used to ensure that code often used in most + SQL statements and definitely for parts of the SQL processing are + kept in a code segment by itself. This has the advantage that the + risk of common code being overlapping in caches of the CPU is less. + This can be a cause of big performance problems. + Routines should be put in this category with care and when they are + put there one should also strive to make as much of the error handling + as possible (or uncommon code of the routine) to execute in a + separate method to avoid moving to much code to this code segment. + + It is very easy to use, simply add HOT_METHOD at the end of the + function declaration. + For more input see GCC manual (available in GCC 2.95 and later) +*/ + +#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR > 94) +#define HOT_METHOD \ + __attribute__ ((section ("hot_code_section"))) +#else +#define HOT_METHOD +#endif + +/* + The following macro is used to ensure that popular global variables + are located next to each other to avoid that they contend for the + same cache lines. + + It is very easy to use, simply add HOT_DATA at the end of the declaration + of the variable, the variable must be initialised because of the way + that linker works so a declaration using HOT_DATA should look like: + uint global_hot_data HOT_DATA = 0; + For more input see GCC manual (available in GCC 2.95 and later) +*/ + +#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR > 94) +#define HOT_DATA \ + __attribute__ ((section ("hot_data_section"))) +#else +#define HOT_DATA +#endif + +/* + now let's figure out if inline functions are supported + autoconf defines 'inline' to be empty, if not +*/ +#define inline_test_1(X) X ## 1 +#define inline_test_2(X) inline_test_1(X) +#if inline_test_2(inline) != 1 +#define HAVE_INLINE +#endif +#undef inline_test_2 +#undef inline_test_1 +/* helper macro for "instantiating" inline functions */ +#define STATIC_INLINE static inline + +/* + The following macros are used to control inlining a bit more than + usual. These macros are used to ensure that inlining always or + never occurs (independent of compilation mode). + For more input see GCC manual (available in GCC 3.1.1 and later) +*/ + +#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR > 10) +#define ALWAYS_INLINE __attribute__ ((always_inline)) +#define NEVER_INLINE __attribute__ ((noinline)) +#else +#define ALWAYS_INLINE +#define NEVER_INLINE +#endif + + +/* Fix problem with S_ISLNK() on Linux */ +#if defined(TARGET_OS_LINUX) || defined(__GLIBC__) +#undef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + +/* + Temporary solution to solve bug#7156. Include "sys/types.h" before + the thread headers, else the function madvise() will not be defined +*/ +#if defined(HAVE_SYS_TYPES_H) && ( defined(sun) || defined(__sun) ) +#include +#endif + +/* The client defines this to avoid all thread code */ +#if defined(UNDEF_THREADS_HACK) +#undef THREAD +#undef HAVE_LINUXTHREADS +#undef HAVE_NPTL +#endif + +#ifdef HAVE_THREADS_WITHOUT_SOCKETS +/* MIT pthreads does not work with unix sockets */ +#undef HAVE_SYS_UN_H +#endif + +#define __EXTENSIONS__ 1 /* We want some extension */ +#ifndef __STDC_EXT__ +#define __STDC_EXT__ 1 /* To get large file support on hpux */ +#endif + +/* + Solaris 9 include file refers to X/Open document + + System Interfaces and Headers, Issue 5 + + saying we should define _XOPEN_SOURCE=500 to get POSIX.1c prototypes, + but apparently other systems (namely FreeBSD) don't agree. + + On a newer Solaris 10, the above file recognizes also _XOPEN_SOURCE=600. + Furthermore, it tests that if a program requires older standard + (_XOPEN_SOURCE<600 or _POSIX_C_SOURCE<200112L) it cannot be + run on a new compiler (that defines _STDC_C99) and issues an #error. + It's also an #error if a program requires new standard (_XOPEN_SOURCE=600 + or _POSIX_C_SOURCE=200112L) and a compiler does not define _STDC_C99. + + To add more to this mess, Sun Studio C compiler defines _STDC_C99 while + C++ compiler does not! + + So, in a desperate attempt to get correct prototypes for both + C and C++ code, we define either _XOPEN_SOURCE=600 or _XOPEN_SOURCE=500 + depending on the compiler's announced C standard support. + + Cleaner solutions are welcome. +*/ +#ifdef __sun +#if __STDC_VERSION__ - 0 >= 199901L +#define _XOPEN_SOURCE 600 +#else +#define _XOPEN_SOURCE 500 +#endif +#endif + +#if defined(THREAD) && !defined(__WIN__) +#ifndef _POSIX_PTHREAD_SEMANTICS +#define _POSIX_PTHREAD_SEMANTICS /* We want posix threads */ +#endif + +#if !defined(SCO) +#define _REENTRANT 1 /* Some thread libraries require this */ +#endif +#if !defined(_THREAD_SAFE) && !defined(_AIX) +#define _THREAD_SAFE /* Required for OSF1 */ +#endif +#if defined(HPUX10) || defined(HPUX11) +C_MODE_START /* HPUX needs this, signal.h bug */ +#include +C_MODE_END +#else +#include /* AIX must have this included first */ +#endif +#if !defined(SCO) && !defined(_REENTRANT) +#define _REENTRANT 1 /* Threads requires reentrant code */ +#endif +#endif /* THREAD */ + +/* Go around some bugs in different OS and compilers */ +#ifdef _AIX /* By soren@t.dk */ +#define _H_STRINGS +#define _SYS_STREAM_H +/* #define _AIX32_CURSES */ /* XXX: this breaks AIX 4.3.3 (others?). */ +#define ulonglong2double(A) my_ulonglong2double(A) +#define my_off_t2double(A) my_ulonglong2double(A) +C_MODE_START +double my_ulonglong2double(unsigned long long A); +C_MODE_END +#endif /* _AIX */ + +#ifdef HAVE_BROKEN_SNPRINTF /* HPUX 10.20 don't have this defined */ +#undef HAVE_SNPRINTF +#endif +#ifdef HAVE_BROKEN_PREAD +/* + pread()/pwrite() are not 64 bit safe on HP-UX 11.0 without + installing the kernel patch PHKL_20349 or greater +*/ +#undef HAVE_PREAD +#undef HAVE_PWRITE +#endif +#if defined(HAVE_BROKEN_INLINE) && !defined(__cplusplus) +#undef inline +#define inline +#endif + +#ifdef UNDEF_HAVE_GETHOSTBYNAME_R /* For OSF4.x */ +#undef HAVE_GETHOSTBYNAME_R +#endif +#ifdef UNDEF_HAVE_INITGROUPS /* For AIX 4.3 */ +#undef HAVE_INITGROUPS +#endif + +/* gcc/egcs issues */ + +#if defined(__GNUC) && defined(__EXCEPTIONS) +#error "Please add -fno-exceptions to CXXFLAGS and reconfigure/recompile" +#endif + + +/* Fix a bug in gcc 2.8.0 on IRIX 6.2 */ +#if SIZEOF_LONG == 4 && defined(__LONG_MAX__) && (__GNUC__ == 2 && __GNUC_MINOR__ == 8) +#undef __LONG_MAX__ /* Is a longlong value in gcc 2.8.0 ??? */ +#define __LONG_MAX__ 2147483647 +#endif + +/* egcs 1.1.2 has a problem with memcpy on Alpha */ +#if defined(__GNUC__) && defined(__alpha__) && ! (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)) +#define BAD_MEMCPY +#endif + +#if defined(_lint) && !defined(lint) +#define lint +#endif +#if SIZEOF_LONG_LONG > 4 && !defined(_LONG_LONG) +#define _LONG_LONG 1 /* For AIX string library */ +#endif + +#ifndef stdin +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STDDEF_H +#include +#endif + +#include +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_FLOAT_H +#include +#endif +#ifdef HAVE_FENV_H +#include /* For fesetround() */ +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_TIMEB_H +#include /* Avoid warnings on SCO */ +#endif +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif /* TIME_WITH_SYS_TIME */ +#ifdef HAVE_UNISTD_H +#include +#endif +#if defined(__cplusplus) && defined(NO_CPLUSPLUS_ALLOCA) +#undef HAVE_ALLOCA +#undef HAVE_ALLOCA_H +#endif +#ifdef HAVE_ALLOCA_H +#include +#endif + +#include /* Recommended by debian */ +/* We need the following to go around a problem with openssl on solaris */ +#if defined(HAVE_CRYPT_H) +#include +#endif + +/* + A lot of our programs uses asserts, so better to always include it + This also fixes a problem when people uses DBUG_ASSERT without including + assert.h +*/ +#include + +/* an assert that works at compile-time. only for constant expression */ +#ifdef _some_old_compiler_that_does_not_understand_the_construct_below_ +#define compile_time_assert(X) do { } while(0) +#else +#define compile_time_assert(X) \ + do \ + { \ + typedef char compile_time_assert[(X) ? 1 : -1]; \ + } while(0) +#endif + +/* Go around some bugs in different OS and compilers */ +#if defined (HPUX11) && defined(_LARGEFILE_SOURCE) +#define _LARGEFILE64_SOURCE +#endif +#if defined(_HPUX_SOURCE) && defined(HAVE_SYS_STREAM_H) +#include /* HPUX 10.20 defines ulong here. UGLY !!! */ +#define HAVE_ULONG +#endif +#if defined(HPUX10) && defined(_LARGEFILE64_SOURCE) && defined(THREAD) +/* Fix bug in setrlimit */ +#undef setrlimit +#define setrlimit cma_setrlimit64 +#endif +/* Declare madvise where it is not declared for C++, like Solaris */ +#if HAVE_MADVISE && !HAVE_DECL_MADVISE && defined(__cplusplus) +extern "C" int madvise(void *addr, size_t len, int behav); +#endif + +#ifdef __QNXNTO__ +/* This has to be after include limits.h */ +#define HAVE_ERRNO_AS_DEFINE +#define HAVE_FCNTL_LOCK +#undef HAVE_FINITE +#undef LONGLONG_MIN /* These get wrongly defined in QNX 6.2 */ +#undef LONGLONG_MAX /* standard system library 'limits.h' */ +#endif + +/* We can not live without the following defines */ + +#define USE_MYFUNC 1 /* Must use syscall indirection */ +#define MASTER 1 /* Compile without unireg */ +#define ENGLISH 1 /* Messages in English */ +#define POSIX_MISTAKE 1 /* regexp: Fix stupid spec error */ +#define USE_REGEX 1 /* We want the use the regex library */ +/* Do not define for ultra sparcs */ +#define USE_BMOVE512 1 /* Use this unless system bmove is faster */ + +#define QUOTE_ARG(x) #x /* Quote argument (before cpp) */ +#define STRINGIFY_ARG(x) QUOTE_ARG(x) /* Quote argument, after cpp */ + +/* Paranoid settings. Define I_AM_PARANOID if you are paranoid */ +#ifdef I_AM_PARANOID +#define DONT_ALLOW_USER_CHANGE 1 +#define DONT_USE_MYSQL_PWD 1 +#endif + +/* Does the system remember a signal handler after a signal ? */ +#ifndef HAVE_BSD_SIGNALS +#define DONT_REMEMBER_SIGNAL +#endif + +#if defined(_lint) || defined(FORCE_INIT_OF_VARS) +#define LINT_INIT(var) var=0 /* No uninitialize-warning */ +#else +#define LINT_INIT(var) +#endif + +#if defined(_lint) || defined(FORCE_INIT_OF_VARS) || defined(HAVE_purify) +#define PURIFY_OR_LINT_INIT(var) var=0 +#else +#define PURIFY_OR_LINT_INIT(var) +#endif + +#if !defined(HAVE_UINT) +#undef HAVE_UINT +#define HAVE_UINT +typedef unsigned int uint; +typedef unsigned short ushort; +#endif + +#define CMP_NUM(a,b) (((a) < (b)) ? -1 : ((a) == (b)) ? 0 : 1) +#define sgn(a) (((a) < 0) ? -1 : ((a) > 0) ? 1 : 0) +#define swap_variables(t, a, b) { t swap_dummy; swap_dummy= a; a= b; b= swap_dummy; } +#define test(a) ((a) ? 1 : 0) +#define set_if_bigger(a,b) do { if ((a) < (b)) (a)=(b); } while(0) +#define set_if_smaller(a,b) do { if ((a) > (b)) (a)=(b); } while(0) +#define test_all_bits(a,b) (((a) & (b)) == (b)) +#define set_bits(type, bit_count) (sizeof(type)*8 <= (bit_count) ? ~(type) 0 : ((((type) 1) << (bit_count)) - (type) 1)) +#define array_elements(A) ((uint) (sizeof(A)/sizeof(A[0]))) + +/* Define some general constants */ +#ifndef TRUE +#define TRUE (1) /* Logical true */ +#define FALSE (0) /* Logical false */ +#endif + +#if defined(__GNUC__) +#define function_volatile volatile +#define my_reinterpret_cast(A) reinterpret_cast +#define my_const_cast(A) const_cast +# ifndef GCC_VERSION +# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +# endif +#elif !defined(my_reinterpret_cast) +#define my_reinterpret_cast(A) (A) +#define my_const_cast(A) (A) +#endif + +#include + +/* + Wen using the embedded library, users might run into link problems, + duplicate declaration of __cxa_pure_virtual, solved by declaring it a + weak symbol. +*/ +#if defined(USE_MYSYS_NEW) && ! defined(DONT_DECLARE_CXA_PURE_VIRTUAL) +C_MODE_START +int __cxa_pure_virtual () __attribute__ ((weak)); +C_MODE_END +#endif + +/* From old s-system.h */ + +/* + Support macros for non ansi & other old compilers. Since such + things are no longer supported we do nothing. We keep then since + some of our code may still be needed to upgrade old customers. +*/ +#define _VARARGS(X) X +#define _STATIC_VARARGS(X) X + +/* The DBUG_ON flag always takes precedence over default DBUG_OFF */ +#if defined(DBUG_ON) && defined(DBUG_OFF) +#undef DBUG_OFF +#endif + +/* We might be forced to turn debug off, if not turned off already */ +#if (defined(FORCE_DBUG_OFF) || defined(_lint)) && !defined(DBUG_OFF) +# define DBUG_OFF +# ifdef DBUG_ON +# undef DBUG_ON +# endif +#endif + +typedef char my_bool; /* Small bool */ +#include + +#define MIN_ARRAY_SIZE 0 /* Zero or One. Gcc allows zero*/ +#define ASCII_BITS_USED 8 /* Bit char used */ +#define NEAR_F /* No near function handling */ + +/* Some types that is different between systems */ + +typedef int File; /* File descriptor */ +#ifndef Socket_defined +typedef int my_socket; /* File descriptor for sockets */ +#define INVALID_SOCKET -1 +#endif +/* Type for fuctions that handles signals */ +#define sig_handler void +C_MODE_START +typedef void (*sig_return)();/* Returns type from signal */ +C_MODE_END +#if defined(__GNUC__) && !defined(_lint) +typedef char pchar; /* Mixed prototypes can take char */ +typedef char puchar; /* Mixed prototypes can take char */ +typedef char pbool; /* Mixed prototypes can take char */ +typedef short pshort; /* Mixed prototypes can take short int */ +typedef float pfloat; /* Mixed prototypes can take float */ +#else +typedef int pchar; /* Mixed prototypes can't take char */ +typedef uint puchar; /* Mixed prototypes can't take char */ +typedef int pbool; /* Mixed prototypes can't take char */ +typedef int pshort; /* Mixed prototypes can't take short int */ +typedef double pfloat; /* Mixed prototypes can't take float */ +#endif +C_MODE_START +typedef int (*qsort_cmp)(const void *,const void *); +typedef int (*qsort_cmp2)(void*, const void *,const void *); +C_MODE_END +#define qsort_t RETQSORTTYPE /* Broken GCC cant handle typedef !!!! */ +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +/* file create flags */ + +#ifndef O_SHARE /* Probably not windows */ +#define O_SHARE 0 /* Flag to my_open for shared files */ +#ifndef O_BINARY +#define O_BINARY 0 /* Flag to my_open for binary files */ +#endif +#ifndef FILE_BINARY +#define FILE_BINARY O_BINARY /* Flag to my_fopen for binary streams */ +#endif +#ifdef HAVE_FCNTL +#define HAVE_FCNTL_LOCK +#define F_TO_EOF 0L /* Param to lockf() to lock rest of file */ +#endif +#endif /* O_SHARE */ + +#ifndef O_TEMPORARY +#define O_TEMPORARY 0 +#endif +#ifndef O_SHORT_LIVED +#define O_SHORT_LIVED 0 +#endif +#ifndef O_NOFOLLOW +#define O_NOFOLLOW 0 +#endif + +/* additional file share flags for win32 */ +#ifdef __WIN__ +#define _SH_DENYRWD 0x110 /* deny read/write mode & delete */ +#define _SH_DENYWRD 0x120 /* deny write mode & delete */ +#define _SH_DENYRDD 0x130 /* deny read mode & delete */ +#define _SH_DENYDEL 0x140 /* deny delete only */ +#endif /* __WIN__ */ + + +/* #define USE_RECORD_LOCK */ + + /* Unsigned types supported by the compiler */ +#define UNSINT8 /* unsigned int8 (char) */ +#define UNSINT16 /* unsigned int16 */ +#define UNSINT32 /* unsigned int32 */ + + /* General constants */ +#define FN_LEN 256 /* Max file name len */ +#define FN_HEADLEN 253 /* Max length of filepart of file name */ +#define FN_EXTLEN 20 /* Max length of extension (part of FN_LEN) */ +#define FN_REFLEN 512 /* Max length of full path-name */ +#define FN_EXTCHAR '.' +#define FN_HOMELIB '~' /* ~/ is used as abbrev for home dir */ +#define FN_CURLIB '.' /* ./ is used as abbrev for current dir */ +#define FN_PARENTDIR ".." /* Parent directory; Must be a string */ + +#ifndef FN_LIBCHAR +#define FN_LIBCHAR '/' +#define FN_ROOTDIR "/" +#endif + +/* + MY_FILE_MIN is Windows speciality and is used to quickly detect + the mismatch of CRT and mysys file IO usage on Windows at runtime. + CRT file descriptors can be in the range 0-2047, whereas descriptors returned + by my_open() will start with 2048. If a file descriptor with value less then + MY_FILE_MIN is passed to mysys IO function, chances are it stemms from + open()/fileno() and not my_open()/my_fileno. + + For Posix, mysys functions are light wrappers around libc, and MY_FILE_MIN + is logically 0. +*/ + +#ifdef _WIN32 +#define MY_FILE_MIN 2048 +#else +#define MY_FILE_MIN 0 +#endif + +/* + MY_NFILE is the default size of my_file_info array. + + It is larger on Windows, because it all file handles are stored in my_file_info + Default size is 16384 and this should be enough for most cases.If it is not + enough, --max-open-files with larger value can be used. + + For Posix , my_file_info array is only used to store filenames for + error reporting and its size is not a limitation for number of open files. +*/ +#ifdef _WIN32 +#define MY_NFILE (16384 + MY_FILE_MIN) +#else +#define MY_NFILE 64 +#endif + +#ifndef OS_FILE_LIMIT +#define OS_FILE_LIMIT 65535 +#endif + +/* #define EXT_IN_LIBNAME */ +/* #define FN_NO_CASE_SENCE */ +/* #define FN_UPPER_CASE TRUE */ + +/* + Io buffer size; Must be a power of 2 and a multiple of 512. May be + smaller what the disk page size. This influences the speed of the + isam btree library. eg to big to slow. +*/ +#define IO_SIZE 4096 +/* + How much overhead does malloc have. The code often allocates + something like 1024-MALLOC_OVERHEAD bytes +*/ +#ifdef SAFEMALLOC +#define MALLOC_OVERHEAD (8+24+4) +#else +#define MALLOC_OVERHEAD 8 +#endif + /* get memory in huncs */ +#define ONCE_ALLOC_INIT (uint) (4096-MALLOC_OVERHEAD) + /* Typical record cash */ +#define RECORD_CACHE_SIZE (uint) (64*1024-MALLOC_OVERHEAD) + /* Typical key cash */ +#define KEY_CACHE_SIZE (uint) (8*1024*1024-MALLOC_OVERHEAD) + /* Default size of a key cache block */ +#define KEY_CACHE_BLOCK_SIZE (uint) 1024 + + + /* Some things that this system doesn't have */ + +#define NO_HASH /* Not needed anymore */ +#ifdef _WIN32 +#define NO_DIR_LIBRARY /* Not standard dir-library */ +#endif + +/* Some defines of functions for portability */ + +#undef remove /* Crashes MySQL on SCO 5.0.0 */ +#ifndef __WIN__ +#define closesocket(A) close(A) +#ifndef ulonglong2double +#define ulonglong2double(A) ((double) (ulonglong) (A)) +#define my_off_t2double(A) ((double) (my_off_t) (A)) +#endif +#ifndef double2ulonglong +#define double2ulonglong(A) ((ulonglong) (double) (A)) +#endif +#endif + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif +#define ulong_to_double(X) ((double) (ulong) (X)) +#define SET_STACK_SIZE(X) /* Not needed on real machines */ + +#ifndef STACK_DIRECTION +#error "please add -DSTACK_DIRECTION=1 or -1 to your CPPFLAGS" +#endif + +#if !defined(HAVE_STRTOK_R) +inline char *strtok_r(char *str, const char *delim, char **saveptr) +{ + return strtok(str,delim); +} +#endif + +/* This is from the old m-machine.h file */ + +#if SIZEOF_LONG_LONG > 4 +#define HAVE_LONG_LONG 1 +#endif + +/* + Some pre-ANSI-C99 systems like AIX 5.1 and Linux/GCC 2.95 define + ULONGLONG_MAX, LONGLONG_MIN, LONGLONG_MAX; we use them if they're defined. + Also on Windows we define these constants by hand in config-win.h. +*/ + +#if defined(HAVE_LONG_LONG) && !defined(LONGLONG_MIN) +#define LONGLONG_MIN ((long long) 0x8000000000000000LL) +#define LONGLONG_MAX ((long long) 0x7FFFFFFFFFFFFFFFLL) +#endif + +#if defined(HAVE_LONG_LONG) && !defined(ULONGLONG_MAX) +/* First check for ANSI C99 definition: */ +#ifdef ULLONG_MAX +#define ULONGLONG_MAX ULLONG_MAX +#else +#define ULONGLONG_MAX ((unsigned long long)(~0ULL)) +#endif +#endif /* defined (HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)*/ + +#define INT_MIN32 (~0x7FFFFFFFL) +#define INT_MAX32 0x7FFFFFFFL +#define UINT_MAX32 0xFFFFFFFFL +#define INT_MIN24 (~0x007FFFFF) +#define INT_MAX24 0x007FFFFF +#define UINT_MAX24 0x00FFFFFF +#define INT_MIN16 (~0x7FFF) +#define INT_MAX16 0x7FFF +#define UINT_MAX16 0xFFFF +#define INT_MIN8 (~0x7F) +#define INT_MAX8 0x7F +#define UINT_MAX8 0xFF + +/* From limits.h instead */ +#ifndef DBL_MIN +#define DBL_MIN 4.94065645841246544e-324 +#define FLT_MIN ((float)1.40129846432481707e-45) +#endif +#ifndef DBL_MAX +#define DBL_MAX 1.79769313486231470e+308 +#define FLT_MAX ((float)3.40282346638528860e+38) +#endif +#ifndef SIZE_T_MAX +#define SIZE_T_MAX ~((size_t) 0) +#endif + +#ifndef isfinite +#ifdef HAVE_FINITE +#define isfinite(x) finite(x) +#else +#define finite(x) (1.0 / fabs(x) > 0.0) +#endif /* HAVE_FINITE */ +#endif /* isfinite */ + +#ifndef HAVE_ISNAN +#define isnan(x) ((x) != (x)) +#endif + +#ifdef HAVE_ISINF +/* Check if C compiler is affected by GCC bug #39228 */ +#if !defined(__cplusplus) && defined(HAVE_BROKEN_ISINF) +/* Force store/reload of the argument to/from a 64-bit double */ +static inline double my_isinf(double x) +{ + volatile double t= x; + return isinf(t); +} +#else +/* System-provided isinf() is available and safe to use */ +#define my_isinf(X) isinf(X) +#endif +#else /* !HAVE_ISINF */ +#define my_isinf(X) (!finite(X) && !isnan(X)) +#endif + +/* Define missing math constants. */ +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_E +#define M_E 2.7182818284590452354 +#endif +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 +#endif + +/* + Max size that must be added to a so that we know Size to make + adressable obj. +*/ +#if SIZEOF_CHARP == 4 +typedef long my_ptrdiff_t; +#else +typedef long long my_ptrdiff_t; +#endif + +#define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1)) +#define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double)) +/* Size to make adressable obj. */ +#define ALIGN_PTR(A, t) ((t*) MY_ALIGN((A),sizeof(t))) + /* Offset of field f in structure t */ +#define OFFSET(t, f) ((size_t)(char *)&((t *)0)->f) +#define ADD_TO_PTR(ptr,size,type) (type) ((uchar*) (ptr)+size) +#define PTR_BYTE_DIFF(A,B) (my_ptrdiff_t) ((uchar*) (A) - (uchar*) (B)) + +#define MY_DIV_UP(A, B) (((A) + (B) - 1) / (B)) +#define MY_ALIGNED_BYTE_ARRAY(N, S, T) T N[MY_DIV_UP(S, sizeof(T))] + +/* + Custom version of standard offsetof() macro which can be used to get + offsets of members in class for non-POD types (according to the current + version of C++ standard offsetof() macro can't be used in such cases and + attempt to do so causes warnings to be emitted, OTOH in many cases it is + still OK to assume that all instances of the class has the same offsets + for the same members). + + This is temporary solution which should be removed once File_parser class + and related routines are refactored. +*/ + +#define my_offsetof(TYPE, MEMBER) \ + ((size_t)((char *)&(((TYPE *)0x10)->MEMBER) - (char*)0x10)) + +#define NullS STATIC_CAST(char *)(0) +/* Nowdays we do not support MessyDos */ +#ifndef NEAR +#define NEAR /* Who needs segments ? */ +#define FAR /* On a good machine */ +#ifndef HUGE_PTR +#define HUGE_PTR +#endif +#endif +#if defined(__IBMC__) || defined(__IBMCPP__) +/* This was _System _Export but caused a lot of warnings on _AIX43 */ +#define STDCALL +#elif !defined( STDCALL) +#define STDCALL +#endif + +/* Typdefs for easyier portability */ + +#ifndef HAVE_UCHAR +typedef unsigned char uchar; /* Short for unsigned char */ +#endif + +#ifndef HAVE_INT8 +typedef signed char int8; /* Signed integer >= 8 bits */ +#endif +#ifndef HAVE_UINT8 +typedef unsigned char uint8; /* Unsigned integer >= 8 bits */ +#endif +#ifndef HAVE_INT16 +typedef short int16; +#endif +#ifndef HAVE_UINT16 +typedef unsigned short uint16; +#endif +#if SIZEOF_INT == 4 +#ifndef HAVE_INT32 +typedef int int32; +#endif +#ifndef HAVE_UINT32 +typedef unsigned int uint32; +#endif +#elif SIZEOF_LONG == 4 +#ifndef HAVE_INT32 +typedef long int32; +#endif +#ifndef HAVE_UINT32 +typedef unsigned long uint32; +#endif +#else +#error Neither int or long is of 4 bytes width +#endif + +#if !defined(HAVE_ULONG) && !defined(__USE_MISC) +typedef unsigned long ulong; /* Short for unsigned long */ +#endif +#ifndef longlong_defined +/* + Using [unsigned] long long is preferable as [u]longlong because we use + [unsigned] long long unconditionally in many places, + for example in constants with [U]LL suffix. +*/ +#if defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8 +typedef unsigned long long int ulonglong; /* ulong or unsigned long long */ +typedef long long int longlong; +#else +typedef unsigned long ulonglong; /* ulong or unsigned long long */ +typedef long longlong; +#endif +#endif +#ifndef HAVE_INT64 +typedef longlong int64; +#endif +#ifndef HAVE_UINT64 +typedef ulonglong uint64; +#endif + +#if defined(NO_CLIENT_LONG_LONG) +typedef unsigned long my_ulonglong; +#elif defined (__WIN__) +typedef unsigned __int64 my_ulonglong; +#else +typedef unsigned long long my_ulonglong; +#endif + +#if SIZEOF_CHARP == SIZEOF_INT +typedef int intptr; +#elif SIZEOF_CHARP == SIZEOF_LONG +typedef long intptr; +#elif SIZEOF_CHARP == SIZEOF_LONG_LONG +typedef long long intptr; +#else +#error sizeof(void *) is neither sizeof(int) nor sizeof(long) nor sizeof(long long) +#endif + +#define MY_ERRPTR ((void*)(intptr)1) + +#ifdef USE_RAID +/* + The following is done with a if to not get problems with pre-processors + with late define evaluation +*/ +#if SIZEOF_OFF_T == 4 +#define SYSTEM_SIZEOF_OFF_T 4 +#else +#define SYSTEM_SIZEOF_OFF_T 8 +#endif +#undef SIZEOF_OFF_T +#define SIZEOF_OFF_T 8 +#else +#define SYSTEM_SIZEOF_OFF_T SIZEOF_OFF_T +#endif /* USE_RAID */ + +#if SIZEOF_OFF_T > 4 +typedef ulonglong my_off_t; +#else +typedef unsigned long my_off_t; +#endif +#define MY_FILEPOS_ERROR (~STATIC_CAST(my_off_t)(0)) +#if !defined(__WIN__) +typedef off_t os_off_t; +#endif + +#if defined(__WIN__) +#define socket_errno WSAGetLastError() +#define SOCKET_EINTR WSAEINTR +#define SOCKET_EAGAIN WSAEINPROGRESS +#define SOCKET_ETIMEDOUT WSAETIMEDOUT +#define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK +#define SOCKET_EADDRINUSE WSAEADDRINUSE +#define SOCKET_ENFILE ENFILE +#define SOCKET_EMFILE EMFILE +#else /* Unix */ +#define socket_errno errno +#define closesocket(A) close(A) +#define SOCKET_EINTR EINTR +#define SOCKET_EAGAIN EAGAIN +#define SOCKET_ETIMEDOUT SOCKET_EINTR +#define SOCKET_EWOULDBLOCK EWOULDBLOCK +#define SOCKET_EADDRINUSE EADDRINUSE +#define SOCKET_ENFILE ENFILE +#define SOCKET_EMFILE EMFILE +#endif + +typedef uint8 int7; /* Most effective integer 0 <= x <= 127 */ +typedef short int15; /* Most effective integer 0 <= x <= 32767 */ +typedef int myf; /* Type of MyFlags in my_funcs */ + /* Macros for converting *constants* to the right type */ +#define INT8(v) (int8) (v) +#define INT16(v) (int16) (v) +#define INT32(v) (int32) (v) +#define MYF(v) STATIC_CAST(myf)(v) + +/* + Defines to make it possible to prioritize register assignments. No + longer that important with modern compilers. +*/ +#ifndef USING_X +#define reg1 register +#define reg2 register +#define reg3 register +#define reg4 register +#define reg5 register +#define reg6 register +#define reg7 register +#define reg8 register +#define reg9 register +#define reg10 register +#define reg11 register +#define reg12 register +#define reg13 register +#define reg14 register +#define reg15 register +#define reg16 register +#endif + +/* + Sometimes we want to make sure that the variable is not put into + a register in debugging mode so we can see its value in the core +*/ + +#ifndef DBUG_OFF +#define dbug_volatile volatile +#else +#define dbug_volatile +#endif + +/* Some helper macros */ +#define YESNO(X) ((X) ? "yes" : "no") + +/* Defines for time function */ +#define SCALE_SEC 100 +#define SCALE_USEC 10000 +#define MY_HOW_OFTEN_TO_ALARM 2 /* How often we want info on screen */ +#define MY_HOW_OFTEN_TO_WRITE 10000 /* How often we want info on screen */ + +/* + Define-funktions for reading and storing in machine independent format + (low byte first) +*/ + +/* Optimized store functions for Intel x86 */ +#if defined(__i386__) || defined(_WIN32) +#define sint2korr(A) (*((const int16 *) (A))) +#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \ + (((uint32) 255L << 24) | \ + (((uint32) (uchar) (A)[2]) << 16) |\ + (((uint32) (uchar) (A)[1]) << 8) | \ + ((uint32) (uchar) (A)[0])) : \ + (((uint32) (uchar) (A)[2]) << 16) |\ + (((uint32) (uchar) (A)[1]) << 8) | \ + ((uint32) (uchar) (A)[0]))) +#define sint4korr(A) (*((const long *) (A))) +#define uint2korr(A) (*((const uint16 *) (A))) +#if defined(HAVE_purify) && !defined(_WIN32) +#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\ + (((uint32) ((uchar) (A)[1])) << 8) +\ + (((uint32) ((uchar) (A)[2])) << 16)) +#else +/* + ATTENTION ! + + Please, note, uint3korr reads 4 bytes (not 3) ! + It means, that you have to provide enough allocated space ! +*/ +#define uint3korr(A) (long) (*((const unsigned int *) (A)) & 0xFFFFFF) +#endif /* HAVE_purify && !_WIN32 */ +#define uint4korr(A) (*((const uint32 *) (A))) +#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\ + (((uint32) ((uchar) (A)[1])) << 8) +\ + (((uint32) ((uchar) (A)[2])) << 16) +\ + (((uint32) ((uchar) (A)[3])) << 24)) +\ + (((ulonglong) ((uchar) (A)[4])) << 32)) +#define uint6korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) + \ + (((uint32) ((uchar) (A)[1])) << 8) + \ + (((uint32) ((uchar) (A)[2])) << 16) + \ + (((uint32) ((uchar) (A)[3])) << 24)) + \ + (((ulonglong) ((uchar) (A)[4])) << 32) + \ + (((ulonglong) ((uchar) (A)[5])) << 40)) +#define uint8korr(A) (*((const ulonglong *) (A))) +#define sint8korr(A) (*((const longlong *) (A))) +#define int2store(T,A) *((uint16*) (T))= (uint16) (A) +#define int3store(T,A) do { *(T)= (uchar) ((A));\ + *(T+1)=(uchar) (((uint) (A) >> 8));\ + *(T+2)=(uchar) (((A) >> 16)); } while (0) +#define int4store(T,A) *((long *) (T))= (long) (A) +#define int5store(T,A) do { *(T)= (uchar)((A));\ + *((T)+1)=(uchar) (((A) >> 8));\ + *((T)+2)=(uchar) (((A) >> 16));\ + *((T)+3)=(uchar) (((A) >> 24)); \ + *((T)+4)=(uchar) (((A) >> 32)); } while(0) +#define int6store(T,A) do { *(T)= (uchar)((A)); \ + *((T)+1)=(uchar) (((A) >> 8)); \ + *((T)+2)=(uchar) (((A) >> 16)); \ + *((T)+3)=(uchar) (((A) >> 24)); \ + *((T)+4)=(uchar) (((A) >> 32)); \ + *((T)+5)=(uchar) (((A) >> 40)); } while(0) +#define int8store(T,A) *((ulonglong *) (T))= (ulonglong) (A) + +typedef union { + double v; + long m[2]; +} doubleget_union; +#define doubleget(V,M) \ +do { doubleget_union _tmp; \ + _tmp.m[0] = *((const long*)(M)); \ + _tmp.m[1] = *(((const long*) (M))+1); \ + (V) = _tmp.v; } while(0) +#define doublestore(T,V) do { *((long *) T) = ((const doubleget_union *)&V)->m[0]; \ + *(((long *) T)+1) = ((const doubleget_union *)&V)->m[1]; \ + } while (0) +#define float4get(V,M) do { *((float *) &(V)) = *((const float*) (M)); } while(0) +#define float8get(V,M) doubleget((V),(M)) +#define float4store(V,M) memcpy((uchar*) V,(const uchar*) (&M),sizeof(float)) +#define floatstore(T,V) memcpy((uchar*)(T), (const uchar*)(&V),sizeof(float)) +#define floatget(V,M) memcpy((uchar*) &V,(const uchar*) (M),sizeof(float)) +#define float8store(V,M) doublestore((V),(M)) +#else + +/* + We're here if it's not a IA-32 architecture (Win32 and UNIX IA-32 defines + were done before) +*/ +#define sint2korr(A) (int16) (((int16) ((uchar) (A)[0])) +\ + ((int16) ((int16) (A)[1]) << 8)) +#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \ + (((uint32) 255L << 24) | \ + (((uint32) (uchar) (A)[2]) << 16) |\ + (((uint32) (uchar) (A)[1]) << 8) | \ + ((uint32) (uchar) (A)[0])) : \ + (((uint32) (uchar) (A)[2]) << 16) |\ + (((uint32) (uchar) (A)[1]) << 8) | \ + ((uint32) (uchar) (A)[0]))) +#define sint4korr(A) (int32) (((int32) ((uchar) (A)[0])) +\ + (((int32) ((uchar) (A)[1]) << 8)) +\ + (((int32) ((uchar) (A)[2]) << 16)) +\ + (((int32) ((int16) (A)[3]) << 24))) +#define sint8korr(A) (longlong) uint8korr(A) +#define uint2korr(A) (uint16) (((uint16) ((uchar) (A)[0])) +\ + ((uint16) ((uchar) (A)[1]) << 8)) +#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\ + (((uint32) ((uchar) (A)[1])) << 8) +\ + (((uint32) ((uchar) (A)[2])) << 16)) +#define uint4korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\ + (((uint32) ((uchar) (A)[1])) << 8) +\ + (((uint32) ((uchar) (A)[2])) << 16) +\ + (((uint32) ((uchar) (A)[3])) << 24)) +#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\ + (((uint32) ((uchar) (A)[1])) << 8) +\ + (((uint32) ((uchar) (A)[2])) << 16) +\ + (((uint32) ((uchar) (A)[3])) << 24)) +\ + (((ulonglong) ((uchar) (A)[4])) << 32)) +#define uint6korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) + \ + (((uint32) ((uchar) (A)[1])) << 8) + \ + (((uint32) ((uchar) (A)[2])) << 16) + \ + (((uint32) ((uchar) (A)[3])) << 24)) + \ + (((ulonglong) ((uchar) (A)[4])) << 32) + \ + (((ulonglong) ((uchar) (A)[5])) << 40)) +#define uint8korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\ + (((uint32) ((uchar) (A)[1])) << 8) +\ + (((uint32) ((uchar) (A)[2])) << 16) +\ + (((uint32) ((uchar) (A)[3])) << 24)) +\ + (((ulonglong) (((uint32) ((uchar) (A)[4])) +\ + (((uint32) ((uchar) (A)[5])) << 8) +\ + (((uint32) ((uchar) (A)[6])) << 16) +\ + (((uint32) ((uchar) (A)[7])) << 24))) <<\ + 32)) +#define int2store(T,A) do { uint def_temp= (uint) (A) ;\ + *((uchar*) (T))= (uchar)(def_temp); \ + *((uchar*) (T)+1)=(uchar)((def_temp >> 8)); \ + } while(0) +#define int3store(T,A) do { /*lint -save -e734 */\ + *((uchar*)(T))=(uchar) ((A));\ + *((uchar*) (T)+1)=(uchar) (((A) >> 8));\ + *((uchar*)(T)+2)=(uchar) (((A) >> 16)); \ + /*lint -restore */} while(0) +#define int4store(T,A) do { *((char *)(T))=(char) ((A));\ + *(((char *)(T))+1)=(char) (((A) >> 8));\ + *(((char *)(T))+2)=(char) (((A) >> 16));\ + *(((char *)(T))+3)=(char) (((A) >> 24)); } while(0) +#define int5store(T,A) do { *((char *)(T))= (char)((A)); \ + *(((char *)(T))+1)= (char)(((A) >> 8)); \ + *(((char *)(T))+2)= (char)(((A) >> 16)); \ + *(((char *)(T))+3)= (char)(((A) >> 24)); \ + *(((char *)(T))+4)= (char)(((A) >> 32)); \ + } while(0) +#define int6store(T,A) do { *((char *)(T))= (char)((A)); \ + *(((char *)(T))+1)= (char)(((A) >> 8)); \ + *(((char *)(T))+2)= (char)(((A) >> 16)); \ + *(((char *)(T))+3)= (char)(((A) >> 24)); \ + *(((char *)(T))+4)= (char)(((A) >> 32)); \ + *(((char *)(T))+5)= (char)(((A) >> 40)); \ + } while(0) +#define int8store(T,A) do { uint def_temp= (uint) (A), def_temp2= (uint) ((A) >> 32); \ + int4store((T),def_temp); \ + int4store((T+4),def_temp2); } while(0) +#ifdef WORDS_BIGENDIAN +#define float4store(T,A) do { *(T)= ((uchar *) &A)[3];\ + *((T)+1)=(char) ((uchar *) &A)[2];\ + *((T)+2)=(char) ((uchar *) &A)[1];\ + *((T)+3)=(char) ((uchar *) &A)[0]; } while(0) + +#define float4get(V,M) do { float def_temp;\ + ((uchar*) &def_temp)[0]=(M)[3];\ + ((uchar*) &def_temp)[1]=(M)[2];\ + ((uchar*) &def_temp)[2]=(M)[1];\ + ((uchar*) &def_temp)[3]=(M)[0];\ + (V)=def_temp; } while(0) +#define float8store(T,V) do { *(T)= ((uchar *) &V)[7];\ + *((T)+1)=(char) ((uchar *) &V)[6];\ + *((T)+2)=(char) ((uchar *) &V)[5];\ + *((T)+3)=(char) ((uchar *) &V)[4];\ + *((T)+4)=(char) ((uchar *) &V)[3];\ + *((T)+5)=(char) ((uchar *) &V)[2];\ + *((T)+6)=(char) ((uchar *) &V)[1];\ + *((T)+7)=(char) ((uchar *) &V)[0]; } while(0) + +#define float8get(V,M) do { double def_temp;\ + ((uchar*) &def_temp)[0]=(M)[7];\ + ((uchar*) &def_temp)[1]=(M)[6];\ + ((uchar*) &def_temp)[2]=(M)[5];\ + ((uchar*) &def_temp)[3]=(M)[4];\ + ((uchar*) &def_temp)[4]=(M)[3];\ + ((uchar*) &def_temp)[5]=(M)[2];\ + ((uchar*) &def_temp)[6]=(M)[1];\ + ((uchar*) &def_temp)[7]=(M)[0];\ + (V) = def_temp; } while(0) +#else +#define float4get(V,M) memcpy_fixed((uchar*) &V,(uchar*) (M),sizeof(float)) +#define float4store(V,M) memcpy_fixed((uchar*) V,(uchar*) (&M),sizeof(float)) + +#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) +#define doublestore(T,V) do { *(((char*)T)+0)=(char) ((uchar *) &V)[4];\ + *(((char*)T)+1)=(char) ((uchar *) &V)[5];\ + *(((char*)T)+2)=(char) ((uchar *) &V)[6];\ + *(((char*)T)+3)=(char) ((uchar *) &V)[7];\ + *(((char*)T)+4)=(char) ((uchar *) &V)[0];\ + *(((char*)T)+5)=(char) ((uchar *) &V)[1];\ + *(((char*)T)+6)=(char) ((uchar *) &V)[2];\ + *(((char*)T)+7)=(char) ((uchar *) &V)[3]; }\ + while(0) +#define doubleget(V,M) do { double def_temp;\ + ((uchar*) &def_temp)[0]=(M)[4];\ + ((uchar*) &def_temp)[1]=(M)[5];\ + ((uchar*) &def_temp)[2]=(M)[6];\ + ((uchar*) &def_temp)[3]=(M)[7];\ + ((uchar*) &def_temp)[4]=(M)[0];\ + ((uchar*) &def_temp)[5]=(M)[1];\ + ((uchar*) &def_temp)[6]=(M)[2];\ + ((uchar*) &def_temp)[7]=(M)[3];\ + (V) = def_temp; } while(0) +#endif /* __FLOAT_WORD_ORDER */ + +#define float8get(V,M) doubleget((V),(M)) +#define float8store(V,M) doublestore((V),(M)) +#endif /* WORDS_BIGENDIAN */ + +#endif /* __i386__ OR _WIN32 */ + +/* + Macro for reading 32-bit integer from network byte order (big-endian) + from unaligned memory location. +*/ +#define int4net(A) (int32) (((uint32) ((uchar) (A)[3])) |\ + (((uint32) ((uchar) (A)[2])) << 8) |\ + (((uint32) ((uchar) (A)[1])) << 16) |\ + (((uint32) ((uchar) (A)[0])) << 24)) +/* + Define-funktions for reading and storing in machine format from/to + short/long to/from some place in memory V should be a (not + register) variable, M is a pointer to byte +*/ + +#ifdef WORDS_BIGENDIAN + +#define ushortget(V,M) do { V = (uint16) (((uint16) ((uchar) (M)[1]))+\ + ((uint16) ((uint16) (M)[0]) << 8)); } while(0) +#define shortget(V,M) do { V = (short) (((short) ((uchar) (M)[1]))+\ + ((short) ((short) (M)[0]) << 8)); } while(0) +#define longget(V,M) do { int32 def_temp;\ + ((uchar*) &def_temp)[0]=(M)[0];\ + ((uchar*) &def_temp)[1]=(M)[1];\ + ((uchar*) &def_temp)[2]=(M)[2];\ + ((uchar*) &def_temp)[3]=(M)[3];\ + (V)=def_temp; } while(0) +#define ulongget(V,M) do { uint32 def_temp;\ + ((uchar*) &def_temp)[0]=(M)[0];\ + ((uchar*) &def_temp)[1]=(M)[1];\ + ((uchar*) &def_temp)[2]=(M)[2];\ + ((uchar*) &def_temp)[3]=(M)[3];\ + (V)=def_temp; } while(0) +#define shortstore(T,A) do { uint def_temp=(uint) (A) ;\ + *(((char*)T)+1)=(char)(def_temp); \ + *(((char*)T)+0)=(char)(def_temp >> 8); } while(0) +#define longstore(T,A) do { *(((char*)T)+3)=((A));\ + *(((char*)T)+2)=(((A) >> 8));\ + *(((char*)T)+1)=(((A) >> 16));\ + *(((char*)T)+0)=(((A) >> 24)); } while(0) + +#define floatget(V,M) memcpy_fixed((uchar*) &V,(uchar*) (M),sizeof(float)) +#define floatstore(T,V) memcpy_fixed((uchar*) (T),(uchar*)(&V),sizeof(float)) +#define doubleget(V,M) memcpy_fixed((uchar*) &V,(uchar*) (M),sizeof(double)) +#define doublestore(T,V) memcpy_fixed((uchar*) (T),(uchar*) &V,sizeof(double)) +#define longlongget(V,M) memcpy_fixed((uchar*) &V,(uchar*) (M),sizeof(ulonglong)) +#define longlongstore(T,V) memcpy_fixed((uchar*) (T),(uchar*) &V,sizeof(ulonglong)) + +#else + +#define ushortget(V,M) do { V = uint2korr(M); } while(0) +#define shortget(V,M) do { V = sint2korr(M); } while(0) +#define longget(V,M) do { V = sint4korr(M); } while(0) +#define ulongget(V,M) do { V = uint4korr(M); } while(0) +#define shortstore(T,V) int2store(T,V) +#define longstore(T,V) int4store(T,V) +#ifndef floatstore +#define floatstore(T,V) memcpy_fixed((uchar*) (T),(uchar*) (&V),sizeof(float)) +#define floatget(V,M) memcpy_fixed((uchar*) &V, (uchar*) (M), sizeof(float)) +#endif +#ifndef doubleget +#define doubleget(V,M) memcpy_fixed((uchar*) &V,(uchar*) (M),sizeof(double)) +#define doublestore(T,V) memcpy_fixed((uchar*) (T),(uchar*) &V,sizeof(double)) +#endif /* doubleget */ +#define longlongget(V,M) memcpy_fixed((uchar*) &V,(uchar*) (M),sizeof(ulonglong)) +#define longlongstore(T,V) memcpy_fixed((uchar*) (T),(uchar*) &V,sizeof(ulonglong)) + +#endif /* WORDS_BIGENDIAN */ + +/* sprintf does not always return the number of bytes :- */ +#ifdef SPRINTF_RETURNS_INT +#define my_sprintf(buff,args) sprintf args +#else +#ifdef SPRINTF_RETURNS_PTR +#define my_sprintf(buff,args) ((int)(sprintf args - buff)) +#else +#define my_sprintf(buff,args) ((ulong) sprintf args, (ulong) strlen(buff)) +#endif +#endif + +#ifndef THREAD +#define thread_safe_increment(V,L) (V)++ +#define thread_safe_decrement(V,L) (V)-- +#define thread_safe_add(V,C,L) (V)+=(C) +#define thread_safe_sub(V,C,L) (V)-=(C) +#define statistic_increment(V,L) (V)++ +#define statistic_decrement(V,L) (V)-- +#define statistic_add(V,C,L) (V)+=(C) +#define statistic_sub(V,C,L) (V)-=(C) +#endif + +#if defined(HAVE_CHARSET_utf8mb3) || defined(HAVE_CHARSET_utf8mb4) +#define MYSQL_UNIVERSAL_CLIENT_CHARSET "utf8" +#else +#define MYSQL_UNIVERSAL_CLIENT_CHARSET MYSQL_DEFAULT_CHARSET_NAME +#endif + +#if defined(EMBEDDED_LIBRARY) && !defined(HAVE_EMBEDDED_PRIVILEGE_CONTROL) +#define NO_EMBEDDED_ACCESS_CHECKS +#endif + +#ifdef HAVE_DLOPEN +#if defined(__WIN__) +#define dlsym(lib, name) GetProcAddress((HMODULE)lib, name) +#define dlopen(libname, unused) LoadLibraryEx(libname, NULL, 0) +#define dlclose(lib) FreeLibrary((HMODULE)lib) +#elif defined(HAVE_DLFCN_H) +#include +#endif +#endif + +/* FreeBSD 2.2.2 does not define RTLD_NOW) */ +#ifndef RTLD_NOW +#define RTLD_NOW 1 +#endif + +#ifndef HAVE_DLERROR +#define dlerror() "" +#endif + + +#ifndef __NETWARE__ +/* + * Include standard definitions of operator new and delete. + */ +#ifdef __cplusplus +#include +#endif +#else +/* + * Define placement versions of operator new and operator delete since + * we don't have when building for Netware. + */ +#ifdef __cplusplus +inline void *operator new(size_t, void *ptr) { return ptr; } +inline void *operator new[](size_t, void *ptr) { return ptr; } +inline void operator delete(void*, void*) { /* Do nothing */ } +inline void operator delete[](void*, void*) { /* Do nothing */ } +#endif +#endif + +/* Length of decimal number represented by INT32. */ +#define MY_INT32_NUM_DECIMAL_DIGITS 11 + +/* Length of decimal number represented by INT64. */ +#define MY_INT64_NUM_DECIMAL_DIGITS 21 + +/* Define some useful general macros (should be done after all headers). */ +#if !defined(max) +#define max(a, b) ((a) > (b) ? (a) : (b)) +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif +/* + Only Linux is known to need an explicit sync of the directory to make sure a + file creation/deletion/renaming in(from,to) this directory durable. +*/ +#ifdef TARGET_OS_LINUX +#define NEED_EXPLICIT_SYNC_DIR 1 +#else +/* + On linux default rwlock scheduling policy is good enough for + waiting_threads.c, on other systems use our special implementation + (which is slower). + + QQ perhaps this should be tested in configure ? how ? +*/ +#define WT_RWLOCKS_USE_MUTEXES 1 +#endif + +#if !defined(__cplusplus) && !defined(bool) +#define bool In_C_you_should_use_my_bool_instead() +#endif + +/* Provide __func__ macro definition for platforms that miss it. */ +#if __STDC_VERSION__ < 199901L +# if __GNUC__ >= 2 +# define __func__ __FUNCTION__ +# else +# define __func__ "" +# endif +#elif defined(_MSC_VER) +# if _MSC_VER < 1300 +# define __func__ "" +# else +# define __func__ __FUNCTION__ +# endif +#elif defined(__BORLANDC__) +# define __func__ __FUNC__ +#else +# define __func__ "" +#endif + +#ifndef HAVE_RINT +/** + All integers up to this number can be represented exactly as double precision + values (DBL_MANT_DIG == 53 for IEEE 754 hardware). +*/ +#define MAX_EXACT_INTEGER ((1LL << DBL_MANT_DIG) - 1) + +/** + rint(3) implementation for platforms that do not have it. + Always rounds to the nearest integer with ties being rounded to the nearest + even integer to mimic glibc's rint() behavior in the "round-to-nearest" + FPU mode. Hardware-specific optimizations are possible (frndint on x86). + Unlike this implementation, hardware will also honor the FPU rounding mode. +*/ + +static inline double rint(double x) +{ + double f, i; + f = modf(x, &i); + + /* + All doubles with absolute values > MAX_EXACT_INTEGER are even anyway, + no need to check it. + */ + if (x > 0.0) + i += (double) ((f > 0.5) || (f == 0.5 && + i <= (double) MAX_EXACT_INTEGER && + (longlong) i % 2)); + else + i -= (double) ((f < -0.5) || (f == -0.5 && + i >= (double) -MAX_EXACT_INTEGER && + (longlong) i % 2)); + return i; +} +#endif /* HAVE_RINT */ + +/* + MYSQL_PLUGIN_IMPORT macro is used to export mysqld data + (i.e variables) for usage in storage engine loadable plugins. + Outside of Windows, it is dummy. +*/ +#ifndef MYSQL_PLUGIN_IMPORT +#if (defined(_WIN32) && defined(MYSQL_DYNAMIC_PLUGIN)) +#define MYSQL_PLUGIN_IMPORT __declspec(dllimport) +#else +#define MYSQL_PLUGIN_IMPORT +#endif +#endif + +#endif /* my_global_h */ diff --git a/NetService/include/Mysql/my_libwrap.h b/NetService/include/Mysql/my_libwrap.h new file mode 100644 index 00000000..9a857947 --- /dev/null +++ b/NetService/include/Mysql/my_libwrap.h @@ -0,0 +1,27 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifdef HAVE_LIBWRAP +#include +#include +#ifdef NEED_SYS_SYSLOG_H +#include +#endif /* NEED_SYS_SYSLOG_H */ + +extern void my_fromhost(struct request_info *req); +extern int my_hosts_access(struct request_info *req); +extern char *my_eval_client(struct request_info *req); + +#endif /* HAVE_LIBWRAP */ diff --git a/NetService/include/Mysql/my_list.h b/NetService/include/Mysql/my_list.h new file mode 100644 index 00000000..775b5658 --- /dev/null +++ b/NetService/include/Mysql/my_list.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _list_h_ +#define _list_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct st_list { + struct st_list *prev,*next; + void *data; +} LIST; + +typedef int (*list_walk_action)(void *,void *); + +extern LIST *list_add(LIST *root,LIST *element); +extern LIST *list_delete(LIST *root,LIST *element); +extern LIST *list_cons(void *data,LIST *root); +extern LIST *list_reverse(LIST *root); +extern void list_free(LIST *root,unsigned int free_data); +extern unsigned int list_length(LIST *); +extern int list_walk(LIST *,list_walk_action action,unsigned char * argument); + +#define list_rest(a) ((a)->next) +#define list_push(a,b) (a)=list_cons((b),(a)) +#define list_pop(A) {LIST *old=(A); (A)=list_delete(old,old) ; my_free((unsigned char *) old,MYF(MY_FAE)); } + +#ifdef __cplusplus +} +#endif +#endif diff --git a/NetService/include/Mysql/my_md5.h b/NetService/include/Mysql/my_md5.h new file mode 100644 index 00000000..6458f27c --- /dev/null +++ b/NetService/include/Mysql/my_md5.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* See md5.c for explanation and copyright information. */ + +/* + * $FreeBSD: src/contrib/cvs/lib/md5.h,v 1.2 1999/12/11 15:10:02 peter Exp $ + */ + +/* Unlike previous versions of this code, uint32 need not be exactly + 32 bits, merely 32 bits or more. Choosing a data type which is 32 + bits instead of 64 is not important; speed is considerably more + important. ANSI guarantees that "unsigned long" will be big enough, + and always using it seems to have few disadvantages. */ +typedef uint32 cvs_uint32; + +typedef struct { + cvs_uint32 buf[4]; + cvs_uint32 bits[2]; + unsigned char in[64]; +} my_MD5Context; + +#ifdef __cplusplus +extern "C" { +#endif +void my_MD5Init (my_MD5Context *context); +void my_MD5Update (my_MD5Context *context, + unsigned char const *buf, unsigned len); +void my_MD5Final (unsigned char digest[16], + my_MD5Context *context); + +#ifdef __cplusplus +} +#endif + +#define MY_MD5_HASH(digest,buf,len) \ +do { \ + my_MD5Context ctx; \ + my_MD5Init (&ctx); \ + my_MD5Update (&ctx, buf, len); \ + my_MD5Final (digest, &ctx); \ +} while (0) diff --git a/NetService/include/Mysql/my_net.h b/NetService/include/Mysql/my_net.h new file mode 100644 index 00000000..18fb3db8 --- /dev/null +++ b/NetService/include/Mysql/my_net.h @@ -0,0 +1,114 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + thread safe version of some common functions: + my_inet_ntoa + + This file is also used to make handling of sockets and ioctl() + portable accross systems. + +*/ + +#ifndef _my_net_h +#define _my_net_h +C_MODE_START + +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_POLL +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#if !defined(__WIN__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__NETWARE__) +#include +#include +#include +#if !defined(alpha_linux_port) +#include +#endif +#endif + +#if defined(__WIN__) +#define O_NONBLOCK 1 /* For emulation of fcntl() */ + +/* + SHUT_RDWR is called SD_BOTH in windows and + is defined to 2 in winsock2.h + #define SD_BOTH 0x02 +*/ +#define SHUT_RDWR 0x02 + +#endif + +/* + On OSes which don't have the in_addr_t, we guess that using uint32 is the best + possible choice. We guess this from the fact that on HP-UX64bit & FreeBSD64bit + & Solaris64bit, in_addr_t is equivalent to uint32. And on Linux32bit too. +*/ +#ifndef HAVE_IN_ADDR_T +#define in_addr_t uint32 +#endif + +/* Thread safe or portable version of some functions */ + +void my_inet_ntoa(struct in_addr in, char *buf); + +/* + Handling of gethostbyname_r() +*/ + +#if !defined(HAVE_GETHOSTBYNAME_R) +struct hostent *my_gethostbyname_r(const char *name, + struct hostent *result, char *buffer, + int buflen, int *h_errnop); +void my_gethostbyname_r_free(); +#elif defined(HAVE_PTHREAD_ATTR_CREATE) || defined(_AIX) || defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE) +struct hostent *my_gethostbyname_r(const char *name, + struct hostent *result, char *buffer, + int buflen, int *h_errnop); +#define my_gethostbyname_r_free() +#if !defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE) && !defined(HPUX10) +#define GETHOSTBYNAME_BUFF_SIZE sizeof(struct hostent_data) +#endif /* !defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE) */ + +#elif defined(HAVE_GETHOSTBYNAME_R_RETURN_INT) +#define GETHOSTBYNAME_BUFF_SIZE sizeof(struct hostent_data) +struct hostent *my_gethostbyname_r(const char *name, + struct hostent *result, char *buffer, + int buflen, int *h_errnop); +#define my_gethostbyname_r_free() +#else +#define my_gethostbyname_r(A,B,C,D,E) gethostbyname_r((A),(B),(C),(D),(E)) +#define my_gethostbyname_r_free() +#endif /* !defined(HAVE_GETHOSTBYNAME_R) */ + +#ifndef GETHOSTBYNAME_BUFF_SIZE +#define GETHOSTBYNAME_BUFF_SIZE 2048 +#endif + +C_MODE_END +#endif diff --git a/NetService/include/Mysql/my_no_pthread.h b/NetService/include/Mysql/my_no_pthread.h new file mode 100644 index 00000000..b11dbff4 --- /dev/null +++ b/NetService/include/Mysql/my_no_pthread.h @@ -0,0 +1,50 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#if !defined(_my_no_pthread_h) && !defined(THREAD) +#define _my_no_pthread_h + + +/* + This block is to access some thread-related type definitions + even in builds which do not need thread functions, + as some variables (based on these types) are declared + even in non-threaded builds. + Case in point: 'mf_keycache.c' +*/ +#if defined(__WIN__) +#else /* Normal threads */ +#include + +#endif /* defined(__WIN__) */ + + +/* + This undefs some pthread mutex locks when one isn't using threads + to make thread safe code, that should also work in single thread + environment, easier to use. +*/ +#define pthread_mutex_init(A,B) +#define pthread_mutex_lock(A) +#define pthread_mutex_unlock(A) +#define pthread_mutex_destroy(A) +#define my_rwlock_init(A,B) +#define rw_rdlock(A) +#define rw_wrlock(A) +#define rw_unlock(A) +#define rwlock_destroy(A) + +#endif diff --git a/NetService/include/Mysql/my_nosys.h b/NetService/include/Mysql/my_nosys.h new file mode 100644 index 00000000..df5639b8 --- /dev/null +++ b/NetService/include/Mysql/my_nosys.h @@ -0,0 +1,52 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Header to remove use of my_functions in functions where we need speed and + where calls to posix functions should work +*/ +#ifndef _my_nosys_h +#define _my_nosys_h +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __MY_NOSYS__ +#define __MY_NOSYS__ + +#ifndef HAVE_STDLIB_H +#include +#endif + +#undef my_read /* Can be predefined in raid.h */ +#undef my_write +#undef my_seek +#define my_read(a,b,c,d) my_quick_read(a,b,c,d) +#define my_write(a,b,c,d) my_quick_write(a,b,c) +extern size_t my_quick_read(File Filedes,uchar *Buffer,size_t Count, + myf myFlags); +extern size_t my_quick_write(File Filedes,const uchar *Buffer,size_t Count); + +#if !defined(SAFEMALLOC) && defined(USE_HALLOC) +#define my_malloc(a,b) halloc(a,1) +#define my_no_flags_free(a) hfree(a) +#endif + +#endif /* __MY_NOSYS__ */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/NetService/include/Mysql/my_pthread.h b/NetService/include/Mysql/my_pthread.h new file mode 100644 index 00000000..ab26860d --- /dev/null +++ b/NetService/include/Mysql/my_pthread.h @@ -0,0 +1,734 @@ +/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Defines to make different thread packages compatible */ + +#ifndef _my_pthread_h +#define _my_pthread_h + +#ifndef ETIME +#define ETIME ETIMEDOUT /* For FreeBSD */ +#endif + +#ifdef __cplusplus +#define EXTERNC extern "C" +extern "C" { +#else +#define EXTERNC +#endif /* __cplusplus */ + +#if defined(__WIN__) +typedef CRITICAL_SECTION pthread_mutex_t; +typedef DWORD pthread_t; +typedef struct thread_attr { + DWORD dwStackSize ; + DWORD dwCreatingFlag ; +} pthread_attr_t ; + +typedef struct { int dummy; } pthread_condattr_t; + +/* Implementation of posix conditions */ + +typedef struct st_pthread_link { + DWORD thread_id; + struct st_pthread_link *next; +} pthread_link; + +typedef struct { + uint32 waiting; + CRITICAL_SECTION lock_waiting; + + enum { + SIGNAL= 0, + BROADCAST= 1, + MAX_EVENTS= 2 + } EVENTS; + + HANDLE events[MAX_EVENTS]; + HANDLE broadcast_block_event; + +} pthread_cond_t; + + +typedef int pthread_mutexattr_t; +#define pthread_self() GetCurrentThreadId() +#define pthread_handler_t EXTERNC void * __cdecl +typedef void * (__cdecl *pthread_handler)(void *); + +/* + Struct and macros to be used in combination with the + windows implementation of pthread_cond_timedwait +*/ + +/* + Declare a union to make sure FILETIME is properly aligned + so it can be used directly as a 64 bit value. The value + stored is in 100ns units. + */ +union ft64 { + FILETIME ft; + __int64 i64; +}; + +struct timespec { + union ft64 tv; + /* The max timeout value in millisecond for pthread_cond_timedwait */ + long max_timeout_msec; +}; + +#define set_timespec_time_nsec(ABSTIME,TIME,NSEC) do { \ + (ABSTIME).tv.i64= (TIME)+(__int64)(NSEC)/100; \ + (ABSTIME).max_timeout_msec= (long)((NSEC)/1000000); \ +} while(0) + +#define set_timespec_nsec(ABSTIME,NSEC) do { \ + union ft64 tv; \ + GetSystemTimeAsFileTime(&tv.ft); \ + set_timespec_time_nsec((ABSTIME), tv.i64, (NSEC)); \ +} while(0) + +int win_pthread_mutex_trylock(pthread_mutex_t *mutex); +int pthread_create(pthread_t *,pthread_attr_t *,pthread_handler,void *); +int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); +int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + struct timespec *abstime); +int pthread_cond_signal(pthread_cond_t *cond); +int pthread_cond_broadcast(pthread_cond_t *cond); +int pthread_cond_destroy(pthread_cond_t *cond); +int pthread_attr_init(pthread_attr_t *connect_att); +int pthread_attr_setstacksize(pthread_attr_t *connect_att,DWORD stack); +int pthread_attr_destroy(pthread_attr_t *connect_att); +struct tm *localtime_r(const time_t *timep,struct tm *tmp); +struct tm *gmtime_r(const time_t *timep,struct tm *tmp); + +void pthread_exit(void *a); +int pthread_join(pthread_t thread, void **value_ptr); + + +#define ETIMEDOUT 145 /* Win32 doesn't have this */ +#define HAVE_LOCALTIME_R 1 +#define _REENTRANT 1 +#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1 + + +#undef SAFE_MUTEX /* This will cause conflicts */ +#define pthread_key(T,V) DWORD V +#define pthread_key_create(A,B) ((*A=TlsAlloc())==0xFFFFFFFF) +#define pthread_key_delete(A) TlsFree(A) +#define my_pthread_setspecific_ptr(T,V) (!TlsSetValue((T),(V))) +#define pthread_setspecific(A,B) (!TlsSetValue((A),(B))) +#define pthread_getspecific(A) (TlsGetValue(A)) +#define my_pthread_getspecific(T,A) ((T) TlsGetValue(A)) +#define my_pthread_getspecific_ptr(T,V) ((T) TlsGetValue(V)) + +#define pthread_equal(A,B) ((A) == (B)) +#define pthread_mutex_init(A,B) (InitializeCriticalSection(A),0) +#define pthread_mutex_lock(A) (EnterCriticalSection(A),0) +#define pthread_mutex_trylock(A) win_pthread_mutex_trylock((A)) +#define pthread_mutex_unlock(A) (LeaveCriticalSection(A),0) +#define pthread_mutex_destroy(A) DeleteCriticalSection(A) +#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH) + + +/* Dummy defines for easier code */ +#define pthread_attr_setdetachstate(A,B) pthread_dummy(0) +#define pthread_attr_setscope(A,B) +#define pthread_detach_this_thread() +#define pthread_condattr_init(A) +#define pthread_condattr_destroy(A) +#define pthread_yield() SwitchToThread() + + +#else /* Normal threads */ + +#ifdef HAVE_rts_threads +#define sigwait org_sigwait +#include +#undef sigwait +#endif +#include +#ifndef _REENTRANT +#define _REENTRANT +#endif +#ifdef HAVE_THR_SETCONCURRENCY +#include /* Probably solaris */ +#endif +#ifdef HAVE_SCHED_H +#include +#endif +#ifdef HAVE_SYNCH_H +#include +#endif + +#ifdef __NETWARE__ +void my_pthread_exit(void *status); +#define pthread_exit(A) my_pthread_exit(A) +#endif + +#define pthread_key(T,V) pthread_key_t V +#define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,(V)) +#define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,(void*) (V)) +#define pthread_detach_this_thread() +#define pthread_handler_t EXTERNC void * +typedef void *(* pthread_handler)(void *); + +/* Test first for RTS or FSU threads */ + +#if defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) +#define HAVE_rts_threads +extern int my_pthread_create_detached; +#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C)) +#define PTHREAD_CREATE_DETACHED &my_pthread_create_detached +#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_GLOBAL +#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_LOCAL +#define USE_ALARM_THREAD +#endif /* defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) */ + +#if defined(_BSDI_VERSION) && _BSDI_VERSION < 199910 +int sigwait(sigset_t *set, int *sig); +#endif + +#ifndef HAVE_NONPOSIX_SIGWAIT +#define my_sigwait(A,B) sigwait((A),(B)) +#else +int my_sigwait(const sigset_t *set,int *sig); +#endif + +#ifdef HAVE_NONPOSIX_PTHREAD_MUTEX_INIT +#ifndef SAFE_MUTEX +#define pthread_mutex_init(a,b) my_pthread_mutex_noposix_init((a),(b)) +extern int my_pthread_mutex_noposix_init(pthread_mutex_t *mp, + const pthread_mutexattr_t *attr); +#endif /* SAFE_MUTEX */ +#define pthread_cond_init(a,b) my_pthread_cond_noposix_init((a),(b)) +extern int my_pthread_cond_noposix_init(pthread_cond_t *mp, + const pthread_condattr_t *attr); +#endif /* HAVE_NONPOSIX_PTHREAD_MUTEX_INIT */ + +#if defined(HAVE_SIGTHREADMASK) && !defined(HAVE_PTHREAD_SIGMASK) +#define pthread_sigmask(A,B,C) sigthreadmask((A),(B),(C)) +#endif + +#if !defined(HAVE_SIGWAIT) && !defined(HAVE_rts_threads) && !defined(sigwait) && !defined(alpha_linux_port) && !defined(HAVE_NONPOSIX_SIGWAIT) && !defined(HAVE_DEC_3_2_THREADS) && !defined(_AIX) +int sigwait(sigset_t *setp, int *sigp); /* Use our implemention */ +#endif + + +/* + We define my_sigset() and use that instead of the system sigset() so that + we can favor an implementation based on sigaction(). On some systems, such + as Mac OS X, sigset() results in flags such as SA_RESTART being set, and + we want to make sure that no such flags are set. +*/ +#if defined(HAVE_SIGACTION) && !defined(my_sigset) +#define my_sigset(A,B) do { struct sigaction l_s; sigset_t l_set; int l_rc; \ + DBUG_ASSERT((A) != 0); \ + sigemptyset(&l_set); \ + l_s.sa_handler = (B); \ + l_s.sa_mask = l_set; \ + l_s.sa_flags = 0; \ + l_rc= sigaction((A), &l_s, (struct sigaction *) NULL);\ + DBUG_ASSERT(l_rc == 0); \ + } while (0) +#elif defined(HAVE_SIGSET) && !defined(my_sigset) +#define my_sigset(A,B) sigset((A),(B)) +#elif !defined(my_sigset) +#define my_sigset(A,B) signal((A),(B)) +#endif + +#if !defined(HAVE_PTHREAD_ATTR_SETSCOPE) || defined(HAVE_DEC_3_2_THREADS) +#define pthread_attr_setscope(A,B) +#undef HAVE_GETHOSTBYADDR_R /* No definition */ +#endif + +#if defined(HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT) && !defined(SAFE_MUTEX) +extern int my_pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, + struct timespec *abstime); +#define pthread_cond_timedwait(A,B,C) my_pthread_cond_timedwait((A),(B),(C)) +#endif + +#if !defined( HAVE_NONPOSIX_PTHREAD_GETSPECIFIC) +#define my_pthread_getspecific(A,B) ((A) pthread_getspecific(B)) +#else +#define my_pthread_getspecific(A,B) ((A) my_pthread_getspecific_imp(B)) +void *my_pthread_getspecific_imp(pthread_key_t key); +#endif + +#ifndef HAVE_LOCALTIME_R +struct tm *localtime_r(const time_t *clock, struct tm *res); +#endif + +#ifndef HAVE_GMTIME_R +struct tm *gmtime_r(const time_t *clock, struct tm *res); +#endif + +#ifdef HAVE_PTHREAD_CONDATTR_CREATE +/* DCE threads on HPUX 10.20 */ +#define pthread_condattr_init pthread_condattr_create +#define pthread_condattr_destroy pthread_condattr_delete +#endif + +/* FSU THREADS */ +#if !defined(HAVE_PTHREAD_KEY_DELETE) && !defined(pthread_key_delete) +#define pthread_key_delete(A) pthread_dummy(0) +#endif + +#if ((defined(HAVE_PTHREAD_ATTR_CREATE) && !defined(HAVE_SIGWAIT)) || defined(HAVE_DEC_3_2_THREADS)) +/* This is set on AIX_3_2 and Siemens unix (and DEC OSF/1 3.2 too) */ +#define pthread_key_create(A,B) \ + pthread_keycreate(A,(B) ?\ + (pthread_destructor_t) (B) :\ + (pthread_destructor_t) pthread_dummy) +#define pthread_attr_init(A) pthread_attr_create(A) +#define pthread_attr_destroy(A) pthread_attr_delete(A) +#define pthread_attr_setdetachstate(A,B) pthread_dummy(0) +#define pthread_create(A,B,C,D) pthread_create((A),*(B),(C),(D)) +#ifndef pthread_sigmask +#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C)) +#endif +#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH) +#undef pthread_detach_this_thread +#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); } +#elif !defined(__NETWARE__) /* HAVE_PTHREAD_ATTR_CREATE && !HAVE_SIGWAIT */ +#ifndef HAVE_PTHREAD_KILL +# define HAVE_PTHREAD_KILL +#endif +#endif + +#endif /* defined(__WIN__) */ + +#if defined(HPUX10) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS) +#undef pthread_cond_timedwait +#define pthread_cond_timedwait(a,b,c) my_pthread_cond_timedwait((a),(b),(c)) +int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + struct timespec *abstime); +#endif + +#if defined(HPUX10) +#define pthread_attr_getstacksize(A,B) my_pthread_attr_getstacksize(A,B) +void my_pthread_attr_getstacksize(pthread_attr_t *attrib, size_t *size); +#endif + +#if defined(HAVE_POSIX1003_4a_MUTEX) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS) +#undef pthread_mutex_trylock +#define pthread_mutex_trylock(a) my_pthread_mutex_trylock((a)) +int my_pthread_mutex_trylock(pthread_mutex_t *mutex); +#endif + +#if !defined(HAVE_PTHREAD_YIELD_ONE_ARG) && !defined(HAVE_PTHREAD_YIELD_ZERO_ARG) +/* no pthread_yield() available */ +#ifdef HAVE_SCHED_YIELD +#define pthread_yield() sched_yield() +#elif defined(HAVE_PTHREAD_YIELD_NP) /* can be Mac OS X */ +#define pthread_yield() pthread_yield_np() +#elif defined(HAVE_THR_YIELD) +#define pthread_yield() thr_yield() +#endif +#endif + +/* + The defines set_timespec and set_timespec_nsec should be used + for calculating an absolute time at which + pthread_cond_timedwait should timeout +*/ + +#define set_timespec(ABSTIME,SEC) set_timespec_nsec((ABSTIME),(SEC)*1000000000ULL) + +#ifndef set_timespec_nsec +#define set_timespec_nsec(ABSTIME,NSEC) \ + set_timespec_time_nsec((ABSTIME),my_getsystime(),(NSEC)) +#endif /* !set_timespec_nsec */ + +/* adapt for two different flavors of struct timespec */ +#ifdef HAVE_TIMESPEC_TS_SEC +#define MY_tv_sec ts_sec +#define MY_tv_nsec ts_nsec +#else +#define MY_tv_sec tv_sec +#define MY_tv_nsec tv_nsec +#endif /* HAVE_TIMESPEC_TS_SEC */ + +#ifndef set_timespec_time_nsec +#define set_timespec_time_nsec(ABSTIME,TIME,NSEC) do { \ + ulonglong nsec= (NSEC); \ + ulonglong now= (TIME) + (nsec/100); \ + (ABSTIME).MY_tv_sec= (now / 10000000ULL); \ + (ABSTIME).MY_tv_nsec= (now % 10000000ULL * 100 + (nsec % 100)); \ +} while(0) +#endif /* !set_timespec_time_nsec */ + +/* safe_mutex adds checking to mutex for easier debugging */ + +#if defined(__NETWARE__) && !defined(SAFE_MUTEX_DETECT_DESTROY) +#define SAFE_MUTEX_DETECT_DESTROY +#endif +struct st_hash; + +typedef struct st_safe_mutex_t +{ + pthread_mutex_t global,mutex; + const char *file, *name; + uint line,count; + myf create_flags, active_flags; + ulong id; + pthread_t thread; + struct st_hash *locked_mutex, *used_mutex; + struct st_safe_mutex_t *prev, *next; +#ifdef SAFE_MUTEX_DETECT_DESTROY + struct st_safe_mutex_info_t *info; /* to track destroying of mutexes */ +#endif +} safe_mutex_t; + +typedef struct st_safe_mutex_deadlock_t +{ + const char *file, *name; + safe_mutex_t *mutex; + uint line; + ulong count; + ulong id; + my_bool warning_only; +} safe_mutex_deadlock_t; + +#ifdef SAFE_MUTEX_DETECT_DESTROY +/* + Used to track the destroying of mutexes. This needs to be a seperate + structure because the safe_mutex_t structure could be freed before + the mutexes are destroyed. +*/ + +typedef struct st_safe_mutex_info_t +{ + struct st_safe_mutex_info_t *next; + struct st_safe_mutex_info_t *prev; + const char *init_file; + uint32 init_line; +} safe_mutex_info_t; +#endif /* SAFE_MUTEX_DETECT_DESTROY */ + +int safe_mutex_init(safe_mutex_t *mp, const pthread_mutexattr_t *attr, + const char *name, myf my_flags, + const char *file, uint line); +int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file, + uint line); +int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line); +int safe_mutex_destroy(safe_mutex_t *mp,const char *file, uint line); +int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp,const char *file, + uint line); +int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp, + struct timespec *abstime, const char *file, uint line); +void safe_mutex_global_init(void); +void safe_mutex_end(FILE *file); +void safe_mutex_free_deadlock_data(safe_mutex_t *mp); + + /* Wrappers if safe mutex is actually used */ +#define MYF_TRY_LOCK 1 +#define MYF_NO_DEADLOCK_DETECTION 2 + +#ifdef SAFE_MUTEX +#undef pthread_mutex_init +#undef pthread_mutex_lock +#undef pthread_mutex_unlock +#undef pthread_mutex_destroy +#undef pthread_mutex_wait +#undef pthread_mutex_timedwait +#undef pthread_mutex_t +#undef pthread_cond_wait +#undef pthread_cond_timedwait +#undef pthread_mutex_trylock +#define my_pthread_mutex_init(A,B,C,D) safe_mutex_init((A),(B),(C),(D),__FILE__,__LINE__) +#define pthread_mutex_init(A,B) safe_mutex_init((A),(B),#A,0,__FILE__,__LINE__) +#define pthread_mutex_lock(A) safe_mutex_lock((A), 0, __FILE__, __LINE__) +#define my_pthread_mutex_lock(A,B) safe_mutex_lock((A), (B), __FILE__, __LINE__) +#define pthread_mutex_unlock(A) safe_mutex_unlock((A),__FILE__,__LINE__) +#define pthread_mutex_destroy(A) safe_mutex_destroy((A),__FILE__,__LINE__) +#define pthread_cond_wait(A,B) safe_cond_wait((A),(B),__FILE__,__LINE__) +#define pthread_cond_timedwait(A,B,C) safe_cond_timedwait((A),(B),(C),__FILE__,__LINE__) +#define pthread_mutex_trylock(A) safe_mutex_lock((A), MYF_TRY_LOCK, __FILE__, __LINE__) +#define pthread_mutex_t safe_mutex_t +#define safe_mutex_assert_owner(mp) \ + DBUG_ASSERT((mp)->count > 0 && \ + pthread_equal(pthread_self(), (mp)->thread)) +#define safe_mutex_assert_not_owner(mp) \ + DBUG_ASSERT(! (mp)->count || \ + ! pthread_equal(pthread_self(), (mp)->thread)) +#else +#define my_pthread_mutex_init(A,B,C,D) pthread_mutex_init((A),(B)) +#define my_pthread_mutex_lock(A,B) pthread_mutex_lock(A) +#define safe_mutex_assert_owner(mp) +#define safe_mutex_assert_not_owner(mp) +#endif /* SAFE_MUTEX */ + +#if defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) +typedef struct st_my_pthread_fastmutex_t +{ + pthread_mutex_t mutex; + uint spins; + uint rng_state; +} my_pthread_fastmutex_t; +void fastmutex_global_init(void); + +int my_pthread_fastmutex_init(my_pthread_fastmutex_t *mp, + const pthread_mutexattr_t *attr); +int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp); + +#undef pthread_mutex_init +#undef pthread_mutex_lock +#undef pthread_mutex_unlock +#undef pthread_mutex_destroy +#undef pthread_mutex_wait +#undef pthread_mutex_timedwait +#undef pthread_mutex_t +#undef pthread_cond_wait +#undef pthread_cond_timedwait +#undef pthread_mutex_trylock +#define pthread_mutex_init(A,B) my_pthread_fastmutex_init((A),(B)) +#define pthread_mutex_lock(A) my_pthread_fastmutex_lock(A) +#define pthread_mutex_unlock(A) pthread_mutex_unlock(&(A)->mutex) +#define pthread_mutex_destroy(A) pthread_mutex_destroy(&(A)->mutex) +#define pthread_cond_wait(A,B) pthread_cond_wait((A),&(B)->mutex) +#define pthread_cond_timedwait(A,B,C) pthread_cond_timedwait((A),&(B)->mutex,(C)) +#define pthread_mutex_trylock(A) pthread_mutex_trylock(&(A)->mutex) +#define pthread_mutex_t my_pthread_fastmutex_t +#endif /* defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) */ + + /* READ-WRITE thread locking */ + +#ifdef HAVE_BROKEN_RWLOCK /* For OpenUnix */ +#undef HAVE_PTHREAD_RWLOCK_RDLOCK +#undef HAVE_RWLOCK_INIT +#undef HAVE_RWLOCK_T +#endif + +#if defined(USE_MUTEX_INSTEAD_OF_RW_LOCKS) +/* use these defs for simple mutex locking */ +#define rw_lock_t pthread_mutex_t +#define my_rwlock_init(A,B) pthread_mutex_init((A),(B)) +#define rw_rdlock(A) pthread_mutex_lock((A)) +#define rw_wrlock(A) pthread_mutex_lock((A)) +#define rw_tryrdlock(A) pthread_mutex_trylock((A)) +#define rw_trywrlock(A) pthread_mutex_trylock((A)) +#define rw_unlock(A) pthread_mutex_unlock((A)) +#define rwlock_destroy(A) pthread_mutex_destroy((A)) +#elif defined(HAVE_PTHREAD_RWLOCK_RDLOCK) +#define rw_lock_t pthread_rwlock_t +#define my_rwlock_init(A,B) pthread_rwlock_init((A),(B)) +#define rw_rdlock(A) pthread_rwlock_rdlock(A) +#define rw_wrlock(A) pthread_rwlock_wrlock(A) +#define rw_tryrdlock(A) pthread_rwlock_tryrdlock((A)) +#define rw_trywrlock(A) pthread_rwlock_trywrlock((A)) +#define rw_unlock(A) pthread_rwlock_unlock(A) +#define rwlock_destroy(A) pthread_rwlock_destroy(A) +#elif defined(HAVE_RWLOCK_INIT) +#ifdef HAVE_RWLOCK_T /* For example Solaris 2.6-> */ +#define rw_lock_t rwlock_t +#endif +#define my_rwlock_init(A,B) rwlock_init((A),USYNC_THREAD,0) +#else +/* Use our own version of read/write locks */ +typedef struct _my_rw_lock_t { + pthread_mutex_t lock; /* lock for structure */ + pthread_cond_t readers; /* waiting readers */ + pthread_cond_t writers; /* waiting writers */ + int state; /* -1:writer,0:free,>0:readers */ + int waiters; /* number of waiting writers */ +} my_rw_lock_t; + +#define rw_lock_t my_rw_lock_t +#define rw_rdlock(A) my_rw_rdlock((A)) +#define rw_wrlock(A) my_rw_wrlock((A)) +#define rw_tryrdlock(A) my_rw_tryrdlock((A)) +#define rw_trywrlock(A) my_rw_trywrlock((A)) +#define rw_unlock(A) my_rw_unlock((A)) +#define rwlock_destroy(A) my_rwlock_destroy((A)) + +extern int my_rwlock_init(my_rw_lock_t *, void *); +extern int my_rwlock_destroy(my_rw_lock_t *); +extern int my_rw_rdlock(my_rw_lock_t *); +extern int my_rw_wrlock(my_rw_lock_t *); +extern int my_rw_unlock(my_rw_lock_t *); +extern int my_rw_tryrdlock(my_rw_lock_t *); +extern int my_rw_trywrlock(my_rw_lock_t *); +#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */ + +#define GETHOSTBYADDR_BUFF_SIZE 2048 + +#ifndef HAVE_THR_SETCONCURRENCY +#define thr_setconcurrency(A) pthread_dummy(0) +#endif +#if !defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && ! defined(pthread_attr_setstacksize) +#define pthread_attr_setstacksize(A,B) pthread_dummy(0) +#endif + +/* Define mutex types, see my_thr_init.c */ +#define MY_MUTEX_INIT_SLOW NULL +#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP +extern pthread_mutexattr_t my_fast_mutexattr; +#define MY_MUTEX_INIT_FAST &my_fast_mutexattr +#else +#define MY_MUTEX_INIT_FAST NULL +#endif +#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP +extern pthread_mutexattr_t my_errorcheck_mutexattr; +#define MY_MUTEX_INIT_ERRCHK &my_errorcheck_mutexattr +#else +#define MY_MUTEX_INIT_ERRCHK NULL +#endif + +#ifndef ESRCH +/* Define it to something */ +#define ESRCH 1 +#endif + +typedef ulong my_thread_id; + +extern void my_threadattr_global_init(void); +extern my_bool my_thread_global_init(void); +extern void my_thread_global_end(void); +extern my_bool my_thread_init(void); +extern void my_thread_end(void); +extern const char *my_thread_name(void); +extern my_thread_id my_thread_dbug_id(void); +extern int pthread_dummy(int); + +/* All thread specific variables are in the following struct */ + +#define THREAD_NAME_SIZE 10 +#ifndef DEFAULT_THREAD_STACK +#if SIZEOF_CHARP > 4 +/* + MySQL can survive with 32K, but some glibc libraries require > 128K stack + To resolve hostnames. Also recursive stored procedures needs stack. +*/ +#define DEFAULT_THREAD_STACK (256*1024L) +#else +#define DEFAULT_THREAD_STACK (195*1024) +#endif +#endif + +#define MY_PTHREAD_LOCK_READ 0 +#define MY_PTHREAD_LOCK_WRITE 1 + +struct st_my_thread_var +{ + int thr_errno; + pthread_cond_t suspend; + pthread_mutex_t mutex; + pthread_mutex_t * volatile current_mutex; + pthread_cond_t * volatile current_cond; + pthread_t pthread_self; + my_thread_id id; + int cmp_length; + int volatile abort; + my_bool init; + struct st_my_thread_var *next,**prev; + void *opt_info; + uint lock_type; /* used by conditional release the queue */ + void *stack_ends_here; + safe_mutex_t *mutex_in_use; +#ifndef DBUG_OFF + void *dbug; + char name[THREAD_NAME_SIZE+1]; +#endif +}; + +extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const)); +extern void **my_thread_var_dbug(); +extern safe_mutex_t **my_thread_var_mutex_in_use(); +extern uint my_thread_end_wait_time; +extern my_bool safe_mutex_deadlock_detector; +#define my_thread_var (_my_thread_var()) +#define my_errno my_thread_var->thr_errno +/* + Keep track of shutdown,signal, and main threads so that my_end() will not + report errors with them +*/ + +/* Which kind of thread library is in use */ + +#define THD_LIB_OTHER 1 +#define THD_LIB_NPTL 2 +#define THD_LIB_LT 4 + +extern uint thd_lib_detected; + +/* + thread_safe_xxx functions are for critical statistic or counters. + The implementation is guaranteed to be thread safe, on all platforms. + Note that the calling code should *not* assume the counter is protected + by the mutex given, as the implementation of these helpers may change + to use my_atomic operations instead. +*/ + +/* + Warning: + When compiling without threads, this file is not included. + See the *other* declarations of thread_safe_xxx in include/my_global.h + + Second warning: + See include/config-win.h, for yet another implementation. +*/ +#ifdef THREAD +#ifndef thread_safe_increment +#define thread_safe_increment(V,L) \ + (pthread_mutex_lock((L)), (V)++, pthread_mutex_unlock((L))) +#define thread_safe_decrement(V,L) \ + (pthread_mutex_lock((L)), (V)--, pthread_mutex_unlock((L))) +#endif + +#ifndef thread_safe_add +#define thread_safe_add(V,C,L) \ + (pthread_mutex_lock((L)), (V)+=(C), pthread_mutex_unlock((L))) +#define thread_safe_sub(V,C,L) \ + (pthread_mutex_lock((L)), (V)-=(C), pthread_mutex_unlock((L))) +#endif +#endif + +/* + statistics_xxx functions are for non critical statistic, + maintained in global variables. + When compiling with SAFE_STATISTICS: + - race conditions can not occur. + - some locking occurs, which may cause performance degradation. + + When compiling without SAFE_STATISTICS: + - race conditions can occur, making the result slightly inaccurate. + - the lock given is not honored. +*/ +#ifdef SAFE_STATISTICS +#define statistic_increment(V,L) thread_safe_increment((V),(L)) +#define statistic_decrement(V,L) thread_safe_decrement((V),(L)) +#define statistic_add(V,C,L) thread_safe_add((V),(C),(L)) +#define statistic_sub(V,C,L) thread_safe_sub((V),(C),(L)) +#else +#define statistic_decrement(V,L) (V)-- +#define statistic_increment(V,L) (V)++ +#define statistic_add(V,C,L) (V)+=(C) +#define statistic_sub(V,C,L) (V)-=(C) +#endif /* SAFE_STATISTICS */ + +/* + No locking needed, the counter is owned by the thread +*/ +#define status_var_increment(V) (V)++ +#define status_var_decrement(V) (V)-- +#define status_var_add(V,C) (V)+=(C) +#define status_var_sub(V,C) (V)-=(C) + +#ifdef __cplusplus +} +#endif +#endif /* _my_ptread_h */ diff --git a/NetService/include/Mysql/my_stacktrace.h b/NetService/include/Mysql/my_stacktrace.h new file mode 100644 index 00000000..e7ce42c1 --- /dev/null +++ b/NetService/include/Mysql/my_stacktrace.h @@ -0,0 +1,66 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _my_stacktrace_h_ +#define _my_stacktrace_h_ + +#include + +#ifdef TARGET_OS_LINUX +#if defined (__x86_64__) || defined (__i386__) || \ + (defined(__alpha__) && defined(__GNUC__)) +#define HAVE_STACKTRACE 1 +#endif +#elif defined(__WIN__) +#define HAVE_STACKTRACE 1 +#endif + +#if HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD) +#undef HAVE_STACKTRACE +#define HAVE_STACKTRACE 1 +#endif + +#if !defined(__NETWARE__) +#define HAVE_WRITE_CORE +#endif + +#if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS && \ + HAVE_CXXABI_H && HAVE_ABI_CXA_DEMANGLE && \ + HAVE_WEAK_SYMBOL +#define BACKTRACE_DEMANGLE 1 +#endif + +C_MODE_START + +#if defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE) +void my_init_stacktrace(); +void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack); +void my_safe_print_str(const char* name, const char* val, int max_len); +void my_write_core(int sig); +#if BACKTRACE_DEMANGLE +char *my_demangle(const char *mangled_name, int *status); +#endif +#ifdef __WIN__ +void my_set_exception_pointers(EXCEPTION_POINTERS *ep); +#endif +#endif + +#ifdef HAVE_WRITE_CORE +void my_write_core(int sig); +#endif + +C_MODE_END + +#endif /* _my_stacktrace_h_ */ diff --git a/NetService/include/Mysql/my_sys.h b/NetService/include/Mysql/my_sys.h new file mode 100644 index 00000000..c8ec7916 --- /dev/null +++ b/NetService/include/Mysql/my_sys.h @@ -0,0 +1,1082 @@ +/* Copyright (C) 2000-2003 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + @file + mysys library API +*/ + +#ifndef _my_sys_h +#define _my_sys_h +C_MODE_START + +#ifdef HAVE_AIOWAIT +#include /* Used by record-cache */ +typedef struct my_aio_result { + aio_result_t result; + int pending; +} my_aio_result; +#endif + +#ifndef THREAD +extern int NEAR my_errno; /* Last error in mysys */ +#else +#include +#endif + +#include /* for CHARSET_INFO */ +#include +#include + +#define MYSYS_PROGRAM_DONT_USE_CURSES() { error_handler_hook = my_message_no_curses; mysys_uses_curses=0;} +#define MY_INIT(name); { my_progname= name; my_init(); } + +/** + Max length of an error message generated by mysys utilities. + Some mysys functions produce error messages. These mostly go + to stderr. + This constant defines the size of the buffer used to format + the message. It should be kept in sync with MYSQL_ERRMSG_SIZE, + since sometimes mysys errors are stored in the server diagnostics + area, and we would like to avoid unexpected truncation. +*/ +#define MYSYS_ERRMSG_SIZE (512) + +#define MY_FILE_ERROR ((size_t) -1) + + /* General bitmaps for my_func's */ +#define MY_FFNF 1 /* Fatal if file not found */ +#define MY_FNABP 2 /* Fatal if not all bytes read/writen */ +#define MY_NABP 4 /* Error if not all bytes read/writen */ +#define MY_FAE 8 /* Fatal if any error */ +#define MY_WME 16 /* Write message on error */ +#define MY_WAIT_IF_FULL 32 /* Wait and try again if disk full error */ +#define MY_IGNORE_BADFD 32 /* my_sync: ignore 'bad descriptor' errors */ +#define MY_SYNC_DIR 1024 /* my_create/delete/rename: sync directory */ +#define MY_RAID 64 /* Support for RAID */ +#define MY_FULL_IO 512 /* For my_read - loop intil I/O is complete */ +#define MY_DONT_CHECK_FILESIZE 128 /* Option to init_io_cache() */ +#define MY_LINK_WARNING 32 /* my_redel() gives warning if links */ +#define MY_COPYTIME 64 /* my_redel() copys time */ +#define MY_DELETE_OLD 256 /* my_create_with_symlink() */ +#define MY_RESOLVE_LINK 128 /* my_realpath(); Only resolve links */ +#define MY_HOLD_ORIGINAL_MODES 128 /* my_copy() holds to file modes */ +#define MY_REDEL_MAKE_BACKUP 256 +#define MY_SEEK_NOT_DONE 32 /* my_lock may have to do a seek */ +#define MY_SHORT_WAIT 64 /* my_lock() don't wait if can't lock */ +#define MY_FORCE_LOCK 128 /* use my_lock() even if disable_locking */ +#define MY_NO_WAIT 256 /* my_lock() don't wait at all */ +#define MY_ZEROFILL 32 /* my_malloc(), fill array with zero */ +#define MY_ALLOW_ZERO_PTR 64 /* my_realloc() ; zero ptr -> malloc */ +#define MY_FREE_ON_ERROR 128 /* my_realloc() ; Free old ptr on error */ +#define MY_HOLD_ON_ERROR 256 /* my_realloc() ; Return old ptr on error */ +#define MY_DONT_OVERWRITE_FILE 2048 /* my_copy: Don't overwrite file */ +#define MY_THREADSAFE 2048 /* my_seek(): lock fd mutex */ + +#define MY_CHECK_ERROR 1 /* Params to my_end; Check open-close */ +#define MY_GIVE_INFO 2 /* Give time info about process*/ +#define MY_DONT_FREE_DBUG 4 /* Do not call DBUG_END() in my_end() */ + +#define MY_REMOVE_NONE 0 /* Params for modify_defaults_file */ +#define MY_REMOVE_OPTION 1 +#define MY_REMOVE_SECTION 2 + +#define ME_HIGHBYTE 8 /* Shift for colours */ +#define ME_NOCUR 1 /* Don't use curses message */ +#define ME_OLDWIN 2 /* Use old window */ +#define ME_BELL 4 /* Ring bell then printing message */ +#define ME_HOLDTANG 8 /* Don't delete last keys */ +#define ME_WAITTOT 16 /* Wait for errtime secs of for a action */ +#define ME_WAITTANG 32 /* Wait for a user action */ +#define ME_NOREFRESH 64 /* Dont refresh screen */ +#define ME_NOINPUT 128 /* Dont use the input libary */ +#define ME_COLOUR1 ((1 << ME_HIGHBYTE)) /* Possibly error-colours */ +#define ME_COLOUR2 ((2 << ME_HIGHBYTE)) +#define ME_COLOUR3 ((3 << ME_HIGHBYTE)) +#define ME_FATALERROR 1024 /* Fatal statement error */ +#define ME_JUST_INFO 8192 /**< not error but just info */ +#define ME_JUST_WARNING 16384 /**< not error but just warning */ + + /* Bits in last argument to fn_format */ +#define MY_REPLACE_DIR 1 /* replace dir in name with 'dir' */ +#define MY_REPLACE_EXT 2 /* replace extension with 'ext' */ +#define MY_UNPACK_FILENAME 4 /* Unpack name (~ -> home) */ +#define MY_PACK_FILENAME 8 /* Pack name (home -> ~) */ +#define MY_RESOLVE_SYMLINKS 16 /* Resolve all symbolic links */ +#define MY_RETURN_REAL_PATH 32 /* return full path for file */ +#define MY_SAFE_PATH 64 /* Return NULL if too long path */ +#define MY_RELATIVE_PATH 128 /* name is relative to 'dir' */ +#define MY_APPEND_EXT 256 /* add 'ext' as additional extension*/ + + + /* My seek flags */ +#define MY_SEEK_SET 0 +#define MY_SEEK_CUR 1 +#define MY_SEEK_END 2 + + /* Some constants */ +#define MY_WAIT_FOR_USER_TO_FIX_PANIC 60 /* in seconds */ +#define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */ +#define MIN_COMPRESS_LENGTH 50 /* Don't compress small bl. */ +#define DFLT_INIT_HITS 3 + + /* root_alloc flags */ +#define MY_KEEP_PREALLOC 1 +#define MY_MARK_BLOCKS_FREE 2 /* move used to free list and reuse them */ + + /* Internal error numbers (for assembler functions) */ +#define MY_ERRNO_EDOM 33 +#define MY_ERRNO_ERANGE 34 + + /* Bits for get_date timeflag */ +#define GETDATE_DATE_TIME 1 +#define GETDATE_SHORT_DATE 2 +#define GETDATE_HHMMSSTIME 4 +#define GETDATE_GMT 8 +#define GETDATE_FIXEDLENGTH 16 + + /* defines when allocating data */ +#ifdef SAFEMALLOC +#define my_malloc(SZ,FLAG) _mymalloc((SZ), __FILE__, __LINE__, FLAG ) +#define my_malloc_ci(SZ,FLAG) _mymalloc((SZ), sFile, uLine, FLAG ) +#define my_realloc(PTR,SZ,FLAG) _myrealloc((PTR), (SZ), __FILE__, __LINE__, FLAG ) +#define my_checkmalloc() _sanity( __FILE__, __LINE__ ) +#define my_free(PTR,FLAG) _myfree((PTR), __FILE__, __LINE__,FLAG) +#define my_memdup(A,B,C) _my_memdup((A),(B), __FILE__,__LINE__,C) +#define my_strdup(A,C) _my_strdup((A), __FILE__,__LINE__,C) +#define my_strndup(A,B,C) _my_strndup((A),(B),__FILE__,__LINE__,C) +#define QUICK_SAFEMALLOC sf_malloc_quick=1 +#define NORMAL_SAFEMALLOC sf_malloc_quick=0 +extern uint sf_malloc_prehunc,sf_malloc_endhunc,sf_malloc_quick; +extern ulonglong sf_malloc_mem_limit; + +#define CALLER_INFO_PROTO , const char *sFile, uint uLine +#define CALLER_INFO , __FILE__, __LINE__ +#define ORIG_CALLER_INFO , sFile, uLine +#else +#define my_checkmalloc() +#undef TERMINATE +#define TERMINATE(A,B) {} +#define QUICK_SAFEMALLOC +#define NORMAL_SAFEMALLOC +extern void *my_malloc(size_t Size,myf MyFlags); +#define my_malloc_ci(SZ,FLAG) my_malloc( SZ, FLAG ) +extern void *my_realloc(void *oldpoint, size_t Size, myf MyFlags); +extern void my_no_flags_free(void *ptr); +extern void *my_memdup(const void *from,size_t length,myf MyFlags); +extern char *my_strdup(const char *from,myf MyFlags); +extern char *my_strndup(const char *from, size_t length, + myf MyFlags); +/* we do use FG (as a no-op) in below so that a typo on FG is caught */ +#define my_free(PTR,FG) ((void)FG,my_no_flags_free(PTR)) +#define CALLER_INFO_PROTO /* nothing */ +#define CALLER_INFO /* nothing */ +#define ORIG_CALLER_INFO /* nothing */ +#endif + +/* + ERROR INJECTION: Non-thread-safe global variable to request error inject. + Set this variable to non-zero to request the next my_malloc() to fail. + This works with my_malloc.c:my_malloc() and safemalloc.c:_mymalloc(). + If using this in tests, note that the error messages produced by + my_malloc and safemalloc are different. You may need to modify the + results with --replace_regex. You may find examples in + client/backup_stream.c and backup_client_coverage.test. + The global variable is defined in my_static.c. +*/ +IF_DBUG(extern int my_malloc_error_inject); + +#ifdef HAVE_LARGE_PAGES +extern uint my_get_large_page_size(void); +extern uchar * my_large_malloc(size_t size, myf my_flags); +extern void my_large_free(uchar * ptr, myf my_flags); +#else +#define my_get_large_page_size() (0) +#define my_large_malloc(A,B) my_malloc_lock((A),(B)) +#define my_large_free(A,B) my_free_lock((A),(B)) +#endif /* HAVE_LARGE_PAGES */ + +#ifdef HAVE_ALLOCA +#if defined(_AIX) && !defined(__GNUC__) && !defined(_AIX43) +#pragma alloca +#endif /* _AIX */ +#if defined(__MWERKS__) +#undef alloca +#define alloca _alloca +#endif /* __MWERKS__ */ +#if defined(__GNUC__) && !defined(HAVE_ALLOCA_H) && ! defined(alloca) +#define alloca __builtin_alloca +#endif /* GNUC */ +#define my_alloca(SZ) alloca((size_t) (SZ)) +#define my_afree(PTR) {} +#else +#define my_alloca(SZ) my_malloc(SZ,MYF(0)) +#define my_afree(PTR) my_free(PTR,MYF(MY_WME)) +#endif /* HAVE_ALLOCA */ + +#ifndef errno /* did we already get it? */ +#ifdef HAVE_ERRNO_AS_DEFINE +#include /* errno is a define */ +#else +extern int errno; /* declare errno */ +#endif +#endif /* #ifndef errno */ +extern char *home_dir; /* Home directory for user */ +extern const char *my_progname; /* program-name (printed in errors) */ +extern const char *my_progname_short; /* like above but without directory */ +extern char NEAR curr_dir[]; /* Current directory for user */ +extern void (*error_handler_hook)(uint my_err, const char *str,myf MyFlags); +extern void (*fatal_error_handler_hook)(uint my_err, const char *str, + myf MyFlags); +extern uint my_file_limit; +extern ulong my_thread_stack_size; + +extern const char *(*proc_info_hook)(void *, const char *, const char *, + const char *, const unsigned int); + +#if defined(ENABLED_DEBUG_SYNC) +extern void (*debug_sync_C_callback_ptr)(const char *, size_t); +#define DEBUG_SYNC_C(_sync_point_name_) do { \ + if (debug_sync_C_callback_ptr != NULL) \ + (*debug_sync_C_callback_ptr)(STRING_WITH_LEN(_sync_point_name_)); } \ + while(0) +#else +#define DEBUG_SYNC_C(_sync_point_name_) +#endif /* defined(ENABLED_DEBUG_SYNC) */ + +#ifdef HAVE_LARGE_PAGES +extern my_bool my_use_large_pages; +extern uint my_large_page_size; +#endif + +/* charsets */ +#define MY_ALL_CHARSETS_SIZE 2048 +extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *default_charset_info; +extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *all_charsets[MY_ALL_CHARSETS_SIZE]; +extern CHARSET_INFO compiled_charsets[]; + +/* statistics */ +extern ulong my_file_opened,my_stream_opened, my_tmp_file_created; +extern ulong my_file_total_opened; +extern uint mysys_usage_id; +extern my_bool my_init_done; + + /* Point to current my_message() */ +extern void (*my_sigtstp_cleanup)(void), + /* Executed before jump to shell */ + (*my_sigtstp_restart)(void), + (*my_abort_hook)(int); + /* Executed when comming from shell */ +extern MYSQL_PLUGIN_IMPORT int NEAR my_umask; /* Default creation mask */ +extern int NEAR my_umask_dir, + NEAR my_recived_signals, /* Signals we have got */ + NEAR my_safe_to_handle_signal, /* Set when allowed to SIGTSTP */ + NEAR my_dont_interrupt; /* call remember_intr when set */ +extern my_bool NEAR mysys_uses_curses, my_use_symdir; +extern size_t sf_malloc_cur_memory, sf_malloc_max_memory; + +extern ulong my_default_record_cache_size; +extern my_bool NEAR my_disable_locking,NEAR my_disable_async_io, + NEAR my_disable_flush_key_blocks, NEAR my_disable_symlinks; +extern char wild_many,wild_one,wild_prefix; +extern const char *charsets_dir; +/* from default.c */ +extern char *my_defaults_extra_file; +extern const char *my_defaults_group_suffix; +extern const char *my_defaults_file; + +extern my_bool timed_mutexes; + +typedef struct wild_file_pack /* Struct to hold info when selecting files */ +{ + uint wilds; /* How many wildcards */ + uint not_pos; /* Start of not-theese-files */ + char * *wild; /* Pointer to wildcards */ +} WF_PACK; + +enum loglevel { + ERROR_LEVEL, + WARNING_LEVEL, + INFORMATION_LEVEL +}; + +enum cache_type +{ + TYPE_NOT_SET= 0, READ_CACHE, WRITE_CACHE, + SEQ_READ_APPEND /* sequential read or append */, + READ_FIFO, READ_NET,WRITE_NET}; + +enum flush_type +{ + FLUSH_KEEP, /* flush block and keep it in the cache */ + FLUSH_RELEASE, /* flush block and remove it from the cache */ + FLUSH_IGNORE_CHANGED, /* remove block from the cache */ + /* + As my_disable_flush_pagecache_blocks is always 0, the following option + is strictly equivalent to FLUSH_KEEP + */ + FLUSH_FORCE_WRITE, + /** + @brief like FLUSH_KEEP but return immediately if file is already being + flushed (even partially) by another thread; only for page cache, + forbidden for key cache. + */ + FLUSH_KEEP_LAZY +}; + +typedef struct st_record_cache /* Used when cacheing records */ +{ + File file; + int rc_seek,error,inited; + uint rc_length,read_length,reclength; + my_off_t rc_record_pos,end_of_file; + uchar *rc_buff,*rc_buff2,*rc_pos,*rc_end,*rc_request_pos; +#ifdef HAVE_AIOWAIT + int use_async_io; + my_aio_result aio_result; +#endif + enum cache_type type; +} RECORD_CACHE; + +enum file_type +{ + UNOPEN = 0, FILE_BY_OPEN, FILE_BY_CREATE, STREAM_BY_FOPEN, STREAM_BY_FDOPEN, + FILE_BY_MKSTEMP, FILE_BY_DUP +}; + +struct st_my_file_info +{ + char *name; +#ifdef _WIN32 + HANDLE fhandle; /* win32 file handle */ + int oflag; /* open flags, e.g O_APPEND */ +#endif + enum file_type type; +#if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32) + pthread_mutex_t mutex; +#endif +}; + +extern struct st_my_file_info *my_file_info; + +typedef struct st_dynamic_array +{ + uchar *buffer; + uint elements,max_element; + uint alloc_increment; + uint size_of_element; +} DYNAMIC_ARRAY; + +typedef struct st_my_tmpdir +{ + DYNAMIC_ARRAY full_list; + char **list; + uint cur, max; +#ifdef THREAD + pthread_mutex_t mutex; +#endif +} MY_TMPDIR; + +typedef struct st_dynamic_string +{ + char *str; + size_t length,max_length,alloc_increment; +} DYNAMIC_STRING; + +struct st_io_cache; +/** Function called when certain events happen to an IO_CACHE */ +typedef int (*IO_CACHE_CALLBACK)(struct st_io_cache *cache, + const uchar *buffert, uint length, + my_off_t filepos); + +#ifdef THREAD +typedef struct st_io_cache_share +{ + pthread_mutex_t mutex; /* To sync on reads into buffer. */ + pthread_cond_t cond; /* To wait for signals. */ + pthread_cond_t cond_writer; /* For a synchronized writer. */ + /* Offset in file corresponding to the first byte of buffer. */ + my_off_t pos_in_file; + /* If a synchronized write cache is the source of the data. */ + struct st_io_cache *source_cache; + uchar *buffer; /* The read buffer. */ + uchar *read_end; /* Behind last valid byte of buffer. */ + int running_threads; /* threads not in lock. */ + int total_threads; /* threads sharing the cache. */ + int error; /* Last error. */ +#ifdef NOT_YET_IMPLEMENTED + /* whether the structure should be free'd */ + my_bool alloced; +#endif +} IO_CACHE_SHARE; +#endif + +typedef struct st_io_cache /* Used when cacheing files */ +{ + /* Offset in file corresponding to the first byte of uchar* buffer. */ + my_off_t pos_in_file; + /* + The offset of end of file for READ_CACHE and WRITE_CACHE. + For SEQ_READ_APPEND it the maximum of the actual end of file and + the position represented by read_end. + */ + my_off_t end_of_file; + /* Points to current read position in the buffer */ + uchar *read_pos; + /* the non-inclusive boundary in the buffer for the currently valid read */ + uchar *read_end; + uchar *buffer; /* The read buffer */ + /* Used in ASYNC_IO */ + uchar *request_pos; + + /* Only used in WRITE caches and in SEQ_READ_APPEND to buffer writes */ + uchar *write_buffer; + /* + Only used in SEQ_READ_APPEND, and points to the current read position + in the write buffer. Note that reads in SEQ_READ_APPEND caches can + happen from both read buffer (uchar* buffer) and write buffer + (uchar* write_buffer). + */ + uchar *append_read_pos; + /* Points to current write position in the write buffer */ + uchar *write_pos; + /* The non-inclusive boundary of the valid write area */ + uchar *write_end; + + /* + Current_pos and current_end are convenience variables used by + my_b_tell() and other routines that need to know the current offset + current_pos points to &write_pos, and current_end to &write_end in a + WRITE_CACHE, and &read_pos and &read_end respectively otherwise + */ + uchar **current_pos, **current_end; +#ifdef THREAD + /* + The lock is for append buffer used in SEQ_READ_APPEND cache + need mutex copying from append buffer to read buffer. + */ + pthread_mutex_t append_buffer_lock; + /* + The following is used when several threads are reading the + same file in parallel. They are synchronized on disk + accesses reading the cached part of the file asynchronously. + It should be set to NULL to disable the feature. Only + READ_CACHE mode is supported. + */ + IO_CACHE_SHARE *share; +#endif + /* + A caller will use my_b_read() macro to read from the cache + if the data is already in cache, it will be simply copied with + memcpy() and internal variables will be accordinging updated with + no functions invoked. However, if the data is not fully in the cache, + my_b_read() will call read_function to fetch the data. read_function + must never be invoked directly. + */ + int (*read_function)(struct st_io_cache *,uchar *,size_t); + /* + Same idea as in the case of read_function, except my_b_write() needs to + be replaced with my_b_append() for a SEQ_READ_APPEND cache + */ + int (*write_function)(struct st_io_cache *,const uchar *,size_t); + /* + Specifies the type of the cache. Depending on the type of the cache + certain operations might not be available and yield unpredicatable + results. Details to be documented later + */ + enum cache_type type; + /* + Callbacks were added and are currently used for binary logging of LOAD + DATA INFILE - when a block is read from the file, we create a block + create/append event, and when IO_CACHE is closed, we create an end event; + also used to write the MyISAM WRITE_CACHE blocks to the MyISAM physical + log. These functions could, of course be used for other things. Note: some + callbacks share the same argument ("arg"). + */ + IO_CACHE_CALLBACK pre_read; /**< called before reading from disk */ + IO_CACHE_CALLBACK post_read; /**< called after reading from disk */ + IO_CACHE_CALLBACK pre_close; /**< called before ending the cache */ + /** Called _after_ writing to disk; not honoured by SEQ_READ_APPEND */ + IO_CACHE_CALLBACK post_write; + /* + Counts the number of times, when we were forced to use disk. We use it to + increase the binlog_cache_disk_use status variable. + */ + ulong disk_writes; + void *arg; /**< used by pre/post_read,post_write */ + char *file_name; /* if used with 'open_cached_file' */ + char *dir,*prefix; + File file; /* file descriptor */ + /* + seek_not_done is set by my_b_seek() to inform the upcoming read/write + operation that a seek needs to be preformed prior to the actual I/O + error is 0 if the cache operation was successful, -1 if there was a + "hard" error, and the actual number of I/O-ed bytes if the read/write was + partial. + */ + int seek_not_done,error; + /** + Cumulative 'error' since last [re]init_io_cache(). Useful if cache's user + polls for errors only once in a while. + */ + int hard_write_error_in_the_past; + /* buffer_length is memory size allocated for buffer or write_buffer */ + size_t buffer_length; + /* read_length is the same as buffer_length except when we use async io */ + size_t read_length; + myf myflags; /* Flags used to my_read/my_write */ + /* + alloced_buffer is 1 if the buffer was allocated by init_io_cache() and + 0 if it was supplied by the user. + Currently READ_NET is the only one that will use a buffer allocated + somewhere else + */ + my_bool alloced_buffer; +#ifdef HAVE_AIOWAIT + /* + As inidicated by ifdef, this is for async I/O, which is not currently + used (because it's not reliable on all systems) + */ + uint inited; + my_off_t aio_read_pos; + my_aio_result aio_result; +#endif +} IO_CACHE; + +typedef int (*qsort2_cmp)(const void *, const void *, const void *); + + /* defines for mf_iocache */ + + /* Test if buffer is inited */ +#define my_b_clear(info) (info)->buffer=0 +#define my_b_inited(info) (info)->buffer +#define my_b_EOF INT_MIN + +#define my_b_read(info,Buffer,Count) \ + ((info)->read_pos + (Count) <= (info)->read_end ?\ + (memcpy(Buffer,(info)->read_pos,(size_t) (Count)), \ + ((info)->read_pos+=(Count)),0) :\ + (*(info)->read_function)((info),Buffer,Count)) + +#define my_b_write(info,Buffer,Count) \ + ((info)->write_pos + (Count) <=(info)->write_end ?\ + (memcpy((info)->write_pos, (Buffer), (size_t)(Count)),\ + ((info)->write_pos+=(Count)),0) : \ + (*(info)->write_function)((info),(Buffer),(Count))) + +#define my_b_get(info) \ + ((info)->read_pos != (info)->read_end ?\ + ((info)->read_pos++, (int) (uchar) (info)->read_pos[-1]) :\ + _my_b_get(info)) + + /* my_b_write_byte dosn't have any err-check */ +#define my_b_write_byte(info,chr) \ + (((info)->write_pos < (info)->write_end) ?\ + ((*(info)->write_pos++)=(chr)) :\ + (_my_b_write(info,0,0) , ((*(info)->write_pos++)=(chr)))) + +#define my_b_fill_cache(info) \ + (((info)->read_end=(info)->read_pos),(*(info)->read_function)(info,0,0)) + +#define my_b_tell(info) ((info)->pos_in_file + \ + (size_t) (*(info)->current_pos - (info)->request_pos)) + +#define my_b_get_buffer_start(info) (info)->request_pos +#define my_b_get_bytes_in_buffer(info) (char*) (info)->read_end - \ + (char*) my_b_get_buffer_start(info) +#define my_b_get_pos_in_file(info) (info)->pos_in_file + +/* tell write offset in the SEQ_APPEND cache */ +int my_b_copy_to_file(IO_CACHE *cache, FILE *file); +my_off_t my_b_append_tell(IO_CACHE* info); +my_off_t my_b_safe_tell(IO_CACHE* info); /* picks the correct tell() */ + +#define my_b_bytes_in_cache(info) (size_t) (*(info)->current_end - \ + *(info)->current_pos) + +typedef uint32 ha_checksum; +extern ha_checksum my_crc_dbug_check; + +/* Define the type of function to be passed to process_default_option_files */ +typedef int (*Process_option_func)(void *ctx, const char *group_name, + const char *option); + +#include + + + /* Prototypes for mysys and my_func functions */ + +extern int my_copy(const char *from,const char *to,myf MyFlags); +extern int my_append(const char *from,const char *to,myf MyFlags); +extern int my_delete(const char *name,myf MyFlags); +extern int my_getwd(char * buf,size_t size,myf MyFlags); +extern int my_setwd(const char *dir,myf MyFlags); +extern int my_lock(File fd,int op,my_off_t start, my_off_t length,myf MyFlags); +extern void *my_once_alloc(size_t Size,myf MyFlags); +extern void my_once_free(void); +extern char *my_once_strdup(const char *src,myf myflags); +extern void *my_once_memdup(const void *src, size_t len, myf myflags); +extern File my_open(const char *FileName,int Flags,myf MyFlags); +extern File my_register_filename(File fd, const char *FileName, + enum file_type type_of_file, + uint error_message_number, myf MyFlags); +extern File my_create(const char *FileName,int CreateFlags, + int AccessFlags, myf MyFlags); +extern int my_close(File Filedes,myf MyFlags); +extern File my_dup(File file, myf MyFlags); +extern int my_mkdir(const char *dir, int Flags, myf MyFlags); +extern int my_readlink(char *to, const char *filename, myf MyFlags); +extern int my_is_symlink(const char *filename); +extern int my_realpath(char *to, const char *filename, myf MyFlags); +extern File my_create_with_symlink(const char *linkname, const char *filename, + int createflags, int access_flags, + myf MyFlags); +extern int my_delete_with_symlink(const char *name, myf MyFlags); +extern int my_rename_with_symlink(const char *from,const char *to,myf MyFlags); +extern int my_symlink(const char *content, const char *linkname, myf MyFlags); +extern size_t my_read(File Filedes,uchar *Buffer,size_t Count,myf MyFlags); +extern size_t my_pread(File Filedes,uchar *Buffer,size_t Count,my_off_t offset, + myf MyFlags); +extern int my_rename(const char *from,const char *to,myf MyFlags); +extern my_off_t my_seek(File fd,my_off_t pos,int whence,myf MyFlags); +extern my_off_t my_tell(File fd,myf MyFlags); +extern size_t my_write(File Filedes,const uchar *Buffer,size_t Count, + myf MyFlags); +extern size_t my_pwrite(File Filedes,const uchar *Buffer,size_t Count, + my_off_t offset,myf MyFlags); +extern size_t my_fread(FILE *stream,uchar *Buffer,size_t Count,myf MyFlags); +extern size_t my_fwrite(FILE *stream,const uchar *Buffer,size_t Count, + myf MyFlags); +extern my_off_t my_fseek(FILE *stream,my_off_t pos,int whence,myf MyFlags); +extern my_off_t my_ftell(FILE *stream,myf MyFlags); +extern void *_mymalloc(size_t uSize,const char *sFile, + uint uLine, myf MyFlag); +extern void *_myrealloc(void *pPtr,size_t uSize,const char *sFile, + uint uLine, myf MyFlag); +extern void * my_multi_malloc _VARARGS((myf MyFlags, ...)); +extern void _myfree(void *pPtr,const char *sFile,uint uLine, myf MyFlag); +extern int _sanity(const char *sFile, uint uLine); +extern void *_my_memdup(const void *from, size_t length, + const char *sFile, uint uLine,myf MyFlag); +extern char * _my_strdup(const char *from, const char *sFile, uint uLine, + myf MyFlag); +extern char *_my_strndup(const char *from, size_t length, + const char *sFile, uint uLine, + myf MyFlag); + +/* implemented in my_memmem.c */ +extern void *my_memmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen); + + +#ifdef _WIN32 +extern int my_access(const char *path, int amode); +#else +#define my_access access +#endif + +extern int check_if_legal_filename(const char *path); +extern int check_if_legal_tablename(const char *path); + +#ifdef _WIN32 +extern int nt_share_delete(const char *name,myf MyFlags); +#define my_delete_allow_opened(fname,flags) nt_share_delete((fname),(flags)) +#else +#define my_delete_allow_opened(fname,flags) my_delete((fname),(flags)) +#endif + +#ifdef _WIN32 +/* Windows-only functions (CRT equivalents)*/ +extern File my_sopen(const char *path, int oflag, int shflag, int pmode); +extern HANDLE my_get_osfhandle(File fd); +extern void my_osmaperr(unsigned long last_error); +#endif + +#ifndef TERMINATE +extern void TERMINATE(FILE *file, uint flag); +#endif +extern void init_glob_errs(void); +extern void wait_for_free_space(const char *filename, int errors); +extern FILE *my_fopen(const char *FileName,int Flags,myf MyFlags); +extern FILE *my_fdopen(File Filedes,const char *name, int Flags,myf MyFlags); +extern int my_fclose(FILE *fd,myf MyFlags); +extern File my_fileno(FILE *fd); +extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags); +extern int my_chmod(const char *name, mode_t mode, myf my_flags); +extern int my_sync(File fd, myf my_flags); +extern int my_sync_dir(const char *dir_name, myf my_flags); +extern int my_sync_dir_by_file(const char *file_name, myf my_flags); +extern void my_error _VARARGS((int nr,myf MyFlags, ...)); +extern void my_printf_error _VARARGS((uint my_err, const char *format, + myf MyFlags, ...)) + ATTRIBUTE_FORMAT(printf, 2, 4); +extern void my_printv_error(uint error, const char *format, myf MyFlags, + va_list ap); +extern int my_error_register(const char **errmsgs, int first, int last); +extern const char **my_error_unregister(int first, int last); +extern void my_message(uint my_err, const char *str,myf MyFlags); +extern void my_message_no_curses(uint my_err, const char *str,myf MyFlags); +extern my_bool my_init(void); +extern void my_end(int infoflag); +extern int my_redel(const char *from, const char *to, int MyFlags); +extern int my_copystat(const char *from, const char *to, int MyFlags); +extern char * my_filename(File fd); + +#ifndef THREAD +extern void dont_break(void); +extern void allow_break(void); +#else +#define dont_break() +#define allow_break() +#endif + +#ifdef EXTRA_DEBUG +void my_print_open_files(void); +#else +#define my_print_open_files() +#endif + +extern my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist); +extern char *my_tmpdir(MY_TMPDIR *tmpdir); +extern void free_tmpdir(MY_TMPDIR *tmpdir); + +extern void my_remember_signal(int signal_number,sig_handler (*func)(int)); +extern size_t dirname_part(char * to,const char *name, size_t *to_res_length); +extern size_t dirname_length(const char *name); +#define base_name(A) (A+dirname_length(A)) +extern int test_if_hard_path(const char *dir_name); +extern my_bool has_path(const char *name); +extern char *convert_dirname(char *to, const char *from, const char *from_end); +extern void to_unix_path(char * name); +extern char * fn_ext(const char *name); +extern char * fn_same(char * toname,const char *name,int flag); +extern char * fn_format(char * to,const char *name,const char *dir, + const char *form, uint flag); +extern size_t strlength(const char *str); +extern void pack_dirname(char * to,const char *from); +extern size_t normalize_dirname(char * to, const char *from); +extern size_t unpack_dirname(char * to,const char *from); +extern size_t cleanup_dirname(char * to,const char *from); +extern size_t system_filename(char * to,const char *from); +extern size_t unpack_filename(char * to,const char *from); +extern char * intern_filename(char * to,const char *from); +extern char * directory_file_name(char * dst, const char *src); +extern int pack_filename(char * to, const char *name, size_t max_length); +extern char * my_path(char * to,const char *progname, + const char *own_pathname_part); +extern char * my_load_path(char * to, const char *path, + const char *own_path_prefix); +extern int wild_compare(const char *str,const char *wildstr, + pbool str_is_pattern); +extern WF_PACK *wf_comp(char * str); +extern int wf_test(struct wild_file_pack *wf_pack,const char *name); +extern void wf_end(struct wild_file_pack *buffer); +extern size_t strip_sp(char * str); +extern my_bool array_append_string_unique(const char *str, + const char **array, size_t size); +extern void get_date(char * to,int timeflag,time_t use_time); +extern void soundex(CHARSET_INFO *, char * out_pntr, char * in_pntr, + pbool remove_garbage); +extern int init_record_cache(RECORD_CACHE *info,size_t cachesize,File file, + size_t reclength,enum cache_type type, + pbool use_async_io); +extern int read_cache_record(RECORD_CACHE *info,uchar *to); +extern int end_record_cache(RECORD_CACHE *info); +extern int write_cache_record(RECORD_CACHE *info,my_off_t filepos, + const uchar *record,size_t length); +extern int flush_write_cache(RECORD_CACHE *info); +extern long my_clock(void); +extern sig_handler sigtstp_handler(int signal_number); +extern void handle_recived_signals(void); + +extern sig_handler my_set_alarm_variable(int signo); +extern void my_string_ptr_sort(uchar *base,uint items,size_t size); +extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements, + size_t size_of_element,uchar *buffer[]); +extern qsort_t my_qsort(void *base_ptr, size_t total_elems, size_t size, + qsort_cmp cmp); +extern qsort_t my_qsort2(void *base_ptr, size_t total_elems, size_t size, + qsort2_cmp cmp, void *cmp_argument); +extern qsort2_cmp get_ptr_compare(size_t); +void my_store_ptr(uchar *buff, size_t pack_length, my_off_t pos); +my_off_t my_get_ptr(uchar *ptr, size_t pack_length); +extern int init_io_cache(IO_CACHE *info,File file,size_t cachesize, + enum cache_type type,my_off_t seek_offset, + pbool use_async_io, myf cache_myflags); +extern my_bool reinit_io_cache(IO_CACHE *info,enum cache_type type, + my_off_t seek_offset,pbool use_async_io, + pbool clear_cache); +extern void setup_io_cache(IO_CACHE* info); +extern int _my_b_read(IO_CACHE *info,uchar *Buffer,size_t Count); +#ifdef THREAD +extern int _my_b_read_r(IO_CACHE *info,uchar *Buffer,size_t Count); +extern void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare, + IO_CACHE *write_cache, uint num_threads); +extern void remove_io_thread(IO_CACHE *info); +#endif +extern int _my_b_seq_read(IO_CACHE *info,uchar *Buffer,size_t Count); +extern int _my_b_net_read(IO_CACHE *info,uchar *Buffer,size_t Count); +extern int _my_b_get(IO_CACHE *info); +extern int _my_b_async_read(IO_CACHE *info,uchar *Buffer,size_t Count); +extern int _my_b_write(IO_CACHE *info,const uchar *Buffer,size_t Count); +extern int my_b_append(IO_CACHE *info,const uchar *Buffer,size_t Count); +extern int my_b_safe_write(IO_CACHE *info,const uchar *Buffer,size_t Count); + +extern int my_block_write(IO_CACHE *info, const uchar *Buffer, + size_t Count, my_off_t pos); +extern int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock); + +#define flush_io_cache(info) my_b_flush_io_cache((info),1) + +extern int end_io_cache(IO_CACHE *info); +extern size_t my_b_fill(IO_CACHE *info); +extern void my_b_seek(IO_CACHE *info,my_off_t pos); +extern size_t my_b_gets(IO_CACHE *info, char *to, size_t max_length); +extern my_off_t my_b_filelength(IO_CACHE *info); +extern size_t my_b_printf(IO_CACHE *info, const char* fmt, ...); +extern size_t my_b_vprintf(IO_CACHE *info, const char* fmt, va_list ap); +extern my_bool open_cached_file(IO_CACHE *cache,const char *dir, + const char *prefix, size_t cache_size, + myf cache_myflags); +extern my_bool real_open_cached_file(IO_CACHE *cache); +extern void close_cached_file(IO_CACHE *cache); +File create_temp_file(char *to, const char *dir, const char *pfx, + int mode, myf MyFlags); +#define my_init_dynamic_array(A,B,C,D) init_dynamic_array2(A,B,NULL,C,D CALLER_INFO) +#define my_init_dynamic_array_ci(A,B,C,D) init_dynamic_array2(A,B,NULL,C,D ORIG_CALLER_INFO) +#define my_init_dynamic_array2(A,B,C,D,E) init_dynamic_array2(A,B,C,D,E CALLER_INFO) +#define my_init_dynamic_array2_ci(A,B,C,D,E) init_dynamic_array2(A,B,C,D,E ORIG_CALLER_INFO) +extern my_bool init_dynamic_array2(DYNAMIC_ARRAY *array,uint element_size, + void *init_buffer, uint init_alloc, + uint alloc_increment + CALLER_INFO_PROTO); +/* init_dynamic_array() function is deprecated */ +extern my_bool init_dynamic_array(DYNAMIC_ARRAY *array,uint element_size, + uint init_alloc,uint alloc_increment + CALLER_INFO_PROTO); +extern my_bool insert_dynamic(DYNAMIC_ARRAY *array, const uchar * element); +extern uchar *alloc_dynamic(DYNAMIC_ARRAY *array); +extern uchar *pop_dynamic(DYNAMIC_ARRAY*); +extern my_bool set_dynamic(DYNAMIC_ARRAY *array,uchar * element,uint array_index); +extern my_bool allocate_dynamic(DYNAMIC_ARRAY *array, uint max_elements); +extern void get_dynamic(DYNAMIC_ARRAY *array,uchar * element,uint array_index); +extern void delete_dynamic(DYNAMIC_ARRAY *array); +extern void delete_dynamic_element(DYNAMIC_ARRAY *array, uint array_index); +extern void freeze_size(DYNAMIC_ARRAY *array); +extern int get_index_dynamic(DYNAMIC_ARRAY *array, uchar * element); +#define dynamic_array_ptr(array,array_index) ((array)->buffer+(array_index)*(array)->size_of_element) +#define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index)) +#define push_dynamic(A,B) insert_dynamic((A),(B)) +#define reset_dynamic(array) ((array)->elements= 0) +#define sort_dynamic(A,cmp) my_qsort((A)->buffer, (A)->elements, (A)->size_of_element, (cmp)) + +extern my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str, + size_t init_alloc,size_t alloc_increment); +extern my_bool dynstr_append(DYNAMIC_STRING *str, const char *append); +my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append, + size_t length); +extern my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, + ...); +extern my_bool dynstr_set(DYNAMIC_STRING *str, const char *init_str); +extern my_bool dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size); +extern my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n); +extern void dynstr_free(DYNAMIC_STRING *str); +#ifdef HAVE_MLOCK +extern void *my_malloc_lock(size_t length,myf flags); +extern void my_free_lock(void *ptr,myf flags); +#else +#define my_malloc_lock(A,B) my_malloc((A),(B)) +#define my_free_lock(A,B) my_free((A),(B)) +#endif +#define alloc_root_inited(A) ((A)->min_malloc != 0) +#define ALLOC_ROOT_MIN_BLOCK_SIZE (MALLOC_OVERHEAD + sizeof(USED_MEM) + 8) +#define clear_alloc_root(A) do { (A)->free= (A)->used= (A)->pre_alloc= 0; (A)->min_malloc=0;} while(0) +extern void init_alloc_root(MEM_ROOT *mem_root, size_t block_size, + size_t pre_alloc_size); +extern void *alloc_root(MEM_ROOT *mem_root, size_t Size); +extern void *multi_alloc_root(MEM_ROOT *mem_root, ...); +extern void free_root(MEM_ROOT *root, myf MyFLAGS); +extern void set_prealloc_root(MEM_ROOT *root, char *ptr); +extern void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, + size_t prealloc_size); +extern char *strdup_root(MEM_ROOT *root,const char *str); +extern char *strmake_root(MEM_ROOT *root,const char *str,size_t len); +extern void *memdup_root(MEM_ROOT *root,const void *str, size_t len); +extern int get_defaults_options(int argc, char **argv, + char **defaults, char **extra_defaults, + char **group_suffix); +extern const char *args_separator; +extern int my_load_defaults(const char *conf_file, const char **groups, + int *argc, char ***argv, const char ***); +extern int load_defaults(const char *conf_file, const char **groups, + int *argc, char ***argv); +extern int modify_defaults_file(const char *file_location, const char *option, + const char *option_value, + const char *section_name, int remove_option); +extern int my_search_option_files(const char *conf_file, int *argc, + char ***argv, uint *args_used, + Process_option_func func, void *func_ctx, + const char **default_directories); +extern void free_defaults(char **argv); +extern void my_print_default_files(const char *conf_file); +extern void print_defaults(const char *conf_file, const char **groups); +extern my_bool my_compress(uchar *, size_t *, size_t *); +extern my_bool my_uncompress(uchar *, size_t , size_t *); +extern uchar *my_compress_alloc(const uchar *packet, size_t *len, + size_t *complen); +extern int packfrm(uchar *, size_t, uchar **, size_t *); +extern int unpackfrm(uchar **, size_t *, const uchar *); + +extern ha_checksum my_checksum(ha_checksum crc, const uchar *mem, + size_t count); +#ifndef DBUG_OFF +extern void my_debug_put_break_here(void); +#else +#define my_debug_put_break_here() do {} while(0) +#endif + +extern void my_sleep(ulong m_seconds); +extern ulong crc32(ulong crc, const uchar *buf, uint len); +extern uint my_set_max_open_files(uint files); +void my_free_open_file_info(void); + +extern time_t my_time(myf flags); +extern ulonglong my_getsystime(void); +extern ulonglong my_micro_time(); +extern ulonglong my_micro_time_and_time(time_t *time_arg); +time_t my_time_possible_from_micro(ulonglong microtime); +extern my_bool my_gethwaddr(uchar *to); +extern int my_getncpus(); + +#ifdef HAVE_SYS_MMAN_H +#include + +#ifndef MAP_NOSYNC +#define MAP_NOSYNC 0 +#endif +#ifndef MAP_NORESERVE +#define MAP_NORESERVE 0 /* For irix and AIX */ +#endif + +#ifdef HAVE_MMAP64 +#define my_mmap(a,b,c,d,e,f) mmap64(a,b,c,d,e,f) +#else +#define my_mmap(a,b,c,d,e,f) mmap(a,b,c,d,e,f) +#endif +#define my_munmap(a,b) munmap((a),(b)) + +#else +/* not a complete set of mmap() flags, but only those that nesessary */ +#define PROT_READ 1 +#define PROT_WRITE 2 +#define MAP_NORESERVE 0 +#define MAP_SHARED 0x0001 +#define MAP_PRIVATE 0x0002 +#define MAP_NOSYNC 0x0800 +#define MAP_FAILED ((void *)-1) +#define MS_SYNC 0x0000 + +#ifndef __NETWARE__ +#define HAVE_MMAP +#endif + +void *my_mmap(void *, size_t, int, int, int, my_off_t); +int my_munmap(void *, size_t); +#endif + +/* my_getpagesize */ +#ifdef HAVE_GETPAGESIZE +#define my_getpagesize() getpagesize() +#else +int my_getpagesize(void); +#endif + +int my_msync(int, void *, size_t, int); + +#define MY_UUID_SIZE 16 +#define MY_UUID_STRING_LENGTH (8+1+4+1+4+1+4+1+12) + +void my_uuid_init(ulong seed1, ulong seed2); +void my_uuid(uchar *guid); +void my_uuid2str(const uchar *guid, char *s); +void my_uuid_end(); + +struct my_rnd_struct { + unsigned long seed1,seed2,max_value; + double max_value_dbl; +}; + +void my_rnd_init(struct my_rnd_struct *rand_st, ulong seed1, ulong seed2); +double my_rnd(struct my_rnd_struct *rand_st); + +/* character sets */ +extern uint get_charset_number(const char *cs_name, uint cs_flags); +extern uint get_collation_number(const char *name); +extern const char *get_charset_name(uint cs_number); + +extern CHARSET_INFO *get_charset(uint cs_number, myf flags); +extern CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags); +extern CHARSET_INFO *get_charset_by_csname(const char *cs_name, + uint cs_flags, myf my_flags); + +extern my_bool resolve_charset(const char *cs_name, + CHARSET_INFO *default_cs, + CHARSET_INFO **cs); +extern my_bool resolve_collation(const char *cl_name, + CHARSET_INFO *default_cl, + CHARSET_INFO **cl); + +extern void free_charsets(void); +extern char *get_charsets_dir(char *buf); +extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2); +extern my_bool init_compiled_charsets(myf flags); +extern void add_compiled_collation(CHARSET_INFO *cs); +extern size_t escape_string_for_mysql(CHARSET_INFO *charset_info, + char *to, size_t to_length, + const char *from, size_t length); +#ifdef __WIN__ +#define BACKSLASH_MBTAIL +/* File system character set */ +extern CHARSET_INFO *fs_character_set(void); +#endif +extern size_t escape_quotes_for_mysql(CHARSET_INFO *charset_info, + char *to, size_t to_length, + const char *from, size_t length); + +extern void thd_increment_bytes_sent(ulong length); +extern void thd_increment_bytes_received(ulong length); +extern void thd_increment_net_big_packet_count(ulong length); + +#ifdef __WIN__ +extern my_bool have_tcpip; /* Is set if tcpip is used */ + +/* implemented in my_windac.c */ + +int my_security_attr_create(SECURITY_ATTRIBUTES **psa, const char **perror, + DWORD owner_rights, DWORD everybody_rights); + +void my_security_attr_free(SECURITY_ATTRIBUTES *sa); + +/* implemented in my_conio.c */ +char* my_cgets(char *string, size_t clen, size_t* plen); + +#endif +#ifdef __NETWARE__ +void netware_reg_user(const char *ip, const char *user, + const char *application); +#endif + +C_MODE_END +#endif /* _my_sys_h */ diff --git a/NetService/include/Mysql/my_time.h b/NetService/include/Mysql/my_time.h new file mode 100644 index 00000000..58995f1b --- /dev/null +++ b/NetService/include/Mysql/my_time.h @@ -0,0 +1,172 @@ +/* Copyright (C) 2004-2005 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + This is a private header of sql-common library, containing + declarations for my_time.c +*/ + +#ifndef _my_time_h_ +#define _my_time_h_ +#include "my_global.h" +#include "mysql_time.h" + +C_MODE_START + +extern ulonglong log_10_int[20]; +extern uchar days_in_month[]; + +/* + Portable time_t replacement. + Should be signed and hold seconds for 1902 -- 2038-01-19 range + i.e at least a 32bit variable + + Using the system built in time_t is not an option as + we rely on the above requirements in the time functions + + For example QNX has an unsigned time_t type +*/ +typedef long my_time_t; + +#define MY_TIME_T_MAX LONG_MAX +#define MY_TIME_T_MIN LONG_MIN + +/* Time handling defaults */ +#define TIMESTAMP_MAX_YEAR 2038 +#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1) +#define TIMESTAMP_MAX_VALUE INT_MAX32 +#define TIMESTAMP_MIN_VALUE 1 + +/* two-digit years < this are 20..; >= this are 19.. */ +#define YY_PART_YEAR 70 + +/* Flags to str_to_datetime */ +#define TIME_FUZZY_DATE 1 +#define TIME_DATETIME_ONLY 2 +/* Must be same as MODE_NO_ZERO_IN_DATE */ +#define TIME_NO_ZERO_IN_DATE (65536L*2*2*2*2*2*2*2) +/* Must be same as MODE_NO_ZERO_DATE */ +#define TIME_NO_ZERO_DATE (TIME_NO_ZERO_IN_DATE*2) +#define TIME_INVALID_DATES (TIME_NO_ZERO_DATE*2) + +#define MYSQL_TIME_WARN_TRUNCATED 1 +#define MYSQL_TIME_WARN_OUT_OF_RANGE 2 + +/* Limits for the TIME data type */ +#define TIME_MAX_HOUR 838 +#define TIME_MAX_MINUTE 59 +#define TIME_MAX_SECOND 59 +#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + \ + TIME_MAX_SECOND) +#define TIME_MAX_VALUE_SECONDS (TIME_MAX_HOUR * 3600L + \ + TIME_MAX_MINUTE * 60L + TIME_MAX_SECOND) + +my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date, + ulong flags, int *was_cut); +enum enum_mysql_timestamp_type +str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, + uint flags, int *was_cut); +longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res, + uint flags, int *was_cut); +ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *); +ulonglong TIME_to_ulonglong_date(const MYSQL_TIME *); +ulonglong TIME_to_ulonglong_time(const MYSQL_TIME *); +ulonglong TIME_to_ulonglong(const MYSQL_TIME *); + + +my_bool str_to_time(const char *str,uint length, MYSQL_TIME *l_time, + int *warning); + +int check_time_range(struct st_mysql_time *, int *warning); + +long calc_daynr(uint year,uint month,uint day); +uint calc_days_in_year(uint year); +uint year_2000_handling(uint year); + +void my_init_time(void); + + +/* + Function to check sanity of a TIMESTAMP value + + DESCRIPTION + Check if a given MYSQL_TIME value fits in TIMESTAMP range. + This function doesn't make precise check, but rather a rough + estimate. + + RETURN VALUES + FALSE The value seems sane + TRUE The MYSQL_TIME value is definitely out of range +*/ + +static inline my_bool validate_timestamp_range(const MYSQL_TIME *t) +{ + if ((t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR) || + (t->year == TIMESTAMP_MAX_YEAR && (t->month > 1 || t->day > 19)) || + (t->year == TIMESTAMP_MIN_YEAR && (t->month < 12 || t->day < 31))) + return FALSE; + + return TRUE; +} + +my_time_t +my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, + my_bool *in_dst_time_gap); + +void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type); + +/* + Required buffer length for my_time_to_str, my_date_to_str, + my_datetime_to_str and TIME_to_string functions. Note, that the + caller is still responsible to check that given TIME structure + has values in valid ranges, otherwise size of the buffer could + be not enough. We also rely on the fact that even wrong values + sent using binary protocol fit in this buffer. +*/ +#define MAX_DATE_STRING_REP_LENGTH 30 + +int my_time_to_str(const MYSQL_TIME *l_time, char *to); +int my_date_to_str(const MYSQL_TIME *l_time, char *to); +int my_datetime_to_str(const MYSQL_TIME *l_time, char *to); +int my_TIME_to_str(const MYSQL_TIME *l_time, char *to); + +/* + Available interval types used in any statement. + + 'interval_type' must be sorted so that simple intervals comes first, + ie year, quarter, month, week, day, hour, etc. The order based on + interval size is also important and the intervals should be kept in a + large to smaller order. (get_interval_value() depends on this) + + Note: If you change the order of elements in this enum you should fix + order of elements in 'interval_type_to_name' and 'interval_names' + arrays + + See also interval_type_to_name, get_interval_value, interval_names +*/ + +enum interval_type +{ + INTERVAL_YEAR, INTERVAL_QUARTER, INTERVAL_MONTH, INTERVAL_WEEK, INTERVAL_DAY, + INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_SECOND, INTERVAL_MICROSECOND, + INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE, + INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND, + INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND, + INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND, INTERVAL_LAST +}; + +C_MODE_END + +#endif /* _my_time_h_ */ diff --git a/NetService/include/Mysql/my_tree.h b/NetService/include/Mysql/my_tree.h new file mode 100644 index 00000000..e387b25d --- /dev/null +++ b/NetService/include/Mysql/my_tree.h @@ -0,0 +1,96 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _tree_h +#define _tree_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "my_base.h" /* get 'enum ha_rkey_function' */ + +/* Worst case tree is half full. This gives use 2^(MAX_TREE_HEIGHT/2) leafs */ +#define MAX_TREE_HEIGHT 64 + +#define ELEMENT_KEY(tree,element)\ +(tree->offset_to_key ? (void*)((uchar*) element+tree->offset_to_key) :\ + *((void**) (element+1))) + +#define tree_set_pointer(element,ptr) *((uchar **) (element+1))=((uchar*) (ptr)) + +#define TREE_NO_DUPS 1 + +typedef enum { left_root_right, right_root_left } TREE_WALK; +typedef uint32 element_count; +typedef int (*tree_walk_action)(void *,element_count,void *); + +typedef enum { free_init, free_free, free_end } TREE_FREE; +typedef void (*tree_element_free)(void*, TREE_FREE, void *); + +typedef struct st_tree_element { + struct st_tree_element *left,*right; + uint32 count:31, + colour:1; /* black is marked as 1 */ +} TREE_ELEMENT; + +#define ELEMENT_CHILD(element, offs) (*(TREE_ELEMENT**)((char*)element + offs)) + +typedef struct st_tree { + TREE_ELEMENT *root,null_element; + TREE_ELEMENT **parents[MAX_TREE_HEIGHT]; + uint offset_to_key,elements_in_tree,size_of_element; + ulong memory_limit, allocated; + qsort_cmp2 compare; + void *custom_arg; + MEM_ROOT mem_root; + my_bool with_delete; + tree_element_free free; + uint flag; +} TREE; + + /* Functions on whole tree */ +void init_tree(TREE *tree, ulong default_alloc_size, ulong memory_limit, + int size, qsort_cmp2 compare, my_bool with_delete, + tree_element_free free_element, void *custom_arg); +void delete_tree(TREE*); +void reset_tree(TREE*); + + /* similar to delete tree, except we do not my_free() blocks in mem_root */ +#define is_tree_inited(tree) ((tree)->root != 0) + + /* Functions on leafs */ +TREE_ELEMENT *tree_insert(TREE *tree,void *key, uint key_size, + void *custom_arg); +void *tree_search(TREE *tree, void *key, void *custom_arg); +int tree_walk(TREE *tree,tree_walk_action action, + void *argument, TREE_WALK visit); +int tree_delete(TREE *tree, void *key, uint key_size, void *custom_arg); +void *tree_search_key(TREE *tree, const void *key, + TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos, + enum ha_rkey_function flag, void *custom_arg); +void *tree_search_edge(TREE *tree, TREE_ELEMENT **parents, + TREE_ELEMENT ***last_pos, int child_offs); +void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs, + int r_offs); +ha_rows tree_record_pos(TREE *tree, const void *key, + enum ha_rkey_function search_flag, void *custom_arg); +#define reset_free_element(tree) (tree)->free= 0 + +#define TREE_ELEMENT_EXTRA_SIZE (sizeof(TREE_ELEMENT) + sizeof(void*)) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/NetService/include/Mysql/my_trie.h b/NetService/include/Mysql/my_trie.h new file mode 100644 index 00000000..72dd485a --- /dev/null +++ b/NetService/include/Mysql/my_trie.h @@ -0,0 +1,141 @@ +/* Copyright (C) 2005 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _trie_h +#define _trie_h +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct st_trie_node +{ + uint16 leaf; /* Depth from root node if match, 0 else */ + uchar c; /* Label on this edge */ + struct st_trie_node *next; /* Next label */ + struct st_trie_node *links; /* Array of edges leaving this node */ + struct st_trie_node *fail; /* AC failure function */ +} TRIE_NODE; + +typedef struct st_trie +{ + TRIE_NODE root; + MEM_ROOT mem_root; + CHARSET_INFO *charset; + uint32 nnodes; + uint32 nwords; +} TRIE; + +typedef struct st_ac_trie_state +{ + TRIE *trie; + TRIE_NODE *node; +} AC_TRIE_STATE; + +extern TRIE *trie_init (TRIE *trie, CHARSET_INFO *charset); +extern void trie_free (TRIE *trie); +extern my_bool trie_insert (TRIE *trie, const uchar *key, uint keylen); +extern my_bool ac_trie_prepare (TRIE *trie); +extern void ac_trie_init (TRIE *trie, AC_TRIE_STATE *state); + + +/* `trie_goto' is internal function and shouldn't be used. */ + +static inline TRIE_NODE *trie_goto (TRIE_NODE *root, TRIE_NODE *node, uchar c) +{ + TRIE_NODE *next; + DBUG_ENTER("trie_goto"); + for (next= node->links; next; next= next->next) + if (next->c == c) + DBUG_RETURN(next); + if (root == node) + DBUG_RETURN(root); + DBUG_RETURN(NULL); +} + + +/* + SYNOPSIS + int ac_trie_next (AC_TRIE_STATE *state, uchar *c); + state - valid pointer to `AC_TRIE_STATE' + c - character to lookup + + DESCRIPTION + Implementation of search using Aho-Corasick automaton. + Performs char-by-char search. + + RETURN VALUE + `ac_trie_next' returns length of matched word or 0. +*/ + +static inline int ac_trie_next (AC_TRIE_STATE *state, uchar *c) +{ + TRIE_NODE *root, *node; + DBUG_ENTER("ac_trie_next"); + DBUG_ASSERT(state && c); + root= &state->trie->root; + node= state->node; + while (! (state->node= trie_goto(root, node, *c))) + node= node->fail; + DBUG_RETURN(state->node->leaf); +} + + +/* + SYNOPSIS + my_bool trie_search (TRIE *trie, const uchar *key, uint keylen); + trie - valid pointer to `TRIE' + key - valid pointer to key to insert + keylen - non-0 key length + + DESCRIPTION + Performs key lookup in trie. + + RETURN VALUE + `trie_search' returns `true' if key is in `trie'. Otherwise, + `false' is returned. + + NOTES + Consecutive search here is "best by test". arrays are very short, so + binary search or hashing would add too much complexity that would + overweight speed gain. Especially because compiler can optimize simple + consecutive loop better (tested) +*/ + +static inline my_bool trie_search (TRIE *trie, const uchar *key, uint keylen) +{ + TRIE_NODE *node; + uint k; + DBUG_ENTER("trie_search"); + DBUG_ASSERT(trie && key && keylen); + node= &trie->root; + + for (k= 0; k < keylen; k++) + { + uchar p; + if (! (node= node->links)) + DBUG_RETURN(FALSE); + p= key[k]; + while (p != node->c) + if (! (node= node->next)) + DBUG_RETURN(FALSE); + } + + DBUG_RETURN(node->leaf > 0); +} + +#ifdef __cplusplus +} +#endif +#endif diff --git a/NetService/include/Mysql/my_uctype.h b/NetService/include/Mysql/my_uctype.h new file mode 100644 index 00000000..9aaf4788 --- /dev/null +++ b/NetService/include/Mysql/my_uctype.h @@ -0,0 +1,1479 @@ +/* Copyright (C) 2006 MySQL AB + + 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; version 2 of the License. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/* + Unicode ctype data + Generated from UnicodeData-5.0.0d9.txt +*/ +static unsigned char uctype_page00[256]= +{ + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, + 16, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 16, 16, 16, 16, 16, + 16, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 16, 16, 16, 16, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 32, 16, 16, + 16, 16, 20, 20, 16, 2, 16, 16, 16, 20, 2, 16, 20, 20, 20, 16, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static unsigned char uctype_page01[256]= +{ + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, + 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, + 1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 2, 1, 1, 2, 1, + 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 1, 1, + 2, 1, 1, 1, 2, 1, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, + 2, 2, 2, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 2, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2 +}; + +static unsigned char uctype_page02[256]= +{ + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 2, + 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 2, 2, 2, 2, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +}; + +static unsigned char uctype_page03[256]= +{ + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 0, 0, 0, 0, 16, 16, 0, 0, 0, 0, 2, 2, 2, 2, 16, 0, + 0, 0, 0, 0, 16, 16, 1, 16, 1, 1, 1, 0, 1, 0, 1, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 2, 2, 2, 2, 1, 2, 16, 1, 2, 1, 1, 2, 2, 1, 1, 1 +}; + +static unsigned char uctype_page04[256]= +{ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 16, 18, 18, 18, 18, 0, 18, 18, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 +}; + +static unsigned char uctype_page05[256]= +{ + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 2, 16, 16, 16, 16, 16, 16, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 16, 16, 0, 0, 0, 0, 0, + 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 16, 18, + 16, 18, 18, 16, 18, 18, 16, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 2, 2, 2, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page06[256]= +{ + 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, + 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 16, 0, 0, 16, 16, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 2, 2, + 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 16, 2, 18, 18, 18, 18, 18, 18, 18, 32, 18, 18, + 18, 18, 18, 18, 18, 2, 2, 18, 18, 16, 18, 18, 18, 18, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 16, 16, 2 +}; + +static unsigned char uctype_page07[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 32, + 2, 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 2, 2, 16, 16, 16, 16, 2, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page09[256]= +{ + 0, 18, 18, 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, + 2, 18, 18, 18, 18, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 18, 18, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, + 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, + 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, + 18, 18, 18, 18, 18, 0, 0, 18, 18, 0, 0, 18, 18, 18, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 2, 2, 0, 2, + 2, 2, 18, 18, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 16, 16, 20, 20, 20, 20, 20, 20, 16, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page0A[256]= +{ + 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, + 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 18, 0, 18, 18, + 18, 18, 18, 0, 0, 0, 0, 18, 18, 0, 0, 18, 18, 18, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 18, 18, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, + 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, + 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 0, 18, 18, 18, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 18, 18, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page0B[256]= +{ + 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, + 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, + 18, 18, 18, 18, 0, 0, 0, 18, 18, 0, 0, 18, 18, 18, 0, 0, + 0, 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 2, 2, 0, 2, + 2, 2, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 16, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, + 2, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 0, 2, 0, 2, 2, + 0, 0, 0, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 18, 18, + 18, 18, 18, 0, 0, 0, 18, 18, 18, 0, 18, 18, 18, 18, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page0C[256]= +{ + 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, + 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 18, 18, + 18, 18, 18, 18, 18, 0, 18, 18, 18, 0, 18, 18, 18, 18, 0, 0, + 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, + 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, + 18, 18, 18, 18, 18, 0, 18, 18, 18, 0, 18, 18, 18, 18, 0, 0, + 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 2, 0, + 2, 2, 18, 18, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page0D[256]= +{ + 0, 0, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, + 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 18, 18, + 18, 18, 18, 18, 0, 0, 18, 18, 18, 0, 18, 18, 18, 18, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 18, 0, 0, 0, 0, 18, + 18, 18, 18, 18, 18, 0, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18, 18, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page0E[256]= +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 18, 2, 2, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 16, + 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 16, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 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, 2, 2, 0, 2, 0, 0, 2, 2, 0, 2, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, + 0, 2, 2, 2, 0, 2, 0, 2, 0, 0, 2, 2, 0, 2, 2, 2, + 2, 18, 2, 2, 18, 18, 18, 18, 18, 18, 0, 18, 18, 2, 0, 0, + 2, 2, 2, 2, 2, 0, 2, 0, 18, 18, 18, 18, 18, 18, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 2, 2, 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 +}; + +static unsigned char uctype_page0F[256]= +{ + 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 16, 16, 16, 16, 16, 16, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 16, 18, 16, 18, 16, 18, 16, 16, 16, 16, 18, 18, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 16, 18, 18, 2, 2, 2, 2, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 16, 16, + 16, 16, 16, 16, 16, 16, 18, 16, 16, 16, 16, 16, 16, 0, 0, 16, + 16, 16, 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, 0, 0, 0 +}; + +static unsigned char uctype_page10[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 0, 18, 18, 18, 18, + 18, 18, 18, 0, 0, 0, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, + 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 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, 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, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 0, 0, 0 +}; + +static unsigned char uctype_page11[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page12[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static unsigned char uctype_page13[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 18, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page14[256]= +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static unsigned char uctype_page16[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 7, 7, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page17[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, + 2, 2, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 18, 18, 18, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, + 2, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 32, 32, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 16, 16, 16, 2, 16, 16, 16, 16, 2, 18, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page18[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 18, 8, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 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, 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 +}; + +static unsigned char uctype_page19[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, + 16, 0, 0, 0, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 2, 2, 2, 2, 2, 2, 2, 18, 18, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +}; + +static unsigned char uctype_page1A[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 0, 0, 16, 16, + 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, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page1B[256]= +{ + 18, 18, 18, 18, 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 16, 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, 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, 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, 0, 0 +}; + +static unsigned char uctype_page1D[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 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, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18 +}; + +static unsigned char uctype_page1E[256]= +{ + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page1F[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 1, 0, 1, 0, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 0, 2, 2, 1, 1, 1, 1, 1, 16, 2, 16, + 16, 16, 2, 2, 2, 0, 2, 2, 1, 1, 1, 1, 1, 16, 16, 16, + 2, 2, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 0, 16, 16, 16, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 16, 16, 16, + 0, 0, 2, 2, 2, 0, 2, 2, 1, 1, 1, 1, 1, 16, 16, 0 +}; + +static unsigned char uctype_page20[256]= +{ + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 32, 32, 32, 32, 32, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 32, 32, 32, 32, 32, 8, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, + 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 32, 32, 32, 32, 32, 32, + 20, 2, 0, 0, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 2, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 0, + 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 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, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page21[256]= +{ + 16, 16, 1, 16, 16, 16, 16, 1, 16, 16, 2, 1, 1, 1, 2, 2, + 1, 1, 1, 2, 16, 1, 16, 16, 16, 1, 1, 1, 1, 1, 16, 16, + 16, 16, 16, 16, 1, 16, 1, 16, 1, 16, 1, 1, 1, 1, 16, 2, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 16, 16, 2, 2, 1, 1, + 16, 16, 16, 16, 16, 1, 2, 2, 2, 2, 16, 16, 16, 16, 2, 0, + 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +}; + +static unsigned char uctype_page23[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page24[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 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, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 +}; + +static unsigned char uctype_page26[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 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, 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 +}; + +static unsigned char uctype_page27[256]= +{ + 0, 16, 16, 16, 16, 0, 16, 16, 16, 16, 0, 0, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 0, 16, + 16, 16, 16, 0, 0, 0, 16, 0, 16, 16, 16, 16, 16, 16, 16, 0, + 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 16, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +}; + +static unsigned char uctype_page2B[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 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, 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, 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, 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, + 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, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page2C[256]= +{ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 1, 2, 1, 1, 1, 2, 2, 1, 2, 1, 2, 1, 2, 0, 0, 0, + 0, 0, 0, 0, 2, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 2, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 20, 16, 16 +}; + +static unsigned char uctype_page2D[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 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 +}; + +static unsigned char uctype_page2E[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 16, 16, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page2F[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 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, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0 +}; + +static unsigned char uctype_page30[256]= +{ + 8, 16, 16, 16, 16, 2, 2, 7, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 7, 7, 7, 7, 7, 7, 7, 7, 7, 18, 18, 18, 18, 18, 18, + 16, 2, 2, 2, 2, 2, 16, 16, 7, 7, 7, 2, 2, 16, 16, 16, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 0, 18, 18, 16, 16, 2, 2, 2, + 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2 +}; + +static unsigned char uctype_page31[256]= +{ + 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 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, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static unsigned char uctype_page32[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0 +}; + +static unsigned char uctype_page4D[256]= +{ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +}; + +static unsigned char uctype_page9F[256]= +{ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 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, 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 +}; + +static unsigned char uctype_pageA4[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_pageA7[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 16, 16, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_pageA8[256]= +{ + 2, 2, 18, 2, 2, 2, 18, 2, 2, 2, 2, 18, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 18, 18, 18, 18, 18, 16, 16, 16, 16, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 16, 16, 16, 16, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_pageD7[256]= +{ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 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, 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, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_pageD8[256]= +{ + 32, 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, 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, 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, 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, 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, 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 +}; + +static unsigned char uctype_pageDB[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, 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, 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, 32, + 32, 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, 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, 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, 32 +}; + +static unsigned char uctype_pageDC[256]= +{ + 32, 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, 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, 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, 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, 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, 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 +}; + +static unsigned char uctype_pageDF[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, 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, 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, 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, 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, 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, 32 +}; + +static unsigned char uctype_pageE0[256]= +{ + 32, 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, 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, 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, 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, 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, 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 +}; + +static unsigned char uctype_pageF8[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, 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, 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, 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, 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, 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, 32 +}; + +static unsigned char uctype_pageFA[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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 +}; + +static unsigned char uctype_pageFB[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 18, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 0, + 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 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, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static unsigned char uctype_pageFD[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 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, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 0, 0 +}; + +static unsigned char uctype_pageFE[256]= +{ + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 32 +}; + +static unsigned char uctype_pageFF[256]= +{ + 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, + 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16, + 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, + 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 32, 16, 16, 0, 0 +}; + +MY_UNI_CTYPE my_uni_ctype[256]={ + {0,uctype_page00}, + {0,uctype_page01}, + {0,uctype_page02}, + {0,uctype_page03}, + {0,uctype_page04}, + {0,uctype_page05}, + {0,uctype_page06}, + {0,uctype_page07}, + {0,NULL}, + {0,uctype_page09}, + {0,uctype_page0A}, + {0,uctype_page0B}, + {0,uctype_page0C}, + {0,uctype_page0D}, + {0,uctype_page0E}, + {0,uctype_page0F}, + {0,uctype_page10}, + {0,uctype_page11}, + {0,uctype_page12}, + {0,uctype_page13}, + {0,uctype_page14}, + {2,NULL}, + {0,uctype_page16}, + {0,uctype_page17}, + {0,uctype_page18}, + {0,uctype_page19}, + {0,uctype_page1A}, + {0,uctype_page1B}, + {0,NULL}, + {0,uctype_page1D}, + {0,uctype_page1E}, + {0,uctype_page1F}, + {0,uctype_page20}, + {0,uctype_page21}, + {16,NULL}, + {0,uctype_page23}, + {0,uctype_page24}, + {16,NULL}, + {0,uctype_page26}, + {0,uctype_page27}, + {16,NULL}, + {16,NULL}, + {16,NULL}, + {0,uctype_page2B}, + {0,uctype_page2C}, + {0,uctype_page2D}, + {0,uctype_page2E}, + {0,uctype_page2F}, + {0,uctype_page30}, + {0,uctype_page31}, + {0,uctype_page32}, + {16,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {0,uctype_page4D}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {0,uctype_page9F}, + {2,NULL}, + {2,NULL}, + {2,NULL}, + {2,NULL}, + {0,uctype_pageA4}, + {0,NULL}, + {0,NULL}, + {0,uctype_pageA7}, + {0,uctype_pageA8}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {0,uctype_pageD7}, + {0,uctype_pageD8}, + {0,NULL}, + {0,NULL}, + {0,uctype_pageDB}, + {0,uctype_pageDC}, + {0,NULL}, + {0,NULL}, + {0,uctype_pageDF}, + {0,uctype_pageE0}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,uctype_pageF8}, + {2,NULL}, + {0,uctype_pageFA}, + {0,uctype_pageFB}, + {2,NULL}, + {0,uctype_pageFD}, + {0,uctype_pageFE}, + {0,uctype_pageFF} +}; + + diff --git a/NetService/include/Mysql/my_vle.h b/NetService/include/Mysql/my_vle.h new file mode 100644 index 00000000..c09f8222 --- /dev/null +++ b/NetService/include/Mysql/my_vle.h @@ -0,0 +1,38 @@ +/* Copyright (C) 2005 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef VLE_H +#define VLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "my_global.h" + +/* + The size (in bytes) required to store the object ITEM, which can be + either an expression or a type (since sizeof() is used on the item). +*/ +#define my_vle_sizeof(ITEM) (((sizeof(ITEM) * CHAR_BIT) + 6) / 7) + +uchar *my_vle_encode(uchar *vle, size_t max, ulong value); +uchar const *my_vle_decode(ulong *value_ptr, uchar const *vle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/NetService/include/Mysql/my_xml.h b/NetService/include/Mysql/my_xml.h new file mode 100644 index 00000000..6a453ee9 --- /dev/null +++ b/NetService/include/Mysql/my_xml.h @@ -0,0 +1,89 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#ifndef _my_xml_h +#define _my_xml_h + +#ifdef __cplusplus +extern "C" { +#endif + + +#define MY_XML_OK 0 +#define MY_XML_ERROR 1 + +/* + A flag whether to use absolute tag names in call-back functions, + like "a", "a.b" and "a.b.c" (used in character set file parser), + or relative names like "a", "b" and "c". +*/ +#define MY_XML_FLAG_RELATIVE_NAMES 1 + +/* + A flag whether to skip normilization of text values before calling + call-back functions: i.e. skip leading/trailing spaces, + \r, \n, \t characters. +*/ +#define MY_XML_FLAG_SKIP_TEXT_NORMALIZATION 2 + +enum my_xml_node_type +{ + MY_XML_NODE_TAG, /* can have TAG, ATTR and TEXT children */ + MY_XML_NODE_ATTR, /* can have TEXT children */ + MY_XML_NODE_TEXT /* cannot have children */ +}; + +typedef struct xml_stack_st +{ + int flags; + enum my_xml_node_type current_node_type; + char errstr[128]; + char attr[128]; + char *attrend; + const char *beg; + const char *cur; + const char *end; + void *user_data; + int (*enter)(struct xml_stack_st *st,const char *val, size_t len); + int (*value)(struct xml_stack_st *st,const char *val, size_t len); + int (*leave_xml)(struct xml_stack_st *st,const char *val, size_t len); +} MY_XML_PARSER; + +void my_xml_parser_create(MY_XML_PARSER *st); +void my_xml_parser_free(MY_XML_PARSER *st); +int my_xml_parse(MY_XML_PARSER *st,const char *str, size_t len); + +void my_xml_set_value_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, + const char *, + size_t len)); +void my_xml_set_enter_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, + const char *, + size_t len)); +void my_xml_set_leave_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, + const char *, + size_t len)); +void my_xml_set_user_data(MY_XML_PARSER *st, void *); + +size_t my_xml_error_pos(MY_XML_PARSER *st); +uint my_xml_error_lineno(MY_XML_PARSER *st); + +const char *my_xml_error_string(MY_XML_PARSER *st); + +#ifdef __cplusplus +} +#endif + +#endif /* _my_xml_h */ diff --git a/NetService/include/Mysql/myisampack.h b/NetService/include/Mysql/myisampack.h new file mode 100644 index 00000000..34a085e4 --- /dev/null +++ b/NetService/include/Mysql/myisampack.h @@ -0,0 +1,238 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Storing of values in high byte first order. + + integer keys and file pointers are stored with high byte first to get + better compression +*/ + +/* these two are for uniformity */ +#define mi_sint1korr(A) ((int8)(*A)) +#define mi_uint1korr(A) ((uint8)(*A)) + +#define mi_sint2korr(A) ((int16) (((int16) (((const uchar*) (A))[1])) +\ + ((int16) ((int16) ((const char*) (A))[0]) << 8))) +#define mi_sint3korr(A) ((int32) (((((const uchar*) (A))[0]) & 128) ? \ + (((uint32) 255L << 24) | \ + (((uint32) ((const uchar*) (A))[0]) << 16) |\ + (((uint32) ((const uchar*) (A))[1]) << 8) | \ + ((uint32) ((const uchar*) (A))[2])) : \ + (((uint32) ((const uchar*) (A))[0]) << 16) |\ + (((uint32) ((const uchar*) (A))[1]) << 8) | \ + ((uint32) ((const uchar*) (A))[2]))) +#define mi_sint4korr(A) ((int32) (((int32) (((const uchar*) (A))[3])) +\ + ((int32) (((const uchar*) (A))[2]) << 8) +\ + ((int32) (((const uchar*) (A))[1]) << 16) +\ + ((int32) ((int16) ((const char*) (A))[0]) << 24))) +#define mi_sint8korr(A) ((longlong) mi_uint8korr(A)) +#define mi_uint2korr(A) ((uint16) (((uint16) (((const uchar*) (A))[1])) +\ + ((uint16) (((const uchar*) (A))[0]) << 8))) +#define mi_uint3korr(A) ((uint32) (((uint32) (((const uchar*) (A))[2])) +\ + (((uint32) (((const uchar*) (A))[1])) << 8) +\ + (((uint32) (((const uchar*) (A))[0])) << 16))) +#define mi_uint4korr(A) ((uint32) (((uint32) (((const uchar*) (A))[3])) +\ + (((uint32) (((const uchar*) (A))[2])) << 8) +\ + (((uint32) (((const uchar*) (A))[1])) << 16) +\ + (((uint32) (((const uchar*) (A))[0])) << 24))) +#define mi_uint5korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[4])) +\ + (((uint32) (((const uchar*) (A))[3])) << 8) +\ + (((uint32) (((const uchar*) (A))[2])) << 16) +\ + (((uint32) (((const uchar*) (A))[1])) << 24)) +\ + (((ulonglong) (((const uchar*) (A))[0])) << 32)) +#define mi_uint6korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[5])) +\ + (((uint32) (((const uchar*) (A))[4])) << 8) +\ + (((uint32) (((const uchar*) (A))[3])) << 16) +\ + (((uint32) (((const uchar*) (A))[2])) << 24)) +\ + (((ulonglong) (((uint32) (((const uchar*) (A))[1])) +\ + (((uint32) (((const uchar*) (A))[0]) << 8)))) <<\ + 32)) +#define mi_uint7korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[6])) +\ + (((uint32) (((const uchar*) (A))[5])) << 8) +\ + (((uint32) (((const uchar*) (A))[4])) << 16) +\ + (((uint32) (((const uchar*) (A))[3])) << 24)) +\ + (((ulonglong) (((uint32) (((const uchar*) (A))[2])) +\ + (((uint32) (((const uchar*) (A))[1])) << 8) +\ + (((uint32) (((const uchar*) (A))[0])) << 16))) <<\ + 32)) +#define mi_uint8korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[7])) +\ + (((uint32) (((const uchar*) (A))[6])) << 8) +\ + (((uint32) (((const uchar*) (A))[5])) << 16) +\ + (((uint32) (((const uchar*) (A))[4])) << 24)) +\ + (((ulonglong) (((uint32) (((const uchar*) (A))[3])) +\ + (((uint32) (((const uchar*) (A))[2])) << 8) +\ + (((uint32) (((const uchar*) (A))[1])) << 16) +\ + (((uint32) (((const uchar*) (A))[0])) << 24))) <<\ + 32)) + +/* This one is for uniformity */ +#define mi_int1store(T,A) *((uchar*)(T))= (uchar) (A) + +#define mi_int2store(T,A) { uint def_temp= (uint) (A) ;\ + ((uchar*) (T))[1]= (uchar) (def_temp);\ + ((uchar*) (T))[0]= (uchar) (def_temp >> 8); } +#define mi_int3store(T,A) { /*lint -save -e734 */\ + ulong def_temp= (ulong) (A);\ + ((uchar*) (T))[2]= (uchar) (def_temp);\ + ((uchar*) (T))[1]= (uchar) (def_temp >> 8);\ + ((uchar*) (T))[0]= (uchar) (def_temp >> 16);\ + /*lint -restore */} +#define mi_int4store(T,A) { ulong def_temp= (ulong) (A);\ + ((uchar*) (T))[3]= (uchar) (def_temp);\ + ((uchar*) (T))[2]= (uchar) (def_temp >> 8);\ + ((uchar*) (T))[1]= (uchar) (def_temp >> 16);\ + ((uchar*) (T))[0]= (uchar) (def_temp >> 24); } +#define mi_int5store(T,A) { ulong def_temp= (ulong) (A),\ + def_temp2= (ulong) ((A) >> 32);\ + ((uchar*) (T))[4]= (uchar) (def_temp);\ + ((uchar*) (T))[3]= (uchar) (def_temp >> 8);\ + ((uchar*) (T))[2]= (uchar) (def_temp >> 16);\ + ((uchar*) (T))[1]= (uchar) (def_temp >> 24);\ + ((uchar*) (T))[0]= (uchar) (def_temp2); } +#define mi_int6store(T,A) { ulong def_temp= (ulong) (A),\ + def_temp2= (ulong) ((A) >> 32);\ + ((uchar*) (T))[5]= (uchar) (def_temp);\ + ((uchar*) (T))[4]= (uchar) (def_temp >> 8);\ + ((uchar*) (T))[3]= (uchar) (def_temp >> 16);\ + ((uchar*) (T))[2]= (uchar) (def_temp >> 24);\ + ((uchar*) (T))[1]= (uchar) (def_temp2);\ + ((uchar*) (T))[0]= (uchar) (def_temp2 >> 8); } +#define mi_int7store(T,A) { ulong def_temp= (ulong) (A),\ + def_temp2= (ulong) ((A) >> 32);\ + ((uchar*) (T))[6]= (uchar) (def_temp);\ + ((uchar*) (T))[5]= (uchar) (def_temp >> 8);\ + ((uchar*) (T))[4]= (uchar) (def_temp >> 16);\ + ((uchar*) (T))[3]= (uchar) (def_temp >> 24);\ + ((uchar*) (T))[2]= (uchar) (def_temp2);\ + ((uchar*) (T))[1]= (uchar) (def_temp2 >> 8);\ + ((uchar*) (T))[0]= (uchar) (def_temp2 >> 16); } +#define mi_int8store(T,A) { ulong def_temp3= (ulong) (A),\ + def_temp4= (ulong) ((A) >> 32);\ + mi_int4store((uchar*) (T) + 0, def_temp4);\ + mi_int4store((uchar*) (T) + 4, def_temp3); } + +#ifdef WORDS_BIGENDIAN + +#define mi_float4store(T,A) { ((uchar*) (T))[0]= ((uchar*) &A)[0];\ + ((uchar*) (T))[1]= ((uchar*) &A)[1];\ + ((uchar*) (T))[2]= ((uchar*) &A)[2];\ + ((uchar*) (T))[3]= ((uchar*) &A)[3]; } + +#define mi_float4get(V,M) { float def_temp;\ + ((uchar*) &def_temp)[0]= ((const uchar*) (M))[0];\ + ((uchar*) &def_temp)[1]= ((const uchar*) (M))[1]; \ + ((uchar*) &def_temp)[2]= ((const uchar*) (M))[2];\ + ((uchar*) &def_temp)[3]= ((const uchar*) (M))[3];\ + (V)= def_temp; } + +#define mi_float8store(T,V) { ((uchar*) (T))[0]= ((const uchar*) &V)[0];\ + ((uchar*) (T))[1]= ((const uchar*) &V)[1];\ + ((uchar*) (T))[2]= ((const uchar*) &V)[2];\ + ((uchar*) (T))[3]= ((const uchar*) &V)[3];\ + ((uchar*) (T))[4]= ((const uchar*) &V)[4];\ + ((uchar*) (T))[5]= ((const uchar*) &V)[5];\ + ((uchar*) (T))[6]= ((const uchar*) &V)[6];\ + ((uchar*) (T))[7]= ((const uchar*) &V)[7]; } + +#define mi_float8get(V,M) { double def_temp;\ + ((uchar*) &def_temp)[0]= ((const uchar*) (M))[0];\ + ((uchar*) &def_temp)[1]= ((const uchar*) (M))[1];\ + ((uchar*) &def_temp)[2]= ((const uchar*) (M))[2];\ + ((uchar*) &def_temp)[3]= ((const uchar*) (M))[3];\ + ((uchar*) &def_temp)[4]= ((const uchar*) (M))[4];\ + ((uchar*) &def_temp)[5]= ((const uchar*) (M))[5];\ + ((uchar*) &def_temp)[6]= ((const uchar*) (M))[6];\ + ((uchar*) &def_temp)[7]= ((const uchar*) (M))[7]; \ + (V)= def_temp; } +#else + +#define mi_float4store(T,A) { ((uchar*) (T))[0]= ((const uchar*) &A)[3];\ + ((uchar*) (T))[1]= ((const uchar*) &A)[2];\ + ((uchar*) (T))[2]= ((const uchar*) &A)[1];\ + ((uchar*) (T))[3]= ((const uchar*) &A)[0]; } + +#define mi_float4get(V,M) { float def_temp;\ + ((uchar*) &def_temp)[0]= ((const uchar*) (M))[3];\ + ((uchar*) &def_temp)[1]= ((const uchar*) (M))[2];\ + ((uchar*) &def_temp)[2]= ((const uchar*) (M))[1];\ + ((uchar*) &def_temp)[3]= ((const uchar*) (M))[0];\ + (V)= def_temp; } + +#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) +#define mi_float8store(T,V) { ((uchar*) (T))[0]= ((const uchar*) &V)[3];\ + ((uchar*) (T))[1]= ((const uchar*) &V)[2];\ + ((uchar*) (T))[2]= ((const uchar*) &V)[1];\ + ((uchar*) (T))[3]= ((const uchar*) &V)[0];\ + ((uchar*) (T))[4]= ((const uchar*) &V)[7];\ + ((uchar*) (T))[5]= ((const uchar*) &V)[6];\ + ((uchar*) (T))[6]= ((const uchar*) &V)[5];\ + ((uchar*) (T))[7]= ((const uchar*) &V)[4];} + +#define mi_float8get(V,M) { double def_temp;\ + ((uchar*) &def_temp)[0]= ((const uchar*) (M))[3];\ + ((uchar*) &def_temp)[1]= ((const uchar*) (M))[2];\ + ((uchar*) &def_temp)[2]= ((const uchar*) (M))[1];\ + ((uchar*) &def_temp)[3]= ((const uchar*) (M))[0];\ + ((uchar*) &def_temp)[4]= ((const uchar*) (M))[7];\ + ((uchar*) &def_temp)[5]= ((const uchar*) (M))[6];\ + ((uchar*) &def_temp)[6]= ((const uchar*) (M))[5];\ + ((uchar*) &def_temp)[7]= ((const uchar*) (M))[4];\ + (V)= def_temp; } + +#else +#define mi_float8store(T,V) { ((uchar*) (T))[0]= ((const uchar*) &V)[7];\ + ((uchar*) (T))[1]= ((const uchar*) &V)[6];\ + ((uchar*) (T))[2]= ((const uchar*) &V)[5];\ + ((uchar*) (T))[3]= ((const uchar*) &V)[4];\ + ((uchar*) (T))[4]= ((const uchar*) &V)[3];\ + ((uchar*) (T))[5]= ((const uchar*) &V)[2];\ + ((uchar*) (T))[6]= ((const uchar*) &V)[1];\ + ((uchar*) (T))[7]= ((const uchar*) &V)[0];} + +#define mi_float8get(V,M) { double def_temp;\ + ((uchar*) &def_temp)[0]= ((const uchar*) (M))[7];\ + ((uchar*) &def_temp)[1]= ((const uchar*) (M))[6];\ + ((uchar*) &def_temp)[2]= ((const uchar*) (M))[5];\ + ((uchar*) &def_temp)[3]= ((const uchar*) (M))[4];\ + ((uchar*) &def_temp)[4]= ((const uchar*) (M))[3];\ + ((uchar*) &def_temp)[5]= ((const uchar*) (M))[2];\ + ((uchar*) &def_temp)[6]= ((const uchar*) (M))[1];\ + ((uchar*) &def_temp)[7]= ((const uchar*) (M))[0];\ + (V)= def_temp; } +#endif /* __FLOAT_WORD_ORDER */ +#endif /* WORDS_BIGENDIAN */ + +/* Fix to avoid warnings when sizeof(ha_rows) == sizeof(long) */ + +#ifdef BIG_TABLES +#define mi_rowstore(T,A) mi_int8store(T, A) +#define mi_rowkorr(T) mi_uint8korr(T) +#else +#define mi_rowstore(T,A) { mi_int4store(T, 0);\ + mi_int4store(((uchar*) (T) + 4), A); } +#define mi_rowkorr(T) mi_uint4korr((const uchar*) (T) + 4) +#endif + +#if SIZEOF_OFF_T > 4 +#define mi_sizestore(T,A) mi_int8store(T, A) +#define mi_sizekorr(T) mi_uint8korr(T) +#else +#define mi_sizestore(T,A) { if ((A) == HA_OFFSET_ERROR)\ + bfill((char*) (T), 8, 255);\ + else { mi_int4store((T), 0);\ + mi_int4store(((T) + 4), A); }} +#define mi_sizekorr(T) mi_uint4korr((const uchar*) (T) + 4) +#endif diff --git a/NetService/include/Mysql/mysql.h b/NetService/include/Mysql/mysql.h new file mode 100644 index 00000000..64467dce --- /dev/null +++ b/NetService/include/Mysql/mysql.h @@ -0,0 +1,756 @@ +/* Copyright (C) 2000-2003 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + This file defines the client API to MySQL and also the ABI of the + dynamically linked libmysqlclient. + + The ABI should never be changed in a released product of MySQL + thus you need to take great care when changing the file. In case + the file is changed so the ABI is broken, you must also + update the SHAREDLIB_MAJOR_VERSION in configure.in . + +*/ + +#ifndef _mysql_h +#define _mysql_h + +#ifdef _AIX /* large-file support will break without this */ +#include +#endif + +#ifdef __CYGWIN__ /* CYGWIN implements a UNIX API */ +#undef WIN +#undef _WIN +#undef _WIN32 +#undef _WIN64 +#undef __WIN__ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _global_h /* If not standard header */ +#include +#ifdef __LCC__ +#include /* For windows */ +#endif +typedef char my_bool; +#if (defined(_WIN32) || defined(_WIN64)) && !defined(__WIN__) +#define __WIN__ +#include +#endif +#if !defined(__WIN__) +#define STDCALL +#else +#define STDCALL __stdcall +#endif + +#ifndef my_socket_defined +#ifdef __WIN__ +#define my_socket SOCKET +#else +typedef int my_socket; +#endif /* __WIN__ */ +#endif /* my_socket_defined */ +#endif /* _global_h */ + +#include "mysql_version.h" +#include "mysql_com.h" +#include "mysql_time.h" + +#include "my_list.h" /* for LISTs used in 'MYSQL' and 'MYSQL_STMT' */ + +extern unsigned int mysql_port; +extern char *mysql_unix_port; + +#define CLIENT_NET_READ_TIMEOUT 365*24*3600 /* Timeout on read */ +#define CLIENT_NET_WRITE_TIMEOUT 365*24*3600 /* Timeout on write */ + +#ifdef __NETWARE__ +#pragma pack(push, 8) /* 8 byte alignment */ +#endif + +#define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG) +#define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG) +#define IS_BLOB(n) ((n) & BLOB_FLAG) +#define IS_NUM(t) ((t) <= MYSQL_TYPE_INT24 || (t) == MYSQL_TYPE_YEAR || (t) == MYSQL_TYPE_NEWDECIMAL) +#define IS_NUM_FIELD(f) ((f)->flags & NUM_FLAG) +#define INTERNAL_NUM_FIELD(f) (((f)->type <= MYSQL_TYPE_INT24 && ((f)->type != MYSQL_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == MYSQL_TYPE_YEAR) +#define IS_LONGDATA(t) ((t) >= MYSQL_TYPE_TINY_BLOB && (t) <= MYSQL_TYPE_STRING) + + +typedef struct st_mysql_field { + char *name; /* Name of column */ + char *org_name; /* Original column name, if an alias */ + char *table; /* Table of column if column was a field */ + char *org_table; /* Org table name, if table was an alias */ + char *db; /* Database for table */ + char *catalog; /* Catalog for table */ + char *def; /* Default value (set by mysql_list_fields) */ + unsigned long length; /* Width of column (create length) */ + unsigned long max_length; /* Max width for selected set */ + unsigned int name_length; + unsigned int org_name_length; + unsigned int table_length; + unsigned int org_table_length; + unsigned int db_length; + unsigned int catalog_length; + unsigned int def_length; + unsigned int flags; /* Div flags */ + unsigned int decimals; /* Number of decimals in field */ + unsigned int charsetnr; /* Character set */ + enum enum_field_types type; /* Type of field. See mysql_com.h for types */ + void *extension; +} MYSQL_FIELD; + +typedef char **MYSQL_ROW; /* return data as array of strings */ +typedef unsigned int MYSQL_FIELD_OFFSET; /* offset to current field */ + +#ifndef _global_h +#if defined(NO_CLIENT_LONG_LONG) +typedef unsigned long my_ulonglong; +#elif defined (__WIN__) +typedef unsigned __int64 my_ulonglong; +#else +typedef unsigned long long my_ulonglong; +#endif +#endif + +#include "typelib.h" + +#define MYSQL_COUNT_ERROR (~(my_ulonglong) 0) + +/* backward compatibility define - to be removed eventually */ +#define ER_WARN_DATA_TRUNCATED WARN_DATA_TRUNCATED + +typedef struct st_mysql_rows { + struct st_mysql_rows *next; /* list of rows */ + MYSQL_ROW data; + unsigned long length; +} MYSQL_ROWS; + +typedef MYSQL_ROWS *MYSQL_ROW_OFFSET; /* offset to current row */ + +#include "my_alloc.h" + +typedef struct embedded_query_result EMBEDDED_QUERY_RESULT; +typedef struct st_mysql_data { + MYSQL_ROWS *data; + struct embedded_query_result *embedded_info; + MEM_ROOT alloc; + my_ulonglong rows; + unsigned int fields; + /* extra info for embedded library */ + void *extension; +} MYSQL_DATA; + +enum mysql_option +{ + MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS, MYSQL_OPT_NAMED_PIPE, + MYSQL_INIT_COMMAND, MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP, + MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME, MYSQL_OPT_LOCAL_INFILE, + MYSQL_OPT_PROTOCOL, MYSQL_SHARED_MEMORY_BASE_NAME, MYSQL_OPT_READ_TIMEOUT, + MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT, + MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION, + MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, + MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT, + MYSQL_OPT_SSL_VERIFY_SERVER_CERT +}; + +struct st_mysql_options { + unsigned int connect_timeout, read_timeout, write_timeout; + unsigned int port, protocol; + unsigned long client_flag; + char *host,*user,*password,*unix_socket,*db; + struct st_dynamic_array *init_commands; + char *my_cnf_file,*my_cnf_group, *charset_dir, *charset_name; + char *ssl_key; /* PEM key file */ + char *ssl_cert; /* PEM cert file */ + char *ssl_ca; /* PEM CA file */ + char *ssl_capath; /* PEM directory of CA-s? */ + char *ssl_cipher; /* cipher to use */ + char *shared_memory_base_name; + unsigned long max_allowed_packet; + my_bool use_ssl; /* if to use SSL or not */ + my_bool compress,named_pipe; + my_bool unused1; + my_bool unused2; + my_bool unused3; + my_bool unused4; + enum mysql_option methods_to_use; + char *client_ip; + /* Refuse client connecting to server if it uses old (pre-4.1.1) protocol */ + my_bool secure_auth; + /* 0 - never report, 1 - always report (default) */ + my_bool report_data_truncation; + + /* function pointers for local infile support */ + int (*local_infile_init)(void **, const char *, void *); + int (*local_infile_read)(void *, char *, unsigned int); + void (*local_infile_end)(void *); + int (*local_infile_error)(void *, char *, unsigned int); + void *local_infile_userdata; + void *extension; +}; + +enum mysql_status +{ + MYSQL_STATUS_READY,MYSQL_STATUS_GET_RESULT,MYSQL_STATUS_USE_RESULT +}; + +enum mysql_protocol_type +{ + MYSQL_PROTOCOL_DEFAULT, MYSQL_PROTOCOL_TCP, MYSQL_PROTOCOL_SOCKET, + MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY +}; + +typedef struct character_set +{ + unsigned int number; /* character set number */ + unsigned int state; /* character set state */ + const char *csname; /* collation name */ + const char *name; /* character set name */ + const char *comment; /* comment */ + const char *dir; /* character set directory */ + unsigned int mbminlen; /* min. length for multibyte strings */ + unsigned int mbmaxlen; /* max. length for multibyte strings */ +} MY_CHARSET_INFO; + +struct st_mysql_methods; +struct st_mysql_stmt; + +typedef struct st_mysql +{ + NET net; /* Communication parameters */ + unsigned char *connector_fd; /* ConnectorFd for SSL */ + char *host,*user,*passwd,*unix_socket,*server_version,*host_info; + char *info, *db; + struct charset_info_st *charset; + MYSQL_FIELD *fields; + MEM_ROOT field_alloc; + my_ulonglong affected_rows; + my_ulonglong insert_id; /* id if insert on table with NEXTNR */ + my_ulonglong extra_info; /* Not used */ + unsigned long thread_id; /* Id for connection in server */ + unsigned long packet_length; + unsigned int port; + unsigned long client_flag,server_capabilities; + unsigned int protocol_version; + unsigned int field_count; + unsigned int server_status; + unsigned int server_language; + unsigned int warning_count; + struct st_mysql_options options; + enum mysql_status status; + my_bool free_me; /* If free in mysql_close */ + my_bool reconnect; /* set to 1 if automatic reconnect */ + + /* session-wide random string */ + char scramble[SCRAMBLE_LENGTH+1]; + my_bool unused1; + void *unused2, *unused3, *unused4, *unused5; + + LIST *stmts; /* list of all statements */ + const struct st_mysql_methods *methods; + void *thd; + /* + Points to boolean flag in MYSQL_RES or MYSQL_STMT. We set this flag + from mysql_stmt_close if close had to cancel result set of this object. + */ + my_bool *unbuffered_fetch_owner; + /* needed for embedded server - no net buffer to store the 'info' */ + char *info_buffer; + void *extension; +} MYSQL; + + +typedef struct st_mysql_res { + my_ulonglong row_count; + MYSQL_FIELD *fields; + MYSQL_DATA *data; + MYSQL_ROWS *data_cursor; + unsigned long *lengths; /* column lengths of current row */ + MYSQL *handle; /* for unbuffered reads */ + const struct st_mysql_methods *methods; + MYSQL_ROW row; /* If unbuffered read */ + MYSQL_ROW current_row; /* buffer to current row */ + MEM_ROOT field_alloc; + unsigned int field_count, current_field; + my_bool eof; /* Used by mysql_fetch_row */ + /* mysql_stmt_close() had to cancel this result */ + my_bool unbuffered_fetch_cancelled; + void *extension; +} MYSQL_RES; + + +#if !defined(MYSQL_SERVER) && !defined(MYSQL_CLIENT) +#define MYSQL_CLIENT +#endif + + +typedef struct st_mysql_parameters +{ + unsigned long *p_max_allowed_packet; + unsigned long *p_net_buffer_length; + void *extension; +} MYSQL_PARAMETERS; + +#if !defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY) +#define max_allowed_packet (*mysql_get_parameters()->p_max_allowed_packet) +#define net_buffer_length (*mysql_get_parameters()->p_net_buffer_length) +#endif + +/* + Set up and bring down the server; to ensure that applications will + work when linked against either the standard client library or the + embedded server library, these functions should be called. +*/ +int STDCALL mysql_server_init(int argc, char **argv, char **groups); +void STDCALL mysql_server_end(void); + +/* + mysql_server_init/end need to be called when using libmysqld or + libmysqlclient (exactly, mysql_server_init() is called by mysql_init() so + you don't need to call it explicitely; but you need to call + mysql_server_end() to free memory). The names are a bit misleading + (mysql_SERVER* to be used when using libmysqlCLIENT). So we add more general + names which suit well whether you're using libmysqld or libmysqlclient. We + intend to promote these aliases over the mysql_server* ones. +*/ +#define mysql_library_init mysql_server_init +#define mysql_library_end mysql_server_end + +MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void); + +/* + Set up and bring down a thread; these function should be called + for each thread in an application which opens at least one MySQL + connection. All uses of the connection(s) should be between these + function calls. +*/ +my_bool STDCALL mysql_thread_init(void); +void STDCALL mysql_thread_end(void); + +/* + Functions to get information from the MYSQL and MYSQL_RES structures + Should definitely be used if one uses shared libraries. +*/ + +my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res); +unsigned int STDCALL mysql_num_fields(MYSQL_RES *res); +my_bool STDCALL mysql_eof(MYSQL_RES *res); +MYSQL_FIELD *STDCALL mysql_fetch_field_direct(MYSQL_RES *res, + unsigned int fieldnr); +MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res); +MYSQL_ROW_OFFSET STDCALL mysql_row_tell(MYSQL_RES *res); +MYSQL_FIELD_OFFSET STDCALL mysql_field_tell(MYSQL_RES *res); + +unsigned int STDCALL mysql_field_count(MYSQL *mysql); +my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql); +my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql); +unsigned int STDCALL mysql_errno(MYSQL *mysql); +const char * STDCALL mysql_error(MYSQL *mysql); +const char *STDCALL mysql_sqlstate(MYSQL *mysql); +unsigned int STDCALL mysql_warning_count(MYSQL *mysql); +const char * STDCALL mysql_info(MYSQL *mysql); +unsigned long STDCALL mysql_thread_id(MYSQL *mysql); +const char * STDCALL mysql_character_set_name(MYSQL *mysql); +int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname); + +MYSQL * STDCALL mysql_init(MYSQL *mysql); +my_bool STDCALL mysql_ssl_set(MYSQL *mysql, const char *key, + const char *cert, const char *ca, + const char *capath, const char *cipher); +const char * STDCALL mysql_get_ssl_cipher(MYSQL *mysql); +my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, + const char *passwd, const char *db); +MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host, + const char *user, + const char *passwd, + const char *db, + unsigned int port, + const char *unix_socket, + unsigned long clientflag); +int STDCALL mysql_select_db(MYSQL *mysql, const char *db); +int STDCALL mysql_query(MYSQL *mysql, const char *q); +int STDCALL mysql_send_query(MYSQL *mysql, const char *q, + unsigned long length); +int STDCALL mysql_real_query(MYSQL *mysql, const char *q, + unsigned long length); +MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql); +MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql); + +void STDCALL mysql_get_character_set_info(MYSQL *mysql, + MY_CHARSET_INFO *charset); + +/* local infile support */ + +#define LOCAL_INFILE_ERROR_LEN 512 + +void +mysql_set_local_infile_handler(MYSQL *mysql, + int (*local_infile_init)(void **, const char *, + void *), + int (*local_infile_read)(void *, char *, + unsigned int), + void (*local_infile_end)(void *), + int (*local_infile_error)(void *, char*, + unsigned int), + void *); + +void +mysql_set_local_infile_default(MYSQL *mysql); + +int STDCALL mysql_shutdown(MYSQL *mysql, + enum mysql_enum_shutdown_level + shutdown_level); +int STDCALL mysql_dump_debug_info(MYSQL *mysql); +int STDCALL mysql_refresh(MYSQL *mysql, + unsigned int refresh_options); +int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid); +int STDCALL mysql_set_server_option(MYSQL *mysql, + enum enum_mysql_set_option + option); +int STDCALL mysql_ping(MYSQL *mysql); +const char * STDCALL mysql_stat(MYSQL *mysql); +const char * STDCALL mysql_get_server_info(MYSQL *mysql); +const char * STDCALL mysql_get_client_info(void); +unsigned long STDCALL mysql_get_client_version(void); +const char * STDCALL mysql_get_host_info(MYSQL *mysql); +unsigned long STDCALL mysql_get_server_version(MYSQL *mysql); +unsigned int STDCALL mysql_get_proto_info(MYSQL *mysql); +MYSQL_RES * STDCALL mysql_list_dbs(MYSQL *mysql,const char *wild); +MYSQL_RES * STDCALL mysql_list_tables(MYSQL *mysql,const char *wild); +MYSQL_RES * STDCALL mysql_list_processes(MYSQL *mysql); +int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option, + const void *arg); +void STDCALL mysql_free_result(MYSQL_RES *result); +void STDCALL mysql_data_seek(MYSQL_RES *result, + my_ulonglong offset); +MYSQL_ROW_OFFSET STDCALL mysql_row_seek(MYSQL_RES *result, + MYSQL_ROW_OFFSET offset); +MYSQL_FIELD_OFFSET STDCALL mysql_field_seek(MYSQL_RES *result, + MYSQL_FIELD_OFFSET offset); +MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result); +unsigned long * STDCALL mysql_fetch_lengths(MYSQL_RES *result); +MYSQL_FIELD * STDCALL mysql_fetch_field(MYSQL_RES *result); +MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table, + const char *wild); +unsigned long STDCALL mysql_escape_string(char *to,const char *from, + unsigned long from_length); +unsigned long STDCALL mysql_hex_string(char *to,const char *from, + unsigned long from_length); +unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, + char *to,const char *from, + unsigned long length); +void STDCALL mysql_debug(const char *debug); +void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name); +unsigned int STDCALL mysql_thread_safe(void); +my_bool STDCALL mysql_embedded(void); +my_bool STDCALL mysql_read_query_result(MYSQL *mysql); + + +/* + The following definitions are added for the enhanced + client-server protocol +*/ + +/* statement state */ +enum enum_mysql_stmt_state +{ + MYSQL_STMT_INIT_DONE= 1, MYSQL_STMT_PREPARE_DONE, MYSQL_STMT_EXECUTE_DONE, + MYSQL_STMT_FETCH_DONE +}; + + +/* + This structure is used to define bind information, and + internally by the client library. + Public members with their descriptions are listed below + (conventionally `On input' refers to the binds given to + mysql_stmt_bind_param, `On output' refers to the binds given + to mysql_stmt_bind_result): + + buffer_type - One of the MYSQL_* types, used to describe + the host language type of buffer. + On output: if column type is different from + buffer_type, column value is automatically converted + to buffer_type before it is stored in the buffer. + buffer - On input: points to the buffer with input data. + On output: points to the buffer capable to store + output data. + The type of memory pointed by buffer must correspond + to buffer_type. See the correspondence table in + the comment to mysql_stmt_bind_param. + + The two above members are mandatory for any kind of bind. + + buffer_length - the length of the buffer. You don't have to set + it for any fixed length buffer: float, double, + int, etc. It must be set however for variable-length + types, such as BLOBs or STRINGs. + + length - On input: in case when lengths of input values + are different for each execute, you can set this to + point at a variable containining value length. This + way the value length can be different in each execute. + If length is not NULL, buffer_length is not used. + Note, length can even point at buffer_length if + you keep bind structures around while fetching: + this way you can change buffer_length before + each execution, everything will work ok. + On output: if length is set, mysql_stmt_fetch will + write column length into it. + + is_null - On input: points to a boolean variable that should + be set to TRUE for NULL values. + This member is useful only if your data may be + NULL in some but not all cases. + If your data is never NULL, is_null should be set to 0. + If your data is always NULL, set buffer_type + to MYSQL_TYPE_NULL, and is_null will not be used. + + is_unsigned - On input: used to signify that values provided for one + of numeric types are unsigned. + On output describes signedness of the output buffer. + If, taking into account is_unsigned flag, column data + is out of range of the output buffer, data for this column + is regarded truncated. Note that this has no correspondence + to the sign of result set column, if you need to find it out + use mysql_stmt_result_metadata. + error - where to write a truncation error if it is present. + possible error value is: + 0 no truncation + 1 value is out of range or buffer is too small + + Please note that MYSQL_BIND also has internals members. +*/ + +typedef struct st_mysql_bind +{ + unsigned long *length; /* output length pointer */ + my_bool *is_null; /* Pointer to null indicator */ + void *buffer; /* buffer to get/put data */ + /* set this if you want to track data truncations happened during fetch */ + my_bool *error; + unsigned char *row_ptr; /* for the current data position */ + void (*store_param_func)(NET *net, struct st_mysql_bind *param); + void (*fetch_result)(struct st_mysql_bind *, MYSQL_FIELD *, + unsigned char **row); + void (*skip_result)(struct st_mysql_bind *, MYSQL_FIELD *, + unsigned char **row); + /* output buffer length, must be set when fetching str/binary */ + unsigned long buffer_length; + unsigned long offset; /* offset position for char/binary fetch */ + unsigned long length_value; /* Used if length is 0 */ + unsigned int param_number; /* For null count and error messages */ + unsigned int pack_length; /* Internal length for packed data */ + enum enum_field_types buffer_type; /* buffer type */ + my_bool error_value; /* used if error is 0 */ + my_bool is_unsigned; /* set if integer type is unsigned */ + my_bool long_data_used; /* If used with mysql_send_long_data */ + my_bool is_null_value; /* Used if is_null is 0 */ + void *extension; +} MYSQL_BIND; + + +/* statement handler */ +typedef struct st_mysql_stmt +{ + MEM_ROOT mem_root; /* root allocations */ + LIST list; /* list to keep track of all stmts */ + MYSQL *mysql; /* connection handle */ + MYSQL_BIND *params; /* input parameters */ + MYSQL_BIND *bind; /* output parameters */ + MYSQL_FIELD *fields; /* result set metadata */ + MYSQL_DATA result; /* cached result set */ + MYSQL_ROWS *data_cursor; /* current row in cached result */ + /* + mysql_stmt_fetch() calls this function to fetch one row (it's different + for buffered, unbuffered and cursor fetch). + */ + int (*read_row_func)(struct st_mysql_stmt *stmt, + unsigned char **row); + /* copy of mysql->affected_rows after statement execution */ + my_ulonglong affected_rows; + my_ulonglong insert_id; /* copy of mysql->insert_id */ + unsigned long stmt_id; /* Id for prepared statement */ + unsigned long flags; /* i.e. type of cursor to open */ + unsigned long prefetch_rows; /* number of rows per one COM_FETCH */ + /* + Copied from mysql->server_status after execute/fetch to know + server-side cursor status for this statement. + */ + unsigned int server_status; + unsigned int last_errno; /* error code */ + unsigned int param_count; /* input parameter count */ + unsigned int field_count; /* number of columns in result set */ + enum enum_mysql_stmt_state state; /* statement state */ + char last_error[MYSQL_ERRMSG_SIZE]; /* error message */ + char sqlstate[SQLSTATE_LENGTH+1]; + /* Types of input parameters should be sent to server */ + my_bool send_types_to_server; + my_bool bind_param_done; /* input buffers were supplied */ + unsigned char bind_result_done; /* output buffers were supplied */ + /* mysql_stmt_close() had to cancel this result */ + my_bool unbuffered_fetch_cancelled; + /* + Is set to true if we need to calculate field->max_length for + metadata fields when doing mysql_stmt_store_result. + */ + my_bool update_max_length; + void *extension; +} MYSQL_STMT; + +enum enum_stmt_attr_type +{ + /* + When doing mysql_stmt_store_result calculate max_length attribute + of statement metadata. This is to be consistent with the old API, + where this was done automatically. + In the new API we do that only by request because it slows down + mysql_stmt_store_result sufficiently. + */ + STMT_ATTR_UPDATE_MAX_LENGTH, + /* + unsigned long with combination of cursor flags (read only, for update, + etc) + */ + STMT_ATTR_CURSOR_TYPE, + /* + Amount of rows to retrieve from server per one fetch if using cursors. + Accepts unsigned long attribute in the range 1 - ulong_max + */ + STMT_ATTR_PREFETCH_ROWS +}; + + +typedef struct st_mysql_methods +{ + my_bool (*read_query_result)(MYSQL *mysql); + my_bool (*advanced_command)(MYSQL *mysql, + enum enum_server_command command, + const unsigned char *header, + unsigned long header_length, + const unsigned char *arg, + unsigned long arg_length, + my_bool skip_check, + MYSQL_STMT *stmt); + MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields, + unsigned int fields); + MYSQL_RES * (*use_result)(MYSQL *mysql); + void (*fetch_lengths)(unsigned long *to, + MYSQL_ROW column, unsigned int field_count); + void (*flush_use_result)(MYSQL *mysql, my_bool flush_all_results); +#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) + MYSQL_FIELD * (*list_fields)(MYSQL *mysql); + my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt); + int (*stmt_execute)(MYSQL_STMT *stmt); + int (*read_binary_rows)(MYSQL_STMT *stmt); + int (*unbuffered_fetch)(MYSQL *mysql, char **row); + void (*free_embedded_thd)(MYSQL *mysql); + const char *(*read_statistics)(MYSQL *mysql); + my_bool (*next_result)(MYSQL *mysql); + int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd); + int (*read_rows_from_cursor)(MYSQL_STMT *stmt); +#endif +} MYSQL_METHODS; + + +MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql); +int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, + unsigned long length); +int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt); +int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt); +int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg, + unsigned int column, + unsigned long offset); +int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt); +unsigned long STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt); +my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, + enum enum_stmt_attr_type attr_type, + const void *attr); +my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, + enum enum_stmt_attr_type attr_type, + void *attr); +my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd); +my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); +my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt); +my_bool STDCALL mysql_stmt_reset(MYSQL_STMT * stmt); +my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt); +my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, + unsigned int param_number, + const char *data, + unsigned long length); +MYSQL_RES *STDCALL mysql_stmt_result_metadata(MYSQL_STMT *stmt); +MYSQL_RES *STDCALL mysql_stmt_param_metadata(MYSQL_STMT *stmt); +unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt); +const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt); +const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt); +MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_seek(MYSQL_STMT *stmt, + MYSQL_ROW_OFFSET offset); +MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_tell(MYSQL_STMT *stmt); +void STDCALL mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong offset); +my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt); +my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt); +my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt); +unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt); + +my_bool STDCALL mysql_commit(MYSQL * mysql); +my_bool STDCALL mysql_rollback(MYSQL * mysql); +my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode); +my_bool STDCALL mysql_more_results(MYSQL *mysql); +int STDCALL mysql_next_result(MYSQL *mysql); +int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt); +void STDCALL mysql_close(MYSQL *sock); + + +/* status return codes */ +#define MYSQL_NO_DATA 100 +#define MYSQL_DATA_TRUNCATED 101 + +#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT) + +#ifdef USE_OLD_FUNCTIONS +MYSQL * STDCALL mysql_connect(MYSQL *mysql, const char *host, + const char *user, const char *passwd); +int STDCALL mysql_create_db(MYSQL *mysql, const char *DB); +int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB); +#endif +#define HAVE_MYSQL_REAL_CONNECT + +/* + The following functions are mainly exported because of mysqlbinlog; + They are not for general usage +*/ + +#define simple_command(mysql, command, arg, length, skip_check) \ + (*(mysql)->methods->advanced_command)(mysql, command, 0, \ + 0, arg, length, skip_check, NULL) +#define stmt_command(mysql, command, arg, length, stmt) \ + (*(mysql)->methods->advanced_command)(mysql, command, 0, \ + 0, arg, length, 1, stmt) + +#ifdef __NETWARE__ +#pragma pack(pop) /* restore alignment */ +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _mysql_h */ diff --git a/NetService/include/Mysql/mysql_com.h b/NetService/include/Mysql/mysql_com.h new file mode 100644 index 00000000..8b16fd26 --- /dev/null +++ b/NetService/include/Mysql/mysql_com.h @@ -0,0 +1,543 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* +** Common definition between mysql server & client +*/ + +#ifndef _mysql_com_h +#define _mysql_com_h + +#define HOSTNAME_LENGTH 60 +#define SYSTEM_CHARSET_MBMAXLEN 4 +#define NAME_CHAR_LEN 64 /* Field/table name length */ +#define USERNAME_CHAR_LENGTH 16 +#define NAME_LEN (NAME_CHAR_LEN*SYSTEM_CHARSET_MBMAXLEN) +#define USERNAME_LENGTH (USERNAME_CHAR_LENGTH*SYSTEM_CHARSET_MBMAXLEN) + +#define SERVER_VERSION_LENGTH 60 +#define SQLSTATE_LENGTH 5 + +/* + Maximum length of comments +*/ +#define TABLE_COMMENT_INLINE_MAXLEN 180 /* pre 6.0: 60 (3-byte) characters */ +#define TABLE_COMMENT_MAXLEN 2048 +#define COLUMN_COMMENT_MAXLEN 1024 +#define INDEX_COMMENT_MAXLEN 1024 + + +/* + USER_HOST_BUFF_SIZE -- length of string buffer, that is enough to contain + username and hostname parts of the user identifier with trailing zero in + MySQL standard format: + user_name_part@host_name_part\0 +*/ +#define USER_HOST_BUFF_SIZE HOSTNAME_LENGTH + USERNAME_LENGTH + 2 + +#define LOCAL_HOST "localhost" +#define LOCAL_HOST_NAMEDPIPE "." + + +#if defined(__WIN__) && !defined( _CUSTOMCONFIG_) +#define MYSQL_NAMEDPIPE "MySQL" +#define MYSQL_SERVICENAME "MySQL" +#endif /* __WIN__ */ + +/* + You should add new commands to the end of this list, otherwise old + servers won't be able to handle them as 'unsupported'. +*/ + +enum enum_server_command +{ + COM_SLEEP, COM_QUIT, COM_INIT_DB, COM_QUERY, COM_FIELD_LIST, + COM_CREATE_DB, COM_DROP_DB, COM_REFRESH, COM_SHUTDOWN, COM_STATISTICS, + COM_PROCESS_INFO, COM_CONNECT, COM_PROCESS_KILL, COM_DEBUG, COM_PING, + COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP, + COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE, + COM_STMT_PREPARE, COM_STMT_EXECUTE, COM_STMT_SEND_LONG_DATA, COM_STMT_CLOSE, + COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH, COM_DAEMON, + /* don't forget to update const char *command_name[] in sql_parse.cc */ + + /* Must be last */ + COM_END +}; + + +/* + Length of random string sent by server on handshake; this is also length of + obfuscated password, recieved from client +*/ +#define SCRAMBLE_LENGTH 20 +#define SCRAMBLE_LENGTH_323 8 +/* length of password stored in the db: new passwords are preceeded with '*' */ +#define SCRAMBLED_PASSWORD_CHAR_LENGTH (SCRAMBLE_LENGTH*2+1) +#define SCRAMBLED_PASSWORD_CHAR_LENGTH_323 (SCRAMBLE_LENGTH_323*2) + + +#define NOT_NULL_FLAG 1 /* Field can't be NULL */ +#define PRI_KEY_FLAG 2 /* Field is part of a primary key */ +#define UNIQUE_KEY_FLAG 4 /* Field is part of a unique key */ +#define MULTIPLE_KEY_FLAG 8 /* Field is part of a key */ +#define BLOB_FLAG 16 /* Field is a blob */ +#define UNSIGNED_FLAG 32 /* Field is unsigned */ +#define ZEROFILL_FLAG 64 /* Field is zerofill */ +#define BINARY_FLAG 128 /* Field is binary */ + +/* The following are only sent to new clients */ +#define ENUM_FLAG 256 /* field is an enum */ +#define AUTO_INCREMENT_FLAG 512 /* field is a autoincrement field */ +#define TIMESTAMP_FLAG 1024 /* Field is a timestamp */ +#define SET_FLAG 2048 /* field is a set */ +#define NO_DEFAULT_VALUE_FLAG 4096 /* Field doesn't have default value */ +#define ON_UPDATE_NOW_FLAG 8192 /* Field is set to NOW on UPDATE */ +#define NUM_FLAG 32768 /* Field is num (for clients) */ +#define PART_KEY_FLAG 16384 /* Intern; Part of some key */ +#define GROUP_FLAG 32768 /* Intern: Group field */ +#define UNIQUE_FLAG 65536 /* Intern: Used by sql_yacc */ +#define BINCMP_FLAG 131072 /* Intern: Used by sql_yacc */ +#define GET_FIXED_FIELDS_FLAG (1 << 18) /* Used to get fields in item tree */ +#define FIELD_IN_PART_FUNC_FLAG (1 << 19)/* Field part of partition func */ +#define FIELD_IN_ADD_INDEX (1<< 20) /* Intern: Field used in ADD INDEX */ +#define FIELD_IS_RENAMED (1<< 21) /* Intern: Field is being renamed */ +#define FIELD_STORAGE_FLAGS 22 /* Storage type: bit 22, 23 and 24 */ +#define COLUMN_FORMAT_FLAGS 25 /* Column format: bit 25, 26 and 27 */ + +#define REFRESH_GRANT 1 /* Refresh grant tables */ +#define REFRESH_LOG 2 /* Start on new log file */ +#define REFRESH_TABLES 4 /* close all tables */ +#define REFRESH_HOSTS 8 /* Flush host cache */ +#define REFRESH_STATUS 16 /* Flush status variables */ +#define REFRESH_THREADS 32 /* Flush thread cache */ +#define REFRESH_SLAVE 64 /* Reset master info and restart slave + thread */ +#define REFRESH_MASTER 128 /* Remove all bin logs in the index + and truncate the index */ + +/* The following can't be set with mysql_refresh() */ +#define REFRESH_READ_LOCK 16384 /* Lock tables for read */ +#define REFRESH_FAST 32768 /* Intern flag */ + +/* RESET (remove all queries) from query cache */ +#define REFRESH_QUERY_CACHE 65536 +#define REFRESH_QUERY_CACHE_FREE 0x20000L /* pack query cache */ +#define REFRESH_DES_KEY_FILE 0x40000L +#define REFRESH_USER_RESOURCES 0x80000L +#define REFRESH_BACKUP_LOG 0x200000L + +#define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */ +#define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */ +#define CLIENT_LONG_FLAG 4 /* Get all column flags */ +#define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */ +#define CLIENT_NO_SCHEMA 16 /* Don't allow database.table.column */ +#define CLIENT_COMPRESS 32 /* Can use compression protocol */ +#define CLIENT_ODBC 64 /* Odbc client */ +#define CLIENT_LOCAL_FILES 128 /* Can use LOAD DATA LOCAL */ +#define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */ +#define CLIENT_PROTOCOL_41 512 /* New 4.1 protocol */ +#define CLIENT_INTERACTIVE 1024 /* This is an interactive client */ +#define CLIENT_SSL 2048 /* Switch to SSL after handshake */ +#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */ +#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */ +#define CLIENT_RESERVED 16384 /* Old flag for 4.1 protocol */ +#define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */ +#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */ +#define CLIENT_MULTI_RESULTS (1UL << 17) /* Enable/disable multi-results */ +#define CLIENT_PS_MULTI_RESULTS (1UL << 18) /* Multi-results in PS-protocol */ + +#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30) +#define CLIENT_REMEMBER_OPTIONS (1UL << 31) + +/* Gather all possible capabilites (flags) supported by the server */ +#define CLIENT_ALL_FLAGS (CLIENT_LONG_PASSWORD | \ + CLIENT_FOUND_ROWS | \ + CLIENT_LONG_FLAG | \ + CLIENT_CONNECT_WITH_DB | \ + CLIENT_NO_SCHEMA | \ + CLIENT_COMPRESS | \ + CLIENT_ODBC | \ + CLIENT_LOCAL_FILES | \ + CLIENT_IGNORE_SPACE | \ + CLIENT_PROTOCOL_41 | \ + CLIENT_INTERACTIVE | \ + CLIENT_SSL | \ + CLIENT_IGNORE_SIGPIPE | \ + CLIENT_TRANSACTIONS | \ + CLIENT_RESERVED | \ + CLIENT_SECURE_CONNECTION | \ + CLIENT_MULTI_STATEMENTS | \ + CLIENT_MULTI_RESULTS | \ + CLIENT_PS_MULTI_RESULTS | \ + CLIENT_SSL_VERIFY_SERVER_CERT | \ + CLIENT_REMEMBER_OPTIONS) + +/* + Switch off the flags that are optional and depending on build flags + If any of the optional flags is supported by the build it will be switched + on before sending to the client during the connection handshake. +*/ +#define CLIENT_BASIC_FLAGS (((CLIENT_ALL_FLAGS & ~CLIENT_SSL) \ + & ~CLIENT_COMPRESS) \ + & ~CLIENT_SSL_VERIFY_SERVER_CERT) + +#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */ +#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */ +#define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */ +#define SERVER_QUERY_NO_GOOD_INDEX_USED 16 +#define SERVER_QUERY_NO_INDEX_USED 32 +/** + The server was able to fulfill the clients request and opened a + read-only non-scrollable cursor for a query. This flag comes + in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands. +*/ +#define SERVER_STATUS_CURSOR_EXISTS 64 +/** + This flag is sent when a read-only cursor is exhausted, in reply to + COM_STMT_FETCH command. +*/ +#define SERVER_STATUS_LAST_ROW_SENT 128 +#define SERVER_STATUS_DB_DROPPED 256 /* A database was dropped */ +#define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512 +/** + Sent to the client if after a prepared statement reprepare + we discovered that the new statement returns a different + number of result set columns. +*/ +#define SERVER_STATUS_METADATA_CHANGED 1024 +/* + Tell clients that this query was logged to the slow query log. + Not yet set in the server, but interface is defined for applications + to use. See WorkLog 4098. +*/ +#define SERVER_QUERY_WAS_SLOW 2048 + +/** + To mark ResultSet containing output parameter values. +*/ +#define SERVER_PS_OUT_PARAMS 4096 + +/** + Server status flags that must be cleared when starting + execution of a new SQL statement. + Flags from this set are only added to the + current server status by the execution engine, but + never removed -- the execution engine expects them + to disappear automagically by the next command. +*/ +#define SERVER_STATUS_CLEAR_SET (SERVER_QUERY_NO_GOOD_INDEX_USED| \ + SERVER_QUERY_NO_INDEX_USED|\ + SERVER_MORE_RESULTS_EXISTS|\ + SERVER_STATUS_METADATA_CHANGED) + +#define MYSQL_ERRMSG_SIZE 512 +#define NET_READ_TIMEOUT 30 /* Timeout on read */ +#define NET_WRITE_TIMEOUT 60 /* Timeout on write */ +#define NET_WAIT_TIMEOUT 8*60*60 /* Wait for new query */ + +#define ONLY_KILL_QUERY 1 + + +struct st_vio; /* Only C */ +typedef struct st_vio Vio; + +#define MAX_TINYINT_WIDTH 3 /* Max width for a TINY w.o. sign */ +#define MAX_SMALLINT_WIDTH 5 /* Max width for a SHORT w.o. sign */ +#define MAX_MEDIUMINT_WIDTH 8 /* Max width for a INT24 w.o. sign */ +#define MAX_INT_WIDTH 10 /* Max width for a LONG w.o. sign */ +#define MAX_BIGINT_WIDTH 20 /* Max width for a LONGLONG */ +#define MAX_CHAR_WIDTH 255 /* Max length for a CHAR colum */ +#define MAX_BLOB_WIDTH 16777216 /* Default width for blob */ + +typedef struct st_net { +#if !defined(CHECK_EMBEDDED_DIFFERENCES) || !defined(EMBEDDED_LIBRARY) + Vio *vio; + unsigned char *buff,*buff_end,*write_pos,*read_pos; + my_socket fd; /* For Perl DBI/dbd */ + /* + The following variable is set if we are doing several queries in one + command ( as in LOAD TABLE ... FROM MASTER ), + and do not want to confuse the client with OK at the wrong time + */ + unsigned long remain_in_buf,length, buf_length, where_b; + unsigned long max_packet,max_packet_size; + unsigned int pkt_nr,compress_pkt_nr; + unsigned int write_timeout, read_timeout, retry_count; + int fcntl; + unsigned int *return_status; + unsigned char reading_or_writing; + char save_char; + my_bool unused1; /* Please remove with the next incompatible ABI change. */ + my_bool unused2; /* Please remove with the next incompatible ABI change */ + my_bool compress; + my_bool unused3; /* Please remove with the next incompatible ABI change. */ + /* + Pointer to query object in query cache, do not equal NULL (0) for + queries in cache that have not stored its results yet + */ +#endif + /* + Unused, please remove with the next incompatible ABI change. + */ + unsigned char *unused; + unsigned int last_errno; + unsigned char error; + my_bool unused4; /* Please remove with the next incompatible ABI change. */ + my_bool unused5; /* Please remove with the next incompatible ABI change. */ + /** Client library error message buffer. Actually belongs to struct MYSQL. */ + char last_error[MYSQL_ERRMSG_SIZE]; + /** Client library sqlstate buffer. Set along with the error message. */ + char sqlstate[SQLSTATE_LENGTH+1]; + void *extension; +} NET; + + +#define packet_error (~(unsigned long) 0) + +enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, + MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG, + MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE, + MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP, + MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24, + MYSQL_TYPE_DATE, MYSQL_TYPE_TIME, + MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR, + MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR, + MYSQL_TYPE_BIT, + MYSQL_TYPE_NEWDECIMAL=246, + MYSQL_TYPE_ENUM=247, + MYSQL_TYPE_SET=248, + MYSQL_TYPE_TINY_BLOB=249, + MYSQL_TYPE_MEDIUM_BLOB=250, + MYSQL_TYPE_LONG_BLOB=251, + MYSQL_TYPE_BLOB=252, + MYSQL_TYPE_VAR_STRING=253, + MYSQL_TYPE_STRING=254, + MYSQL_TYPE_GEOMETRY=255, + MAX_NO_FIELD_TYPES /* Should always be last */ +}; + +/* For backward compatibility */ +#define CLIENT_MULTI_QUERIES CLIENT_MULTI_STATEMENTS +#define FIELD_TYPE_DECIMAL MYSQL_TYPE_DECIMAL +#define FIELD_TYPE_NEWDECIMAL MYSQL_TYPE_NEWDECIMAL +#define FIELD_TYPE_TINY MYSQL_TYPE_TINY +#define FIELD_TYPE_SHORT MYSQL_TYPE_SHORT +#define FIELD_TYPE_LONG MYSQL_TYPE_LONG +#define FIELD_TYPE_FLOAT MYSQL_TYPE_FLOAT +#define FIELD_TYPE_DOUBLE MYSQL_TYPE_DOUBLE +#define FIELD_TYPE_NULL MYSQL_TYPE_NULL +#define FIELD_TYPE_TIMESTAMP MYSQL_TYPE_TIMESTAMP +#define FIELD_TYPE_LONGLONG MYSQL_TYPE_LONGLONG +#define FIELD_TYPE_INT24 MYSQL_TYPE_INT24 +#define FIELD_TYPE_DATE MYSQL_TYPE_DATE +#define FIELD_TYPE_TIME MYSQL_TYPE_TIME +#define FIELD_TYPE_DATETIME MYSQL_TYPE_DATETIME +#define FIELD_TYPE_YEAR MYSQL_TYPE_YEAR +#define FIELD_TYPE_NEWDATE MYSQL_TYPE_NEWDATE +#define FIELD_TYPE_ENUM MYSQL_TYPE_ENUM +#define FIELD_TYPE_SET MYSQL_TYPE_SET +#define FIELD_TYPE_TINY_BLOB MYSQL_TYPE_TINY_BLOB +#define FIELD_TYPE_MEDIUM_BLOB MYSQL_TYPE_MEDIUM_BLOB +#define FIELD_TYPE_LONG_BLOB MYSQL_TYPE_LONG_BLOB +#define FIELD_TYPE_BLOB MYSQL_TYPE_BLOB +#define FIELD_TYPE_VAR_STRING MYSQL_TYPE_VAR_STRING +#define FIELD_TYPE_STRING MYSQL_TYPE_STRING +#define FIELD_TYPE_CHAR MYSQL_TYPE_TINY +#define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM +#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY +#define FIELD_TYPE_BIT MYSQL_TYPE_BIT + + +/* Shutdown/kill enums and constants */ + +/* Bits for THD::killable. */ +#define MYSQL_SHUTDOWN_KILLABLE_CONNECT (unsigned char)(1 << 0) +#define MYSQL_SHUTDOWN_KILLABLE_TRANS (unsigned char)(1 << 1) +#define MYSQL_SHUTDOWN_KILLABLE_LOCK_TABLE (unsigned char)(1 << 2) +#define MYSQL_SHUTDOWN_KILLABLE_UPDATE (unsigned char)(1 << 3) + +enum mysql_enum_shutdown_level { + /* + We want levels to be in growing order of hardness (because we use number + comparisons). Note that DEFAULT does not respect the growing property, but + it's ok. + */ + SHUTDOWN_DEFAULT = 0, + /* wait for existing connections to finish */ + SHUTDOWN_WAIT_CONNECTIONS= MYSQL_SHUTDOWN_KILLABLE_CONNECT, + /* wait for existing trans to finish */ + SHUTDOWN_WAIT_TRANSACTIONS= MYSQL_SHUTDOWN_KILLABLE_TRANS, + /* wait for existing updates to finish (=> no partial MyISAM update) */ + SHUTDOWN_WAIT_UPDATES= MYSQL_SHUTDOWN_KILLABLE_UPDATE, + /* flush InnoDB buffers and other storage engines' buffers*/ + SHUTDOWN_WAIT_ALL_BUFFERS= (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1), + /* don't flush InnoDB buffers, flush other storage engines' buffers*/ + SHUTDOWN_WAIT_CRITICAL_BUFFERS= (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1) + 1, + /* Now the 2 levels of the KILL command */ +#if MYSQL_VERSION_ID >= 50000 + KILL_QUERY= 254, +#endif + KILL_CONNECTION= 255 +}; + + +enum enum_cursor_type +{ + CURSOR_TYPE_NO_CURSOR= 0, + CURSOR_TYPE_READ_ONLY= 1, + CURSOR_TYPE_FOR_UPDATE= 2, + CURSOR_TYPE_SCROLLABLE= 4 +}; + + +/* options for mysql_set_option */ +enum enum_mysql_set_option +{ + MYSQL_OPTION_MULTI_STATEMENTS_ON, + MYSQL_OPTION_MULTI_STATEMENTS_OFF +}; + +#define net_new_transaction(net) ((net)->pkt_nr=0) + +#ifdef __cplusplus +extern "C" { +#endif + +my_bool my_net_init(NET *net, Vio* vio); +void my_net_local_init(NET *net); +void net_end(NET *net); + void net_clear(NET *net, my_bool clear_buffer); +my_bool net_realloc(NET *net, size_t length); +my_bool net_flush(NET *net); +my_bool my_net_write(NET *net,const unsigned char *packet, size_t len); +my_bool net_write_command(NET *net,unsigned char command, + const unsigned char *header, size_t head_len, + const unsigned char *packet, size_t len); +int net_real_write(NET *net,const unsigned char *packet, size_t len); +unsigned long my_net_read(NET *net); + +#ifdef _global_h +void my_net_set_write_timeout(NET *net, uint timeout); +void my_net_set_read_timeout(NET *net, uint timeout); +#endif + +struct sockaddr; +int my_connect(my_socket s, const struct sockaddr *name, unsigned int namelen, + unsigned int timeout); +struct my_rnd_struct; + +#ifdef __cplusplus +} +#endif + + /* The following is for user defined functions */ + +enum Item_result +{ + STRING_RESULT=0, REAL_RESULT, INT_RESULT, ROW_RESULT, DECIMAL_RESULT +#ifdef MYSQL_SERVER + ,IMPOSSIBLE_RESULT /* Yes, we know this is ugly, don't tell us */ + ,MAX_NO_ITEM_RESULTS = IMPOSSIBLE_RESULT /* Should always be last */ +#endif +}; + +typedef struct st_udf_args +{ + unsigned int arg_count; /* Number of arguments */ + enum Item_result *arg_type; /* Pointer to item_results */ + char **args; /* Pointer to argument */ + unsigned long *lengths; /* Length of string arguments */ + char *maybe_null; /* Set to 1 for all maybe_null args */ + char **attributes; /* Pointer to attribute name */ + unsigned long *attribute_lengths; /* Length of attribute arguments */ + void *extension; +} UDF_ARGS; + + /* This holds information about the result */ + +typedef struct st_udf_init +{ + my_bool maybe_null; /* 1 if function can return NULL */ + unsigned int decimals; /* for real functions */ + unsigned long max_length; /* For string functions */ + char *ptr; /* free pointer for function data */ + my_bool const_item; /* 1 if function always returns the same value */ + void *extension; +} UDF_INIT; +/* + TODO: add a notion for determinism of the UDF. + See Item_udf_func::update_used_tables () +*/ + + /* Constants when using compression */ +#define NET_HEADER_SIZE 4 /* standard header size */ +#define COMP_HEADER_SIZE 3 /* compression header extra size */ + + /* Prototypes to password functions */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + These functions are used for authentication by client and server and + implemented in sql/password.c +*/ + +void create_random_string(char *to, unsigned int length, + struct my_rnd_struct *rand_st); + +void hash_password(unsigned long *to, const char *password, unsigned int password_len); +void make_scrambled_password_323(char *to, const char *password); +void scramble_323(char *to, const char *message, const char *password); +my_bool check_scramble_323(const char *, const char *message, + unsigned long *salt); +void get_salt_from_password_323(unsigned long *res, const char *password); +void make_password_from_salt_323(char *to, const unsigned long *salt); + +void make_scrambled_password(char *to, const char *password); +void scramble(char *to, const char *message, const char *password); +my_bool check_scramble(const char *reply, const char *message, + const unsigned char *hash_stage2); +void get_salt_from_password(unsigned char *res, const char *password); +void make_password_from_salt(char *to, const unsigned char *hash_stage2); +char *octet2hex(char *to, const char *str, unsigned int len); + +/* end of password.c */ + +char *get_tty_password(const char *opt_message); +const char *mysql_errno_to_sqlstate(unsigned int mysql_errno); + +/* Some other useful functions */ + +my_bool my_thread_init(void); +void my_thread_end(void); + +#ifdef _global_h +ulong STDCALL net_field_length(uchar **packet); +my_ulonglong net_field_length_ll(uchar **packet); +uchar *net_store_length(uchar *pkg, ulonglong length); +#endif + +#ifdef __cplusplus +} +#endif + +#define NULL_LENGTH ((unsigned long) ~0) /* For net_store_length */ +#define MYSQL_STMT_HEADER 4 +#define MYSQL_LONG_DATA_HEADER 6 + +#define NOT_FIXED_DEC 31 +#endif diff --git a/NetService/include/Mysql/mysql_time.h b/NetService/include/Mysql/mysql_time.h new file mode 100644 index 00000000..0a3f17a8 --- /dev/null +++ b/NetService/include/Mysql/mysql_time.h @@ -0,0 +1,55 @@ +/* Copyright (C) 2004 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _mysql_time_h_ +#define _mysql_time_h_ + +/* + Time declarations shared between the server and client API: + you should not add anything to this header unless it's used + (and hence should be visible) in mysql.h. + If you're looking for a place to add new time-related declaration, + it's most likely my_time.h. See also "C API Handling of Date + and Time Values" chapter in documentation. +*/ + +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; + + +/* + Structure which is used to represent datetime values inside MySQL. + + We assume that values in this structure are normalized, i.e. year <= 9999, + month <= 12, day <= 31, hour <= 23, hour <= 59, hour <= 59. Many functions + in server such as my_system_gmt_sec() or make_time() family of functions + rely on this (actually now usage of make_*() family relies on a bit weaker + restriction). Also functions that produce MYSQL_TIME as result ensure this. + There is one exception to this rule though if this structure holds time + value (time_type == MYSQL_TIMESTAMP_TIME) days and hour member can hold + bigger values. +*/ +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; + +#endif /* _mysql_time_h_ */ diff --git a/NetService/include/Mysql/mysql_version.h b/NetService/include/Mysql/mysql_version.h new file mode 100644 index 00000000..3f052b8d --- /dev/null +++ b/NetService/include/Mysql/mysql_version.h @@ -0,0 +1,26 @@ +/* Copyright Abandoned 1996, 1999, 2001 MySQL AB + This file is public domain and comes with NO WARRANTY of any kind */ + +/* Version numbers for protocol & mysqld */ + +#ifndef _mysql_version_h +#define _mysql_version_h + +#ifdef _CUSTOMCONFIG_ +# include +#else +# define PROTOCOL_VERSION 10 +# define MYSQL_SERVER_VERSION "6.0.0" +# define MYSQL_VERSION_ID 60000 +# define MYSQL_PORT 3306 +# define MYSQL_PORT_DEFAULT 0 +# define MYSQL_UNIX_ADDR "/tmp/mysql.sock" +# define MYSQL_CONFIG_NAME "my" +# define MYSQL_COMPILATION_COMMENT "Source distribution" +#endif /* _CUSTOMCONFIG_ */ + +#ifndef LICENSE +# define LICENSE GPL +#endif /* LICENSE */ + +#endif /* _mysql_version_h */ diff --git a/NetService/include/Mysql/mysqld_error.h b/NetService/include/Mysql/mysqld_error.h new file mode 100644 index 00000000..653e583e --- /dev/null +++ b/NetService/include/Mysql/mysqld_error.h @@ -0,0 +1,730 @@ +/* Autogenerated file, please don't edit */ + +#define ER_ERROR_FIRST 1000 +#define ER_HASHCHK 1000 +#define ER_NISAMCHK 1001 +#define ER_NO 1002 +#define ER_YES 1003 +#define ER_CANT_CREATE_FILE 1004 +#define ER_CANT_CREATE_TABLE 1005 +#define ER_CANT_CREATE_DB 1006 +#define ER_DB_CREATE_EXISTS 1007 +#define ER_DB_DROP_EXISTS 1008 +#define ER_DB_DROP_DELETE 1009 +#define ER_DB_DROP_RMDIR 1010 +#define ER_CANT_DELETE_FILE 1011 +#define ER_CANT_FIND_SYSTEM_REC 1012 +#define ER_CANT_GET_STAT 1013 +#define ER_CANT_GET_WD 1014 +#define ER_CANT_LOCK 1015 +#define ER_CANT_OPEN_FILE 1016 +#define ER_FILE_NOT_FOUND 1017 +#define ER_CANT_READ_DIR 1018 +#define ER_CANT_SET_WD 1019 +#define ER_CHECKREAD 1020 +#define ER_DISK_FULL 1021 +#define ER_DUP_KEY 1022 +#define ER_ERROR_ON_CLOSE 1023 +#define ER_ERROR_ON_READ 1024 +#define ER_ERROR_ON_RENAME 1025 +#define ER_ERROR_ON_WRITE 1026 +#define ER_FILE_USED 1027 +#define ER_FILSORT_ABORT 1028 +#define ER_FORM_NOT_FOUND 1029 +#define ER_GET_ERRNO 1030 +#define ER_ILLEGAL_HA 1031 +#define ER_KEY_NOT_FOUND 1032 +#define ER_NOT_FORM_FILE 1033 +#define ER_NOT_KEYFILE 1034 +#define ER_OLD_KEYFILE 1035 +#define ER_OPEN_AS_READONLY 1036 +#define ER_OUTOFMEMORY 1037 +#define ER_OUT_OF_SORTMEMORY 1038 +#define ER_UNEXPECTED_EOF 1039 +#define ER_CON_COUNT_ERROR 1040 +#define ER_OUT_OF_RESOURCES 1041 +#define ER_BAD_HOST_ERROR 1042 +#define ER_HANDSHAKE_ERROR 1043 +#define ER_DBACCESS_DENIED_ERROR 1044 +#define ER_ACCESS_DENIED_ERROR 1045 +#define ER_NO_DB_ERROR 1046 +#define ER_UNKNOWN_COM_ERROR 1047 +#define ER_BAD_NULL_ERROR 1048 +#define ER_BAD_DB_ERROR 1049 +#define ER_TABLE_EXISTS_ERROR 1050 +#define ER_BAD_TABLE_ERROR 1051 +#define ER_NON_UNIQ_ERROR 1052 +#define ER_SERVER_SHUTDOWN 1053 +#define ER_BAD_FIELD_ERROR 1054 +#define ER_WRONG_FIELD_WITH_GROUP 1055 +#define ER_WRONG_GROUP_FIELD 1056 +#define ER_WRONG_SUM_SELECT 1057 +#define ER_WRONG_VALUE_COUNT 1058 +#define ER_TOO_LONG_IDENT 1059 +#define ER_DUP_FIELDNAME 1060 +#define ER_DUP_KEYNAME 1061 +#define ER_DUP_ENTRY 1062 +#define ER_WRONG_FIELD_SPEC 1063 +#define ER_PARSE_ERROR 1064 +#define ER_EMPTY_QUERY 1065 +#define ER_NONUNIQ_TABLE 1066 +#define ER_INVALID_DEFAULT 1067 +#define ER_MULTIPLE_PRI_KEY 1068 +#define ER_TOO_MANY_KEYS 1069 +#define ER_TOO_MANY_KEY_PARTS 1070 +#define ER_TOO_LONG_KEY 1071 +#define ER_KEY_COLUMN_DOES_NOT_EXITS 1072 +#define ER_BLOB_USED_AS_KEY 1073 +#define ER_TOO_BIG_FIELDLENGTH 1074 +#define ER_WRONG_AUTO_KEY 1075 +#define ER_READY 1076 +#define ER_NORMAL_SHUTDOWN 1077 +#define ER_GOT_SIGNAL 1078 +#define ER_SHUTDOWN_COMPLETE 1079 +#define ER_FORCING_CLOSE 1080 +#define ER_IPSOCK_ERROR 1081 +#define ER_NO_SUCH_INDEX 1082 +#define ER_WRONG_FIELD_TERMINATORS 1083 +#define ER_BLOBS_AND_NO_TERMINATED 1084 +#define ER_TEXTFILE_NOT_READABLE 1085 +#define ER_FILE_EXISTS_ERROR 1086 +#define ER_LOAD_INFO 1087 +#define ER_ALTER_INFO 1088 +#define ER_WRONG_SUB_KEY 1089 +#define ER_CANT_REMOVE_ALL_FIELDS 1090 +#define ER_CANT_DROP_FIELD_OR_KEY 1091 +#define ER_INSERT_INFO 1092 +#define ER_UPDATE_TABLE_USED 1093 +#define ER_NO_SUCH_THREAD 1094 +#define ER_KILL_DENIED_ERROR 1095 +#define ER_NO_TABLES_USED 1096 +#define ER_TOO_BIG_SET 1097 +#define ER_NO_UNIQUE_LOGFILE 1098 +#define ER_TABLE_NOT_LOCKED_FOR_WRITE 1099 +#define ER_TABLE_NOT_LOCKED 1100 +#define ER_BLOB_CANT_HAVE_DEFAULT 1101 +#define ER_WRONG_DB_NAME 1102 +#define ER_WRONG_TABLE_NAME 1103 +#define ER_TOO_BIG_SELECT 1104 +#define ER_UNKNOWN_ERROR 1105 +#define ER_UNKNOWN_PROCEDURE 1106 +#define ER_WRONG_PARAMCOUNT_TO_PROCEDURE 1107 +#define ER_WRONG_PARAMETERS_TO_PROCEDURE 1108 +#define ER_UNKNOWN_TABLE 1109 +#define ER_FIELD_SPECIFIED_TWICE 1110 +#define ER_INVALID_GROUP_FUNC_USE 1111 +#define ER_UNSUPPORTED_EXTENSION 1112 +#define ER_TABLE_MUST_HAVE_COLUMNS 1113 +#define ER_RECORD_FILE_FULL 1114 +#define ER_UNKNOWN_CHARACTER_SET 1115 +#define ER_TOO_MANY_TABLES 1116 +#define ER_TOO_MANY_FIELDS 1117 +#define ER_TOO_BIG_ROWSIZE 1118 +#define ER_STACK_OVERRUN 1119 +#define ER_WRONG_OUTER_JOIN 1120 +#define ER_NULL_COLUMN_IN_INDEX 1121 +#define ER_CANT_FIND_UDF 1122 +#define ER_CANT_INITIALIZE_UDF 1123 +#define ER_UDF_NO_PATHS 1124 +#define ER_UDF_EXISTS 1125 +#define ER_CANT_OPEN_LIBRARY 1126 +#define ER_CANT_FIND_DL_ENTRY 1127 +#define ER_FUNCTION_NOT_DEFINED 1128 +#define ER_HOST_IS_BLOCKED 1129 +#define ER_HOST_NOT_PRIVILEGED 1130 +#define ER_PASSWORD_ANONYMOUS_USER 1131 +#define ER_PASSWORD_NOT_ALLOWED 1132 +#define ER_PASSWORD_NO_MATCH 1133 +#define ER_UPDATE_INFO 1134 +#define ER_CANT_CREATE_THREAD 1135 +#define ER_WRONG_VALUE_COUNT_ON_ROW 1136 +#define ER_CANT_REOPEN_TABLE 1137 +#define ER_INVALID_USE_OF_NULL 1138 +#define ER_REGEXP_ERROR 1139 +#define ER_MIX_OF_GROUP_FUNC_AND_FIELDS 1140 +#define ER_NONEXISTING_GRANT 1141 +#define ER_TABLEACCESS_DENIED_ERROR 1142 +#define ER_COLUMNACCESS_DENIED_ERROR 1143 +#define ER_ILLEGAL_GRANT_FOR_TABLE 1144 +#define ER_GRANT_WRONG_HOST_OR_USER 1145 +#define ER_NO_SUCH_TABLE 1146 +#define ER_NONEXISTING_TABLE_GRANT 1147 +#define ER_NOT_ALLOWED_COMMAND 1148 +#define ER_SYNTAX_ERROR 1149 +#define ER_DELAYED_CANT_CHANGE_LOCK 1150 +#define ER_TOO_MANY_DELAYED_THREADS 1151 +#define ER_ABORTING_CONNECTION 1152 +#define ER_NET_PACKET_TOO_LARGE 1153 +#define ER_NET_READ_ERROR_FROM_PIPE 1154 +#define ER_NET_FCNTL_ERROR 1155 +#define ER_NET_PACKETS_OUT_OF_ORDER 1156 +#define ER_NET_UNCOMPRESS_ERROR 1157 +#define ER_NET_READ_ERROR 1158 +#define ER_NET_READ_INTERRUPTED 1159 +#define ER_NET_ERROR_ON_WRITE 1160 +#define ER_NET_WRITE_INTERRUPTED 1161 +#define ER_TOO_LONG_STRING 1162 +#define ER_TABLE_CANT_HANDLE_BLOB 1163 +#define ER_TABLE_CANT_HANDLE_AUTO_INCREMENT 1164 +#define ER_DELAYED_INSERT_TABLE_LOCKED 1165 +#define ER_WRONG_COLUMN_NAME 1166 +#define ER_WRONG_KEY_COLUMN 1167 +#define ER_WRONG_MRG_TABLE 1168 +#define ER_DUP_UNIQUE 1169 +#define ER_BLOB_KEY_WITHOUT_LENGTH 1170 +#define ER_PRIMARY_CANT_HAVE_NULL 1171 +#define ER_TOO_MANY_ROWS 1172 +#define ER_REQUIRES_PRIMARY_KEY 1173 +#define ER_NO_RAID_COMPILED 1174 +#define ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE 1175 +#define ER_KEY_DOES_NOT_EXITS 1176 +#define ER_CHECK_NO_SUCH_TABLE 1177 +#define ER_CHECK_NOT_IMPLEMENTED 1178 +#define ER_CANT_DO_THIS_DURING_AN_TRANSACTION 1179 +#define ER_ERROR_DURING_COMMIT 1180 +#define ER_ERROR_DURING_ROLLBACK 1181 +#define ER_ERROR_DURING_FLUSH_LOGS 1182 +#define ER_ERROR_DURING_CHECKPOINT 1183 +#define ER_NEW_ABORTING_CONNECTION 1184 +#define ER_DUMP_NOT_IMPLEMENTED 1185 +#define ER_FLUSH_MASTER_BINLOG_CLOSED 1186 +#define ER_INDEX_REBUILD 1187 +#define ER_MASTER 1188 +#define ER_MASTER_NET_READ 1189 +#define ER_MASTER_NET_WRITE 1190 +#define ER_FT_MATCHING_KEY_NOT_FOUND 1191 +#define ER_LOCK_OR_ACTIVE_TRANSACTION 1192 +#define ER_UNKNOWN_SYSTEM_VARIABLE 1193 +#define ER_CRASHED_ON_USAGE 1194 +#define ER_CRASHED_ON_REPAIR 1195 +#define ER_WARNING_NOT_COMPLETE_ROLLBACK 1196 +#define ER_TRANS_CACHE_FULL 1197 +#define ER_SLAVE_MUST_STOP 1198 +#define ER_SLAVE_NOT_RUNNING 1199 +#define ER_BAD_SLAVE 1200 +#define ER_MASTER_INFO 1201 +#define ER_SLAVE_THREAD 1202 +#define ER_TOO_MANY_USER_CONNECTIONS 1203 +#define ER_SET_CONSTANTS_ONLY 1204 +#define ER_LOCK_WAIT_TIMEOUT 1205 +#define ER_LOCK_TABLE_FULL 1206 +#define ER_READ_ONLY_TRANSACTION 1207 +#define ER_DROP_DB_WITH_READ_LOCK 1208 +#define ER_CREATE_DB_WITH_READ_LOCK 1209 +#define ER_WRONG_ARGUMENTS 1210 +#define ER_NO_PERMISSION_TO_CREATE_USER 1211 +#define ER_UNION_TABLES_IN_DIFFERENT_DIR 1212 +#define ER_LOCK_DEADLOCK 1213 +#define ER_TABLE_CANT_HANDLE_FT 1214 +#define ER_CANNOT_ADD_FOREIGN 1215 +#define ER_NO_REFERENCED_ROW 1216 +#define ER_ROW_IS_REFERENCED 1217 +#define ER_CONNECT_TO_MASTER 1218 +#define ER_QUERY_ON_MASTER 1219 +#define ER_ERROR_WHEN_EXECUTING_COMMAND 1220 +#define ER_WRONG_USAGE 1221 +#define ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 1222 +#define ER_CANT_UPDATE_WITH_READLOCK 1223 +#define ER_MIXING_NOT_ALLOWED 1224 +#define ER_DUP_ARGUMENT 1225 +#define ER_USER_LIMIT_REACHED 1226 +#define ER_SPECIFIC_ACCESS_DENIED_ERROR 1227 +#define ER_LOCAL_VARIABLE 1228 +#define ER_GLOBAL_VARIABLE 1229 +#define ER_NO_DEFAULT 1230 +#define ER_WRONG_VALUE_FOR_VAR 1231 +#define ER_WRONG_TYPE_FOR_VAR 1232 +#define ER_VAR_CANT_BE_READ 1233 +#define ER_CANT_USE_OPTION_HERE 1234 +#define ER_NOT_SUPPORTED_YET 1235 +#define ER_MASTER_FATAL_ERROR_READING_BINLOG 1236 +#define ER_SLAVE_IGNORED_TABLE 1237 +#define ER_INCORRECT_GLOBAL_LOCAL_VAR 1238 +#define ER_WRONG_FK_DEF 1239 +#define ER_KEY_REF_DO_NOT_MATCH_TABLE_REF 1240 +#define ER_OPERAND_COLUMNS 1241 +#define ER_SUBQUERY_NO_1_ROW 1242 +#define ER_UNKNOWN_STMT_HANDLER 1243 +#define ER_CORRUPT_HELP_DB 1244 +#define ER_CYCLIC_REFERENCE 1245 +#define ER_AUTO_CONVERT 1246 +#define ER_ILLEGAL_REFERENCE 1247 +#define ER_DERIVED_MUST_HAVE_ALIAS 1248 +#define ER_SELECT_REDUCED 1249 +#define ER_TABLENAME_NOT_ALLOWED_HERE 1250 +#define ER_NOT_SUPPORTED_AUTH_MODE 1251 +#define ER_SPATIAL_CANT_HAVE_NULL 1252 +#define ER_COLLATION_CHARSET_MISMATCH 1253 +#define ER_SLAVE_WAS_RUNNING 1254 +#define ER_SLAVE_WAS_NOT_RUNNING 1255 +#define ER_TOO_BIG_FOR_UNCOMPRESS 1256 +#define ER_ZLIB_Z_MEM_ERROR 1257 +#define ER_ZLIB_Z_BUF_ERROR 1258 +#define ER_ZLIB_Z_DATA_ERROR 1259 +#define ER_CUT_VALUE_GROUP_CONCAT 1260 +#define ER_WARN_TOO_FEW_RECORDS 1261 +#define ER_WARN_TOO_MANY_RECORDS 1262 +#define ER_WARN_NULL_TO_NOTNULL 1263 +#define ER_WARN_DATA_OUT_OF_RANGE 1264 +#define WARN_DATA_TRUNCATED 1265 +#define ER_WARN_USING_OTHER_HANDLER 1266 +#define ER_CANT_AGGREGATE_2COLLATIONS 1267 +#define ER_DROP_USER 1268 +#define ER_REVOKE_GRANTS 1269 +#define ER_CANT_AGGREGATE_3COLLATIONS 1270 +#define ER_CANT_AGGREGATE_NCOLLATIONS 1271 +#define ER_VARIABLE_IS_NOT_STRUCT 1272 +#define ER_UNKNOWN_COLLATION 1273 +#define ER_SLAVE_IGNORED_SSL_PARAMS 1274 +#define ER_SERVER_IS_IN_SECURE_AUTH_MODE 1275 +#define ER_WARN_FIELD_RESOLVED 1276 +#define ER_BAD_SLAVE_UNTIL_COND 1277 +#define ER_MISSING_SKIP_SLAVE 1278 +#define ER_UNTIL_COND_IGNORED 1279 +#define ER_WRONG_NAME_FOR_INDEX 1280 +#define ER_WRONG_NAME_FOR_CATALOG 1281 +#define ER_WARN_QC_RESIZE 1282 +#define ER_BAD_FT_COLUMN 1283 +#define ER_UNKNOWN_KEY_CACHE 1284 +#define ER_WARN_HOSTNAME_WONT_WORK 1285 +#define ER_UNKNOWN_STORAGE_ENGINE 1286 +#define ER_WARN_DEPRECATED_SYNTAX 1287 +#define ER_NON_UPDATABLE_TABLE 1288 +#define ER_FEATURE_DISABLED 1289 +#define ER_OPTION_PREVENTS_STATEMENT 1290 +#define ER_DUPLICATED_VALUE_IN_TYPE 1291 +#define ER_TRUNCATED_WRONG_VALUE 1292 +#define ER_TOO_MUCH_AUTO_TIMESTAMP_COLS 1293 +#define ER_INVALID_ON_UPDATE 1294 +#define ER_UNSUPPORTED_PS 1295 +#define ER_GET_ERRMSG 1296 +#define ER_GET_TEMPORARY_ERRMSG 1297 +#define ER_UNKNOWN_TIME_ZONE 1298 +#define ER_WARN_INVALID_TIMESTAMP 1299 +#define ER_INVALID_CHARACTER_STRING 1300 +#define ER_WARN_ALLOWED_PACKET_OVERFLOWED 1301 +#define ER_CONFLICTING_DECLARATIONS 1302 +#define ER_SP_NO_RECURSIVE_CREATE 1303 +#define ER_SP_ALREADY_EXISTS 1304 +#define ER_SP_DOES_NOT_EXIST 1305 +#define ER_SP_DROP_FAILED 1306 +#define ER_SP_STORE_FAILED 1307 +#define ER_SP_LILABEL_MISMATCH 1308 +#define ER_SP_LABEL_REDEFINE 1309 +#define ER_SP_LABEL_MISMATCH 1310 +#define ER_SP_UNINIT_VAR 1311 +#define ER_SP_BADSELECT 1312 +#define ER_SP_BADRETURN 1313 +#define ER_SP_BADSTATEMENT 1314 +#define ER_UPDATE_LOG_DEPRECATED_IGNORED 1315 +#define ER_UPDATE_LOG_DEPRECATED_TRANSLATED 1316 +#define ER_QUERY_INTERRUPTED 1317 +#define ER_SP_WRONG_NO_OF_ARGS 1318 +#define ER_SP_COND_MISMATCH 1319 +#define ER_SP_NORETURN 1320 +#define ER_SP_NORETURNEND 1321 +#define ER_SP_BAD_CURSOR_QUERY 1322 +#define ER_SP_BAD_CURSOR_SELECT 1323 +#define ER_SP_CURSOR_MISMATCH 1324 +#define ER_SP_CURSOR_ALREADY_OPEN 1325 +#define ER_SP_CURSOR_NOT_OPEN 1326 +#define ER_SP_UNDECLARED_VAR 1327 +#define ER_SP_WRONG_NO_OF_FETCH_ARGS 1328 +#define ER_SP_FETCH_NO_DATA 1329 +#define ER_SP_DUP_PARAM 1330 +#define ER_SP_DUP_VAR 1331 +#define ER_SP_DUP_COND 1332 +#define ER_SP_DUP_CURS 1333 +#define ER_SP_CANT_ALTER 1334 +#define ER_SP_SUBSELECT_NYI 1335 +#define ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG 1336 +#define ER_SP_VARCOND_AFTER_CURSHNDLR 1337 +#define ER_SP_CURSOR_AFTER_HANDLER 1338 +#define ER_SP_CASE_NOT_FOUND 1339 +#define ER_FPARSER_TOO_BIG_FILE 1340 +#define ER_FPARSER_BAD_HEADER 1341 +#define ER_FPARSER_EOF_IN_COMMENT 1342 +#define ER_FPARSER_ERROR_IN_PARAMETER 1343 +#define ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER 1344 +#define ER_VIEW_NO_EXPLAIN 1345 +#define ER_FRM_UNKNOWN_TYPE 1346 +#define ER_WRONG_OBJECT 1347 +#define ER_NONUPDATEABLE_COLUMN 1348 +#define ER_VIEW_SELECT_DERIVED 1349 +#define ER_VIEW_SELECT_CLAUSE 1350 +#define ER_VIEW_SELECT_VARIABLE 1351 +#define ER_VIEW_SELECT_TMPTABLE 1352 +#define ER_VIEW_WRONG_LIST 1353 +#define ER_WARN_VIEW_MERGE 1354 +#define ER_WARN_VIEW_WITHOUT_KEY 1355 +#define ER_VIEW_INVALID 1356 +#define ER_SP_NO_DROP_SP 1357 +#define ER_SP_GOTO_IN_HNDLR 1358 +#define ER_TRG_ALREADY_EXISTS 1359 +#define ER_TRG_DOES_NOT_EXIST 1360 +#define ER_TRG_ON_VIEW_OR_TEMP_TABLE 1361 +#define ER_TRG_CANT_CHANGE_ROW 1362 +#define ER_TRG_NO_SUCH_ROW_IN_TRG 1363 +#define ER_NO_DEFAULT_FOR_FIELD 1364 +#define ER_DIVISION_BY_ZERO 1365 +#define ER_TRUNCATED_WRONG_VALUE_FOR_FIELD 1366 +#define ER_ILLEGAL_VALUE_FOR_TYPE 1367 +#define ER_VIEW_NONUPD_CHECK 1368 +#define ER_VIEW_CHECK_FAILED 1369 +#define ER_PROCACCESS_DENIED_ERROR 1370 +#define ER_RELAY_LOG_FAIL 1371 +#define ER_PASSWD_LENGTH 1372 +#define ER_UNKNOWN_TARGET_BINLOG 1373 +#define ER_IO_ERR_LOG_INDEX_READ 1374 +#define ER_BINLOG_PURGE_PROHIBITED 1375 +#define ER_FSEEK_FAIL 1376 +#define ER_BINLOG_PURGE_FATAL_ERR 1377 +#define ER_LOG_IN_USE 1378 +#define ER_LOG_PURGE_UNKNOWN_ERR 1379 +#define ER_RELAY_LOG_INIT 1380 +#define ER_NO_BINARY_LOGGING 1381 +#define ER_RESERVED_SYNTAX 1382 +#define ER_WSAS_FAILED 1383 +#define ER_DIFF_GROUPS_PROC 1384 +#define ER_NO_GROUP_FOR_PROC 1385 +#define ER_ORDER_WITH_PROC 1386 +#define ER_LOGGING_PROHIBIT_CHANGING_OF 1387 +#define ER_NO_FILE_MAPPING 1388 +#define ER_WRONG_MAGIC 1389 +#define ER_PS_MANY_PARAM 1390 +#define ER_KEY_PART_0 1391 +#define ER_VIEW_CHECKSUM 1392 +#define ER_VIEW_MULTIUPDATE 1393 +#define ER_VIEW_NO_INSERT_FIELD_LIST 1394 +#define ER_VIEW_DELETE_MERGE_VIEW 1395 +#define ER_CANNOT_USER 1396 +#define ER_XAER_NOTA 1397 +#define ER_XAER_INVAL 1398 +#define ER_XAER_RMFAIL 1399 +#define ER_XAER_OUTSIDE 1400 +#define ER_XAER_RMERR 1401 +#define ER_XA_RBROLLBACK 1402 +#define ER_NONEXISTING_PROC_GRANT 1403 +#define ER_PROC_AUTO_GRANT_FAIL 1404 +#define ER_PROC_AUTO_REVOKE_FAIL 1405 +#define ER_DATA_TOO_LONG 1406 +#define ER_SP_BAD_SQLSTATE 1407 +#define ER_STARTUP 1408 +#define ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR 1409 +#define ER_CANT_CREATE_USER_WITH_GRANT 1410 +#define ER_WRONG_VALUE_FOR_TYPE 1411 +#define ER_TABLE_DEF_CHANGED 1412 +#define ER_SP_DUP_HANDLER 1413 +#define ER_SP_NOT_VAR_ARG 1414 +#define ER_SP_NO_RETSET 1415 +#define ER_CANT_CREATE_GEOMETRY_OBJECT 1416 +#define ER_FAILED_ROUTINE_BREAK_BINLOG 1417 +#define ER_BINLOG_UNSAFE_ROUTINE 1418 +#define ER_BINLOG_CREATE_ROUTINE_NEED_SUPER 1419 +#define ER_EXEC_STMT_WITH_OPEN_CURSOR 1420 +#define ER_STMT_HAS_NO_OPEN_CURSOR 1421 +#define ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG 1422 +#define ER_NO_DEFAULT_FOR_VIEW_FIELD 1423 +#define ER_SP_NO_RECURSION 1424 +#define ER_TOO_BIG_SCALE 1425 +#define ER_TOO_BIG_PRECISION 1426 +#define ER_M_BIGGER_THAN_D 1427 +#define ER_WRONG_LOCK_OF_SYSTEM_TABLE 1428 +#define ER_CONNECT_TO_FOREIGN_DATA_SOURCE 1429 +#define ER_QUERY_ON_FOREIGN_DATA_SOURCE 1430 +#define ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST 1431 +#define ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE 1432 +#define ER_FOREIGN_DATA_STRING_INVALID 1433 +#define ER_CANT_CREATE_FEDERATED_TABLE 1434 +#define ER_TRG_IN_WRONG_SCHEMA 1435 +#define ER_STACK_OVERRUN_NEED_MORE 1436 +#define ER_TOO_LONG_BODY 1437 +#define ER_WARN_CANT_DROP_DEFAULT_KEYCACHE 1438 +#define ER_TOO_BIG_DISPLAYWIDTH 1439 +#define ER_XAER_DUPID 1440 +#define ER_DATETIME_FUNCTION_OVERFLOW 1441 +#define ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG 1442 +#define ER_VIEW_PREVENT_UPDATE 1443 +#define ER_PS_NO_RECURSION 1444 +#define ER_SP_CANT_SET_AUTOCOMMIT 1445 +#define ER_MALFORMED_DEFINER 1446 +#define ER_VIEW_FRM_NO_USER 1447 +#define ER_VIEW_OTHER_USER 1448 +#define ER_NO_SUCH_USER 1449 +#define ER_FORBID_SCHEMA_CHANGE 1450 +#define ER_ROW_IS_REFERENCED_2 1451 +#define ER_NO_REFERENCED_ROW_2 1452 +#define ER_SP_BAD_VAR_SHADOW 1453 +#define ER_TRG_NO_DEFINER 1454 +#define ER_OLD_FILE_FORMAT 1455 +#define ER_SP_RECURSION_LIMIT 1456 +#define ER_SP_PROC_TABLE_CORRUPT 1457 +#define ER_SP_WRONG_NAME 1458 +#define ER_TABLE_NEEDS_UPGRADE 1459 +#define ER_SP_NO_AGGREGATE 1460 +#define ER_MAX_PREPARED_STMT_COUNT_REACHED 1461 +#define ER_VIEW_RECURSIVE 1462 +#define ER_NON_GROUPING_FIELD_USED 1463 +#define ER_TABLE_CANT_HANDLE_SPKEYS 1464 +#define ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA 1465 +#define ER_REMOVED_SPACES 1466 +#define ER_AUTOINC_READ_FAILED 1467 +#define ER_USERNAME 1468 +#define ER_HOSTNAME 1469 +#define ER_WRONG_STRING_LENGTH 1470 +#define ER_NON_INSERTABLE_TABLE 1471 +#define ER_ADMIN_WRONG_MRG_TABLE 1472 +#define ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT 1473 +#define ER_NAME_BECOMES_EMPTY 1474 +#define ER_AMBIGUOUS_FIELD_TERM 1475 +#define ER_FOREIGN_SERVER_EXISTS 1476 +#define ER_FOREIGN_SERVER_DOESNT_EXIST 1477 +#define ER_ILLEGAL_HA_CREATE_OPTION 1478 +#define ER_PARTITION_REQUIRES_VALUES_ERROR 1479 +#define ER_PARTITION_WRONG_VALUES_ERROR 1480 +#define ER_PARTITION_MAXVALUE_ERROR 1481 +#define ER_PARTITION_SUBPARTITION_ERROR 1482 +#define ER_PARTITION_SUBPART_MIX_ERROR 1483 +#define ER_PARTITION_WRONG_NO_PART_ERROR 1484 +#define ER_PARTITION_WRONG_NO_SUBPART_ERROR 1485 +#define ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR 1486 +#define ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR 1487 +#define ER_FIELD_NOT_FOUND_PART_ERROR 1488 +#define ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR 1489 +#define ER_INCONSISTENT_PARTITION_INFO_ERROR 1490 +#define ER_PARTITION_FUNC_NOT_ALLOWED_ERROR 1491 +#define ER_PARTITIONS_MUST_BE_DEFINED_ERROR 1492 +#define ER_RANGE_NOT_INCREASING_ERROR 1493 +#define ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR 1494 +#define ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR 1495 +#define ER_PARTITION_ENTRY_ERROR 1496 +#define ER_MIX_HANDLER_ERROR 1497 +#define ER_PARTITION_NOT_DEFINED_ERROR 1498 +#define ER_TOO_MANY_PARTITIONS_ERROR 1499 +#define ER_SUBPARTITION_ERROR 1500 +#define ER_CANT_CREATE_HANDLER_FILE 1501 +#define ER_BLOB_FIELD_IN_PART_FUNC_ERROR 1502 +#define ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF 1503 +#define ER_NO_PARTS_ERROR 1504 +#define ER_PARTITION_MGMT_ON_NONPARTITIONED 1505 +#define ER_FOREIGN_KEY_ON_PARTITIONED 1506 +#define ER_DROP_PARTITION_NON_EXISTENT 1507 +#define ER_DROP_LAST_PARTITION 1508 +#define ER_COALESCE_ONLY_ON_HASH_PARTITION 1509 +#define ER_REORG_HASH_ONLY_ON_SAME_NO 1510 +#define ER_REORG_NO_PARAM_ERROR 1511 +#define ER_ONLY_ON_RANGE_LIST_PARTITION 1512 +#define ER_ADD_PARTITION_SUBPART_ERROR 1513 +#define ER_ADD_PARTITION_NO_NEW_PARTITION 1514 +#define ER_COALESCE_PARTITION_NO_PARTITION 1515 +#define ER_REORG_PARTITION_NOT_EXIST 1516 +#define ER_SAME_NAME_PARTITION 1517 +#define ER_NO_BINLOG_ERROR 1518 +#define ER_CONSECUTIVE_REORG_PARTITIONS 1519 +#define ER_REORG_OUTSIDE_RANGE 1520 +#define ER_PARTITION_FUNCTION_FAILURE 1521 +#define ER_PART_STATE_ERROR 1522 +#define ER_LIMITED_PART_RANGE 1523 +#define ER_PLUGIN_IS_NOT_LOADED 1524 +#define ER_WRONG_VALUE 1525 +#define ER_NO_PARTITION_FOR_GIVEN_VALUE 1526 +#define ER_FILEGROUP_OPTION_ONLY_ONCE 1527 +#define ER_CREATE_FILEGROUP_FAILED 1528 +#define ER_DROP_FILEGROUP_FAILED 1529 +#define ER_TABLESPACE_AUTO_EXTEND_ERROR 1530 +#define ER_WRONG_SIZE_NUMBER 1531 +#define ER_SIZE_OVERFLOW_ERROR 1532 +#define ER_ALTER_FILEGROUP_FAILED 1533 +#define ER_BINLOG_ROW_LOGGING_FAILED 1534 +#define ER_BINLOG_ROW_WRONG_TABLE_DEF 1535 +#define ER_BINLOG_ROW_RBR_TO_SBR 1536 +#define ER_EVENT_ALREADY_EXISTS 1537 +#define ER_EVENT_STORE_FAILED 1538 +#define ER_EVENT_DOES_NOT_EXIST 1539 +#define ER_EVENT_CANT_ALTER 1540 +#define ER_EVENT_DROP_FAILED 1541 +#define ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG 1542 +#define ER_EVENT_ENDS_BEFORE_STARTS 1543 +#define ER_EVENT_EXEC_TIME_IN_THE_PAST 1544 +#define ER_EVENT_OPEN_TABLE_FAILED 1545 +#define ER_EVENT_NEITHER_M_EXPR_NOR_M_AT 1546 +#define ER_COL_COUNT_DOESNT_MATCH_CORRUPTED 1547 +#define ER_CANNOT_LOAD_FROM_TABLE 1548 +#define ER_EVENT_CANNOT_DELETE 1549 +#define ER_EVENT_COMPILE_ERROR 1550 +#define ER_EVENT_SAME_NAME 1551 +#define ER_EVENT_DATA_TOO_LONG 1552 +#define ER_DROP_INDEX_FK 1553 +#define ER_WARN_DEPRECATED_SYNTAX_WITH_VER 1554 +#define ER_CANT_WRITE_LOCK_LOG_TABLE 1555 +#define ER_CANT_LOCK_LOG_TABLE 1556 +#define ER_FOREIGN_DUPLICATE_KEY 1557 +#define ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE 1558 +#define ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR 1559 +#define ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT 1560 +#define ER_NDB_CANT_SWITCH_BINLOG_FORMAT 1561 +#define ER_PARTITION_NO_TEMPORARY 1562 +#define ER_PARTITION_CONST_DOMAIN_ERROR 1563 +#define ER_PARTITION_FUNCTION_IS_NOT_ALLOWED 1564 +#define ER_DDL_LOG_ERROR 1565 +#define ER_NULL_IN_VALUES_LESS_THAN 1566 +#define ER_WRONG_PARTITION_NAME 1567 +#define ER_CANT_CHANGE_TX_ISOLATION 1568 +#define ER_DUP_ENTRY_AUTOINCREMENT_CASE 1569 +#define ER_EVENT_MODIFY_QUEUE_ERROR 1570 +#define ER_EVENT_SET_VAR_ERROR 1571 +#define ER_PARTITION_MERGE_ERROR 1572 +#define ER_CANT_ACTIVATE_LOG 1573 +#define ER_RBR_NOT_AVAILABLE 1574 +#define ER_BASE64_DECODE_ERROR 1575 +#define ER_EVENT_RECURSION_FORBIDDEN 1576 +#define ER_EVENTS_DB_ERROR 1577 +#define ER_ONLY_INTEGERS_ALLOWED 1578 +#define ER_UNSUPORTED_LOG_ENGINE 1579 +#define ER_BAD_LOG_STATEMENT 1580 +#define ER_CANT_RENAME_LOG_TABLE 1581 +#define ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT 1582 +#define ER_WRONG_PARAMETERS_TO_NATIVE_FCT 1583 +#define ER_WRONG_PARAMETERS_TO_STORED_FCT 1584 +#define ER_NATIVE_FCT_NAME_COLLISION 1585 +#define ER_DUP_ENTRY_WITH_KEY_NAME 1586 +#define ER_BINLOG_PURGE_EMFILE 1587 +#define ER_EVENT_CANNOT_CREATE_IN_THE_PAST 1588 +#define ER_EVENT_CANNOT_ALTER_IN_THE_PAST 1589 +#define ER_SLAVE_INCIDENT 1590 +#define ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT 1591 +#define ER_BINLOG_UNSAFE_STATEMENT 1592 +#define ER_SLAVE_FATAL_ERROR 1593 +#define ER_SLAVE_RELAY_LOG_READ_FAILURE 1594 +#define ER_SLAVE_RELAY_LOG_WRITE_FAILURE 1595 +#define ER_SLAVE_CREATE_EVENT_FAILURE 1596 +#define ER_SLAVE_MASTER_COM_FAILURE 1597 +#define ER_BINLOG_LOGGING_IMPOSSIBLE 1598 +#define ER_VIEW_NO_CREATION_CTX 1599 +#define ER_VIEW_INVALID_CREATION_CTX 1600 +#define ER_SR_INVALID_CREATION_CTX 1601 +#define ER_TRG_CORRUPTED_FILE 1602 +#define ER_TRG_NO_CREATION_CTX 1603 +#define ER_TRG_INVALID_CREATION_CTX 1604 +#define ER_EVENT_INVALID_CREATION_CTX 1605 +#define ER_TRG_CANT_OPEN_TABLE 1606 +#define ER_CANT_CREATE_SROUTINE 1607 +#define ER_SLAVE_AMBIGOUS_EXEC_MODE 1608 +#define ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT 1609 +#define ER_SLAVE_CORRUPT_EVENT 1610 +#define ER_LOAD_DATA_INVALID_COLUMN 1611 +#define ER_LOG_PURGE_NO_FILE 1612 +#define ER_NEED_REPREPARE 1613 +#define ER_DELAYED_NOT_SUPPORTED 1614 +#define ER_WARN_AUTO_CONVERT_LOCK 1615 +#define ER_NO_AUTO_CONVERT_LOCK_STRICT 1616 +#define ER_NO_AUTO_CONVERT_LOCK_TRANSACTION 1617 +#define ER_NO_STORAGE_ENGINE 1618 +#define ER_BACKUP_BACKUP_START 1619 +#define ER_BACKUP_BACKUP_DONE 1620 +#define ER_BACKUP_RESTORE_START 1621 +#define ER_BACKUP_RESTORE_DONE 1622 +#define ER_BACKUP_NOTHING_TO_BACKUP 1623 +#define ER_BACKUP_CANNOT_INCLUDE_DB 1624 +#define ER_BACKUP_BACKUP 1625 +#define ER_BACKUP_RESTORE 1626 +#define ER_BACKUP_RUNNING 1627 +#define ER_BACKUP_BACKUP_PREPARE 1628 +#define ER_BACKUP_RESTORE_PREPARE 1629 +#define ER_BACKUP_INVALID_LOC 1630 +#define ER_BACKUP_READ_LOC 1631 +#define ER_BACKUP_WRITE_LOC 1632 +#define ER_BACKUP_LIST_DBS 1633 +#define ER_BACKUP_LIST_TABLES 1634 +#define ER_BACKUP_LIST_DB_TABLES 1635 +#define ER_BACKUP_SKIP_VIEW 1636 +#define ER_BACKUP_NO_ENGINE 1637 +#define ER_BACKUP_TABLE_OPEN 1638 +#define ER_BACKUP_READ_HEADER 1639 +#define ER_BACKUP_WRITE_HEADER 1640 +#define ER_BACKUP_NO_BACKUP_DRIVER 1641 +#define ER_BACKUP_NOT_ACCEPTED 1642 +#define ER_BACKUP_CREATE_BACKUP_DRIVER 1643 +#define ER_BACKUP_CREATE_RESTORE_DRIVER 1644 +#define ER_BACKUP_TOO_MANY_IMAGES 1645 +#define ER_BACKUP_WRITE_META 1646 +#define ER_BACKUP_READ_META 1647 +#define ER_BACKUP_CREATE_META 1648 +#define ER_BACKUP_GET_BUF 1649 +#define ER_BACKUP_WRITE_DATA 1650 +#define ER_BACKUP_READ_DATA 1651 +#define ER_BACKUP_NEXT_CHUNK 1652 +#define ER_BACKUP_INIT_BACKUP_DRIVER 1653 +#define ER_BACKUP_INIT_RESTORE_DRIVER 1654 +#define ER_BACKUP_STOP_BACKUP_DRIVER 1655 +#define ER_BACKUP_STOP_RESTORE_DRIVERS 1656 +#define ER_BACKUP_PREPARE_DRIVER 1657 +#define ER_BACKUP_CREATE_VP 1658 +#define ER_BACKUP_UNLOCK_DRIVER 1659 +#define ER_BACKUP_CANCEL_BACKUP 1660 +#define ER_BACKUP_CANCEL_RESTORE 1661 +#define ER_BACKUP_GET_DATA 1662 +#define ER_BACKUP_SEND_DATA 1663 +#define ER_BACKUP_SEND_DATA_RETRY 1664 +#define ER_BACKUP_OPEN_TABLES 1665 +#define ER_BACKUP_THREAD_INIT 1666 +#define ER_BACKUP_PROGRESS_TABLES 1667 +#define ER_TABLESPACE_EXIST 1668 +#define ER_NO_SUCH_TABLESPACE 1669 +#define ER_SLAVE_HEARTBEAT_FAILURE 1670 +#define ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE 1671 +#define ER_BACKUP_CANT_FIND_SE 1672 +#define ER_BACKUP_NO_NATIVE_BE 1673 +#define ER_BACKUP_UNKNOWN_BE 1674 +#define ER_BACKUP_WRONG_TABLE_BE 1675 +#define ER_BACKUP_CANT_RESTORE_DB 1676 +#define ER_BACKUP_CANT_RESTORE_TABLE 1677 +#define ER_BACKUP_CANT_RESTORE_VIEW 1678 +#define ER_BACKUP_CANT_RESTORE_SROUT 1679 +#define ER_BACKUP_CANT_RESTORE_EVENT 1680 +#define ER_BACKUP_CANT_RESTORE_TRIGGER 1681 +#define ER_BACKUP_CATALOG_ADD_DB 1682 +#define ER_BACKUP_CATALOG_ADD_TABLE 1683 +#define ER_BACKUP_CATALOG_ADD_VIEW 1684 +#define ER_BACKUP_CATALOG_ADD_SROUT 1685 +#define ER_BACKUP_CATALOG_ADD_EVENT 1686 +#define ER_BACKUP_CATALOG_ADD_TRIGGER 1687 +#define ER_BACKUP_UNKNOWN_OBJECT 1688 +#define ER_BACKUP_UNKNOWN_OBJECT_TYPE 1689 +#define ER_BACKUP_OPEN_WR 1690 +#define ER_BACKUP_OPEN_RD 1691 +#define ER_BACKUP_BAD_MAGIC 1692 +#define ER_BACKUP_CONTEXT_CREATE 1693 +#define ER_BACKUP_CONTEXT_REMOVE 1694 +#define ER_BAD_PATH 1695 +#define ER_DDL_BLOCK 1696 +#define ER_BACKUP_LOGGER_INIT 1697 +#define ER_BACKUP_WRITE_SUMMARY 1698 +#define ER_BACKUP_READ_SUMMARY 1699 +#define ER_BACKUP_GET_META_DB 1700 +#define ER_BACKUP_GET_META_TABLE 1701 +#define ER_BACKUP_GET_META_VIEW 1702 +#define ER_BACKUP_GET_META_SROUT 1703 +#define ER_BACKUP_GET_META_EVENT 1704 +#define ER_BACKUP_GET_META_TRIGGER 1705 +#define ER_BACKUP_CREATE_BE 1706 +#define ER_BACKUP_LIST_PERDB 1707 +#define ER_BACKUP_LIST_DB_VIEWS 1708 +#define ER_BACKUP_LIST_DB_SROUT 1709 +#define ER_BACKUP_LIST_DB_EVENTS 1710 +#define ER_BACKUP_LIST_DB_TRIGGERS 1711 +#define ER_BACKUP_LOG_WRITE_ERROR 1712 +#define ER_TABLESPACE_NOT_EMPTY 1713 +#define ER_BACKUP_CAT_ENUM 1714 +#define ER_BACKUP_CANT_RESTORE_TS 1715 +#define ER_BACKUP_TS_CHANGE 1716 +#define ER_BACKUP_GET_META_TS 1717 +#define ER_TABLESPACE_DATAFILE_EXIST 1718 +#define ER_BACKUP_CATALOG_ADD_TS 1719 +#define ER_DEBUG_SYNC_TIMEOUT 1720 +#define ER_DEBUG_SYNC_HIT_LIMIT 1721 +#define ER_BACKUP_FAILED_TO_INIT_COMPRESSION 1722 +#define ER_BACKUP_OBTAIN_NAME_LOCK_FAILED 1723 +#define ER_BACKUP_RELEASE_NAME_LOCK_FAILED 1724 +#define ER_BACKUP_BACKUPDIR 1725 +#define ER_ERROR_LAST 1725 diff --git a/NetService/include/Mysql/mysys/rijndael.h b/NetService/include/Mysql/mysys/rijndael.h new file mode 100644 index 00000000..89963a85 --- /dev/null +++ b/NetService/include/Mysql/mysys/rijndael.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2002 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +/* + rijndael-alg-fst.h + + @version 3.0 (December 2000) + Optimised ANSI C code for the Rijndael cipher (now AES) + @author Vincent Rijmen + @author Antoon Bosselaers + @author Paulo Barreto + + This code is hereby placed in the public domain. + Modified by Peter Zaitsev to fit MySQL coding style. + */ + +#define AES_MAXKC (256/32) +#define AES_MAXKB (256/8) +#define AES_MAXNR 14 + +int rijndaelKeySetupEnc(uint32 rk[/*4*(Nr + 1)*/], const uint8 cipherKey[], + int keyBits); +int rijndaelKeySetupDec(uint32 rk[/*4*(Nr + 1)*/], const uint8 cipherKey[], + int keyBits); +void rijndaelEncrypt(const uint32 rk[/*4*(Nr + 1)*/], int Nr, + const uint8 pt[16], uint8 ct[16]); +void rijndaelDecrypt(const uint32 rk[/*4*(Nr + 1)*/], int Nr, + const uint8 ct[16], uint8 pt[16]); diff --git a/NetService/include/Mysql/mysys_err.h b/NetService/include/Mysql/mysys_err.h new file mode 100644 index 00000000..7167395f --- /dev/null +++ b/NetService/include/Mysql/mysys_err.h @@ -0,0 +1,90 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _mysys_err_h +#define _mysys_err_h +#ifdef __cplusplus +extern "C" { +#endif + +#define GLOBERRS (EE_ERROR_LAST - EE_ERROR_FIRST + 1) /* Nr of global errors */ +#define EE(X) (globerrs[(X) - EE_ERROR_FIRST]) + +extern const char * NEAR globerrs[]; /* my_error_messages is here */ + +/* Error message numbers in global map */ +/* + Do not add error numbers before EE_ERROR_FIRST. + If necessary to add lower numbers, change EE_ERROR_FIRST accordingly. + + We start with error 1 to not confuse peoples with 'error 0' +*/ + +#define EE_ERROR_FIRST 1 /*Copy first error nr.*/ +#define EE_CANTCREATEFILE 1 +#define EE_READ 2 +#define EE_WRITE 3 +#define EE_BADCLOSE 4 +#define EE_OUTOFMEMORY 5 +#define EE_DELETE 6 +#define EE_LINK 7 +#define EE_EOFERR 9 +#define EE_CANTLOCK 10 +#define EE_CANTUNLOCK 11 +#define EE_DIR 12 +#define EE_STAT 13 +#define EE_CANT_CHSIZE 14 +#define EE_CANT_OPEN_STREAM 15 +#define EE_GETWD 16 +#define EE_SETWD 17 +#define EE_LINK_WARNING 18 +#define EE_OPEN_WARNING 19 +#define EE_DISK_FULL 20 +#define EE_CANT_MKDIR 21 +#define EE_UNKNOWN_CHARSET 22 +#define EE_OUT_OF_FILERESOURCES 23 +#define EE_CANT_READLINK 24 +#define EE_CANT_SYMLINK 25 +#define EE_REALPATH 26 +#define EE_SYNC 27 +#define EE_UNKNOWN_COLLATION 28 +#define EE_FILENOTFOUND 29 +#define EE_FILE_NOT_CLOSED 30 +#define EE_CANT_CHMOD 31 +#define EE_ERROR_LAST 31 /* Copy last error nr */ +/* Add error numbers before EE_ERROR_LAST and change it accordingly. */ + + /* exit codes for all MySQL programs */ + +#define EXIT_UNSPECIFIED_ERROR 1 +#define EXIT_UNKNOWN_OPTION 2 +#define EXIT_AMBIGUOUS_OPTION 3 +#define EXIT_NO_ARGUMENT_ALLOWED 4 +#define EXIT_ARGUMENT_REQUIRED 5 +#define EXIT_VAR_PREFIX_NOT_UNIQUE 6 +#define EXIT_UNKNOWN_VARIABLE 7 +#define EXIT_OUT_OF_MEMORY 8 +#define EXIT_UNKNOWN_SUFFIX 9 +#define EXIT_NO_PTR_TO_VARIABLE 10 +#define EXIT_CANNOT_CONNECT_TO_SERVICE 11 +#define EXIT_OPTION_DISABLED 12 +#define EXIT_ARGUMENT_INVALID 13 + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/NetService/include/Mysql/queues.h b/NetService/include/Mysql/queues.h new file mode 100644 index 00000000..d01b73ba --- /dev/null +++ b/NetService/include/Mysql/queues.h @@ -0,0 +1,72 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Code for generell handling of priority Queues. + Implemention of queues from "Algoritms in C" by Robert Sedgewick. + Copyright Monty Program KB. + By monty. +*/ + +#ifndef _queues_h +#define _queues_h +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct st_queue { + uchar **root; + void *first_cmp_arg; + uint elements; + uint max_elements; + uint offset_to_key; /* compare is done on element+offset */ + int max_at_top; /* Normally 1, set to -1 if queue_top gives max */ + int (*compare)(void *, uchar *,uchar *); + uint auto_extent; +} QUEUE; + +#define queue_top(queue) ((queue)->root[1]) +#define queue_element(queue,index) ((queue)->root[index+1]) +#define queue_end(queue) ((queue)->root[(queue)->elements]) +#define queue_replaced(queue) _downheap(queue,1) +#define queue_set_cmp_arg(queue, set_arg) (queue)->first_cmp_arg= set_arg +#define queue_set_max_at_top(queue, set_arg) \ + (queue)->max_at_top= set_arg ? -1 : 1 +typedef int (*queue_compare)(void *,uchar *, uchar *); + +int init_queue(QUEUE *queue,uint max_elements,uint offset_to_key, + pbool max_at_top, queue_compare compare, + void *first_cmp_arg); +int init_queue_ex(QUEUE *queue,uint max_elements,uint offset_to_key, + pbool max_at_top, queue_compare compare, + void *first_cmp_arg, uint auto_extent); +int reinit_queue(QUEUE *queue,uint max_elements,uint offset_to_key, + pbool max_at_top, queue_compare compare, + void *first_cmp_arg); +int resize_queue(QUEUE *queue, uint max_elements); +void delete_queue(QUEUE *queue); +void queue_insert(QUEUE *queue,uchar *element); +int queue_insert_safe(QUEUE *queue, uchar *element); +uchar *queue_remove(QUEUE *queue,uint idx); +#define queue_remove_all(queue) { (queue)->elements= 0; } +#define queue_is_full(queue) (queue->elements == queue->max_elements) +void _downheap(QUEUE *queue,uint idx); +void queue_fix(QUEUE *queue); +#define is_queue_inited(queue) ((queue)->root != 0) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/NetService/include/Mysql/service_versions.h b/NetService/include/Mysql/service_versions.h new file mode 100644 index 00000000..114957cd --- /dev/null +++ b/NetService/include/Mysql/service_versions.h @@ -0,0 +1,24 @@ +/* Copyright (C) 2009 Sun Microsystems, Inc. + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifdef _WIN32 +#define SERVICE_VERSION __declspec(dllexport) void * +#else +#define SERVICE_VERSION void * +#endif + +#define VERSION_my_snprintf 0x0100 +#define VERSION_thd_alloc 0x0100 + diff --git a/NetService/include/Mysql/sha1.h b/NetService/include/Mysql/sha1.h new file mode 100644 index 00000000..e476456a --- /dev/null +++ b/NetService/include/Mysql/sha1.h @@ -0,0 +1,66 @@ +/* Copyright (C) 2002, 2006 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + This is the header file for code which implements the Secure + Hashing Algorithm 1 as defined in FIPS PUB 180-1 published + April 17, 1995. + + Many of the variable names in this code, especially the + single character names, were used because those were the names + used in the publication. + + Please read the file sha1.c for more information. + + Modified 2002 by Peter Zaitsev to better follow MySQL standards +*/ + + +enum sha_result_codes +{ + SHA_SUCCESS = 0, + SHA_NULL, /* Null pointer parameter */ + SHA_INPUT_TOO_LONG, /* input data too long */ + SHA_STATE_ERROR /* called Input after Result */ +}; + +#define SHA1_HASH_SIZE 20 /* Hash size in bytes */ + +/* + This structure will hold context information for the SHA-1 + hashing operation +*/ + +typedef struct SHA1_CONTEXT +{ + ulonglong Length; /* Message length in bits */ + uint32 Intermediate_Hash[SHA1_HASH_SIZE/4]; /* Message Digest */ + int Computed; /* Is the digest computed? */ + int Corrupted; /* Is the message digest corrupted? */ + int16 Message_Block_Index; /* Index into message block array */ + uint8 Message_Block[64]; /* 512-bit message blocks */ +} SHA1_CONTEXT; + +/* + Function Prototypes +*/ + +C_MODE_START + +int mysql_sha1_reset(SHA1_CONTEXT*); +int mysql_sha1_input(SHA1_CONTEXT*, const uint8 *, unsigned int); +int mysql_sha1_result(SHA1_CONTEXT* , uint8 Message_Digest[SHA1_HASH_SIZE]); + +C_MODE_END diff --git a/NetService/include/Mysql/sha2.h b/NetService/include/Mysql/sha2.h new file mode 100644 index 00000000..49dbac56 --- /dev/null +++ b/NetService/include/Mysql/sha2.h @@ -0,0 +1,72 @@ +/* Copyright (C) 2007 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef included_sha2_h +#define included_sha2_h + +#include + +#if defined(HAVE_YASSL) || defined(HAVE_OPENSSL) + +# ifdef HAVE_STDDEF_H +# include +# endif + +# ifndef HAVE_YASSL +# include + +# else + +#include "../extra/yassl/taocrypt/include/sha.hpp" + +# ifdef __cplusplus +extern "C" { +# endif + +#ifndef SHA512_DIGEST_LENGTH +#define SHA512_DIGEST_LENGTH TaoCrypt::SHA512::DIGEST_SIZE +#endif + +#ifndef SHA384_DIGEST_LENGTH +#define SHA384_DIGEST_LENGTH TaoCrypt::SHA384::DIGEST_SIZE +#endif + +#ifndef SHA256_DIGEST_LENGTH +#define SHA256_DIGEST_LENGTH TaoCrypt::SHA256::DIGEST_SIZE +#endif + +#ifndef SHA224_DIGEST_LENGTH +#define SHA224_DIGEST_LENGTH TaoCrypt::SHA224::DIGEST_SIZE +#endif + +#define GEN_YASSL_SHA2_BRIDGE(size) \ +unsigned char* SHA##size(const unsigned char *input_ptr, size_t input_length, \ + char unsigned *output_ptr); + +GEN_YASSL_SHA2_BRIDGE(512); +GEN_YASSL_SHA2_BRIDGE(384); +GEN_YASSL_SHA2_BRIDGE(256); +GEN_YASSL_SHA2_BRIDGE(224); + +#undef GEN_YASSL_SHA2_BRIDGE + +# ifdef __cplusplus +} +# endif + +# endif /* HAVE_YASSL */ + +#endif /* HAVE_OPENSSL || HAVE_YASSL */ +#endif /* included_sha2_h */ diff --git a/NetService/include/Mysql/sql_common.h b/NetService/include/Mysql/sql_common.h new file mode 100644 index 00000000..9e43d076 --- /dev/null +++ b/NetService/include/Mysql/sql_common.h @@ -0,0 +1,50 @@ +/* Copyright (C) 2003-2004, 2006 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +extern const char *unknown_sqlstate; +extern const char *cant_connect_sqlstate; +extern const char *not_error_sqlstate; + +#ifdef __cplusplus +extern "C" { +#endif + +extern CHARSET_INFO *default_client_charset_info; +MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, + my_bool default_value, uint server_capabilities); +void free_rows(MYSQL_DATA *cur); +void free_old_query(MYSQL *mysql); +void end_server(MYSQL *mysql); +my_bool mysql_reconnect(MYSQL *mysql); +void mysql_read_default_options(struct st_mysql_options *options, + const char *filename,const char *group); +my_bool +cli_advanced_command(MYSQL *mysql, enum enum_server_command command, + const unsigned char *header, ulong header_length, + const unsigned char *arg, ulong arg_length, + my_bool skip_check, MYSQL_STMT *stmt); +unsigned long cli_safe_read(MYSQL *mysql); +void net_clear_error(NET *net); +void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net); +void set_stmt_error(MYSQL_STMT *stmt, int errcode, const char *sqlstate, + const char *err); +void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate); +#ifdef __cplusplus +} +#endif + +#define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41) + diff --git a/NetService/include/Mysql/sslopt-case.h b/NetService/include/Mysql/sslopt-case.h new file mode 100644 index 00000000..ee6c83cd --- /dev/null +++ b/NetService/include/Mysql/sslopt-case.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) + case OPT_SSL_KEY: + case OPT_SSL_CERT: + case OPT_SSL_CA: + case OPT_SSL_CAPATH: + case OPT_SSL_CIPHER: + /* + Enable use of SSL if we are using any ssl option + One can disable SSL later by using --skip-ssl or --ssl=0 + */ + opt_use_ssl= 1; + break; +#endif diff --git a/NetService/include/Mysql/sslopt-longopts.h b/NetService/include/Mysql/sslopt-longopts.h new file mode 100644 index 00000000..06422e59 --- /dev/null +++ b/NetService/include/Mysql/sslopt-longopts.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) + + {"ssl", OPT_SSL_SSL, + "Enable SSL for connection (automatically enabled with other flags). Disable with --skip-ssl.", + (uchar **) &opt_use_ssl, (uchar **) &opt_use_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0, + 0, 0, 0}, + {"ssl-ca", OPT_SSL_CA, + "CA file in PEM format (check OpenSSL docs, implies --ssl).", + (uchar **) &opt_ssl_ca, (uchar **) &opt_ssl_ca, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, + {"ssl-capath", OPT_SSL_CAPATH, + "CA directory (check OpenSSL docs, implies --ssl).", + (uchar **) &opt_ssl_capath, (uchar **) &opt_ssl_capath, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, + {"ssl-cert", OPT_SSL_CERT, "X509 cert in PEM format (implies --ssl).", + (uchar **) &opt_ssl_cert, (uchar **) &opt_ssl_cert, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, + {"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use (implies --ssl).", + (uchar **) &opt_ssl_cipher, (uchar **) &opt_ssl_cipher, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, + {"ssl-key", OPT_SSL_KEY, "X509 key in PEM format (implies --ssl).", + (uchar **) &opt_ssl_key, (uchar **) &opt_ssl_key, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, +#ifdef MYSQL_CLIENT + {"ssl-verify-server-cert", OPT_SSL_VERIFY_SERVER_CERT, + "Verify server's \"Common Name\" in its cert against hostname used when connecting. This option is disabled by default.", + (uchar **) &opt_ssl_verify_server_cert, (uchar **) &opt_ssl_verify_server_cert, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, +#endif +#endif /* HAVE_OPENSSL */ diff --git a/NetService/include/Mysql/sslopt-vars.h b/NetService/include/Mysql/sslopt-vars.h new file mode 100644 index 00000000..9d25c336 --- /dev/null +++ b/NetService/include/Mysql/sslopt-vars.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) +#ifdef SSL_VARS_NOT_STATIC +#define SSL_STATIC +#else +#define SSL_STATIC static +#endif +SSL_STATIC my_bool opt_use_ssl = 0; +SSL_STATIC char *opt_ssl_ca = 0; +SSL_STATIC char *opt_ssl_capath = 0; +SSL_STATIC char *opt_ssl_cert = 0; +SSL_STATIC char *opt_ssl_cipher = 0; +SSL_STATIC char *opt_ssl_key = 0; +#ifdef MYSQL_CLIENT +SSL_STATIC my_bool opt_ssl_verify_server_cert= 0; +#endif +#endif diff --git a/NetService/include/Mysql/t_ctype.h b/NetService/include/Mysql/t_ctype.h new file mode 100644 index 00000000..15600019 --- /dev/null +++ b/NetService/include/Mysql/t_ctype.h @@ -0,0 +1,254 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Copyright (C) 1998, 1999 by Pruet Boonma, all rights reserved. + Copyright (C) 1998 by Theppitak Karoonboonyanan, all rights reserved. + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies. + Smaphan Raruenrom and Pruet Boonma makes no representations about + the suitability of this software for any purpose. It is provided + "as is" without express or implied warranty. +*/ + +/* LC_COLLATE category + Level information */ + +#ifndef _t_ctype_h +#define _t_ctype_h + +#define TOT_LEVELS 5 +#define LAST_LEVEL 4 /* TOT_LEVELS - 1 */ + +#define IGNORE 0 + + +/* level 1 symbols & order */ +enum l1_symbols { + L1_08 = TOT_LEVELS, + L1_18, + L1_28, + L1_38, + L1_48, + L1_58, + L1_68, + L1_78, + L1_88, + L1_98, + L1_A8, + L1_B8, + L1_C8, + L1_D8, + L1_E8, + L1_F8, + L1_G8, + L1_H8, + L1_I8, + L1_J8, + L1_K8, + L1_L8, + L1_M8, + L1_N8, + L1_O8, + L1_P8, + L1_Q8, + L1_R8, + L1_S8, + L1_T8, + L1_U8, + L1_V8, + L1_W8, + L1_X8, + L1_Y8, + L1_Z8, + L1_KO_KAI, + L1_KHO_KHAI, + L1_KHO_KHUAT, + L1_KHO_KHWAI, + L1_KHO_KHON, + L1_KHO_RAKHANG, + L1_NGO_NGU, + L1_CHO_CHAN, + L1_CHO_CHING, + L1_CHO_CHANG, + L1_SO_SO, + L1_CHO_CHOE, + L1_YO_YING, + L1_DO_CHADA, + L1_TO_PATAK, + L1_THO_THAN, + L1_THO_NANGMONTHO, + L1_THO_PHUTHAO, + L1_NO_NEN, + L1_DO_DEK, + L1_TO_TAO, + L1_THO_THUNG, + L1_THO_THAHAN, + L1_THO_THONG, + L1_NO_NU, + L1_BO_BAIMAI, + L1_PO_PLA, + L1_PHO_PHUNG, + L1_FO_FA, + L1_PHO_PHAN, + L1_FO_FAN, + L1_PHO_SAMPHAO, + L1_MO_MA, + L1_YO_YAK, + L1_RO_RUA, + L1_RU, + L1_LO_LING, + L1_LU, + L1_WO_WAEN, + L1_SO_SALA, + L1_SO_RUSI, + L1_SO_SUA, + L1_HO_HIP, + L1_LO_CHULA, + L1_O_ANG, + L1_HO_NOKHUK, + L1_NKHIT, + L1_SARA_A, + L1_MAI_HAN_AKAT, + L1_SARA_AA, + L1_SARA_AM, + L1_SARA_I, + L1_SARA_II, + L1_SARA_UE, + L1_SARA_UEE, + L1_SARA_U, + L1_SARA_UU, + L1_SARA_E, + L1_SARA_AE, + L1_SARA_O, + L1_SARA_AI_MAIMUAN, + L1_SARA_AI_MAIMALAI +}; + +/* level 2 symbols & order */ +enum l2_symbols { + L2_BLANK = TOT_LEVELS, + L2_THAII, + L2_YAMAK, + L2_PINTHU, + L2_GARAN, + L2_TYKHU, + L2_TONE1, + L2_TONE2, + L2_TONE3, + L2_TONE4 +}; + +/* level 3 symbols & order */ +enum l3_symbols { + L3_BLANK = TOT_LEVELS, + L3_SPACE, + L3_NB_SACE, + L3_LOW_LINE, + L3_HYPHEN, + L3_COMMA, + L3_SEMICOLON, + L3_COLON, + L3_EXCLAMATION, + L3_QUESTION, + L3_SOLIDUS, + L3_FULL_STOP, + L3_PAIYAN_NOI, + L3_MAI_YAMOK, + L3_GRAVE, + L3_CIRCUMFLEX, + L3_TILDE, + L3_APOSTROPHE, + L3_QUOTATION, + L3_L_PARANTHESIS, + L3_L_BRACKET, + L3_L_BRACE, + L3_R_BRACE, + L3_R_BRACKET, + L3_R_PARENTHESIS, + L3_AT, + L3_BAHT, + L3_DOLLAR, + L3_FONGMAN, + L3_ANGKHANKHU, + L3_KHOMUT, + L3_ASTERISK, + L3_BK_SOLIDUS, + L3_AMPERSAND, + L3_NUMBER, + L3_PERCENT, + L3_PLUS, + L3_LESS_THAN, + L3_EQUAL, + L3_GREATER_THAN, + L3_V_LINE +}; + +/* level 4 symbols & order */ +enum l4_symbols { + L4_BLANK = TOT_LEVELS, + L4_MIN, + L4_CAP, + L4_EXT +}; + +enum level_symbols { + L_UPRUPR = TOT_LEVELS, + L_UPPER, + L_MIDDLE, + L_LOWER +}; + +#define _is(c) (t_ctype[(c)][LAST_LEVEL]) +#define _level 8 +#define _consnt 16 +#define _ldvowel 32 +#define _fllwvowel 64 +#define _uprvowel 128 +#define _lwrvowel 256 +#define _tone 512 +#define _diacrt1 1024 +#define _diacrt2 2048 +#define _combine 4096 +#define _stone 8192 +#define _tdig 16384 +#define _rearvowel (_fllwvowel | _uprvowel | _lwrvowel) +#define _diacrt (_diacrt1 | _diacrt2) +#define levelof(c) ( _is(c) & _level ) +#define isthai(c) ( (c) >= 128 ) +#define istalpha(c) ( _is(c) & (_consnt|_ldvowel|_rearvowel|\ + _tone|_diacrt1|_diacrt2) ) +#define isconsnt(c) ( _is(c) & _consnt ) +#define isldvowel(c) ( _is(c) & _ldvowel ) +#define isfllwvowel(c) ( _is(c) & _fllwvowel ) +#define ismidvowel(c) ( _is(c) & (_ldvowel|_fllwvowel) ) +#define isuprvowel(c) ( _is(c) & _uprvowel ) +#define islwrvowel(c) ( _is(c) & _lwrvowel ) +#define isuprlwrvowel(c) ( _is(c) & (_lwrvowel | _uprvowel)) +#define isrearvowel(c) ( _is(c) & _rearvowel ) +#define isvowel(c) ( _is(c) & (_ldvowel|_rearvowel) ) +#define istone(c) ( _is(c) & _tone ) +#define isunldable(c) ( _is(c) & (_rearvowel|_tone|_diacrt1|_diacrt2) ) +#define iscombinable(c) ( _is(c) & _combine ) +#define istdigit(c) ( _is(c) & _tdig ) +#define isstone(c) ( _is(c) & _stone ) +#define isdiacrt1(c) ( _is(c) & _diacrt1) +#define isdiacrt2(c) ( _is(c) & _diacrt2) +#define isdiacrt(c) ( _is(c) & _diacrt) + +/* Function prototype called by sql/field.cc */ +void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length); + +#endif diff --git a/NetService/include/Mysql/thr_alarm.h b/NetService/include/Mysql/thr_alarm.h new file mode 100644 index 00000000..fb906039 --- /dev/null +++ b/NetService/include/Mysql/thr_alarm.h @@ -0,0 +1,110 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Prototypes when using thr_alarm library functions */ + +#ifndef _thr_alarm_h +#define _thr_alarm_h +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef USE_ALARM_THREAD +#define USE_ONE_SIGNAL_HAND /* One must call process_alarm */ +#endif +#ifdef HAVE_rts_threads +#undef USE_ONE_SIGNAL_HAND +#define USE_ALARM_THREAD +#define THR_SERVER_ALARM SIGUSR1 +#else +#define THR_SERVER_ALARM SIGALRM +#endif + +typedef struct st_alarm_info +{ + ulong next_alarm_time; + uint active_alarms; + uint max_used_alarms; +} ALARM_INFO; + +void thr_alarm_info(ALARM_INFO *info); + +#if defined(DONT_USE_THR_ALARM) || !defined(THREAD) + +#define USE_ALARM_THREAD +#undef USE_ONE_SIGNAL_HAND + +typedef my_bool thr_alarm_t; +typedef my_bool ALARM; + +#define thr_alarm_init(A) (*(A))=0 +#define thr_alarm_in_use(A) (*(A) != 0) +#define thr_end_alarm(A) +#define thr_alarm(A,B,C) ((*(A)=1)-1) +/* The following should maybe be (*(A)) */ +#define thr_got_alarm(A) 0 +#define init_thr_alarm(A) +#define thr_alarm_kill(A) +#define resize_thr_alarm(N) +#define end_thr_alarm(A) + +#else +#if defined(__WIN__) +typedef struct st_thr_alarm_entry +{ + rf_SetTimer crono; +} thr_alarm_entry; + +#else /* System with posix threads */ + +typedef int thr_alarm_entry; + +#define thr_got_alarm(thr_alarm) (**(thr_alarm)) + +#endif /* __WIN__ */ + +typedef thr_alarm_entry* thr_alarm_t; + +typedef struct st_alarm { + ulong expire_time; + thr_alarm_entry alarmed; /* set when alarm is due */ + pthread_t thread; + my_thread_id thread_id; + my_bool malloced; +} ALARM; + +extern uint thr_client_alarm; +extern pthread_t alarm_thread; + +#define thr_alarm_init(A) (*(A))=0 +#define thr_alarm_in_use(A) (*(A)!= 0) +void init_thr_alarm(uint max_alarm); +void resize_thr_alarm(uint max_alarms); +my_bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff); +void thr_alarm_kill(my_thread_id thread_id); +void thr_end_alarm(thr_alarm_t *alarmed); +void end_thr_alarm(my_bool free_structures); +sig_handler process_alarm(int); +#ifndef thr_got_alarm +my_bool thr_got_alarm(thr_alarm_t *alrm); +#endif + + +#endif /* DONT_USE_THR_ALARM */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _thr_alarm_h */ diff --git a/NetService/include/Mysql/thr_lock.h b/NetService/include/Mysql/thr_lock.h new file mode 100644 index 00000000..38f0478f --- /dev/null +++ b/NetService/include/Mysql/thr_lock.h @@ -0,0 +1,181 @@ +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* For use with thr_lock:s */ + +#ifndef _thr_lock_h +#define _thr_lock_h +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +struct st_thr_lock; +extern ulong locks_immediate,locks_waited ; + +/** + Lock types are used to request a lock on a table. Changes in this enumeration + might affect transactional locks as well. + Important: if a new lock type is added, a matching lock description + must be added to sql_test.cc's lock_descriptions array. + @see set_handler_table_locks + @see read_lock_type_for_table +*/ +enum thr_lock_type { TL_IGNORE=-1, + TL_UNLOCK, /* UNLOCK ANY LOCK */ + /* + Parser only! At open_tables() becomes TL_READ or + TL_READ_NO_INSERT depending on the binary log format + (SBR/RBR) and on the table category (log table). + Used for tables that are read by statements which + modify tables. + */ + TL_READ_DEFAULT, + TL_READ, /* Read lock */ + TL_READ_WITH_SHARED_LOCKS, + /* High prior. than TL_WRITE. Allow concurrent insert */ + TL_READ_HIGH_PRIORITY, + /* READ, Don't allow concurrent insert */ + TL_READ_NO_INSERT, + /* + Write lock, but allow other threads to read / write. + Used by BDB tables in MySQL to mark that someone is + reading/writing to the table. + */ + TL_WRITE_ALLOW_WRITE, + /* + Write lock, but allow other threads to read. + Used by ALTER TABLE in MySQL to allow readers + to use the table until ALTER TABLE is finished. + */ + TL_WRITE_ALLOW_READ, + /* + WRITE lock used by concurrent insert. Will allow + READ, if one could use concurrent insert on table. + */ + TL_WRITE_CONCURRENT_INSERT, + /* Write used by INSERT DELAYED. Allows READ locks */ + TL_WRITE_DELAYED, + /* + parser only! Late bound low_priority flag. + At open_tables() becomes thd->update_lock_default. + */ + TL_WRITE_DEFAULT, + /* WRITE lock that has lower priority than TL_READ */ + TL_WRITE_LOW_PRIORITY, + /* Normal WRITE lock */ + TL_WRITE, + /* Abort new lock request with an error */ + TL_WRITE_ONLY}; + +enum enum_thr_lock_result { THR_LOCK_SUCCESS= 0, THR_LOCK_ABORTED= 1, + THR_LOCK_WAIT_TIMEOUT= 2, THR_LOCK_DEADLOCK= 3 }; + + +extern ulong max_write_lock_count; +extern ulong table_lock_wait_timeout; +extern my_bool thr_lock_inited; +extern enum thr_lock_type thr_upgraded_concurrent_insert_lock; + +/* + A description of the thread which owns the lock. The address + of an instance of this structure is used to uniquely identify the thread. +*/ + +typedef struct st_thr_lock_info +{ + pthread_t thread; + my_thread_id thread_id; + ulong n_cursors; +} THR_LOCK_INFO; + +/* + Lock owner identifier. Globally identifies the lock owner within the + thread and among all the threads. The address of an instance of this + structure is used as id. +*/ + +typedef struct st_thr_lock_owner +{ + THR_LOCK_INFO *info; +} THR_LOCK_OWNER; + + +typedef struct st_thr_lock_data { + THR_LOCK_OWNER *owner; + struct st_thr_lock_data *next,**prev; + struct st_thr_lock *lock; + pthread_cond_t *cond; + enum thr_lock_type type; + void *status_param; /* Param to status functions */ + void *debug_print_param; +} THR_LOCK_DATA; + +struct st_lock_list { + THR_LOCK_DATA *data,**last; +}; + +typedef struct st_thr_lock { + LIST list; + pthread_mutex_t mutex; + struct st_lock_list read_wait; + struct st_lock_list read; + struct st_lock_list write_wait; + struct st_lock_list write; + /* write_lock_count is incremented for write locks and reset on read locks */ + ulong write_lock_count; + uint read_no_write_count; + void (*get_status)(void*, my_bool); /* When one gets a lock */ + void (*copy_status)(void*,void*); + void (*update_status)(void*); /* Before release of write */ + void (*restore_status)(void*); /* Before release of read */ + my_bool (*check_status)(void *); + my_bool allow_multiple_concurrent_insert; +} THR_LOCK; + + +extern LIST *thr_lock_thread_list; +extern pthread_mutex_t THR_LOCK_lock; + +my_bool init_thr_lock(void); /* Must be called once/thread */ +#define thr_lock_owner_init(owner, info_arg) (owner)->info= (info_arg) +void thr_lock_info_init(THR_LOCK_INFO *info); +void thr_lock_init(THR_LOCK *lock); +void thr_lock_delete(THR_LOCK *lock); +void thr_lock_data_init(THR_LOCK *lock,THR_LOCK_DATA *data, + void *status_param); +enum enum_thr_lock_result thr_lock(THR_LOCK_DATA *data, + THR_LOCK_OWNER *owner, + enum thr_lock_type lock_type); +void thr_unlock(THR_LOCK_DATA *data); +enum enum_thr_lock_result thr_multi_lock(THR_LOCK_DATA **data, + uint count, THR_LOCK_OWNER *owner); +void thr_multi_unlock(THR_LOCK_DATA **data,uint count); +void +thr_lock_merge_status(THR_LOCK_DATA **data, uint count); +void thr_abort_locks(THR_LOCK *lock, my_bool upgrade_lock); +my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread); +void thr_print_locks(void); /* For debugging */ +my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, + enum thr_lock_type new_lock_type); +void thr_downgrade_write_lock(THR_LOCK_DATA *data, + enum thr_lock_type new_lock_type); +my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data); +#ifdef __cplusplus +} +#endif +#endif /* _thr_lock_h */ diff --git a/NetService/include/Mysql/typelib.h b/NetService/include/Mysql/typelib.h new file mode 100644 index 00000000..46106d1b --- /dev/null +++ b/NetService/include/Mysql/typelib.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#ifndef _typelib_h +#define _typelib_h + +#include "my_alloc.h" + +typedef struct st_typelib { /* Different types saved here */ + unsigned int count; /* How many types */ + const char *name; /* Name of typelib */ + const char **type_names; + unsigned int *type_lengths; +} TYPELIB; + +extern my_ulonglong find_typeset(char *x, TYPELIB *typelib,int *error_position); +extern int find_type_or_exit(const char *x, TYPELIB *typelib, + const char *option); +extern int find_type(char *x, const TYPELIB *typelib, unsigned int full_name); +extern void make_type(char *to,unsigned int nr,TYPELIB *typelib); +extern const char *get_type(TYPELIB *typelib,unsigned int nr); +extern TYPELIB *copy_typelib(MEM_ROOT *root, TYPELIB *from); + +extern TYPELIB sql_protocol_typelib; + +#endif /* _typelib_h */ diff --git a/NetService/include/Mysql/violite.h b/NetService/include/Mysql/violite.h new file mode 100644 index 00000000..2720047b --- /dev/null +++ b/NetService/include/Mysql/violite.h @@ -0,0 +1,222 @@ +/* Copyright (C) 2000 MySQL AB + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + * Vio Lite. + * Purpose: include file for Vio that will work with C and C++ + */ + +#ifndef vio_violite_h_ +#define vio_violite_h_ + +#include "my_net.h" /* needed because of struct in_addr */ + + +/* Simple vio interface in C; The functions are implemented in violite.c */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +enum enum_vio_type +{ + VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET, VIO_TYPE_NAMEDPIPE, + VIO_TYPE_SSL, VIO_TYPE_SHARED_MEMORY +}; + + +#define VIO_LOCALHOST 1 /* a localhost connection */ +#define VIO_BUFFERED_READ 2 /* use buffered read */ +#define VIO_READ_BUFFER_SIZE 16384 /* size of read buffer */ + +Vio* vio_new(my_socket sd, enum enum_vio_type type, uint flags); +#ifdef __WIN__ +Vio* vio_new_win32pipe(HANDLE hPipe); +Vio* vio_new_win32shared_memory(NET *net,HANDLE handle_file_map, + HANDLE handle_map, + HANDLE event_server_wrote, + HANDLE event_server_read, + HANDLE event_client_wrote, + HANDLE event_client_read, + HANDLE event_conn_closed); +size_t vio_read_pipe(Vio *vio, uchar * buf, size_t size); +size_t vio_write_pipe(Vio *vio, const uchar * buf, size_t size); +int vio_close_pipe(Vio * vio); +#else +#define HANDLE void * +#endif /* __WIN__ */ + +void vio_delete(Vio* vio); +int vio_close(Vio* vio); +void vio_reset(Vio* vio, enum enum_vio_type type, + my_socket sd, HANDLE hPipe, uint flags); +size_t vio_read(Vio *vio, uchar * buf, size_t size); +size_t vio_read_buff(Vio *vio, uchar * buf, size_t size); +size_t vio_write(Vio *vio, const uchar * buf, size_t size); +int vio_blocking(Vio *vio, my_bool onoff, my_bool *old_mode); +my_bool vio_is_blocking(Vio *vio); +/* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible */ +int vio_fastsend(Vio *vio); +/* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible */ +int vio_keepalive(Vio *vio, my_bool onoff); +/* Whenever we should retry the last read/write operation. */ +my_bool vio_should_retry(Vio *vio); +/* Check that operation was timed out */ +my_bool vio_was_interrupted(Vio *vio); +/* Short text description of the socket for those, who are curious.. */ +const char* vio_description(Vio *vio); +/* Return the type of the connection */ +enum enum_vio_type vio_type(Vio* vio); +/* Return last error number */ +int vio_errno(Vio*vio); +/* Get socket number */ +my_socket vio_fd(Vio*vio); +/* Remote peer's address and name in text form */ +my_bool vio_peer_addr(Vio *vio, char *buf, uint16 *port, size_t buflen); +my_bool vio_poll_read(Vio *vio,uint timeout); +my_bool vio_peek_read(Vio *vio, uint *bytes); +ssize_t vio_pending(Vio *vio); + +#ifdef HAVE_OPENSSL +#include +#if OPENSSL_VERSION_NUMBER < 0x0090700f +#define DES_cblock des_cblock +#define DES_key_schedule des_key_schedule +#define DES_set_key_unchecked(k,ks) des_set_key_unchecked((k),*(ks)) +#define DES_ede3_cbc_encrypt(i,o,l,k1,k2,k3,iv,e) des_ede3_cbc_encrypt((i),(o),(l),*(k1),*(k2),*(k3),(iv),(e)) +#endif + +#define HEADER_DES_LOCL_H dummy_something +#define YASSL_MYSQL_COMPATIBLE +#ifndef YASSL_PREFIX +#define YASSL_PREFIX +#endif +/* Set yaSSL to use same type as MySQL do for socket handles */ +typedef my_socket YASSL_SOCKET_T; +#define YASSL_SOCKET_T_DEFINED +#include +#include + +#ifndef EMBEDDED_LIBRARY + +struct st_VioSSLFd +{ + SSL_CTX *ssl_context; +}; + +int sslaccept(struct st_VioSSLFd*, Vio *, long timeout); +int sslconnect(struct st_VioSSLFd*, Vio *, long timeout); + +struct st_VioSSLFd +*new_VioSSLConnectorFd(const char *key_file, const char *cert_file, + const char *ca_file, const char *ca_path, + const char *cipher); +struct st_VioSSLFd +*new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, + const char *ca_file,const char *ca_path, + const char *cipher); +void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd); +#endif /* ! EMBEDDED_LIBRARY */ +#endif /* HAVE_OPENSSL */ + +#ifdef HAVE_SMEM +size_t vio_read_shared_memory(Vio *vio, uchar * buf, size_t size); +size_t vio_write_shared_memory(Vio *vio, const uchar * buf, size_t size); +int vio_close_shared_memory(Vio * vio); +#endif + +void vio_end(void); + +#ifdef __cplusplus +} +#endif + +#if !defined(DONT_MAP_VIO) +#define vio_delete(vio) (vio)->viodelete(vio) +#define vio_errno(vio) (vio)->vioerrno(vio) +#define vio_read(vio, buf, size) ((vio)->read)(vio,buf,size) +#define vio_write(vio, buf, size) ((vio)->write)(vio, buf, size) +#define vio_blocking(vio, set_blocking_mode, old_mode)\ + (vio)->vioblocking(vio, set_blocking_mode, old_mode) +#define vio_is_blocking(vio) (vio)->is_blocking(vio) +#define vio_fastsend(vio) (vio)->fastsend(vio) +#define vio_keepalive(vio, set_keep_alive) (vio)->viokeepalive(vio, set_keep_alive) +#define vio_should_retry(vio) (vio)->should_retry(vio) +#define vio_was_interrupted(vio) (vio)->was_interrupted(vio) +#define vio_close(vio) ((vio)->vioclose)(vio) +#define vio_peer_addr(vio, buf, prt, buflen) (vio)->peer_addr(vio, buf, prt, buflen) +#define vio_timeout(vio, which, seconds) (vio)->timeout(vio, which, seconds) +#endif /* !defined(DONT_MAP_VIO) */ + +/* This enumerator is used in parser - should be always visible */ +enum SSL_type +{ + SSL_TYPE_NOT_SPECIFIED= -1, + SSL_TYPE_NONE, + SSL_TYPE_ANY, + SSL_TYPE_X509, + SSL_TYPE_SPECIFIED +}; + + +/* HFTODO - hide this if we don't want client in embedded server */ +/* This structure is for every connection on both sides */ +struct st_vio +{ + my_socket sd; /* my_socket - real or imaginary */ + HANDLE hPipe; + my_bool localhost; /* Are we from localhost? */ + int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */ + struct sockaddr_storage local; /* Local internet address */ + struct sockaddr_storage remote; /* Remote internet address */ + int addrLen; /* Length of remote address */ + enum enum_vio_type type; /* Type of connection */ + char desc[30]; /* String description */ + char *read_buffer; /* buffer for vio_read_buff */ + char *read_pos; /* start of unfetched data in the + read buffer */ + char *read_end; /* end of unfetched data */ + /* function pointers. They are similar for socket/SSL/whatever */ + void (*viodelete)(Vio*); + int (*vioerrno)(Vio*); + size_t (*read)(Vio*, uchar *, size_t); + size_t (*write)(Vio*, const uchar *, size_t); + int (*vioblocking)(Vio*, my_bool, my_bool *); + my_bool (*is_blocking)(Vio*); + int (*viokeepalive)(Vio*, my_bool); + int (*fastsend)(Vio*); + my_bool (*peer_addr)(Vio*, char *, uint16*, size_t); + void (*in_addr)(Vio*, struct sockaddr_storage*); + my_bool (*should_retry)(Vio*); + my_bool (*was_interrupted)(Vio*); + int (*vioclose)(Vio*); + void (*timeout)(Vio*, unsigned int which, unsigned int timeout); +#ifdef HAVE_OPENSSL + void *ssl_arg; +#endif +#ifdef HAVE_SMEM + HANDLE handle_file_map; + char *handle_map; + HANDLE event_server_wrote; + HANDLE event_server_read; + HANDLE event_client_wrote; + HANDLE event_client_read; + HANDLE event_conn_closed; + size_t shared_memory_remain; + char *shared_memory_pos; + NET *net; +#endif /* HAVE_SMEM */ +}; +#endif /* vio_violite_h_ */ diff --git a/NetService/include/Mysql/waiting_threads.h b/NetService/include/Mysql/waiting_threads.h new file mode 100644 index 00000000..1e580529 --- /dev/null +++ b/NetService/include/Mysql/waiting_threads.h @@ -0,0 +1,130 @@ +/* Copyright (C) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. + + 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _waiting_threads_h +#define _waiting_threads_h + +#include +#include + +#include + +C_MODE_START + +typedef struct st_wt_resource_id WT_RESOURCE_ID; +typedef struct st_wt_resource WT_RESOURCE; + +typedef struct st_wt_resource_type { + my_bool (*compare)(const void *a, const void *b); + const void *(*make_key)(const WT_RESOURCE_ID *id, uint *len); /* not used */ +} WT_RESOURCE_TYPE; + +struct st_wt_resource_id { + ulonglong value; + const WT_RESOURCE_TYPE *type; +}; +/* the below differs from sizeof(WT_RESOURCE_ID) by the amount of padding */ +#define sizeof_WT_RESOURCE_ID (sizeof(ulonglong)+sizeof(void*)) + +#define WT_WAIT_STATS 24 +#define WT_CYCLE_STATS 32 +extern ulonglong wt_wait_table[WT_WAIT_STATS]; +extern uint32 wt_wait_stats[WT_WAIT_STATS+1]; +extern uint32 wt_cycle_stats[2][WT_CYCLE_STATS+1]; +extern uint32 wt_success_stats; + +typedef struct st_wt_thd { + /* + XXX + there's no protection (mutex) against concurrent access of the + dynarray below. it is assumed that a caller will have it anyway + (not to protect this array but to protect its own - caller's - + data structures), and we'll get it for free. A caller needs to + ensure that a blocker won't release a resource before a blocked + thread starts waiting, which is usually done with a mutex. + + If the above assumption is wrong, we'll need to add a mutex here. + */ + DYNAMIC_ARRAY my_resources; + /* + 'waiting_for' is modified under waiting_for->lock, and only by thd itself + 'waiting_for' is read lock-free (using pinning protocol), but a thd object + can read its own 'waiting_for' without any locks or tricks. + */ + WT_RESOURCE *waiting_for; + LF_PINS *pins; + + /* pointers to values */ + const ulong *timeout_short; + const ulong *deadlock_search_depth_short; + const ulong *timeout_long; + const ulong *deadlock_search_depth_long; + + /* + weight relates to the desirability of a transaction being killed if it's + part of a deadlock. In a deadlock situation transactions with lower weights + are killed first. + + Examples of using the weight to implement different selection strategies: + + 1. Latest + Keep all weights equal. + 2. Random + Assight weights at random. + (variant: modify a weight randomly before every lock request) + 3. Youngest + Set weight to -NOW() + 4. Minimum locks + count locks granted in your lock manager, store the value as a weight + 5. Minimum work + depends on the definition of "work". For example, store the number + of rows modifies in this transaction (or a length of REDO log for a + transaction) as a weight. + + It is only statistically relevant and is not protected by any locks. + */ + ulong volatile weight; + /* + 'killed' is indirectly protected by waiting_for->lock because + a killed thread needs to clear its 'waiting_for' and thus needs a lock. + That is a thread needs an exclusive lock to read 'killed' reliably. + But other threads may change 'killed' from 0 to 1, a shared + lock is enough for that. + */ + my_bool killed; +#ifndef DBUG_OFF + const char *name; +#endif +} WT_THD; + +#define WT_TIMEOUT ETIMEDOUT +#define WT_OK 0 +#define WT_DEADLOCK -1 +#define WT_DEPTH_EXCEEDED -2 +#define WT_FREE_TO_GO -3 + +void wt_init(void); +void wt_end(void); +void wt_thd_lazy_init(WT_THD *, const ulong *, const ulong *, const ulong *, const ulong *); +void wt_thd_destroy(WT_THD *); +int wt_thd_will_wait_for(WT_THD *, WT_THD *, const WT_RESOURCE_ID *); +int wt_thd_cond_timedwait(WT_THD *, pthread_mutex_t *); +void wt_thd_release(WT_THD *, const WT_RESOURCE_ID *); +#define wt_thd_release_all(THD) wt_thd_release((THD), 0) +my_bool wt_resource_id_memcmp(const void *, const void *); + +C_MODE_END + +#endif diff --git a/NetService/include/Mysql/wqueue.h b/NetService/include/Mysql/wqueue.h new file mode 100644 index 00000000..658f3d66 --- /dev/null +++ b/NetService/include/Mysql/wqueue.h @@ -0,0 +1,27 @@ + +#ifndef _wqueue_h +#define _wqueue_h + +#include +#include + +/* info about requests in a waiting queue */ +typedef struct st_pagecache_wqueue +{ + struct st_my_thread_var *last_thread; /* circular list of waiting + threads */ +} WQUEUE; + +#ifdef THREAD +void wqueue_link_into_queue(WQUEUE *wqueue, struct st_my_thread_var *thread); +void wqueue_unlink_from_queue(WQUEUE *wqueue, struct st_my_thread_var *thread); +void wqueue_add_to_queue(WQUEUE *wqueue, struct st_my_thread_var *thread); +void wqueue_add_and_wait(WQUEUE *wqueue, + struct st_my_thread_var *thread, + pthread_mutex_t *lock); +void wqueue_release_queue(WQUEUE *wqueue); +void wqueue_release_one_locktype_from_queue(WQUEUE *wqueue); + +#endif + +#endif diff --git a/NetService/lib/libmysql.lib b/NetService/lib/libmysql.lib new file mode 100644 index 00000000..228f31a2 Binary files /dev/null and b/NetService/lib/libmysql.lib differ diff --git a/NetService/lib/mysqlclient.lib b/NetService/lib/mysqlclient.lib new file mode 100644 index 00000000..84c88f04 Binary files /dev/null and b/NetService/lib/mysqlclient.lib differ diff --git a/NetService/lib64/libmysql.lib b/NetService/lib64/libmysql.lib new file mode 100644 index 00000000..8cf07eac Binary files /dev/null and b/NetService/lib64/libmysql.lib differ diff --git a/NetService/lib64/mysqlclient.lib b/NetService/lib64/mysqlclient.lib new file mode 100644 index 00000000..c08858a4 Binary files /dev/null and b/NetService/lib64/mysqlclient.lib differ diff --git a/NetService/makefile b/NetService/makefile index dc1c759b..61c9bca8 100644 --- a/NetService/makefile +++ b/NetService/makefile @@ -1,22 +1,32 @@ # author by AngryPowman, for VNOC server -# revision : 3 +# revision : 4 +# revisioned by Tydus CXX=g++ -VPATH=src:test:../Message:../program_options -CXXFLAGS=-std=c++0x -CUR_DIR = $(shell pwd) -INCS := $(CUR_DIR)/include -Server_OBJ=VNOCServer.o NetService.o AsioTcpServer.o MessageParser.o PackMessage.o MsgDef.o VnocProtocol.o +LD=g++ +VPATH=src:test:../Message:../program_options:src/mysql +CUR_DIR := $(shell pwd) +INCS := -I$(CUR_DIR)/include -I$(CUR_DIR)/dependencies/build/include +LIBS := -L$(CUR_DIR)/lib -L$(CUR_DIR)/dependencies/build/lib + +CXXFLAGS=-std=c++0x $(INCS) +LDFLAGS := $(LIBS) + +PO_OBJ=cmdline.o options_description.o utf8_codecvt_facet.o config_file.o parsers.o value_semantic.o convert.o positional_options.o variables_map.o split.o +Server_OBJ=VNOCServer.o NetService.o AsioTcpServer.o MessageParser.o PackMessage.o MsgDef.o VnocProtocol.o Config.o UserManage.o UserStorage.o SQLUserStorage.o FileUserStorage.o MysqlWrapper.o $(PO_OBJ) + +all : Server EchoTestServer + %.o : %.cpp - $(CXX) -c $(CXXFLAGS) -I$(INCS) $< -o $@ + $(CXX) -c $(CXXFLAGS) $< -o $@ -all : Server test_bin Server : $(Server_OBJ) - $(CXX) -lpthread $^ -o bin/$@ -test_bin: EchoTestServer + mkdir -p bin + $(LD) $(LIBS) -lpthread -lmysql $^ -o bin/$@ EchoTestServer : EchoTestServer.o AsioTcpServer.o - $(CXX) -lpthread $^ -o bin/$@ + mkdir -p bin + $(LD) $(LIBS) -lpthread $^ -o bin/$@ clean : rm -fr bin/* - rm -f *.o + rm -f *.o *.obj diff --git a/NetService/msgdef.xml b/NetService/msgdef.xml new file mode 100644 index 00000000..e59c01d5 --- /dev/null +++ b/NetService/msgdef.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NetService/server.sln b/NetService/server.sln index 03df3ec5..16496dbe 100644 --- a/NetService/server.sln +++ b/NetService/server.sln @@ -5,11 +5,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server", "server.vcxproj", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EchoTestServer", "EchoTestServer\EchoTestServer.vcxproj", "{111C4F30-3E77-FA0D-1C5E-B1E1B2B15020}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cppunit_dll", "..\cppunit-1.12.1\src\cppunit\cppunit_dll.vcxproj", "{5292D033-ECD7-A1D5-1E11-D3E0004BA81B}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cppunit", "..\cppunit-1.12.1\src\cppunit\cppunit.vcxproj", "{9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testRunner", "src\test\testRunner\testRunner.vcxproj", "{B8DED7FE-BF81-4F18-932D-A7D430EB436C}" + ProjectSection(ProjectDependencies) = postProject + {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E} = {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +22,18 @@ Global Template|x64 = Template|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Debug|Win32.ActiveCfg = Debug|Win32 + {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Debug|Win32.Build.0 = Debug|Win32 + {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Debug|x64.ActiveCfg = Debug|x64 + {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Debug|x64.Build.0 = Debug|x64 + {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Release|Win32.ActiveCfg = Release|Win32 + {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Release|Win32.Build.0 = Release|Win32 + {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Release|x64.ActiveCfg = Release|x64 + {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Release|x64.Build.0 = Release|x64 + {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Template|Win32.ActiveCfg = Release|Win32 + {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Template|Win32.Build.0 = Release|Win32 + {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Template|x64.ActiveCfg = Release|x64 + {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Template|x64.Build.0 = Release|x64 {111C4F30-3E77-FA0D-1C5E-B1E1B2B15020}.Debug|Win32.ActiveCfg = Debug|Win32 {111C4F30-3E77-FA0D-1C5E-B1E1B2B15020}.Debug|Win32.Build.0 = Debug|Win32 {111C4F30-3E77-FA0D-1C5E-B1E1B2B15020}.Debug|x64.ActiveCfg = Debug|x64 @@ -33,18 +46,6 @@ Global {111C4F30-3E77-FA0D-1C5E-B1E1B2B15020}.Template|Win32.Build.0 = Release|Win32 {111C4F30-3E77-FA0D-1C5E-B1E1B2B15020}.Template|x64.ActiveCfg = Release|x64 {111C4F30-3E77-FA0D-1C5E-B1E1B2B15020}.Template|x64.Build.0 = Release|x64 - {5292D033-ECD7-A1D5-1E11-D3E0004BA81B}.Debug|Win32.ActiveCfg = Debug|Win32 - {5292D033-ECD7-A1D5-1E11-D3E0004BA81B}.Debug|Win32.Build.0 = Debug|Win32 - {5292D033-ECD7-A1D5-1E11-D3E0004BA81B}.Debug|x64.ActiveCfg = Debug|x64 - {5292D033-ECD7-A1D5-1E11-D3E0004BA81B}.Debug|x64.Build.0 = Debug|x64 - {5292D033-ECD7-A1D5-1E11-D3E0004BA81B}.Release|Win32.ActiveCfg = Release|Win32 - {5292D033-ECD7-A1D5-1E11-D3E0004BA81B}.Release|Win32.Build.0 = Release|Win32 - {5292D033-ECD7-A1D5-1E11-D3E0004BA81B}.Release|x64.ActiveCfg = Release|x64 - {5292D033-ECD7-A1D5-1E11-D3E0004BA81B}.Release|x64.Build.0 = Release|x64 - {5292D033-ECD7-A1D5-1E11-D3E0004BA81B}.Template|Win32.ActiveCfg = Template|Win32 - {5292D033-ECD7-A1D5-1E11-D3E0004BA81B}.Template|Win32.Build.0 = Template|Win32 - {5292D033-ECD7-A1D5-1E11-D3E0004BA81B}.Template|x64.ActiveCfg = Template|x64 - {5292D033-ECD7-A1D5-1E11-D3E0004BA81B}.Template|x64.Build.0 = Template|x64 {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.Debug|Win32.ActiveCfg = Debug|Win32 {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.Debug|Win32.Build.0 = Debug|Win32 {9F0E65B5-A837-D35E-CDB7-44DE0889EE9E}.Debug|x64.ActiveCfg = Debug|x64 @@ -69,18 +70,6 @@ Global {B8DED7FE-BF81-4F18-932D-A7D430EB436C}.Template|Win32.Build.0 = Release|Win32 {B8DED7FE-BF81-4F18-932D-A7D430EB436C}.Template|x64.ActiveCfg = Release|x64 {B8DED7FE-BF81-4F18-932D-A7D430EB436C}.Template|x64.Build.0 = Release|x64 - {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Debug|Win32.ActiveCfg = Debug|Win32 - {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Debug|Win32.Build.0 = Debug|Win32 - {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Debug|x64.ActiveCfg = Debug|x64 - {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Debug|x64.Build.0 = Debug|x64 - {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Release|Win32.ActiveCfg = Release|Win32 - {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Release|Win32.Build.0 = Release|Win32 - {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Release|x64.ActiveCfg = Release|x64 - {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Release|x64.Build.0 = Release|x64 - {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Template|Win32.ActiveCfg = Release|Win32 - {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Template|Win32.Build.0 = Release|Win32 - {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Template|x64.ActiveCfg = Release|x64 - {D19666CB-CB3B-49CD-4968-C85337B74D8A}.Template|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/NetService/server.vcxproj b/NetService/server.vcxproj index b4c47054..3c1336ae 100644 --- a/NetService/server.vcxproj +++ b/NetService/server.vcxproj @@ -72,6 +72,8 @@ true $(MSBuildProjectDirectory)/include;$(IncludePath) + $(ReferencePath) + $(ProjectDir)/lib;$(LibraryPath) true @@ -80,9 +82,11 @@ false $(MSBuildProjectDirectory)/include;$(IncludePath) + $(ProjectDir)/lib;$(LibraryPath) false + $(MSBuildProjectDirectory)/include;$(IncludePath) @@ -95,7 +99,7 @@ Console true - ../VisualLeakDetector/lib/win32/vld.lib;%(AdditionalDependencies) + ../ThirdLibs/VisualLeakDetector/lib/win32/vld.lib;$(ProjectDir)/lib/libmysql.lib;%(AdditionalDependencies) @@ -130,6 +134,7 @@ true true WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_WIN32_WINNT=0x0501;BOOST_ALL_NO_LIB;%(PreprocessorDefinitions) + MultiThreaded Console @@ -152,7 +157,7 @@ MaxSpeed true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;BOOST_ALL_NO_LIB;%(PreprocessorDefinitions) Console @@ -162,22 +167,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + @@ -189,11 +231,23 @@ + + + + + + + + + + + + diff --git a/NetService/server.vcxproj.filters b/NetService/server.vcxproj.filters index 378a7eff..b816f723 100644 --- a/NetService/server.vcxproj.filters +++ b/NetService/server.vcxproj.filters @@ -1,111 +1,285 @@  + + modules + + + modules\room + + + modules\room + + + modules\obj + + + modules\room + + + modules\room + + + handlers + + + handlers + + + handlers + - header + service - header + service - - header + + service + + + config + + + service + + + common + + + database + + + database + + + database - header + service + + + database + + + database + + + database + + + service - header + common - - header + + message - - header + + message - - header + + message - - header + + message - - header + + message\MsgDataValue + + + message\MsgDataValue + + + message\MsgDataValue + + + message\MsgDataValue + + + message\MsgDataValue + + + message + + + message + + + message + + + message + + + message + + + message + + + message + + + Tinyxml + + + Tinyxml - - - source - - - source - - - source - - - source - - - source - - - source - - - source - - source\po + common\po - source\po + common\po - source\po + common\po - source\po + common\po - source\po + common\po - source\po + common\po - source\po + common\po - source\po + common\po - source\po + common\po - source\po + common\po - source\po + common\po + + + modules\room + + + modules\room + + + modules\obj + + + service + + + + service + + + service + + + database + + + database + + + database + + + database + + + database - source + config + + + message + + + message + + + message + + + message\MsgDataValue + + + message\MsgDataValue + + + message\MsgDataValue + + + message + + + message + + + message + + + Tinyxml + + + Tinyxml + + + Tinyxml + + + Tinyxml - - {c6301850-38aa-4a4c-978f-a2463b9e0c87} + + {bb5a4351-106e-413d-8eff-2ce37b97bd8c} + + + {22bc2e4a-f0a8-4e88-afd0-f89104921b77} + + + {ffa6ecef-1bba-4e99-81ca-aee1b537d022} + + + {507323fa-5a96-4da0-b999-afb35d6b8ed6} + + + {f4513da3-85ef-48ab-958e-6f1ef56a8483} - - {393855ef-cd99-460d-b224-78fd97847471} + + {1fa30f25-1661-46e4-8224-9ba60b64c9a4} - + + {92577f27-b8e6-42e9-9ffd-bd169d758e28} + + + {5ccd4261-0374-44c1-861c-61b0aa95e1e4} + + + {3024ed16-4ff3-4cc4-b9bc-df016cf13f03} + + {def1898a-4f9c-4311-bf47-46283aca1628} + + {ffcd399b-b376-49d1-8c27-c4a83d0867ba} + + + {612edc88-d65f-4513-a139-0d3150d54afe} + - header + service \ No newline at end of file diff --git a/NetService/src/AsioTcpConnection.hpp b/NetService/src/AsioTcpConnection.hpp index 75ff509b..7e79df84 100644 --- a/NetService/src/AsioTcpConnection.hpp +++ b/NetService/src/AsioTcpConnection.hpp @@ -10,7 +10,7 @@ class AsioTcpConnection: public Connection asio::ip::tcp::socket& socket(){return socket_;} template int recv(char * buf, size_t len, Handler handler) { - socket_.async_receive(asio::buffer(buf, len), handler); + async_read(socket_, asio::buffer(buf, len), handler); return 0; } template int read_some(char * buf, size_t len, Handler handler) diff --git a/NetService/src/AsioTcpServer.cpp b/NetService/src/AsioTcpServer.cpp index 3c0b15e7..baff38d4 100644 --- a/NetService/src/AsioTcpServer.cpp +++ b/NetService/src/AsioTcpServer.cpp @@ -5,12 +5,17 @@ #include #include "asio.hpp" #include +#include using namespace asio; using namespace asio::ip; using namespace std; static asio::io_service g_io_service; - +void TermHandler(int para) +{ + cout<<"term server"<CreateHandler(conn); - handler->start(); - - AsioTcpConnection* new_connection(new AsioTcpConnection(io_service_)); - acceptor_.async_accept(new_connection->socket(), - std::bind(&AsioTcpServer::AcceptHandler, this ,new_connection, - std::placeholders::_1)); - } else - { - EZLOGGERSTREAM<CreateHandler(conn); + handler->start(); + + new_connection_ = new AsioTcpConnection(io_service_); + acceptor_.async_accept(new_connection_->socket(), + std::bind(&AsioTcpServer::AcceptHandler, this ,new_connection_, + std::placeholders::_1)); + } else + { + EZLOGGERSTREAM<socket(), - std::bind(&AsioTcpServer::AcceptHandler, this ,new_connection, + new_connection_ = new AsioTcpConnection(io_service_); + acceptor_.async_accept(new_connection_->socket(), + std::bind(&AsioTcpServer::AcceptHandler, this ,new_connection_, std::placeholders::_1)); std::thread t(&AsioTcpServer::worker, this); t.join(); diff --git a/NetService/src/AsioTcpServer.hpp b/NetService/src/AsioTcpServer.hpp index 85e5e085..ac2a4050 100644 --- a/NetService/src/AsioTcpServer.hpp +++ b/NetService/src/AsioTcpServer.hpp @@ -1,6 +1,6 @@ #ifndef ASIOTCPSERVER_H_ #define ASIOTCPSERVER_H_ - +#include #include "asio.hpp" #include "SocketServer.hpp" #include "AsioTcpConnection.hpp" @@ -16,8 +16,9 @@ class AsioTcpServer :public SocketServer asio::io_service& io_service_; asio::ip::tcp::acceptor acceptor_; SocketHandlerFactory* handlerFactory_; + AsioTcpConnection *new_connection_; void worker(); - void AcceptHandler( AsioTcpConnection* conn, const asio::error_code& error); + void AcceptHandler( AsioTcpConnection *conn, const asio::error_code& error); }; diff --git a/NetService/src/Common.h b/NetService/src/Common.h new file mode 100644 index 00000000..46bfa57e --- /dev/null +++ b/NetService/src/Common.h @@ -0,0 +1,67 @@ +#ifndef VNOC_COMMON_H_ +#define VNOC_COMMON_H_ + +typedef unsigned int GUID_t; + +//stl +#include +#include +#include +#include +#include +#include + +using namespace std; + +//socket dependencies +#if defined(_WIN32) +#include +#pragma comment(lib, "Ws2_32.lib") +#else +#include +#include +#endif + +//debug +#include + +//Datatypes +#if defined(_WIN32) //for windows +#ifndef byte +typedef unsigned __int8 byte; +#endif +typedef __int8 int8; +typedef __int16 int16; +typedef __int32 int32; +typedef __int64 int64; +typedef unsigned __int32 uint; +typedef unsigned __int8 uint8; +typedef unsigned __int16 uint16; +typedef unsigned __int32 uint32; +typedef unsigned __int64 uint64; +#else +#ifndef byte +typedef unsigned char byte; +#endif +typedef char int8; +typedef short int16; +typedef int int32; +typedef long long int64; +typedef unsigned int uint; +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef unsigned long long uint64; +#endif + +//Lines +#if defined(_WIN32) +#define NEWLINE "\r\n" +#else +#define NEWLINE "\n" +#endif + +#ifndef SAFE_DELETE +#define SAFE_DELETE(x) if(NULL != (x)) { delete (x); (x)=NULL; } +#endif +#endif \ No newline at end of file diff --git a/NetService/src/Config.cpp b/NetService/src/Config.cpp index 0cd01280..1519226b 100644 --- a/NetService/src/Config.cpp +++ b/NetService/src/Config.cpp @@ -12,6 +12,11 @@ bool Config::Initialize(std::string config_file) po::options_description config("Configuration"); config.add_options() ("port", po::value(), "server port") + ("sql_host", po::value(), "sql host") + ("sql_port", po::value(), "sql port") + ("sql_username", po::value(), "sql db username") + ("sql_password", po::value(), "sql password") + ("user_db", po::value(), "sql database name for user information") ; po::options_description config_file_options; @@ -21,7 +26,7 @@ bool Config::Initialize(std::string config_file) EZLOGGERVLSTREAM(axter::log_often) << "can not open config file: " << config_file << "\n"; return 0; } else { - store(po::parse_config_file(ifs, config_file_options), vm_); + store(po::parse_config_file(ifs, config_file_options, true), vm_); notify(vm_); } return true; diff --git a/NetService/src/FileUserStorage.cpp b/NetService/src/FileUserStorage.cpp new file mode 100644 index 00000000..461ab4dc --- /dev/null +++ b/NetService/src/FileUserStorage.cpp @@ -0,0 +1,49 @@ +#include "FileUserStorage.h" + +fUserStorage::fUserStorage() +{ +} + +fUserStorage::~fUserStorage() +{ +} + + + +bool fUserStorage::IfUserExist(const char* pUser) +{ + for (int i = 0; i < nUserCount; i++) + { + if ( strcmp(pUserTable[i].strUser, pUser) == 0) + { + return true; + } + } + return false; +} +bool fUserStorage::GetPassword(const char* pUser, char* pPassWordBuff, size_t cbBuff) +{ + for (int i = 0; i < nUserCount; i++) + { + if ( strcmp(pUserTable[i].strUser, pUser) == 0) + { + memcpy(pPassWordBuff, pUserTable[i].passwordData, cbBuff); + return true; + } + } + return false; +} +bool fUserStorage::GetUserInfo(const char* pUser, userinfo* pUserInfo) +{ + userinfo *p = pUserTable; + for (int i = 0; i < nUserCount; i++) + { + if ( strcmp(pUserTable[i].strUser, pUser) == 0) + { + memcpy(pUserInfo, p, sizeof(userinfo)); + return true; + } + ++p; + } + return false; +} \ No newline at end of file diff --git a/NetService/src/FileUserStorage.h b/NetService/src/FileUserStorage.h new file mode 100644 index 00000000..46608b55 --- /dev/null +++ b/NetService/src/FileUserStorage.h @@ -0,0 +1,21 @@ +#pragma once +#include +#include "UserStorage.h" + + +class fUserStorage :public UserStorage + +{ +public: + fUserStorage(); + ~fUserStorage(); + //ij + bool IfUserExist(const char* pUser); + bool GetPassword(const char* pUser, char* pPassWordBuff, size_t cbBuff); + bool GetUserInfo(const char* pUser, userinfo* pUserInfo); + +private: + int nUserCount; + userinfo *pUserTable; +}; + diff --git a/NetService/src/GlobalDefinition.h b/NetService/src/GlobalDefinition.h new file mode 100644 index 00000000..37e57e39 --- /dev/null +++ b/NetService/src/GlobalDefinition.h @@ -0,0 +1,30 @@ +#ifndef VNOC_GLOBAL_DEFINITION_H_ +#define VNOC_GLOBAL_DEFINITION_H_ + +//ض +#define MAX_ROOM_USER_LIMIT 1024 //ѧ +#define MAX_ROOM_NAME_LEN 12 //󳤶 +#define MAX_NICKNAME_LEN 16 //dz󳤶 + +// +#define DEFAULT_ROOM_POOL_SIZE 256 //سʼС +#define DEFAULT_ROOM_POOL_INCREASE_SIZE 100 //ÿߴ + +typedef uint32 RoomID_t; + +// +enum VNOCUserType +{ + UT_UNCERTAIN = 0, //δЧδ֪ + UT_TEACHER = 1, //ѧ + UT_STUDENT = 2 //ʦ +}; + +//Ȩ +enum VNOCUserPermission +{ + PER_CHAT = 0, + +}; + +#endif \ No newline at end of file diff --git a/NetService/src/NetService.cpp b/NetService/src/NetService.cpp index 2f5d660b..16cb715e 100644 --- a/NetService/src/NetService.cpp +++ b/NetService/src/NetService.cpp @@ -9,6 +9,8 @@ #include "VnocMessageSocketHandler.hpp" #include "RliMessageHandler.hpp" #include "RvcMessageHandler.hpp" +#include "RclMessageHandler.hpp" + using namespace std; @@ -29,7 +31,7 @@ bool NetService::start(unsigned int u_port) VnocMessageHandlerFactory socketHandlerFactory(protocol_); RliMessageHandler rliHandler(protocol_); RvcMessageHandler rvcHandler(protocol_); - + RclMessageHandler rclHandler(protocol_); server_= new AsioTcpServer(protocol_->getSocketHandlerFactory()); server_->start(u_port); return true; diff --git a/NetService/src/RclMessageHandler.hpp b/NetService/src/RclMessageHandler.hpp new file mode 100644 index 00000000..02856cae --- /dev/null +++ b/NetService/src/RclMessageHandler.hpp @@ -0,0 +1,47 @@ +#pragma once +#include "VnocProtocol.hpp" +//#include "UserManage.hpp" +#include "Room.h" + +class RclMessageHandler : public IMessageHandler +{ +public: + RclMessageHandler(VnocProtocol *protocol):protocol_(protocol) + { + protocol_->RegisterMessageHandler(this); + } + virtual VMsg getMessageType() const + { + return MSG_RequestClassList_Id; + } + virtual int operator()(const CMessage *msg, MessageContext *ctx) + { + std::cout << "handle RclMessageHandler" << endl; + MSG_AnswerClassList aclMessage; + MSG_RequestClassList rclMessage(*msg); + + //temporary room data + std::vector roomList; + std::vector roomNameList; + std::vector roomStateList; + //roomList.resize(100); + for (uint32 i = 0; i < 200; ++i) + { + //Room& room = roomList[i]; + //room.setRoomID(10000 + i); + //room.setPoolObjId(i); + //room.setIsValid(true); + roomList.push_back(10000 + i); + roomNameList.push_back("!!!"); + roomStateList.push_back(i); + } + + aclMessage.SetRoomIdList(roomList); + aclMessage.SetRoomNameList(roomNameList); + aclMessage.SetRoomStateList(roomStateList); + protocol_->SendVnocMessage(&aclMessage, ctx); + return 1; + } +private: + VnocProtocol *protocol_; +}; \ No newline at end of file diff --git a/NetService/src/RliMessageHandler.hpp b/NetService/src/RliMessageHandler.hpp index 148f5c47..4041a17e 100644 --- a/NetService/src/RliMessageHandler.hpp +++ b/NetService/src/RliMessageHandler.hpp @@ -1,5 +1,7 @@ #pragma once #include "VnocProtocol.hpp" +#include "UserManage.hpp" +#include class RliMessageHandler : public IMessageHandler { @@ -8,17 +10,58 @@ class RliMessageHandler : public IMessageHandler { protocol_->RegisterMessageHandler(this); } - virtual MSGTYPE getMessageType() const + + virtual VMsg getMessageType() const { - return MSG_RLI_TYPE; + return MSG_RequestLogin_Id; } + virtual int operator()(const CMessage *msg, MessageContext *ctx) { - MSG_ALI aliMessage; - aliMessage.SetLoginResult(0); + int LoginResult; + MSG_AnswerLogin aliMessage; + std::string strAccountNumber; + std::string strPassword; + MSG_RequestLogin rliMessage(*msg); + userinfo UserInfo = {0}; + rliMessage.GetAccountNumber(strAccountNumber); + rliMessage.GetPassword(strPassword); + LoginResult = CUserManage::GetInstance()->Authenticate(strAccountNumber.c_str(), strPassword.c_str(), &UserInfo); + if (LOGIN_OK == LoginResult) + { + aliMessage.SetLoginResult(0); //½ɹ + ctx->userName = strAccountNumber; + EZLOGGERVLSTREAM(axter::log_often)<<"User's account login successfully. (RLI)"<userName<< + " (RLI)"<SendVnocMessage(&aliMessage, ctx); + EZLOGGERVLSTREAM(axter::log_often)<<"Server had geted RLI and had sended ALI to client. (RLI)"<getUniqueID(); + + if (isFull() == false) + { + if (isUserExists(userId) == false) + { + _userMap.insert(std::make_pair(userId, user)); + return true; + } + else + { + //student exist + return false; + } + } + + return false; +} + +bool Room::removeUser(GUID_t guid) +{ + auto iter = _userMap.find(guid); + if (iter != _userMap.end()) + { + _userMap.erase(iter); + return true; + } + + return false; +} + +bool Room::isUserExists(GUID_t studentId) const +{ + auto iter = _userMap.find(studentId); + if (iter != _userMap.end()) + { + return true; + } + + return false; +} + +bool Room::isFull() const +{ + if (getOnlineCount() >= getMaxUserCount()) + { + return true; + } + + return false; +} + +VNOCUser* Room::getUser(GUID_t guid) +{ + if (isUserExists(guid) == true) + { + auto iter = _userMap.find(guid); + return iter->second; + } + + return NULL; +} + +const VNOCUserMap& Room::getUserMap() const +{ + return _userMap; +} + +void Room::setPoolObjId(uint32 poolObjId) +{ + _poolObjId = poolObjId; +} + +uint32 Room::getPoolObjId() const +{ + return _poolObjId; +} + +void Room::setIsValid(bool valid) +{ + _isValid = valid; +} + + +bool Room::getIsValid() const +{ + return _isValid; +} \ No newline at end of file diff --git a/NetService/src/Room.h b/NetService/src/Room.h new file mode 100644 index 00000000..1f2d6464 --- /dev/null +++ b/NetService/src/Room.h @@ -0,0 +1,49 @@ +#ifndef VNOC_ROOM_H_ +#define VNOC_ROOM_H_ + +#include "Common.h" +#include "GlobalDefinition.h" + +class VNOCUser; + +typedef std::map VNOCUserMap; + +class Room +{ +public: + Room(); + ~Room(); + +public: + void cleanup(); + +public: + GUID_t getRoomID() const; + void setRoomID(GUID_t roomId); + void setMaxUserCount(uint16 maxCount); + uint16 getMaxUserCount() const; + void setRoomName(std::string roomName); + std::string getRoomName() const; + uint16 getOnlineCount() const; + bool addUser(VNOCUser* user); + bool removeUser(GUID_t guid); + bool isUserExists(GUID_t guid) const; + bool isFull() const; + VNOCUser* getUser(GUID_t guid); + const VNOCUserMap& getUserMap() const; + void setPoolObjId(uint32 poolObjId); + uint32 getPoolObjId() const; + void setIsValid(bool valid); + bool getIsValid() const; + +private: + RoomID_t _roomId; + VNOCUserMap _userMap; + uint16 _maxUserCount; + std::string _roomName; + static Room _instance; + uint32 _poolObjId; + bool _isValid; +}; + +#endif \ No newline at end of file diff --git a/NetService/src/RoomManager.cpp b/NetService/src/RoomManager.cpp new file mode 100644 index 00000000..d72f4bbd --- /dev/null +++ b/NetService/src/RoomManager.cpp @@ -0,0 +1,74 @@ +#include "RoomManager.h" +#include "Room.h" + +RoomManager RoomManager::_instance; + +RoomManager::RoomManager(void) +{ +} + + +RoomManager::~RoomManager(void) +{ +} + +RoomManager& RoomManager::instance() +{ + return _instance; +} + + +void RoomManager::init() +{ + +} + +void RoomManager::fini() +{ + +} + +void RoomManager::release() +{ + +} + +//manage +bool RoomManager::add(Room* room) +{ + assert(room != NULL); + + _roomMap[room->getRoomID()] = room; + + return true; +} + +bool RoomManager::remove(Room* room) +{ + assert(room != NULL); + + return remove(room->getRoomID()); +} + +bool RoomManager::remove(RoomID_t roomId) +{ + auto iter = _roomMap.find(roomId); + if (iter != _roomMap.end()) + { + _roomMap.erase(iter); + return true; + } + + return false; +} + +Room* RoomManager::getRoom(RoomID_t roomId) +{ + auto iter = _roomMap.find(roomId); + if (iter != _roomMap.end()) + { + return iter->second; + } + + return NULL; +} \ No newline at end of file diff --git a/NetService/src/RoomManager.h b/NetService/src/RoomManager.h new file mode 100644 index 00000000..3dc303ed --- /dev/null +++ b/NetService/src/RoomManager.h @@ -0,0 +1,39 @@ +#ifndef VNOC_ROOM_MANAGER_H_ +#define VNOC_ROOM_MANAGER_H_ + +#include "Common.h" +#include "GlobalDefinition.h" + +class Room; +class RoomManager +{ + typedef std::map RoomMap; + +public: + static RoomManager& instance(); + ~RoomManager(); + +private: + RoomManager(); + +public: + void init(); + void fini(); + void release(); + + //obj + Room* acquire(); + + //manage + bool add(Room* room); + bool remove(Room* room); + bool remove(RoomID_t roomId); + Room* getRoom(RoomID_t roomId); + +private: + RoomMap _roomMap; + static RoomManager _instance; +}; + +#endif + diff --git a/NetService/src/RoomPool.cpp b/NetService/src/RoomPool.cpp new file mode 100644 index 00000000..52c1a117 --- /dev/null +++ b/NetService/src/RoomPool.cpp @@ -0,0 +1,105 @@ +#include "Room.h" +#include "RoomPool.h" + +RoomPool::RoomPool() +{ + _poolSize = 0; + _incrPoolSize = 0; + _offset = 0; +} + +RoomPool::~RoomPool() +{ + destroy(); +} + +bool RoomPool::initPool(uint32 size/* = DEFAULT_ROOM_POOL_SIZE*/, uint32 incrSize/* = DEFAULT_ROOM_POOL_INCREASE_SIZE*/) +{ + if (size == 0 || incrSize == 0) + { + return false; + } + + _poolSize = size; + _incrPoolSize = incrSize; + _offset = 0; + + _roomObjPool.reserve(_poolSize); + for (uint32 i = 0; i < _poolSize; ++i) + { + Room* room = new Room(); + room->cleanup(); + _roomObjPool.push_back(room); + } + + return true; +} + +void RoomPool::destroy() +{ + for (uint32 i = 0; i < _roomObjPool.size(); ++i) + { + SAFE_DELETE(_roomObjPool[i]); + } + + _roomObjPool.clear(); +} + +Room* RoomPool::acquire() +{ + if (_offset >= _poolSize) + { + uint32 increasedSize = _poolSize + _incrPoolSize; + _roomObjPool.reserve(increasedSize); + for (uint32 i = _poolSize; i < increasedSize; ++i) + { + Room* room = new Room(); + _roomObjPool.push_back(room); + } + + _poolSize = increasedSize; + } + + Room* room = _roomObjPool[_offset]; + if (room != NULL && room->getIsValid() == false) + { + room->setPoolObjId(_offset); + room->setRoomID(_offset); + room->setIsValid(true); + + _offset++; + + return room; + } + + return NULL; +} + +void RoomPool::release(uint32 poolObjId) +{ + if (_roomObjPool[poolObjId] == NULL) + { + return; + } + + if (poolObjId >= _offset) + { + return; + } + + _offset--; + Room* releaseRoomPtr = _roomObjPool[poolObjId]; + if (poolObjId == _offset) + { + releaseRoomPtr->cleanup(); + } + else + { + // exchange pointer + _roomObjPool[poolObjId] = _roomObjPool[_offset]; + _roomObjPool[_offset] = releaseRoomPtr; + _roomObjPool[poolObjId]->setPoolObjId(poolObjId); + + releaseRoomPtr->cleanup(); + } +} \ No newline at end of file diff --git a/NetService/src/RoomPool.h b/NetService/src/RoomPool.h new file mode 100644 index 00000000..d4252c2a --- /dev/null +++ b/NetService/src/RoomPool.h @@ -0,0 +1,29 @@ +#ifndef VNOC_ROOM_POOL_H_ +#define VNOC_ROOM_POOL_H_ + +#include "Common.h" +#include "GlobalDefinition.h" + +class Room; +class RoomPool +{ +public: + RoomPool(); + ~RoomPool(); + +public: + bool initPool(uint32 size = DEFAULT_ROOM_POOL_SIZE, uint32 incrSize = DEFAULT_ROOM_POOL_INCREASE_SIZE); + void destroy(); + Room* acquire(); + void release(uint32 poolObjId); + +private: + std::vector _roomObjPool; + uint32 _poolSize; + uint32 _incrPoolSize; + uint32 _offset; + +}; + + +#endif \ No newline at end of file diff --git a/NetService/src/RvcMessageHandler.hpp b/NetService/src/RvcMessageHandler.hpp index e358a889..8b9fc58f 100644 --- a/NetService/src/RvcMessageHandler.hpp +++ b/NetService/src/RvcMessageHandler.hpp @@ -1,5 +1,6 @@ #pragma once #include "VnocProtocol.hpp" +#include class RvcMessageHandler: public IMessageHandler { @@ -8,20 +9,24 @@ class RvcMessageHandler: public IMessageHandler { protocol_->RegisterMessageHandler(this); } - virtual MSGTYPE getMessageType() const + + virtual VMsg getMessageType() const { - return MSG_RVC_TYPE; + return MSG_RequestVerificationCode_Id; } + virtual int operator()(const CMessage *msg, MessageContext *ctx) { - MSG_AVC avcMessage; + MSG_AnswerVerificationCode avcMessage; avcMessage.SetCaptchaType(0); - byte captcha[] = {0}; - avcMessage.SetCaptcha(captcha,sizeof(captcha)); + std::string strCaptcha; + avcMessage.SetCaptcha(strCaptcha); avcMessage.SetLoginTag(1); protocol_->SendVnocMessage(&avcMessage, ctx); + EZLOGGERVLSTREAM(axter::log_often)<<"Server had geted RVC and had sended AVC to client. (RVC)"< +#include +#include +using namespace std; +void sUserStorage ::SaveConnLog(string host,string name,string password,string db,int port /*= 3306*/ ) +{ + EZLOGGERSTREAM<<"MySQL host :"<getValue("sql_host"); + string name = Config::getInstance()->getValue("sql_username"); + string password = Config::getInstance()->getValue("sql_password"); + string db = Config::getInstance()->getValue("user_db"); + int port = Config::getInstance()->getValue("sql_port"); + + SaveConnLog(host, name, password, db, port); + EZLOGGERVLSTREAM(axter::log_often)<<"Save Connection Log that host is: "<< + host<< + " name is: "<< + name<< + " passWord is: "<< + password<< + " db is: "<< + db<< + " port is"<< + port<asString()); + if (strlen(p) > cbBuff) + { + return false; + } + strcpy(pPassWordBuff, p); + + /*int a=0,b=0; + for (int i = 0; i < 40; i+=2) + { + if ( p[i] >= 'A' && p[i]<='F' ) + { + a = p[i] - 'A' +10; + }else if (p[i] >= '0' && p[i]<='9' ) + { + a = p[i] - '0' ; + } + else if ( p[i] >= 'a' && p[i]<='f' ) + { + a = p[i] - 'a' + 10; + } + if ( p[i+1] >= 'A' && p[i+1]<='F' ) + { + b = p[i+1] - 'A' +10; + }else if (p[i+1] >= '0' && p[i+1]<='9' ) + { + b = p[i+1] - '0' ; + } + else if ( p[i+1] >= 'a' && p[i+1]<='f' ) + { + b = p[i+1] - 'a' + 10; + } + + pPassWordBuff[i/2] = a*16 + b; + }*/ + return true; +} +bool sUserStorage::GetUserInfo(const char* pUser, userinfo* pUserInfo) +{ + + if (!bIsConn) + { + return false; + } + char SQL[100] = "select passwd from vnoc.user_info where user='"; + strcat(SQL, pUser); + strcat(SQL, "'"); + MWCommand com(&conn, SQL); + com.Execute(); + com.FetchNext(); + if (com.GetField_Num() == 0) + { + return false; + } + + strcpy(pUserInfo->strUser, pUser); + + int a=0,b=0; + + const char* p = com.GetOneData()->asString(); + for (int i = 0; i < 40; i+=2) + { + if ( p[i] >= 'A' && p[i]<='F' ) + { + a = p[i] - 'A' +10; + }else if (p[i] >= '0' && p[i]<='9' ) + { + a = p[i] - '0' ; + } + else if ( p[i] >= 'a' && p[i]<='f' ) + { + a = p[i] - 'a' + 10; + } + if ( p[i+1] >= 'A' && p[i+1]<='F' ) + { + b = p[i+1] - 'A' +10; + }else if (p[i+1] >= '0' && p[i+1]<='9' ) + { + b = p[i+1] - '0' ; + } + else if ( p[i+1] >= 'a' && p[i+1]<='f' ) + { + b = p[i+1] - 'a' + 10; + } + + pUserInfo->passwordData[i/2] = a*16 + b; + } + + + char SQL1[100] = "select nickname from vnoc.user_info where user='"; + strcat(SQL1, pUser); + strcat(SQL1, "'"); + MWCommand com1(&conn, SQL1); + com1.Execute(); + com1.FetchNext(); + strcpy(pUserInfo->strNickname, com1.GetOneData()->asString()); + + char SQL2[100] = "select email from vnoc.user_info where user='"; + strcat(SQL2, pUser); + strcat(SQL2, "'"); + MWCommand com2(&conn, SQL2); + com2.Execute(); + com2.FetchNext(); + strcpy(pUserInfo->strEmailAddr, com2.GetOneData()->asString()); + + char SQL3[100] = "select gender from vnoc.user_info where user='"; + strcat(SQL3, pUser); + strcat(SQL3, "'"); + MWCommand com3(&conn, SQL3); + com3.Execute(); + com3.FetchNext(); + pUserInfo->gender = com3.GetOneData()->asInt(); + + char SQL4[100] = "select old from vnoc.user_info where user='"; + strcat(SQL4, pUser); + strcat(SQL4, "'"); + MWCommand com4(&conn, SQL4); + com4.Execute(); + com4.FetchNext(); + pUserInfo->uOld = com4.GetOneData()->asInt(); + return true; +} diff --git a/NetService/src/SQLUserStorage.h b/NetService/src/SQLUserStorage.h new file mode 100644 index 00000000..adeccb81 --- /dev/null +++ b/NetService/src/SQLUserStorage.h @@ -0,0 +1,19 @@ +#pragma once +#include "UserStorage.h" +#include "mysql/MysqlWrapper.h" +#pragma comment(lib, "../lib/libmysql.lib") + +class sUserStorage :public UserStorage +{ +public: + sUserStorage (); + ~sUserStorage (); + bool IfUserExist(const char* pUser); + bool GetPassword(const char* pUser, char* pPassWordBuff, size_t cbBuff); + bool GetUserInfo(const char* pUser, userinfo* pUserInfo); +private: + void SaveConnLog(string host,string name,string password,string db,int port /*= 3306*/ ); + MWConnection conn; + bool bIsConn; +}; + diff --git a/NetService/src/UserInfo.hpp b/NetService/src/UserInfo.hpp new file mode 100644 index 00000000..42bbf138 --- /dev/null +++ b/NetService/src/UserInfo.hpp @@ -0,0 +1,38 @@ +#pragma once + +struct userinfo +{ + //кܶûϢ + char strUser[40]; + char passwordData[20]; + char strNickname[40]; + char strEmailAddr[40]; + int gender; //1 male 2female + unsigned int uOld; +};//148byte + + + +/* +____user1 +admin +{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19} +admin +123456789@gmail.com +1 +18 +____user2 +test +{6,4,5,9,8,9,6,3,7,7,1,6,4,6,3,5,8,0,0,0} +test +test@test.com +0 +20 +____user3 +able +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} +iceable +645989637@qq.com +1 +17 +*/ \ No newline at end of file diff --git a/NetService/src/UserManage.cpp b/NetService/src/UserManage.cpp new file mode 100644 index 00000000..6b0c80ef --- /dev/null +++ b/NetService/src/UserManage.cpp @@ -0,0 +1,5 @@ +#include "UserManage.hpp" +#include + +std::mutex userSetMutex; +CUserManage CUserManage::_instance; \ No newline at end of file diff --git a/NetService/src/UserManage.hpp b/NetService/src/UserManage.hpp index 16331c8e..66ef6d1a 100644 --- a/NetService/src/UserManage.hpp +++ b/NetService/src/UserManage.hpp @@ -1,57 +1,93 @@ -/* -ûģ -1 û֤ -2 ûע -3 һ -4 ϴļ -5 û -*/ +#pragma once + +#include "UserInfo.hpp" +#include "UserStorage.h" #include -#define NULLPOINT -1 -#define LOGIN_OK 1 -#define TEST_FALSE 2 +#include +#include +#include -using namespace std; +#define NULLPOINT -1 +#define LOGIN_OK 1 +#define TEST_FALSE 2 +#define ACCOUNT_NULL 3 +#define HAS_LOGINED 4 + +extern std::mutex userSetMutex; -struct userinfo -{ - //кܶûϢ -}; class CUserManage { -private: - + public: - //ֵ LOGIN_OK ½ɹ TEST_FALSE ֤ʧ NULLPOINT ָЧ - //½ɹûϢ - int Authenticate(string sUser, char* pPassword, userinfo* pUserInfo, int nPassLen = 20) -{ - char strPass[20] = "0000000000000000000"; - - if (false)//˺Ƿ ݿ - { - return TEST_FALSE; - } - - int i = 0; - do - { - if (strPass[i] != pPassword[i]) - { - return TEST_FALSE; - } - ++i; - } while (i < nPassLen); - - if ((int)pUserInfo == 0) - { - return NULLPOINT; - } - - //ûϢ - //userinfo->xx == xx; - return LOGIN_OK; -} - -}; + UserStorage *_us; + static CUserManage* GetInstance() + { + return &_instance; + } + //return value: LOGIN_OK(login-success) TEST_FALSE(verification-failure) NULLPOINT(null-pointer) + //get the user's information if login-success. + void initial(UserStorage *us) + { + _us = us; + } + int Authenticate(const char* szUser,const char* pPassword, userinfo* pUserInfo, int nPassLen = 40) + { + if (szUser == NULL || strcmp(szUser, "") == 0) + { + return TEST_FALSE; + } + strncpy(pUserInfo->strUser, szUser, 40); + userSetMutex.lock(); + bool usernameInserted = insertOnlineUser(szUser); + userSetMutex.unlock(); + if(usernameInserted == false) + { + return HAS_LOGINED;//this user has logined, deny this login request. + } + + return LOGIN_OK; + if ( !_us->IfUserExist(szUser) )//check the username in the database + { + return ACCOUNT_NULL; + } + char strPass[41] = {0}; + _us->GetPassword(szUser, strPass, 40); + + int i = 0; //verify the password + do + { + if (strPass[i] != pPassword[i]) + { + return TEST_FALSE; + } + ++i; + } while (i < nPassLen); + + if (pUserInfo == 0) + { + return NULLPOINT; + } + + //get the user's information + _us->GetUserInfo(szUser, pUserInfo); + + return LOGIN_OK; + } + bool deleteOnlineUser(const char* szUser) + { + std::string temp = szUser; + userSetMutex.lock(); + bool deleteResult = 0 != onlineUsers.erase(temp); + userSetMutex.unlock(); + return deleteResult; + } +private: + static CUserManage _instance; + std::set onlineUsers; + bool insertOnlineUser(const char *szUser) + { + std::string temp = szUser; + return onlineUsers.insert(temp).second; + } +}; \ No newline at end of file diff --git a/NetService/src/UserStorage.cpp b/NetService/src/UserStorage.cpp new file mode 100644 index 00000000..c3cfb63c --- /dev/null +++ b/NetService/src/UserStorage.cpp @@ -0,0 +1,23 @@ +#include "UserStorage.h" + +UserStorage::UserStorage() +{ +} + +UserStorage::~UserStorage() +{ + +} + +bool UserStorage::IfUserExist(const char* pUser) +{ + return false; +} +bool UserStorage::GetPassword(const char* pUser, char* pPassWordBuff, size_t cbBuff) +{ + return false; +} +bool UserStorage::GetUserInfo(const char* pUser, userinfo* pUserInfo) +{ + return false; +} \ No newline at end of file diff --git a/NetService/src/UserStorage.h b/NetService/src/UserStorage.h new file mode 100644 index 00000000..c11aa434 --- /dev/null +++ b/NetService/src/UserStorage.h @@ -0,0 +1,18 @@ +#pragma once +#include "UserInfo.hpp" +#include + + + + +class UserStorage +{ +public: + UserStorage(); + ~UserStorage(); + virtual bool IfUserExist(const char* pUser); + virtual bool GetPassword(const char* pUser, char* pPassWordBuff, size_t cbBuff) ; + virtual bool GetUserInfo(const char* pUser, userinfo* pUserInfo) ; +private: + +}; \ No newline at end of file diff --git a/NetService/src/VNOCServer.cpp b/NetService/src/VNOCServer.cpp index e5388353..7cdbdce4 100644 --- a/NetService/src/VNOCServer.cpp +++ b/NetService/src/VNOCServer.cpp @@ -12,12 +12,20 @@ #include "NetService.h" #include "Config.hpp" #include +#include "SQLUserStorage.h" +#include "UserManage.hpp" +#include "../../NMessage/ParserMessageXML.h" using namespace std; +using namespace VNOC::Message; int main() { + ParserMessageXML::Instance().LoadFile("msgdef.xml"); Config::getInstance()->Initialize("vnoc.conf"); cout<<"port:"<getValue("port")<initial(&us); + NetService net; net.start(Config::getInstance()->getValue("port")); @@ -25,5 +33,5 @@ int main() } #ifdef WIN32 -#include "../../VisualLeakDetector/include/vld.h" +//#include "../../ThirdLibs/VisualLeakDetector/include/vld.h" #endif \ No newline at end of file diff --git a/NetService/src/VNOCUser.cpp b/NetService/src/VNOCUser.cpp new file mode 100644 index 00000000..2351f2ae --- /dev/null +++ b/NetService/src/VNOCUser.cpp @@ -0,0 +1,33 @@ +#include "VNOCUser.h" +#include "GlobalDefinition.h" + +VNOCUser::VNOCUser() +{ +} + +VNOCUser::~VNOCUser() +{ +} + +void VNOCUser::setUniqueID(GUID_t guid) +{ + _guid = guid; +} + +GUID_t VNOCUser::getUniqueID() +{ + return _guid; +} + +void VNOCUser::setNickName(std::string studentName) +{ + if (studentName.length() <= MAX_NICKNAME_LEN) + { + _studentName = studentName; + } +} + +void VNOCUser::heartbeat(int64 now) +{ + +} \ No newline at end of file diff --git a/NetService/src/VNOCUser.h b/NetService/src/VNOCUser.h new file mode 100644 index 00000000..840be0ec --- /dev/null +++ b/NetService/src/VNOCUser.h @@ -0,0 +1,37 @@ +#ifndef VNOC_VNOC_USER_H_ +#define VNOC_VNOC_USER_H_ + +#include "Common.h" + +struct AccountInfo +{ + std::string account; + std::string email; + uint8 gender; + + AccountInfo() : gender(0) + { + } +}; + +class VNOCUser +{ +public: + VNOCUser(); + virtual ~VNOCUser(); + +public: + virtual void setUniqueID(GUID_t guid); + virtual GUID_t getUniqueID(); + virtual void setNickName(std::string studentName); + +public: + virtual void heartbeat(int64 now); + AccountInfo accountInfo; + +private: + GUID_t _guid; + std::string _studentName; +}; + +#endif \ No newline at end of file diff --git a/NetService/src/VnocMessageSocketHandler.hpp b/NetService/src/VnocMessageSocketHandler.hpp index 9c4f38e5..3a596b2a 100644 --- a/NetService/src/VnocMessageSocketHandler.hpp +++ b/NetService/src/VnocMessageSocketHandler.hpp @@ -4,10 +4,13 @@ #include #include "AsioTcpConnection.hpp" #include "SocketHandler.hpp" -#include "../../Message/MsgDef.h" +#include "../../NMessage/MessageUnion.h" #include "VnocProtocol.hpp" +#include "util.hpp" #include +using namespace VNOC::Message; + template class VnocMessageSocketHandler : public SocketHandler, IVnocMessageProtocolHandler { @@ -23,14 +26,13 @@ class VnocMessageSocketHandler : public SocketHandler, IVnocMessageProtocolHandl private: void ReadHeaderHandler(const asio::error_code& error, size_t bytes_transferred); void ReadBodyHandler(char *messageBuffer, const asio::error_code& error, size_t bytes_transferred); - void SendHandler(char* buffer, const asio::error_code& error, size_t bytes_transferred); + void SendHandler(smart_buf buffer, const asio::error_code& error, size_t bytes_transferred); //post a read operation to wait for message header. void readHeader(); - const static size_t HEADER_LEN = 30; - char headerData_[HEADER_LEN]; - ConnectionT *connection_; + char headerData_[MSG_HEAD_LEN]; + ConnectionT* connection_; MessageContext *ctx_; VnocProtocol* protocol_; diff --git a/NetService/src/VnocMessageSocketHandler.inl b/NetService/src/VnocMessageSocketHandler.inl index 1965d48c..5295e498 100644 --- a/NetService/src/VnocMessageSocketHandler.inl +++ b/NetService/src/VnocMessageSocketHandler.inl @@ -1,9 +1,12 @@ -#include "../../Message/MessageParser.h" -#include "../../Message/PackMessage.h" +#include "../../NMessage/Message2Parser.h" +#include "../../NMessage/Message2Pack.h" +#include "../../NMessage/BufferMessage.h" #include #include "VnocProtocol.hpp" const size_t MAX_PACKAGE_LEN = 1024*1024U; +using namespace std; +using namespace VNOC::Message; template VnocMessageSocketHandler::VnocMessageSocketHandler(ConnectionT *connection):connection_(connection) { @@ -13,7 +16,10 @@ VnocMessageSocketHandler::VnocMessageSocketHandler(ConnectionT *con template VnocMessageSocketHandler::~VnocMessageSocketHandler() { + EZLOGGERVLSTREAM(axter::log_often)<<"delete connection Handler."<deleteOnlineUser(ctx_->userName.c_str()); delete ctx_; + delete connection_; } template @@ -27,90 +33,97 @@ void VnocMessageSocketHandler::readHeader(){ template void VnocMessageSocketHandler::start() { + EZLOGGERVLSTREAM(axter::log_often)<<"New connection start."< void VnocMessageSocketHandler::ReadHeaderHandler(const asio::error_code& error, size_t bytes_transferred) { + EZLOGGERVLSTREAM(axter::log_often)<<"ReadHeaderHandler, received: "< MAX_PACKAGE_LEN) { - EZLOGGERVLSTREAM(axter::log_often)<<"package_len > MAX_PACKAGE_LEN\n"; + if (package_len > MAX_PACKAGE_LEN) { + EZLOGGERVLSTREAM(axter::log_often)<<"package_len > MAX_PACKAGE_LEN"<recv(&messageBuffer[HEADER_LEN], package_len - HEADER_LEN, + memcpy(messageBuffer, headerData_, MSG_HEAD_LEN); + EZLOGGERVLSTREAM(axter::log_often)<<"get correct header, lenth:"<recv(&messageBuffer[MSG_HEAD_LEN], package_len - MSG_HEAD_LEN, std::bind(&VnocMessageSocketHandler::ReadBodyHandler, this, messageBuffer, - std::placeholders::_1, - std::placeholders::_2)); + std::placeholders::_1, + std::placeholders::_2)); } template void VnocMessageSocketHandler::ReadBodyHandler(char *messageBuffer, const asio::error_code& error, size_t bytes_transferred){ - std::unique_ptr safe_buf(messageBuffer); + EZLOGGERVLSTREAM(axter::log_often)<<"received: "< msg(parser.Parse((byte*)safe_buf.get(), bytes_transferred + HEADER_LEN)); + EZLOGGERVLSTREAM(axter::log_often)<<"receve message body"<GetMessageType(); - auto handlers = protocol_->getHandler((MSGTYPE)type); - for(auto i = handlers.begin(); i != handlers.end(); ++i){ - ret = (**i)(msg.get(), this->ctx_) || ret; + if (msg.IsValid()){ + int type = msg.MsgId(); + EZLOGGERVLSTREAM(axter::log_often)<<"message type: "<getHandler((VMsg)type); + for(auto message_handler = handlers.begin(); message_handler != handlers.end(); ++message_handler){ + ret = (**message_handler)(&msg, this->ctx_) || ret; } } + //wait for next message + readHeader(); - if (ret == 0){ - //message is not handled, we need post a read opeartion - readHeader(); - } } template -void VnocMessageSocketHandler::SendHandler(char* buffer, const asio::error_code& error, size_t bytes_transferred) +void VnocMessageSocketHandler::SendHandler(smart_buf buffer, const asio::error_code& error, size_t bytes_transferred) { - delete []buffer; - if (!error){ - readHeader(); - } + } - template +template void VnocMessageSocketHandler::SendVnocMessage(const CMessage *msg) { - PackMessage packer; - size_t length = packer.GetMessageLen(msg); + CMessage2Pack m2Pack; + CBufferMessage PackBuff; + m2Pack.PackMessage(msg, PackBuff); + size_t length = PackBuff.GetSize(); assert(length != 0); - char *pack = new char[length]; - packer.Pack(msg, (byte*)pack, length); - connection_->send(pack, length, + assert(PackBuff.GetBuffer() != NULL); + smart_buf pack(new char[length]); + memcpy((char*)pack, PackBuff.GetBuffer(), length); + char *buf = pack; + connection_->send(buf, length, std::bind(&VnocMessageSocketHandler::SendHandler, this, pack, std::placeholders::_1, std::placeholders::_2)); + EZLOGGERVLSTREAM(axter::log_often)<<"send vnoc message type:"<< msg->MsgId()<<" lenght: "<getMessageType(); - assert (type != MSGTYPE_NULL); - assert (type < MSGTYPE_END); + VMsg type = MessageHandler->getMessageType(); + assert (type > MSG_TYPE_NULL); + assert (type < MSG_TYPE_END); handlerMap_[type].push_back(MessageHandler); } void VnocProtocol::RegisterSocketHandlerFactory(SocketHandlerFactory *factory) { handlerFactory_ = factory; } -list& VnocProtocol::getHandler(MSGTYPE msgType) +list& VnocProtocol::getHandler(VMsg msgType) { - assert (msgType != MSGTYPE_NULL); - assert (msgType < MSGTYPE_END); + assert (msgType > MSG_TYPE_NULL); + assert (msgType < MSG_TYPE_END); return handlerMap_[msgType]; } diff --git a/NetService/src/VnocProtocol.hpp b/NetService/src/VnocProtocol.hpp index 77502bee..491cb081 100644 --- a/NetService/src/VnocProtocol.hpp +++ b/NetService/src/VnocProtocol.hpp @@ -2,7 +2,7 @@ #ifndef VNOC_PROTOCOL_H #define VNOC_PROTOCOL_H -#include "../../Message/MsgDef.h" +#include "../../NMessage/MessageUnion.h" #include #include #include @@ -11,6 +11,7 @@ using std::list; using std::array; +using namespace VNOC::Message; class IVnocMessageProtocolHandler { @@ -29,23 +30,23 @@ class IMessageHandler public: //if the message is handled, return 1; virtual int operator()(const CMessage *msg, MessageContext *ctx)=0; - virtual MSGTYPE getMessageType() const = 0; + virtual VMsg getMessageType() const = 0; }; class VnocProtocol { public: SocketHandlerFactory* getSocketHandlerFactory(){return handlerFactory_;} - VnocProtocol (){ + VnocProtocol (){ } void RegisterMessageHandler(IMessageHandler *MessageHandler); void RegisterSocketHandlerFactory(SocketHandlerFactory *factory); void SendVnocMessage(const CMessage *msg, MessageContext *ctx); - list& getHandler(MSGTYPE msgType); + list& getHandler(VMsg msgType); private: SocketHandlerFactory *handlerFactory_; - array,MSGTYPE::MSGTYPE_END > handlerMap_; + array, VMsg::MSG_TYPE_END > handlerMap_; }; #endif //VNOC_PROTOCOL_H diff --git a/NetService/src/VnocRoomManager.cpp b/NetService/src/VnocRoomManager.cpp new file mode 100644 index 00000000..4216909a --- /dev/null +++ b/NetService/src/VnocRoomManager.cpp @@ -0,0 +1,8 @@ +#include "VnocRoomManager.hpp" +#include + +using namespace std; +const std::vector *VnocRoomManager::getRoomList() +{ + return &roomList_; +} \ No newline at end of file diff --git a/NetService/src/VnocRoomManager.hpp b/NetService/src/VnocRoomManager.hpp new file mode 100644 index 00000000..cdae0f9d --- /dev/null +++ b/NetService/src/VnocRoomManager.hpp @@ -0,0 +1,14 @@ +#pragma once +#ifndef ROOM_MANAGER_H +#define ROOM_MANAGER_H +#include "Config.hpp" +#include +class VnocRoom{ +}; +class VnocRoomManager { +public: + const std::vector *getRoomList(); +private: + std::vector roomList_; +}; +#endif //ROOM_MANAGER_H diff --git a/NetService/src/mysql/MWSQL_Example.cpp b/NetService/src/mysql/MWSQL_Example.cpp new file mode 100644 index 00000000..429208c2 --- /dev/null +++ b/NetService/src/mysql/MWSQL_Example.cpp @@ -0,0 +1,60 @@ + +#include +#include "MysqlWrapper.h" + + +#pragma comment(lib,"sql/lib/libmysql.lib") + + +using namespace std; + + +int main() +{ + + MWConnection conn; + MWCommand Table(&conn,"select * from writers"); + MWCommand Table1(&conn,"INSERT INTO writers VALUES('Test')"); + MWCommand Password(&conn,"select password from writers"); + MWCommand TestDouble(&conn,"select password from writers"); + //ݿ + if(conn.Connect("ַ","˺","","ݿ") != MW_SQL_ERR) + { + cout<<"OK!"<asC_String()<asInt()<asDoubule()<m_Mysql; + m_runsql = runsql; + return MW_SQL_OK; +} + +int MWCommand::Execute() +{ + return mysql_query(m_SQL,m_runsql.c_str()); +} + +MYSQL_ROW MWCommand::FetchNext() +{ + if (m_SQL == NULL) + { + return 0; + } + + if (m_Result == NULL) + { + m_Result = mysql_store_result(m_SQL); + } + + m_Field_Num = mysql_num_fields(m_Result); + + m_Line_Num = (int)mysql_num_rows(m_Result); + + return (m_Row = mysql_fetch_row(m_Result)); +} + + +MYSQL_ROW MWCommand::First() +{ + if (m_SQL == NULL) + { + return 0; + } + + if (m_Result == NULL) + { + m_Result = mysql_store_result(m_SQL); + } + + m_Field_Num = mysql_num_fields(m_Result); + + m_Line_Num = (int)mysql_num_rows(m_Result); + + return (m_Row = mysql_fetch_row(m_Result)); +} + +MWType* MWCommand::GetData( int index ) +{ + if (m_Row == NULL) + { + return NULL; + } + + if (m_MWTpye != NULL) + { + delete m_MWTpye; + m_MWTpye = NULL; + } + + m_MWTpye = new MWType; + + m_MWTpye->m_Data = m_Row[index]; + + return m_MWTpye; +} + +MWType* MWCommand::GetOneData() +{ + + if (m_MWTpye != NULL) + { + delete m_MWTpye; + m_MWTpye = NULL; + } + if (GetField_Num() == 0) + { + m_MWTpye = new MWType; + + m_MWTpye->m_Data = m_Row[GetField_Num()]; + } + else + { + m_MWTpye = new MWType; + + m_MWTpye->m_Data = m_Row[GetField_Num() - 1]; + } + return m_MWTpye; +} + +void MWCommand::_Close() +{ + if (m_Row != NULL) + { + mysql_free_result(m_Result); + m_Row = NULL; + } + + if (m_MWTpye != NULL) + { + delete m_MWTpye; + m_MWTpye = NULL; + } +} + + +//MWType + +const char* MWType::asString() const +{ + return m_Data.c_str(); +} + +int MWType::asInt() const +{ + return atoi(m_Data.data()); +} + +short MWType::asShort() const +{ + return atoi(m_Data.data()); +} + +long MWType::asLong() const +{ + return atol(m_Data.data()); +} + + +double MWType::asDoubule() const +{ + double Ret = 0; + sscanf(m_Data.c_str(),"%lf",&Ret); + return Ret; +} + diff --git a/NetService/src/mysql/MysqlWrapper.h b/NetService/src/mysql/MysqlWrapper.h new file mode 100644 index 00000000..aed73543 --- /dev/null +++ b/NetService/src/mysql/MysqlWrapper.h @@ -0,0 +1,116 @@ + + +#pragma once + + +#include +#include "../../include/Mysql/mysql.h" + + + +using std::string; + + +#define MW_SQL_OK 0 +#define MW_SQL_ERR -1 + +class MWType; + +class MWConnection +{ +public: + MWConnection(){ + mysql_init(&m_Mysql); + } + ~MWConnection(){ + Shutdown(); + }; + + friend class MWCommand; + +public: + + //hostΪNULL localhost ʱ ΪĬӱݿ + int Connect(string host,string name,string password,string db,int port = 3306); + + void Shutdown(); + +private: + + MYSQL m_Mysql; + +}; + + +class MWCommand +{ +public: + MWCommand():m_SQL(NULL),m_Result(NULL),m_Field_Num(0),m_MWTpye(NULL),m_Row(NULL){} + MWCommand(MWConnection* conn,string runsql):m_SQL(NULL),m_Result(NULL),m_Field_Num(0),m_MWTpye(NULL),m_Row(NULL){ + _Command(conn,runsql); + } + ~MWCommand(){ + _Close(); + } +public: + + MYSQL_ROW FetchNext(); + + MYSQL_ROW First(); + + MWType* GetData(int index); + + //һĽ + MWType* GetOneData(); + + int GetField_Num(){ + return m_Field_Num; + } + + int GetLine_Num(){ + return m_Line_Num; + } + + int Execute(); + +private: + + void _Close(); + + int _Command(MWConnection* conn,string runsql); + +private: + + MYSQL_RES *m_Result; + MYSQL_ROW m_Row; + + MWType* m_MWTpye; + + int m_Line_Num; + int m_Field_Num; + MYSQL* m_SQL; + string m_runsql; +}; + + +class MWType +{ +public: + MWType(){} + ~MWType(){} + + friend class MWCommand; + + const char* asString() const; + + long asLong() const; + + int asInt() const; + + double asDoubule() const; + + short asShort() const; + +private: + string m_Data; +}; \ No newline at end of file diff --git a/NetService/src/test/MockTcpConnection.hpp b/NetService/src/test/MockTcpConnection.hpp index b140f7de..aa7e127e 100644 --- a/NetService/src/test/MockTcpConnection.hpp +++ b/NetService/src/test/MockTcpConnection.hpp @@ -2,12 +2,13 @@ #define MOCK_TCP_CONNECTION_H #include "../SocketServer.hpp" #include +#include #include #include class EventOperator { public: - virtual void operator()(const asio::error_code& error, size_t bytes_transferred)=0; + virtual void operator()(const asio::error_code& error, size_t bytes_transferred) = 0; }; template class HandlerWrapper : public EventOperator @@ -81,7 +82,7 @@ class MockTcpConnection: public Connection if (len >= recvBufLen){ putLen = recvBufLen; len -= recvBufLen; - } else { + } else { putLen = len; len = 0; } @@ -100,8 +101,14 @@ class MockTcpConnection: public Connection } } } + } + void close() + { + asio::error_code ec(asio::error::shut_down); + (*recvHandler_)(ec, 0); } + size_t getSendLen(){return sendLen_;} const char *getSendBuf(){return sendBuf_;} private: @@ -110,7 +117,7 @@ class MockTcpConnection: public Connection char* recvBuf_; size_t recvBufLen; size_t sendLen_; - char sendBuf_[1024]; + char sendBuf_[102400]; bool isReadSome_; size_t receivedLenth_; }; diff --git a/NetService/src/test/RoomPoolTest.cpp b/NetService/src/test/RoomPoolTest.cpp new file mode 100644 index 00000000..47eb2570 --- /dev/null +++ b/NetService/src/test/RoomPoolTest.cpp @@ -0,0 +1,54 @@ +#include +#include +#include "../RoomPool.cpp" + +class RoomPoolTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( RoomPoolTest ); + CPPUNIT_TEST( testInitPool ); + CPPUNIT_TEST( testAcquire ); + CPPUNIT_TEST( testRelease ); + CPPUNIT_TEST_SUITE_END(); + +public: + void testInitPool() + { + RoomPool rPool; + CPPUNIT_ASSERT(rPool.initPool(0, 0) == false); + CPPUNIT_ASSERT(rPool.initPool(0) == false); + CPPUNIT_ASSERT(rPool.initPool(1, 0) == false); + CPPUNIT_ASSERT(rPool.initPool() == true); + CPPUNIT_ASSERT(rPool.initPool(1, 1) == true); + } + + void testAcquire() + { + RoomPool rPool; + rPool.initPool(); + for(int i = 0; i < 16; ++i) + { + CPPUNIT_ASSERT (rPool.acquire() != NULL); + } + rPool.destroy(); + rPool.initPool(10, 10); + for(int i = 0; i < 16; ++i) + { + CPPUNIT_ASSERT(rPool.acquire() != NULL); + } + } + + void testRelease() + { + RoomPool rPool; + rPool.initPool(); + for(int i = 0; i < 256; ++i) + rPool.acquire(); + for(int i = 64; i < 128; ++i) + rPool.release(i); + for(int i = 0; i < 64; ++i) + CPPUNIT_ASSERT(rPool.acquire() != NULL); + } + +}; +CPPUNIT_TEST_SUITE_REGISTRATION ( RoomPoolTest ); +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(RoomPoolTest, "RoomPoolTest"); \ No newline at end of file diff --git a/NetService/src/test/VnocMessageHandlerTest.cpp b/NetService/src/test/VnocMessageHandlerTest.cpp index 9016718c..7ffa9a4e 100644 --- a/NetService/src/test/VnocMessageHandlerTest.cpp +++ b/NetService/src/test/VnocMessageHandlerTest.cpp @@ -5,109 +5,248 @@ #include "MockTcpConnection.hpp" #include "../RvcMessageHandler.hpp" #include "../RliMessageHandler.hpp" +#include "../RclMessageHandler.hpp" +#include "../FileUserStorage.h" +#include "../UserManage.hpp" +#include +#include +#include "../../NMessage/MessageUnion.h" +#include "../../NMessage/Message2Pack.h" +#include "../../NMessage/Message2Parser.h" + +#include class VnocMessageHandlerTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( VnocMessageHandlerTest ); CPPUNIT_TEST( testRVC ); - CPPUNIT_TEST( testRLI ); + CPPUNIT_TEST( testRLIdefault ); + CPPUNIT_TEST( testRLIwithEmptyAccountNumber ); + CPPUNIT_TEST( testRLIwithAccountNumber ); + CPPUNIT_TEST( testRLIwithAccountNumberAndPassword ); + CPPUNIT_TEST( testRLIofLoginTwoTimes ); + CPPUNIT_TEST( testRCL ); + CPPUNIT_TEST( testUserSetDelete ); CPPUNIT_TEST_SUITE_END(); MockTcpConnection *conn_; VnocProtocol *protocol_; public: + fUserStorage us; + void setUp() { conn_ = new MockTcpConnection; protocol_ = new VnocProtocol(); + CUserManage::GetInstance()->initial(&us); } void tearDown() { - delete conn_; delete protocol_; } public: void testRVC() { - RvcMessageHandler rvcHandler(protocol_); + RvcMessageHandler rvchandler(protocol_); VnocMessageSocketHandler handler(conn_); handler.setProtocol(protocol_); handler.start(); - char rvc[]={0x56, - 0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x35, - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - - 0x14, - 0x00,0x00,0x00,0x00, - 0x01, - - 0x00,0x00,0x00,0x10, - - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - - 0x00,0x00, - 0x43}; - conn_->setRecv(rvc, sizeof(rvc)); + MSG_RequestVerificationCode rvcMessage; + CBufferMessage buff; + CMessage2Pack packer; + rvcMessage.SetMachineAddress("EASB-ASDASD-ASD"); + packer.PackMessage(&rvcMessage, buff); + conn_->setRecv((char*)buff.GetBuffer(), buff.GetSize()); const char *sendBuf = conn_->getSendBuf(); - //return a AVC message - CPPUNIT_ASSERT(sendBuf[24]==0x15); + //return an AVC message + CMessage2Parser parser; + buff.Copy(sendBuf, conn_->getSendLen()); + CMessage msg(CMessage2Parser::GetMsgType(buff)); + CPPUNIT_ASSERT(msg.MsgId() == MSG_AnswerVerificationCode_Id); } - void testRLI() - { - char testRLI [] = {0x56, - 0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x5D, - - - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x16, - 0x00,0x00,0x00,0x00, - - 0x03, + void testRLIdefault() + { + RliMessageHandler rlihandler(protocol_); + VnocMessageSocketHandler handler(conn_); + handler.setProtocol(protocol_); + handler.start(); + MSG_RequestLogin rliMessage; + CBufferMessage buff; + CMessage2Pack packer; + packer.PackMessage(&rliMessage, buff); + conn_->setRecv((char*)buff.GetBuffer(), buff.GetSize()); + char *sendBuf = (char*)conn_->getSendBuf(); + //return an ALI message with login-failure. + CMessage2Parser parser; + CBufferMessage Rbuff; + Rbuff.Copy(sendBuf, conn_->getSendLen()); + MSG_AnswerLogin msg; + parser.Parser(&msg, Rbuff); + CPPUNIT_ASSERT(msg.MsgId() == MSG_AnswerLogin_Id); + uint8 LoginResult = 0; + msg.GetLoginResult(LoginResult); + CPPUNIT_ASSERT(LoginResult == 1); + } - 0x00,0x00,0x00,0x10, - 0x00,0x00,0x00,0x10, - 0x00,0x00,0x00,0x10, + void testRLIwithEmptyAccountNumber() + { + RliMessageHandler rlihandler(protocol_); + VnocMessageSocketHandler handler(conn_); + handler.setProtocol(protocol_); + handler.start(); + MSG_RequestLogin rliMessage; + CBufferMessage buff; + CMessage2Pack packer; + rliMessage.SetAccountNumber(""); + packer.PackMessage(&rliMessage, buff); + conn_->setRecv((char*)buff.GetBuffer(), buff.GetSize()); + char *sendBuf = (char*)conn_->getSendBuf(); + //return an ALI message with login-failure. + CMessage2Parser parser; + CBufferMessage Rbuff; + Rbuff.Copy(sendBuf, conn_->getSendLen()); + MSG_AnswerLogin msg; + parser.Parser(&msg, Rbuff); + CPPUNIT_ASSERT(msg.MsgId() == MSG_AnswerLogin_Id); + uint8 LoginResult = 0; + msg.GetLoginResult(LoginResult); + CPPUNIT_ASSERT(LoginResult == 1); + } + void testRLIwithAccountNumber() + { + RliMessageHandler rlihandler(protocol_); + VnocMessageSocketHandler handler(conn_); + handler.setProtocol(protocol_); + handler.start(); + MSG_RequestLogin rliMessage; + rliMessage.SetAccountNumber("testRLIwithAccountNumber"); + CBufferMessage buff; + CMessage2Pack packer; + packer.PackMessage(&rliMessage, buff); + conn_->setRecv((char*)buff.GetBuffer(), buff.GetSize()); + char *sendBuf = (char*)conn_->getSendBuf(); + //return an ALI message with login-success + CMessage2Parser parser; + CBufferMessage Rbuff; + Rbuff.Copy(sendBuf, conn_->getSendLen()); + MSG_AnswerLogin msg; + parser.Parser(&msg, Rbuff); + CPPUNIT_ASSERT(msg.MsgId() == MSG_AnswerLogin_Id); + uint8 LoginResult = 0; + msg.GetLoginResult(LoginResult); + CPPUNIT_ASSERT(LoginResult == 0); + } - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02, + void testUserSetDelete() + { + RliMessageHandler rlihandler(protocol_); + VnocMessageSocketHandler *handler = new VnocMessageSocketHandler(conn_); + handler->setProtocol(protocol_); + handler->start(); + MSG_RequestLogin rliMessage; + char tempAccountNumber[] = "testUserSetDelete"; + rliMessage.SetAccountNumber(tempAccountNumber); + CBufferMessage buff; + CMessage2Pack packer; + packer.PackMessage(&rliMessage, buff); + conn_->setRecv((char*)buff.GetBuffer(), buff.GetSize()); + char *sendBuf = (char*)conn_->getSendBuf(); + //return an ALI message with login-success + CMessage2Parser parser; + CBufferMessage Rbuff; + Rbuff.Copy(sendBuf, conn_->getSendLen()); + MSG_AnswerLogin msg; + parser.Parser(&msg, Rbuff); + CPPUNIT_ASSERT(msg.MsgId() == MSG_AnswerLogin_Id); + uint8 LoginResult = 0; + msg.GetLoginResult(LoginResult); + CPPUNIT_ASSERT(LoginResult == 0); + + conn_->close(); + CPPUNIT_ASSERT(CUserManage::GetInstance()->deleteOnlineUser(tempAccountNumber) == false); + } - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03, + void testRLIwithAccountNumberAndPassword() + { + RliMessageHandler rlihandler(protocol_); + VnocMessageSocketHandler handler(conn_); + handler.setProtocol(protocol_); + handler.start(); + MSG_RequestLogin rliMessage; + rliMessage.SetPassword("testRLIwithAccountNumberAndPassword"); + rliMessage.SetAccountNumber("testRLIwithAccountNumberAndPassword"); + CBufferMessage buff; + CMessage2Pack packer; + packer.PackMessage(&rliMessage, buff); + conn_->setRecv((char*)buff.GetBuffer(), buff.GetSize()); + char *sendBuf = (char*)conn_->getSendBuf(); + //return an ALI message with login-success + CMessage2Parser parser; + CBufferMessage Rbuff; + Rbuff.Copy(sendBuf, conn_->getSendLen()); + MSG_AnswerLogin msg; + parser.Parser(&msg, Rbuff); + CPPUNIT_ASSERT(msg.MsgId() == MSG_AnswerLogin_Id); + uint8 LoginResult = 0; + msg.GetLoginResult(LoginResult); + CPPUNIT_ASSERT(LoginResult == 0); + } - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04, + void testRLIofLoginTwoTimes() + { + RliMessageHandler rlihandler(protocol_); + VnocMessageSocketHandler handler(conn_); + handler.setProtocol(protocol_); + handler.start(); + MSG_RequestLogin rliMessage; + rliMessage.SetAccountNumber("testRLIofLoginTwoTimes"); + CBufferMessage buff; + CMessage2Pack packer; + packer.PackMessage(&rliMessage, buff); + conn_->setRecv((char*)buff.GetBuffer(), buff.GetSize()); + char *sendBuf = (char*)conn_->getSendBuf(); + //return an ALI message with login-success + CMessage2Parser parser; + CBufferMessage Rbuff; + Rbuff.Copy(sendBuf, conn_->getSendLen()); + MSG_AnswerLogin msg; + parser.Parser(&msg, Rbuff); + CPPUNIT_ASSERT(msg.MsgId() == MSG_AnswerLogin_Id); + uint8 LoginResult = 0; + msg.GetLoginResult(LoginResult); + CPPUNIT_ASSERT(LoginResult == 0); + + conn_->setRecv((char*)buff.GetBuffer(), buff.GetSize()); + sendBuf = (char*)conn_->getSendBuf(); + //return an ALI message with login-failure + Rbuff.Copy(sendBuf, conn_->getSendLen()); + parser.Parser(&msg, Rbuff); + CPPUNIT_ASSERT(msg.MsgId() == MSG_AnswerLogin_Id); + msg.GetLoginResult(LoginResult); + CPPUNIT_ASSERT(LoginResult == 1); + } - 0x00,0x00, - 0x43}; - RliMessageHandler rvcHandler(protocol_); + void testRCL() + { + RclMessageHandler rclhandler(protocol_); VnocMessageSocketHandler handler(conn_); handler.setProtocol(protocol_); handler.start(); - conn_->setRecv(testRLI, sizeof(testRLI)); - const char *sendBuf = conn_->getSendBuf(); - //return an AVC message - CPPUNIT_ASSERT(sendBuf[24]==0x17); + MSG_RequestClassList rclMessage; + CBufferMessage buff; + CMessage2Pack packer; + rclMessage.SetUserType(0); + packer.PackMessage(&rclMessage, buff); + conn_->setRecv((char*)buff.GetBuffer(), buff.GetSize()); + char *sendBuf = (char*)conn_->getSendBuf(); + //return an ACL message + CMessage2Parser parser; + CBufferMessage Rbuff; + Rbuff.Copy(sendBuf, conn_->getSendLen()); + MSG_AnswerClassList msg; + parser.Parser(&msg, Rbuff); + CPPUNIT_ASSERT(msg.MsgId() == MSG_AnswerClassList_Id); } }; diff --git a/NetService/src/test/testRunner.cpp b/NetService/src/test/testRunner.cpp index ebbcf412..25a915c1 100644 --- a/NetService/src/test/testRunner.cpp +++ b/NetService/src/test/testRunner.cpp @@ -1,14 +1,27 @@ +//#include "../../ThirdLibs/VisualLeakDetector/include/vld.h" + #include #include - - +#include +#include +#include +#include +using namespace std; int main( int argc, char **argv) { - CppUnit::TextUi::TestRunner runner; - CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry(); - runner.addTest( registry.makeTest() ); - bool wasSuccessful = runner.run( "", false ); + CppUnit::TestResult controller; + CppUnit::TestResultCollector result; + + CppUnit::TextUi::TestRunner runner; + CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry(); + runner.addTest( registry.makeTest() ); + runner.eventManager().addListener( &result ); + runner.run(); + + ofstream xmlFileOut("cpptestresults.xml"); + CppUnit::XmlOutputter xmlOut(&result, xmlFileOut); + xmlOut.write(); - return wasSuccessful; -} + return 0; +} \ No newline at end of file diff --git a/NetService/src/test/testRunner/testRunner.vcxproj b/NetService/src/test/testRunner/testRunner.vcxproj index b138bc7a..841f3a51 100644 --- a/NetService/src/test/testRunner/testRunner.vcxproj +++ b/NetService/src/test/testRunner/testRunner.vcxproj @@ -101,7 +101,7 @@ true - cppunitd.lib;%(AdditionalDependencies) + ../../../../ThirdLibs/VisualLeakDetector/lib/win32/vld.lib;cppunitd.lib;%(AdditionalDependencies) @@ -159,15 +159,48 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/NetService/src/test/testRunner/testRunner.vcxproj.filters b/NetService/src/test/testRunner/testRunner.vcxproj.filters index c49d9346..a22ebc5c 100644 --- a/NetService/src/test/testRunner/testRunner.vcxproj.filters +++ b/NetService/src/test/testRunner/testRunner.vcxproj.filters @@ -13,6 +13,15 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {4fde6400-70fe-44a3-adac-64bb5050f940} + + + {76b98a06-4d93-40c6-83c8-9ec3980b8efe} + + + {2a5c846d-5123-4a5d-97e9-bc6275cb280c} + @@ -24,20 +33,115 @@ Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files + + Source Files + + + Message\MsgDataValue + + + Message\MsgDataValue + + + Message\MsgDataValue + + + Message + + + Message + + + Message + + + Message + + + Message + + + Message + + + Tinyxml + + + Tinyxml + + + Tinyxml + + + Tinyxml + + + + + Message\MsgDataValue + + + Message\MsgDataValue + + + Message\MsgDataValue + + + Message\MsgDataValue + + + Message\MsgDataValue + + + Message + + + Message + + + Message + + + Message + + + Message + + + Message + + + Message + + + Message + + + Message + + + Message + + + Tinyxml + + + Tinyxml + \ No newline at end of file diff --git a/NetService/src/test/testRunner/userinfo b/NetService/src/test/testRunner/userinfo new file mode 100644 index 00000000..11fabb24 Binary files /dev/null and b/NetService/src/test/testRunner/userinfo differ diff --git a/NetService/src/test/testUserManage.cpp b/NetService/src/test/testUserManage.cpp index fa08fddd..4f7534b0 100644 --- a/NetService/src/test/testUserManage.cpp +++ b/NetService/src/test/testUserManage.cpp @@ -1,19 +1,20 @@ #include #include #include "../UserManage.hpp" - +#include "../FileUserStorage.h" +#include "../Room.cpp" class CUserManageTest : public CppUnit::TestFixture { private: - CPPUNIT_TEST_SUITE( CUserManageTest ); - CPPUNIT_TEST( AuthenticateTest ); + CPPUNIT_TEST_SUITE( CUserManageTest ); + CPPUNIT_TEST( AuthenticateTest ); CPPUNIT_TEST_SUITE_END(); - CUserManage um; + public: void setUp() { - + } void tearDown() { @@ -22,14 +23,23 @@ class CUserManageTest : public CppUnit::TestFixture public: void AuthenticateTest() { - - string strUser = "user00"; - char strPassword[20] = "0000000000000000000"; - userinfo stInfo = {}; - CPPUNIT_ASSERT(um.Authenticate(strUser, (char*)strPassword, &stInfo)); - + fUserStorage us; + CUserManage::GetInstance()->initial(&us); + char strUser0[] = "user00"; //û + char strPassword0[40] = "00000000000000000000000000000000000000"; + userinfo stInfo0 = {}; + CPPUNIT_ASSERT(CUserManage::GetInstance()->Authenticate( strUser0, (char*)strPassword0, &stInfo0)); + char strUser1[] = "admin"; //ɹ½ + char strPassword1[40] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + userinfo stInfo1 = {}; + CPPUNIT_ASSERT(CUserManage::GetInstance()->Authenticate( strUser1, (char*)strPassword1, &stInfo1)); + char strUser2[] = "able"; // + char strPassword2[40] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + userinfo stInfo2 = {}; + CPPUNIT_ASSERT(CUserManage::GetInstance()->Authenticate( strUser2, (char*)strPassword2, &stInfo2)); + } }; -CPPUNIT_TEST_SUITE_REGISTRATION ( CUserManageTest ); +CPPUNIT_TEST_SUITE_REGISTRATION ( CUserManageTest ); CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CUserManageTest, "CUserManageTest"); \ No newline at end of file diff --git a/NetService/src/testUserManage.cpp b/NetService/src/testUserManage.cpp deleted file mode 100644 index b744fdc3..00000000 --- a/NetService/src/testUserManage.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include "UserManage.hpp" - - -class CUserManageTest : public CppUnit::TestFixture -{ -private: - CPPUNIT_TEST_SUITE( CUserManageTest ); - CPPUNIT_TEST( AuthenticateTest ); - CPPUNIT_TEST_SUITE_END(); - CUserManage um; -public: - void setUp() - { - - } - void tearDown() - { - - } -public: - void AuthenticateTest() - { - - string strUser = "user00"; - char strPassword[20] = "0000000000000000000"; - userinfo stInfo = {}; - CPPUNIT_ASSERT(um.Authenticate(strUser, (char*)strPassword, &stInfo)); - - } - -}; -CPPUNIT_TEST_SUITE_REGISTRATION ( CUserManageTest ); -CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CUserManageTest, "CUserManageTest"); \ No newline at end of file diff --git a/NetService/src/util.hpp b/NetService/src/util.hpp index d278a089..ec0c052a 100644 --- a/NetService/src/util.hpp +++ b/NetService/src/util.hpp @@ -1,7 +1,40 @@ #pragma once #ifndef UTIL_H_ #define UTIL_H_ +#include +#include +using namespace std; +class smart_buf_imp{ +public: + smart_buf_imp(char *raw){ + this->buf_ = raw; + } + smart_buf_imp():buf_(NULL){}; + ~smart_buf_imp(){ + delete[] buf_; + } + operator char *(){ + return buf_; + } +private: + mutable char *buf_; + smart_buf_imp(const smart_buf_imp &other){} + smart_buf_imp &operator =(const smart_buf_imp &other){} +}; +class smart_buf{ +public: + smart_buf(char *raw):imp_(new smart_buf_imp(raw)){} + + operator char *(){ + return (char *)(*imp_); + } + operator unsigned char *(){ + return (unsigned char*)(char *)*this; + } +private: + shared_ptr imp_; +}; #endif //UTIL_H_ diff --git a/NetService/userinfo b/NetService/userinfo new file mode 100644 index 00000000..11fabb24 Binary files /dev/null and b/NetService/userinfo differ diff --git a/NetService/vnoc.conf b/NetService/vnoc.conf index 4718b991..5a2a0a15 100644 --- a/NetService/vnoc.conf +++ b/NetService/vnoc.conf @@ -1 +1,9 @@ -port=2508 \ No newline at end of file +#vnoc server +port=2508 + +#user database +sql_host=xxy1991.dlinkddns.com +sql_port=3306 +sql_username=vnoc +sql_password=ldldld +user_db=vnoc \ No newline at end of file diff --git a/README.md b/README.md index 781331ab..bd39f8d0 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,8 @@ vnoc +==== + +简介:程序员交流聊天工具 +==== + +交流QQ群:161902175 ! ==== \ No newline at end of file diff --git a/TestClient/NetClient.cpp b/TestClient/NetClient.cpp deleted file mode 100644 index 094bb4cf..00000000 --- a/TestClient/NetClient.cpp +++ /dev/null @@ -1,61 +0,0 @@ - -#include "NetClient.h" - - - -NetClient::NetClient(BYTE mainVer /* = 2 */,BYTE minorVer /* = 2 */) -{ - WORD socketVer = MAKEWORD(minorVer,mainVer); - WSADATA wsaData; - if (::WSAStartup(socketVer,&wsaData) != 0) - { - //ʼsocketʧ - return; - } -} - - -NetClient::~NetClient() -{ - ::WSACleanup(); - if (m_hSocket != NULL) - { - this->CloseSocket(); - m_hSocket = NULL; - } -} - - -void NetClient::SetLinkAttribute(u_short Port,LPCTSTR Addr,short _family) -{ - if (Addr != 0||Port != 0||_family != 0) - { - m_sockAddr.sin_family = _family; - m_sockAddr.sin_addr.S_un.S_addr = inet_addr(Addr); - m_sockAddr.sin_port = ::htons(Port); - } -} - -bool NetClient::CreateSocket(u_short Port,LPCTSTR Addr,int Type,short _family /* = AF_INET */,int Protocol /* = 0 */) -{ - if (m_hSocket != NULL) - { - return false; - } - this->SetLinkAttribute(Port,Addr,_family); - m_hSocket = ::socket(AF_INET,Type,Protocol); - if (m_hSocket != INVALID_SOCKET) - { - return true; - } - return false; -} - -bool NetClient::CloseSocket() -{ - if (::closesocket(m_hSocket)!= INVALID_SOCKET) - { - return true; - } - return false; -} \ No newline at end of file diff --git a/TestClient/NetClient.h b/TestClient/NetClient.h deleted file mode 100644 index cc78fc3d..00000000 --- a/TestClient/NetClient.h +++ /dev/null @@ -1,40 +0,0 @@ - -#ifndef MET_CLIENT -#define MET_CLIENT - -#include - -#pragma comment(lib,"WS2_32") - - -#define VNOC_SOC_S 0; -#define VNOC_SOC_F -1; - -class NetClient -{ -public: - NetClient(BYTE mainVer = 2,BYTE minorVer = 2); - virtual ~NetClient(); - - bool CreateSocket(u_short Port,LPCTSTR Addr,int Type,short _family = AF_INET,int Protocol = 0); - bool CloseSocket(); - -/* - int Monitor(); - int ShutMonitor(); - - int Message();*/ - - -public: - - virtual void SetLinkAttribute(u_short Port,LPCTSTR Addr,short _family); - - sockaddr_in m_sockAddr; - -/*private:*/ - - SOCKET m_hSocket; -}; - -#endif \ No newline at end of file diff --git a/TestClient/main.cpp b/TestClient/main.cpp deleted file mode 100644 index 8bd4afa9..00000000 --- a/TestClient/main.cpp +++ /dev/null @@ -1,70 +0,0 @@ - -#include "NetClient.h" -#include - -using namespace std; - -NetClient Test; - -int main() -{ - // ׽ - SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if(sListen == INVALID_SOCKET) - { - printf("Failed socket() \n"); - return 0; - } - - // sockaddr_inṹ - sockaddr_in sin; - sin.sin_family = AF_INET; - sin.sin_port = htons(5555); - sin.sin_addr.S_un.S_addr = INADDR_ANY; - - // ׽ֵһصַ - if(::bind(sListen, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) - { - printf("Failed bind() \n"); - return 0; - } - - // ģʽ - if(::listen(sListen, 2) == SOCKET_ERROR) - { - printf("Failed listen() \n"); - return 0; - } - - // ѭܿͻ - sockaddr_in remoteAddr; - int nAddrLen = sizeof(remoteAddr); - SOCKET sClient; - char szText[] = ""; - char szRecv[256] = {0}; - while(TRUE) - { - // һ - sClient = ::accept(sListen, (SOCKADDR*)&remoteAddr, &nAddrLen); - if(sClient == INVALID_SOCKET) - { - printf("Failed accept()"); - continue; - } - - printf(" ܵһӣ%s \r\n", inet_ntoa(remoteAddr.sin_addr)); - - // ͻ˷ - ::send(sClient, szText, strlen(szText), 0); - - ::recv(sClient,szRecv,256,0); - printf(" ܵһϢ%s \n",szRecv); - // رͬͻ˵ - ::closesocket(sClient); - } - - // رռ׽ - ::closesocket(sListen); - - return 0; -} \ No newline at end of file diff --git a/TinyXML/tinystr.cpp b/ThirdLibs/TinyXML/tinystr.cpp similarity index 96% rename from TinyXML/tinystr.cpp rename to ThirdLibs/TinyXML/tinystr.cpp index f53d8c98..68125071 100644 --- a/TinyXML/tinystr.cpp +++ b/ThirdLibs/TinyXML/tinystr.cpp @@ -1,5 +1,6 @@ /* www.sourceforge.net/projects/tinyxml +Original file by Yves Berquin. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -21,8 +22,13 @@ must not be misrepresented as being the original software. distribution. */ +/* + * THIS FILE WAS ALTERED BY Tyge Lvset, 7. April 2005. + */ + #ifndef TIXML_USE_STL + #include "tinystr.h" // Error value for find primitive diff --git a/TinyXML/tinystr.h b/ThirdLibs/TinyXML/tinystr.h similarity index 93% rename from TinyXML/tinystr.h rename to ThirdLibs/TinyXML/tinystr.h index 89cca334..3c2aa9d5 100644 --- a/TinyXML/tinystr.h +++ b/ThirdLibs/TinyXML/tinystr.h @@ -1,5 +1,6 @@ /* www.sourceforge.net/projects/tinyxml +Original file by Yves Berquin. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -21,6 +22,17 @@ must not be misrepresented as being the original software. distribution. */ +/* + * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. + * + * - completely rewritten. compact, clean, and fast implementation. + * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems) + * - fixed reserve() to work as per specification. + * - fixed buggy compares operator==(), operator<(), and operator>() + * - fixed operator+=() to take a const ref argument, following spec. + * - added "copy" constructor with length, and most compare operators. + * - added swap(), clear(), size(), capacity(), operator+(). + */ #ifndef TIXML_USE_STL @@ -94,11 +106,13 @@ class TiXmlString quit(); } + // = operator TiXmlString& operator = (const char * copy) { return assign( copy, (size_type)strlen(copy)); } + // = operator TiXmlString& operator = (const TiXmlString & copy) { return assign(copy.start(), copy.length()); diff --git a/TinyXML/tinyxml.cpp b/ThirdLibs/TinyXML/tinyxml.cpp similarity index 81% rename from TinyXML/tinyxml.cpp rename to ThirdLibs/TinyXML/tinyxml.cpp index 53320d93..5de21f6d 100644 --- a/TinyXML/tinyxml.cpp +++ b/ThirdLibs/TinyXML/tinyxml.cpp @@ -1,6 +1,6 @@ /* www.sourceforge.net/projects/tinyxml -Original code by Lee Thomason (www.grinninglizard.com) +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -21,6 +21,7 @@ must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ + #include #ifdef TIXML_USE_STL @@ -30,7 +31,6 @@ distribution. #include "tinyxml.h" -FILE* TiXmlFOpen( const char* filename, const char* mode ); bool TiXmlBase::condenseWhiteSpace = true; @@ -161,7 +161,6 @@ void TiXmlNode::CopyTo( TiXmlNode* target ) const { target->SetValue (value.c_str() ); target->userData = userData; - target->location = location; } @@ -187,11 +186,10 @@ TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) assert( node->parent == 0 || node->parent == this ); assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); - if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) + if ( node->Type() == TiXmlNode::DOCUMENT ) { delete node; - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); return 0; } @@ -212,10 +210,9 @@ TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) { - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + if ( addThis.Type() == TiXmlNode::DOCUMENT ) { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); return 0; } TiXmlNode* node = addThis.Clone(); @@ -231,10 +228,9 @@ TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& if ( !beforeThis || beforeThis->parent != this ) { return 0; } - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + if ( addThis.Type() == TiXmlNode::DOCUMENT ) { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); return 0; } @@ -264,10 +260,9 @@ TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& a if ( !afterThis || afterThis->parent != this ) { return 0; } - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + if ( addThis.Type() == TiXmlNode::DOCUMENT ) { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); return 0; } @@ -294,20 +289,9 @@ TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& a TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) { - if ( !replaceThis ) - return 0; - if ( replaceThis->parent != this ) return 0; - if ( withThis.ToDocument() ) { - // A document can never be a child. Thanks to Noam. - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - TiXmlNode* node = withThis.Clone(); if ( !node ) return 0; @@ -333,10 +317,6 @@ TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& wit bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) { - if ( !removeThis ) { - return false; - } - if ( removeThis->parent != this ) { assert( 0 ); @@ -522,7 +502,7 @@ const TiXmlDocument* TiXmlNode::GetDocument() const TiXmlElement::TiXmlElement (const char * _value) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) + : TiXmlNode( TiXmlNode::ELEMENT ) { firstChild = lastChild = 0; value = _value; @@ -531,7 +511,7 @@ TiXmlElement::TiXmlElement (const char * _value) #ifdef TIXML_USE_STL TiXmlElement::TiXmlElement( const std::string& _value ) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) + : TiXmlNode( TiXmlNode::ELEMENT ) { firstChild = lastChild = 0; value = _value; @@ -540,18 +520,17 @@ TiXmlElement::TiXmlElement( const std::string& _value ) TiXmlElement::TiXmlElement( const TiXmlElement& copy) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) + : TiXmlNode( TiXmlNode::ELEMENT ) { firstChild = lastChild = 0; copy.CopyTo( this ); } -TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base ) +void TiXmlElement::operator=( const TiXmlElement& base ) { ClearThis(); base.CopyTo( this ); - return *this; } @@ -585,9 +564,9 @@ const char* TiXmlElement::Attribute( const char* name ) const #ifdef TIXML_USE_STL const std::string* TiXmlElement::Attribute( const std::string& name ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( attrib ) - return &attrib->ValueStr(); + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return &node->ValueStr(); return 0; } #endif @@ -595,202 +574,195 @@ const std::string* TiXmlElement::Attribute( const std::string& name ) const const char* TiXmlElement::Attribute( const char* name, int* i ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const char* result = 0; - - if ( attrib ) { - result = attrib->Value(); - if ( i ) { - attrib->QueryIntValue( i ); + const char* s = Attribute( name ); + if ( i ) + { + if ( s ) { + *i = atoi( s ); + } + else { + *i = 0; } } - return result; + return s; } #ifdef TIXML_USE_STL const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const std::string* result = 0; - - if ( attrib ) { - result = &attrib->ValueStr(); - if ( i ) { - attrib->QueryIntValue( i ); + const std::string* s = Attribute( name ); + if ( i ) + { + if ( s ) { + *i = atoi( s->c_str() ); + } + else { + *i = 0; } } - return result; + return s; } #endif const char* TiXmlElement::Attribute( const char* name, double* d ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const char* result = 0; - - if ( attrib ) { - result = attrib->Value(); - if ( d ) { - attrib->QueryDoubleValue( d ); + const char* s = Attribute( name ); + if ( d ) + { + if ( s ) { + *d = atof( s ); + } + else { + *d = 0; } } - return result; + return s; } #ifdef TIXML_USE_STL const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const std::string* result = 0; - - if ( attrib ) { - result = &attrib->ValueStr(); - if ( d ) { - attrib->QueryDoubleValue( d ); + const std::string* s = Attribute( name ); + if ( d ) + { + if ( s ) { + *d = atof( s->c_str() ); + } + else { + *d = 0; } } - return result; + return s; } #endif int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryIntValue( ival ); -} - - -int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const { const TiXmlAttribute* node = attributeSet.Find( name ); if ( !node ) return TIXML_NO_ATTRIBUTE; - - int ival = 0; - int result = node->QueryIntValue( &ival ); - *value = (unsigned)ival; - return result; -} - - -int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - int result = TIXML_WRONG_TYPE; - if ( StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) ) - { - *bval = true; - result = TIXML_SUCCESS; - } - else if ( StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) ) - { - *bval = false; - result = TIXML_SUCCESS; - } - return result; + return node->QueryIntValue( ival ); } - #ifdef TIXML_USE_STL int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) return TIXML_NO_ATTRIBUTE; - return attrib->QueryIntValue( ival ); + return node->QueryIntValue( ival ); } #endif int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) return TIXML_NO_ATTRIBUTE; - return attrib->QueryDoubleValue( dval ); + return node->QueryDoubleValue( dval ); } #ifdef TIXML_USE_STL int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) return TIXML_NO_ATTRIBUTE; - return attrib->QueryDoubleValue( dval ); + return node->QueryDoubleValue( dval ); } #endif void TiXmlElement::SetAttribute( const char * name, int val ) { - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetIntValue( val ); - } + char buf[64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); + #else + sprintf( buf, "%d", val ); + #endif + SetAttribute( name, buf ); } #ifdef TIXML_USE_STL void TiXmlElement::SetAttribute( const std::string& name, int val ) { - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetIntValue( val ); - } + std::ostringstream oss; + oss << val; + SetAttribute( name, oss.str() ); } #endif void TiXmlElement::SetDoubleAttribute( const char * name, double val ) { - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetDoubleValue( val ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetDoubleValue( val ); - } + char buf[256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); + #else + sprintf( buf, "%f", val ); + #endif + SetAttribute( name, buf ); } -#endif void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) { - TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); - if ( attrib ) { - attrib->SetValue( cvalue ); + #ifdef TIXML_USE_STL + TIXML_STRING _name( cname ); + TIXML_STRING _value( cvalue ); + #else + const char* _name = cname; + const char* _value = cvalue; + #endif + + TiXmlAttribute* node = attributeSet.Find( _name ); + if ( node ) + { + node->SetValue( _value ); + return; + } + + TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue ); + if ( attrib ) + { + attributeSet.Add( attrib ); + } + else + { + TiXmlDocument* document = GetDocument(); + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); } } #ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value ) +void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value ) { - TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name ); - if ( attrib ) { - attrib->SetValue( _value ); + TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + { + node->SetValue( _value ); + return; + } + + TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); + if ( attrib ) + { + attributeSet.Add( attrib ); + } + else + { + TiXmlDocument* document = GetDocument(); + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); } } #endif @@ -909,14 +881,14 @@ const char* TiXmlElement::GetText() const } -TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) { tabsize = 4; useMicrosoftBOM = false; ClearError(); } -TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) { tabsize = 4; useMicrosoftBOM = false; @@ -926,7 +898,7 @@ TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode #ifdef TIXML_USE_STL -TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) { tabsize = 4; useMicrosoftBOM = false; @@ -936,33 +908,49 @@ TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiX #endif -TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) { copy.CopyTo( this ); } -TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy ) +void TiXmlDocument::operator=( const TiXmlDocument& copy ) { Clear(); copy.CopyTo( this ); - return *this; } bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) { + // See STL_STRING_BUG below. + //StringToBuffer buf( value ); + return LoadFile( Value(), encoding ); } bool TiXmlDocument::SaveFile() const { + // See STL_STRING_BUG below. +// StringToBuffer buf( value ); +// +// if ( buf.buffer && SaveFile( buf.buffer ) ) +// return true; +// +// return false; return SaveFile( Value() ); } bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) { + // There was a really terrifying little bug here. The code: + // value = filename + // in the STL case, cause the assignment method of the std::string to + // be called. What is strange, is that the std::string had the same + // address as it's c_str() method, and so bad things happen. Looks + // like a bug in the Microsoft STL implementation. + // Add an extra string to avoid the crash. TIXML_STRING filename( _filename ); value = filename; @@ -1007,6 +995,11 @@ bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) return false; } + // If we have a file, assume it is all one big XML file, and read it in. + // The document parser may decide the document ends sooner than the entire file, however. + TIXML_STRING data; + data.reserve( length ); + // Subtle bug here. TinyXml did use fgets. But from the XML spec: // 2.11 End-of-Line Handling // @@ -1037,46 +1030,58 @@ bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) return false; } - // Process the buffer in place to normalize new lines. (See comment above.) - // Copies from the 'p' to 'q' pointer, where p can advance faster if - // a newline-carriage return is hit. - // - // Wikipedia: - // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or - // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)... - // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others - // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS - // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9 - - const char* p = buf; // the read head - char* q = buf; // the write head - const char CR = 0x0d; - const char LF = 0x0a; + const char* lastPos = buf; + const char* p = buf; buf[length] = 0; while( *p ) { assert( p < (buf+length) ); - assert( q <= (buf+length) ); - assert( q <= p ); - - if ( *p == CR ) { - *q++ = LF; - p++; - if ( *p == LF ) { // check for CR+LF (and skip LF) - p++; + if ( *p == 0xa ) { + // Newline character. No special rules for this. Append all the characters + // since the last string, and include the newline. + data.append( lastPos, (p-lastPos+1) ); // append, include the newline + ++p; // move past the newline + lastPos = p; // and point to the new buffer (may be 0) + assert( p <= (buf+length) ); + } + else if ( *p == 0xd ) { + // Carriage return. Append what we have so far, then + // handle moving forward in the buffer. + if ( (p-lastPos) > 0 ) { + data.append( lastPos, p-lastPos ); // do not add the CR + } + data += (char)0xa; // a proper newline + + if ( *(p+1) == 0xa ) { + // Carriage return - new line sequence + p += 2; + lastPos = p; + assert( p <= (buf+length) ); + } + else { + // it was followed by something else...that is presumably characters again. + ++p; + lastPos = p; + assert( p <= (buf+length) ); } } else { - *q++ = *p++; + ++p; } } - assert( q <= (buf+length) ); - *q = 0; + // Handle any left over characters. + if ( p-lastPos ) { + data.append( lastPos, p-lastPos ); + } + delete [] buf; + buf = 0; - Parse( buf, 0, encoding ); + Parse( data.c_str(), 0, encoding ); - delete [] buf; - return !Error(); + if ( Error() ) + return false; + else + return true; } @@ -1215,7 +1220,7 @@ void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) cons if (value.find ('\"') == TIXML_STRING::npos) { if ( cfile ) { - fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); + fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); } if ( str ) { (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; @@ -1223,7 +1228,7 @@ void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) cons } else { if ( cfile ) { - fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); + fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); } if ( str ) { (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; @@ -1261,9 +1266,9 @@ void TiXmlAttribute::SetDoubleValue( double _value ) { char buf [256]; #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value); + TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); #else - sprintf (buf, "%g", _value); + sprintf (buf, "%lf", _value); #endif SetValue (buf); } @@ -1279,17 +1284,16 @@ double TiXmlAttribute::DoubleValue() const } -TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) +TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) { copy.CopyTo( this ); } -TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base ) +void TiXmlComment::operator=( const TiXmlComment& base ) { Clear(); base.CopyTo( this ); - return *this; } @@ -1378,7 +1382,7 @@ TiXmlNode* TiXmlText::Clone() const TiXmlDeclaration::TiXmlDeclaration( const char * _version, const char * _encoding, const char * _standalone ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) + : TiXmlNode( TiXmlNode::DECLARATION ) { version = _version; encoding = _encoding; @@ -1390,7 +1394,7 @@ TiXmlDeclaration::TiXmlDeclaration( const char * _version, TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, const std::string& _encoding, const std::string& _standalone ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) + : TiXmlNode( TiXmlNode::DECLARATION ) { version = _version; encoding = _encoding; @@ -1400,17 +1404,16 @@ TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) + : TiXmlNode( TiXmlNode::DECLARATION ) { copy.CopyTo( this ); } -TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) +void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) { Clear(); copy.CopyTo( this ); - return *this; } @@ -1545,9 +1548,9 @@ void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) #ifdef TIXML_USE_STL -TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const +const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const { - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) { if ( node->name == name ) return node; @@ -1555,22 +1558,23 @@ TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const return 0; } -TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) +/* +TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) { - TiXmlAttribute* attrib = Find( _name ); - if ( !attrib ) { - attrib = new TiXmlAttribute(); - Add( attrib ); - attrib->SetName( _name ); + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; } - return attrib; + return 0; } +*/ #endif -TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const +const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const { - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) { if ( strcmp( node->name.c_str(), name ) == 0 ) return node; @@ -1578,18 +1582,17 @@ TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const return 0; } - -TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) +/* +TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) { - TiXmlAttribute* attrib = Find( _name ); - if ( !attrib ) { - attrib = new TiXmlAttribute(); - Add( attrib ); - attrib->SetName( _name ); + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; } - return attrib; + return 0; } - +*/ #ifdef TIXML_USE_STL std::istream& operator>> (std::istream & in, TiXmlNode & base) diff --git a/TinyXML/tinyxml.h b/ThirdLibs/TinyXML/tinyxml.h similarity index 94% rename from TinyXML/tinyxml.h rename to ThirdLibs/TinyXML/tinyxml.h index c13ba392..c6f40cc2 100644 --- a/TinyXML/tinyxml.h +++ b/ThirdLibs/TinyXML/tinyxml.h @@ -1,6 +1,6 @@ /* www.sourceforge.net/projects/tinyxml -Original code by Lee Thomason (www.grinninglizard.com) +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -43,8 +43,6 @@ distribution. #define DEBUG #endif -#define TIXML_USE_STL - #ifdef TIXML_USE_STL #include #include @@ -65,19 +63,21 @@ distribution. #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) // Microsoft visual studio, version 2005 and higher. #define TIXML_SNPRINTF _snprintf_s + #define TIXML_SNSCANF _snscanf_s #define TIXML_SSCANF sscanf_s #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) // Microsoft visual studio, version 6 and higher. //#pragma message( "Using _sn* functions." ) #define TIXML_SNPRINTF _snprintf + #define TIXML_SNSCANF _snscanf #define TIXML_SSCANF sscanf #elif defined(__GNUC__) && (__GNUC__ >= 3 ) // GCC version 3 and higher.s //#warning( "Using sn* functions." ) #define TIXML_SNPRINTF snprintf + #define TIXML_SNSCANF snscanf #define TIXML_SSCANF sscanf #else - #define TIXML_SNPRINTF snprintf #define TIXML_SSCANF sscanf #endif #endif @@ -92,8 +92,8 @@ class TiXmlDeclaration; class TiXmlParsingData; const int TIXML_MAJOR_VERSION = 2; -const int TIXML_MINOR_VERSION = 6; -const int TIXML_PATCH_VERSION = 2; +const int TIXML_MINOR_VERSION = 5; +const int TIXML_PATCH_VERSION = 3; /* Internal structure for tracking location of items in the XML file. @@ -109,11 +109,10 @@ struct TiXmlCursor /** - Implements the interface to the "Visitor pattern" (see the Accept() method.) If you call the Accept() method, it requires being passed a TiXmlVisitor class to handle callbacks. For nodes that contain other nodes (Document, Element) you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves - are simply called with Visit(). + are simple called with Visit(). If you return 'true' from a Visit method, recursive parsing will continue. If you return false, no children of this node or its sibilings will be Visited. @@ -148,7 +147,7 @@ class TiXmlVisitor virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } /// Visit a comment node virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } - /// Visit an unknown node + /// Visit an unknow node virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } }; @@ -268,6 +267,7 @@ class TiXmlBase TIXML_NO_ERROR = 0, TIXML_ERROR, TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_OUT_OF_MEMORY, TIXML_ERROR_PARSING_ELEMENT, TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, TIXML_ERROR_READING_ELEMENT_VALUE, @@ -288,7 +288,6 @@ class TiXmlBase protected: static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); - inline static bool IsWhiteSpace( char c ) { return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); @@ -463,13 +462,13 @@ class TiXmlNode : public TiXmlBase */ enum NodeType { - TINYXML_DOCUMENT, - TINYXML_ELEMENT, - TINYXML_COMMENT, - TINYXML_UNKNOWN, - TINYXML_TEXT, - TINYXML_DECLARATION, - TINYXML_TYPECOUNT + DOCUMENT, + ELEMENT, + COMMENT, + UNKNOWN, + TEXT, + DECLARATION, + TYPECOUNT }; virtual ~TiXmlNode(); @@ -680,8 +679,8 @@ class TiXmlNode : public TiXmlBase #endif /** Query the type (as an enumerated value, above) of this node. - The possible types are: TINYXML_DOCUMENT, TINYXML_ELEMENT, TINYXML_COMMENT, - TINYXML_UNKNOWN, TINYXML_TEXT, and TINYXML_DECLARATION. + The possible types are: DOCUMENT, ELEMENT, COMMENT, + UNKNOWN, TEXT, and DECLARATION. */ int Type() const { return type; } @@ -916,14 +915,17 @@ class TiXmlAttributeSet const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Find( const char* _name ) const; - TiXmlAttribute* FindOrCreate( const char* _name ); - -# ifdef TIXML_USE_STL - TiXmlAttribute* Find( const std::string& _name ) const; - TiXmlAttribute* FindOrCreate( const std::string& _name ); -# endif + const TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* Find( const char* _name ) { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); + } + #ifdef TIXML_USE_STL + const TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* Find( const std::string& _name ) { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); + } + #endif private: //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), @@ -952,7 +954,7 @@ class TiXmlElement : public TiXmlNode TiXmlElement( const TiXmlElement& ); - TiXmlElement& operator=( const TiXmlElement& base ); + void operator=( const TiXmlElement& base ); virtual ~TiXmlElement(); @@ -985,13 +987,6 @@ class TiXmlElement : public TiXmlNode does not exist, then TIXML_NO_ATTRIBUTE is returned. */ int QueryIntAttribute( const char* name, int* _value ) const; - /// QueryUnsignedAttribute examines the attribute - see QueryIntAttribute(). - int QueryUnsignedAttribute( const char* name, unsigned* _value ) const; - /** QueryBoolAttribute examines the attribute - see QueryIntAttribute(). - Note that '1', 'true', or 'yes' are considered true, while '0', 'false' - and 'no' are considered false. - */ - int QueryBoolAttribute( const char* name, bool* _value ) const; /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). int QueryDoubleAttribute( const char* name, double* _value ) const; /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). @@ -1005,21 +1000,11 @@ class TiXmlElement : public TiXmlNode } #ifdef TIXML_USE_STL - /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). - int QueryStringAttribute( const char* name, std::string* _value ) const { - const char* cstr = Attribute( name ); - if ( cstr ) { - *_value = std::string( cstr ); - return TIXML_SUCCESS; - } - return TIXML_NO_ATTRIBUTE; - } - /** Template form of the attribute query which will try to read the attribute into the specified type. Very easy, very powerful, but be careful to make sure to call this with the correct type. - NOTE: This method doesn't work correctly for 'string' types that contain spaces. + NOTE: This method doesn't work correctly for 'string' types. @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE */ @@ -1035,8 +1020,13 @@ class TiXmlElement : public TiXmlNode return TIXML_SUCCESS; return TIXML_WRONG_TYPE; } - - int QueryValueAttribute( const std::string& name, std::string* outValue ) const + /* + This is - in theory - a bug fix for "QueryValueAtribute returns truncated std::string" + but template specialization is hard to get working cross-compiler. Leaving the bug for now. + + // The above will fail for std::string because the space character is used as a seperator. + // Specialize for strings. Bug [ 1695429 ] QueryValueAtribute returns truncated std::string + template<> int QueryValueAttribute( const std::string& name, std::string* outValue ) const { const TiXmlAttribute* node = attributeSet.Find( name ); if ( !node ) @@ -1044,6 +1034,7 @@ class TiXmlElement : public TiXmlNode *outValue = node->ValueStr(); return TIXML_SUCCESS; } + */ #endif /** Sets an attribute of name to a given value. The attribute @@ -1062,8 +1053,6 @@ class TiXmlElement : public TiXmlNode void SetAttribute( const std::string& name, const std::string& _value ); ///< STL std::string form. void SetAttribute( const std::string& name, int _value ); - ///< STL std::string form. - void SetDoubleAttribute( const std::string& name, double value ); #endif /** Sets an attribute of name to a given value. The attribute @@ -1155,6 +1144,7 @@ class TiXmlElement : public TiXmlNode const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); private: + TiXmlAttributeSet attributeSet; }; @@ -1165,13 +1155,13 @@ class TiXmlComment : public TiXmlNode { public: /// Constructs an empty comment. - TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} + TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} /// Construct a comment from text. - TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { + TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) { SetValue( _value ); } TiXmlComment( const TiXmlComment& ); - TiXmlComment& operator=( const TiXmlComment& base ); + void operator=( const TiXmlComment& base ); virtual ~TiXmlComment() {} @@ -1185,8 +1175,8 @@ class TiXmlComment : public TiXmlNode */ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. /** Walk the XML tree visiting this node and all of its children. */ @@ -1219,7 +1209,7 @@ class TiXmlText : public TiXmlNode normal, encoded text. If you want it be output as a CDATA text element, set the parameter _cdata to 'true' */ - TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT) { SetValue( initValue ); cdata = false; @@ -1228,15 +1218,15 @@ class TiXmlText : public TiXmlNode #ifdef TIXML_USE_STL /// Constructor. - TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) { SetValue( initValue ); cdata = false; } #endif - TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } - TiXmlText& operator=( const TiXmlText& base ) { base.CopyTo( this ); return *this; } + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } + void operator=( const TiXmlText& base ) { base.CopyTo( this ); } // Write this text object to a FILE stream. virtual void Print( FILE* cfile, int depth ) const; @@ -1288,7 +1278,7 @@ class TiXmlDeclaration : public TiXmlNode { public: /// Construct an empty declaration. - TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} + TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} #ifdef TIXML_USE_STL /// Constructor. @@ -1303,7 +1293,7 @@ class TiXmlDeclaration : public TiXmlNode const char* _standalone ); TiXmlDeclaration( const TiXmlDeclaration& copy ); - TiXmlDeclaration& operator=( const TiXmlDeclaration& copy ); + void operator=( const TiXmlDeclaration& copy ); virtual ~TiXmlDeclaration() {} @@ -1356,11 +1346,11 @@ class TiXmlDeclaration : public TiXmlNode class TiXmlUnknown : public TiXmlNode { public: - TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} + TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} virtual ~TiXmlUnknown() {} - TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } - TiXmlUnknown& operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); return *this; } + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } + void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } /// Creates a copy of this Unknown and returns it. virtual TiXmlNode* Clone() const; @@ -1369,8 +1359,8 @@ class TiXmlUnknown : public TiXmlNode virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. /** Walk the XML tree visiting this node and all of its children. */ @@ -1406,7 +1396,7 @@ class TiXmlDocument : public TiXmlNode #endif TiXmlDocument( const TiXmlDocument& copy ); - TiXmlDocument& operator=( const TiXmlDocument& copy ); + void operator=( const TiXmlDocument& copy ); virtual ~TiXmlDocument() {} @@ -1433,10 +1423,14 @@ class TiXmlDocument : public TiXmlNode #ifdef TIXML_USE_STL bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. { +// StringToBuffer f( filename ); +// return ( f.buffer && LoadFile( f.buffer, encoding )); return LoadFile( filename.c_str(), encoding ); } bool SaveFile( const std::string& filename ) const ///< STL std::string version. { +// StringToBuffer f( filename ); +// return ( f.buffer && SaveFile( f.buffer )); return SaveFile( filename.c_str() ); } #endif @@ -1644,7 +1638,7 @@ class TiXmlHandle TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } /// Copy constructor TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } - TiXmlHandle operator=( const TiXmlHandle& ref ) { if ( &ref != this ) this->node = ref.node; return *this; } + TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } /// Return a handle to the first child node. TiXmlHandle FirstChild() const; @@ -1805,3 +1799,4 @@ class TiXmlPrinter : public TiXmlVisitor #endif #endif + diff --git a/TinyXML/tinyxmlerror.cpp b/ThirdLibs/TinyXML/tinyxmlerror.cpp similarity index 94% rename from TinyXML/tinyxmlerror.cpp rename to ThirdLibs/TinyXML/tinyxmlerror.cpp index 6f248cf3..d24f63b2 100644 --- a/TinyXML/tinyxmlerror.cpp +++ b/ThirdLibs/TinyXML/tinyxmlerror.cpp @@ -21,6 +21,7 @@ must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ + #include "tinyxml.h" // The goal of the seperate error file is to make the first @@ -30,11 +31,12 @@ distribution. // It also cleans up the code a bit. // -const char* TiXmlBase::errorString[ TiXmlBase::TIXML_ERROR_STRING_COUNT ] = +const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] = { "No error", "Error", "Failed to open file", + "Memory allocation failed.", "Error parsing Element.", "Failed to read Element name", "Error reading Element value.", diff --git a/TinyXML/tinyxmlparser.cpp b/ThirdLibs/TinyXML/tinyxmlparser.cpp similarity index 96% rename from TinyXML/tinyxmlparser.cpp rename to ThirdLibs/TinyXML/tinyxmlparser.cpp index 0bf5b6dd..9c91b4f9 100644 --- a/TinyXML/tinyxmlparser.cpp +++ b/ThirdLibs/TinyXML/tinyxmlparser.cpp @@ -1,6 +1,6 @@ /* www.sourceforge.net/projects/tinyxml -Original code by Lee Thomason (www.grinninglizard.com) +Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -21,6 +21,7 @@ must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ + #include #include @@ -39,7 +40,7 @@ distribution. // Note tha "PutString" hardcodes the same list. This // is less flexible than it appears. Changing the entries // or order will break putstring. -TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] = +TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = { { "&", 5, '&' }, { "<", 4, '<' }, @@ -173,7 +174,7 @@ class TiXmlParsingData public: void Stamp( const char* now, TiXmlEncoding encoding ); - const TiXmlCursor& Cursor() const { return cursor; } + const TiXmlCursor& Cursor() { return cursor; } private: // Only used by the document! @@ -345,7 +346,7 @@ const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) continue; } - if ( IsWhiteSpace( *p ) ) // Still using old rules for white space. + if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. ++p; else break; @@ -353,7 +354,7 @@ const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) } else { - while ( *p && IsWhiteSpace( *p ) ) + while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) ++p; } @@ -630,9 +631,9 @@ const char* TiXmlBase::ReadText( const char* p, } } } - if ( p && *p ) + if ( p ) p += strlen( endTag ); - return ( p && *p ) ? p : 0; + return p; } #ifdef TIXML_USE_STL @@ -824,6 +825,7 @@ TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) return 0; } + TiXmlDocument* doc = GetDocument(); p = SkipWhiteSpace( p, encoding ); if ( !p || !*p ) @@ -894,6 +896,11 @@ TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) // Set the parent, so it can report errors returnNode->parent = this; } + else + { + if ( doc ) + doc->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); + } return returnNode; } @@ -1076,6 +1083,7 @@ const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc TIXML_STRING endTag (""; // Check for and read attributes. Also look for an empty // tag or an end tag. @@ -1114,20 +1122,10 @@ const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc } // We should find the end tag now - // note that: - // and - // - // are both valid end tags. if ( StringEqual( p, endTag.c_str(), false, encoding ) ) { p += endTag.length(); - p = SkipWhiteSpace( p, encoding ); - if ( p && *p && *p == '>' ) { - ++p; - return p; - } - if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); - return 0; + return p; } else { @@ -1141,6 +1139,7 @@ const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc TiXmlAttribute* attrib = new TiXmlAttribute(); if ( !attrib ) { + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding ); return 0; } @@ -1163,7 +1162,7 @@ const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc #endif if ( node ) { - if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding ); + node->SetValue( attrib->Value() ); delete attrib; return 0; } @@ -1192,7 +1191,8 @@ const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXm if ( !textNode ) { - return 0; + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, encoding ); + return 0; } if ( TiXmlBase::IsWhiteSpaceCondensed() ) @@ -1297,10 +1297,9 @@ const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc if ( !p ) { - if ( document ) - document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding ); + if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding ); } - if ( p && *p == '>' ) + if ( *p == '>' ) return p+1; return p; } @@ -1350,8 +1349,7 @@ const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc if ( !StringEqual( p, startTag, false, encoding ) ) { - if ( document ) - document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); + document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); return 0; } p += strlen( startTag ); @@ -1381,7 +1379,7 @@ const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc value.append( p, 1 ); ++p; } - if ( p && *p ) + if ( p ) p += strlen( endTag ); return p; @@ -1393,6 +1391,10 @@ const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlE p = SkipWhiteSpace( p, encoding ); if ( !p || !*p ) return 0; +// int tabsize = 4; +// if ( document ) +// tabsize = document->TabSize(); + if ( data ) { data->Stamp( p, encoding ); @@ -1444,7 +1446,7 @@ const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlE // its best, even without them. value = ""; while ( p && *p // existence - && !IsWhiteSpace( *p ) // whitespace + && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace && *p != '/' && *p != '>' ) // tag end { if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { @@ -1513,8 +1515,7 @@ const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncodi if ( !StringEqual( p, startTag, false, encoding ) ) { - if ( document ) - document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); + document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); return 0; } p += strlen( startTag ); @@ -1538,7 +1539,7 @@ const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncodi const char* end = "<"; p = ReadText( p, &value, ignoreWhite, end, false, encoding ); - if ( p && *p ) + if ( p ) return p-1; // don't truncate the '<' return 0; } diff --git a/VisualLeakDetector/bin/Win32/Microsoft.DTfW.DHL.manifest b/ThirdLibs/VisualLeakDetector/bin/Win32/Microsoft.DTfW.DHL.manifest similarity index 97% rename from VisualLeakDetector/bin/Win32/Microsoft.DTfW.DHL.manifest rename to ThirdLibs/VisualLeakDetector/bin/Win32/Microsoft.DTfW.DHL.manifest index 236ae6cc..e61222f0 100644 --- a/VisualLeakDetector/bin/Win32/Microsoft.DTfW.DHL.manifest +++ b/ThirdLibs/VisualLeakDetector/bin/Win32/Microsoft.DTfW.DHL.manifest @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/VisualLeakDetector/bin/Win32/dbghelp.dll b/ThirdLibs/VisualLeakDetector/bin/Win32/dbghelp.dll similarity index 100% rename from VisualLeakDetector/bin/Win32/dbghelp.dll rename to ThirdLibs/VisualLeakDetector/bin/Win32/dbghelp.dll diff --git a/VisualLeakDetector/bin/Win32/vld_x86.dll b/ThirdLibs/VisualLeakDetector/bin/Win32/vld_x86.dll similarity index 100% rename from VisualLeakDetector/bin/Win32/vld_x86.dll rename to ThirdLibs/VisualLeakDetector/bin/Win32/vld_x86.dll diff --git a/VisualLeakDetector/bin/Win64/Microsoft.DTfW.DHL.manifest b/ThirdLibs/VisualLeakDetector/bin/Win64/Microsoft.DTfW.DHL.manifest similarity index 97% rename from VisualLeakDetector/bin/Win64/Microsoft.DTfW.DHL.manifest rename to ThirdLibs/VisualLeakDetector/bin/Win64/Microsoft.DTfW.DHL.manifest index 40843368..1ea64d51 100644 --- a/VisualLeakDetector/bin/Win64/Microsoft.DTfW.DHL.manifest +++ b/ThirdLibs/VisualLeakDetector/bin/Win64/Microsoft.DTfW.DHL.manifest @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/VisualLeakDetector/bin/Win64/dbghelp.dll b/ThirdLibs/VisualLeakDetector/bin/Win64/dbghelp.dll similarity index 100% rename from VisualLeakDetector/bin/Win64/dbghelp.dll rename to ThirdLibs/VisualLeakDetector/bin/Win64/dbghelp.dll diff --git a/VisualLeakDetector/bin/Win64/vld_x64.dll b/ThirdLibs/VisualLeakDetector/bin/Win64/vld_x64.dll similarity index 100% rename from VisualLeakDetector/bin/Win64/vld_x64.dll rename to ThirdLibs/VisualLeakDetector/bin/Win64/vld_x64.dll diff --git a/VisualLeakDetector/include/vld.h b/ThirdLibs/VisualLeakDetector/include/vld.h similarity index 96% rename from VisualLeakDetector/include/vld.h rename to ThirdLibs/VisualLeakDetector/include/vld.h index 8307fa61..653b41fb 100644 --- a/VisualLeakDetector/include/vld.h +++ b/ThirdLibs/VisualLeakDetector/include/vld.h @@ -1,307 +1,307 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Visual Leak Detector - Import Library Header -// Copyright (c) 2005-2011 VLD Team -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -// -// See COPYING.txt for the full terms of the GNU Lesser General Public License. -// -//////////////////////////////////////////////////////////////////////////////// - -#pragma once - -#include "vld_def.h" - -#if defined _DEBUG || defined VLD_FORCE_ENABLE - -#include - -#pragma comment(lib, "vld.lib") - -// Force a symbolic reference to the global VisualLeakDetector class object from -// the DLL. This ensures that the DLL is loaded and linked with the program, -// even if no code otherwise imports any of the DLL's exports. -#pragma comment(linker, "/include:__imp_?g_vld@@3VVisualLeakDetector@@A") - -//////////////////////////////////////////////////////////////////////////////// -// -// Visual Leak Detector APIs -// - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -// VLDDisable - Disables Visual Leak Detector's memory leak detection at -// runtime. If memory leak detection is already disabled, then calling this -// function has no effect. -// -// Note: In multithreaded programs, this function operates on a per-thread -// basis. In other words, if you call this function from one thread, then -// memory leak detection is only disabled for that thread. If memory leak -// detection is enabled for other threads, then it will remain enabled for -// those other threads. It was designed to work this way to insulate you, -// the programmer, from having to ensure thread synchronization when calling -// VLDEnable() and VLDDisable(). Without this, calling these two functions -// unsynchronized could result in unpredictable and unintended behavior. -// But this also means that if you want to disable memory leak detection -// process-wide, then you need to call this function from every thread in -// the process. -// -// Return Value: -// -// None. -// -__declspec(dllimport) void VLDDisable (); - -// VLDEnable - Enables Visual Leak Detector's memory leak detection at runtime. -// If memory leak detection is already enabled, which it is by default, then -// calling this function has no effect. -// -// Note: In multithreaded programs, this function operates on a per-thread -// basis. In other words, if you call this function from one thread, then -// memory leak detection is only enabled for that thread. If memory leak -// detection is disabled for other threads, then it will remain disabled for -// those other threads. It was designed to work this way to insulate you, -// the programmer, from having to ensure thread synchronization when calling -// VLDEnable() and VLDDisable(). Without this, calling these two functions -// unsynchronized could result in unpredictable and unintended behavior. -// But this also means that if you want to enable memory leak detection -// process-wide, then you need to call this function from every thread in -// the process. -// -// Return Value: -// -// None. -// -__declspec(dllimport) void VLDEnable (); - -// VLDRestore - Restore Visual Leak Detector's previous state. -// -// Return Value: -// -// None. -// -__declspec(dllimport) void VLDRestore (); - -// VLDGlobalDisable - Disables Visual Leak Detector's memory leak detection at -// runtime in all threads. If memory leak detection is already disabled, -// then calling this function has no effect. -// -// Return Value: -// -// None. -// -__declspec(dllimport) void VLDGlobalDisable (); - -// VLDGlobalEnable - Enables Visual Leak Detector's memory leak detection -// at runtime in all threads. If memory leak detection is already enabled, -// which it is by default, then calling this function has no effect. -// -// Return Value: -// -// None. -// -__declspec(dllimport) void VLDGlobalEnable (); - -// VLDReportLeaks - Report leaks up to the execution point. -// -// Return Value: -// -// None. -// -__declspec(dllimport) UINT VLDReportLeaks (); - -// VLDGetLeaksCount - Return memory leaks count to the execution point. -// -// Return Value: -// -// None. -// -__declspec(dllimport) UINT VLDGetLeaksCount (); - -// VLDMarkAllLeaksAsReported - Mark all leaks as reported. -// -// Return Value: -// -// None. -// -__declspec(dllimport) void VLDMarkAllLeaksAsReported (); - - -// VLDRefreshModules - Look for recently loaded DLLs and patch them if necessary. -// -// Return Value: -// -// None. -// -__declspec(dllimport) void VLDRefreshModules(); - - -// VLDEnableModule - Enable Memory leak checking on the specified module. -// -// module: module handle. -// -// Return Value: -// -// None. -// - -__declspec(dllimport) void VLDEnableModule(HMODULE module); - - -// VLDDisableModule - Disable Memory leak checking on the specified module. -// -// module: module handle. -// -// Return Value: -// -// None. -// -__declspec(dllimport) void VLDDisableModule(HMODULE module); - -// VLDGetOptions - Return all current options. -// -// Return Value: -// -// Mask of current options. -// -__declspec(dllimport) UINT VLDGetOptions(); - -// VLDGetReportFilename - Return current report filename. -// -// filename: current report filename (max characters - MAX_PATH). -// -// Return Value: -// -// None. -// -__declspec(dllimport) void VLDGetReportFilename(WCHAR *filename); - -// VLDSetOptions - Update the report options via function call rather than INI file. -// -// option_mask: Only the following flags are checked -// VLD_OPT_AGGREGATE_DUPLICATES -// VLD_OPT_MODULE_LIST_INCLUDE -// VLD_OPT_SAFE_STACK_WALK -// VLD_OPT_SLOW_DEBUGGER_DUMP -// VLD_OPT_TRACE_INTERNAL_FRAMES -// VLD_OPT_START_DISABLED -// VLD_OPT_SKIP_HEAPFREE_LEAKS -// VLD_OPT_VALIDATE_HEAPFREE -// -// maxDataDump: maximum number of user-data bytes to dump for each leaked block. -// -// maxTraceFrames: maximum number of frames per stack trace for each leaked block. -// -// Return Value: -// -// None. -// -__declspec(dllimport) void VLDSetOptions(UINT option_mask, SIZE_T maxDataDump, UINT maxTraceFrames); - -// VLDSetModulesList - Set list of modules included/excluded in leak detection -// depending on parameter "includeModules". -// -// modules: list of modules to be forcefully included/excluded in leak detection. -// -// includeModules: include or exclude that modules. -// -// Return Value: -// -// None. -// -__declspec(dllimport) void VLDSetModulesList(CONST WCHAR *modules, BOOL includeModules); - -// VLDGetModulesList - Return current list of included/excluded modules -// depending on flag VLD_OPT_TRACE_INTERNAL_FRAMES. -// -// modules: destination string for list of included/excluded modules (maximum length 512 characters). -// -// size: maximum string size. -// -// Return Value: -// -// BOOL: TRUE if include modules, otherwise FALSE. -// -__declspec(dllimport) BOOL VLDGetModulesList(WCHAR *modules, UINT size); - -// VLDSetReportOptions - Update the report options via function call rather than INI file. -// -// Only the following flags are checked -// VLD_OPT_REPORT_TO_DEBUGGER -// VLD_OPT_REPORT_TO_FILE -// VLD_OPT_REPORT_TO_STDOUT -// VLD_OPT_UNICODE_REPORT -// -// filename is optional and can be NULL. -// -// Return Value: -// -// None. -// -__declspec(dllimport) void VLDSetReportOptions(UINT option_mask, CONST WCHAR *filename); - -// VLDSetReportHook - Installs or uninstalls a client-defined reporting function by hooking it -// into the C run-time debug reporting process (debug version only). -// -// mode: The action to take: VLD_RPTHOOK_INSTALL or VLD_RPTHOOK_REMOVE. -// -// pfnNewHook: Report hook to install or remove. -// -// Return Value: -// -// int: 0 if success. -// -__declspec(dllimport) int VLDSetReportHook(int mode, VLD_REPORT_HOOK pfnNewHook); - -// VLDResolveCallstacks - Performs symbol resolution for all saved extent CallStack's that have -// been tracked by Visual Leak Detector. This function is necessary for applications that -// dynamically load and unload modules, and through which memory leaks might be included. -// If this is NOT called, stack traces may have stack frames with no symbol information. This -// happens because the symbol API's cannot look up symbols for a binary / module that has been unloaded -// from the process. -// -// Return Value: -// -// None. -// -__declspec(dllexport) void VLDResolveCallstacks(); - -#ifdef __cplusplus -} -#endif // __cplusplus - -#else // !_DEBUG - -#define VLDEnable() -#define VLDDisable() -#define VLDRestore() -#define VLDReportLeaks() 0 -#define VLDGetLeaksCount() 0 -#define VLDMarkAllLeaksAsReported() -#define VLDRefreshModules() -#define VLDEnableModule(a) -#define VLDDisableModule(b) -#define VLDGetOptions() 0 -#define VLDGetReportFilename(a) -#define VLDSetOptions(a, b, c) -#define VLDSetReportHook(a, b) -#define VLDSetModulesList(a) -#define VLDGetModulesList(a, b) FALSE -#define VLDSetReportOptions(a, b) - -#endif // _DEBUG +//////////////////////////////////////////////////////////////////////////////// +// +// Visual Leak Detector - Import Library Header +// Copyright (c) 2005-2011 VLD Team +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// See COPYING.txt for the full terms of the GNU Lesser General Public License. +// +//////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "vld_def.h" + +#if defined _DEBUG || defined VLD_FORCE_ENABLE + +#include + +#pragma comment(lib, "vld.lib") + +// Force a symbolic reference to the global VisualLeakDetector class object from +// the DLL. This ensures that the DLL is loaded and linked with the program, +// even if no code otherwise imports any of the DLL's exports. +#pragma comment(linker, "/include:__imp_?g_vld@@3VVisualLeakDetector@@A") + +//////////////////////////////////////////////////////////////////////////////// +// +// Visual Leak Detector APIs +// + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// VLDDisable - Disables Visual Leak Detector's memory leak detection at +// runtime. If memory leak detection is already disabled, then calling this +// function has no effect. +// +// Note: In multithreaded programs, this function operates on a per-thread +// basis. In other words, if you call this function from one thread, then +// memory leak detection is only disabled for that thread. If memory leak +// detection is enabled for other threads, then it will remain enabled for +// those other threads. It was designed to work this way to insulate you, +// the programmer, from having to ensure thread synchronization when calling +// VLDEnable() and VLDDisable(). Without this, calling these two functions +// unsynchronized could result in unpredictable and unintended behavior. +// But this also means that if you want to disable memory leak detection +// process-wide, then you need to call this function from every thread in +// the process. +// +// Return Value: +// +// None. +// +__declspec(dllimport) void VLDDisable (); + +// VLDEnable - Enables Visual Leak Detector's memory leak detection at runtime. +// If memory leak detection is already enabled, which it is by default, then +// calling this function has no effect. +// +// Note: In multithreaded programs, this function operates on a per-thread +// basis. In other words, if you call this function from one thread, then +// memory leak detection is only enabled for that thread. If memory leak +// detection is disabled for other threads, then it will remain disabled for +// those other threads. It was designed to work this way to insulate you, +// the programmer, from having to ensure thread synchronization when calling +// VLDEnable() and VLDDisable(). Without this, calling these two functions +// unsynchronized could result in unpredictable and unintended behavior. +// But this also means that if you want to enable memory leak detection +// process-wide, then you need to call this function from every thread in +// the process. +// +// Return Value: +// +// None. +// +__declspec(dllimport) void VLDEnable (); + +// VLDRestore - Restore Visual Leak Detector's previous state. +// +// Return Value: +// +// None. +// +__declspec(dllimport) void VLDRestore (); + +// VLDGlobalDisable - Disables Visual Leak Detector's memory leak detection at +// runtime in all threads. If memory leak detection is already disabled, +// then calling this function has no effect. +// +// Return Value: +// +// None. +// +__declspec(dllimport) void VLDGlobalDisable (); + +// VLDGlobalEnable - Enables Visual Leak Detector's memory leak detection +// at runtime in all threads. If memory leak detection is already enabled, +// which it is by default, then calling this function has no effect. +// +// Return Value: +// +// None. +// +__declspec(dllimport) void VLDGlobalEnable (); + +// VLDReportLeaks - Report leaks up to the execution point. +// +// Return Value: +// +// None. +// +__declspec(dllimport) UINT VLDReportLeaks (); + +// VLDGetLeaksCount - Return memory leaks count to the execution point. +// +// Return Value: +// +// None. +// +__declspec(dllimport) UINT VLDGetLeaksCount (); + +// VLDMarkAllLeaksAsReported - Mark all leaks as reported. +// +// Return Value: +// +// None. +// +__declspec(dllimport) void VLDMarkAllLeaksAsReported (); + + +// VLDRefreshModules - Look for recently loaded DLLs and patch them if necessary. +// +// Return Value: +// +// None. +// +__declspec(dllimport) void VLDRefreshModules(); + + +// VLDEnableModule - Enable Memory leak checking on the specified module. +// +// module: module handle. +// +// Return Value: +// +// None. +// + +__declspec(dllimport) void VLDEnableModule(HMODULE module); + + +// VLDDisableModule - Disable Memory leak checking on the specified module. +// +// module: module handle. +// +// Return Value: +// +// None. +// +__declspec(dllimport) void VLDDisableModule(HMODULE module); + +// VLDGetOptions - Return all current options. +// +// Return Value: +// +// Mask of current options. +// +__declspec(dllimport) UINT VLDGetOptions(); + +// VLDGetReportFilename - Return current report filename. +// +// filename: current report filename (max characters - MAX_PATH). +// +// Return Value: +// +// None. +// +__declspec(dllimport) void VLDGetReportFilename(WCHAR *filename); + +// VLDSetOptions - Update the report options via function call rather than INI file. +// +// option_mask: Only the following flags are checked +// VLD_OPT_AGGREGATE_DUPLICATES +// VLD_OPT_MODULE_LIST_INCLUDE +// VLD_OPT_SAFE_STACK_WALK +// VLD_OPT_SLOW_DEBUGGER_DUMP +// VLD_OPT_TRACE_INTERNAL_FRAMES +// VLD_OPT_START_DISABLED +// VLD_OPT_SKIP_HEAPFREE_LEAKS +// VLD_OPT_VALIDATE_HEAPFREE +// +// maxDataDump: maximum number of user-data bytes to dump for each leaked block. +// +// maxTraceFrames: maximum number of frames per stack trace for each leaked block. +// +// Return Value: +// +// None. +// +__declspec(dllimport) void VLDSetOptions(UINT option_mask, SIZE_T maxDataDump, UINT maxTraceFrames); + +// VLDSetModulesList - Set list of modules included/excluded in leak detection +// depending on parameter "includeModules". +// +// modules: list of modules to be forcefully included/excluded in leak detection. +// +// includeModules: include or exclude that modules. +// +// Return Value: +// +// None. +// +__declspec(dllimport) void VLDSetModulesList(CONST WCHAR *modules, BOOL includeModules); + +// VLDGetModulesList - Return current list of included/excluded modules +// depending on flag VLD_OPT_TRACE_INTERNAL_FRAMES. +// +// modules: destination string for list of included/excluded modules (maximum length 512 characters). +// +// size: maximum string size. +// +// Return Value: +// +// BOOL: TRUE if include modules, otherwise FALSE. +// +__declspec(dllimport) BOOL VLDGetModulesList(WCHAR *modules, UINT size); + +// VLDSetReportOptions - Update the report options via function call rather than INI file. +// +// Only the following flags are checked +// VLD_OPT_REPORT_TO_DEBUGGER +// VLD_OPT_REPORT_TO_FILE +// VLD_OPT_REPORT_TO_STDOUT +// VLD_OPT_UNICODE_REPORT +// +// filename is optional and can be NULL. +// +// Return Value: +// +// None. +// +__declspec(dllimport) void VLDSetReportOptions(UINT option_mask, CONST WCHAR *filename); + +// VLDSetReportHook - Installs or uninstalls a client-defined reporting function by hooking it +// into the C run-time debug reporting process (debug version only). +// +// mode: The action to take: VLD_RPTHOOK_INSTALL or VLD_RPTHOOK_REMOVE. +// +// pfnNewHook: Report hook to install or remove. +// +// Return Value: +// +// int: 0 if success. +// +__declspec(dllimport) int VLDSetReportHook(int mode, VLD_REPORT_HOOK pfnNewHook); + +// VLDResolveCallstacks - Performs symbol resolution for all saved extent CallStack's that have +// been tracked by Visual Leak Detector. This function is necessary for applications that +// dynamically load and unload modules, and through which memory leaks might be included. +// If this is NOT called, stack traces may have stack frames with no symbol information. This +// happens because the symbol API's cannot look up symbols for a binary / module that has been unloaded +// from the process. +// +// Return Value: +// +// None. +// +__declspec(dllexport) void VLDResolveCallstacks(); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#else // !_DEBUG + +#define VLDEnable() +#define VLDDisable() +#define VLDRestore() +#define VLDReportLeaks() 0 +#define VLDGetLeaksCount() 0 +#define VLDMarkAllLeaksAsReported() +#define VLDRefreshModules() +#define VLDEnableModule(a) +#define VLDDisableModule(b) +#define VLDGetOptions() 0 +#define VLDGetReportFilename(a) +#define VLDSetOptions(a, b, c) +#define VLDSetReportHook(a, b) +#define VLDSetModulesList(a) +#define VLDGetModulesList(a, b) FALSE +#define VLDSetReportOptions(a, b) + +#endif // _DEBUG diff --git a/VisualLeakDetector/include/vld_def.h b/ThirdLibs/VisualLeakDetector/include/vld_def.h similarity index 98% rename from VisualLeakDetector/include/vld_def.h rename to ThirdLibs/VisualLeakDetector/include/vld_def.h index 223aa1bf..1fc828bf 100644 --- a/VisualLeakDetector/include/vld_def.h +++ b/ThirdLibs/VisualLeakDetector/include/vld_def.h @@ -1,44 +1,44 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Visual Leak Detector - Import Library Header -// Copyright (c) 2005-2011 VLD Team -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -// -// See COPYING.txt for the full terms of the GNU Lesser General Public License. -// -//////////////////////////////////////////////////////////////////////////////// - -#pragma once - -#define VLD_OPT_AGGREGATE_DUPLICATES 0x0001 // If set, aggregate duplicate leaks in the leak report. -#define VLD_OPT_MODULE_LIST_INCLUDE 0x0002 // If set, modules in the module list are included, all others are excluded. -#define VLD_OPT_REPORT_TO_DEBUGGER 0x0004 // If set, the memory leak report is sent to the debugger. -#define VLD_OPT_REPORT_TO_FILE 0x0008 // If set, the memory leak report is sent to a file. -#define VLD_OPT_SAFE_STACK_WALK 0x0010 // If set, the stack is walked using the "safe" method (StackWalk64). -#define VLD_OPT_SELF_TEST 0x0020 // If set, perform a self-test to verify memory leak self-checking. -#define VLD_OPT_SLOW_DEBUGGER_DUMP 0x0040 // If set, inserts a slight delay between sending output to the debugger. -#define VLD_OPT_START_DISABLED 0x0080 // If set, memory leak detection will initially disabled. -#define VLD_OPT_TRACE_INTERNAL_FRAMES 0x0100 // If set, include useless frames (e.g. internal to VLD) in call stacks. -#define VLD_OPT_UNICODE_REPORT 0x0200 // If set, the leak report will be encoded UTF-16 instead of ASCII. -#define VLD_OPT_VLDOFF 0x0400 // If set, VLD will be completely deactivated. It will not attach to any modules. -#define VLD_OPT_REPORT_TO_STDOUT 0x0800 // If set, the memory leak report is sent to stdout. -#define VLD_OPT_SKIP_HEAPFREE_LEAKS 0x1000 // If set, VLD skip HeapFree memory leaks. -#define VLD_OPT_VALIDATE_HEAPFREE 0x2000 // If set, VLD verifies and reports heap consistency for HeapFree calls. - -#define VLD_RPTHOOK_INSTALL 0 -#define VLD_RPTHOOK_REMOVE 1 - -typedef int (__cdecl * VLD_REPORT_HOOK)(int reportType, wchar_t *message, int *returnValue); +//////////////////////////////////////////////////////////////////////////////// +// +// Visual Leak Detector - Import Library Header +// Copyright (c) 2005-2011 VLD Team +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// See COPYING.txt for the full terms of the GNU Lesser General Public License. +// +//////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#define VLD_OPT_AGGREGATE_DUPLICATES 0x0001 // If set, aggregate duplicate leaks in the leak report. +#define VLD_OPT_MODULE_LIST_INCLUDE 0x0002 // If set, modules in the module list are included, all others are excluded. +#define VLD_OPT_REPORT_TO_DEBUGGER 0x0004 // If set, the memory leak report is sent to the debugger. +#define VLD_OPT_REPORT_TO_FILE 0x0008 // If set, the memory leak report is sent to a file. +#define VLD_OPT_SAFE_STACK_WALK 0x0010 // If set, the stack is walked using the "safe" method (StackWalk64). +#define VLD_OPT_SELF_TEST 0x0020 // If set, perform a self-test to verify memory leak self-checking. +#define VLD_OPT_SLOW_DEBUGGER_DUMP 0x0040 // If set, inserts a slight delay between sending output to the debugger. +#define VLD_OPT_START_DISABLED 0x0080 // If set, memory leak detection will initially disabled. +#define VLD_OPT_TRACE_INTERNAL_FRAMES 0x0100 // If set, include useless frames (e.g. internal to VLD) in call stacks. +#define VLD_OPT_UNICODE_REPORT 0x0200 // If set, the leak report will be encoded UTF-16 instead of ASCII. +#define VLD_OPT_VLDOFF 0x0400 // If set, VLD will be completely deactivated. It will not attach to any modules. +#define VLD_OPT_REPORT_TO_STDOUT 0x0800 // If set, the memory leak report is sent to stdout. +#define VLD_OPT_SKIP_HEAPFREE_LEAKS 0x1000 // If set, VLD skip HeapFree memory leaks. +#define VLD_OPT_VALIDATE_HEAPFREE 0x2000 // If set, VLD verifies and reports heap consistency for HeapFree calls. + +#define VLD_RPTHOOK_INSTALL 0 +#define VLD_RPTHOOK_REMOVE 1 + +typedef int (__cdecl * VLD_REPORT_HOOK)(int reportType, wchar_t *message, int *returnValue); diff --git a/VisualLeakDetector/lib/Win32/vld.lib b/ThirdLibs/VisualLeakDetector/lib/Win32/vld.lib similarity index 100% rename from VisualLeakDetector/lib/Win32/vld.lib rename to ThirdLibs/VisualLeakDetector/lib/Win32/vld.lib diff --git a/VisualLeakDetector/lib/Win64/vld.lib b/ThirdLibs/VisualLeakDetector/lib/Win64/vld.lib similarity index 100% rename from VisualLeakDetector/lib/Win64/vld.lib rename to ThirdLibs/VisualLeakDetector/lib/Win64/vld.lib diff --git a/scintilla/.hg_archival.txt b/ThirdLibs/scintilla/.hg_archival.txt similarity index 100% rename from scintilla/.hg_archival.txt rename to ThirdLibs/scintilla/.hg_archival.txt diff --git a/scintilla/.hgeol b/ThirdLibs/scintilla/.hgeol similarity index 100% rename from scintilla/.hgeol rename to ThirdLibs/scintilla/.hgeol diff --git a/scintilla/.hgignore b/ThirdLibs/scintilla/.hgignore similarity index 100% rename from scintilla/.hgignore rename to ThirdLibs/scintilla/.hgignore diff --git a/scintilla/.hgtags b/ThirdLibs/scintilla/.hgtags similarity index 100% rename from scintilla/.hgtags rename to ThirdLibs/scintilla/.hgtags diff --git a/scintilla/License.txt b/ThirdLibs/scintilla/License.txt similarity index 97% rename from scintilla/License.txt rename to ThirdLibs/scintilla/License.txt index 8d286121..cbe25b2f 100644 --- a/scintilla/License.txt +++ b/ThirdLibs/scintilla/License.txt @@ -1,20 +1,20 @@ -License for Scintilla and SciTE - -Copyright 1998-2003 by Neil Hodgson - -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation. - -NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE +License for Scintilla and SciTE + +Copyright 1998-2003 by Neil Hodgson + +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. + +NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/scintilla/README b/ThirdLibs/scintilla/README similarity index 96% rename from scintilla/README rename to ThirdLibs/scintilla/README index cada051b..d7efc690 100644 --- a/scintilla/README +++ b/ThirdLibs/scintilla/README @@ -1,70 +1,70 @@ -README for building of Scintilla and SciTE - -Scintilla can be built by itself. -To build SciTE, Scintilla must first be built. - - -*** GTK+/Linux version *** - -You must first have GTK+ 2.0 or later and GCC (4.1 or better) installed. -GTK+ 1.x will not work. -Other C++ compilers may work but may require tweaking the make file. - -To build Scintilla, use the makefile located in the scintilla/gtk directory - cd scintilla/gtk - make - cd ../.. - -To build and install SciTE, use the makefile located in the scite/gtk directory - cd scite/gtk - make - make install - -This installs SciTE into $prefix/bin. The value of $prefix is determined from -the location of Gnome if it is installed. This is usually /usr if installed -with Linux or /usr/local if built from source. If Gnome is not installed -/usr/bin is used as the prefix. The prefix can be overridden on the command -line like "make prefix=/opt" but the same value should be used for both make -and make install as this location is compiled into the executable. The global -properties file is installed at $prefix/share/scite/SciTEGlobal.properties. -The language specific properties files are also installed into this directory. - -To remove SciTE - make uninstall - -To clean the object files which may be needed to change $prefix - make clean - -The current make file only supports static linking between SciTE and Scintilla. - - -*** Windows version *** - -A C++ compiler is required. Visual Studio .NET 2010 is the development system -used for most development although TDM Mingw32 4.4.1 is also supported. - -To build Scintilla, make in the scintilla/win32 directory - cd scintilla\win32 -GCC: mingw32-make -VS .NET: nmake -f scintilla.mak - cd ..\.. - -To build SciTE, use the makefiles located in the scite/win32 directory - cd scite\win32 -GCC: mingw32-make -VS .NET: nmake -f scite.mak - -An executable SciTE will now be in scite\bin. - -The Visual C++ 6.0 project (.dsp) and make files are no longer supported but are left -in the download for people that are prepared to update them. - -*** GTK+/Windows version *** - -Mingw32 is known to work. Other compilers will probably not work. - -Only Scintilla will build with GTK+ on Windows. SciTE will not work. - -To build Scintilla, make in the scintilla/gtk directory - cd scintilla\gtk - mingw32-make +README for building of Scintilla and SciTE + +Scintilla can be built by itself. +To build SciTE, Scintilla must first be built. + + +*** GTK+/Linux version *** + +You must first have GTK+ 2.0 or later and GCC (4.1 or better) installed. +GTK+ 1.x will not work. +Other C++ compilers may work but may require tweaking the make file. + +To build Scintilla, use the makefile located in the scintilla/gtk directory + cd scintilla/gtk + make + cd ../.. + +To build and install SciTE, use the makefile located in the scite/gtk directory + cd scite/gtk + make + make install + +This installs SciTE into $prefix/bin. The value of $prefix is determined from +the location of Gnome if it is installed. This is usually /usr if installed +with Linux or /usr/local if built from source. If Gnome is not installed +/usr/bin is used as the prefix. The prefix can be overridden on the command +line like "make prefix=/opt" but the same value should be used for both make +and make install as this location is compiled into the executable. The global +properties file is installed at $prefix/share/scite/SciTEGlobal.properties. +The language specific properties files are also installed into this directory. + +To remove SciTE + make uninstall + +To clean the object files which may be needed to change $prefix + make clean + +The current make file only supports static linking between SciTE and Scintilla. + + +*** Windows version *** + +A C++ compiler is required. Visual Studio .NET 2010 is the development system +used for most development although TDM Mingw32 4.4.1 is also supported. + +To build Scintilla, make in the scintilla/win32 directory + cd scintilla\win32 +GCC: mingw32-make +VS .NET: nmake -f scintilla.mak + cd ..\.. + +To build SciTE, use the makefiles located in the scite/win32 directory + cd scite\win32 +GCC: mingw32-make +VS .NET: nmake -f scite.mak + +An executable SciTE will now be in scite\bin. + +The Visual C++ 6.0 project (.dsp) and make files are no longer supported but are left +in the download for people that are prepared to update them. + +*** GTK+/Windows version *** + +Mingw32 is known to work. Other compilers will probably not work. + +Only Scintilla will build with GTK+ on Windows. SciTE will not work. + +To build Scintilla, make in the scintilla/gtk directory + cd scintilla\gtk + mingw32-make diff --git a/scintilla/bin/SciLexer.dll b/ThirdLibs/scintilla/bin/SciLexer.dll similarity index 100% rename from scintilla/bin/SciLexer.dll rename to ThirdLibs/scintilla/bin/SciLexer.dll diff --git a/scintilla/bin/Scintilla.dll b/ThirdLibs/scintilla/bin/Scintilla.dll similarity index 100% rename from scintilla/bin/Scintilla.dll rename to ThirdLibs/scintilla/bin/Scintilla.dll diff --git a/scintilla/bin/empty.txt b/ThirdLibs/scintilla/bin/empty.txt similarity index 100% rename from scintilla/bin/empty.txt rename to ThirdLibs/scintilla/bin/empty.txt diff --git a/scintilla/cocoa/Framework.mk b/ThirdLibs/scintilla/cocoa/Framework.mk similarity index 96% rename from scintilla/cocoa/Framework.mk rename to ThirdLibs/scintilla/cocoa/Framework.mk index d18ee813..ba9fa16f 100644 --- a/scintilla/cocoa/Framework.mk +++ b/ThirdLibs/scintilla/cocoa/Framework.mk @@ -1,71 +1,71 @@ -### start defines ### -include common.mk - -INST_NAME=-install_name \ - @executable_path/../Frameworks/Sci.framework/Versions/A/Sci - -LD=gcc $(ARCH) -dynamiclib -framework Cocoa $(INST_NAME) - -LEXOBJS:=$(addsuffix .o,$(basename $(notdir $(wildcard ../lexers/Lex*.cxx)))) - -SCI_LEXERS=$(LEXOBJS) \ - LexerBase.o LexerModule.o LexerSimple.o Accessor.o - -SCI_OBJ=AutoComplete.o CallTip.o CellBuffer.o CharClassify.o \ - ContractionState.o Decoration.o Document.o Editor.o \ - ExternalLexer.o Indicator.o KeyMap.o LineMarker.o PerLine.o \ - PositionCache.o PropSetSimple.o RESearch.o RunStyles.o ScintillaBase.o Style.o \ - StyleContext.o UniConversion.o ViewStyle.o XPM.o WordList.o \ - Selection.o CharacterSet.o Catalogue.o $(SCI_LEXERS) - -WAH_OBJ=DocumentAccessor.o KeyWords.o WindowAccessor.o - -COC_OBJ=PlatCocoa.o ScintillaCocoa.o ScintillaView.o InfoBar.o - -OBJ=$(SCI_OBJ) $(UNUSED_OBJ) $(COC_OBJ) -OBJS=$(addprefix $(FRM_BLD)/,$(OBJ)) - -TARG=$(APP)/Versions/A/Sci -APP=$(FRM_BLD)/Sci.framework -### end defines ### - -### start targets ### - -all: $(FRM_BLD) $(TARG) - -cleanfrm: - -rm -rf $(FRM_BLD) - -$(APP): $(FRM_BLD) - -rm -rf $(APP) - -mkdir $(APP) - -mkdir $(APP)/Versions - -mkdir $(APP)/Versions/A - -mkdir $(APP)/Versions/A/Headers - -mkdir $(APP)/Versions/A/Resources - -ln -sf `pwd`/$(APP)/Versions/A `pwd`/$(APP)/Versions/Current - -ln -sf `pwd`/$(APP)/Versions/A/Headers `pwd`/$(APP)/Headers - -ln -sf `pwd`/$(APP)/Versions/A/Resources `pwd`/$(APP)/Resources - -cp *.h $(APP)/Headers/ - -cp ../src/*.h $(APP)/Headers/ - -cp ../include/*.h $(APP)/Headers/ - -cp -R ScintillaFramework/English.lproj $(APP)/Resources - -cp res/*.png $(APP)/Resources - -cp ScintillaFramework/Info.plist $(APP)/Resources - -$(TARG) : $(OBJS) $(APP) - $(LD) $(OBJS) $(gDEFs) -o $(TARG) -lstdc++ - -ln `pwd`/$(TARG) `pwd`/$(APP)/Sci - -$(FRM_BLD): - -mkdir $(BLD) - -mkdir $(FRM_BLD) - -### get around to filling out the real dependencies later ### -#$(FRM_BLD)/AutoComplete.o : ../src/AutoComplete.cxx ../src/AutoComplete.h \ -# ../include/Platform.h - -#$(FRM_BLD)/CallTip.o : ../src/CallTip.cxx ../src/CallTip.h \ -# ../include/Platform.h - -### end targets ### +### start defines ### +include common.mk + +INST_NAME=-install_name \ + @executable_path/../Frameworks/Sci.framework/Versions/A/Sci + +LD=gcc $(ARCH) -dynamiclib -framework Cocoa $(INST_NAME) + +LEXOBJS:=$(addsuffix .o,$(basename $(notdir $(wildcard ../lexers/Lex*.cxx)))) + +SCI_LEXERS=$(LEXOBJS) \ + LexerBase.o LexerModule.o LexerSimple.o Accessor.o + +SCI_OBJ=AutoComplete.o CallTip.o CellBuffer.o CharClassify.o \ + ContractionState.o Decoration.o Document.o Editor.o \ + ExternalLexer.o Indicator.o KeyMap.o LineMarker.o PerLine.o \ + PositionCache.o PropSetSimple.o RESearch.o RunStyles.o ScintillaBase.o Style.o \ + StyleContext.o UniConversion.o ViewStyle.o XPM.o WordList.o \ + Selection.o CharacterSet.o Catalogue.o $(SCI_LEXERS) + +WAH_OBJ=DocumentAccessor.o KeyWords.o WindowAccessor.o + +COC_OBJ=PlatCocoa.o ScintillaCocoa.o ScintillaView.o InfoBar.o + +OBJ=$(SCI_OBJ) $(UNUSED_OBJ) $(COC_OBJ) +OBJS=$(addprefix $(FRM_BLD)/,$(OBJ)) + +TARG=$(APP)/Versions/A/Sci +APP=$(FRM_BLD)/Sci.framework +### end defines ### + +### start targets ### + +all: $(FRM_BLD) $(TARG) + +cleanfrm: + -rm -rf $(FRM_BLD) + +$(APP): $(FRM_BLD) + -rm -rf $(APP) + -mkdir $(APP) + -mkdir $(APP)/Versions + -mkdir $(APP)/Versions/A + -mkdir $(APP)/Versions/A/Headers + -mkdir $(APP)/Versions/A/Resources + -ln -sf `pwd`/$(APP)/Versions/A `pwd`/$(APP)/Versions/Current + -ln -sf `pwd`/$(APP)/Versions/A/Headers `pwd`/$(APP)/Headers + -ln -sf `pwd`/$(APP)/Versions/A/Resources `pwd`/$(APP)/Resources + -cp *.h $(APP)/Headers/ + -cp ../src/*.h $(APP)/Headers/ + -cp ../include/*.h $(APP)/Headers/ + -cp -R ScintillaFramework/English.lproj $(APP)/Resources + -cp res/*.png $(APP)/Resources + -cp ScintillaFramework/Info.plist $(APP)/Resources + +$(TARG) : $(OBJS) $(APP) + $(LD) $(OBJS) $(gDEFs) -o $(TARG) -lstdc++ + -ln `pwd`/$(TARG) `pwd`/$(APP)/Sci + +$(FRM_BLD): + -mkdir $(BLD) + -mkdir $(FRM_BLD) + +### get around to filling out the real dependencies later ### +#$(FRM_BLD)/AutoComplete.o : ../src/AutoComplete.cxx ../src/AutoComplete.h \ +# ../include/Platform.h + +#$(FRM_BLD)/CallTip.o : ../src/CallTip.cxx ../src/CallTip.h \ +# ../include/Platform.h + +### end targets ### diff --git a/scintilla/cocoa/InfoBar.h b/ThirdLibs/scintilla/cocoa/InfoBar.h similarity index 96% rename from scintilla/cocoa/InfoBar.h rename to ThirdLibs/scintilla/cocoa/InfoBar.h index 96248115..a83a92c9 100644 --- a/scintilla/cocoa/InfoBar.h +++ b/ThirdLibs/scintilla/cocoa/InfoBar.h @@ -1,55 +1,55 @@ - -/** - * Scintilla source code edit control - * InfoBar.h - Implements special info bar with zoom info, caret position etc. to be used with - * ScintillaView. - * - * Mike Lischke - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). - */ - -#import -#import "InfoBarCommunicator.h" - -/** - * Extended text cell for vertically aligned text. - */ -@interface VerticallyCenteredTextFieldCell : NSTextFieldCell -{ - BOOL mIsEditingOrSelecting; -} - -@end - -@interface InfoBar : NSView -{ -@private - NSImage* mBackground; - IBDisplay mDisplayMask; - - float mScaleFactor; - NSPopUpButton* mZoomPopup; - - int mCurrentCaretX; - int mCurrentCaretY; - NSTextField* mCaretPositionLabel; - NSTextField* mStatusTextLabel; - - id mCallback; -} - -- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location - value: (float) value; -- (void) setCallback: (id ) callback; - -- (void) createItems; -- (void) layout; -- (void) setDisplay: (IBDisplay) display; -- (void) zoomItemAction: (id) sender; -- (void) setScaleFactor: (float) newScaleFactor adjustPopup: (BOOL) flag; -- (void) setCaretPosition: (NSPoint) position; -- (void) sizeToFit; - -@end + +/** + * Scintilla source code edit control + * InfoBar.h - Implements special info bar with zoom info, caret position etc. to be used with + * ScintillaView. + * + * Mike Lischke + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). + */ + +#import +#import "InfoBarCommunicator.h" + +/** + * Extended text cell for vertically aligned text. + */ +@interface VerticallyCenteredTextFieldCell : NSTextFieldCell +{ + BOOL mIsEditingOrSelecting; +} + +@end + +@interface InfoBar : NSView +{ +@private + NSImage* mBackground; + IBDisplay mDisplayMask; + + float mScaleFactor; + NSPopUpButton* mZoomPopup; + + int mCurrentCaretX; + int mCurrentCaretY; + NSTextField* mCaretPositionLabel; + NSTextField* mStatusTextLabel; + + id mCallback; +} + +- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location + value: (float) value; +- (void) setCallback: (id ) callback; + +- (void) createItems; +- (void) layout; +- (void) setDisplay: (IBDisplay) display; +- (void) zoomItemAction: (id) sender; +- (void) setScaleFactor: (float) newScaleFactor adjustPopup: (BOOL) flag; +- (void) setCaretPosition: (NSPoint) position; +- (void) sizeToFit; + +@end diff --git a/scintilla/cocoa/InfoBar.mm b/ThirdLibs/scintilla/cocoa/InfoBar.mm similarity index 96% rename from scintilla/cocoa/InfoBar.mm rename to ThirdLibs/scintilla/cocoa/InfoBar.mm index dccafa7e..0d4a7a75 100644 --- a/scintilla/cocoa/InfoBar.mm +++ b/ThirdLibs/scintilla/cocoa/InfoBar.mm @@ -1,448 +1,448 @@ - -/** - * Scintilla source code edit control - * InfoBar.mm - Implements special info bar with zoom info, caret position etc. to be used with - * ScintillaView. - * - * Mike Lischke - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). - */ - -#import "InfoBar.h" - -//-------------------------------------------------------------------------------------------------- - -@implementation VerticallyCenteredTextFieldCell - -// Inspired by code from Daniel Jalkut, Red Sweater Software. - -- (NSRect) drawingRectForBounds: (NSRect) theRect -{ - // Get the parent's idea of where we should draw - NSRect newRect = [super drawingRectForBounds: theRect]; - - // When the text field is being edited or selected, we have to turn off the magic because it - // screws up the configuration of the field editor. We sneak around this by intercepting - // selectWithFrame and editWithFrame and sneaking a reduced, centered rect in at the last minute. - if (mIsEditingOrSelecting == NO) - { - // Get our ideal size for current text - NSSize textSize = [self cellSizeForBounds: theRect]; - - // Center that in the proposed rect - float heightDelta = newRect.size.height - textSize.height; - if (heightDelta > 0) - { - newRect.size.height -= heightDelta; - newRect.origin.y += ceil(heightDelta / 2); - } - } - - return newRect; -} - -//-------------------------------------------------------------------------------------------------- - -- (void) selectWithFrame: (NSRect) aRect inView: (NSView*) controlView editor: (NSText*) textObj - delegate:(id) anObject start: (NSInteger) selStart length: (NSInteger) selLength -{ - aRect = [self drawingRectForBounds: aRect]; - mIsEditingOrSelecting = YES; - [super selectWithFrame: aRect - inView: controlView - editor: textObj - delegate: anObject - start: selStart - length: selLength]; - mIsEditingOrSelecting = NO; -} - -//-------------------------------------------------------------------------------------------------- - -- (void) editWithFrame: (NSRect) aRect inView: (NSView*) controlView editor: (NSText*) textObj - delegate: (id) anObject event: (NSEvent*) theEvent -{ - aRect = [self drawingRectForBounds: aRect]; - mIsEditingOrSelecting = YES; - [super editWithFrame: aRect - inView: controlView - editor: textObj - delegate: anObject - event: theEvent]; - mIsEditingOrSelecting = NO; -} - -@end - -//-------------------------------------------------------------------------------------------------- - -@implementation InfoBar - -- (id) initWithFrame: (NSRect) frame -{ - self = [super initWithFrame: frame]; - if (self) - { - NSBundle* bundle = [NSBundle bundleForClass: [InfoBar class]]; - - NSString* path = [bundle pathForResource: @"info_bar_bg" ofType: @"png" inDirectory: nil]; - mBackground = [[[NSImage alloc] initWithContentsOfFile: path] retain]; - if (![mBackground isValid]) - NSLog(@"Background image for info bar is invalid."); - - mScaleFactor = 1.0; - mCurrentCaretX = 0; - mCurrentCaretY = 0; - [self createItems]; - } - return self; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called by a connected compontent (usually the info bar) if something changed there. - * - * @param type The type of the notification. - * @param message Carries the new status message if the type is a status message change. - * @param location Carries the new location (e.g. caret) if the type is a caret change or similar type. - * @param location Carries the new zoom value if the type is a zoom change. - */ -- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location - value: (float) value -{ - switch (type) - { - case IBNZoomChanged: - [self setScaleFactor: value adjustPopup: YES]; - break; - case IBNCaretChanged: - [self setCaretPosition: location]; - break; - case IBNStatusChanged: - [mStatusTextLabel setStringValue: message]; - break; - } -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Used to set a protocol object we can use to send change notifications to. - */ -- (void) setCallback: (id ) callback -{ - mCallback = callback; -} - -//-------------------------------------------------------------------------------------------------- - -static NSString *DefaultScaleMenuLabels[] = { - @"20%", @"30%", @"50%", @"75%", @"100%", @"130%", @"160%", @"200%", @"250%", @"300%" -}; -static float DefaultScaleMenuFactors[] = { - 0.2, 0.3, 0.5, 0.75, 1.0, 1.3, 1.6, 2.0, 2.5, 3.0 -}; -static unsigned DefaultScaleMenuSelectedItemIndex = 4; -static float BarFontSize = 10.0; - -- (void) createItems -{ - // 1) The zoom popup. - unsigned numberOfDefaultItems = sizeof(DefaultScaleMenuLabels) / sizeof(NSString *); - - // Create the popup button. - mZoomPopup = [[NSPopUpButton allocWithZone:[self zone]] initWithFrame: NSMakeRect(0.0, 0.0, 1.0, 1.0) pullsDown: NO]; - - // No border or background please. - [[mZoomPopup cell] setBordered: NO]; - [[mZoomPopup cell] setArrowPosition: NSPopUpArrowAtBottom]; - - // Fill it. - for (unsigned count = 0; count < numberOfDefaultItems; count++) - { - [mZoomPopup addItemWithTitle: NSLocalizedStringFromTable(DefaultScaleMenuLabels[count], @"ZoomValues", nil)]; - id currentItem = [mZoomPopup itemAtIndex: count]; - if (DefaultScaleMenuFactors[count] != 0.0) - [currentItem setRepresentedObject: [NSNumber numberWithFloat: DefaultScaleMenuFactors[count]]]; - } - [mZoomPopup selectItemAtIndex: DefaultScaleMenuSelectedItemIndex]; - - // Hook it up. - [mZoomPopup setTarget: self]; - [mZoomPopup setAction: @selector(zoomItemAction:)]; - - // Set a suitable font. - [mZoomPopup setFont: [NSFont menuBarFontOfSize: BarFontSize]]; - - // Make sure the popup is big enough to fit the cells. - [mZoomPopup sizeToFit]; - - // Don't let it become first responder - [mZoomPopup setRefusesFirstResponder: YES]; - - // put it in the scrollview. - [self addSubview: mZoomPopup]; - [mZoomPopup release]; - - // 2) The caret position label. - Class oldCellClass = [NSTextField cellClass]; - [NSTextField setCellClass: [VerticallyCenteredTextFieldCell class]]; - - mCaretPositionLabel = [[NSTextField alloc] initWithFrame: NSMakeRect(0.0, 0.0, 50.0, 1.0)]; - [mCaretPositionLabel setBezeled: NO]; - [mCaretPositionLabel setBordered: NO]; - [mCaretPositionLabel setEditable: NO]; - [mCaretPositionLabel setSelectable: NO]; - [mCaretPositionLabel setDrawsBackground: NO]; - [mCaretPositionLabel setFont: [NSFont menuBarFontOfSize: BarFontSize]]; - - NSTextFieldCell* cell = [mCaretPositionLabel cell]; - [cell setPlaceholderString: @"0:0"]; - [cell setAlignment: NSCenterTextAlignment]; - - [self addSubview: mCaretPositionLabel]; - [mCaretPositionLabel release]; - - // 3) The status text. - mStatusTextLabel = [[NSTextField alloc] initWithFrame: NSMakeRect(0.0, 0.0, 1.0, 1.0)]; - [mStatusTextLabel setBezeled: NO]; - [mStatusTextLabel setBordered: NO]; - [mStatusTextLabel setEditable: NO]; - [mStatusTextLabel setSelectable: NO]; - [mStatusTextLabel setDrawsBackground: NO]; - [mStatusTextLabel setFont: [NSFont menuBarFontOfSize: BarFontSize]]; - - cell = [mStatusTextLabel cell]; - [cell setPlaceholderString: @""]; - - [self addSubview: mStatusTextLabel]; - [mStatusTextLabel release]; - - // Restore original cell class so that everything else doesn't get broken - [NSTextField setCellClass: oldCellClass]; -} - -//-------------------------------------------------------------------------------------------------- - -- (void) dealloc -{ - [mBackground release]; - [super dealloc]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Fill the background. - */ -- (void) drawRect: (NSRect) rect -{ - // Since the background is seamless, we don't need to take care for the proper offset. - // Simply tile the background over the invalid rectangle. - NSPoint target = {rect.origin.x, 0}; - while (target.x < rect.origin.x + rect.size.width) - { - [mBackground drawAtPoint: target fromRect: NSZeroRect operation: NSCompositeCopy fraction: 1]; - target.x += mBackground.size.width; - } - - // Draw separator lines between items. - NSRect verticalLineRect; - float component = 190.0 / 255.0; - NSColor* lineColor = [NSColor colorWithDeviceRed: component green: component blue: component alpha: 1]; - - if (mDisplayMask & IBShowZoom) - { - verticalLineRect = [mZoomPopup frame]; - verticalLineRect.origin.x += verticalLineRect.size.width + 1.0; - verticalLineRect.size.width = 1.0; - if (NSIntersectsRect(rect, verticalLineRect)) - { - [lineColor set]; - NSRectFill(verticalLineRect); - } - } - - if (mDisplayMask & IBShowCaretPosition) - { - verticalLineRect = [mCaretPositionLabel frame]; - verticalLineRect.origin.x += verticalLineRect.size.width + 1.0; - verticalLineRect.size.width = 1.0; - if (NSIntersectsRect(rect, verticalLineRect)) - { - [lineColor set]; - NSRectFill(verticalLineRect); - } - } -} - -//-------------------------------------------------------------------------------------------------- - -- (BOOL) isOpaque -{ - return YES; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Used to reposition our content depending on the size of the view. - */ -- (void) setFrame: (NSRect) newFrame -{ - [super setFrame: newFrame]; - [self layout]; -} - -//-------------------------------------------------------------------------------------------------- - -- (void) layout -{ - NSRect currentBounds = {0, 0, 0, [self frame].size.height}; - if (mDisplayMask & IBShowZoom) - { - [mZoomPopup setHidden: NO]; - currentBounds.size.width = [mZoomPopup frame].size.width; - [mZoomPopup setFrame: currentBounds]; - currentBounds.origin.x += currentBounds.size.width + 1; // Add 1 for the separator. - } - else - [mZoomPopup setHidden: YES]; - - if (mDisplayMask & IBShowCaretPosition) - { - [mCaretPositionLabel setHidden: NO]; - currentBounds.size.width = [mCaretPositionLabel frame].size.width; - [mCaretPositionLabel setFrame: currentBounds]; - currentBounds.origin.x += currentBounds.size.width + 1; - } - else - [mCaretPositionLabel setHidden: YES]; - - if (mDisplayMask & IBShowStatusText) - { - // The status text always takes the rest of the available space. - [mStatusTextLabel setHidden: NO]; - currentBounds.size.width = [self frame].size.width - currentBounds.origin.x; - [mStatusTextLabel setFrame: currentBounds]; - } - else - [mStatusTextLabel setHidden: YES]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Used to switch the visible parts of the info bar. - * - * @param display Bitwise ORed IBDisplay values which determine what to show on the bar. - */ -- (void) setDisplay: (IBDisplay) display -{ - if (mDisplayMask != display) - { - mDisplayMask = display; - [self layout]; - [self needsDisplay]; - } -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Handler for selection changes in the zoom menu. - */ -- (void) zoomItemAction: (id) sender -{ - NSNumber* selectedFactorObject = [[sender selectedCell] representedObject]; - - if (selectedFactorObject == nil) - { - NSLog(@"Scale popup action: setting arbitrary zoom factors is not yet supported."); - return; - } - else - { - [self setScaleFactor: [selectedFactorObject floatValue] adjustPopup: NO]; - } -} - -//-------------------------------------------------------------------------------------------------- - -- (void) setScaleFactor: (float) newScaleFactor adjustPopup: (BOOL) flag -{ - if (mScaleFactor != newScaleFactor) - { - mScaleFactor = newScaleFactor; - if (flag) - { - unsigned count = 0; - unsigned numberOfDefaultItems = sizeof(DefaultScaleMenuFactors) / sizeof(float); - - // We only work with some preset zoom values. If the given value does not correspond - // to one then show no selection. - while (count < numberOfDefaultItems && (fabs(newScaleFactor - DefaultScaleMenuFactors[count]) > 0.07)) - count++; - if (count == numberOfDefaultItems) - [mZoomPopup selectItemAtIndex: -1]; - else - { - [mZoomPopup selectItemAtIndex: count]; - - // Set scale factor to found preset value if it comes close. - mScaleFactor = DefaultScaleMenuFactors[count]; - } - } - else - { - // Internally set. Notify owner. - [mCallback notify: IBNZoomChanged message: nil location: NSZeroPoint value: newScaleFactor]; - } - } -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called from the notification method to update the caret position display. - */ -- (void) setCaretPosition: (NSPoint) position -{ - // Make the position one-based. - int newX = (int) position.x + 1; - int newY = (int) position.y + 1; - - if (mCurrentCaretX != newX || mCurrentCaretY != newY) - { - mCurrentCaretX = newX; - mCurrentCaretY = newY; - - [mCaretPositionLabel setStringValue: [NSString stringWithFormat: @"%d:%d", newX, newY]]; - } -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Makes the bar resize to the smallest width that can accomodate the currently enabled items. - */ -- (void) sizeToFit -{ - NSRect frame = [self frame]; - frame.size.width = 0; - if (mDisplayMask & IBShowZoom) - frame.size.width += [mZoomPopup frame].size.width; - - if (mDisplayMask & IBShowCaretPosition) - frame.size.width += [mCaretPositionLabel frame].size.width; - - if (mDisplayMask & IBShowStatusText) - frame.size.width += [mStatusTextLabel frame].size.width; - - [self setFrame: frame]; -} - -@end + +/** + * Scintilla source code edit control + * InfoBar.mm - Implements special info bar with zoom info, caret position etc. to be used with + * ScintillaView. + * + * Mike Lischke + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). + */ + +#import "InfoBar.h" + +//-------------------------------------------------------------------------------------------------- + +@implementation VerticallyCenteredTextFieldCell + +// Inspired by code from Daniel Jalkut, Red Sweater Software. + +- (NSRect) drawingRectForBounds: (NSRect) theRect +{ + // Get the parent's idea of where we should draw + NSRect newRect = [super drawingRectForBounds: theRect]; + + // When the text field is being edited or selected, we have to turn off the magic because it + // screws up the configuration of the field editor. We sneak around this by intercepting + // selectWithFrame and editWithFrame and sneaking a reduced, centered rect in at the last minute. + if (mIsEditingOrSelecting == NO) + { + // Get our ideal size for current text + NSSize textSize = [self cellSizeForBounds: theRect]; + + // Center that in the proposed rect + float heightDelta = newRect.size.height - textSize.height; + if (heightDelta > 0) + { + newRect.size.height -= heightDelta; + newRect.origin.y += ceil(heightDelta / 2); + } + } + + return newRect; +} + +//-------------------------------------------------------------------------------------------------- + +- (void) selectWithFrame: (NSRect) aRect inView: (NSView*) controlView editor: (NSText*) textObj + delegate:(id) anObject start: (NSInteger) selStart length: (NSInteger) selLength +{ + aRect = [self drawingRectForBounds: aRect]; + mIsEditingOrSelecting = YES; + [super selectWithFrame: aRect + inView: controlView + editor: textObj + delegate: anObject + start: selStart + length: selLength]; + mIsEditingOrSelecting = NO; +} + +//-------------------------------------------------------------------------------------------------- + +- (void) editWithFrame: (NSRect) aRect inView: (NSView*) controlView editor: (NSText*) textObj + delegate: (id) anObject event: (NSEvent*) theEvent +{ + aRect = [self drawingRectForBounds: aRect]; + mIsEditingOrSelecting = YES; + [super editWithFrame: aRect + inView: controlView + editor: textObj + delegate: anObject + event: theEvent]; + mIsEditingOrSelecting = NO; +} + +@end + +//-------------------------------------------------------------------------------------------------- + +@implementation InfoBar + +- (id) initWithFrame: (NSRect) frame +{ + self = [super initWithFrame: frame]; + if (self) + { + NSBundle* bundle = [NSBundle bundleForClass: [InfoBar class]]; + + NSString* path = [bundle pathForResource: @"info_bar_bg" ofType: @"png" inDirectory: nil]; + mBackground = [[[NSImage alloc] initWithContentsOfFile: path] retain]; + if (![mBackground isValid]) + NSLog(@"Background image for info bar is invalid."); + + mScaleFactor = 1.0; + mCurrentCaretX = 0; + mCurrentCaretY = 0; + [self createItems]; + } + return self; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called by a connected compontent (usually the info bar) if something changed there. + * + * @param type The type of the notification. + * @param message Carries the new status message if the type is a status message change. + * @param location Carries the new location (e.g. caret) if the type is a caret change or similar type. + * @param location Carries the new zoom value if the type is a zoom change. + */ +- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location + value: (float) value +{ + switch (type) + { + case IBNZoomChanged: + [self setScaleFactor: value adjustPopup: YES]; + break; + case IBNCaretChanged: + [self setCaretPosition: location]; + break; + case IBNStatusChanged: + [mStatusTextLabel setStringValue: message]; + break; + } +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Used to set a protocol object we can use to send change notifications to. + */ +- (void) setCallback: (id ) callback +{ + mCallback = callback; +} + +//-------------------------------------------------------------------------------------------------- + +static NSString *DefaultScaleMenuLabels[] = { + @"20%", @"30%", @"50%", @"75%", @"100%", @"130%", @"160%", @"200%", @"250%", @"300%" +}; +static float DefaultScaleMenuFactors[] = { + 0.2, 0.3, 0.5, 0.75, 1.0, 1.3, 1.6, 2.0, 2.5, 3.0 +}; +static unsigned DefaultScaleMenuSelectedItemIndex = 4; +static float BarFontSize = 10.0; + +- (void) createItems +{ + // 1) The zoom popup. + unsigned numberOfDefaultItems = sizeof(DefaultScaleMenuLabels) / sizeof(NSString *); + + // Create the popup button. + mZoomPopup = [[NSPopUpButton allocWithZone:[self zone]] initWithFrame: NSMakeRect(0.0, 0.0, 1.0, 1.0) pullsDown: NO]; + + // No border or background please. + [[mZoomPopup cell] setBordered: NO]; + [[mZoomPopup cell] setArrowPosition: NSPopUpArrowAtBottom]; + + // Fill it. + for (unsigned count = 0; count < numberOfDefaultItems; count++) + { + [mZoomPopup addItemWithTitle: NSLocalizedStringFromTable(DefaultScaleMenuLabels[count], @"ZoomValues", nil)]; + id currentItem = [mZoomPopup itemAtIndex: count]; + if (DefaultScaleMenuFactors[count] != 0.0) + [currentItem setRepresentedObject: [NSNumber numberWithFloat: DefaultScaleMenuFactors[count]]]; + } + [mZoomPopup selectItemAtIndex: DefaultScaleMenuSelectedItemIndex]; + + // Hook it up. + [mZoomPopup setTarget: self]; + [mZoomPopup setAction: @selector(zoomItemAction:)]; + + // Set a suitable font. + [mZoomPopup setFont: [NSFont menuBarFontOfSize: BarFontSize]]; + + // Make sure the popup is big enough to fit the cells. + [mZoomPopup sizeToFit]; + + // Don't let it become first responder + [mZoomPopup setRefusesFirstResponder: YES]; + + // put it in the scrollview. + [self addSubview: mZoomPopup]; + [mZoomPopup release]; + + // 2) The caret position label. + Class oldCellClass = [NSTextField cellClass]; + [NSTextField setCellClass: [VerticallyCenteredTextFieldCell class]]; + + mCaretPositionLabel = [[NSTextField alloc] initWithFrame: NSMakeRect(0.0, 0.0, 50.0, 1.0)]; + [mCaretPositionLabel setBezeled: NO]; + [mCaretPositionLabel setBordered: NO]; + [mCaretPositionLabel setEditable: NO]; + [mCaretPositionLabel setSelectable: NO]; + [mCaretPositionLabel setDrawsBackground: NO]; + [mCaretPositionLabel setFont: [NSFont menuBarFontOfSize: BarFontSize]]; + + NSTextFieldCell* cell = [mCaretPositionLabel cell]; + [cell setPlaceholderString: @"0:0"]; + [cell setAlignment: NSCenterTextAlignment]; + + [self addSubview: mCaretPositionLabel]; + [mCaretPositionLabel release]; + + // 3) The status text. + mStatusTextLabel = [[NSTextField alloc] initWithFrame: NSMakeRect(0.0, 0.0, 1.0, 1.0)]; + [mStatusTextLabel setBezeled: NO]; + [mStatusTextLabel setBordered: NO]; + [mStatusTextLabel setEditable: NO]; + [mStatusTextLabel setSelectable: NO]; + [mStatusTextLabel setDrawsBackground: NO]; + [mStatusTextLabel setFont: [NSFont menuBarFontOfSize: BarFontSize]]; + + cell = [mStatusTextLabel cell]; + [cell setPlaceholderString: @""]; + + [self addSubview: mStatusTextLabel]; + [mStatusTextLabel release]; + + // Restore original cell class so that everything else doesn't get broken + [NSTextField setCellClass: oldCellClass]; +} + +//-------------------------------------------------------------------------------------------------- + +- (void) dealloc +{ + [mBackground release]; + [super dealloc]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Fill the background. + */ +- (void) drawRect: (NSRect) rect +{ + // Since the background is seamless, we don't need to take care for the proper offset. + // Simply tile the background over the invalid rectangle. + NSPoint target = {rect.origin.x, 0}; + while (target.x < rect.origin.x + rect.size.width) + { + [mBackground drawAtPoint: target fromRect: NSZeroRect operation: NSCompositeCopy fraction: 1]; + target.x += mBackground.size.width; + } + + // Draw separator lines between items. + NSRect verticalLineRect; + float component = 190.0 / 255.0; + NSColor* lineColor = [NSColor colorWithDeviceRed: component green: component blue: component alpha: 1]; + + if (mDisplayMask & IBShowZoom) + { + verticalLineRect = [mZoomPopup frame]; + verticalLineRect.origin.x += verticalLineRect.size.width + 1.0; + verticalLineRect.size.width = 1.0; + if (NSIntersectsRect(rect, verticalLineRect)) + { + [lineColor set]; + NSRectFill(verticalLineRect); + } + } + + if (mDisplayMask & IBShowCaretPosition) + { + verticalLineRect = [mCaretPositionLabel frame]; + verticalLineRect.origin.x += verticalLineRect.size.width + 1.0; + verticalLineRect.size.width = 1.0; + if (NSIntersectsRect(rect, verticalLineRect)) + { + [lineColor set]; + NSRectFill(verticalLineRect); + } + } +} + +//-------------------------------------------------------------------------------------------------- + +- (BOOL) isOpaque +{ + return YES; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Used to reposition our content depending on the size of the view. + */ +- (void) setFrame: (NSRect) newFrame +{ + [super setFrame: newFrame]; + [self layout]; +} + +//-------------------------------------------------------------------------------------------------- + +- (void) layout +{ + NSRect currentBounds = {0, 0, 0, [self frame].size.height}; + if (mDisplayMask & IBShowZoom) + { + [mZoomPopup setHidden: NO]; + currentBounds.size.width = [mZoomPopup frame].size.width; + [mZoomPopup setFrame: currentBounds]; + currentBounds.origin.x += currentBounds.size.width + 1; // Add 1 for the separator. + } + else + [mZoomPopup setHidden: YES]; + + if (mDisplayMask & IBShowCaretPosition) + { + [mCaretPositionLabel setHidden: NO]; + currentBounds.size.width = [mCaretPositionLabel frame].size.width; + [mCaretPositionLabel setFrame: currentBounds]; + currentBounds.origin.x += currentBounds.size.width + 1; + } + else + [mCaretPositionLabel setHidden: YES]; + + if (mDisplayMask & IBShowStatusText) + { + // The status text always takes the rest of the available space. + [mStatusTextLabel setHidden: NO]; + currentBounds.size.width = [self frame].size.width - currentBounds.origin.x; + [mStatusTextLabel setFrame: currentBounds]; + } + else + [mStatusTextLabel setHidden: YES]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Used to switch the visible parts of the info bar. + * + * @param display Bitwise ORed IBDisplay values which determine what to show on the bar. + */ +- (void) setDisplay: (IBDisplay) display +{ + if (mDisplayMask != display) + { + mDisplayMask = display; + [self layout]; + [self needsDisplay]; + } +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Handler for selection changes in the zoom menu. + */ +- (void) zoomItemAction: (id) sender +{ + NSNumber* selectedFactorObject = [[sender selectedCell] representedObject]; + + if (selectedFactorObject == nil) + { + NSLog(@"Scale popup action: setting arbitrary zoom factors is not yet supported."); + return; + } + else + { + [self setScaleFactor: [selectedFactorObject floatValue] adjustPopup: NO]; + } +} + +//-------------------------------------------------------------------------------------------------- + +- (void) setScaleFactor: (float) newScaleFactor adjustPopup: (BOOL) flag +{ + if (mScaleFactor != newScaleFactor) + { + mScaleFactor = newScaleFactor; + if (flag) + { + unsigned count = 0; + unsigned numberOfDefaultItems = sizeof(DefaultScaleMenuFactors) / sizeof(float); + + // We only work with some preset zoom values. If the given value does not correspond + // to one then show no selection. + while (count < numberOfDefaultItems && (fabs(newScaleFactor - DefaultScaleMenuFactors[count]) > 0.07)) + count++; + if (count == numberOfDefaultItems) + [mZoomPopup selectItemAtIndex: -1]; + else + { + [mZoomPopup selectItemAtIndex: count]; + + // Set scale factor to found preset value if it comes close. + mScaleFactor = DefaultScaleMenuFactors[count]; + } + } + else + { + // Internally set. Notify owner. + [mCallback notify: IBNZoomChanged message: nil location: NSZeroPoint value: newScaleFactor]; + } + } +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called from the notification method to update the caret position display. + */ +- (void) setCaretPosition: (NSPoint) position +{ + // Make the position one-based. + int newX = (int) position.x + 1; + int newY = (int) position.y + 1; + + if (mCurrentCaretX != newX || mCurrentCaretY != newY) + { + mCurrentCaretX = newX; + mCurrentCaretY = newY; + + [mCaretPositionLabel setStringValue: [NSString stringWithFormat: @"%d:%d", newX, newY]]; + } +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Makes the bar resize to the smallest width that can accomodate the currently enabled items. + */ +- (void) sizeToFit +{ + NSRect frame = [self frame]; + frame.size.width = 0; + if (mDisplayMask & IBShowZoom) + frame.size.width += [mZoomPopup frame].size.width; + + if (mDisplayMask & IBShowCaretPosition) + frame.size.width += [mCaretPositionLabel frame].size.width; + + if (mDisplayMask & IBShowStatusText) + frame.size.width += [mStatusTextLabel frame].size.width; + + [self setFrame: frame]; +} + +@end diff --git a/scintilla/cocoa/InfoBarCommunicator.h b/ThirdLibs/scintilla/cocoa/InfoBarCommunicator.h similarity index 97% rename from scintilla/cocoa/InfoBarCommunicator.h rename to ThirdLibs/scintilla/cocoa/InfoBarCommunicator.h index ba8ae7a1..a6b4c4b9 100644 --- a/scintilla/cocoa/InfoBarCommunicator.h +++ b/ThirdLibs/scintilla/cocoa/InfoBarCommunicator.h @@ -1,35 +1,35 @@ -/* - * InfoBarCommunicator.h - Definitions of a communication protocol and other data types used for - * the info bar implementation. - * - * Mike Lischke - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). - */ - -enum IBDisplay { - IBShowZoom = 0x01, - IBShowCaretPosition = 0x02, - IBShowStatusText = 0x04, - IBShowAll = 0xFF -}; - -/** - * The info bar communicator protocol is used for communication between ScintillaView and its - * information bar component. Using this protocol decouples any potential info target from the main - * ScintillaView implementation. The protocol is used two-way. - */ - -enum NotificationType { - IBNZoomChanged, // The user selected another zoom value. - IBNCaretChanged, // The caret in the editor changed. - IBNStatusChanged, // The application set a new status message. -}; - -@protocol InfoBarCommunicator -- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location - value: (float) value; -- (void) setCallback: (id ) callback; -@end - +/* + * InfoBarCommunicator.h - Definitions of a communication protocol and other data types used for + * the info bar implementation. + * + * Mike Lischke + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). + */ + +enum IBDisplay { + IBShowZoom = 0x01, + IBShowCaretPosition = 0x02, + IBShowStatusText = 0x04, + IBShowAll = 0xFF +}; + +/** + * The info bar communicator protocol is used for communication between ScintillaView and its + * information bar component. Using this protocol decouples any potential info target from the main + * ScintillaView implementation. The protocol is used two-way. + */ + +enum NotificationType { + IBNZoomChanged, // The user selected another zoom value. + IBNCaretChanged, // The caret in the editor changed. + IBNStatusChanged, // The application set a new status message. +}; + +@protocol InfoBarCommunicator +- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location + value: (float) value; +- (void) setCallback: (id ) callback; +@end + diff --git a/scintilla/cocoa/PlatCocoa.h b/ThirdLibs/scintilla/cocoa/PlatCocoa.h similarity index 97% rename from scintilla/cocoa/PlatCocoa.h rename to ThirdLibs/scintilla/cocoa/PlatCocoa.h index 775602ba..58017706 100644 --- a/scintilla/cocoa/PlatCocoa.h +++ b/ThirdLibs/scintilla/cocoa/PlatCocoa.h @@ -1,123 +1,123 @@ - -/** - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). - */ - -#ifndef PLATCOCOA_H -#define PLATCOCOA_H - -#include -#include -#include - -#include - -#include - -#include -#include "QuartzTextLayout.h" - -#include "Platform.h" -#include "Scintilla.h" - -NSRect PRectangleToNSRect(Scintilla::PRectangle& rc); -Scintilla::PRectangle NSRectToPRectangle(NSRect& rc); -CFStringEncoding EncodingFromCharacterSet(bool unicode, int characterSet); - -@interface ScintillaContextMenu : NSMenu -{ - Scintilla::ScintillaCocoa* owner; -} -- (void) handleCommand: (NSMenuItem*) sender; -- (void) setOwner: (Scintilla::ScintillaCocoa*) newOwner; - -@end - -namespace Scintilla { - -// A class to do the actual text rendering for us using Quartz 2D. -class SurfaceImpl : public Surface -{ -private: - bool unicodeMode; - float x; - float y; - - CGContextRef gc; - - /** The text layout instance */ - QuartzTextLayout* textLayout; - int codePage; - int verticalDeviceResolution; - - /** If the surface is a bitmap context, contains a reference to the bitmap data. */ - uint8_t* bitmapData; - /** If the surface is a bitmap context, stores the dimensions of the bitmap. */ - int bitmapWidth; - int bitmapHeight; - - /** Set the CGContext's fill colour to the specified desired colour. */ - void FillColour( const ColourDesired& back ); - - - // 24-bit RGB+A bitmap data constants - static const int BITS_PER_COMPONENT = 8; - static const int BITS_PER_PIXEL = BITS_PER_COMPONENT * 4; - static const int BYTES_PER_PIXEL = BITS_PER_PIXEL / 8; -public: - SurfaceImpl(); - ~SurfaceImpl(); - - void Init(WindowID wid); - void Init(SurfaceID sid, WindowID wid); - void InitPixMap(int width, int height, Surface *surface_, WindowID wid); - CGContextRef GetContext() { return gc; } - - void Release(); - bool Initialised(); - void PenColour(ColourDesired fore); - - /** Returns a CGImageRef that represents the surface. Returns NULL if this is not possible. */ - CGImageRef GetImage(); - void CopyImageRectangle(Surface &surfaceSource, PRectangle srcRect, PRectangle dstRect); - - int LogPixelsY(); - int DeviceHeightFont(int points); - void MoveTo(int x_, int y_); - void LineTo(int x_, int y_); - void Polygon(Scintilla::Point *pts, int npts, ColourDesired fore, ColourDesired back); - void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back); - void FillRectangle(PRectangle rc, ColourDesired back); - void FillRectangle(PRectangle rc, Surface &surfacePattern); - void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back); - void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill, - ColourDesired outline, int alphaOutline, int flags); - void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage); - void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back); - void Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource); - void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, - ColourDesired back); - void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, - ColourDesired back); - void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore); - void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions); - XYPOSITION WidthText(Font &font_, const char *s, int len); - XYPOSITION WidthChar(Font &font_, char ch); - XYPOSITION Ascent(Font &font_); - XYPOSITION Descent(Font &font_); - XYPOSITION InternalLeading(Font &font_); - XYPOSITION ExternalLeading(Font &font_); - XYPOSITION Height(Font &font_); - XYPOSITION AverageCharWidth(Font &font_); - - void SetClip(PRectangle rc); - void FlushCachedState(); - - void SetUnicodeMode(bool unicodeMode_); - void SetDBCSMode(int codePage_); -}; // SurfaceImpl class - -} // Scintilla namespace - -#endif + +/** + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). + */ + +#ifndef PLATCOCOA_H +#define PLATCOCOA_H + +#include +#include +#include + +#include + +#include + +#include +#include "QuartzTextLayout.h" + +#include "Platform.h" +#include "Scintilla.h" + +NSRect PRectangleToNSRect(Scintilla::PRectangle& rc); +Scintilla::PRectangle NSRectToPRectangle(NSRect& rc); +CFStringEncoding EncodingFromCharacterSet(bool unicode, int characterSet); + +@interface ScintillaContextMenu : NSMenu +{ + Scintilla::ScintillaCocoa* owner; +} +- (void) handleCommand: (NSMenuItem*) sender; +- (void) setOwner: (Scintilla::ScintillaCocoa*) newOwner; + +@end + +namespace Scintilla { + +// A class to do the actual text rendering for us using Quartz 2D. +class SurfaceImpl : public Surface +{ +private: + bool unicodeMode; + float x; + float y; + + CGContextRef gc; + + /** The text layout instance */ + QuartzTextLayout* textLayout; + int codePage; + int verticalDeviceResolution; + + /** If the surface is a bitmap context, contains a reference to the bitmap data. */ + uint8_t* bitmapData; + /** If the surface is a bitmap context, stores the dimensions of the bitmap. */ + int bitmapWidth; + int bitmapHeight; + + /** Set the CGContext's fill colour to the specified desired colour. */ + void FillColour( const ColourDesired& back ); + + + // 24-bit RGB+A bitmap data constants + static const int BITS_PER_COMPONENT = 8; + static const int BITS_PER_PIXEL = BITS_PER_COMPONENT * 4; + static const int BYTES_PER_PIXEL = BITS_PER_PIXEL / 8; +public: + SurfaceImpl(); + ~SurfaceImpl(); + + void Init(WindowID wid); + void Init(SurfaceID sid, WindowID wid); + void InitPixMap(int width, int height, Surface *surface_, WindowID wid); + CGContextRef GetContext() { return gc; } + + void Release(); + bool Initialised(); + void PenColour(ColourDesired fore); + + /** Returns a CGImageRef that represents the surface. Returns NULL if this is not possible. */ + CGImageRef GetImage(); + void CopyImageRectangle(Surface &surfaceSource, PRectangle srcRect, PRectangle dstRect); + + int LogPixelsY(); + int DeviceHeightFont(int points); + void MoveTo(int x_, int y_); + void LineTo(int x_, int y_); + void Polygon(Scintilla::Point *pts, int npts, ColourDesired fore, ColourDesired back); + void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back); + void FillRectangle(PRectangle rc, ColourDesired back); + void FillRectangle(PRectangle rc, Surface &surfacePattern); + void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back); + void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill, + ColourDesired outline, int alphaOutline, int flags); + void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage); + void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back); + void Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource); + void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, + ColourDesired back); + void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, + ColourDesired back); + void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore); + void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions); + XYPOSITION WidthText(Font &font_, const char *s, int len); + XYPOSITION WidthChar(Font &font_, char ch); + XYPOSITION Ascent(Font &font_); + XYPOSITION Descent(Font &font_); + XYPOSITION InternalLeading(Font &font_); + XYPOSITION ExternalLeading(Font &font_); + XYPOSITION Height(Font &font_); + XYPOSITION AverageCharWidth(Font &font_); + + void SetClip(PRectangle rc); + void FlushCachedState(); + + void SetUnicodeMode(bool unicodeMode_); + void SetDBCSMode(int codePage_); +}; // SurfaceImpl class + +} // Scintilla namespace + +#endif diff --git a/scintilla/cocoa/PlatCocoa.mm b/ThirdLibs/scintilla/cocoa/PlatCocoa.mm similarity index 96% rename from scintilla/cocoa/PlatCocoa.mm rename to ThirdLibs/scintilla/cocoa/PlatCocoa.mm index a3fd9cfa..300af377 100644 --- a/scintilla/cocoa/PlatCocoa.mm +++ b/ThirdLibs/scintilla/cocoa/PlatCocoa.mm @@ -1,2175 +1,2175 @@ -/** - * Scintilla source code edit control - * PlatCocoa.mm - implementation of platform facilities on MacOS X/Cocoa - * - * Written by Mike Lischke - * Based on PlatMacOSX.cxx - * Based on work by Evan Jones (c) 2002 - * Based on PlatGTK.cxx Copyright 1998-2002 by Neil Hodgson - * The License.txt file describes the conditions under which this software may be distributed. - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). - */ - -#import - -#include "PlatCocoa.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "XPM.h" - -#import - -#import // Temporary - -using namespace Scintilla; - -extern sptr_t scintilla_send_message(void* sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam); - -//-------------------------------------------------------------------------------------------------- - -/** - * Converts a PRectangle as used by Scintilla to standard Obj-C NSRect structure . - */ -NSRect PRectangleToNSRect(PRectangle& rc) -{ - return NSMakeRect(rc.left, rc.top, rc.Width(), rc.Height()); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Converts an NSRect as used by the system to a native Scintilla rectangle. - */ -PRectangle NSRectToPRectangle(NSRect& rc) -{ - return PRectangle(rc.origin.x, rc.origin.y, rc.size.width + rc.origin.x, rc.size.height + rc.origin.y); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Converts a PRctangle as used by Scintilla to a Quartz-style rectangle. - */ -inline CGRect PRectangleToCGRect(PRectangle& rc) -{ - return CGRectMake(rc.left, rc.top, rc.Width(), rc.Height()); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Converts a Quartz-style rectangle to a PRectangle structure as used by Scintilla. - */ -inline PRectangle CGRectToPRectangle(const CGRect& rect) -{ - PRectangle rc; - rc.left = (int)(rect.origin.x + 0.5); - rc.top = (int)(rect.origin.y + 0.5); - rc.right = (int)(rect.origin.x + rect.size.width + 0.5); - rc.bottom = (int)(rect.origin.y + rect.size.height + 0.5); - return rc; -} - -//----------------- Point -------------------------------------------------------------------------- - -/** - * Converts a point given as a long into a native Point structure. - */ -Scintilla::Point Scintilla::Point::FromLong(long lpoint) -{ - return Scintilla::Point( - Platform::LowShortFromLong(lpoint), - Platform::HighShortFromLong(lpoint) - ); -} - -//----------------- Font --------------------------------------------------------------------------- - -Font::Font(): fid(0) -{ -} - -//-------------------------------------------------------------------------------------------------- - -Font::~Font() -{ - Release(); -} - -//-------------------------------------------------------------------------------------------------- - -static int FontCharacterSet(Font &f) { - return reinterpret_cast(f.GetID())->getCharacterSet(); -} - -/** - * Creates a CTFontRef with the given properties. - */ -void Font::Create(const FontParameters &fp) -{ - Release(); - - QuartzTextStyle* style = new QuartzTextStyle(); - fid = style; - - // Create the font with attributes - QuartzFont font(fp.faceName, strlen(fp.faceName), fp.size, fp.weight, fp.italic); - CTFontRef fontRef = font.getFontID(); - style->setFontRef(fontRef, fp.characterSet); -} - -//-------------------------------------------------------------------------------------------------- - -void Font::Release() -{ - if (fid) - delete reinterpret_cast( fid ); - fid = 0; -} - -//----------------- SurfaceImpl -------------------------------------------------------------------- - -SurfaceImpl::SurfaceImpl() -{ - unicodeMode = true; - x = 0; - y = 0; - gc = NULL; - - textLayout = new QuartzTextLayout(NULL); - codePage = 0; - verticalDeviceResolution = 0; - - bitmapData = NULL; // Release will try and delete bitmapData if != NULL - bitmapWidth = 0; - bitmapHeight = 0; - - Release(); -} - -//-------------------------------------------------------------------------------------------------- - -SurfaceImpl::~SurfaceImpl() -{ - Release(); - delete textLayout; -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::Release() -{ - textLayout->setContext (NULL); - if ( bitmapData != NULL ) - { - delete[] bitmapData; - // We only "own" the graphics context if we are a bitmap context - if (gc != NULL) - CGContextRelease(gc); - } - bitmapData = NULL; - gc = NULL; - - bitmapWidth = 0; - bitmapHeight = 0; - x = 0; - y = 0; -} - -//-------------------------------------------------------------------------------------------------- - -bool SurfaceImpl::Initialised() -{ - // We are initalised if the graphics context is not null - return gc != NULL;// || port != NULL; -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::Init(WindowID) -{ - // To be able to draw, the surface must get a CGContext handle. We save the graphics port, - // then aquire/release the context on an as-need basis (see above). - // XXX Docs on QDBeginCGContext are light, a better way to do this would be good. - // AFAIK we should not hold onto a context retrieved this way, thus the need for - // aquire/release of the context. - - Release(); -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::Init(SurfaceID sid, WindowID) -{ - Release(); - gc = reinterpret_cast(sid); - CGContextSetLineWidth(gc, 1.0); - textLayout->setContext(gc); -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::InitPixMap(int width, int height, Surface* /* surface_ */, WindowID /* wid */) -{ - Release(); - - // Create a new bitmap context, along with the RAM for the bitmap itself - bitmapWidth = width; - bitmapHeight = height; - - const int bitmapBytesPerRow = (width * BYTES_PER_PIXEL); - const int bitmapByteCount = (bitmapBytesPerRow * height); - - // Create an RGB color space. - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - if (colorSpace == NULL) - return; - - // Create the bitmap. - bitmapData = new uint8_t[bitmapByteCount]; - if (bitmapData != NULL) - { - // create the context - gc = CGBitmapContextCreate(bitmapData, - width, - height, - BITS_PER_COMPONENT, - bitmapBytesPerRow, - colorSpace, - kCGImageAlphaPremultipliedLast); - - if (gc == NULL) - { - // the context couldn't be created for some reason, - // and we have no use for the bitmap without the context - delete[] bitmapData; - bitmapData = NULL; - } - textLayout->setContext (gc); - } - - // the context retains the color space, so we can release it - CGColorSpaceRelease(colorSpace); - - if (gc != NULL && bitmapData != NULL) - { - // "Erase" to white. - CGContextClearRect( gc, CGRectMake( 0, 0, width, height ) ); - CGContextSetRGBFillColor( gc, 1.0, 1.0, 1.0, 1.0 ); - CGContextFillRect( gc, CGRectMake( 0, 0, width, height ) ); - } -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::PenColour(ColourDesired fore) -{ - if (gc) - { - ColourDesired colour(fore.AsLong()); - - // Set the Stroke color to match - CGContextSetRGBStrokeColor(gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, - colour.GetBlue() / 255.0, 1.0 ); - } -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::FillColour(const ColourDesired& back) -{ - if (gc) - { - ColourDesired colour(back.AsLong()); - - // Set the Fill color to match - CGContextSetRGBFillColor(gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, - colour.GetBlue() / 255.0, 1.0 ); - } -} - -//-------------------------------------------------------------------------------------------------- - -CGImageRef SurfaceImpl::GetImage() -{ - // For now, assume that GetImage can only be called on PixMap surfaces. - if (bitmapData == NULL) - return NULL; - - CGContextFlush(gc); - - // Create an RGB color space. - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - if( colorSpace == NULL ) - return NULL; - - const int bitmapBytesPerRow = ((int) bitmapWidth * BYTES_PER_PIXEL); - const int bitmapByteCount = (bitmapBytesPerRow * (int) bitmapHeight); - - // Make a copy of the bitmap data for the image creation and divorce it - // From the SurfaceImpl lifetime - CFDataRef dataRef = CFDataCreate(kCFAllocatorDefault, bitmapData, bitmapByteCount); - - // Create a data provider. - CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(dataRef); - - CGImageRef image = NULL; - if (dataProvider != NULL) - { - // Create the CGImage. - image = CGImageCreate(bitmapWidth, - bitmapHeight, - BITS_PER_COMPONENT, - BITS_PER_PIXEL, - bitmapBytesPerRow, - colorSpace, - kCGImageAlphaPremultipliedLast, - dataProvider, - NULL, - 0, - kCGRenderingIntentDefault); - } - - // The image retains the color space, so we can release it. - CGColorSpaceRelease(colorSpace); - colorSpace = NULL; - - // Done with the data provider. - CGDataProviderRelease(dataProvider); - dataProvider = NULL; - - // Done with the data provider. - CFRelease(dataRef); - - return image; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Returns the vertical logical device resolution of the main monitor. - */ -int SurfaceImpl::LogPixelsY() -{ - if (verticalDeviceResolution == 0) - { - NSSize deviceResolution = [[[[NSScreen mainScreen] deviceDescription] - objectForKey: NSDeviceResolution] sizeValue]; - verticalDeviceResolution = (int) deviceResolution.height; - } - return verticalDeviceResolution; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Converts the logical font height (in dpi) into a pixel height for the current main screen. - */ -int SurfaceImpl::DeviceHeightFont(int points) -{ - int logPix = LogPixelsY(); - return (points * logPix + logPix / 2) / 72; -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::MoveTo(int x_, int y_) -{ - x = x_; - y = y_; -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::LineTo(int x_, int y_) -{ - CGContextBeginPath( gc ); - - // Because Quartz is based on floating point, lines are drawn with half their colour - // on each side of the line. Integer coordinates specify the INTERSECTION of the pixel - // divison lines. If you specify exact pixel values, you get a line that - // is twice as thick but half as intense. To get pixel aligned rendering, - // we render the "middle" of the pixels by adding 0.5 to the coordinates. - CGContextMoveToPoint( gc, x + 0.5, y + 0.5 ); - CGContextAddLineToPoint( gc, x_ + 0.5, y_ + 0.5 ); - CGContextStrokePath( gc ); - x = x_; - y = y_; -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::Polygon(Scintilla::Point *pts, int npts, ColourDesired fore, - ColourDesired back) -{ - // Allocate memory for the array of points. - CGPoint *points = new CGPoint[npts]; - - for (int i = 0;i < npts;i++) - { - // Quartz floating point issues: plot the MIDDLE of the pixels - points[i].x = pts[i].x + 0.5; - points[i].y = pts[i].y + 0.5; - } - - CGContextBeginPath(gc); - - // Set colours - FillColour(back); - PenColour(fore); - - // Draw the polygon - CGContextAddLines(gc, points, npts); - - // Explicitly close the path, so it is closed for stroking AND filling (implicit close = filling only) - CGContextClosePath( gc ); - CGContextDrawPath( gc, kCGPathFillStroke ); - - // Deallocate memory. - delete points; - points = NULL; -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back) -{ - if (gc) - { - CGContextBeginPath( gc ); - FillColour(back); - PenColour(fore); - - // Quartz integer -> float point conversion fun (see comment in SurfaceImpl::LineTo) - // We subtract 1 from the Width() and Height() so that all our drawing is within the area defined - // by the PRectangle. Otherwise, we draw one pixel too far to the right and bottom. - CGContextAddRect( gc, CGRectMake( rc.left + 0.5, rc.top + 0.5, rc.Width() - 1, rc.Height() - 1 ) ); - CGContextDrawPath( gc, kCGPathFillStroke ); - } -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::FillRectangle(PRectangle rc, ColourDesired back) -{ - if (gc) - { - FillColour(back); - // Snap rectangle boundaries to nearest int - rc.left = lround(rc.left); - rc.right = lround(rc.right); - CGRect rect = PRectangleToCGRect(rc); - CGContextFillRect(gc, rect); - } -} - -//-------------------------------------------------------------------------------------------------- - -void drawImageRefCallback(CGImageRef pattern, CGContextRef gc) -{ - CGContextDrawImage(gc, CGRectMake(0, 0, CGImageGetWidth(pattern), CGImageGetHeight(pattern)), pattern); -} - -//-------------------------------------------------------------------------------------------------- - -void releaseImageRefCallback(CGImageRef pattern) -{ - CGImageRelease(pattern); -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) -{ - SurfaceImpl& patternSurface = static_cast(surfacePattern); - - // For now, assume that copy can only be called on PixMap surfaces. Shows up black. - CGImageRef image = patternSurface.GetImage(); - if (image == NULL) - { - FillRectangle(rc, ColourDesired(0)); - return; - } - - const CGPatternCallbacks drawImageCallbacks = { 0, - reinterpret_cast(drawImageRefCallback), - reinterpret_cast(releaseImageRefCallback) }; - - CGPatternRef pattern = CGPatternCreate(image, - CGRectMake(0, 0, patternSurface.bitmapWidth, patternSurface.bitmapHeight), - CGAffineTransformIdentity, - patternSurface.bitmapWidth, - patternSurface.bitmapHeight, - kCGPatternTilingNoDistortion, - true, - &drawImageCallbacks - ); - if (pattern != NULL) - { - // Create a pattern color space - CGColorSpaceRef colorSpace = CGColorSpaceCreatePattern( NULL ); - if( colorSpace != NULL ) { - - CGContextSaveGState( gc ); - CGContextSetFillColorSpace( gc, colorSpace ); - - // Unlike the documentation, you MUST pass in a "components" parameter: - // For coloured patterns it is the alpha value. - const CGFloat alpha = 1.0; - CGContextSetFillPattern( gc, pattern, &alpha ); - CGContextFillRect( gc, PRectangleToCGRect( rc ) ); - CGContextRestoreGState( gc ); - // Free the color space, the pattern and image - CGColorSpaceRelease( colorSpace ); - } /* colorSpace != NULL */ - colorSpace = NULL; - CGPatternRelease( pattern ); - pattern = NULL; - } /* pattern != NULL */ -} - -void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back) { - // This is only called from the margin marker drawing code for SC_MARK_ROUNDRECT - // The Win32 version does - // ::RoundRect(hdc, rc.left + 1, rc.top, rc.right - 1, rc.bottom, 8, 8 ); - // which is a rectangle with rounded corners each having a radius of 4 pixels. - // It would be almost as good just cutting off the corners with lines at - // 45 degrees as is done on GTK+. - - // Create a rectangle with semicircles at the corners - const int MAX_RADIUS = 4; - int radius = Platform::Minimum( MAX_RADIUS, rc.Height()/2 ); - radius = Platform::Minimum( radius, rc.Width()/2 ); - - // Points go clockwise, starting from just below the top left - // Corners are kept together, so we can easily create arcs to connect them - CGPoint corners[4][3] = - { - { - { rc.left, rc.top + radius }, - { rc.left, rc.top }, - { rc.left + radius, rc.top }, - }, - { - { rc.right - radius - 1, rc.top }, - { rc.right - 1, rc.top }, - { rc.right - 1, rc.top + radius }, - }, - { - { rc.right - 1, rc.bottom - radius - 1 }, - { rc.right - 1, rc.bottom - 1 }, - { rc.right - radius - 1, rc.bottom - 1 }, - }, - { - { rc.left + radius, rc.bottom - 1 }, - { rc.left, rc.bottom - 1 }, - { rc.left, rc.bottom - radius - 1 }, - }, - }; - - // Align the points in the middle of the pixels - for( int i = 0; i < 4*3; ++ i ) - { - CGPoint* c = (CGPoint*) corners; - c[i].x += 0.5; - c[i].y += 0.5; - } - - PenColour( fore ); - FillColour( back ); - - // Move to the last point to begin the path - CGContextBeginPath( gc ); - CGContextMoveToPoint( gc, corners[3][2].x, corners[3][2].y ); - - for ( int i = 0; i < 4; ++ i ) - { - CGContextAddLineToPoint( gc, corners[i][0].x, corners[i][0].y ); - CGContextAddArcToPoint( gc, corners[i][1].x, corners[i][1].y, corners[i][2].x, corners[i][2].y, radius ); - } - - // Close the path to enclose it for stroking and for filling, then draw it - CGContextClosePath( gc ); - CGContextDrawPath( gc, kCGPathFillStroke ); -} - -void Scintilla::SurfaceImpl::AlphaRectangle(PRectangle rc, int /*cornerSize*/, ColourDesired fill, int alphaFill, - ColourDesired /*outline*/, int /*alphaOutline*/, int /*flags*/) -{ - if ( gc ) { - ColourDesired colour( fill.AsLong() ); - - // Snap rectangle boundaries to nearest int - rc.left = lround(rc.left); - rc.right = lround(rc.right); - // Set the Fill color to match - CGContextSetRGBFillColor( gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, colour.GetBlue() / 255.0, alphaFill / 255.0 ); - CGRect rect = PRectangleToCGRect( rc ); - CGContextFillRect( gc, rect ); - } -} - -static CGImageRef ImageCreateFromRGBA(int width, int height, const unsigned char *pixelsImage, bool invert) { - CGImageRef image = 0; - - // Create an RGB color space. - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - if (colorSpace) { - const int bitmapBytesPerRow = ((int) width * 4); - const int bitmapByteCount = (bitmapBytesPerRow * (int) height); - - // Create a data provider. - CGDataProviderRef dataProvider = 0; - unsigned char *pixelsUpsideDown = 0; - if (invert) { - pixelsUpsideDown = new unsigned char[bitmapByteCount]; - - for (int y=0; y(surfaceSource); - CGImageRef image = source.GetImage(); - - CGRect src = PRectangleToCGRect(srcRect); - CGRect dst = PRectangleToCGRect(dstRect); - - /* source from QuickDrawToQuartz2D.pdf on developer.apple.com */ - float w = (float) CGImageGetWidth(image); - float h = (float) CGImageGetHeight(image); - CGRect drawRect = CGRectMake (0, 0, w, h); - if (!CGRectEqualToRect (src, dst)) - { - float sx = CGRectGetWidth(dst) / CGRectGetWidth(src); - float sy = CGRectGetHeight(dst) / CGRectGetHeight(src); - float dx = CGRectGetMinX(dst) - (CGRectGetMinX(src) * sx); - float dy = CGRectGetMinY(dst) - (CGRectGetMinY(src) * sy); - drawRect = CGRectMake (dx, dy, w*sx, h*sy); - } - CGContextSaveGState (gc); - CGContextClipToRect (gc, dst); - CGContextDrawImage (gc, drawRect, image); - CGContextRestoreGState (gc); - CGImageRelease(image); -} - -void SurfaceImpl::Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource) { - // Maybe we have to make the Surface two contexts: - // a bitmap context which we do all the drawing on, and then a "real" context - // which we copy the output to when we call "Synchronize". Ugh! Gross and slow! - - // For now, assume that copy can only be called on PixMap surfaces - SurfaceImpl& source = static_cast(surfaceSource); - - // Get the CGImageRef - CGImageRef image = source.GetImage(); - // If we could not get an image reference, fill the rectangle black - if ( image == NULL ) - { - FillRectangle( rc, ColourDesired( 0 ) ); - return; - } - - // Now draw the image on the surface - - // Some fancy clipping work is required here: draw only inside of rc - CGContextSaveGState( gc ); - CGContextClipToRect( gc, PRectangleToCGRect( rc ) ); - - //Platform::DebugPrintf(stderr, "Copy: CGContextDrawImage: (%d, %d) - (%d X %d)\n", rc.left - from.x, rc.top - from.y, source.bitmapWidth, source.bitmapHeight ); - CGContextDrawImage( gc, CGRectMake( rc.left - from.x, rc.top - from.y, source.bitmapWidth, source.bitmapHeight ), image ); - - // Undo the clipping fun - CGContextRestoreGState( gc ); - - // Done with the image - CGImageRelease( image ); - image = NULL; -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, - ColourDesired fore, ColourDesired back) -{ - FillRectangle(rc, back); - DrawTextTransparent(rc, font_, ybase, s, len, fore); -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, - ColourDesired fore, ColourDesired back) -{ - CGContextSaveGState(gc); - CGContextClipToRect(gc, PRectangleToCGRect(rc)); - DrawTextNoClip(rc, font_, ybase, s, len, fore, back); - CGContextRestoreGState(gc); -} - -//-------------------------------------------------------------------------------------------------- - -CFStringEncoding EncodingFromCharacterSet(bool unicode, int characterSet) -{ - if (unicode) - return kCFStringEncodingUTF8; - - // Unsupported -> Latin1 as reasonably safe - enum { notSupported = kCFStringEncodingISOLatin1}; - - switch (characterSet) - { - case SC_CHARSET_ANSI: - return kCFStringEncodingISOLatin1; - case SC_CHARSET_DEFAULT: - return kCFStringEncodingISOLatin1; - case SC_CHARSET_BALTIC: - return kCFStringEncodingWindowsBalticRim; - case SC_CHARSET_CHINESEBIG5: - return kCFStringEncodingBig5; - case SC_CHARSET_EASTEUROPE: - return kCFStringEncodingWindowsLatin2; - case SC_CHARSET_GB2312: - return kCFStringEncodingGB_18030_2000; - case SC_CHARSET_GREEK: - return kCFStringEncodingWindowsGreek; - case SC_CHARSET_HANGUL: - return kCFStringEncodingEUC_KR; - case SC_CHARSET_MAC: - return kCFStringEncodingMacRoman; - case SC_CHARSET_OEM: - return kCFStringEncodingISOLatin1; - case SC_CHARSET_RUSSIAN: - return kCFStringEncodingKOI8_R; - case SC_CHARSET_CYRILLIC: - return kCFStringEncodingWindowsCyrillic; - case SC_CHARSET_SHIFTJIS: - return kCFStringEncodingShiftJIS; - case SC_CHARSET_SYMBOL: - return kCFStringEncodingMacSymbol; - case SC_CHARSET_TURKISH: - return kCFStringEncodingWindowsLatin5; - case SC_CHARSET_JOHAB: - return kCFStringEncodingWindowsKoreanJohab; - case SC_CHARSET_HEBREW: - return kCFStringEncodingWindowsHebrew; - case SC_CHARSET_ARABIC: - return kCFStringEncodingWindowsArabic; - case SC_CHARSET_VIETNAMESE: - return kCFStringEncodingWindowsVietnamese; - case SC_CHARSET_THAI: - return kCFStringEncodingISOLatinThai; - case SC_CHARSET_8859_15: - return kCFStringEncodingISOLatin1; - default: - return notSupported; - } -} - -void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, - ColourDesired fore) -{ - CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); - ColourDesired colour(fore.AsLong()); - CGColorRef color = CGColorCreateGenericRGB(colour.GetRed()/255.0,colour.GetGreen()/255.0,colour.GetBlue()/255.0,1.0); - - QuartzTextStyle* style = reinterpret_cast(font_.GetID()); - style->setCTStyleColor(color); - - CGColorRelease(color); - - textLayout->setText (reinterpret_cast(s), len, encoding, *reinterpret_cast(font_.GetID())); - textLayout->draw(rc.left, ybase); -} - -static size_t utf8LengthFromLead(unsigned char uch) { - if (uch >= (0x80 + 0x40 + 0x20 + 0x10)) { - return 4; - } else if (uch >= (0x80 + 0x40 + 0x20)) { - return 3; - } else if (uch >= (0x80)) { - return 2; - } else { - return 1; - } -} - -//-------------------------------------------------------------------------------------------------- - -void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) -{ - CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); - textLayout->setText (reinterpret_cast(s), len, encoding, *reinterpret_cast(font_.GetID())); - - CTLineRef mLine = textLayout->getCTLine(); - assert(mLine != NULL); - - if (unicodeMode) { - // Map the widths given for UTF-16 characters back onto the UTF-8 input string - CFIndex fit = textLayout->getStringLength(); - int ui=0; - const unsigned char *us = reinterpret_cast(s); - int i=0; - while (ui 0) - lastPos = positions[i-1]; - while (isetText (reinterpret_cast(s), len, encoding, *reinterpret_cast(font_.GetID())); - - return textLayout->MeasureStringWidth(); - } - return 1; -} - -XYPOSITION SurfaceImpl::WidthChar(Font &font_, char ch) { - char str[2] = { ch, '\0' }; - if (font_.GetID()) - { - CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); - textLayout->setText (reinterpret_cast(str), 1, encoding, *reinterpret_cast(font_.GetID())); - - return textLayout->MeasureStringWidth(); - } - else - return 1; -} - -// This string contains a good range of characters to test for size. -const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890" -"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - -XYPOSITION SurfaceImpl::Ascent(Font &font_) { - if (!font_.GetID()) - return 1; - - float ascent = reinterpret_cast( font_.GetID() )->getAscent(); - return ascent + 0.5; - -} - -XYPOSITION SurfaceImpl::Descent(Font &font_) { - if (!font_.GetID()) - return 1; - - float descent = reinterpret_cast( font_.GetID() )->getDescent(); - return descent + 0.5; - -} - -XYPOSITION SurfaceImpl::InternalLeading(Font &) { - return 0; -} - -XYPOSITION SurfaceImpl::ExternalLeading(Font &font_) { - if (!font_.GetID()) - return 1; - - float leading = reinterpret_cast( font_.GetID() )->getLeading(); - return leading + 0.5; - -} - -XYPOSITION SurfaceImpl::Height(Font &font_) { - - int ht = Ascent(font_) + Descent(font_); - return ht; -} - -XYPOSITION SurfaceImpl::AverageCharWidth(Font &font_) { - - if (!font_.GetID()) - return 1; - - const int sizeStringLength = (sizeof( sizeString ) / sizeof( sizeString[0] ) - 1); - int width = WidthText( font_, sizeString, sizeStringLength ); - - return (int) ((width / (float) sizeStringLength) + 0.5); -} - -void SurfaceImpl::SetClip(PRectangle rc) { - CGContextClipToRect( gc, PRectangleToCGRect( rc ) ); -} - -void SurfaceImpl::FlushCachedState() { - CGContextSynchronize( gc ); -} - -void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) { - unicodeMode = unicodeMode_; -} - -void SurfaceImpl::SetDBCSMode(int codePage_) { - if (codePage_ && (codePage_ != SC_CP_UTF8)) - codePage = codePage_; -} - -Surface *Surface::Allocate(int) -{ - return new SurfaceImpl(); -} - -//----------------- Window ------------------------------------------------------------------------- - -// Cocoa uses different types for windows and views, so a Window may -// be either an NSWindow or NSView and the code will check the type -// before performing an action. - -Window::~Window() -{ -} - -//-------------------------------------------------------------------------------------------------- - -void Window::Destroy() -{ - if (wid) - { - id idWin = reinterpret_cast(wid); - if ([idWin isKindOfClass: [NSWindow class]]) - { - NSWindow* win = reinterpret_cast(idWin); - [win release]; - } - } - wid = 0; -} - -//-------------------------------------------------------------------------------------------------- - -bool Window::HasFocus() -{ - NSView* container = reinterpret_cast(wid); - return [[container window] firstResponder] == container; -} - -//-------------------------------------------------------------------------------------------------- - -static int ScreenMax(NSWindow* win) -{ - NSScreen* screen = [win screen]; - NSRect frame = [screen frame]; - return frame.origin.y + frame.size.height; -} - -PRectangle Window::GetPosition() -{ - if (wid) - { - NSRect rect; - id idWin = reinterpret_cast(wid); - NSWindow* win; - if ([idWin isKindOfClass: [NSView class]]) - { - // NSView - NSView* view = reinterpret_cast(idWin); - win = [view window]; - rect = [view bounds]; - rect = [view convertRectToBase: rect]; - rect.origin = [win convertBaseToScreen:rect.origin]; - } - else - { - // NSWindow - win = reinterpret_cast(idWin); - rect = [win frame]; - } - int screenHeight = ScreenMax(win); - // Invert screen positions to match Scintilla - return PRectangle( - NSMinX(rect), screenHeight - NSMaxY(rect), - NSMaxX(rect), screenHeight - NSMinY(rect)); - } - else - { - return PRectangle(0, 0, 1, 1); - } -} - -//-------------------------------------------------------------------------------------------------- - -void Window::SetPosition(PRectangle rc) -{ - if (wid) - { - id idWin = reinterpret_cast(wid); - if ([idWin isKindOfClass: [NSView class]]) - { - // NSView - // Moves this view inside the parent view - NSRect nsrc = NSMakeRect(rc.left, rc.bottom, rc.Width(), rc.Height()); - NSView* view = reinterpret_cast(idWin); - nsrc.origin = [[view window] convertScreenToBase:nsrc.origin]; - [view setFrame: nsrc]; - } - else - { - // NSWindow - NSWindow* win = reinterpret_cast(idWin); - int screenHeight = ScreenMax(win); - NSRect nsrc = NSMakeRect(rc.left, screenHeight - rc.bottom, - rc.Width(), rc.Height()); - [win setFrame: nsrc display:YES]; - } - } -} - -//-------------------------------------------------------------------------------------------------- - -void Window::SetPositionRelative(PRectangle rc, Window window) -{ - PRectangle rcOther = window.GetPosition(); - rc.left += rcOther.left; - rc.right += rcOther.left; - rc.top += rcOther.top; - rc.bottom += rcOther.top; - SetPosition(rc); -} - -//-------------------------------------------------------------------------------------------------- - -PRectangle Window::GetClientPosition() -{ - // This means, in MacOS X terms, get the "frame bounds". Call GetPosition, just like on Win32. - return GetPosition(); -} - -//-------------------------------------------------------------------------------------------------- - -void Window::Show(bool show) -{ - if (wid) - { - id idWin = reinterpret_cast(wid); - if ([idWin isKindOfClass: [NSWindow class]]) - { - NSWindow* win = reinterpret_cast(idWin); - if (show) - { - [win orderFront:nil]; - } - else - { - [win orderOut:nil]; - } - } - } -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Invalidates the entire window or view so it is completely redrawn. - */ -void Window::InvalidateAll() -{ - if (wid) - { - id idWin = reinterpret_cast(wid); - NSView* container; - if ([idWin isKindOfClass: [NSView class]]) - { - container = reinterpret_cast(idWin); - } - else - { - // NSWindow - NSWindow* win = reinterpret_cast(idWin); - container = reinterpret_cast([win contentView]); - container.needsDisplay = YES; - } - container.needsDisplay = YES; - } -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Invalidates part of the window or view so only this part redrawn. - */ -void Window::InvalidateRectangle(PRectangle rc) -{ - if (wid) - { - id idWin = reinterpret_cast(wid); - NSView* container; - if ([idWin isKindOfClass: [NSView class]]) - { - container = reinterpret_cast(idWin); - } - else - { - // NSWindow - NSWindow* win = reinterpret_cast(idWin); - container = reinterpret_cast([win contentView]); - } - [container setNeedsDisplayInRect: PRectangleToNSRect(rc)]; - } -} - -//-------------------------------------------------------------------------------------------------- - -void Window::SetFont(Font&) -{ - // Implemented on list subclass on Cocoa. -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Converts the Scintilla cursor enum into an NSCursor and stores it in the associated NSView, - * which then will take care to set up a new mouse tracking rectangle. - */ -void Window::SetCursor(Cursor curs) -{ - if (wid) - { - id idWin = reinterpret_cast(wid); - if ([idWin isMemberOfClass: [InnerView class]]) - { - InnerView* container = reinterpret_cast(idWin); - [container setCursor: curs]; - } - } -} - -//-------------------------------------------------------------------------------------------------- - -void Window::SetTitle(const char* s) -{ - if (wid) - { - id idWin = reinterpret_cast(wid); - if ([idWin isKindOfClass: [NSWindow class]]) - { - NSWindow* win = reinterpret_cast(idWin); - NSString* sTitle = [NSString stringWithUTF8String:s]; - [win setTitle:sTitle]; - } - } -} - -//-------------------------------------------------------------------------------------------------- - -PRectangle Window::GetMonitorRect(Point) -{ - if (wid) - { - id idWin = reinterpret_cast(wid); - if ([idWin isKindOfClass: [NSWindow class]]) - { - NSWindow* win = reinterpret_cast(idWin); - NSScreen* screen = [win screen]; - NSRect rect = [screen frame]; - int screenHeight = rect.origin.y + rect.size.height; - // Invert screen positions to match Scintilla - return PRectangle( - NSMinX(rect), screenHeight - NSMaxY(rect), - NSMaxX(rect), screenHeight - NSMinY(rect)); - } - } - return PRectangle(); -} - -//----------------- ImageFromXPM ------------------------------------------------------------------- - -// Convert an XPM image into an NSImage for use with Cocoa - -static NSImage* ImageFromXPM(XPM* pxpm) -{ - NSImage* img = nil; - if (pxpm) - { - const int width = pxpm->GetWidth(); - const int height = pxpm->GetHeight(); - PRectangle rcxpm(0, 0, width, height); - Surface* surfaceXPM = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); - if (surfaceXPM) - { - surfaceXPM->InitPixMap(width, height, NULL, NULL); - SurfaceImpl* surfaceIXPM = static_cast(surfaceXPM); - CGContextClearRect(surfaceIXPM->GetContext(), CGRectMake(0, 0, width, height)); - pxpm->Draw(surfaceXPM, rcxpm); - img = [[[NSImage alloc] initWithSize:NSZeroSize] autorelease]; - CGImageRef imageRef = surfaceIXPM->GetImage(); - NSBitmapImageRep *bitmapRep = [[NSBitmapImageRep alloc] initWithCGImage: imageRef]; - [img addRepresentation: bitmapRep]; - [bitmapRep release]; - CGImageRelease(imageRef); - delete surfaceXPM; - } - } - return img; -} - -//----------------- ListBox ------------------------------------------------------------------------ - -ListBox::ListBox() -{ -} - -//-------------------------------------------------------------------------------------------------- - -ListBox::~ListBox() -{ -} - -//-------------------------------------------------------------------------------------------------- - -struct RowData -{ - int type; - std::string text; - RowData(int type_, const char* text_) : - type(type_), text(text_) - { - } -}; - -class LinesData -{ - std::vector lines; -public: - LinesData() - { - } - ~LinesData() - { - } - int Length() const - { - return static_cast(lines.size()); - } - void Clear() - { - lines.clear(); - } - void Add(int /* index */, int type, char* str) - { - lines.push_back(RowData(type, str)); - } - int GetType(size_t index) const - { - if (index < lines.size()) - { - return lines[index].type; - } - else - { - return 0; - } - } - const char* GetString(size_t index) const - { - if (index < lines.size()) - { - return lines[index].text.c_str(); - } - else - { - return 0; - } - } -}; - -class ListBoxImpl; - -@interface AutoCompletionDataSource : -NSObject -#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 - -#endif -{ - ListBoxImpl* box; -} - -@end - -//----------------- ListBoxImpl -------------------------------------------------------------------- - -// Map from icon type to an NSImage* -typedef std::map ImageMap; - -class ListBoxImpl : public ListBox -{ -private: - ControlRef lb; - ImageMap images; - int lineHeight; - bool unicodeMode; - int desiredVisibleRows; - unsigned int maxItemWidth; - unsigned int aveCharWidth; - unsigned int maxIconWidth; - Font font; - int maxWidth; - - NSTableView* table; - NSScrollView* scroller; - NSTableColumn* colIcon; - NSTableColumn* colText; - AutoCompletionDataSource* ds; - - LinesData ld; - CallBackAction doubleClickAction; - void* doubleClickActionData; - -public: - ListBoxImpl() : lb(NULL), lineHeight(10), unicodeMode(false), - desiredVisibleRows(5), maxItemWidth(0), aveCharWidth(8), maxIconWidth(0), - doubleClickAction(NULL), doubleClickActionData(NULL) - { - } - ~ListBoxImpl() {} - - // ListBox methods - void SetFont(Font& font); - void Create(Window& parent, int ctrlID, Scintilla::Point pt, int lineHeight_, bool unicodeMode_, int technology_); - void SetAverageCharWidth(int width); - void SetVisibleRows(int rows); - int GetVisibleRows() const; - PRectangle GetDesiredRect(); - int CaretFromEdge(); - void Clear(); - void Append(char* s, int type = -1); - int Length(); - void Select(int n); - int GetSelection(); - int Find(const char* prefix); - void GetValue(int n, char* value, int len); - void RegisterImage(int type, const char* xpm_data); - void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage); - void ClearRegisteredImages(); - void SetDoubleClickAction(CallBackAction action, void* data) - { - doubleClickAction = action; - doubleClickActionData = data; - } - void SetList(const char* list, char separator, char typesep); - - // For access from AutoCompletionDataSource - int Rows(); - NSImage* ImageForRow(NSInteger row); - NSString* TextForRow(NSInteger row); - void DoubleClick(); -}; - -@implementation AutoCompletionDataSource - -- (void)setBox: (ListBoxImpl*)box_ -{ - box = box_; -} - -- (void) doubleClick: (id) sender -{ -#pragma unused(sender) - if (box) - { - box->DoubleClick(); - } -} - -- (id)tableView: (NSTableView*)aTableView objectValueForTableColumn: (NSTableColumn*)aTableColumn row: (NSInteger)rowIndex -{ -#pragma unused(aTableView) - if (!box) - return nil; - if ([(NSString*)[aTableColumn identifier] isEqualToString: @"icon"]) - { - return box->ImageForRow(rowIndex); - } - else { - return box->TextForRow(rowIndex); - } -} - -- (void)tableView: (NSTableView*)aTableView setObjectValue: anObject forTableColumn: (NSTableColumn*)aTableColumn row: (NSInteger)rowIndex -{ -#pragma unused(aTableView) -#pragma unused(anObject) -#pragma unused(aTableColumn) -#pragma unused(rowIndex) -} - -- (NSInteger)numberOfRowsInTableView: (NSTableView*)aTableView -{ -#pragma unused(aTableView) - if (!box) - return 0; - return box->Rows(); -} - -@end - -ListBox* ListBox::Allocate() -{ - ListBoxImpl* lb = new ListBoxImpl(); - return lb; -} - -void ListBoxImpl::Create(Window& /*parent*/, int /*ctrlID*/, Scintilla::Point pt, - int lineHeight_, bool unicodeMode_, int) -{ - lineHeight = lineHeight_; - unicodeMode = unicodeMode_; - maxWidth = 2000; - - NSRect lbRect = NSMakeRect(pt.x,pt.y, 120, lineHeight * desiredVisibleRows); - NSWindow* winLB = [[NSWindow alloc] initWithContentRect: lbRect - styleMask: NSBorderlessWindowMask - backing: NSBackingStoreBuffered - defer: NO]; - [winLB setLevel:NSFloatingWindowLevel]; - [winLB setHasShadow:YES]; - scroller = [NSScrollView alloc]; - NSRect scRect = NSMakeRect(0, 0, lbRect.size.width, lbRect.size.height); - [scroller initWithFrame: scRect]; - [scroller setHasVerticalScroller:YES]; - table = [[NSTableView alloc] initWithFrame: scRect]; - [table setHeaderView:nil]; - [scroller setDocumentView: table]; - colIcon = [[NSTableColumn alloc] initWithIdentifier:@"icon"]; - [colIcon setWidth: 20]; - [colIcon setEditable:NO]; - [colIcon setHidden:YES]; - NSImageCell* imCell = [[[NSImageCell alloc] init] autorelease]; - [colIcon setDataCell:imCell]; - [table addTableColumn:colIcon]; - colText = [[NSTableColumn alloc] initWithIdentifier:@"name"]; - [colText setResizingMask:NSTableColumnAutoresizingMask]; - [colText setEditable:NO]; - [table addTableColumn:colText]; - ds = [[AutoCompletionDataSource alloc] init]; - [ds setBox:this]; - [table setDataSource: ds]; // Weak reference - [scroller setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; - [[winLB contentView] addSubview: scroller]; - - [table setTarget:ds]; - [table setDoubleAction:@selector(doubleClick:)]; - wid = winLB; -} - -void ListBoxImpl::SetFont(Font& font_) -{ - font.SetID(font_.GetID()); - // NSCell setFont takes an NSFont* rather than a CTFontRef but they - // are the same thing toll-free bridged. - QuartzTextStyle* style = reinterpret_cast(font_.GetID()); - NSFont *pfont = (NSFont *)style->getFontRef(); - [[colText dataCell] setFont: pfont]; - CGFloat itemHeight = lround([pfont ascender] - [pfont descender]); - [table setRowHeight:itemHeight]; -} - -void ListBoxImpl::SetAverageCharWidth(int width) -{ - aveCharWidth = width; -} - -void ListBoxImpl::SetVisibleRows(int rows) -{ - desiredVisibleRows = rows; -} - -int ListBoxImpl::GetVisibleRows() const -{ - return desiredVisibleRows; -} - -PRectangle ListBoxImpl::GetDesiredRect() -{ - PRectangle rcDesired; - rcDesired = GetPosition(); - - // There appears to be an extra pixel above and below the row contents - int itemHeight = [table rowHeight] + 2; - - int rows = Length(); - if ((rows == 0) || (rows > desiredVisibleRows)) - rows = desiredVisibleRows; - - rcDesired.bottom = rcDesired.top + itemHeight * rows; - rcDesired.right = rcDesired.left + maxItemWidth + aveCharWidth; - - if (Length() > rows) - { - [scroller setHasVerticalScroller:YES]; - rcDesired.right += [NSScroller scrollerWidth]; - } - else - { - [scroller setHasVerticalScroller:NO]; - } - rcDesired.right += maxIconWidth; - rcDesired.right += 6; - - return rcDesired; -} - -int ListBoxImpl::CaretFromEdge() -{ - if ([colIcon isHidden]) - return 3; - else - return 6 + [colIcon width]; -} - -void ListBoxImpl::Clear() -{ - maxItemWidth = 0; - maxIconWidth = 0; - ld.Clear(); -} - -void ListBoxImpl::Append(char* s, int type) -{ - int count = Length(); - ld.Add(count, type, s); - - Scintilla::SurfaceImpl surface; - unsigned int width = surface.WidthText(font, s, static_cast(strlen(s))); - if (width > maxItemWidth) - { - maxItemWidth = width; - [colText setWidth: maxItemWidth]; - } - ImageMap::iterator it = images.find(type); - if (it != images.end()) - { - NSImage* img = it->second; - if (img) - { - unsigned int widthIcon = img.size.width; - if (widthIcon > maxIconWidth) - { - [colIcon setHidden: NO]; - maxIconWidth = widthIcon; - [colIcon setWidth: maxIconWidth]; - } - } - } -} - -void ListBoxImpl::SetList(const char* list, char separator, char typesep) -{ - Clear(); - size_t count = strlen(list) + 1; - char* words = new char[count]; - if (words) - { - memcpy(words, list, count); - char* startword = words; - char* numword = NULL; - int i = 0; - for (; words[i]; i++) - { - if (words[i] == separator) - { - words[i] = '\0'; - if (numword) - *numword = '\0'; - Append(startword, numword?atoi(numword + 1):-1); - startword = words + i + 1; - numword = NULL; - } - else if (words[i] == typesep) - { - numword = words + i; - } - } - if (startword) - { - if (numword) - *numword = '\0'; - Append(startword, numword?atoi(numword + 1):-1); - } - delete []words; - } - [table reloadData]; -} - -int ListBoxImpl::Length() -{ - return ld.Length(); -} - -void ListBoxImpl::Select(int n) -{ - [table selectRowIndexes:[NSIndexSet indexSetWithIndex:n] byExtendingSelection:NO]; - [table scrollRowToVisible:n]; -} - -int ListBoxImpl::GetSelection() -{ - return static_cast([table selectedRow]); -} - -int ListBoxImpl::Find(const char* prefix) -{ - int count = Length(); - for (int i = 0; i < count; i++) - { - const char* s = ld.GetString(i); - if (s && (s[0] != '\0') && (0 == strncmp(prefix, s, strlen(prefix)))) - { - return i; - } - } - return - 1; -} - -void ListBoxImpl::GetValue(int n, char* value, int len) -{ - const char* textString = ld.GetString(n); - if (textString == NULL) - { - value[0] = '\0'; - return; - } - strncpy(value, textString, len); - value[len - 1] = '\0'; -} - -void ListBoxImpl::RegisterImage(int type, const char* xpm_data) -{ - XPM xpm(xpm_data); - NSImage* img = ImageFromXPM(&xpm); - [img retain]; - ImageMap::iterator it=images.find(type); - if (it == images.end()) - { - images[type] = img; - } - else - { - [it->second release]; - it->second = img; - } -} - -void ListBoxImpl::RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) { - CGImageRef imageRef = ImageCreateFromRGBA(width, height, pixelsImage, false); - NSSize sz = {width, height}; - NSImage *img = [[[NSImage alloc] initWithSize: sz] autorelease]; - NSBitmapImageRep *bitmapRep = [[NSBitmapImageRep alloc] initWithCGImage: imageRef]; - [img addRepresentation: bitmapRep]; - [bitmapRep release]; - CGImageRelease(imageRef); - [img retain]; - ImageMap::iterator it=images.find(type); - if (it == images.end()) - { - images[type] = img; - } - else - { - [it->second release]; - it->second = img; - } -} - -void ListBoxImpl::ClearRegisteredImages() -{ - for (ImageMap::iterator it=images.begin(); - it != images.end(); ++it) - { - [it->second release]; - it->second = nil; - } - images.clear(); -} - -int ListBoxImpl::Rows() -{ - return ld.Length(); -} - -NSImage* ListBoxImpl::ImageForRow(NSInteger row) -{ - ImageMap::iterator it = images.find(ld.GetType(row)); - if (it != images.end()) - { - NSImage* img = it->second; - return img; - } - else - { - return nil; - } -} - -NSString* ListBoxImpl::TextForRow(NSInteger row) -{ - const char* textString = ld.GetString(row); - NSString* sTitle; - if (unicodeMode) - sTitle = [NSString stringWithUTF8String:textString]; - else - sTitle = [NSString stringWithCString:textString encoding:NSWindowsCP1252StringEncoding]; - return sTitle; -} - -void ListBoxImpl::DoubleClick() -{ - if (doubleClickAction) - { - doubleClickAction(doubleClickActionData); - } -} - -//----------------- ScintillaContextMenu ----------------------------------------------------------- - -@implementation ScintillaContextMenu : NSMenu - -// This NSMenu subclass serves also as target for menu commands and forwards them as -// notfication messages to the front end. - -- (void) handleCommand: (NSMenuItem*) sender -{ - owner->HandleCommand([sender tag]); -} - -//-------------------------------------------------------------------------------------------------- - -- (void) setOwner: (Scintilla::ScintillaCocoa*) newOwner -{ - owner = newOwner; -} - -@end - -//----------------- Menu --------------------------------------------------------------------------- - -Menu::Menu() - : mid(0) -{ -} - -//-------------------------------------------------------------------------------------------------- - -void Menu::CreatePopUp() -{ - Destroy(); - mid = [[ScintillaContextMenu alloc] initWithTitle: @""]; -} - -//-------------------------------------------------------------------------------------------------- - -void Menu::Destroy() -{ - ScintillaContextMenu* menu = reinterpret_cast(mid); - [menu release]; - mid = NULL; -} - -//-------------------------------------------------------------------------------------------------- - -void Menu::Show(Point, Window &) -{ - // Cocoa menus are handled a bit differently. We only create the menu. The framework - // takes care to show it properly. -} - -//----------------- ElapsedTime -------------------------------------------------------------------- - -// ElapsedTime is used for precise performance measurements during development -// and not for anything a user sees. - -ElapsedTime::ElapsedTime() { - struct timeval curTime; - gettimeofday( &curTime, NULL ); - - bigBit = curTime.tv_sec; - littleBit = curTime.tv_usec; -} - -double ElapsedTime::Duration(bool reset) { - struct timeval curTime; - gettimeofday( &curTime, NULL ); - long endBigBit = curTime.tv_sec; - long endLittleBit = curTime.tv_usec; - double result = 1000000.0 * (endBigBit - bigBit); - result += endLittleBit - littleBit; - result /= 1000000.0; - if (reset) { - bigBit = endBigBit; - littleBit = endLittleBit; - } - return result; -} - -//----------------- Platform ----------------------------------------------------------------------- - -ColourDesired Platform::Chrome() -{ - return ColourDesired(0xE0, 0xE0, 0xE0); -} - -//-------------------------------------------------------------------------------------------------- - -ColourDesired Platform::ChromeHighlight() -{ - return ColourDesired(0xFF, 0xFF, 0xFF); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Returns the currently set system font for the user. - */ -const char *Platform::DefaultFont() -{ - NSString* name = [[NSUserDefaults standardUserDefaults] stringForKey: @"NSFixedPitchFont"]; - return [name UTF8String]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Returns the currently set system font size for the user. - */ -int Platform::DefaultFontSize() -{ - return static_cast([[NSUserDefaults standardUserDefaults] - integerForKey: @"NSFixedPitchFontSize"]); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Returns the time span in which two consequtive mouse clicks must occur to be considered as - * double click. - * - * @return - */ -unsigned int Platform::DoubleClickTime() -{ - float threshold = [[NSUserDefaults standardUserDefaults] floatForKey: - @"com.apple.mouse.doubleClickThreshold"]; - if (threshold == 0) - threshold = 0.5; - return static_cast(threshold / kEventDurationMillisecond); -} - -//-------------------------------------------------------------------------------------------------- - -bool Platform::MouseButtonBounce() -{ - return false; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Helper method for the backend to reach through to the scintiall window. - */ -long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam) -{ - return scintilla_send_message(w, msg, wParam, lParam); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Helper method for the backend to reach through to the scintiall window. - */ -long Platform::SendScintillaPointer(WindowID w, unsigned int msg, unsigned long wParam, void *lParam) -{ - return scintilla_send_message(w, msg, wParam, (long) lParam); -} - -//-------------------------------------------------------------------------------------------------- - -bool Platform::IsDBCSLeadByte(int codePage, char ch) -{ - // Byte ranges found in Wikipedia articles with relevant search strings in each case - unsigned char uch = static_cast(ch); - switch (codePage) - { - case 932: - // Shift_jis - return ((uch >= 0x81) && (uch <= 0x9F)) || - ((uch >= 0xE0) && (uch <= 0xFC)); - // Lead bytes F0 to FC may be a Microsoft addition. - case 936: - // GBK - return (uch >= 0x81) && (uch <= 0xFE); - case 949: - // Korean Wansung KS C-5601-1987 - return (uch >= 0x81) && (uch <= 0xFE); - case 950: - // Big5 - return (uch >= 0x81) && (uch <= 0xFE); - case 1361: - // Korean Johab KS C-5601-1992 - return - ((uch >= 0x84) && (uch <= 0xD3)) || - ((uch >= 0xD8) && (uch <= 0xDE)) || - ((uch >= 0xE0) && (uch <= 0xF9)); - } - return false; -} - -//-------------------------------------------------------------------------------------------------- - -int Platform::DBCSCharLength(int /* codePage */, const char* /* s */) -{ - // DBCS no longer uses this. - return 1; -} - -//-------------------------------------------------------------------------------------------------- - -int Platform::DBCSCharMaxLength() -{ - return 2; -} - -//-------------------------------------------------------------------------------------------------- - -int Platform::Minimum(int a, int b) -{ - return (a < b) ? a : b; -} - -//-------------------------------------------------------------------------------------------------- - -int Platform::Maximum(int a, int b) { - return (a > b) ? a : b; -} - -//-------------------------------------------------------------------------------------------------- - -//#define TRACE -#ifdef TRACE - -void Platform::DebugDisplay(const char *s) -{ - fprintf( stderr, s ); -} - -//-------------------------------------------------------------------------------------------------- - -void Platform::DebugPrintf(const char *format, ...) -{ - const int BUF_SIZE = 2000; - char buffer[BUF_SIZE]; - - va_list pArguments; - va_start(pArguments, format); - vsnprintf(buffer, BUF_SIZE, format, pArguments); - va_end(pArguments); - Platform::DebugDisplay(buffer); -} - -#else - -void Platform::DebugDisplay(const char *) {} - -void Platform::DebugPrintf(const char *, ...) {} - -#endif - -//-------------------------------------------------------------------------------------------------- - -static bool assertionPopUps = true; - -bool Platform::ShowAssertionPopUps(bool assertionPopUps_) -{ - bool ret = assertionPopUps; - assertionPopUps = assertionPopUps_; - return ret; -} - -//-------------------------------------------------------------------------------------------------- - -void Platform::Assert(const char *c, const char *file, int line) -{ - char buffer[2000]; - sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line); - strcat(buffer, "\r\n"); - Platform::DebugDisplay(buffer); -#ifdef DEBUG - // Jump into debugger in assert on Mac (CL269835) - ::Debugger(); -#endif -} - -//-------------------------------------------------------------------------------------------------- - -int Platform::Clamp(int val, int minVal, int maxVal) -{ - if (val > maxVal) - val = maxVal; - if (val < minVal) - val = minVal; - return val; -} - -//----------------- DynamicLibrary ----------------------------------------------------------------- - -/** - * Implements the platform specific part of library loading. - * - * @param modulePath The path to the module to load. - * @return A library instance or NULL if the module could not be found or another problem occured. - */ -DynamicLibrary* DynamicLibrary::Load(const char* /* modulePath */) -{ - // Not implemented. - return NULL; -} - -//-------------------------------------------------------------------------------------------------- - +/** + * Scintilla source code edit control + * PlatCocoa.mm - implementation of platform facilities on MacOS X/Cocoa + * + * Written by Mike Lischke + * Based on PlatMacOSX.cxx + * Based on work by Evan Jones (c) 2002 + * Based on PlatGTK.cxx Copyright 1998-2002 by Neil Hodgson + * The License.txt file describes the conditions under which this software may be distributed. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). + */ + +#import + +#include "PlatCocoa.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "XPM.h" + +#import + +#import // Temporary + +using namespace Scintilla; + +extern sptr_t scintilla_send_message(void* sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam); + +//-------------------------------------------------------------------------------------------------- + +/** + * Converts a PRectangle as used by Scintilla to standard Obj-C NSRect structure . + */ +NSRect PRectangleToNSRect(PRectangle& rc) +{ + return NSMakeRect(rc.left, rc.top, rc.Width(), rc.Height()); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Converts an NSRect as used by the system to a native Scintilla rectangle. + */ +PRectangle NSRectToPRectangle(NSRect& rc) +{ + return PRectangle(rc.origin.x, rc.origin.y, rc.size.width + rc.origin.x, rc.size.height + rc.origin.y); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Converts a PRctangle as used by Scintilla to a Quartz-style rectangle. + */ +inline CGRect PRectangleToCGRect(PRectangle& rc) +{ + return CGRectMake(rc.left, rc.top, rc.Width(), rc.Height()); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Converts a Quartz-style rectangle to a PRectangle structure as used by Scintilla. + */ +inline PRectangle CGRectToPRectangle(const CGRect& rect) +{ + PRectangle rc; + rc.left = (int)(rect.origin.x + 0.5); + rc.top = (int)(rect.origin.y + 0.5); + rc.right = (int)(rect.origin.x + rect.size.width + 0.5); + rc.bottom = (int)(rect.origin.y + rect.size.height + 0.5); + return rc; +} + +//----------------- Point -------------------------------------------------------------------------- + +/** + * Converts a point given as a long into a native Point structure. + */ +Scintilla::Point Scintilla::Point::FromLong(long lpoint) +{ + return Scintilla::Point( + Platform::LowShortFromLong(lpoint), + Platform::HighShortFromLong(lpoint) + ); +} + +//----------------- Font --------------------------------------------------------------------------- + +Font::Font(): fid(0) +{ +} + +//-------------------------------------------------------------------------------------------------- + +Font::~Font() +{ + Release(); +} + +//-------------------------------------------------------------------------------------------------- + +static int FontCharacterSet(Font &f) { + return reinterpret_cast(f.GetID())->getCharacterSet(); +} + +/** + * Creates a CTFontRef with the given properties. + */ +void Font::Create(const FontParameters &fp) +{ + Release(); + + QuartzTextStyle* style = new QuartzTextStyle(); + fid = style; + + // Create the font with attributes + QuartzFont font(fp.faceName, strlen(fp.faceName), fp.size, fp.weight, fp.italic); + CTFontRef fontRef = font.getFontID(); + style->setFontRef(fontRef, fp.characterSet); +} + +//-------------------------------------------------------------------------------------------------- + +void Font::Release() +{ + if (fid) + delete reinterpret_cast( fid ); + fid = 0; +} + +//----------------- SurfaceImpl -------------------------------------------------------------------- + +SurfaceImpl::SurfaceImpl() +{ + unicodeMode = true; + x = 0; + y = 0; + gc = NULL; + + textLayout = new QuartzTextLayout(NULL); + codePage = 0; + verticalDeviceResolution = 0; + + bitmapData = NULL; // Release will try and delete bitmapData if != NULL + bitmapWidth = 0; + bitmapHeight = 0; + + Release(); +} + +//-------------------------------------------------------------------------------------------------- + +SurfaceImpl::~SurfaceImpl() +{ + Release(); + delete textLayout; +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::Release() +{ + textLayout->setContext (NULL); + if ( bitmapData != NULL ) + { + delete[] bitmapData; + // We only "own" the graphics context if we are a bitmap context + if (gc != NULL) + CGContextRelease(gc); + } + bitmapData = NULL; + gc = NULL; + + bitmapWidth = 0; + bitmapHeight = 0; + x = 0; + y = 0; +} + +//-------------------------------------------------------------------------------------------------- + +bool SurfaceImpl::Initialised() +{ + // We are initalised if the graphics context is not null + return gc != NULL;// || port != NULL; +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::Init(WindowID) +{ + // To be able to draw, the surface must get a CGContext handle. We save the graphics port, + // then aquire/release the context on an as-need basis (see above). + // XXX Docs on QDBeginCGContext are light, a better way to do this would be good. + // AFAIK we should not hold onto a context retrieved this way, thus the need for + // aquire/release of the context. + + Release(); +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::Init(SurfaceID sid, WindowID) +{ + Release(); + gc = reinterpret_cast(sid); + CGContextSetLineWidth(gc, 1.0); + textLayout->setContext(gc); +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::InitPixMap(int width, int height, Surface* /* surface_ */, WindowID /* wid */) +{ + Release(); + + // Create a new bitmap context, along with the RAM for the bitmap itself + bitmapWidth = width; + bitmapHeight = height; + + const int bitmapBytesPerRow = (width * BYTES_PER_PIXEL); + const int bitmapByteCount = (bitmapBytesPerRow * height); + + // Create an RGB color space. + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + if (colorSpace == NULL) + return; + + // Create the bitmap. + bitmapData = new uint8_t[bitmapByteCount]; + if (bitmapData != NULL) + { + // create the context + gc = CGBitmapContextCreate(bitmapData, + width, + height, + BITS_PER_COMPONENT, + bitmapBytesPerRow, + colorSpace, + kCGImageAlphaPremultipliedLast); + + if (gc == NULL) + { + // the context couldn't be created for some reason, + // and we have no use for the bitmap without the context + delete[] bitmapData; + bitmapData = NULL; + } + textLayout->setContext (gc); + } + + // the context retains the color space, so we can release it + CGColorSpaceRelease(colorSpace); + + if (gc != NULL && bitmapData != NULL) + { + // "Erase" to white. + CGContextClearRect( gc, CGRectMake( 0, 0, width, height ) ); + CGContextSetRGBFillColor( gc, 1.0, 1.0, 1.0, 1.0 ); + CGContextFillRect( gc, CGRectMake( 0, 0, width, height ) ); + } +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::PenColour(ColourDesired fore) +{ + if (gc) + { + ColourDesired colour(fore.AsLong()); + + // Set the Stroke color to match + CGContextSetRGBStrokeColor(gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, + colour.GetBlue() / 255.0, 1.0 ); + } +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::FillColour(const ColourDesired& back) +{ + if (gc) + { + ColourDesired colour(back.AsLong()); + + // Set the Fill color to match + CGContextSetRGBFillColor(gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, + colour.GetBlue() / 255.0, 1.0 ); + } +} + +//-------------------------------------------------------------------------------------------------- + +CGImageRef SurfaceImpl::GetImage() +{ + // For now, assume that GetImage can only be called on PixMap surfaces. + if (bitmapData == NULL) + return NULL; + + CGContextFlush(gc); + + // Create an RGB color space. + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + if( colorSpace == NULL ) + return NULL; + + const int bitmapBytesPerRow = ((int) bitmapWidth * BYTES_PER_PIXEL); + const int bitmapByteCount = (bitmapBytesPerRow * (int) bitmapHeight); + + // Make a copy of the bitmap data for the image creation and divorce it + // From the SurfaceImpl lifetime + CFDataRef dataRef = CFDataCreate(kCFAllocatorDefault, bitmapData, bitmapByteCount); + + // Create a data provider. + CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(dataRef); + + CGImageRef image = NULL; + if (dataProvider != NULL) + { + // Create the CGImage. + image = CGImageCreate(bitmapWidth, + bitmapHeight, + BITS_PER_COMPONENT, + BITS_PER_PIXEL, + bitmapBytesPerRow, + colorSpace, + kCGImageAlphaPremultipliedLast, + dataProvider, + NULL, + 0, + kCGRenderingIntentDefault); + } + + // The image retains the color space, so we can release it. + CGColorSpaceRelease(colorSpace); + colorSpace = NULL; + + // Done with the data provider. + CGDataProviderRelease(dataProvider); + dataProvider = NULL; + + // Done with the data provider. + CFRelease(dataRef); + + return image; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Returns the vertical logical device resolution of the main monitor. + */ +int SurfaceImpl::LogPixelsY() +{ + if (verticalDeviceResolution == 0) + { + NSSize deviceResolution = [[[[NSScreen mainScreen] deviceDescription] + objectForKey: NSDeviceResolution] sizeValue]; + verticalDeviceResolution = (int) deviceResolution.height; + } + return verticalDeviceResolution; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Converts the logical font height (in dpi) into a pixel height for the current main screen. + */ +int SurfaceImpl::DeviceHeightFont(int points) +{ + int logPix = LogPixelsY(); + return (points * logPix + logPix / 2) / 72; +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::MoveTo(int x_, int y_) +{ + x = x_; + y = y_; +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::LineTo(int x_, int y_) +{ + CGContextBeginPath( gc ); + + // Because Quartz is based on floating point, lines are drawn with half their colour + // on each side of the line. Integer coordinates specify the INTERSECTION of the pixel + // divison lines. If you specify exact pixel values, you get a line that + // is twice as thick but half as intense. To get pixel aligned rendering, + // we render the "middle" of the pixels by adding 0.5 to the coordinates. + CGContextMoveToPoint( gc, x + 0.5, y + 0.5 ); + CGContextAddLineToPoint( gc, x_ + 0.5, y_ + 0.5 ); + CGContextStrokePath( gc ); + x = x_; + y = y_; +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::Polygon(Scintilla::Point *pts, int npts, ColourDesired fore, + ColourDesired back) +{ + // Allocate memory for the array of points. + CGPoint *points = new CGPoint[npts]; + + for (int i = 0;i < npts;i++) + { + // Quartz floating point issues: plot the MIDDLE of the pixels + points[i].x = pts[i].x + 0.5; + points[i].y = pts[i].y + 0.5; + } + + CGContextBeginPath(gc); + + // Set colours + FillColour(back); + PenColour(fore); + + // Draw the polygon + CGContextAddLines(gc, points, npts); + + // Explicitly close the path, so it is closed for stroking AND filling (implicit close = filling only) + CGContextClosePath( gc ); + CGContextDrawPath( gc, kCGPathFillStroke ); + + // Deallocate memory. + delete points; + points = NULL; +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back) +{ + if (gc) + { + CGContextBeginPath( gc ); + FillColour(back); + PenColour(fore); + + // Quartz integer -> float point conversion fun (see comment in SurfaceImpl::LineTo) + // We subtract 1 from the Width() and Height() so that all our drawing is within the area defined + // by the PRectangle. Otherwise, we draw one pixel too far to the right and bottom. + CGContextAddRect( gc, CGRectMake( rc.left + 0.5, rc.top + 0.5, rc.Width() - 1, rc.Height() - 1 ) ); + CGContextDrawPath( gc, kCGPathFillStroke ); + } +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::FillRectangle(PRectangle rc, ColourDesired back) +{ + if (gc) + { + FillColour(back); + // Snap rectangle boundaries to nearest int + rc.left = lround(rc.left); + rc.right = lround(rc.right); + CGRect rect = PRectangleToCGRect(rc); + CGContextFillRect(gc, rect); + } +} + +//-------------------------------------------------------------------------------------------------- + +void drawImageRefCallback(CGImageRef pattern, CGContextRef gc) +{ + CGContextDrawImage(gc, CGRectMake(0, 0, CGImageGetWidth(pattern), CGImageGetHeight(pattern)), pattern); +} + +//-------------------------------------------------------------------------------------------------- + +void releaseImageRefCallback(CGImageRef pattern) +{ + CGImageRelease(pattern); +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) +{ + SurfaceImpl& patternSurface = static_cast(surfacePattern); + + // For now, assume that copy can only be called on PixMap surfaces. Shows up black. + CGImageRef image = patternSurface.GetImage(); + if (image == NULL) + { + FillRectangle(rc, ColourDesired(0)); + return; + } + + const CGPatternCallbacks drawImageCallbacks = { 0, + reinterpret_cast(drawImageRefCallback), + reinterpret_cast(releaseImageRefCallback) }; + + CGPatternRef pattern = CGPatternCreate(image, + CGRectMake(0, 0, patternSurface.bitmapWidth, patternSurface.bitmapHeight), + CGAffineTransformIdentity, + patternSurface.bitmapWidth, + patternSurface.bitmapHeight, + kCGPatternTilingNoDistortion, + true, + &drawImageCallbacks + ); + if (pattern != NULL) + { + // Create a pattern color space + CGColorSpaceRef colorSpace = CGColorSpaceCreatePattern( NULL ); + if( colorSpace != NULL ) { + + CGContextSaveGState( gc ); + CGContextSetFillColorSpace( gc, colorSpace ); + + // Unlike the documentation, you MUST pass in a "components" parameter: + // For coloured patterns it is the alpha value. + const CGFloat alpha = 1.0; + CGContextSetFillPattern( gc, pattern, &alpha ); + CGContextFillRect( gc, PRectangleToCGRect( rc ) ); + CGContextRestoreGState( gc ); + // Free the color space, the pattern and image + CGColorSpaceRelease( colorSpace ); + } /* colorSpace != NULL */ + colorSpace = NULL; + CGPatternRelease( pattern ); + pattern = NULL; + } /* pattern != NULL */ +} + +void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back) { + // This is only called from the margin marker drawing code for SC_MARK_ROUNDRECT + // The Win32 version does + // ::RoundRect(hdc, rc.left + 1, rc.top, rc.right - 1, rc.bottom, 8, 8 ); + // which is a rectangle with rounded corners each having a radius of 4 pixels. + // It would be almost as good just cutting off the corners with lines at + // 45 degrees as is done on GTK+. + + // Create a rectangle with semicircles at the corners + const int MAX_RADIUS = 4; + int radius = Platform::Minimum( MAX_RADIUS, rc.Height()/2 ); + radius = Platform::Minimum( radius, rc.Width()/2 ); + + // Points go clockwise, starting from just below the top left + // Corners are kept together, so we can easily create arcs to connect them + CGPoint corners[4][3] = + { + { + { rc.left, rc.top + radius }, + { rc.left, rc.top }, + { rc.left + radius, rc.top }, + }, + { + { rc.right - radius - 1, rc.top }, + { rc.right - 1, rc.top }, + { rc.right - 1, rc.top + radius }, + }, + { + { rc.right - 1, rc.bottom - radius - 1 }, + { rc.right - 1, rc.bottom - 1 }, + { rc.right - radius - 1, rc.bottom - 1 }, + }, + { + { rc.left + radius, rc.bottom - 1 }, + { rc.left, rc.bottom - 1 }, + { rc.left, rc.bottom - radius - 1 }, + }, + }; + + // Align the points in the middle of the pixels + for( int i = 0; i < 4*3; ++ i ) + { + CGPoint* c = (CGPoint*) corners; + c[i].x += 0.5; + c[i].y += 0.5; + } + + PenColour( fore ); + FillColour( back ); + + // Move to the last point to begin the path + CGContextBeginPath( gc ); + CGContextMoveToPoint( gc, corners[3][2].x, corners[3][2].y ); + + for ( int i = 0; i < 4; ++ i ) + { + CGContextAddLineToPoint( gc, corners[i][0].x, corners[i][0].y ); + CGContextAddArcToPoint( gc, corners[i][1].x, corners[i][1].y, corners[i][2].x, corners[i][2].y, radius ); + } + + // Close the path to enclose it for stroking and for filling, then draw it + CGContextClosePath( gc ); + CGContextDrawPath( gc, kCGPathFillStroke ); +} + +void Scintilla::SurfaceImpl::AlphaRectangle(PRectangle rc, int /*cornerSize*/, ColourDesired fill, int alphaFill, + ColourDesired /*outline*/, int /*alphaOutline*/, int /*flags*/) +{ + if ( gc ) { + ColourDesired colour( fill.AsLong() ); + + // Snap rectangle boundaries to nearest int + rc.left = lround(rc.left); + rc.right = lround(rc.right); + // Set the Fill color to match + CGContextSetRGBFillColor( gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, colour.GetBlue() / 255.0, alphaFill / 255.0 ); + CGRect rect = PRectangleToCGRect( rc ); + CGContextFillRect( gc, rect ); + } +} + +static CGImageRef ImageCreateFromRGBA(int width, int height, const unsigned char *pixelsImage, bool invert) { + CGImageRef image = 0; + + // Create an RGB color space. + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + if (colorSpace) { + const int bitmapBytesPerRow = ((int) width * 4); + const int bitmapByteCount = (bitmapBytesPerRow * (int) height); + + // Create a data provider. + CGDataProviderRef dataProvider = 0; + unsigned char *pixelsUpsideDown = 0; + if (invert) { + pixelsUpsideDown = new unsigned char[bitmapByteCount]; + + for (int y=0; y(surfaceSource); + CGImageRef image = source.GetImage(); + + CGRect src = PRectangleToCGRect(srcRect); + CGRect dst = PRectangleToCGRect(dstRect); + + /* source from QuickDrawToQuartz2D.pdf on developer.apple.com */ + float w = (float) CGImageGetWidth(image); + float h = (float) CGImageGetHeight(image); + CGRect drawRect = CGRectMake (0, 0, w, h); + if (!CGRectEqualToRect (src, dst)) + { + float sx = CGRectGetWidth(dst) / CGRectGetWidth(src); + float sy = CGRectGetHeight(dst) / CGRectGetHeight(src); + float dx = CGRectGetMinX(dst) - (CGRectGetMinX(src) * sx); + float dy = CGRectGetMinY(dst) - (CGRectGetMinY(src) * sy); + drawRect = CGRectMake (dx, dy, w*sx, h*sy); + } + CGContextSaveGState (gc); + CGContextClipToRect (gc, dst); + CGContextDrawImage (gc, drawRect, image); + CGContextRestoreGState (gc); + CGImageRelease(image); +} + +void SurfaceImpl::Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource) { + // Maybe we have to make the Surface two contexts: + // a bitmap context which we do all the drawing on, and then a "real" context + // which we copy the output to when we call "Synchronize". Ugh! Gross and slow! + + // For now, assume that copy can only be called on PixMap surfaces + SurfaceImpl& source = static_cast(surfaceSource); + + // Get the CGImageRef + CGImageRef image = source.GetImage(); + // If we could not get an image reference, fill the rectangle black + if ( image == NULL ) + { + FillRectangle( rc, ColourDesired( 0 ) ); + return; + } + + // Now draw the image on the surface + + // Some fancy clipping work is required here: draw only inside of rc + CGContextSaveGState( gc ); + CGContextClipToRect( gc, PRectangleToCGRect( rc ) ); + + //Platform::DebugPrintf(stderr, "Copy: CGContextDrawImage: (%d, %d) - (%d X %d)\n", rc.left - from.x, rc.top - from.y, source.bitmapWidth, source.bitmapHeight ); + CGContextDrawImage( gc, CGRectMake( rc.left - from.x, rc.top - from.y, source.bitmapWidth, source.bitmapHeight ), image ); + + // Undo the clipping fun + CGContextRestoreGState( gc ); + + // Done with the image + CGImageRelease( image ); + image = NULL; +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, + ColourDesired fore, ColourDesired back) +{ + FillRectangle(rc, back); + DrawTextTransparent(rc, font_, ybase, s, len, fore); +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, + ColourDesired fore, ColourDesired back) +{ + CGContextSaveGState(gc); + CGContextClipToRect(gc, PRectangleToCGRect(rc)); + DrawTextNoClip(rc, font_, ybase, s, len, fore, back); + CGContextRestoreGState(gc); +} + +//-------------------------------------------------------------------------------------------------- + +CFStringEncoding EncodingFromCharacterSet(bool unicode, int characterSet) +{ + if (unicode) + return kCFStringEncodingUTF8; + + // Unsupported -> Latin1 as reasonably safe + enum { notSupported = kCFStringEncodingISOLatin1}; + + switch (characterSet) + { + case SC_CHARSET_ANSI: + return kCFStringEncodingISOLatin1; + case SC_CHARSET_DEFAULT: + return kCFStringEncodingISOLatin1; + case SC_CHARSET_BALTIC: + return kCFStringEncodingWindowsBalticRim; + case SC_CHARSET_CHINESEBIG5: + return kCFStringEncodingBig5; + case SC_CHARSET_EASTEUROPE: + return kCFStringEncodingWindowsLatin2; + case SC_CHARSET_GB2312: + return kCFStringEncodingGB_18030_2000; + case SC_CHARSET_GREEK: + return kCFStringEncodingWindowsGreek; + case SC_CHARSET_HANGUL: + return kCFStringEncodingEUC_KR; + case SC_CHARSET_MAC: + return kCFStringEncodingMacRoman; + case SC_CHARSET_OEM: + return kCFStringEncodingISOLatin1; + case SC_CHARSET_RUSSIAN: + return kCFStringEncodingKOI8_R; + case SC_CHARSET_CYRILLIC: + return kCFStringEncodingWindowsCyrillic; + case SC_CHARSET_SHIFTJIS: + return kCFStringEncodingShiftJIS; + case SC_CHARSET_SYMBOL: + return kCFStringEncodingMacSymbol; + case SC_CHARSET_TURKISH: + return kCFStringEncodingWindowsLatin5; + case SC_CHARSET_JOHAB: + return kCFStringEncodingWindowsKoreanJohab; + case SC_CHARSET_HEBREW: + return kCFStringEncodingWindowsHebrew; + case SC_CHARSET_ARABIC: + return kCFStringEncodingWindowsArabic; + case SC_CHARSET_VIETNAMESE: + return kCFStringEncodingWindowsVietnamese; + case SC_CHARSET_THAI: + return kCFStringEncodingISOLatinThai; + case SC_CHARSET_8859_15: + return kCFStringEncodingISOLatin1; + default: + return notSupported; + } +} + +void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, + ColourDesired fore) +{ + CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); + ColourDesired colour(fore.AsLong()); + CGColorRef color = CGColorCreateGenericRGB(colour.GetRed()/255.0,colour.GetGreen()/255.0,colour.GetBlue()/255.0,1.0); + + QuartzTextStyle* style = reinterpret_cast(font_.GetID()); + style->setCTStyleColor(color); + + CGColorRelease(color); + + textLayout->setText (reinterpret_cast(s), len, encoding, *reinterpret_cast(font_.GetID())); + textLayout->draw(rc.left, ybase); +} + +static size_t utf8LengthFromLead(unsigned char uch) { + if (uch >= (0x80 + 0x40 + 0x20 + 0x10)) { + return 4; + } else if (uch >= (0x80 + 0x40 + 0x20)) { + return 3; + } else if (uch >= (0x80)) { + return 2; + } else { + return 1; + } +} + +//-------------------------------------------------------------------------------------------------- + +void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) +{ + CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); + textLayout->setText (reinterpret_cast(s), len, encoding, *reinterpret_cast(font_.GetID())); + + CTLineRef mLine = textLayout->getCTLine(); + assert(mLine != NULL); + + if (unicodeMode) { + // Map the widths given for UTF-16 characters back onto the UTF-8 input string + CFIndex fit = textLayout->getStringLength(); + int ui=0; + const unsigned char *us = reinterpret_cast(s); + int i=0; + while (ui 0) + lastPos = positions[i-1]; + while (isetText (reinterpret_cast(s), len, encoding, *reinterpret_cast(font_.GetID())); + + return textLayout->MeasureStringWidth(); + } + return 1; +} + +XYPOSITION SurfaceImpl::WidthChar(Font &font_, char ch) { + char str[2] = { ch, '\0' }; + if (font_.GetID()) + { + CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); + textLayout->setText (reinterpret_cast(str), 1, encoding, *reinterpret_cast(font_.GetID())); + + return textLayout->MeasureStringWidth(); + } + else + return 1; +} + +// This string contains a good range of characters to test for size. +const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890" +"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +XYPOSITION SurfaceImpl::Ascent(Font &font_) { + if (!font_.GetID()) + return 1; + + float ascent = reinterpret_cast( font_.GetID() )->getAscent(); + return ascent + 0.5; + +} + +XYPOSITION SurfaceImpl::Descent(Font &font_) { + if (!font_.GetID()) + return 1; + + float descent = reinterpret_cast( font_.GetID() )->getDescent(); + return descent + 0.5; + +} + +XYPOSITION SurfaceImpl::InternalLeading(Font &) { + return 0; +} + +XYPOSITION SurfaceImpl::ExternalLeading(Font &font_) { + if (!font_.GetID()) + return 1; + + float leading = reinterpret_cast( font_.GetID() )->getLeading(); + return leading + 0.5; + +} + +XYPOSITION SurfaceImpl::Height(Font &font_) { + + int ht = Ascent(font_) + Descent(font_); + return ht; +} + +XYPOSITION SurfaceImpl::AverageCharWidth(Font &font_) { + + if (!font_.GetID()) + return 1; + + const int sizeStringLength = (sizeof( sizeString ) / sizeof( sizeString[0] ) - 1); + int width = WidthText( font_, sizeString, sizeStringLength ); + + return (int) ((width / (float) sizeStringLength) + 0.5); +} + +void SurfaceImpl::SetClip(PRectangle rc) { + CGContextClipToRect( gc, PRectangleToCGRect( rc ) ); +} + +void SurfaceImpl::FlushCachedState() { + CGContextSynchronize( gc ); +} + +void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) { + unicodeMode = unicodeMode_; +} + +void SurfaceImpl::SetDBCSMode(int codePage_) { + if (codePage_ && (codePage_ != SC_CP_UTF8)) + codePage = codePage_; +} + +Surface *Surface::Allocate(int) +{ + return new SurfaceImpl(); +} + +//----------------- Window ------------------------------------------------------------------------- + +// Cocoa uses different types for windows and views, so a Window may +// be either an NSWindow or NSView and the code will check the type +// before performing an action. + +Window::~Window() +{ +} + +//-------------------------------------------------------------------------------------------------- + +void Window::Destroy() +{ + if (wid) + { + id idWin = reinterpret_cast(wid); + if ([idWin isKindOfClass: [NSWindow class]]) + { + NSWindow* win = reinterpret_cast(idWin); + [win release]; + } + } + wid = 0; +} + +//-------------------------------------------------------------------------------------------------- + +bool Window::HasFocus() +{ + NSView* container = reinterpret_cast(wid); + return [[container window] firstResponder] == container; +} + +//-------------------------------------------------------------------------------------------------- + +static int ScreenMax(NSWindow* win) +{ + NSScreen* screen = [win screen]; + NSRect frame = [screen frame]; + return frame.origin.y + frame.size.height; +} + +PRectangle Window::GetPosition() +{ + if (wid) + { + NSRect rect; + id idWin = reinterpret_cast(wid); + NSWindow* win; + if ([idWin isKindOfClass: [NSView class]]) + { + // NSView + NSView* view = reinterpret_cast(idWin); + win = [view window]; + rect = [view bounds]; + rect = [view convertRectToBase: rect]; + rect.origin = [win convertBaseToScreen:rect.origin]; + } + else + { + // NSWindow + win = reinterpret_cast(idWin); + rect = [win frame]; + } + int screenHeight = ScreenMax(win); + // Invert screen positions to match Scintilla + return PRectangle( + NSMinX(rect), screenHeight - NSMaxY(rect), + NSMaxX(rect), screenHeight - NSMinY(rect)); + } + else + { + return PRectangle(0, 0, 1, 1); + } +} + +//-------------------------------------------------------------------------------------------------- + +void Window::SetPosition(PRectangle rc) +{ + if (wid) + { + id idWin = reinterpret_cast(wid); + if ([idWin isKindOfClass: [NSView class]]) + { + // NSView + // Moves this view inside the parent view + NSRect nsrc = NSMakeRect(rc.left, rc.bottom, rc.Width(), rc.Height()); + NSView* view = reinterpret_cast(idWin); + nsrc.origin = [[view window] convertScreenToBase:nsrc.origin]; + [view setFrame: nsrc]; + } + else + { + // NSWindow + NSWindow* win = reinterpret_cast(idWin); + int screenHeight = ScreenMax(win); + NSRect nsrc = NSMakeRect(rc.left, screenHeight - rc.bottom, + rc.Width(), rc.Height()); + [win setFrame: nsrc display:YES]; + } + } +} + +//-------------------------------------------------------------------------------------------------- + +void Window::SetPositionRelative(PRectangle rc, Window window) +{ + PRectangle rcOther = window.GetPosition(); + rc.left += rcOther.left; + rc.right += rcOther.left; + rc.top += rcOther.top; + rc.bottom += rcOther.top; + SetPosition(rc); +} + +//-------------------------------------------------------------------------------------------------- + +PRectangle Window::GetClientPosition() +{ + // This means, in MacOS X terms, get the "frame bounds". Call GetPosition, just like on Win32. + return GetPosition(); +} + +//-------------------------------------------------------------------------------------------------- + +void Window::Show(bool show) +{ + if (wid) + { + id idWin = reinterpret_cast(wid); + if ([idWin isKindOfClass: [NSWindow class]]) + { + NSWindow* win = reinterpret_cast(idWin); + if (show) + { + [win orderFront:nil]; + } + else + { + [win orderOut:nil]; + } + } + } +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Invalidates the entire window or view so it is completely redrawn. + */ +void Window::InvalidateAll() +{ + if (wid) + { + id idWin = reinterpret_cast(wid); + NSView* container; + if ([idWin isKindOfClass: [NSView class]]) + { + container = reinterpret_cast(idWin); + } + else + { + // NSWindow + NSWindow* win = reinterpret_cast(idWin); + container = reinterpret_cast([win contentView]); + container.needsDisplay = YES; + } + container.needsDisplay = YES; + } +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Invalidates part of the window or view so only this part redrawn. + */ +void Window::InvalidateRectangle(PRectangle rc) +{ + if (wid) + { + id idWin = reinterpret_cast(wid); + NSView* container; + if ([idWin isKindOfClass: [NSView class]]) + { + container = reinterpret_cast(idWin); + } + else + { + // NSWindow + NSWindow* win = reinterpret_cast(idWin); + container = reinterpret_cast([win contentView]); + } + [container setNeedsDisplayInRect: PRectangleToNSRect(rc)]; + } +} + +//-------------------------------------------------------------------------------------------------- + +void Window::SetFont(Font&) +{ + // Implemented on list subclass on Cocoa. +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Converts the Scintilla cursor enum into an NSCursor and stores it in the associated NSView, + * which then will take care to set up a new mouse tracking rectangle. + */ +void Window::SetCursor(Cursor curs) +{ + if (wid) + { + id idWin = reinterpret_cast(wid); + if ([idWin isMemberOfClass: [InnerView class]]) + { + InnerView* container = reinterpret_cast(idWin); + [container setCursor: curs]; + } + } +} + +//-------------------------------------------------------------------------------------------------- + +void Window::SetTitle(const char* s) +{ + if (wid) + { + id idWin = reinterpret_cast(wid); + if ([idWin isKindOfClass: [NSWindow class]]) + { + NSWindow* win = reinterpret_cast(idWin); + NSString* sTitle = [NSString stringWithUTF8String:s]; + [win setTitle:sTitle]; + } + } +} + +//-------------------------------------------------------------------------------------------------- + +PRectangle Window::GetMonitorRect(Point) +{ + if (wid) + { + id idWin = reinterpret_cast(wid); + if ([idWin isKindOfClass: [NSWindow class]]) + { + NSWindow* win = reinterpret_cast(idWin); + NSScreen* screen = [win screen]; + NSRect rect = [screen frame]; + int screenHeight = rect.origin.y + rect.size.height; + // Invert screen positions to match Scintilla + return PRectangle( + NSMinX(rect), screenHeight - NSMaxY(rect), + NSMaxX(rect), screenHeight - NSMinY(rect)); + } + } + return PRectangle(); +} + +//----------------- ImageFromXPM ------------------------------------------------------------------- + +// Convert an XPM image into an NSImage for use with Cocoa + +static NSImage* ImageFromXPM(XPM* pxpm) +{ + NSImage* img = nil; + if (pxpm) + { + const int width = pxpm->GetWidth(); + const int height = pxpm->GetHeight(); + PRectangle rcxpm(0, 0, width, height); + Surface* surfaceXPM = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); + if (surfaceXPM) + { + surfaceXPM->InitPixMap(width, height, NULL, NULL); + SurfaceImpl* surfaceIXPM = static_cast(surfaceXPM); + CGContextClearRect(surfaceIXPM->GetContext(), CGRectMake(0, 0, width, height)); + pxpm->Draw(surfaceXPM, rcxpm); + img = [[[NSImage alloc] initWithSize:NSZeroSize] autorelease]; + CGImageRef imageRef = surfaceIXPM->GetImage(); + NSBitmapImageRep *bitmapRep = [[NSBitmapImageRep alloc] initWithCGImage: imageRef]; + [img addRepresentation: bitmapRep]; + [bitmapRep release]; + CGImageRelease(imageRef); + delete surfaceXPM; + } + } + return img; +} + +//----------------- ListBox ------------------------------------------------------------------------ + +ListBox::ListBox() +{ +} + +//-------------------------------------------------------------------------------------------------- + +ListBox::~ListBox() +{ +} + +//-------------------------------------------------------------------------------------------------- + +struct RowData +{ + int type; + std::string text; + RowData(int type_, const char* text_) : + type(type_), text(text_) + { + } +}; + +class LinesData +{ + std::vector lines; +public: + LinesData() + { + } + ~LinesData() + { + } + int Length() const + { + return static_cast(lines.size()); + } + void Clear() + { + lines.clear(); + } + void Add(int /* index */, int type, char* str) + { + lines.push_back(RowData(type, str)); + } + int GetType(size_t index) const + { + if (index < lines.size()) + { + return lines[index].type; + } + else + { + return 0; + } + } + const char* GetString(size_t index) const + { + if (index < lines.size()) + { + return lines[index].text.c_str(); + } + else + { + return 0; + } + } +}; + +class ListBoxImpl; + +@interface AutoCompletionDataSource : +NSObject +#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 + +#endif +{ + ListBoxImpl* box; +} + +@end + +//----------------- ListBoxImpl -------------------------------------------------------------------- + +// Map from icon type to an NSImage* +typedef std::map ImageMap; + +class ListBoxImpl : public ListBox +{ +private: + ControlRef lb; + ImageMap images; + int lineHeight; + bool unicodeMode; + int desiredVisibleRows; + unsigned int maxItemWidth; + unsigned int aveCharWidth; + unsigned int maxIconWidth; + Font font; + int maxWidth; + + NSTableView* table; + NSScrollView* scroller; + NSTableColumn* colIcon; + NSTableColumn* colText; + AutoCompletionDataSource* ds; + + LinesData ld; + CallBackAction doubleClickAction; + void* doubleClickActionData; + +public: + ListBoxImpl() : lb(NULL), lineHeight(10), unicodeMode(false), + desiredVisibleRows(5), maxItemWidth(0), aveCharWidth(8), maxIconWidth(0), + doubleClickAction(NULL), doubleClickActionData(NULL) + { + } + ~ListBoxImpl() {} + + // ListBox methods + void SetFont(Font& font); + void Create(Window& parent, int ctrlID, Scintilla::Point pt, int lineHeight_, bool unicodeMode_, int technology_); + void SetAverageCharWidth(int width); + void SetVisibleRows(int rows); + int GetVisibleRows() const; + PRectangle GetDesiredRect(); + int CaretFromEdge(); + void Clear(); + void Append(char* s, int type = -1); + int Length(); + void Select(int n); + int GetSelection(); + int Find(const char* prefix); + void GetValue(int n, char* value, int len); + void RegisterImage(int type, const char* xpm_data); + void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage); + void ClearRegisteredImages(); + void SetDoubleClickAction(CallBackAction action, void* data) + { + doubleClickAction = action; + doubleClickActionData = data; + } + void SetList(const char* list, char separator, char typesep); + + // For access from AutoCompletionDataSource + int Rows(); + NSImage* ImageForRow(NSInteger row); + NSString* TextForRow(NSInteger row); + void DoubleClick(); +}; + +@implementation AutoCompletionDataSource + +- (void)setBox: (ListBoxImpl*)box_ +{ + box = box_; +} + +- (void) doubleClick: (id) sender +{ +#pragma unused(sender) + if (box) + { + box->DoubleClick(); + } +} + +- (id)tableView: (NSTableView*)aTableView objectValueForTableColumn: (NSTableColumn*)aTableColumn row: (NSInteger)rowIndex +{ +#pragma unused(aTableView) + if (!box) + return nil; + if ([(NSString*)[aTableColumn identifier] isEqualToString: @"icon"]) + { + return box->ImageForRow(rowIndex); + } + else { + return box->TextForRow(rowIndex); + } +} + +- (void)tableView: (NSTableView*)aTableView setObjectValue: anObject forTableColumn: (NSTableColumn*)aTableColumn row: (NSInteger)rowIndex +{ +#pragma unused(aTableView) +#pragma unused(anObject) +#pragma unused(aTableColumn) +#pragma unused(rowIndex) +} + +- (NSInteger)numberOfRowsInTableView: (NSTableView*)aTableView +{ +#pragma unused(aTableView) + if (!box) + return 0; + return box->Rows(); +} + +@end + +ListBox* ListBox::Allocate() +{ + ListBoxImpl* lb = new ListBoxImpl(); + return lb; +} + +void ListBoxImpl::Create(Window& /*parent*/, int /*ctrlID*/, Scintilla::Point pt, + int lineHeight_, bool unicodeMode_, int) +{ + lineHeight = lineHeight_; + unicodeMode = unicodeMode_; + maxWidth = 2000; + + NSRect lbRect = NSMakeRect(pt.x,pt.y, 120, lineHeight * desiredVisibleRows); + NSWindow* winLB = [[NSWindow alloc] initWithContentRect: lbRect + styleMask: NSBorderlessWindowMask + backing: NSBackingStoreBuffered + defer: NO]; + [winLB setLevel:NSFloatingWindowLevel]; + [winLB setHasShadow:YES]; + scroller = [NSScrollView alloc]; + NSRect scRect = NSMakeRect(0, 0, lbRect.size.width, lbRect.size.height); + [scroller initWithFrame: scRect]; + [scroller setHasVerticalScroller:YES]; + table = [[NSTableView alloc] initWithFrame: scRect]; + [table setHeaderView:nil]; + [scroller setDocumentView: table]; + colIcon = [[NSTableColumn alloc] initWithIdentifier:@"icon"]; + [colIcon setWidth: 20]; + [colIcon setEditable:NO]; + [colIcon setHidden:YES]; + NSImageCell* imCell = [[[NSImageCell alloc] init] autorelease]; + [colIcon setDataCell:imCell]; + [table addTableColumn:colIcon]; + colText = [[NSTableColumn alloc] initWithIdentifier:@"name"]; + [colText setResizingMask:NSTableColumnAutoresizingMask]; + [colText setEditable:NO]; + [table addTableColumn:colText]; + ds = [[AutoCompletionDataSource alloc] init]; + [ds setBox:this]; + [table setDataSource: ds]; // Weak reference + [scroller setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; + [[winLB contentView] addSubview: scroller]; + + [table setTarget:ds]; + [table setDoubleAction:@selector(doubleClick:)]; + wid = winLB; +} + +void ListBoxImpl::SetFont(Font& font_) +{ + font.SetID(font_.GetID()); + // NSCell setFont takes an NSFont* rather than a CTFontRef but they + // are the same thing toll-free bridged. + QuartzTextStyle* style = reinterpret_cast(font_.GetID()); + NSFont *pfont = (NSFont *)style->getFontRef(); + [[colText dataCell] setFont: pfont]; + CGFloat itemHeight = lround([pfont ascender] - [pfont descender]); + [table setRowHeight:itemHeight]; +} + +void ListBoxImpl::SetAverageCharWidth(int width) +{ + aveCharWidth = width; +} + +void ListBoxImpl::SetVisibleRows(int rows) +{ + desiredVisibleRows = rows; +} + +int ListBoxImpl::GetVisibleRows() const +{ + return desiredVisibleRows; +} + +PRectangle ListBoxImpl::GetDesiredRect() +{ + PRectangle rcDesired; + rcDesired = GetPosition(); + + // There appears to be an extra pixel above and below the row contents + int itemHeight = [table rowHeight] + 2; + + int rows = Length(); + if ((rows == 0) || (rows > desiredVisibleRows)) + rows = desiredVisibleRows; + + rcDesired.bottom = rcDesired.top + itemHeight * rows; + rcDesired.right = rcDesired.left + maxItemWidth + aveCharWidth; + + if (Length() > rows) + { + [scroller setHasVerticalScroller:YES]; + rcDesired.right += [NSScroller scrollerWidth]; + } + else + { + [scroller setHasVerticalScroller:NO]; + } + rcDesired.right += maxIconWidth; + rcDesired.right += 6; + + return rcDesired; +} + +int ListBoxImpl::CaretFromEdge() +{ + if ([colIcon isHidden]) + return 3; + else + return 6 + [colIcon width]; +} + +void ListBoxImpl::Clear() +{ + maxItemWidth = 0; + maxIconWidth = 0; + ld.Clear(); +} + +void ListBoxImpl::Append(char* s, int type) +{ + int count = Length(); + ld.Add(count, type, s); + + Scintilla::SurfaceImpl surface; + unsigned int width = surface.WidthText(font, s, static_cast(strlen(s))); + if (width > maxItemWidth) + { + maxItemWidth = width; + [colText setWidth: maxItemWidth]; + } + ImageMap::iterator it = images.find(type); + if (it != images.end()) + { + NSImage* img = it->second; + if (img) + { + unsigned int widthIcon = img.size.width; + if (widthIcon > maxIconWidth) + { + [colIcon setHidden: NO]; + maxIconWidth = widthIcon; + [colIcon setWidth: maxIconWidth]; + } + } + } +} + +void ListBoxImpl::SetList(const char* list, char separator, char typesep) +{ + Clear(); + size_t count = strlen(list) + 1; + char* words = new char[count]; + if (words) + { + memcpy(words, list, count); + char* startword = words; + char* numword = NULL; + int i = 0; + for (; words[i]; i++) + { + if (words[i] == separator) + { + words[i] = '\0'; + if (numword) + *numword = '\0'; + Append(startword, numword?atoi(numword + 1):-1); + startword = words + i + 1; + numword = NULL; + } + else if (words[i] == typesep) + { + numword = words + i; + } + } + if (startword) + { + if (numword) + *numword = '\0'; + Append(startword, numword?atoi(numword + 1):-1); + } + delete []words; + } + [table reloadData]; +} + +int ListBoxImpl::Length() +{ + return ld.Length(); +} + +void ListBoxImpl::Select(int n) +{ + [table selectRowIndexes:[NSIndexSet indexSetWithIndex:n] byExtendingSelection:NO]; + [table scrollRowToVisible:n]; +} + +int ListBoxImpl::GetSelection() +{ + return static_cast([table selectedRow]); +} + +int ListBoxImpl::Find(const char* prefix) +{ + int count = Length(); + for (int i = 0; i < count; i++) + { + const char* s = ld.GetString(i); + if (s && (s[0] != '\0') && (0 == strncmp(prefix, s, strlen(prefix)))) + { + return i; + } + } + return - 1; +} + +void ListBoxImpl::GetValue(int n, char* value, int len) +{ + const char* textString = ld.GetString(n); + if (textString == NULL) + { + value[0] = '\0'; + return; + } + strncpy(value, textString, len); + value[len - 1] = '\0'; +} + +void ListBoxImpl::RegisterImage(int type, const char* xpm_data) +{ + XPM xpm(xpm_data); + NSImage* img = ImageFromXPM(&xpm); + [img retain]; + ImageMap::iterator it=images.find(type); + if (it == images.end()) + { + images[type] = img; + } + else + { + [it->second release]; + it->second = img; + } +} + +void ListBoxImpl::RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) { + CGImageRef imageRef = ImageCreateFromRGBA(width, height, pixelsImage, false); + NSSize sz = {width, height}; + NSImage *img = [[[NSImage alloc] initWithSize: sz] autorelease]; + NSBitmapImageRep *bitmapRep = [[NSBitmapImageRep alloc] initWithCGImage: imageRef]; + [img addRepresentation: bitmapRep]; + [bitmapRep release]; + CGImageRelease(imageRef); + [img retain]; + ImageMap::iterator it=images.find(type); + if (it == images.end()) + { + images[type] = img; + } + else + { + [it->second release]; + it->second = img; + } +} + +void ListBoxImpl::ClearRegisteredImages() +{ + for (ImageMap::iterator it=images.begin(); + it != images.end(); ++it) + { + [it->second release]; + it->second = nil; + } + images.clear(); +} + +int ListBoxImpl::Rows() +{ + return ld.Length(); +} + +NSImage* ListBoxImpl::ImageForRow(NSInteger row) +{ + ImageMap::iterator it = images.find(ld.GetType(row)); + if (it != images.end()) + { + NSImage* img = it->second; + return img; + } + else + { + return nil; + } +} + +NSString* ListBoxImpl::TextForRow(NSInteger row) +{ + const char* textString = ld.GetString(row); + NSString* sTitle; + if (unicodeMode) + sTitle = [NSString stringWithUTF8String:textString]; + else + sTitle = [NSString stringWithCString:textString encoding:NSWindowsCP1252StringEncoding]; + return sTitle; +} + +void ListBoxImpl::DoubleClick() +{ + if (doubleClickAction) + { + doubleClickAction(doubleClickActionData); + } +} + +//----------------- ScintillaContextMenu ----------------------------------------------------------- + +@implementation ScintillaContextMenu : NSMenu + +// This NSMenu subclass serves also as target for menu commands and forwards them as +// notfication messages to the front end. + +- (void) handleCommand: (NSMenuItem*) sender +{ + owner->HandleCommand([sender tag]); +} + +//-------------------------------------------------------------------------------------------------- + +- (void) setOwner: (Scintilla::ScintillaCocoa*) newOwner +{ + owner = newOwner; +} + +@end + +//----------------- Menu --------------------------------------------------------------------------- + +Menu::Menu() + : mid(0) +{ +} + +//-------------------------------------------------------------------------------------------------- + +void Menu::CreatePopUp() +{ + Destroy(); + mid = [[ScintillaContextMenu alloc] initWithTitle: @""]; +} + +//-------------------------------------------------------------------------------------------------- + +void Menu::Destroy() +{ + ScintillaContextMenu* menu = reinterpret_cast(mid); + [menu release]; + mid = NULL; +} + +//-------------------------------------------------------------------------------------------------- + +void Menu::Show(Point, Window &) +{ + // Cocoa menus are handled a bit differently. We only create the menu. The framework + // takes care to show it properly. +} + +//----------------- ElapsedTime -------------------------------------------------------------------- + +// ElapsedTime is used for precise performance measurements during development +// and not for anything a user sees. + +ElapsedTime::ElapsedTime() { + struct timeval curTime; + gettimeofday( &curTime, NULL ); + + bigBit = curTime.tv_sec; + littleBit = curTime.tv_usec; +} + +double ElapsedTime::Duration(bool reset) { + struct timeval curTime; + gettimeofday( &curTime, NULL ); + long endBigBit = curTime.tv_sec; + long endLittleBit = curTime.tv_usec; + double result = 1000000.0 * (endBigBit - bigBit); + result += endLittleBit - littleBit; + result /= 1000000.0; + if (reset) { + bigBit = endBigBit; + littleBit = endLittleBit; + } + return result; +} + +//----------------- Platform ----------------------------------------------------------------------- + +ColourDesired Platform::Chrome() +{ + return ColourDesired(0xE0, 0xE0, 0xE0); +} + +//-------------------------------------------------------------------------------------------------- + +ColourDesired Platform::ChromeHighlight() +{ + return ColourDesired(0xFF, 0xFF, 0xFF); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Returns the currently set system font for the user. + */ +const char *Platform::DefaultFont() +{ + NSString* name = [[NSUserDefaults standardUserDefaults] stringForKey: @"NSFixedPitchFont"]; + return [name UTF8String]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Returns the currently set system font size for the user. + */ +int Platform::DefaultFontSize() +{ + return static_cast([[NSUserDefaults standardUserDefaults] + integerForKey: @"NSFixedPitchFontSize"]); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Returns the time span in which two consequtive mouse clicks must occur to be considered as + * double click. + * + * @return + */ +unsigned int Platform::DoubleClickTime() +{ + float threshold = [[NSUserDefaults standardUserDefaults] floatForKey: + @"com.apple.mouse.doubleClickThreshold"]; + if (threshold == 0) + threshold = 0.5; + return static_cast(threshold / kEventDurationMillisecond); +} + +//-------------------------------------------------------------------------------------------------- + +bool Platform::MouseButtonBounce() +{ + return false; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Helper method for the backend to reach through to the scintiall window. + */ +long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam) +{ + return scintilla_send_message(w, msg, wParam, lParam); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Helper method for the backend to reach through to the scintiall window. + */ +long Platform::SendScintillaPointer(WindowID w, unsigned int msg, unsigned long wParam, void *lParam) +{ + return scintilla_send_message(w, msg, wParam, (long) lParam); +} + +//-------------------------------------------------------------------------------------------------- + +bool Platform::IsDBCSLeadByte(int codePage, char ch) +{ + // Byte ranges found in Wikipedia articles with relevant search strings in each case + unsigned char uch = static_cast(ch); + switch (codePage) + { + case 932: + // Shift_jis + return ((uch >= 0x81) && (uch <= 0x9F)) || + ((uch >= 0xE0) && (uch <= 0xFC)); + // Lead bytes F0 to FC may be a Microsoft addition. + case 936: + // GBK + return (uch >= 0x81) && (uch <= 0xFE); + case 949: + // Korean Wansung KS C-5601-1987 + return (uch >= 0x81) && (uch <= 0xFE); + case 950: + // Big5 + return (uch >= 0x81) && (uch <= 0xFE); + case 1361: + // Korean Johab KS C-5601-1992 + return + ((uch >= 0x84) && (uch <= 0xD3)) || + ((uch >= 0xD8) && (uch <= 0xDE)) || + ((uch >= 0xE0) && (uch <= 0xF9)); + } + return false; +} + +//-------------------------------------------------------------------------------------------------- + +int Platform::DBCSCharLength(int /* codePage */, const char* /* s */) +{ + // DBCS no longer uses this. + return 1; +} + +//-------------------------------------------------------------------------------------------------- + +int Platform::DBCSCharMaxLength() +{ + return 2; +} + +//-------------------------------------------------------------------------------------------------- + +int Platform::Minimum(int a, int b) +{ + return (a < b) ? a : b; +} + +//-------------------------------------------------------------------------------------------------- + +int Platform::Maximum(int a, int b) { + return (a > b) ? a : b; +} + +//-------------------------------------------------------------------------------------------------- + +//#define TRACE +#ifdef TRACE + +void Platform::DebugDisplay(const char *s) +{ + fprintf( stderr, s ); +} + +//-------------------------------------------------------------------------------------------------- + +void Platform::DebugPrintf(const char *format, ...) +{ + const int BUF_SIZE = 2000; + char buffer[BUF_SIZE]; + + va_list pArguments; + va_start(pArguments, format); + vsnprintf(buffer, BUF_SIZE, format, pArguments); + va_end(pArguments); + Platform::DebugDisplay(buffer); +} + +#else + +void Platform::DebugDisplay(const char *) {} + +void Platform::DebugPrintf(const char *, ...) {} + +#endif + +//-------------------------------------------------------------------------------------------------- + +static bool assertionPopUps = true; + +bool Platform::ShowAssertionPopUps(bool assertionPopUps_) +{ + bool ret = assertionPopUps; + assertionPopUps = assertionPopUps_; + return ret; +} + +//-------------------------------------------------------------------------------------------------- + +void Platform::Assert(const char *c, const char *file, int line) +{ + char buffer[2000]; + sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line); + strcat(buffer, "\r\n"); + Platform::DebugDisplay(buffer); +#ifdef DEBUG + // Jump into debugger in assert on Mac (CL269835) + ::Debugger(); +#endif +} + +//-------------------------------------------------------------------------------------------------- + +int Platform::Clamp(int val, int minVal, int maxVal) +{ + if (val > maxVal) + val = maxVal; + if (val < minVal) + val = minVal; + return val; +} + +//----------------- DynamicLibrary ----------------------------------------------------------------- + +/** + * Implements the platform specific part of library loading. + * + * @param modulePath The path to the module to load. + * @return A library instance or NULL if the module could not be found or another problem occured. + */ +DynamicLibrary* DynamicLibrary::Load(const char* /* modulePath */) +{ + // Not implemented. + return NULL; +} + +//-------------------------------------------------------------------------------------------------- + diff --git a/scintilla/cocoa/QuartzTextLayout.h b/ThirdLibs/scintilla/cocoa/QuartzTextLayout.h similarity index 95% rename from scintilla/cocoa/QuartzTextLayout.h rename to ThirdLibs/scintilla/cocoa/QuartzTextLayout.h index 9f2681ec..c789ed10 100644 --- a/scintilla/cocoa/QuartzTextLayout.h +++ b/ThirdLibs/scintilla/cocoa/QuartzTextLayout.h @@ -1,111 +1,111 @@ -/* - * QuartzTextLayout.h - * - * Original Code by Evan Jones on Wed Oct 02 2002. - * Contributors: - * Shane Caraveo, ActiveState - * Bernd Paradies, Adobe - * - */ - -#ifndef _QUARTZ_TEXT_LAYOUT_H -#define _QUARTZ_TEXT_LAYOUT_H - -#include - -#include "QuartzTextStyle.h" - - -class QuartzTextLayout -{ -public: - /** Create a text layout for drawing on the specified context. */ - QuartzTextLayout( CGContextRef context ) - { - mString = NULL; - mLine = NULL; - stringLength = 0; - setContext(context); - } - - ~QuartzTextLayout() - { - if ( mString != NULL ) - { - CFRelease(mString); - mString = NULL; - } - if ( mLine != NULL ) - { - CFRelease(mLine); - mLine = NULL; - } - } - - inline void setText( const UInt8* buffer, size_t byteLength, CFStringEncoding encoding, const QuartzTextStyle& r ) - { - CFStringRef str = CFStringCreateWithBytes( NULL, buffer, byteLength, encoding, false ); - if (!str) - return; - - stringLength = CFStringGetLength(str); - - CFMutableDictionaryRef stringAttribs = r.getCTStyle(); - - if (mString != NULL) - CFRelease(mString); - mString = ::CFAttributedStringCreate(NULL, str, stringAttribs); - - if (mLine != NULL) - CFRelease(mLine); - mLine = ::CTLineCreateWithAttributedString(mString); - - CFRelease( str ); - } - - /** Draw the text layout into the current CGContext at the specified position. - * @param x The x axis position to draw the baseline in the current CGContext. - * @param y The y axis position to draw the baseline in the current CGContext. */ - void draw( float x, float y ) - { - if (mLine == NULL) - return; - - ::CGContextSetTextMatrix(gc, CGAffineTransformMakeScale(1.0, -1.0)); - - // Set the text drawing position. - ::CGContextSetTextPosition(gc, x, y); - - // And finally, draw! - ::CTLineDraw(mLine, gc); - } - - float MeasureStringWidth() - { - if (mLine == NULL) - return 0.0f; - - return ::CTLineGetTypographicBounds(mLine, NULL, NULL, NULL); - } - - CTLineRef getCTLine() { - return mLine; - } - - CFIndex getStringLength() { - return stringLength; - } - - inline void setContext (CGContextRef context) - { - gc = context; - } - -private: - CGContextRef gc; - CFAttributedStringRef mString; - CTLineRef mLine; - CFIndex stringLength; -}; - -#endif +/* + * QuartzTextLayout.h + * + * Original Code by Evan Jones on Wed Oct 02 2002. + * Contributors: + * Shane Caraveo, ActiveState + * Bernd Paradies, Adobe + * + */ + +#ifndef _QUARTZ_TEXT_LAYOUT_H +#define _QUARTZ_TEXT_LAYOUT_H + +#include + +#include "QuartzTextStyle.h" + + +class QuartzTextLayout +{ +public: + /** Create a text layout for drawing on the specified context. */ + QuartzTextLayout( CGContextRef context ) + { + mString = NULL; + mLine = NULL; + stringLength = 0; + setContext(context); + } + + ~QuartzTextLayout() + { + if ( mString != NULL ) + { + CFRelease(mString); + mString = NULL; + } + if ( mLine != NULL ) + { + CFRelease(mLine); + mLine = NULL; + } + } + + inline void setText( const UInt8* buffer, size_t byteLength, CFStringEncoding encoding, const QuartzTextStyle& r ) + { + CFStringRef str = CFStringCreateWithBytes( NULL, buffer, byteLength, encoding, false ); + if (!str) + return; + + stringLength = CFStringGetLength(str); + + CFMutableDictionaryRef stringAttribs = r.getCTStyle(); + + if (mString != NULL) + CFRelease(mString); + mString = ::CFAttributedStringCreate(NULL, str, stringAttribs); + + if (mLine != NULL) + CFRelease(mLine); + mLine = ::CTLineCreateWithAttributedString(mString); + + CFRelease( str ); + } + + /** Draw the text layout into the current CGContext at the specified position. + * @param x The x axis position to draw the baseline in the current CGContext. + * @param y The y axis position to draw the baseline in the current CGContext. */ + void draw( float x, float y ) + { + if (mLine == NULL) + return; + + ::CGContextSetTextMatrix(gc, CGAffineTransformMakeScale(1.0, -1.0)); + + // Set the text drawing position. + ::CGContextSetTextPosition(gc, x, y); + + // And finally, draw! + ::CTLineDraw(mLine, gc); + } + + float MeasureStringWidth() + { + if (mLine == NULL) + return 0.0f; + + return ::CTLineGetTypographicBounds(mLine, NULL, NULL, NULL); + } + + CTLineRef getCTLine() { + return mLine; + } + + CFIndex getStringLength() { + return stringLength; + } + + inline void setContext (CGContextRef context) + { + gc = context; + } + +private: + CGContextRef gc; + CFAttributedStringRef mString; + CTLineRef mLine; + CFIndex stringLength; +}; + +#endif diff --git a/scintilla/cocoa/QuartzTextStyle.h b/ThirdLibs/scintilla/cocoa/QuartzTextStyle.h similarity index 94% rename from scintilla/cocoa/QuartzTextStyle.h rename to ThirdLibs/scintilla/cocoa/QuartzTextStyle.h index 3a17f22d..51d03cf9 100644 --- a/scintilla/cocoa/QuartzTextStyle.h +++ b/ThirdLibs/scintilla/cocoa/QuartzTextStyle.h @@ -1,98 +1,98 @@ -/* - * QuartzTextStyle.h - * - * Created by Evan Jones on Wed Oct 02 2002. - * - */ - -#ifndef _QUARTZ_TEXT_STYLE_H -#define _QUARTZ_TEXT_STYLE_H - -#include "QuartzTextStyleAttribute.h" - -class QuartzTextStyle -{ -public: - QuartzTextStyle() - { - fontRef = NULL; - styleDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - characterSet = 0; - } - - ~QuartzTextStyle() - { - if (styleDict != NULL) - { - CFRelease(styleDict); - styleDict = NULL; - } - - if (fontRef) - { - CFRelease(fontRef); - fontRef = NULL; - } - } - - CFMutableDictionaryRef getCTStyle() const - { - return styleDict; - } - - void setCTStyleColor(CGColor* inColor ) - { - CFDictionarySetValue(styleDict, kCTForegroundColorAttributeName, inColor); - } - - float getAscent() const - { - return ::CTFontGetAscent(fontRef); - } - - float getDescent() const - { - return ::CTFontGetDescent(fontRef); - } - - float getLeading() const - { - return ::CTFontGetLeading(fontRef); - } - - void setFontRef(CTFontRef inRef, int characterSet_) - { - fontRef = inRef; - characterSet = characterSet_; - - if (styleDict != NULL) - CFRelease(styleDict); - - styleDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - CFDictionaryAddValue(styleDict, kCTFontAttributeName, fontRef); - } - - CTFontRef getFontRef() - { - return fontRef; - } - - int getCharacterSet() - { - return characterSet; - } - -private: - CFMutableDictionaryRef styleDict; - CTFontRef fontRef; - int characterSet; -}; - -#endif - +/* + * QuartzTextStyle.h + * + * Created by Evan Jones on Wed Oct 02 2002. + * + */ + +#ifndef _QUARTZ_TEXT_STYLE_H +#define _QUARTZ_TEXT_STYLE_H + +#include "QuartzTextStyleAttribute.h" + +class QuartzTextStyle +{ +public: + QuartzTextStyle() + { + fontRef = NULL; + styleDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + characterSet = 0; + } + + ~QuartzTextStyle() + { + if (styleDict != NULL) + { + CFRelease(styleDict); + styleDict = NULL; + } + + if (fontRef) + { + CFRelease(fontRef); + fontRef = NULL; + } + } + + CFMutableDictionaryRef getCTStyle() const + { + return styleDict; + } + + void setCTStyleColor(CGColor* inColor ) + { + CFDictionarySetValue(styleDict, kCTForegroundColorAttributeName, inColor); + } + + float getAscent() const + { + return ::CTFontGetAscent(fontRef); + } + + float getDescent() const + { + return ::CTFontGetDescent(fontRef); + } + + float getLeading() const + { + return ::CTFontGetLeading(fontRef); + } + + void setFontRef(CTFontRef inRef, int characterSet_) + { + fontRef = inRef; + characterSet = characterSet_; + + if (styleDict != NULL) + CFRelease(styleDict); + + styleDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + CFDictionaryAddValue(styleDict, kCTFontAttributeName, fontRef); + } + + CTFontRef getFontRef() + { + return fontRef; + } + + int getCharacterSet() + { + return characterSet; + } + +private: + CFMutableDictionaryRef styleDict; + CTFontRef fontRef; + int characterSet; +}; + +#endif + diff --git a/scintilla/cocoa/QuartzTextStyleAttribute.h b/ThirdLibs/scintilla/cocoa/QuartzTextStyleAttribute.h similarity index 95% rename from scintilla/cocoa/QuartzTextStyleAttribute.h rename to ThirdLibs/scintilla/cocoa/QuartzTextStyleAttribute.h index 7f389b41..b9698645 100644 --- a/scintilla/cocoa/QuartzTextStyleAttribute.h +++ b/ThirdLibs/scintilla/cocoa/QuartzTextStyleAttribute.h @@ -1,82 +1,82 @@ -/** - * QuartzTextStyleAttribute.h - * - * Original Code by Evan Jones on Wed Oct 02 2002. - * Contributors: - * Shane Caraveo, ActiveState - * Bernd Paradies, Adobe - * - */ - - -#ifndef _QUARTZ_TEXT_STYLE_ATTRIBUTE_H -#define _QUARTZ_TEXT_STYLE_ATTRIBUTE_H - -class QuartzFont -{ -public: - /** Create a font style from a name. */ - QuartzFont( const char* name, size_t length, float size, int weight, bool italic ) - { - assert( name != NULL && length > 0 && name[length] == '\0' ); - - CFStringRef fontName = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingMacRoman); - assert(fontName != NULL); - bool bold = weight > SC_WEIGHT_NORMAL; - - if (bold || italic) - { - CTFontSymbolicTraits desiredTrait = 0; - CTFontSymbolicTraits traitMask = 0; - - // if bold was specified, add the trait - if (bold) { - desiredTrait |= kCTFontBoldTrait; - traitMask |= kCTFontBoldTrait; - } - - // if italic was specified, add the trait - if (italic) { - desiredTrait |= kCTFontItalicTrait; - traitMask |= kCTFontItalicTrait; - } - - // create a font and then a copy of it with the sym traits - CTFontRef iFont = ::CTFontCreateWithName(fontName, size, NULL); - fontid = ::CTFontCreateCopyWithSymbolicTraits(iFont, size, NULL, desiredTrait, traitMask); - if (fontid) - { - CFRelease(iFont); - } - else - { - // Traits failed so use base font - fontid = iFont; - } - } - else - { - // create the font, no traits - fontid = ::CTFontCreateWithName(fontName, size, NULL); - } - - if (!fontid) - { - // Failed to create requested font so use font always present - fontid = ::CTFontCreateWithName((CFStringRef)@"Monaco", size, NULL); - } - - CFRelease(fontName); - } - - CTFontRef getFontID() - { - return fontid; - } - -private: - CTFontRef fontid; -}; - -#endif - +/** + * QuartzTextStyleAttribute.h + * + * Original Code by Evan Jones on Wed Oct 02 2002. + * Contributors: + * Shane Caraveo, ActiveState + * Bernd Paradies, Adobe + * + */ + + +#ifndef _QUARTZ_TEXT_STYLE_ATTRIBUTE_H +#define _QUARTZ_TEXT_STYLE_ATTRIBUTE_H + +class QuartzFont +{ +public: + /** Create a font style from a name. */ + QuartzFont( const char* name, size_t length, float size, int weight, bool italic ) + { + assert( name != NULL && length > 0 && name[length] == '\0' ); + + CFStringRef fontName = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingMacRoman); + assert(fontName != NULL); + bool bold = weight > SC_WEIGHT_NORMAL; + + if (bold || italic) + { + CTFontSymbolicTraits desiredTrait = 0; + CTFontSymbolicTraits traitMask = 0; + + // if bold was specified, add the trait + if (bold) { + desiredTrait |= kCTFontBoldTrait; + traitMask |= kCTFontBoldTrait; + } + + // if italic was specified, add the trait + if (italic) { + desiredTrait |= kCTFontItalicTrait; + traitMask |= kCTFontItalicTrait; + } + + // create a font and then a copy of it with the sym traits + CTFontRef iFont = ::CTFontCreateWithName(fontName, size, NULL); + fontid = ::CTFontCreateCopyWithSymbolicTraits(iFont, size, NULL, desiredTrait, traitMask); + if (fontid) + { + CFRelease(iFont); + } + else + { + // Traits failed so use base font + fontid = iFont; + } + } + else + { + // create the font, no traits + fontid = ::CTFontCreateWithName(fontName, size, NULL); + } + + if (!fontid) + { + // Failed to create requested font so use font always present + fontid = ::CTFontCreateWithName((CFStringRef)@"Monaco", size, NULL); + } + + CFRelease(fontName); + } + + CTFontRef getFontID() + { + return fontid; + } + +private: + CTFontRef fontid; +}; + +#endif + diff --git a/scintilla/cocoa/SciTest.mk b/ThirdLibs/scintilla/cocoa/SciTest.mk similarity index 97% rename from scintilla/cocoa/SciTest.mk rename to ThirdLibs/scintilla/cocoa/SciTest.mk index c0647111..1cd07530 100644 --- a/scintilla/cocoa/SciTest.mk +++ b/ThirdLibs/scintilla/cocoa/SciTest.mk @@ -1,36 +1,36 @@ -### start defines ### -include common.mk - -NAME=Demo - -LD=gcc $(ARCH) -framework Cocoa - -TARG=$(APP)/Contents/MacOS/$(NAME) -APP=$(APP_BLD)/$(NAME).app - -all: $(APP_BLD) $(TARG) - -$(APP): - -rm -rf $(APP) - -mkdir $(APP) - -mkdir $(APP)/Contents/ - -mkdir $(APP)/Contents/Frameworks/ - -mkdir $(APP)/Contents/MacOS/ - -mkdir $(APP)/Contents/Resources/ - -cp ScintillaTest/Info.plist $(APP)/Contents/Info.plist.bak - -sed "s/\$${EXECUTABLE_NAME}/$(NAME)/g" < $(APP)/Contents/Info.plist.bak > $(APP)/Contents/Info.plist.bak2 - -sed "s/\$${PRODUCT_NAME}/$(NAME)/g" < $(APP)/Contents/Info.plist.bak2 > $(APP)/Contents/Info.plist - -rm $(APP)/Contents/Info.plist.bak $(APP)/Contents/Info.plist.bak2 - -cp -r ScintillaTest/English.lproj $(APP)/Contents/Resources/ - /Developer/usr/bin/ibtool --errors --warnings --notices --output-format human-readable-text \ - --compile $(APP)/Contents/Resources/English.lproj/MainMenu.nib ScintillaTest/English.lproj/MainMenu.xib - -cp ScintillaTest/TestData.sql $(APP)/Contents/Resources/ - -make -f Framework.mk all - -$(TARG) : $(APP_BLD)/main.o $(APP_BLD)/AppController.o $(APP) - -cp -R $(FRM_BLD)/Sci.framework $(APP)/Contents/Frameworks/ - $(LD) $(APP_BLD)/main.o $(APP_BLD)/AppController.o $(APP)/Contents/Frameworks/Sci.framework/Sci -o $(TARG) -lstdc++ - -$(APP_BLD) : - -mkdir $(BLD) - -mkdir $(APP_BLD) +### start defines ### +include common.mk + +NAME=Demo + +LD=gcc $(ARCH) -framework Cocoa + +TARG=$(APP)/Contents/MacOS/$(NAME) +APP=$(APP_BLD)/$(NAME).app + +all: $(APP_BLD) $(TARG) + +$(APP): + -rm -rf $(APP) + -mkdir $(APP) + -mkdir $(APP)/Contents/ + -mkdir $(APP)/Contents/Frameworks/ + -mkdir $(APP)/Contents/MacOS/ + -mkdir $(APP)/Contents/Resources/ + -cp ScintillaTest/Info.plist $(APP)/Contents/Info.plist.bak + -sed "s/\$${EXECUTABLE_NAME}/$(NAME)/g" < $(APP)/Contents/Info.plist.bak > $(APP)/Contents/Info.plist.bak2 + -sed "s/\$${PRODUCT_NAME}/$(NAME)/g" < $(APP)/Contents/Info.plist.bak2 > $(APP)/Contents/Info.plist + -rm $(APP)/Contents/Info.plist.bak $(APP)/Contents/Info.plist.bak2 + -cp -r ScintillaTest/English.lproj $(APP)/Contents/Resources/ + /Developer/usr/bin/ibtool --errors --warnings --notices --output-format human-readable-text \ + --compile $(APP)/Contents/Resources/English.lproj/MainMenu.nib ScintillaTest/English.lproj/MainMenu.xib + -cp ScintillaTest/TestData.sql $(APP)/Contents/Resources/ + -make -f Framework.mk all + +$(TARG) : $(APP_BLD)/main.o $(APP_BLD)/AppController.o $(APP) + -cp -R $(FRM_BLD)/Sci.framework $(APP)/Contents/Frameworks/ + $(LD) $(APP_BLD)/main.o $(APP_BLD)/AppController.o $(APP)/Contents/Frameworks/Sci.framework/Sci -o $(TARG) -lstdc++ + +$(APP_BLD) : + -mkdir $(BLD) + -mkdir $(APP_BLD) diff --git a/scintilla/cocoa/ScintillaCocoa.h b/ThirdLibs/scintilla/cocoa/ScintillaCocoa.h similarity index 96% rename from scintilla/cocoa/ScintillaCocoa.h rename to ThirdLibs/scintilla/cocoa/ScintillaCocoa.h index 7108c963..5ee1f149 100644 --- a/scintilla/cocoa/ScintillaCocoa.h +++ b/ThirdLibs/scintilla/cocoa/ScintillaCocoa.h @@ -1,217 +1,217 @@ -/* - * ScintillaCocoa.h - * - * Mike Lischke - * - * Based on ScintillaMacOSX.h - * Original code by Evan Jones on Sun Sep 01 2002. - * Contributors: - * Shane Caraveo, ActiveState - * Bernd Paradies, Adobe - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include "ILexer.h" - -#ifdef SCI_LEXER -#include "SciLexer.h" -#include "PropSetSimple.h" -#endif - -#include "SVector.h" -#include "SplitVector.h" -#include "Partitioning.h" -#include "RunStyles.h" -#include "ContractionState.h" -#include "CellBuffer.h" -#include "CallTip.h" -#include "KeyMap.h" -#include "Indicator.h" -#include "XPM.h" -#include "LineMarker.h" -#include "Style.h" -#include "AutoComplete.h" -#include "ViewStyle.h" -#include "CharClassify.h" -#include "Decoration.h" -#include "Document.h" -#include "Selection.h" -#include "PositionCache.h" -#include "Editor.h" -//#include "ScintillaCallTip.h" - -#include "ScintillaBase.h" - -extern "C" NSString* ScintillaRecPboardType; - -@class ScintillaView; - -/** - * Helper class to be used as timer target (NSTimer). - */ -@interface TimerTarget : NSObject -{ - void* mTarget; - NSNotificationQueue* notificationQueue; -} -- (id) init: (void*) target; -- (void) timerFired: (NSTimer*) timer; -- (void) idleTimerFired: (NSTimer*) timer; -- (void) idleTriggered: (NSNotification*) notification; -@end - -namespace Scintilla { - -/** - * On the Mac, there is no WM_COMMAND or WM_NOTIFY message that can be sent - * back to the parent. Therefore, there must be a callback handler that acts - * like a Windows WndProc, where Scintilla can send notifications to. Use - * ScintillaCocoa::RegisterNotifyHandler() to register such a handler. - * Message format is: - *
- * WM_COMMAND: HIWORD (wParam) = notification code, LOWORD (wParam) = 0 (no control ID), lParam = ScintillaCocoa* - *
- * WM_NOTIFY: wParam = 0 (no control ID), lParam = ptr to SCNotification structure, with hwndFrom set to ScintillaCocoa* - */ -typedef void(*SciNotifyFunc) (intptr_t windowid, unsigned int iMessage, uintptr_t wParam, uintptr_t lParam); - -/** - * Scintilla sends these two messages to the nofity handler. Please refer - * to the Windows API doc for details about the message format. - */ -#define WM_COMMAND 1001 -#define WM_NOTIFY 1002 - -/** - * Main scintilla class, implemented for OS X (Cocoa). - */ -class ScintillaCocoa : public ScintillaBase -{ -private: - TimerTarget* timerTarget; - NSEvent* lastMouseEvent; - - SciNotifyFunc notifyProc; - intptr_t notifyObj; - - bool capturedMouse; - - // Private so ScintillaCocoa objects can not be copied - ScintillaCocoa(const ScintillaCocoa &) : ScintillaBase() {} - ScintillaCocoa &operator=(const ScintillaCocoa &) { return * this; } - - bool GetPasteboardData(NSPasteboard* board, SelectionText* selectedText); - void SetPasteboardData(NSPasteboard* board, const SelectionText& selectedText); - - int scrollSpeed; - int scrollTicks; - NSTimer* tickTimer; - NSTimer* idleTimer; - -protected: - PRectangle GetClientRectangle(); - Point ConvertPoint(NSPoint point); - - virtual void Initialise(); - virtual void Finalise(); - virtual CaseFolder *CaseFolderForEncoding(); - virtual std::string CaseMapString(const std::string &s, int caseMapping); -public: - NSView* ContentView(); - - ScintillaCocoa(NSView* view); - virtual ~ScintillaCocoa(); - - void RegisterNotifyCallback(intptr_t windowid, SciNotifyFunc callback); - sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); - - ScintillaView* TopContainer(); - - void SyncPaint(void* gc, PRectangle rc); - void Draw(NSRect rect, CGContextRef gc); - - virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); - void SetTicking(bool on); - bool SetIdle(bool on); - void SetMouseCapture(bool on); - bool HaveMouseCapture(); - void ScrollText(int linesToMove); - void SetVerticalScrollPos(); - void SetHorizontalScrollPos(); - bool ModifyScrollBars(int nMax, int nPage); - void Resize(); - void DoScroll(float position, NSScrollerPart part, bool horizontal); - - // Notifications for the owner. - void NotifyChange(); - void NotifyFocus(bool focus); - void NotifyParent(SCNotification scn); - void NotifyURIDropped(const char *uri); - - bool HasSelection(); - bool CanUndo(); - bool CanRedo(); - virtual void CopyToClipboard(const SelectionText &selectedText); - virtual void Copy(); - virtual bool CanPaste(); - virtual void Paste(); - virtual void Paste(bool rectangular); - void CTPaint(void* gc, NSRect rc); - void CallTipMouseDown(NSPoint pt); - virtual void CreateCallTipWindow(PRectangle rc); - virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true); - virtual void ClaimSelection(); - - NSPoint GetCaretPosition(); - - static sptr_t DirectFunction(ScintillaCocoa *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam); - - void TimerFired(NSTimer* timer); - void IdleTimerFired(); - int InsertText(NSString* input); - - bool KeyboardInput(NSEvent* event); - void MouseDown(NSEvent* event); - void MouseMove(NSEvent* event); - void MouseUp(NSEvent* event); - void MouseEntered(NSEvent* event); - void MouseExited(NSEvent* event); - void MouseWheel(NSEvent* event); - - // Drag and drop - void StartDrag(); - bool GetDragData(id info, NSPasteboard &pasteBoard, SelectionText* selectedText); - NSDragOperation DraggingEntered(id info); - NSDragOperation DraggingUpdated(id info); - void DraggingExited(id info); - bool PerformDragOperation(id info); - void DragScroll(); - - // Promote some methods needed for NSResponder actions. - virtual void SelectAll(); - void DeleteBackward(); - virtual void Cut(); - virtual void Undo(); - virtual void Redo(); - - virtual NSMenu* CreateContextMenu(NSEvent* event); - void HandleCommand(NSInteger command); - - virtual void ActiveStateChanged(bool isActive); -}; - - -} - - +/* + * ScintillaCocoa.h + * + * Mike Lischke + * + * Based on ScintillaMacOSX.h + * Original code by Evan Jones on Sun Sep 01 2002. + * Contributors: + * Shane Caraveo, ActiveState + * Bernd Paradies, Adobe + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" + +#ifdef SCI_LEXER +#include "SciLexer.h" +#include "PropSetSimple.h" +#endif + +#include "SVector.h" +#include "SplitVector.h" +#include "Partitioning.h" +#include "RunStyles.h" +#include "ContractionState.h" +#include "CellBuffer.h" +#include "CallTip.h" +#include "KeyMap.h" +#include "Indicator.h" +#include "XPM.h" +#include "LineMarker.h" +#include "Style.h" +#include "AutoComplete.h" +#include "ViewStyle.h" +#include "CharClassify.h" +#include "Decoration.h" +#include "Document.h" +#include "Selection.h" +#include "PositionCache.h" +#include "Editor.h" +//#include "ScintillaCallTip.h" + +#include "ScintillaBase.h" + +extern "C" NSString* ScintillaRecPboardType; + +@class ScintillaView; + +/** + * Helper class to be used as timer target (NSTimer). + */ +@interface TimerTarget : NSObject +{ + void* mTarget; + NSNotificationQueue* notificationQueue; +} +- (id) init: (void*) target; +- (void) timerFired: (NSTimer*) timer; +- (void) idleTimerFired: (NSTimer*) timer; +- (void) idleTriggered: (NSNotification*) notification; +@end + +namespace Scintilla { + +/** + * On the Mac, there is no WM_COMMAND or WM_NOTIFY message that can be sent + * back to the parent. Therefore, there must be a callback handler that acts + * like a Windows WndProc, where Scintilla can send notifications to. Use + * ScintillaCocoa::RegisterNotifyHandler() to register such a handler. + * Message format is: + *
+ * WM_COMMAND: HIWORD (wParam) = notification code, LOWORD (wParam) = 0 (no control ID), lParam = ScintillaCocoa* + *
+ * WM_NOTIFY: wParam = 0 (no control ID), lParam = ptr to SCNotification structure, with hwndFrom set to ScintillaCocoa* + */ +typedef void(*SciNotifyFunc) (intptr_t windowid, unsigned int iMessage, uintptr_t wParam, uintptr_t lParam); + +/** + * Scintilla sends these two messages to the nofity handler. Please refer + * to the Windows API doc for details about the message format. + */ +#define WM_COMMAND 1001 +#define WM_NOTIFY 1002 + +/** + * Main scintilla class, implemented for OS X (Cocoa). + */ +class ScintillaCocoa : public ScintillaBase +{ +private: + TimerTarget* timerTarget; + NSEvent* lastMouseEvent; + + SciNotifyFunc notifyProc; + intptr_t notifyObj; + + bool capturedMouse; + + // Private so ScintillaCocoa objects can not be copied + ScintillaCocoa(const ScintillaCocoa &) : ScintillaBase() {} + ScintillaCocoa &operator=(const ScintillaCocoa &) { return * this; } + + bool GetPasteboardData(NSPasteboard* board, SelectionText* selectedText); + void SetPasteboardData(NSPasteboard* board, const SelectionText& selectedText); + + int scrollSpeed; + int scrollTicks; + NSTimer* tickTimer; + NSTimer* idleTimer; + +protected: + PRectangle GetClientRectangle(); + Point ConvertPoint(NSPoint point); + + virtual void Initialise(); + virtual void Finalise(); + virtual CaseFolder *CaseFolderForEncoding(); + virtual std::string CaseMapString(const std::string &s, int caseMapping); +public: + NSView* ContentView(); + + ScintillaCocoa(NSView* view); + virtual ~ScintillaCocoa(); + + void RegisterNotifyCallback(intptr_t windowid, SciNotifyFunc callback); + sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + + ScintillaView* TopContainer(); + + void SyncPaint(void* gc, PRectangle rc); + void Draw(NSRect rect, CGContextRef gc); + + virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + void SetTicking(bool on); + bool SetIdle(bool on); + void SetMouseCapture(bool on); + bool HaveMouseCapture(); + void ScrollText(int linesToMove); + void SetVerticalScrollPos(); + void SetHorizontalScrollPos(); + bool ModifyScrollBars(int nMax, int nPage); + void Resize(); + void DoScroll(float position, NSScrollerPart part, bool horizontal); + + // Notifications for the owner. + void NotifyChange(); + void NotifyFocus(bool focus); + void NotifyParent(SCNotification scn); + void NotifyURIDropped(const char *uri); + + bool HasSelection(); + bool CanUndo(); + bool CanRedo(); + virtual void CopyToClipboard(const SelectionText &selectedText); + virtual void Copy(); + virtual bool CanPaste(); + virtual void Paste(); + virtual void Paste(bool rectangular); + void CTPaint(void* gc, NSRect rc); + void CallTipMouseDown(NSPoint pt); + virtual void CreateCallTipWindow(PRectangle rc); + virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true); + virtual void ClaimSelection(); + + NSPoint GetCaretPosition(); + + static sptr_t DirectFunction(ScintillaCocoa *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam); + + void TimerFired(NSTimer* timer); + void IdleTimerFired(); + int InsertText(NSString* input); + + bool KeyboardInput(NSEvent* event); + void MouseDown(NSEvent* event); + void MouseMove(NSEvent* event); + void MouseUp(NSEvent* event); + void MouseEntered(NSEvent* event); + void MouseExited(NSEvent* event); + void MouseWheel(NSEvent* event); + + // Drag and drop + void StartDrag(); + bool GetDragData(id info, NSPasteboard &pasteBoard, SelectionText* selectedText); + NSDragOperation DraggingEntered(id info); + NSDragOperation DraggingUpdated(id info); + void DraggingExited(id info); + bool PerformDragOperation(id info); + void DragScroll(); + + // Promote some methods needed for NSResponder actions. + virtual void SelectAll(); + void DeleteBackward(); + virtual void Cut(); + virtual void Undo(); + virtual void Redo(); + + virtual NSMenu* CreateContextMenu(NSEvent* event); + void HandleCommand(NSInteger command); + + virtual void ActiveStateChanged(bool isActive); +}; + + +} + + diff --git a/scintilla/cocoa/ScintillaCocoa.mm b/ThirdLibs/scintilla/cocoa/ScintillaCocoa.mm similarity index 97% rename from scintilla/cocoa/ScintillaCocoa.mm rename to ThirdLibs/scintilla/cocoa/ScintillaCocoa.mm index d2528d83..e7beda69 100644 --- a/scintilla/cocoa/ScintillaCocoa.mm +++ b/ThirdLibs/scintilla/cocoa/ScintillaCocoa.mm @@ -1,1842 +1,1842 @@ - -/** - * Scintilla source code edit control - * ScintillaCocoa.mm - Cocoa subclass of ScintillaBase - * - * Written by Mike Lischke - * - * Loosely based on ScintillaMacOSX.cxx. - * Copyright 2003 by Evan Jones - * Based on ScintillaGTK.cxx Copyright 1998-2002 by Neil Hodgson - * The License.txt file describes the conditions under which this software may be distributed. - * - * Copyright (c) 2009, 2010 Sun Microsystems, Inc. All rights reserved. - * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). - */ - -#import - -#import // Temporary - -#include "ScintillaView.h" -#include "PlatCocoa.h" - -using namespace Scintilla; - -#ifndef WM_UNICHAR -#define WM_UNICHAR 0x0109 -#endif - -NSString* ScintillaRecPboardType = @"com.scintilla.utf16-plain-text.rectangular"; - -//-------------------------------------------------------------------------------------------------- - -// Define keyboard shortcuts (equivalents) the Mac way. -#define SCI_CMD ( SCI_CTRL) -#define SCI_SCMD ( SCI_CMD | SCI_SHIFT) -#define SCI_SMETA ( SCI_META | SCI_SHIFT) - -static const KeyToCommand macMapDefault[] = -{ - // OS X specific - {SCK_DOWN, SCI_CTRL, SCI_DOCUMENTEND}, - {SCK_DOWN, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND}, - {SCK_UP, SCI_CTRL, SCI_DOCUMENTSTART}, - {SCK_UP, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND}, - {SCK_LEFT, SCI_CTRL, SCI_VCHOME}, - {SCK_LEFT, SCI_CSHIFT, SCI_VCHOMEEXTEND}, - {SCK_RIGHT, SCI_CTRL, SCI_LINEEND}, - {SCK_RIGHT, SCI_CSHIFT, SCI_LINEENDEXTEND}, - - // Similar to Windows and GTK+ - // Where equivalent clashes with OS X standard, use Meta instead - {SCK_DOWN, SCI_NORM, SCI_LINEDOWN}, - {SCK_DOWN, SCI_SHIFT, SCI_LINEDOWNEXTEND}, - {SCK_DOWN, SCI_META, SCI_LINESCROLLDOWN}, - {SCK_DOWN, SCI_ASHIFT, SCI_LINEDOWNRECTEXTEND}, - {SCK_UP, SCI_NORM, SCI_LINEUP}, - {SCK_UP, SCI_SHIFT, SCI_LINEUPEXTEND}, - {SCK_UP, SCI_META, SCI_LINESCROLLUP}, - {SCK_UP, SCI_ASHIFT, SCI_LINEUPRECTEXTEND}, - {'[', SCI_CTRL, SCI_PARAUP}, - {'[', SCI_CSHIFT, SCI_PARAUPEXTEND}, - {']', SCI_CTRL, SCI_PARADOWN}, - {']', SCI_CSHIFT, SCI_PARADOWNEXTEND}, - {SCK_LEFT, SCI_NORM, SCI_CHARLEFT}, - {SCK_LEFT, SCI_SHIFT, SCI_CHARLEFTEXTEND}, - {SCK_LEFT, SCI_ALT, SCI_WORDLEFT}, - {SCK_LEFT, SCI_META, SCI_WORDLEFT}, - {SCK_LEFT, SCI_SMETA, SCI_WORDLEFTEXTEND}, - {SCK_LEFT, SCI_ASHIFT, SCI_CHARLEFTRECTEXTEND}, - {SCK_RIGHT, SCI_NORM, SCI_CHARRIGHT}, - {SCK_RIGHT, SCI_SHIFT, SCI_CHARRIGHTEXTEND}, - {SCK_RIGHT, SCI_ALT, SCI_WORDRIGHT}, - {SCK_RIGHT, SCI_META, SCI_WORDRIGHT}, - {SCK_RIGHT, SCI_SMETA, SCI_WORDRIGHTEXTEND}, - {SCK_RIGHT, SCI_ASHIFT, SCI_CHARRIGHTRECTEXTEND}, - {'/', SCI_CTRL, SCI_WORDPARTLEFT}, - {'/', SCI_CSHIFT, SCI_WORDPARTLEFTEXTEND}, - {'\\', SCI_CTRL, SCI_WORDPARTRIGHT}, - {'\\', SCI_CSHIFT, SCI_WORDPARTRIGHTEXTEND}, - {SCK_HOME, SCI_NORM, SCI_VCHOME}, - {SCK_HOME, SCI_SHIFT, SCI_VCHOMEEXTEND}, - {SCK_HOME, SCI_CTRL, SCI_DOCUMENTSTART}, - {SCK_HOME, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND}, - {SCK_HOME, SCI_ALT, SCI_HOMEDISPLAY}, - {SCK_HOME, SCI_ASHIFT, SCI_VCHOMERECTEXTEND}, - {SCK_END, SCI_NORM, SCI_LINEEND}, - {SCK_END, SCI_SHIFT, SCI_LINEENDEXTEND}, - {SCK_END, SCI_CTRL, SCI_DOCUMENTEND}, - {SCK_END, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND}, - {SCK_END, SCI_ALT, SCI_LINEENDDISPLAY}, - {SCK_END, SCI_ASHIFT, SCI_LINEENDRECTEXTEND}, - {SCK_PRIOR, SCI_NORM, SCI_PAGEUP}, - {SCK_PRIOR, SCI_SHIFT, SCI_PAGEUPEXTEND}, - {SCK_PRIOR, SCI_ASHIFT, SCI_PAGEUPRECTEXTEND}, - {SCK_NEXT, SCI_NORM, SCI_PAGEDOWN}, - {SCK_NEXT, SCI_SHIFT, SCI_PAGEDOWNEXTEND}, - {SCK_NEXT, SCI_ASHIFT, SCI_PAGEDOWNRECTEXTEND}, - {SCK_DELETE, SCI_NORM, SCI_CLEAR}, - {SCK_DELETE, SCI_SHIFT, SCI_CUT}, - {SCK_DELETE, SCI_CTRL, SCI_DELWORDRIGHT}, - {SCK_DELETE, SCI_CSHIFT, SCI_DELLINERIGHT}, - {SCK_INSERT, SCI_NORM, SCI_EDITTOGGLEOVERTYPE}, - {SCK_INSERT, SCI_SHIFT, SCI_PASTE}, - {SCK_INSERT, SCI_CTRL, SCI_COPY}, - {SCK_ESCAPE, SCI_NORM, SCI_CANCEL}, - {SCK_BACK, SCI_NORM, SCI_DELETEBACK}, - {SCK_BACK, SCI_SHIFT, SCI_DELETEBACK}, - {SCK_BACK, SCI_CTRL, SCI_DELWORDLEFT}, - {SCK_BACK, SCI_ALT, SCI_UNDO}, - {SCK_BACK, SCI_CSHIFT, SCI_DELLINELEFT}, - {'z', SCI_CMD, SCI_UNDO}, - {'z', SCI_SCMD, SCI_REDO}, - {'x', SCI_CMD, SCI_CUT}, - {'c', SCI_CMD, SCI_COPY}, - {'v', SCI_CMD, SCI_PASTE}, - {'a', SCI_CMD, SCI_SELECTALL}, - {SCK_TAB, SCI_NORM, SCI_TAB}, - {SCK_TAB, SCI_SHIFT, SCI_BACKTAB}, - {SCK_RETURN, SCI_NORM, SCI_NEWLINE}, - {SCK_RETURN, SCI_SHIFT, SCI_NEWLINE}, - {SCK_ADD, SCI_CMD, SCI_ZOOMIN}, - {SCK_SUBTRACT, SCI_CMD, SCI_ZOOMOUT}, - {SCK_DIVIDE, SCI_CMD, SCI_SETZOOM}, - {'l', SCI_CMD, SCI_LINECUT}, - {'l', SCI_CSHIFT, SCI_LINEDELETE}, - {'t', SCI_CSHIFT, SCI_LINECOPY}, - {'t', SCI_CTRL, SCI_LINETRANSPOSE}, - {'d', SCI_CTRL, SCI_SELECTIONDUPLICATE}, - {'u', SCI_CTRL, SCI_LOWERCASE}, - {'u', SCI_CSHIFT, SCI_UPPERCASE}, - {0, 0, 0}, -}; - -//-------------------------------------------------------------------------------------------------- - -@implementation TimerTarget - -- (id) init: (void*) target -{ - self = [super init]; - if (self != nil) - { - mTarget = target; - - // Get the default notification queue for the thread which created the instance (usually the - // main thread). We need that later for idle event processing. - NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; - notificationQueue = [[NSNotificationQueue alloc] initWithNotificationCenter: center]; - [center addObserver: self selector: @selector(idleTriggered:) name: @"Idle" object: nil]; - } - return self; -} - -//-------------------------------------------------------------------------------------------------- - -- (void) dealloc -{ - [notificationQueue release]; - [super dealloc]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Method called by a timer installed by ScintillaCocoa. This two step approach is needed because - * a native Obj-C class is required as target for the timer. - */ -- (void) timerFired: (NSTimer*) timer -{ - reinterpret_cast(mTarget)->TimerFired(timer); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Another timer callback for the idle timer. - */ -- (void) idleTimerFired: (NSTimer*) timer -{ -#pragma unused(timer) - // Idle timer event. - // Post a new idle notification, which gets executed when the run loop is idle. - // Since we are coalescing on name and sender there will always be only one actual notification - // even for multiple requests. - NSNotification *notification = [NSNotification notificationWithName: @"Idle" object: self]; - [notificationQueue enqueueNotification: notification - postingStyle: NSPostWhenIdle - coalesceMask: (NSNotificationCoalescingOnName | NSNotificationCoalescingOnSender) - forModes: nil]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Another step for idle events. The timer (for idle events) simply requests a notification on - * idle time. Only when this notification is send we actually call back the editor. - */ -- (void) idleTriggered: (NSNotification*) notification -{ -#pragma unused(notification) - reinterpret_cast(mTarget)->IdleTimerFired(); -} - -@end - -//----------------- ScintillaCocoa ----------------------------------------------------------------- - -ScintillaCocoa::ScintillaCocoa(NSView* view) -{ - wMain= [view retain]; - timerTarget = [[[TimerTarget alloc] init: this] retain]; - Initialise(); -} - -//-------------------------------------------------------------------------------------------------- - -ScintillaCocoa::~ScintillaCocoa() -{ - SetTicking(false); - [timerTarget release]; - NSView* container = ContentView(); - [container release]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Core initialization of the control. Everything that needs to be set up happens here. - */ -void ScintillaCocoa::Initialise() -{ - static bool initedLexers = false; - if (!initedLexers) - { - initedLexers = true; - Scintilla_LinkLexers(); - } - notifyObj = NULL; - notifyProc = NULL; - - capturedMouse = false; - - // Tell Scintilla not to buffer: Quartz buffers drawing for us. - WndProc(SCI_SETBUFFEREDDRAW, 0, 0); - - // We are working with Unicode exclusively. - WndProc(SCI_SETCODEPAGE, SC_CP_UTF8, 0); - - // Add Mac specific key bindings. - for (int i = 0; macMapDefault[i].key; i++) - kmap.AssignCmdKey(macMapDefault[i].key, macMapDefault[i].modifiers, macMapDefault[i].msg); - -} - -//-------------------------------------------------------------------------------------------------- - -/** - * We need some clean up. Do it here. - */ -void ScintillaCocoa::Finalise() -{ - SetTicking(false); - ScintillaBase::Finalise(); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Convert a core foundation string into an array of bytes in a particular encoding - */ - -static char *EncodedBytes(CFStringRef cfsRef, CFStringEncoding encoding) { - CFRange rangeAll = {0, CFStringGetLength(cfsRef)}; - CFIndex usedLen = 0; - CFStringGetBytes(cfsRef, rangeAll, encoding, '?', - false, NULL, 0, &usedLen); - - char *buffer = new char[usedLen+1]; - CFStringGetBytes(cfsRef, rangeAll, encoding, '?', - false, (UInt8 *)buffer,usedLen, NULL); - buffer[usedLen] = '\0'; - return buffer; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Case folders. - */ - -class CaseFolderUTF8 : public CaseFolderTable { -public: - CaseFolderUTF8() { - StandardASCII(); - } - virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) { - if ((lenMixed == 1) && (sizeFolded > 0)) { - folded[0] = mapping[static_cast(mixed[0])]; - return 1; - } else { - CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault, - reinterpret_cast(mixed), - lenMixed, kCFStringEncodingUTF8, false); - - NSString *sMapped = [(NSString *)cfsVal stringByFoldingWithOptions:NSCaseInsensitiveSearch - locale:[NSLocale currentLocale]]; - - const char *cpMapped = [sMapped UTF8String]; - size_t lenMapped = strlen(cpMapped); - if (lenMapped < sizeFolded) { - memcpy(folded, cpMapped, lenMapped); - } else { - lenMapped = 0; - } - CFRelease(cfsVal); - return lenMapped; - } - } -}; - -class CaseFolderDBCS : public CaseFolderTable { - CFStringEncoding encoding; -public: - CaseFolderDBCS(CFStringEncoding encoding_) : encoding(encoding_) { - StandardASCII(); - } - virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) { - if ((lenMixed == 1) && (sizeFolded > 0)) { - folded[0] = mapping[static_cast(mixed[0])]; - return 1; - } else { - CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault, - reinterpret_cast(mixed), - lenMixed, encoding, false); - - NSString *sMapped = [(NSString *)cfsVal stringByFoldingWithOptions:NSCaseInsensitiveSearch - locale:[NSLocale currentLocale]]; - - char *encoded = EncodedBytes((CFStringRef)sMapped, encoding); - - size_t lenMapped = strlen(encoded); - if (lenMapped < sizeFolded) { - memcpy(folded, encoded, lenMapped); - } else { - folded[0] = '\0'; - lenMapped = 1; - } - delete []encoded; - CFRelease(cfsVal); - return lenMapped; - } - // Something failed so return a single NUL byte - folded[0] = '\0'; - return 1; - } -}; - -CaseFolder *ScintillaCocoa::CaseFolderForEncoding() { - if (pdoc->dbcsCodePage == SC_CP_UTF8) { - return new CaseFolderUTF8(); - } else { - CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(), - vs.styles[STYLE_DEFAULT].characterSet); - if (pdoc->dbcsCodePage == 0) { - CaseFolderTable *pcf = new CaseFolderTable(); - pcf->StandardASCII(); - // Only for single byte encodings - for (int i=0x80; i<0x100; i++) { - char sCharacter[2] = "A"; - sCharacter[0] = i; - CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault, - reinterpret_cast(sCharacter), - 1, encoding, false); - - NSString *sMapped = [(NSString *)cfsVal stringByFoldingWithOptions:NSCaseInsensitiveSearch - locale:[NSLocale currentLocale]]; - - char *encoded = EncodedBytes((CFStringRef)sMapped, encoding); - - if (strlen(encoded) == 1) { - pcf->SetTranslation(sCharacter[0], encoded[0]); - } - - delete []encoded; - CFRelease(cfsVal); - } - return pcf; - } else { - return new CaseFolderDBCS(encoding); - } - return 0; - } -} - - -//-------------------------------------------------------------------------------------------------- - -/** - * Case-fold the given string depending on the specified case mapping type. - */ -std::string ScintillaCocoa::CaseMapString(const std::string &s, int caseMapping) -{ - CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(), - vs.styles[STYLE_DEFAULT].characterSet); - CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault, - reinterpret_cast(s.c_str()), - s.length(), encoding, false); - - NSString *sMapped; - switch (caseMapping) - { - case cmUpper: - sMapped = [(NSString *)cfsVal uppercaseString]; - break; - case cmLower: - sMapped = [(NSString *)cfsVal lowercaseString]; - break; - default: - sMapped = (NSString *)cfsVal; - } - - // Back to encoding - char *encoded = EncodedBytes((CFStringRef)sMapped, encoding); - std::string result(encoded); - delete []encoded; - CFRelease(cfsVal); - return result; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Helper function to get the outer container which represents the Scintilla editor on application side. - */ -ScintillaView* ScintillaCocoa::TopContainer() -{ - NSView* container = static_cast(wMain.GetID()); - return static_cast([container superview]); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Helper function to get the inner container which represents the actual "canvas" we work with. - */ -NSView* ScintillaCocoa::ContentView() -{ - return static_cast(wMain.GetID()); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Instead of returning the size of the inner view we have to return the visible part of it - * in order to make scrolling working properly. - */ -PRectangle ScintillaCocoa::GetClientRectangle() -{ - NSView* host = ContentView(); - NSSize size = [host frame].size; - return PRectangle(0, 0, size.width, size.height); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Converts the given point from base coordinates to local coordinates and at the same time into - * a native Point structure. Base coordinates are used for the top window used in the view hierarchy. - */ -Scintilla::Point ScintillaCocoa::ConvertPoint(NSPoint point) -{ - NSView* container = ContentView(); - NSPoint result = [container convertPoint: point fromView: nil]; - - return Point(result.x, result.y); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * A function to directly execute code that would usually go the long way via window messages. - * However this is a Windows metapher and not used here, hence we just call our fake - * window proc. The given parameters directly reflect the message parameters used on Windows. - * - * @param sciThis The target which is to be called. - * @param iMessage A code that indicates which message was sent. - * @param wParam One of the two free parameters for the message. Traditionally a word sized parameter - * (hence the w prefix). - * @param lParam The other of the two free parameters. A signed long. - */ -sptr_t ScintillaCocoa::DirectFunction(ScintillaCocoa *sciThis, unsigned int iMessage, uptr_t wParam, - sptr_t lParam) -{ - return sciThis->WndProc(iMessage, wParam, lParam); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * This method is very similar to DirectFunction. On Windows it sends a message (not in the Obj-C sense) - * to the target window. Here we simply call our fake window proc. - */ -sptr_t scintilla_send_message(void* sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam) -{ - ScintillaView *control = reinterpret_cast(sci); - ScintillaCocoa* scintilla = [control backend]; - return scintilla->WndProc(iMessage, wParam, lParam); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * That's our fake window procedure. On Windows each window has a dedicated procedure to handle - * commands (also used to synchronize UI and background threads), which is not the case in Cocoa. - * - * Messages handled here are almost solely for special commands of the backend. Everything which - * would be sytem messages on Windows (e.g. for key down, mouse move etc.) are handled by - * directly calling appropriate handlers. - */ -sptr_t ScintillaCocoa::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) -{ - switch (iMessage) - { - case SCI_GETDIRECTFUNCTION: - return reinterpret_cast(DirectFunction); - - case SCI_GETDIRECTPOINTER: - return reinterpret_cast(this); - - case SCI_GRABFOCUS: - [[ContentView() window] makeFirstResponder:ContentView()]; - break; - - case SCI_SETBUFFEREDDRAW: - // Buffered drawing not supported on Cocoa - bufferedDraw = false; - break; - - case WM_UNICHAR: - // Special case not used normally. Characters passed in this way will be inserted - // regardless of their value or modifier states. That means no command interpretation is - // performed. - if (IsUnicodeMode()) - { - NSString* input = [NSString stringWithCharacters: (const unichar*) &wParam length: 1]; - const char* utf8 = [input UTF8String]; - AddCharUTF((char*) utf8, static_cast(strlen(utf8)), false); - return 1; - } - return 0; - - default: - sptr_t r = ScintillaBase::WndProc(iMessage, wParam, lParam); - - return r; - } - return 0l; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * In Windows lingo this is the handler which handles anything that wasn't handled in the normal - * window proc which would usually send the message back to generic window proc that Windows uses. - */ -sptr_t ScintillaCocoa::DefWndProc(unsigned int, uptr_t, sptr_t) -{ - return 0; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Enables or disables a timer that can trigger background processing at a regular interval, like - * drag scrolling or caret blinking. - */ -void ScintillaCocoa::SetTicking(bool on) -{ - if (timer.ticking != on) - { - timer.ticking = on; - if (timer.ticking) - { - // Scintilla ticks = milliseconds - tickTimer = [NSTimer scheduledTimerWithTimeInterval: timer.tickSize / 1000.0 - target: timerTarget - selector: @selector(timerFired:) - userInfo: nil - repeats: YES]; - timer.tickerID = reinterpret_cast(tickTimer); - } - else - if (timer.tickerID != NULL) - { - [reinterpret_cast(timer.tickerID) invalidate]; - timer.tickerID = 0; - } - } - timer.ticksToWait = caret.period; -} - -//-------------------------------------------------------------------------------------------------- - -bool ScintillaCocoa::SetIdle(bool on) -{ - if (idler.state != on) - { - idler.state = on; - if (idler.state) - { - // Scintilla ticks = milliseconds - idleTimer = [NSTimer scheduledTimerWithTimeInterval: timer.tickSize / 1000.0 - target: timerTarget - selector: @selector(idleTimerFired:) - userInfo: nil - repeats: YES]; - idler.idlerID = reinterpret_cast(idleTimer); - } - else - if (idler.idlerID != NULL) - { - [reinterpret_cast(idler.idlerID) invalidate]; - idler.idlerID = 0; - } - } - return true; -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::CopyToClipboard(const SelectionText &selectedText) -{ - SetPasteboardData([NSPasteboard generalPasteboard], selectedText); -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::Copy() -{ - if (!sel.Empty()) - { - SelectionText selectedText; - CopySelectionRange(&selectedText); - CopyToClipboard(selectedText); - } -} - -//-------------------------------------------------------------------------------------------------- - -bool ScintillaCocoa::CanPaste() -{ - if (!Editor::CanPaste()) - return false; - - return GetPasteboardData([NSPasteboard generalPasteboard], NULL); -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::Paste() -{ - Paste(false); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Pastes data from the paste board into the editor. - */ -void ScintillaCocoa::Paste(bool forceRectangular) -{ - SelectionText selectedText; - bool ok = GetPasteboardData([NSPasteboard generalPasteboard], &selectedText); - if (forceRectangular) - selectedText.rectangular = forceRectangular; - - if (!ok || !selectedText.s) - // No data or no flavor we support. - return; - - pdoc->BeginUndoAction(); - ClearSelection(false); - int length = selectedText.len - 1; // One less to avoid inserting the terminating 0 character. - if (selectedText.rectangular) - { - SelectionPosition selStart = sel.RangeMain().Start(); - PasteRectangular(selStart, selectedText.s, length); - } - else - if (pdoc->InsertString(sel.RangeMain().caret.Position(), selectedText.s, length)) - SetEmptySelection(sel.RangeMain().caret.Position() + length); - - pdoc->EndUndoAction(); - - Redraw(); - EnsureCaretVisible(); -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::CTPaint(void* gc, NSRect rc) { -#pragma unused(rc) - Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); - if (surfaceWindow) { - surfaceWindow->Init(gc, wMain.GetID()); - surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ct.codePage); - surfaceWindow->SetDBCSMode(ct.codePage); - ct.PaintCT(surfaceWindow); - surfaceWindow->Release(); - delete surfaceWindow; - } -} - -@interface CallTipView : NSControl { - ScintillaCocoa *sci; -} - -@end - -@implementation CallTipView - -- (NSView*) initWithFrame: (NSRect) frame { - self = [super initWithFrame: frame]; - - if (self) { - sci = NULL; - } - - return self; -} - -- (void) dealloc { - [super dealloc]; -} - -- (BOOL) isFlipped { - return YES; -} - -- (void) setSci: (ScintillaCocoa *) sci_ { - sci = sci_; -} - -- (void) drawRect: (NSRect) needsDisplayInRect { - if (sci) { - CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; - sci->CTPaint(context, needsDisplayInRect); - } -} - -- (void) mouseDown: (NSEvent *) event { - if (sci) { - sci->CallTipMouseDown([event locationInWindow]); - } -} - -// On OS X, only the key view should modify the cursor so the calltip can't. -// This view does not become key so resetCursorRects never called. -- (void) resetCursorRects { - //[super resetCursorRects]; - //[self addCursorRect: [self bounds] cursor: [NSCursor arrowCursor]]; -} - -@end - -void ScintillaCocoa::CallTipMouseDown(NSPoint pt) { - NSRect rectBounds = [(NSView *)(ct.wDraw.GetID()) bounds]; - Point location(pt.x, rectBounds.size.height - pt.y); - ct.MouseClick(location); - CallTipClick(); -} - -void ScintillaCocoa::CreateCallTipWindow(PRectangle rc) { - if (!ct.wCallTip.Created()) { - NSRect ctRect = NSMakeRect(rc.top,rc.bottom, rc.Width(), rc.Height()); - NSWindow *callTip = [[NSWindow alloc] initWithContentRect: ctRect - styleMask: NSBorderlessWindowMask - backing: NSBackingStoreBuffered - defer: NO]; - [callTip setLevel:NSFloatingWindowLevel]; - [callTip setHasShadow:YES]; - NSRect ctContent = NSMakeRect(0,0, rc.Width(), rc.Height()); - CallTipView *caption = [[CallTipView alloc] initWithFrame: ctContent]; - [caption setAutoresizingMask: NSViewWidthSizable | NSViewMaxYMargin]; - [caption setSci: this]; - [[callTip contentView] addSubview: caption]; - [callTip orderFront:caption]; - ct.wCallTip = callTip; - ct.wDraw = caption; - } -} - -void ScintillaCocoa::AddToPopUp(const char *label, int cmd, bool enabled) -{ - NSMenuItem* item; - ScintillaContextMenu *menu= reinterpret_cast(popup.GetID()); - [menu setOwner: this]; - [menu setAutoenablesItems: NO]; - - if (cmd == 0) { - item = [NSMenuItem separatorItem]; - } else { - item = [[[NSMenuItem alloc] init] autorelease]; - [item setTitle: [NSString stringWithUTF8String: label]]; - } - [item setTarget: menu]; - [item setAction: @selector(handleCommand:)]; - [item setTag: cmd]; - [item setEnabled: enabled]; - - [menu addItem: item]; -} - -// ------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::ClaimSelection() -{ - // Mac OS X does not have a primary selection. -} - -// ------------------------------------------------------------------------------------------------- - -/** - * Returns the current caret position (which is tracked as an offset into the entire text string) - * as a row:column pair. The result is zero-based. - */ -NSPoint ScintillaCocoa::GetCaretPosition() -{ - NSPoint result; - - result.y = pdoc->LineFromPosition(sel.RangeMain().caret.Position()); - result.x = sel.RangeMain().caret.Position() - pdoc->LineStart(result.y); - return result; -} - -// ------------------------------------------------------------------------------------------------- - -#pragma mark Drag - -/** - * Triggered by the tick timer on a regular basis to scroll the content during a drag operation. - */ -void ScintillaCocoa::DragScroll() -{ - if (!posDrag.IsValid()) - { - scrollSpeed = 1; - scrollTicks = 2000; - return; - } - - // TODO: does not work for wrapped lines, fix it. - int line = pdoc->LineFromPosition(posDrag.Position()); - int currentVisibleLine = cs.DisplayFromDoc(line); - int lastVisibleLine = Platform::Minimum(topLine + LinesOnScreen(), cs.LinesDisplayed()) - 2; - - if (currentVisibleLine <= topLine && topLine > 0) - ScrollTo(topLine - scrollSpeed); - else - if (currentVisibleLine >= lastVisibleLine) - ScrollTo(topLine + scrollSpeed); - else - { - scrollSpeed = 1; - scrollTicks = 2000; - return; - } - - // TODO: also handle horizontal scrolling. - - if (scrollSpeed == 1) - { - scrollTicks -= timer.tickSize; - if (scrollTicks <= 0) - { - scrollSpeed = 5; - scrollTicks = 2000; - } - } - -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called when a drag operation was initiated from within Scintilla. - */ -void ScintillaCocoa::StartDrag() -{ - if (sel.Empty()) - return; - - // Put the data to be dragged on the drag pasteboard. - SelectionText selectedText; - NSPasteboard* pasteboard = [NSPasteboard pasteboardWithName: NSDragPboard]; - CopySelectionRange(&selectedText); - SetPasteboardData(pasteboard, selectedText); - - // calculate the bounds of the selection - PRectangle client = GetTextRectangle(); - int selStart = sel.RangeMain().Start().Position(); - int selEnd = sel.RangeMain().End().Position(); - int startLine = pdoc->LineFromPosition(selStart); - int endLine = pdoc->LineFromPosition(selEnd); - Point pt; - long startPos, endPos, ep; - Rect rcSel; - - if (startLine==endLine && WndProc(SCI_GETWRAPMODE, 0, 0) != SC_WRAP_NONE) { - // Komodo bug http://bugs.activestate.com/show_bug.cgi?id=87571 - // Scintilla bug https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3040200&group_id=2439 - // If the width on a wrapped-line selection is negative, - // find a better bounding rectangle. - - Point ptStart, ptEnd; - startPos = WndProc(SCI_GETLINESELSTARTPOSITION, startLine, 0); - endPos = WndProc(SCI_GETLINESELENDPOSITION, startLine, 0); - // step back a position if we're counting the newline - ep = WndProc(SCI_GETLINEENDPOSITION, startLine, 0); - if (endPos > ep) endPos = ep; - ptStart = LocationFromPosition(static_cast(startPos)); - ptEnd = LocationFromPosition(static_cast(endPos)); - if (ptStart.y == ptEnd.y) { - // We're just selecting part of one visible line - rcSel.left = ptStart.x; - rcSel.right = ptEnd.x < client.right ? ptEnd.x : client.right; - } else { - // Find the bounding box. - startPos = WndProc(SCI_POSITIONFROMLINE, startLine, 0); - rcSel.left = LocationFromPosition(static_cast(startPos)).x; - rcSel.right = client.right; - } - rcSel.top = ptStart.y; - rcSel.bottom = ptEnd.y + vs.lineHeight; - if (rcSel.bottom > client.bottom) { - rcSel.bottom = client.bottom; - } - } else { - rcSel.top = rcSel.bottom = rcSel.right = rcSel.left = -1; - for (int l = startLine; l <= endLine; l++) { - startPos = WndProc(SCI_GETLINESELSTARTPOSITION, l, 0); - endPos = WndProc(SCI_GETLINESELENDPOSITION, l, 0); - if (endPos == startPos) continue; - // step back a position if we're counting the newline - ep = WndProc(SCI_GETLINEENDPOSITION, l, 0); - if (endPos > ep) endPos = ep; - pt = LocationFromPosition(static_cast(startPos)); // top left of line selection - if (pt.x < rcSel.left || rcSel.left < 0) rcSel.left = pt.x; - if (pt.y < rcSel.top || rcSel.top < 0) rcSel.top = pt.y; - pt = LocationFromPosition(static_cast(endPos)); // top right of line selection - pt.y += vs.lineHeight; // get to the bottom of the line - if (pt.x > rcSel.right || rcSel.right < 0) { - if (pt.x > client.right) - rcSel.right = client.right; - else - rcSel.right = pt.x; - } - if (pt.y > rcSel.bottom || rcSel.bottom < 0) { - if (pt.y > client.bottom) - rcSel.bottom = client.bottom; - else - rcSel.bottom = pt.y; - } - } - } - // must convert to global coordinates for drag regions, but also save the - // image rectangle for further calculations and copy operations - PRectangle localRectangle = PRectangle(rcSel.left, rcSel.top, rcSel.right, rcSel.bottom); - - // Prepare drag image. - NSRect selectionRectangle = PRectangleToNSRect(localRectangle); - - NSView* content = ContentView(); - -#if 1 - - // To get a bitmap of the text we're dragging, we just use Paint on a pixmap surface. - SurfaceImpl *sw = new SurfaceImpl(); - SurfaceImpl *pixmap = NULL; - - bool lastHideSelection = hideSelection; - hideSelection = true; - if (sw) - { - pixmap = new SurfaceImpl(); - if (pixmap) - { - PRectangle imageRect = NSRectToPRectangle(selectionRectangle); - paintState = painting; - sw->InitPixMap(client.Width(), client.Height(), NULL, NULL); - paintingAllText = true; - // Have to create a new context and make current as text drawing goes - // to the current context, not a passed context. - CGContextRef gcsw = sw->GetContext(); - NSGraphicsContext *nsgc = [NSGraphicsContext graphicsContextWithGraphicsPort: gcsw - flipped: YES]; - [NSGraphicsContext setCurrentContext:nsgc]; - Paint(sw, client); - paintState = notPainting; - - pixmap->InitPixMap(imageRect.Width(), imageRect.Height(), NULL, NULL); - - CGContextRef gc = pixmap->GetContext(); - // To make Paint() work on a bitmap, we have to flip our coordinates and translate the origin - CGContextTranslateCTM(gc, 0, imageRect.Height()); - CGContextScaleCTM(gc, 1.0, -1.0); - - pixmap->CopyImageRectangle(*sw, imageRect, PRectangle(0, 0, imageRect.Width(), imageRect.Height())); - // XXX TODO: overwrite any part of the image that is not part of the - // selection to make it transparent. right now we just use - // the full rectangle which may include non-selected text. - } - sw->Release(); - delete sw; - } - hideSelection = lastHideSelection; - - NSBitmapImageRep* bitmap = NULL; - if (pixmap) - { - CGImageRef imagePixmap = pixmap->GetImage(); - bitmap = [[[NSBitmapImageRep alloc] initWithCGImage: imagePixmap] autorelease]; - CGImageRelease(imagePixmap); - pixmap->Release(); - delete pixmap; - } -#else - - // Poor man's drag image: take a snapshot of the content view. - [content lockFocus]; - NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: selectionRectangle] autorelease]; - [bitmap setColorSpaceName: NSDeviceRGBColorSpace]; - [content unlockFocus]; - -#endif - - NSImage* image = [[[NSImage alloc] initWithSize: selectionRectangle.size] autorelease]; - [image addRepresentation: bitmap]; - - NSImage* dragImage = [[[NSImage alloc] initWithSize: selectionRectangle.size] autorelease]; - [dragImage setBackgroundColor: [NSColor clearColor]]; - [dragImage lockFocus]; - [image dissolveToPoint: NSMakePoint(0.0, 0.0) fraction: 0.5]; - [dragImage unlockFocus]; - - NSPoint startPoint; - startPoint.x = selectionRectangle.origin.x; - startPoint.y = selectionRectangle.origin.y + selectionRectangle.size.height; - [content dragImage: dragImage - at: startPoint - offset: NSZeroSize - event: lastMouseEvent // Set in MouseMove. - pasteboard: pasteboard - source: content - slideBack: YES]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called when a drag operation reaches the control which was initiated outside. - */ -NSDragOperation ScintillaCocoa::DraggingEntered(id info) -{ - inDragDrop = ddDragging; - return DraggingUpdated(info); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called frequently during a drag operation if we are the target. Keep telling the caller - * what drag operation we accept and update the drop caret position to indicate the - * potential insertion point of the dragged data. - */ -NSDragOperation ScintillaCocoa::DraggingUpdated(id info) -{ - // Convert the drag location from window coordinates to view coordinates and - // from there to a text position to finally set the drag position. - Point location = ConvertPoint([info draggingLocation]); - SetDragPosition(SPositionFromLocation(location)); - - NSDragOperation sourceDragMask = [info draggingSourceOperationMask]; - if (sourceDragMask == NSDragOperationNone) - return sourceDragMask; - - NSPasteboard* pasteboard = [info draggingPasteboard]; - - // Return what type of operation we will perform. Prefer move over copy. - if ([[pasteboard types] containsObject: NSStringPboardType] || - [[pasteboard types] containsObject: ScintillaRecPboardType]) - return (sourceDragMask & NSDragOperationMove) ? NSDragOperationMove : NSDragOperationCopy; - - if ([[pasteboard types] containsObject: NSFilenamesPboardType]) - return (sourceDragMask & NSDragOperationGeneric); - return NSDragOperationNone; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Resets the current drag position as we are no longer the drag target. - */ -void ScintillaCocoa::DraggingExited(id info) -{ -#pragma unused(info) - SetDragPosition(SelectionPosition(invalidPosition)); - inDragDrop = ddNone; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Here is where the real work is done. Insert the text from the pasteboard. - */ -bool ScintillaCocoa::PerformDragOperation(id info) -{ - NSPasteboard* pasteboard = [info draggingPasteboard]; - - if ([[pasteboard types] containsObject: NSFilenamesPboardType]) - { - NSArray* files = [pasteboard propertyListForType: NSFilenamesPboardType]; - for (NSString* uri in files) - NotifyURIDropped([uri UTF8String]); - } - else - { - SelectionText text; - GetPasteboardData(pasteboard, &text); - - if (text.len > 0) - { - NSDragOperation operation = [info draggingSourceOperationMask]; - bool moving = (operation & NSDragOperationMove) != 0; - - DropAt(posDrag, text.s, moving, text.rectangular); - }; - } - - return true; -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::SetPasteboardData(NSPasteboard* board, const SelectionText &selectedText) -{ - if (selectedText.len == 0) - return; - - CFStringEncoding encoding = EncodingFromCharacterSet(selectedText.codePage == SC_CP_UTF8, - selectedText.characterSet); - CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault, - reinterpret_cast(selectedText.s), - selectedText.len-1, encoding, false); - - [board declareTypes:[NSArray arrayWithObjects: - NSStringPboardType, - selectedText.rectangular ? ScintillaRecPboardType : nil, - nil] owner:nil]; - - if (selectedText.rectangular) - { - // This is specific to scintilla, allows us to drag rectangular selections around the document. - [board setString: (NSString *)cfsVal forType: ScintillaRecPboardType]; - } - - [board setString: (NSString *)cfsVal forType: NSStringPboardType]; - - CFRelease(cfsVal); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Helper method to retrieve the best fitting alternative from the general pasteboard. - */ -bool ScintillaCocoa::GetPasteboardData(NSPasteboard* board, SelectionText* selectedText) -{ - NSArray* supportedTypes = [NSArray arrayWithObjects: ScintillaRecPboardType, - NSStringPboardType, - nil]; - NSString *bestType = [board availableTypeFromArray: supportedTypes]; - NSString* data = [board stringForType: bestType]; - - if (data != nil) - { - if (selectedText != nil) - { - CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(), - vs.styles[STYLE_DEFAULT].characterSet); - CFRange rangeAll = {0, [data length]}; - CFIndex usedLen = 0; - CFStringGetBytes((CFStringRef)data, rangeAll, encoding, '?', - false, NULL, 0, &usedLen); - - UInt8 *buffer = new UInt8[usedLen]; - - CFStringGetBytes((CFStringRef)data, rangeAll, encoding, '?', - false, buffer,usedLen, NULL); - - bool rectangular = bestType == ScintillaRecPboardType; - - int len = static_cast(usedLen); - char *dest = Document::TransformLineEnds(&len, (char *)buffer, len, pdoc->eolMode); - - selectedText->Set(dest, len+1, pdoc->dbcsCodePage, - vs.styles[STYLE_DEFAULT].characterSet , rectangular, false); - delete []buffer; - } - return true; - } - - return false; -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::SetMouseCapture(bool on) -{ - capturedMouse = on; - /* - if (mouseDownCaptures) - { - if (capturedMouse) - WndProc(SCI_SETCURSOR, Window::cursorArrow, 0); - else - // Reset to normal. Actual image will be set on mouse move. - WndProc(SCI_SETCURSOR, (unsigned int) SC_CURSORNORMAL, 0); - } - */ -} - -//-------------------------------------------------------------------------------------------------- - -bool ScintillaCocoa::HaveMouseCapture() -{ - return capturedMouse; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Synchronously paint a rectangle of the window. - */ -void ScintillaCocoa::SyncPaint(void* gc, PRectangle rc) -{ - paintState = painting; - rcPaint = rc; - PRectangle rcText = GetTextRectangle(); - paintingAllText = rcPaint.Contains(rcText); - Surface *sw = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); - if (sw) - { - sw->Init(gc, wMain.GetID()); - Paint(sw, rc); - if (paintState == paintAbandoned) - { - // Do a full paint. - rcPaint = GetClientRectangle(); - paintState = painting; - paintingAllText = true; - Paint(sw, rcPaint); - } - sw->Release(); - delete sw; - } - paintState = notPainting; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Scrolls the pixels in the window some number of lines. - * Invalidates the pixels scrolled into view. - */ -void ScintillaCocoa::ScrollText(int linesToMove) -{ - // Move those pixels - NSView *content = ContentView(); - - [content lockFocus]; - int diff = vs.lineHeight * linesToMove; - PRectangle textRect = GetTextRectangle(); - // Include margins as they must scroll - textRect.left = 0; - NSRect textRectangle = PRectangleToNSRect(textRect); - NSPoint destPoint = textRectangle.origin; - destPoint.y += diff; - NSCopyBits(0, textRectangle, destPoint); - - // Paint them nice - NSRect redrawRectangle = textRectangle; - if (linesToMove < 0) { - // Repaint bottom - redrawRectangle.origin.y = redrawRectangle.origin.y + redrawRectangle.size.height + diff; - redrawRectangle.size.height = -diff; - } else { - // Repaint top - redrawRectangle.size.height = diff; - } - - [content drawRect: redrawRectangle]; - [content unlockFocus]; - - // If no flush done here then multiple scrolls will get buffered and screen - // will only update a few times a second. - //[[content window] flushWindow]; - // However, doing the flush leads to the caret updating as a separate operation - // which looks bad when scrolling by holding down the down arrow key. - - // Could invalidate instead of synchronous draw but that may not be as smooth - //[content setNeedsDisplayInRect: redrawRectangle]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Modfies the vertical scroll position to make the current top line show up as such. - */ -void ScintillaCocoa::SetVerticalScrollPos() -{ - ScintillaView* topContainer = TopContainer(); - - // Convert absolute coordinate into the range [0..1]. Keep in mind that the visible area - // does *not* belong to the scroll range. - float relativePosition = (float) topLine / MaxScrollPos(); - [topContainer setVerticalScrollPosition: relativePosition]; -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::SetHorizontalScrollPos() -{ - ScintillaView* topContainer = TopContainer(); - PRectangle textRect = GetTextRectangle(); - - // Convert absolute coordinate into the range [0..1]. Keep in mind that the visible area - // does *not* belong to the scroll range. - float relativePosition = (float) xOffset / (scrollWidth - textRect.Width()); - [topContainer setHorizontalScrollPosition: relativePosition]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Used to adjust both scrollers to reflect the current scroll range and position in the editor. - * - * @param nMax Number of lines in the editor. - * @param nPage Number of lines per scroll page. - * @return True if there was a change, otherwise false. - */ -bool ScintillaCocoa::ModifyScrollBars(int nMax, int nPage) -{ -#pragma unused(nPage) - // Input values are given in lines, not pixels, so we have to convert. - int lineHeight = static_cast(WndProc(SCI_TEXTHEIGHT, 0, 0)); - PRectangle bounds = GetTextRectangle(); - ScintillaView* topContainer = TopContainer(); - - // Set page size to the same value as the scroll range to hide the scrollbar. - int scrollRange = lineHeight * (nMax + 1); // +1 because the caller subtracted one. - int pageSize; - if (verticalScrollBarVisible) - pageSize = bounds.Height(); - else - pageSize = scrollRange; - bool verticalChange = [topContainer setVerticalScrollRange: scrollRange page: pageSize]; - - scrollRange = scrollWidth; - if (horizontalScrollBarVisible) - pageSize = bounds.Width(); - else - pageSize = scrollRange; - bool horizontalChange = [topContainer setHorizontalScrollRange: scrollRange page: pageSize]; - - return verticalChange || horizontalChange; -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::Resize() -{ - ChangeSize(); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called by the frontend control when the user manipulates one of the scrollers. - * - * @param position The relative position of the scroller in the range of [0..1]. - * @param part Specifies which part was clicked on by the user, so we can handle thumb tracking - * as well as page and line scrolling. - * @param horizontal True if the horizontal scroller was hit, otherwise false. - */ -void ScintillaCocoa::DoScroll(float position, NSScrollerPart part, bool horizontal) -{ - // If the given scroller part is not the knob (or knob slot) then the given position is not yet - // current and we have to update it. - if (horizontal) - { - // Horizontal offset is given in pixels. - PRectangle textRect = GetTextRectangle(); - int offset = (int) (position * (scrollWidth - textRect.Width())); - int smallChange = (int) (textRect.Width() / 30); - if (smallChange < 5) - smallChange = 5; - switch (part) - { - case NSScrollerDecrementLine: - offset -= smallChange; - break; - case NSScrollerDecrementPage: - offset -= textRect.Width(); - break; - case NSScrollerIncrementLine: - offset += smallChange; - break; - case NSScrollerIncrementPage: - offset += textRect.Width(); - break; - }; - HorizontalScrollTo(offset); - } - else - { - // VerticalScrolling is by line. If the user is scrolling using the knob we can directly - // set the new scroll position. Otherwise we have to compute it first. - if (part == NSScrollerKnob) - ScrollTo(position * MaxScrollPos(), false); - else - { - switch (part) - { - case NSScrollerDecrementLine: - ScrollTo(topLine - 1, true); - break; - case NSScrollerDecrementPage: - ScrollTo(topLine - LinesOnScreen(), true); - break; - case NSScrollerIncrementLine: - ScrollTo(topLine + 1, true); - break; - case NSScrollerIncrementPage: - ScrollTo(topLine + LinesOnScreen(), true); - break; - }; - - } - } -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Used to register a callback function for a given window. This is used to emulate the way - * Windows notfies other controls (mainly up in the view hierarchy) about certain events. - * - * @param windowid A handle to a window. That value is generic and can be anything. It is passed - * through to the callback. - * @param callback The callback function to be used for future notifications. If NULL then no - * notifications will be sent anymore. - */ -void ScintillaCocoa::RegisterNotifyCallback(intptr_t windowid, SciNotifyFunc callback) -{ - notifyObj = windowid; - notifyProc = callback; -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::NotifyChange() -{ - if (notifyProc != NULL) - notifyProc(notifyObj, WM_COMMAND, Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE), - (uintptr_t) this); -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::NotifyFocus(bool focus) -{ - if (notifyProc != NULL) - notifyProc(notifyObj, WM_COMMAND, Platform::LongFromTwoShorts(GetCtrlID(), (focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS)), - (uintptr_t) this); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Used to send a notification (as WM_NOTIFY call) to the procedure, which has been set by the call - * to RegisterNotifyCallback (so it is not necessarily the parent window). - * - * @param scn The notification to send. - */ -void ScintillaCocoa::NotifyParent(SCNotification scn) -{ - if (notifyProc != NULL) - { - scn.nmhdr.hwndFrom = (void*) this; - scn.nmhdr.idFrom = GetCtrlID(); - notifyProc(notifyObj, WM_NOTIFY, (uintptr_t) 0, (uintptr_t) &scn); - } -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::NotifyURIDropped(const char *uri) -{ - SCNotification scn; - scn.nmhdr.code = SCN_URIDROPPED; - scn.text = uri; - - NotifyParent(scn); -} - -//-------------------------------------------------------------------------------------------------- - -bool ScintillaCocoa::HasSelection() -{ - return !sel.Empty(); -} - -//-------------------------------------------------------------------------------------------------- - -bool ScintillaCocoa::CanUndo() -{ - return pdoc->CanUndo(); -} - -//-------------------------------------------------------------------------------------------------- - -bool ScintillaCocoa::CanRedo() -{ - return pdoc->CanRedo(); -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::TimerFired(NSTimer* timer) -{ -#pragma unused(timer) - Tick(); - DragScroll(); -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::IdleTimerFired() -{ - bool more = Idle(); - if (!more) - SetIdle(false); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Main entry point for drawing the control. - * - * @param rect The area to paint, given in the sender's coordinate system. - * @param gc The context we can use to paint. - */ -void ScintillaCocoa::Draw(NSRect rect, CGContextRef gc) -{ - SyncPaint(gc, NSRectToPRectangle(rect)); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Helper function to translate OS X key codes to Scintilla key codes. - */ -static inline UniChar KeyTranslate(UniChar unicodeChar) -{ - switch (unicodeChar) - { - case NSDownArrowFunctionKey: - return SCK_DOWN; - case NSUpArrowFunctionKey: - return SCK_UP; - case NSLeftArrowFunctionKey: - return SCK_LEFT; - case NSRightArrowFunctionKey: - return SCK_RIGHT; - case NSHomeFunctionKey: - return SCK_HOME; - case NSEndFunctionKey: - return SCK_END; - case NSPageUpFunctionKey: - return SCK_PRIOR; - case NSPageDownFunctionKey: - return SCK_NEXT; - case NSDeleteFunctionKey: - return SCK_DELETE; - case NSInsertFunctionKey: - return SCK_INSERT; - case '\n': - case 3: - return SCK_RETURN; - case 27: - return SCK_ESCAPE; - case 127: - return SCK_BACK; - case '\t': - case 25: // Shift tab, return to unmodified tab and handle that via modifiers. - return SCK_TAB; - default: - return unicodeChar; - } -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Main keyboard input handling method. It is called for any key down event, including function keys, - * numeric keypad input and whatnot. - * - * @param event The event instance associated with the key down event. - * @return True if the input was handled, false otherwise. - */ -bool ScintillaCocoa::KeyboardInput(NSEvent* event) -{ - // For now filter out function keys. - NSUInteger modifiers = [event modifierFlags]; - - NSString* input = [event characters]; - - bool control = (modifiers & NSControlKeyMask) != 0; - bool shift = (modifiers & NSShiftKeyMask) != 0; - bool command = (modifiers & NSCommandKeyMask) != 0; - bool alt = (modifiers & NSAlternateKeyMask) != 0; - - bool handled = false; - - // Handle each entry individually. Usually we only have one entry anway. - for (size_t i = 0; i < input.length; i++) - { - const UniChar originalKey = [input characterAtIndex: i]; - UniChar key = KeyTranslate(originalKey); - - bool consumed = false; // Consumed as command? - - // Signal Control as SCMOD_META - int modifierKeys = - (shift ? SCI_SHIFT : 0) | - (command ? SCI_CTRL : 0) | - (alt ? SCI_ALT : 0) | - (control ? SCI_META : 0); - if (KeyDownWithModifiers(key, modifierKeys, &consumed)) - handled = true; - if (consumed) - handled = true; - } - - return handled; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Used to insert already processed text provided by the Cocoa text input system. - */ -int ScintillaCocoa::InsertText(NSString* input) -{ - CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(), - vs.styles[STYLE_DEFAULT].characterSet); - CFRange rangeAll = {0, [input length]}; - CFIndex usedLen = 0; - CFStringGetBytes((CFStringRef)input, rangeAll, encoding, '?', - false, NULL, 0, &usedLen); - - UInt8 *buffer = new UInt8[usedLen]; - - CFStringGetBytes((CFStringRef)input, rangeAll, encoding, '?', - false, buffer,usedLen, NULL); - - AddCharUTF((char*) buffer, static_cast(usedLen), false); - delete []buffer; - return static_cast(usedLen); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called by the owning view when the mouse pointer enters the control. - */ -void ScintillaCocoa::MouseEntered(NSEvent* event) -{ - if (!HaveMouseCapture()) - { - WndProc(SCI_SETCURSOR, (long int)SC_CURSORNORMAL, 0); - - // Mouse location is given in screen coordinates and might also be outside of our bounds. - Point location = ConvertPoint([event locationInWindow]); - ButtonMove(location); - } -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::MouseExited(NSEvent* /* event */) -{ - // Nothing to do here. -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::MouseDown(NSEvent* event) -{ - Point location = ConvertPoint([event locationInWindow]); - NSTimeInterval time = [event timestamp]; - bool command = ([event modifierFlags] & NSCommandKeyMask) != 0; - bool shift = ([event modifierFlags] & NSShiftKeyMask) != 0; - bool alt = ([event modifierFlags] & NSAlternateKeyMask) != 0; - - ButtonDown(Point(location.x, location.y), (int) (time * 1000), shift, command, alt); -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::MouseMove(NSEvent* event) -{ - lastMouseEvent = event; - - ButtonMove(ConvertPoint([event locationInWindow])); -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::MouseUp(NSEvent* event) -{ - NSTimeInterval time = [event timestamp]; - bool control = ([event modifierFlags] & NSControlKeyMask) != 0; - - ButtonUp(ConvertPoint([event locationInWindow]), (int) (time * 1000), control); -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::MouseWheel(NSEvent* event) -{ - bool command = ([event modifierFlags] & NSCommandKeyMask) != 0; - int dX = 0; - int dY = 0; - - dX = 10 * [event deltaX]; // Arbitrary scale factor. - - // In order to make scrolling with larger offset smoother we scroll less lines the larger the - // delta value is. - if ([event deltaY] < 0) - dY = -(int) sqrt(-10.0 * [event deltaY]); - else - dY = (int) sqrt(10.0 * [event deltaY]); - - if (command) - { - // Zoom! We play with the font sizes in the styles. - // Number of steps/line is ignored, we just care if sizing up or down. - if (dY > 0.5) - KeyCommand(SCI_ZOOMIN); - else if (dY < -0.5) - KeyCommand(SCI_ZOOMOUT); - } - else - { - HorizontalScrollTo(xOffset - dX); - ScrollTo(topLine - dY, true); - } -} - -//-------------------------------------------------------------------------------------------------- - -// Helper methods for NSResponder actions. - -void ScintillaCocoa::SelectAll() -{ - Editor::SelectAll(); -} - -void ScintillaCocoa::DeleteBackward() -{ - KeyDown(SCK_BACK, false, false, false, nil); -} - -void ScintillaCocoa::Cut() -{ - Editor::Cut(); -} - -void ScintillaCocoa::Undo() -{ - Editor::Undo(); -} - -void ScintillaCocoa::Redo() -{ - Editor::Redo(); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Creates and returns a popup menu, which is then displayed by the Cocoa framework. - */ -NSMenu* ScintillaCocoa::CreateContextMenu(NSEvent* /* event */) -{ - // Call ScintillaBase to create the context menu. - ContextMenu(Point(0, 0)); - - return reinterpret_cast(popup.GetID()); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * An intermediate function to forward context menu commands from the menu action handler to - * scintilla. - */ -void ScintillaCocoa::HandleCommand(NSInteger command) -{ - Command(static_cast(command)); -} - -//-------------------------------------------------------------------------------------------------- - -void ScintillaCocoa::ActiveStateChanged(bool isActive) -{ - // If the window is being deactivated, lose the focus and turn off the ticking - if (!isActive) { - DropCaret(); - //SetFocusState( false ); - SetTicking( false ); - } else { - ShowCaretAtCurrentPosition(); - } -} - - -//-------------------------------------------------------------------------------------------------- - + +/** + * Scintilla source code edit control + * ScintillaCocoa.mm - Cocoa subclass of ScintillaBase + * + * Written by Mike Lischke + * + * Loosely based on ScintillaMacOSX.cxx. + * Copyright 2003 by Evan Jones + * Based on ScintillaGTK.cxx Copyright 1998-2002 by Neil Hodgson + * The License.txt file describes the conditions under which this software may be distributed. + * + * Copyright (c) 2009, 2010 Sun Microsystems, Inc. All rights reserved. + * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). + */ + +#import + +#import // Temporary + +#include "ScintillaView.h" +#include "PlatCocoa.h" + +using namespace Scintilla; + +#ifndef WM_UNICHAR +#define WM_UNICHAR 0x0109 +#endif + +NSString* ScintillaRecPboardType = @"com.scintilla.utf16-plain-text.rectangular"; + +//-------------------------------------------------------------------------------------------------- + +// Define keyboard shortcuts (equivalents) the Mac way. +#define SCI_CMD ( SCI_CTRL) +#define SCI_SCMD ( SCI_CMD | SCI_SHIFT) +#define SCI_SMETA ( SCI_META | SCI_SHIFT) + +static const KeyToCommand macMapDefault[] = +{ + // OS X specific + {SCK_DOWN, SCI_CTRL, SCI_DOCUMENTEND}, + {SCK_DOWN, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND}, + {SCK_UP, SCI_CTRL, SCI_DOCUMENTSTART}, + {SCK_UP, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND}, + {SCK_LEFT, SCI_CTRL, SCI_VCHOME}, + {SCK_LEFT, SCI_CSHIFT, SCI_VCHOMEEXTEND}, + {SCK_RIGHT, SCI_CTRL, SCI_LINEEND}, + {SCK_RIGHT, SCI_CSHIFT, SCI_LINEENDEXTEND}, + + // Similar to Windows and GTK+ + // Where equivalent clashes with OS X standard, use Meta instead + {SCK_DOWN, SCI_NORM, SCI_LINEDOWN}, + {SCK_DOWN, SCI_SHIFT, SCI_LINEDOWNEXTEND}, + {SCK_DOWN, SCI_META, SCI_LINESCROLLDOWN}, + {SCK_DOWN, SCI_ASHIFT, SCI_LINEDOWNRECTEXTEND}, + {SCK_UP, SCI_NORM, SCI_LINEUP}, + {SCK_UP, SCI_SHIFT, SCI_LINEUPEXTEND}, + {SCK_UP, SCI_META, SCI_LINESCROLLUP}, + {SCK_UP, SCI_ASHIFT, SCI_LINEUPRECTEXTEND}, + {'[', SCI_CTRL, SCI_PARAUP}, + {'[', SCI_CSHIFT, SCI_PARAUPEXTEND}, + {']', SCI_CTRL, SCI_PARADOWN}, + {']', SCI_CSHIFT, SCI_PARADOWNEXTEND}, + {SCK_LEFT, SCI_NORM, SCI_CHARLEFT}, + {SCK_LEFT, SCI_SHIFT, SCI_CHARLEFTEXTEND}, + {SCK_LEFT, SCI_ALT, SCI_WORDLEFT}, + {SCK_LEFT, SCI_META, SCI_WORDLEFT}, + {SCK_LEFT, SCI_SMETA, SCI_WORDLEFTEXTEND}, + {SCK_LEFT, SCI_ASHIFT, SCI_CHARLEFTRECTEXTEND}, + {SCK_RIGHT, SCI_NORM, SCI_CHARRIGHT}, + {SCK_RIGHT, SCI_SHIFT, SCI_CHARRIGHTEXTEND}, + {SCK_RIGHT, SCI_ALT, SCI_WORDRIGHT}, + {SCK_RIGHT, SCI_META, SCI_WORDRIGHT}, + {SCK_RIGHT, SCI_SMETA, SCI_WORDRIGHTEXTEND}, + {SCK_RIGHT, SCI_ASHIFT, SCI_CHARRIGHTRECTEXTEND}, + {'/', SCI_CTRL, SCI_WORDPARTLEFT}, + {'/', SCI_CSHIFT, SCI_WORDPARTLEFTEXTEND}, + {'\\', SCI_CTRL, SCI_WORDPARTRIGHT}, + {'\\', SCI_CSHIFT, SCI_WORDPARTRIGHTEXTEND}, + {SCK_HOME, SCI_NORM, SCI_VCHOME}, + {SCK_HOME, SCI_SHIFT, SCI_VCHOMEEXTEND}, + {SCK_HOME, SCI_CTRL, SCI_DOCUMENTSTART}, + {SCK_HOME, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND}, + {SCK_HOME, SCI_ALT, SCI_HOMEDISPLAY}, + {SCK_HOME, SCI_ASHIFT, SCI_VCHOMERECTEXTEND}, + {SCK_END, SCI_NORM, SCI_LINEEND}, + {SCK_END, SCI_SHIFT, SCI_LINEENDEXTEND}, + {SCK_END, SCI_CTRL, SCI_DOCUMENTEND}, + {SCK_END, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND}, + {SCK_END, SCI_ALT, SCI_LINEENDDISPLAY}, + {SCK_END, SCI_ASHIFT, SCI_LINEENDRECTEXTEND}, + {SCK_PRIOR, SCI_NORM, SCI_PAGEUP}, + {SCK_PRIOR, SCI_SHIFT, SCI_PAGEUPEXTEND}, + {SCK_PRIOR, SCI_ASHIFT, SCI_PAGEUPRECTEXTEND}, + {SCK_NEXT, SCI_NORM, SCI_PAGEDOWN}, + {SCK_NEXT, SCI_SHIFT, SCI_PAGEDOWNEXTEND}, + {SCK_NEXT, SCI_ASHIFT, SCI_PAGEDOWNRECTEXTEND}, + {SCK_DELETE, SCI_NORM, SCI_CLEAR}, + {SCK_DELETE, SCI_SHIFT, SCI_CUT}, + {SCK_DELETE, SCI_CTRL, SCI_DELWORDRIGHT}, + {SCK_DELETE, SCI_CSHIFT, SCI_DELLINERIGHT}, + {SCK_INSERT, SCI_NORM, SCI_EDITTOGGLEOVERTYPE}, + {SCK_INSERT, SCI_SHIFT, SCI_PASTE}, + {SCK_INSERT, SCI_CTRL, SCI_COPY}, + {SCK_ESCAPE, SCI_NORM, SCI_CANCEL}, + {SCK_BACK, SCI_NORM, SCI_DELETEBACK}, + {SCK_BACK, SCI_SHIFT, SCI_DELETEBACK}, + {SCK_BACK, SCI_CTRL, SCI_DELWORDLEFT}, + {SCK_BACK, SCI_ALT, SCI_UNDO}, + {SCK_BACK, SCI_CSHIFT, SCI_DELLINELEFT}, + {'z', SCI_CMD, SCI_UNDO}, + {'z', SCI_SCMD, SCI_REDO}, + {'x', SCI_CMD, SCI_CUT}, + {'c', SCI_CMD, SCI_COPY}, + {'v', SCI_CMD, SCI_PASTE}, + {'a', SCI_CMD, SCI_SELECTALL}, + {SCK_TAB, SCI_NORM, SCI_TAB}, + {SCK_TAB, SCI_SHIFT, SCI_BACKTAB}, + {SCK_RETURN, SCI_NORM, SCI_NEWLINE}, + {SCK_RETURN, SCI_SHIFT, SCI_NEWLINE}, + {SCK_ADD, SCI_CMD, SCI_ZOOMIN}, + {SCK_SUBTRACT, SCI_CMD, SCI_ZOOMOUT}, + {SCK_DIVIDE, SCI_CMD, SCI_SETZOOM}, + {'l', SCI_CMD, SCI_LINECUT}, + {'l', SCI_CSHIFT, SCI_LINEDELETE}, + {'t', SCI_CSHIFT, SCI_LINECOPY}, + {'t', SCI_CTRL, SCI_LINETRANSPOSE}, + {'d', SCI_CTRL, SCI_SELECTIONDUPLICATE}, + {'u', SCI_CTRL, SCI_LOWERCASE}, + {'u', SCI_CSHIFT, SCI_UPPERCASE}, + {0, 0, 0}, +}; + +//-------------------------------------------------------------------------------------------------- + +@implementation TimerTarget + +- (id) init: (void*) target +{ + self = [super init]; + if (self != nil) + { + mTarget = target; + + // Get the default notification queue for the thread which created the instance (usually the + // main thread). We need that later for idle event processing. + NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; + notificationQueue = [[NSNotificationQueue alloc] initWithNotificationCenter: center]; + [center addObserver: self selector: @selector(idleTriggered:) name: @"Idle" object: nil]; + } + return self; +} + +//-------------------------------------------------------------------------------------------------- + +- (void) dealloc +{ + [notificationQueue release]; + [super dealloc]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Method called by a timer installed by ScintillaCocoa. This two step approach is needed because + * a native Obj-C class is required as target for the timer. + */ +- (void) timerFired: (NSTimer*) timer +{ + reinterpret_cast(mTarget)->TimerFired(timer); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Another timer callback for the idle timer. + */ +- (void) idleTimerFired: (NSTimer*) timer +{ +#pragma unused(timer) + // Idle timer event. + // Post a new idle notification, which gets executed when the run loop is idle. + // Since we are coalescing on name and sender there will always be only one actual notification + // even for multiple requests. + NSNotification *notification = [NSNotification notificationWithName: @"Idle" object: self]; + [notificationQueue enqueueNotification: notification + postingStyle: NSPostWhenIdle + coalesceMask: (NSNotificationCoalescingOnName | NSNotificationCoalescingOnSender) + forModes: nil]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Another step for idle events. The timer (for idle events) simply requests a notification on + * idle time. Only when this notification is send we actually call back the editor. + */ +- (void) idleTriggered: (NSNotification*) notification +{ +#pragma unused(notification) + reinterpret_cast(mTarget)->IdleTimerFired(); +} + +@end + +//----------------- ScintillaCocoa ----------------------------------------------------------------- + +ScintillaCocoa::ScintillaCocoa(NSView* view) +{ + wMain= [view retain]; + timerTarget = [[[TimerTarget alloc] init: this] retain]; + Initialise(); +} + +//-------------------------------------------------------------------------------------------------- + +ScintillaCocoa::~ScintillaCocoa() +{ + SetTicking(false); + [timerTarget release]; + NSView* container = ContentView(); + [container release]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Core initialization of the control. Everything that needs to be set up happens here. + */ +void ScintillaCocoa::Initialise() +{ + static bool initedLexers = false; + if (!initedLexers) + { + initedLexers = true; + Scintilla_LinkLexers(); + } + notifyObj = NULL; + notifyProc = NULL; + + capturedMouse = false; + + // Tell Scintilla not to buffer: Quartz buffers drawing for us. + WndProc(SCI_SETBUFFEREDDRAW, 0, 0); + + // We are working with Unicode exclusively. + WndProc(SCI_SETCODEPAGE, SC_CP_UTF8, 0); + + // Add Mac specific key bindings. + for (int i = 0; macMapDefault[i].key; i++) + kmap.AssignCmdKey(macMapDefault[i].key, macMapDefault[i].modifiers, macMapDefault[i].msg); + +} + +//-------------------------------------------------------------------------------------------------- + +/** + * We need some clean up. Do it here. + */ +void ScintillaCocoa::Finalise() +{ + SetTicking(false); + ScintillaBase::Finalise(); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Convert a core foundation string into an array of bytes in a particular encoding + */ + +static char *EncodedBytes(CFStringRef cfsRef, CFStringEncoding encoding) { + CFRange rangeAll = {0, CFStringGetLength(cfsRef)}; + CFIndex usedLen = 0; + CFStringGetBytes(cfsRef, rangeAll, encoding, '?', + false, NULL, 0, &usedLen); + + char *buffer = new char[usedLen+1]; + CFStringGetBytes(cfsRef, rangeAll, encoding, '?', + false, (UInt8 *)buffer,usedLen, NULL); + buffer[usedLen] = '\0'; + return buffer; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Case folders. + */ + +class CaseFolderUTF8 : public CaseFolderTable { +public: + CaseFolderUTF8() { + StandardASCII(); + } + virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) { + if ((lenMixed == 1) && (sizeFolded > 0)) { + folded[0] = mapping[static_cast(mixed[0])]; + return 1; + } else { + CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault, + reinterpret_cast(mixed), + lenMixed, kCFStringEncodingUTF8, false); + + NSString *sMapped = [(NSString *)cfsVal stringByFoldingWithOptions:NSCaseInsensitiveSearch + locale:[NSLocale currentLocale]]; + + const char *cpMapped = [sMapped UTF8String]; + size_t lenMapped = strlen(cpMapped); + if (lenMapped < sizeFolded) { + memcpy(folded, cpMapped, lenMapped); + } else { + lenMapped = 0; + } + CFRelease(cfsVal); + return lenMapped; + } + } +}; + +class CaseFolderDBCS : public CaseFolderTable { + CFStringEncoding encoding; +public: + CaseFolderDBCS(CFStringEncoding encoding_) : encoding(encoding_) { + StandardASCII(); + } + virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) { + if ((lenMixed == 1) && (sizeFolded > 0)) { + folded[0] = mapping[static_cast(mixed[0])]; + return 1; + } else { + CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault, + reinterpret_cast(mixed), + lenMixed, encoding, false); + + NSString *sMapped = [(NSString *)cfsVal stringByFoldingWithOptions:NSCaseInsensitiveSearch + locale:[NSLocale currentLocale]]; + + char *encoded = EncodedBytes((CFStringRef)sMapped, encoding); + + size_t lenMapped = strlen(encoded); + if (lenMapped < sizeFolded) { + memcpy(folded, encoded, lenMapped); + } else { + folded[0] = '\0'; + lenMapped = 1; + } + delete []encoded; + CFRelease(cfsVal); + return lenMapped; + } + // Something failed so return a single NUL byte + folded[0] = '\0'; + return 1; + } +}; + +CaseFolder *ScintillaCocoa::CaseFolderForEncoding() { + if (pdoc->dbcsCodePage == SC_CP_UTF8) { + return new CaseFolderUTF8(); + } else { + CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(), + vs.styles[STYLE_DEFAULT].characterSet); + if (pdoc->dbcsCodePage == 0) { + CaseFolderTable *pcf = new CaseFolderTable(); + pcf->StandardASCII(); + // Only for single byte encodings + for (int i=0x80; i<0x100; i++) { + char sCharacter[2] = "A"; + sCharacter[0] = i; + CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault, + reinterpret_cast(sCharacter), + 1, encoding, false); + + NSString *sMapped = [(NSString *)cfsVal stringByFoldingWithOptions:NSCaseInsensitiveSearch + locale:[NSLocale currentLocale]]; + + char *encoded = EncodedBytes((CFStringRef)sMapped, encoding); + + if (strlen(encoded) == 1) { + pcf->SetTranslation(sCharacter[0], encoded[0]); + } + + delete []encoded; + CFRelease(cfsVal); + } + return pcf; + } else { + return new CaseFolderDBCS(encoding); + } + return 0; + } +} + + +//-------------------------------------------------------------------------------------------------- + +/** + * Case-fold the given string depending on the specified case mapping type. + */ +std::string ScintillaCocoa::CaseMapString(const std::string &s, int caseMapping) +{ + CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(), + vs.styles[STYLE_DEFAULT].characterSet); + CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault, + reinterpret_cast(s.c_str()), + s.length(), encoding, false); + + NSString *sMapped; + switch (caseMapping) + { + case cmUpper: + sMapped = [(NSString *)cfsVal uppercaseString]; + break; + case cmLower: + sMapped = [(NSString *)cfsVal lowercaseString]; + break; + default: + sMapped = (NSString *)cfsVal; + } + + // Back to encoding + char *encoded = EncodedBytes((CFStringRef)sMapped, encoding); + std::string result(encoded); + delete []encoded; + CFRelease(cfsVal); + return result; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Helper function to get the outer container which represents the Scintilla editor on application side. + */ +ScintillaView* ScintillaCocoa::TopContainer() +{ + NSView* container = static_cast(wMain.GetID()); + return static_cast([container superview]); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Helper function to get the inner container which represents the actual "canvas" we work with. + */ +NSView* ScintillaCocoa::ContentView() +{ + return static_cast(wMain.GetID()); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Instead of returning the size of the inner view we have to return the visible part of it + * in order to make scrolling working properly. + */ +PRectangle ScintillaCocoa::GetClientRectangle() +{ + NSView* host = ContentView(); + NSSize size = [host frame].size; + return PRectangle(0, 0, size.width, size.height); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Converts the given point from base coordinates to local coordinates and at the same time into + * a native Point structure. Base coordinates are used for the top window used in the view hierarchy. + */ +Scintilla::Point ScintillaCocoa::ConvertPoint(NSPoint point) +{ + NSView* container = ContentView(); + NSPoint result = [container convertPoint: point fromView: nil]; + + return Point(result.x, result.y); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * A function to directly execute code that would usually go the long way via window messages. + * However this is a Windows metapher and not used here, hence we just call our fake + * window proc. The given parameters directly reflect the message parameters used on Windows. + * + * @param sciThis The target which is to be called. + * @param iMessage A code that indicates which message was sent. + * @param wParam One of the two free parameters for the message. Traditionally a word sized parameter + * (hence the w prefix). + * @param lParam The other of the two free parameters. A signed long. + */ +sptr_t ScintillaCocoa::DirectFunction(ScintillaCocoa *sciThis, unsigned int iMessage, uptr_t wParam, + sptr_t lParam) +{ + return sciThis->WndProc(iMessage, wParam, lParam); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * This method is very similar to DirectFunction. On Windows it sends a message (not in the Obj-C sense) + * to the target window. Here we simply call our fake window proc. + */ +sptr_t scintilla_send_message(void* sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam) +{ + ScintillaView *control = reinterpret_cast(sci); + ScintillaCocoa* scintilla = [control backend]; + return scintilla->WndProc(iMessage, wParam, lParam); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * That's our fake window procedure. On Windows each window has a dedicated procedure to handle + * commands (also used to synchronize UI and background threads), which is not the case in Cocoa. + * + * Messages handled here are almost solely for special commands of the backend. Everything which + * would be sytem messages on Windows (e.g. for key down, mouse move etc.) are handled by + * directly calling appropriate handlers. + */ +sptr_t ScintillaCocoa::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) +{ + switch (iMessage) + { + case SCI_GETDIRECTFUNCTION: + return reinterpret_cast(DirectFunction); + + case SCI_GETDIRECTPOINTER: + return reinterpret_cast(this); + + case SCI_GRABFOCUS: + [[ContentView() window] makeFirstResponder:ContentView()]; + break; + + case SCI_SETBUFFEREDDRAW: + // Buffered drawing not supported on Cocoa + bufferedDraw = false; + break; + + case WM_UNICHAR: + // Special case not used normally. Characters passed in this way will be inserted + // regardless of their value or modifier states. That means no command interpretation is + // performed. + if (IsUnicodeMode()) + { + NSString* input = [NSString stringWithCharacters: (const unichar*) &wParam length: 1]; + const char* utf8 = [input UTF8String]; + AddCharUTF((char*) utf8, static_cast(strlen(utf8)), false); + return 1; + } + return 0; + + default: + sptr_t r = ScintillaBase::WndProc(iMessage, wParam, lParam); + + return r; + } + return 0l; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * In Windows lingo this is the handler which handles anything that wasn't handled in the normal + * window proc which would usually send the message back to generic window proc that Windows uses. + */ +sptr_t ScintillaCocoa::DefWndProc(unsigned int, uptr_t, sptr_t) +{ + return 0; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Enables or disables a timer that can trigger background processing at a regular interval, like + * drag scrolling or caret blinking. + */ +void ScintillaCocoa::SetTicking(bool on) +{ + if (timer.ticking != on) + { + timer.ticking = on; + if (timer.ticking) + { + // Scintilla ticks = milliseconds + tickTimer = [NSTimer scheduledTimerWithTimeInterval: timer.tickSize / 1000.0 + target: timerTarget + selector: @selector(timerFired:) + userInfo: nil + repeats: YES]; + timer.tickerID = reinterpret_cast(tickTimer); + } + else + if (timer.tickerID != NULL) + { + [reinterpret_cast(timer.tickerID) invalidate]; + timer.tickerID = 0; + } + } + timer.ticksToWait = caret.period; +} + +//-------------------------------------------------------------------------------------------------- + +bool ScintillaCocoa::SetIdle(bool on) +{ + if (idler.state != on) + { + idler.state = on; + if (idler.state) + { + // Scintilla ticks = milliseconds + idleTimer = [NSTimer scheduledTimerWithTimeInterval: timer.tickSize / 1000.0 + target: timerTarget + selector: @selector(idleTimerFired:) + userInfo: nil + repeats: YES]; + idler.idlerID = reinterpret_cast(idleTimer); + } + else + if (idler.idlerID != NULL) + { + [reinterpret_cast(idler.idlerID) invalidate]; + idler.idlerID = 0; + } + } + return true; +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::CopyToClipboard(const SelectionText &selectedText) +{ + SetPasteboardData([NSPasteboard generalPasteboard], selectedText); +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::Copy() +{ + if (!sel.Empty()) + { + SelectionText selectedText; + CopySelectionRange(&selectedText); + CopyToClipboard(selectedText); + } +} + +//-------------------------------------------------------------------------------------------------- + +bool ScintillaCocoa::CanPaste() +{ + if (!Editor::CanPaste()) + return false; + + return GetPasteboardData([NSPasteboard generalPasteboard], NULL); +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::Paste() +{ + Paste(false); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Pastes data from the paste board into the editor. + */ +void ScintillaCocoa::Paste(bool forceRectangular) +{ + SelectionText selectedText; + bool ok = GetPasteboardData([NSPasteboard generalPasteboard], &selectedText); + if (forceRectangular) + selectedText.rectangular = forceRectangular; + + if (!ok || !selectedText.s) + // No data or no flavor we support. + return; + + pdoc->BeginUndoAction(); + ClearSelection(false); + int length = selectedText.len - 1; // One less to avoid inserting the terminating 0 character. + if (selectedText.rectangular) + { + SelectionPosition selStart = sel.RangeMain().Start(); + PasteRectangular(selStart, selectedText.s, length); + } + else + if (pdoc->InsertString(sel.RangeMain().caret.Position(), selectedText.s, length)) + SetEmptySelection(sel.RangeMain().caret.Position() + length); + + pdoc->EndUndoAction(); + + Redraw(); + EnsureCaretVisible(); +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::CTPaint(void* gc, NSRect rc) { +#pragma unused(rc) + Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); + if (surfaceWindow) { + surfaceWindow->Init(gc, wMain.GetID()); + surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ct.codePage); + surfaceWindow->SetDBCSMode(ct.codePage); + ct.PaintCT(surfaceWindow); + surfaceWindow->Release(); + delete surfaceWindow; + } +} + +@interface CallTipView : NSControl { + ScintillaCocoa *sci; +} + +@end + +@implementation CallTipView + +- (NSView*) initWithFrame: (NSRect) frame { + self = [super initWithFrame: frame]; + + if (self) { + sci = NULL; + } + + return self; +} + +- (void) dealloc { + [super dealloc]; +} + +- (BOOL) isFlipped { + return YES; +} + +- (void) setSci: (ScintillaCocoa *) sci_ { + sci = sci_; +} + +- (void) drawRect: (NSRect) needsDisplayInRect { + if (sci) { + CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; + sci->CTPaint(context, needsDisplayInRect); + } +} + +- (void) mouseDown: (NSEvent *) event { + if (sci) { + sci->CallTipMouseDown([event locationInWindow]); + } +} + +// On OS X, only the key view should modify the cursor so the calltip can't. +// This view does not become key so resetCursorRects never called. +- (void) resetCursorRects { + //[super resetCursorRects]; + //[self addCursorRect: [self bounds] cursor: [NSCursor arrowCursor]]; +} + +@end + +void ScintillaCocoa::CallTipMouseDown(NSPoint pt) { + NSRect rectBounds = [(NSView *)(ct.wDraw.GetID()) bounds]; + Point location(pt.x, rectBounds.size.height - pt.y); + ct.MouseClick(location); + CallTipClick(); +} + +void ScintillaCocoa::CreateCallTipWindow(PRectangle rc) { + if (!ct.wCallTip.Created()) { + NSRect ctRect = NSMakeRect(rc.top,rc.bottom, rc.Width(), rc.Height()); + NSWindow *callTip = [[NSWindow alloc] initWithContentRect: ctRect + styleMask: NSBorderlessWindowMask + backing: NSBackingStoreBuffered + defer: NO]; + [callTip setLevel:NSFloatingWindowLevel]; + [callTip setHasShadow:YES]; + NSRect ctContent = NSMakeRect(0,0, rc.Width(), rc.Height()); + CallTipView *caption = [[CallTipView alloc] initWithFrame: ctContent]; + [caption setAutoresizingMask: NSViewWidthSizable | NSViewMaxYMargin]; + [caption setSci: this]; + [[callTip contentView] addSubview: caption]; + [callTip orderFront:caption]; + ct.wCallTip = callTip; + ct.wDraw = caption; + } +} + +void ScintillaCocoa::AddToPopUp(const char *label, int cmd, bool enabled) +{ + NSMenuItem* item; + ScintillaContextMenu *menu= reinterpret_cast(popup.GetID()); + [menu setOwner: this]; + [menu setAutoenablesItems: NO]; + + if (cmd == 0) { + item = [NSMenuItem separatorItem]; + } else { + item = [[[NSMenuItem alloc] init] autorelease]; + [item setTitle: [NSString stringWithUTF8String: label]]; + } + [item setTarget: menu]; + [item setAction: @selector(handleCommand:)]; + [item setTag: cmd]; + [item setEnabled: enabled]; + + [menu addItem: item]; +} + +// ------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::ClaimSelection() +{ + // Mac OS X does not have a primary selection. +} + +// ------------------------------------------------------------------------------------------------- + +/** + * Returns the current caret position (which is tracked as an offset into the entire text string) + * as a row:column pair. The result is zero-based. + */ +NSPoint ScintillaCocoa::GetCaretPosition() +{ + NSPoint result; + + result.y = pdoc->LineFromPosition(sel.RangeMain().caret.Position()); + result.x = sel.RangeMain().caret.Position() - pdoc->LineStart(result.y); + return result; +} + +// ------------------------------------------------------------------------------------------------- + +#pragma mark Drag + +/** + * Triggered by the tick timer on a regular basis to scroll the content during a drag operation. + */ +void ScintillaCocoa::DragScroll() +{ + if (!posDrag.IsValid()) + { + scrollSpeed = 1; + scrollTicks = 2000; + return; + } + + // TODO: does not work for wrapped lines, fix it. + int line = pdoc->LineFromPosition(posDrag.Position()); + int currentVisibleLine = cs.DisplayFromDoc(line); + int lastVisibleLine = Platform::Minimum(topLine + LinesOnScreen(), cs.LinesDisplayed()) - 2; + + if (currentVisibleLine <= topLine && topLine > 0) + ScrollTo(topLine - scrollSpeed); + else + if (currentVisibleLine >= lastVisibleLine) + ScrollTo(topLine + scrollSpeed); + else + { + scrollSpeed = 1; + scrollTicks = 2000; + return; + } + + // TODO: also handle horizontal scrolling. + + if (scrollSpeed == 1) + { + scrollTicks -= timer.tickSize; + if (scrollTicks <= 0) + { + scrollSpeed = 5; + scrollTicks = 2000; + } + } + +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called when a drag operation was initiated from within Scintilla. + */ +void ScintillaCocoa::StartDrag() +{ + if (sel.Empty()) + return; + + // Put the data to be dragged on the drag pasteboard. + SelectionText selectedText; + NSPasteboard* pasteboard = [NSPasteboard pasteboardWithName: NSDragPboard]; + CopySelectionRange(&selectedText); + SetPasteboardData(pasteboard, selectedText); + + // calculate the bounds of the selection + PRectangle client = GetTextRectangle(); + int selStart = sel.RangeMain().Start().Position(); + int selEnd = sel.RangeMain().End().Position(); + int startLine = pdoc->LineFromPosition(selStart); + int endLine = pdoc->LineFromPosition(selEnd); + Point pt; + long startPos, endPos, ep; + Rect rcSel; + + if (startLine==endLine && WndProc(SCI_GETWRAPMODE, 0, 0) != SC_WRAP_NONE) { + // Komodo bug http://bugs.activestate.com/show_bug.cgi?id=87571 + // Scintilla bug https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3040200&group_id=2439 + // If the width on a wrapped-line selection is negative, + // find a better bounding rectangle. + + Point ptStart, ptEnd; + startPos = WndProc(SCI_GETLINESELSTARTPOSITION, startLine, 0); + endPos = WndProc(SCI_GETLINESELENDPOSITION, startLine, 0); + // step back a position if we're counting the newline + ep = WndProc(SCI_GETLINEENDPOSITION, startLine, 0); + if (endPos > ep) endPos = ep; + ptStart = LocationFromPosition(static_cast(startPos)); + ptEnd = LocationFromPosition(static_cast(endPos)); + if (ptStart.y == ptEnd.y) { + // We're just selecting part of one visible line + rcSel.left = ptStart.x; + rcSel.right = ptEnd.x < client.right ? ptEnd.x : client.right; + } else { + // Find the bounding box. + startPos = WndProc(SCI_POSITIONFROMLINE, startLine, 0); + rcSel.left = LocationFromPosition(static_cast(startPos)).x; + rcSel.right = client.right; + } + rcSel.top = ptStart.y; + rcSel.bottom = ptEnd.y + vs.lineHeight; + if (rcSel.bottom > client.bottom) { + rcSel.bottom = client.bottom; + } + } else { + rcSel.top = rcSel.bottom = rcSel.right = rcSel.left = -1; + for (int l = startLine; l <= endLine; l++) { + startPos = WndProc(SCI_GETLINESELSTARTPOSITION, l, 0); + endPos = WndProc(SCI_GETLINESELENDPOSITION, l, 0); + if (endPos == startPos) continue; + // step back a position if we're counting the newline + ep = WndProc(SCI_GETLINEENDPOSITION, l, 0); + if (endPos > ep) endPos = ep; + pt = LocationFromPosition(static_cast(startPos)); // top left of line selection + if (pt.x < rcSel.left || rcSel.left < 0) rcSel.left = pt.x; + if (pt.y < rcSel.top || rcSel.top < 0) rcSel.top = pt.y; + pt = LocationFromPosition(static_cast(endPos)); // top right of line selection + pt.y += vs.lineHeight; // get to the bottom of the line + if (pt.x > rcSel.right || rcSel.right < 0) { + if (pt.x > client.right) + rcSel.right = client.right; + else + rcSel.right = pt.x; + } + if (pt.y > rcSel.bottom || rcSel.bottom < 0) { + if (pt.y > client.bottom) + rcSel.bottom = client.bottom; + else + rcSel.bottom = pt.y; + } + } + } + // must convert to global coordinates for drag regions, but also save the + // image rectangle for further calculations and copy operations + PRectangle localRectangle = PRectangle(rcSel.left, rcSel.top, rcSel.right, rcSel.bottom); + + // Prepare drag image. + NSRect selectionRectangle = PRectangleToNSRect(localRectangle); + + NSView* content = ContentView(); + +#if 1 + + // To get a bitmap of the text we're dragging, we just use Paint on a pixmap surface. + SurfaceImpl *sw = new SurfaceImpl(); + SurfaceImpl *pixmap = NULL; + + bool lastHideSelection = hideSelection; + hideSelection = true; + if (sw) + { + pixmap = new SurfaceImpl(); + if (pixmap) + { + PRectangle imageRect = NSRectToPRectangle(selectionRectangle); + paintState = painting; + sw->InitPixMap(client.Width(), client.Height(), NULL, NULL); + paintingAllText = true; + // Have to create a new context and make current as text drawing goes + // to the current context, not a passed context. + CGContextRef gcsw = sw->GetContext(); + NSGraphicsContext *nsgc = [NSGraphicsContext graphicsContextWithGraphicsPort: gcsw + flipped: YES]; + [NSGraphicsContext setCurrentContext:nsgc]; + Paint(sw, client); + paintState = notPainting; + + pixmap->InitPixMap(imageRect.Width(), imageRect.Height(), NULL, NULL); + + CGContextRef gc = pixmap->GetContext(); + // To make Paint() work on a bitmap, we have to flip our coordinates and translate the origin + CGContextTranslateCTM(gc, 0, imageRect.Height()); + CGContextScaleCTM(gc, 1.0, -1.0); + + pixmap->CopyImageRectangle(*sw, imageRect, PRectangle(0, 0, imageRect.Width(), imageRect.Height())); + // XXX TODO: overwrite any part of the image that is not part of the + // selection to make it transparent. right now we just use + // the full rectangle which may include non-selected text. + } + sw->Release(); + delete sw; + } + hideSelection = lastHideSelection; + + NSBitmapImageRep* bitmap = NULL; + if (pixmap) + { + CGImageRef imagePixmap = pixmap->GetImage(); + bitmap = [[[NSBitmapImageRep alloc] initWithCGImage: imagePixmap] autorelease]; + CGImageRelease(imagePixmap); + pixmap->Release(); + delete pixmap; + } +#else + + // Poor man's drag image: take a snapshot of the content view. + [content lockFocus]; + NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: selectionRectangle] autorelease]; + [bitmap setColorSpaceName: NSDeviceRGBColorSpace]; + [content unlockFocus]; + +#endif + + NSImage* image = [[[NSImage alloc] initWithSize: selectionRectangle.size] autorelease]; + [image addRepresentation: bitmap]; + + NSImage* dragImage = [[[NSImage alloc] initWithSize: selectionRectangle.size] autorelease]; + [dragImage setBackgroundColor: [NSColor clearColor]]; + [dragImage lockFocus]; + [image dissolveToPoint: NSMakePoint(0.0, 0.0) fraction: 0.5]; + [dragImage unlockFocus]; + + NSPoint startPoint; + startPoint.x = selectionRectangle.origin.x; + startPoint.y = selectionRectangle.origin.y + selectionRectangle.size.height; + [content dragImage: dragImage + at: startPoint + offset: NSZeroSize + event: lastMouseEvent // Set in MouseMove. + pasteboard: pasteboard + source: content + slideBack: YES]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called when a drag operation reaches the control which was initiated outside. + */ +NSDragOperation ScintillaCocoa::DraggingEntered(id info) +{ + inDragDrop = ddDragging; + return DraggingUpdated(info); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called frequently during a drag operation if we are the target. Keep telling the caller + * what drag operation we accept and update the drop caret position to indicate the + * potential insertion point of the dragged data. + */ +NSDragOperation ScintillaCocoa::DraggingUpdated(id info) +{ + // Convert the drag location from window coordinates to view coordinates and + // from there to a text position to finally set the drag position. + Point location = ConvertPoint([info draggingLocation]); + SetDragPosition(SPositionFromLocation(location)); + + NSDragOperation sourceDragMask = [info draggingSourceOperationMask]; + if (sourceDragMask == NSDragOperationNone) + return sourceDragMask; + + NSPasteboard* pasteboard = [info draggingPasteboard]; + + // Return what type of operation we will perform. Prefer move over copy. + if ([[pasteboard types] containsObject: NSStringPboardType] || + [[pasteboard types] containsObject: ScintillaRecPboardType]) + return (sourceDragMask & NSDragOperationMove) ? NSDragOperationMove : NSDragOperationCopy; + + if ([[pasteboard types] containsObject: NSFilenamesPboardType]) + return (sourceDragMask & NSDragOperationGeneric); + return NSDragOperationNone; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Resets the current drag position as we are no longer the drag target. + */ +void ScintillaCocoa::DraggingExited(id info) +{ +#pragma unused(info) + SetDragPosition(SelectionPosition(invalidPosition)); + inDragDrop = ddNone; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Here is where the real work is done. Insert the text from the pasteboard. + */ +bool ScintillaCocoa::PerformDragOperation(id info) +{ + NSPasteboard* pasteboard = [info draggingPasteboard]; + + if ([[pasteboard types] containsObject: NSFilenamesPboardType]) + { + NSArray* files = [pasteboard propertyListForType: NSFilenamesPboardType]; + for (NSString* uri in files) + NotifyURIDropped([uri UTF8String]); + } + else + { + SelectionText text; + GetPasteboardData(pasteboard, &text); + + if (text.len > 0) + { + NSDragOperation operation = [info draggingSourceOperationMask]; + bool moving = (operation & NSDragOperationMove) != 0; + + DropAt(posDrag, text.s, moving, text.rectangular); + }; + } + + return true; +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::SetPasteboardData(NSPasteboard* board, const SelectionText &selectedText) +{ + if (selectedText.len == 0) + return; + + CFStringEncoding encoding = EncodingFromCharacterSet(selectedText.codePage == SC_CP_UTF8, + selectedText.characterSet); + CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault, + reinterpret_cast(selectedText.s), + selectedText.len-1, encoding, false); + + [board declareTypes:[NSArray arrayWithObjects: + NSStringPboardType, + selectedText.rectangular ? ScintillaRecPboardType : nil, + nil] owner:nil]; + + if (selectedText.rectangular) + { + // This is specific to scintilla, allows us to drag rectangular selections around the document. + [board setString: (NSString *)cfsVal forType: ScintillaRecPboardType]; + } + + [board setString: (NSString *)cfsVal forType: NSStringPboardType]; + + CFRelease(cfsVal); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Helper method to retrieve the best fitting alternative from the general pasteboard. + */ +bool ScintillaCocoa::GetPasteboardData(NSPasteboard* board, SelectionText* selectedText) +{ + NSArray* supportedTypes = [NSArray arrayWithObjects: ScintillaRecPboardType, + NSStringPboardType, + nil]; + NSString *bestType = [board availableTypeFromArray: supportedTypes]; + NSString* data = [board stringForType: bestType]; + + if (data != nil) + { + if (selectedText != nil) + { + CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(), + vs.styles[STYLE_DEFAULT].characterSet); + CFRange rangeAll = {0, [data length]}; + CFIndex usedLen = 0; + CFStringGetBytes((CFStringRef)data, rangeAll, encoding, '?', + false, NULL, 0, &usedLen); + + UInt8 *buffer = new UInt8[usedLen]; + + CFStringGetBytes((CFStringRef)data, rangeAll, encoding, '?', + false, buffer,usedLen, NULL); + + bool rectangular = bestType == ScintillaRecPboardType; + + int len = static_cast(usedLen); + char *dest = Document::TransformLineEnds(&len, (char *)buffer, len, pdoc->eolMode); + + selectedText->Set(dest, len+1, pdoc->dbcsCodePage, + vs.styles[STYLE_DEFAULT].characterSet , rectangular, false); + delete []buffer; + } + return true; + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::SetMouseCapture(bool on) +{ + capturedMouse = on; + /* + if (mouseDownCaptures) + { + if (capturedMouse) + WndProc(SCI_SETCURSOR, Window::cursorArrow, 0); + else + // Reset to normal. Actual image will be set on mouse move. + WndProc(SCI_SETCURSOR, (unsigned int) SC_CURSORNORMAL, 0); + } + */ +} + +//-------------------------------------------------------------------------------------------------- + +bool ScintillaCocoa::HaveMouseCapture() +{ + return capturedMouse; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Synchronously paint a rectangle of the window. + */ +void ScintillaCocoa::SyncPaint(void* gc, PRectangle rc) +{ + paintState = painting; + rcPaint = rc; + PRectangle rcText = GetTextRectangle(); + paintingAllText = rcPaint.Contains(rcText); + Surface *sw = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); + if (sw) + { + sw->Init(gc, wMain.GetID()); + Paint(sw, rc); + if (paintState == paintAbandoned) + { + // Do a full paint. + rcPaint = GetClientRectangle(); + paintState = painting; + paintingAllText = true; + Paint(sw, rcPaint); + } + sw->Release(); + delete sw; + } + paintState = notPainting; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Scrolls the pixels in the window some number of lines. + * Invalidates the pixels scrolled into view. + */ +void ScintillaCocoa::ScrollText(int linesToMove) +{ + // Move those pixels + NSView *content = ContentView(); + + [content lockFocus]; + int diff = vs.lineHeight * linesToMove; + PRectangle textRect = GetTextRectangle(); + // Include margins as they must scroll + textRect.left = 0; + NSRect textRectangle = PRectangleToNSRect(textRect); + NSPoint destPoint = textRectangle.origin; + destPoint.y += diff; + NSCopyBits(0, textRectangle, destPoint); + + // Paint them nice + NSRect redrawRectangle = textRectangle; + if (linesToMove < 0) { + // Repaint bottom + redrawRectangle.origin.y = redrawRectangle.origin.y + redrawRectangle.size.height + diff; + redrawRectangle.size.height = -diff; + } else { + // Repaint top + redrawRectangle.size.height = diff; + } + + [content drawRect: redrawRectangle]; + [content unlockFocus]; + + // If no flush done here then multiple scrolls will get buffered and screen + // will only update a few times a second. + //[[content window] flushWindow]; + // However, doing the flush leads to the caret updating as a separate operation + // which looks bad when scrolling by holding down the down arrow key. + + // Could invalidate instead of synchronous draw but that may not be as smooth + //[content setNeedsDisplayInRect: redrawRectangle]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Modfies the vertical scroll position to make the current top line show up as such. + */ +void ScintillaCocoa::SetVerticalScrollPos() +{ + ScintillaView* topContainer = TopContainer(); + + // Convert absolute coordinate into the range [0..1]. Keep in mind that the visible area + // does *not* belong to the scroll range. + float relativePosition = (float) topLine / MaxScrollPos(); + [topContainer setVerticalScrollPosition: relativePosition]; +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::SetHorizontalScrollPos() +{ + ScintillaView* topContainer = TopContainer(); + PRectangle textRect = GetTextRectangle(); + + // Convert absolute coordinate into the range [0..1]. Keep in mind that the visible area + // does *not* belong to the scroll range. + float relativePosition = (float) xOffset / (scrollWidth - textRect.Width()); + [topContainer setHorizontalScrollPosition: relativePosition]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Used to adjust both scrollers to reflect the current scroll range and position in the editor. + * + * @param nMax Number of lines in the editor. + * @param nPage Number of lines per scroll page. + * @return True if there was a change, otherwise false. + */ +bool ScintillaCocoa::ModifyScrollBars(int nMax, int nPage) +{ +#pragma unused(nPage) + // Input values are given in lines, not pixels, so we have to convert. + int lineHeight = static_cast(WndProc(SCI_TEXTHEIGHT, 0, 0)); + PRectangle bounds = GetTextRectangle(); + ScintillaView* topContainer = TopContainer(); + + // Set page size to the same value as the scroll range to hide the scrollbar. + int scrollRange = lineHeight * (nMax + 1); // +1 because the caller subtracted one. + int pageSize; + if (verticalScrollBarVisible) + pageSize = bounds.Height(); + else + pageSize = scrollRange; + bool verticalChange = [topContainer setVerticalScrollRange: scrollRange page: pageSize]; + + scrollRange = scrollWidth; + if (horizontalScrollBarVisible) + pageSize = bounds.Width(); + else + pageSize = scrollRange; + bool horizontalChange = [topContainer setHorizontalScrollRange: scrollRange page: pageSize]; + + return verticalChange || horizontalChange; +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::Resize() +{ + ChangeSize(); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called by the frontend control when the user manipulates one of the scrollers. + * + * @param position The relative position of the scroller in the range of [0..1]. + * @param part Specifies which part was clicked on by the user, so we can handle thumb tracking + * as well as page and line scrolling. + * @param horizontal True if the horizontal scroller was hit, otherwise false. + */ +void ScintillaCocoa::DoScroll(float position, NSScrollerPart part, bool horizontal) +{ + // If the given scroller part is not the knob (or knob slot) then the given position is not yet + // current and we have to update it. + if (horizontal) + { + // Horizontal offset is given in pixels. + PRectangle textRect = GetTextRectangle(); + int offset = (int) (position * (scrollWidth - textRect.Width())); + int smallChange = (int) (textRect.Width() / 30); + if (smallChange < 5) + smallChange = 5; + switch (part) + { + case NSScrollerDecrementLine: + offset -= smallChange; + break; + case NSScrollerDecrementPage: + offset -= textRect.Width(); + break; + case NSScrollerIncrementLine: + offset += smallChange; + break; + case NSScrollerIncrementPage: + offset += textRect.Width(); + break; + }; + HorizontalScrollTo(offset); + } + else + { + // VerticalScrolling is by line. If the user is scrolling using the knob we can directly + // set the new scroll position. Otherwise we have to compute it first. + if (part == NSScrollerKnob) + ScrollTo(position * MaxScrollPos(), false); + else + { + switch (part) + { + case NSScrollerDecrementLine: + ScrollTo(topLine - 1, true); + break; + case NSScrollerDecrementPage: + ScrollTo(topLine - LinesOnScreen(), true); + break; + case NSScrollerIncrementLine: + ScrollTo(topLine + 1, true); + break; + case NSScrollerIncrementPage: + ScrollTo(topLine + LinesOnScreen(), true); + break; + }; + + } + } +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Used to register a callback function for a given window. This is used to emulate the way + * Windows notfies other controls (mainly up in the view hierarchy) about certain events. + * + * @param windowid A handle to a window. That value is generic and can be anything. It is passed + * through to the callback. + * @param callback The callback function to be used for future notifications. If NULL then no + * notifications will be sent anymore. + */ +void ScintillaCocoa::RegisterNotifyCallback(intptr_t windowid, SciNotifyFunc callback) +{ + notifyObj = windowid; + notifyProc = callback; +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::NotifyChange() +{ + if (notifyProc != NULL) + notifyProc(notifyObj, WM_COMMAND, Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE), + (uintptr_t) this); +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::NotifyFocus(bool focus) +{ + if (notifyProc != NULL) + notifyProc(notifyObj, WM_COMMAND, Platform::LongFromTwoShorts(GetCtrlID(), (focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS)), + (uintptr_t) this); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Used to send a notification (as WM_NOTIFY call) to the procedure, which has been set by the call + * to RegisterNotifyCallback (so it is not necessarily the parent window). + * + * @param scn The notification to send. + */ +void ScintillaCocoa::NotifyParent(SCNotification scn) +{ + if (notifyProc != NULL) + { + scn.nmhdr.hwndFrom = (void*) this; + scn.nmhdr.idFrom = GetCtrlID(); + notifyProc(notifyObj, WM_NOTIFY, (uintptr_t) 0, (uintptr_t) &scn); + } +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::NotifyURIDropped(const char *uri) +{ + SCNotification scn; + scn.nmhdr.code = SCN_URIDROPPED; + scn.text = uri; + + NotifyParent(scn); +} + +//-------------------------------------------------------------------------------------------------- + +bool ScintillaCocoa::HasSelection() +{ + return !sel.Empty(); +} + +//-------------------------------------------------------------------------------------------------- + +bool ScintillaCocoa::CanUndo() +{ + return pdoc->CanUndo(); +} + +//-------------------------------------------------------------------------------------------------- + +bool ScintillaCocoa::CanRedo() +{ + return pdoc->CanRedo(); +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::TimerFired(NSTimer* timer) +{ +#pragma unused(timer) + Tick(); + DragScroll(); +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::IdleTimerFired() +{ + bool more = Idle(); + if (!more) + SetIdle(false); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Main entry point for drawing the control. + * + * @param rect The area to paint, given in the sender's coordinate system. + * @param gc The context we can use to paint. + */ +void ScintillaCocoa::Draw(NSRect rect, CGContextRef gc) +{ + SyncPaint(gc, NSRectToPRectangle(rect)); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Helper function to translate OS X key codes to Scintilla key codes. + */ +static inline UniChar KeyTranslate(UniChar unicodeChar) +{ + switch (unicodeChar) + { + case NSDownArrowFunctionKey: + return SCK_DOWN; + case NSUpArrowFunctionKey: + return SCK_UP; + case NSLeftArrowFunctionKey: + return SCK_LEFT; + case NSRightArrowFunctionKey: + return SCK_RIGHT; + case NSHomeFunctionKey: + return SCK_HOME; + case NSEndFunctionKey: + return SCK_END; + case NSPageUpFunctionKey: + return SCK_PRIOR; + case NSPageDownFunctionKey: + return SCK_NEXT; + case NSDeleteFunctionKey: + return SCK_DELETE; + case NSInsertFunctionKey: + return SCK_INSERT; + case '\n': + case 3: + return SCK_RETURN; + case 27: + return SCK_ESCAPE; + case 127: + return SCK_BACK; + case '\t': + case 25: // Shift tab, return to unmodified tab and handle that via modifiers. + return SCK_TAB; + default: + return unicodeChar; + } +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Main keyboard input handling method. It is called for any key down event, including function keys, + * numeric keypad input and whatnot. + * + * @param event The event instance associated with the key down event. + * @return True if the input was handled, false otherwise. + */ +bool ScintillaCocoa::KeyboardInput(NSEvent* event) +{ + // For now filter out function keys. + NSUInteger modifiers = [event modifierFlags]; + + NSString* input = [event characters]; + + bool control = (modifiers & NSControlKeyMask) != 0; + bool shift = (modifiers & NSShiftKeyMask) != 0; + bool command = (modifiers & NSCommandKeyMask) != 0; + bool alt = (modifiers & NSAlternateKeyMask) != 0; + + bool handled = false; + + // Handle each entry individually. Usually we only have one entry anway. + for (size_t i = 0; i < input.length; i++) + { + const UniChar originalKey = [input characterAtIndex: i]; + UniChar key = KeyTranslate(originalKey); + + bool consumed = false; // Consumed as command? + + // Signal Control as SCMOD_META + int modifierKeys = + (shift ? SCI_SHIFT : 0) | + (command ? SCI_CTRL : 0) | + (alt ? SCI_ALT : 0) | + (control ? SCI_META : 0); + if (KeyDownWithModifiers(key, modifierKeys, &consumed)) + handled = true; + if (consumed) + handled = true; + } + + return handled; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Used to insert already processed text provided by the Cocoa text input system. + */ +int ScintillaCocoa::InsertText(NSString* input) +{ + CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(), + vs.styles[STYLE_DEFAULT].characterSet); + CFRange rangeAll = {0, [input length]}; + CFIndex usedLen = 0; + CFStringGetBytes((CFStringRef)input, rangeAll, encoding, '?', + false, NULL, 0, &usedLen); + + UInt8 *buffer = new UInt8[usedLen]; + + CFStringGetBytes((CFStringRef)input, rangeAll, encoding, '?', + false, buffer,usedLen, NULL); + + AddCharUTF((char*) buffer, static_cast(usedLen), false); + delete []buffer; + return static_cast(usedLen); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called by the owning view when the mouse pointer enters the control. + */ +void ScintillaCocoa::MouseEntered(NSEvent* event) +{ + if (!HaveMouseCapture()) + { + WndProc(SCI_SETCURSOR, (long int)SC_CURSORNORMAL, 0); + + // Mouse location is given in screen coordinates and might also be outside of our bounds. + Point location = ConvertPoint([event locationInWindow]); + ButtonMove(location); + } +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::MouseExited(NSEvent* /* event */) +{ + // Nothing to do here. +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::MouseDown(NSEvent* event) +{ + Point location = ConvertPoint([event locationInWindow]); + NSTimeInterval time = [event timestamp]; + bool command = ([event modifierFlags] & NSCommandKeyMask) != 0; + bool shift = ([event modifierFlags] & NSShiftKeyMask) != 0; + bool alt = ([event modifierFlags] & NSAlternateKeyMask) != 0; + + ButtonDown(Point(location.x, location.y), (int) (time * 1000), shift, command, alt); +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::MouseMove(NSEvent* event) +{ + lastMouseEvent = event; + + ButtonMove(ConvertPoint([event locationInWindow])); +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::MouseUp(NSEvent* event) +{ + NSTimeInterval time = [event timestamp]; + bool control = ([event modifierFlags] & NSControlKeyMask) != 0; + + ButtonUp(ConvertPoint([event locationInWindow]), (int) (time * 1000), control); +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::MouseWheel(NSEvent* event) +{ + bool command = ([event modifierFlags] & NSCommandKeyMask) != 0; + int dX = 0; + int dY = 0; + + dX = 10 * [event deltaX]; // Arbitrary scale factor. + + // In order to make scrolling with larger offset smoother we scroll less lines the larger the + // delta value is. + if ([event deltaY] < 0) + dY = -(int) sqrt(-10.0 * [event deltaY]); + else + dY = (int) sqrt(10.0 * [event deltaY]); + + if (command) + { + // Zoom! We play with the font sizes in the styles. + // Number of steps/line is ignored, we just care if sizing up or down. + if (dY > 0.5) + KeyCommand(SCI_ZOOMIN); + else if (dY < -0.5) + KeyCommand(SCI_ZOOMOUT); + } + else + { + HorizontalScrollTo(xOffset - dX); + ScrollTo(topLine - dY, true); + } +} + +//-------------------------------------------------------------------------------------------------- + +// Helper methods for NSResponder actions. + +void ScintillaCocoa::SelectAll() +{ + Editor::SelectAll(); +} + +void ScintillaCocoa::DeleteBackward() +{ + KeyDown(SCK_BACK, false, false, false, nil); +} + +void ScintillaCocoa::Cut() +{ + Editor::Cut(); +} + +void ScintillaCocoa::Undo() +{ + Editor::Undo(); +} + +void ScintillaCocoa::Redo() +{ + Editor::Redo(); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Creates and returns a popup menu, which is then displayed by the Cocoa framework. + */ +NSMenu* ScintillaCocoa::CreateContextMenu(NSEvent* /* event */) +{ + // Call ScintillaBase to create the context menu. + ContextMenu(Point(0, 0)); + + return reinterpret_cast(popup.GetID()); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * An intermediate function to forward context menu commands from the menu action handler to + * scintilla. + */ +void ScintillaCocoa::HandleCommand(NSInteger command) +{ + Command(static_cast(command)); +} + +//-------------------------------------------------------------------------------------------------- + +void ScintillaCocoa::ActiveStateChanged(bool isActive) +{ + // If the window is being deactivated, lose the focus and turn off the ticking + if (!isActive) { + DropCaret(); + //SetFocusState( false ); + SetTicking( false ); + } else { + ShowCaretAtCurrentPosition(); + } +} + + +//-------------------------------------------------------------------------------------------------- + diff --git a/scintilla/cocoa/ScintillaFramework/English.lproj/InfoPlist.strings b/ThirdLibs/scintilla/cocoa/ScintillaFramework/English.lproj/InfoPlist.strings similarity index 100% rename from scintilla/cocoa/ScintillaFramework/English.lproj/InfoPlist.strings rename to ThirdLibs/scintilla/cocoa/ScintillaFramework/English.lproj/InfoPlist.strings diff --git a/scintilla/cocoa/ScintillaFramework/Info.plist b/ThirdLibs/scintilla/cocoa/ScintillaFramework/Info.plist similarity index 100% rename from scintilla/cocoa/ScintillaFramework/Info.plist rename to ThirdLibs/scintilla/cocoa/ScintillaFramework/Info.plist diff --git a/scintilla/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj b/ThirdLibs/scintilla/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj similarity index 100% rename from scintilla/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj rename to ThirdLibs/scintilla/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj diff --git a/scintilla/cocoa/ScintillaTest/AppController.h b/ThirdLibs/scintilla/cocoa/ScintillaTest/AppController.h similarity index 95% rename from scintilla/cocoa/ScintillaTest/AppController.h rename to ThirdLibs/scintilla/cocoa/ScintillaTest/AppController.h index a9ceb6ed..dbc2417f 100644 --- a/scintilla/cocoa/ScintillaTest/AppController.h +++ b/ThirdLibs/scintilla/cocoa/ScintillaTest/AppController.h @@ -1,24 +1,24 @@ -/** - * AppController.h - * SciTest - * - * Created by Mike Lischke on 01.04.09. - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). - */ - -#import - -#import "ScintillaView.h" -#import "InfoBar.h" - -@interface AppController : NSObject { - IBOutlet NSBox *mEditHost; - ScintillaView* mEditor; -} - -- (void) awakeFromNib; -- (void) setupEditor; -- (IBAction) searchText: (id) sender; - -@end +/** + * AppController.h + * SciTest + * + * Created by Mike Lischke on 01.04.09. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). + */ + +#import + +#import "ScintillaView.h" +#import "InfoBar.h" + +@interface AppController : NSObject { + IBOutlet NSBox *mEditHost; + ScintillaView* mEditor; +} + +- (void) awakeFromNib; +- (void) setupEditor; +- (IBAction) searchText: (id) sender; + +@end diff --git a/scintilla/cocoa/ScintillaTest/AppController.mm b/ThirdLibs/scintilla/cocoa/ScintillaTest/AppController.mm similarity index 97% rename from scintilla/cocoa/ScintillaTest/AppController.mm rename to ThirdLibs/scintilla/cocoa/ScintillaTest/AppController.mm index 131e877c..294704f0 100644 --- a/scintilla/cocoa/ScintillaTest/AppController.mm +++ b/ThirdLibs/scintilla/cocoa/ScintillaTest/AppController.mm @@ -1,270 +1,270 @@ -/** - * AppController.m - * ScintillaTest - * - * Created by Mike Lischke on 01.04.09. - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). - */ - -#import "AppController.h" - -const char major_keywords[] = - "accessible add all alter analyze and as asc asensitive " - "before between bigint binary blob both by " - "call cascade case change char character check collate column condition connection constraint " - "continue convert create cross current_date current_time current_timestamp current_user cursor " - "database databases day_hour day_microsecond day_minute day_second dec decimal declare default " - "delayed delete desc describe deterministic distinct distinctrow div double drop dual " - "each else elseif enclosed escaped exists exit explain " - "false fetch float float4 float8 for force foreign from fulltext " - "goto grant group " - "having high_priority hour_microsecond hour_minute hour_second " - "if ignore in index infile inner inout insensitive insert int int1 int2 int3 int4 int8 integer " - "interval into is iterate " - "join " - "key keys kill " - "label leading leave left like limit linear lines load localtime localtimestamp lock long " - "longblob longtext loop low_priority " - "master_ssl_verify_server_cert match mediumblob mediumint mediumtext middleint minute_microsecond " - "minute_second mod modifies " - "natural not no_write_to_binlog null numeric " - "on optimize option optionally or order out outer outfile " - "precision primary procedure purge " - "range read reads read_only read_write real references regexp release rename repeat replace " - "require restrict return revoke right rlike " - "schema schemas second_microsecond select sensitive separator set show smallint spatial specific " - "sql sqlexception sqlstate sqlwarning sql_big_result sql_calc_found_rows sql_small_result ssl " - "starting straight_join " - "table terminated then tinyblob tinyint tinytext to trailing trigger true " - "undo union unique unlock unsigned update upgrade usage use using utc_date utc_time utc_timestamp " - "values varbinary varchar varcharacter varying " - "when where while with write " - "xor " - "year_month " - "zerofill"; - -const char procedure_keywords[] = // Not reserved words but intrinsic part of procedure definitions. - "begin comment end"; - -const char client_keywords[] = // Definition of keywords only used by clients, not the server itself. - "delimiter"; - -const char user_keywords[] = // Definition of own keywords, not used by MySQL. - "edit"; - -//-------------------------------------------------------------------------------------------------- - -@implementation AppController - -- (void) awakeFromNib -{ - // Manually set up the scintilla editor. Create an instance and dock it to our edit host. - // Leave some free space around the new view to avoid overlapping with the box borders. - NSRect newFrame = mEditHost.frame; - newFrame.size.width -= 2 * newFrame.origin.x; - newFrame.size.height -= 3 * newFrame.origin.y; - - mEditor = [[[ScintillaView alloc] initWithFrame: newFrame] autorelease]; - - [mEditHost.contentView addSubview: mEditor]; - [mEditor setAutoresizesSubviews: YES]; - [mEditor setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; - - // Let's load some text for the editor, as initial content. - NSError* error = nil; - - NSString* path = [[NSBundle mainBundle] pathForResource: @"TestData" - ofType: @"sql" inDirectory: nil]; - - NSString* sql = [NSString stringWithContentsOfFile: path - encoding: NSUTF8StringEncoding - error: &error]; - if (error && [[error domain] isEqual: NSCocoaErrorDomain]) - NSLog(@"%@", error); - - [mEditor setString: sql]; - - [self setupEditor]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Initialize scintilla editor (styles, colors, markers, folding etc.]. - */ -- (void) setupEditor -{ - // Lexer type is MySQL. - [mEditor setGeneralProperty: SCI_SETLEXER parameter: SCLEX_MYSQL value: 0]; - // alternatively: [mEditor setEditorProperty: SCI_SETLEXERLANGUAGE parameter: nil value: (sptr_t) "mysql"]; - - // Number of styles we use with this lexer. - [mEditor setGeneralProperty: SCI_SETSTYLEBITS value: [mEditor getGeneralProperty: SCI_GETSTYLEBITSNEEDED]]; - - // Keywords to highlight. Indices are: - // 0 - Major keywords (reserved keywords) - // 1 - Normal keywords (everything not reserved but integral part of the language) - // 2 - Database objects - // 3 - Function keywords - // 4 - System variable keywords - // 5 - Procedure keywords (keywords used in procedures like "begin" and "end") - // 6..8 - User keywords 1..3 - [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 0 value: major_keywords]; - [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 5 value: procedure_keywords]; - [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 6 value: client_keywords]; - [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 7 value: user_keywords]; - - // Colors and styles for various syntactic elements. First the default style. - [mEditor setStringProperty: SCI_STYLESETFONT parameter: STYLE_DEFAULT value: @"Helvetica"]; - // [mEditor setStringProperty: SCI_STYLESETFONT parameter: STYLE_DEFAULT value: @"Monospac821 BT"]; // Very pleasing programmer's font. - [mEditor setGeneralProperty: SCI_STYLESETSIZE parameter: STYLE_DEFAULT value: 14]; - [mEditor setColorProperty: SCI_STYLESETFORE parameter: STYLE_DEFAULT value: [NSColor blackColor]]; - - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_DEFAULT value: [NSColor blackColor]]; - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_COMMENT fromHTML: @"#097BF7"]; - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_COMMENTLINE fromHTML: @"#097BF7"]; - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_HIDDENCOMMAND fromHTML: @"#097BF7"]; - [mEditor setColorProperty: SCI_STYLESETBACK parameter: SCE_MYSQL_HIDDENCOMMAND fromHTML: @"#F0F0F0"]; - - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_VARIABLE fromHTML: @"378EA5"]; - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_SYSTEMVARIABLE fromHTML: @"378EA5"]; - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_KNOWNSYSTEMVARIABLE fromHTML: @"#3A37A5"]; - - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_NUMBER fromHTML: @"#7F7F00"]; - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_SQSTRING fromHTML: @"#FFAA3E"]; - - // Note: if we were using ANSI quotes we would set the DQSTRING to the same color as the - // the back tick string. - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_DQSTRING fromHTML: @"#274A6D"]; - - // Keyword highlighting. - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_MAJORKEYWORD fromHTML: @"#007F00"]; - [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_MYSQL_MAJORKEYWORD value: 1]; - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_KEYWORD fromHTML: @"#007F00"]; - [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_MYSQL_KEYWORD value: 1]; - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_PROCEDUREKEYWORD fromHTML: @"#56007F"]; - [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_MYSQL_PROCEDUREKEYWORD value: 1]; - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_USER1 fromHTML: @"#808080"]; - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_USER2 fromHTML: @"#808080"]; - [mEditor setColorProperty: SCI_STYLESETBACK parameter: SCE_MYSQL_USER2 fromHTML: @"#F0E0E0"]; - - // The following 3 styles have no impact as we did not set a keyword list for any of them. - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_DATABASEOBJECT value: [NSColor redColor]]; - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_FUNCTION value: [NSColor redColor]]; - - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_IDENTIFIER value: [NSColor blackColor]]; - [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_QUOTEDIDENTIFIER fromHTML: @"#274A6D"]; - [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_SQL_OPERATOR value: 1]; - - // Line number style. - [mEditor setColorProperty: SCI_STYLESETFORE parameter: STYLE_LINENUMBER fromHTML: @"#F0F0F0"]; - [mEditor setColorProperty: SCI_STYLESETBACK parameter: STYLE_LINENUMBER fromHTML: @"#808080"]; - - [mEditor setGeneralProperty: SCI_SETMARGINTYPEN parameter: 0 value: SC_MARGIN_NUMBER]; - [mEditor setGeneralProperty: SCI_SETMARGINWIDTHN parameter: 0 value: 35]; - - // Markers. - [mEditor setGeneralProperty: SCI_SETMARGINWIDTHN parameter: 1 value: 16]; - - // Some special lexer properties. - [mEditor setLexerProperty: @"fold" value: @"1"]; - [mEditor setLexerProperty: @"fold.compact" value: @"0"]; - [mEditor setLexerProperty: @"fold.comment" value: @"1"]; - [mEditor setLexerProperty: @"fold.preprocessor" value: @"1"]; - - // Folder setup. - [mEditor setGeneralProperty: SCI_SETMARGINWIDTHN parameter: 2 value: 16]; - [mEditor setGeneralProperty: SCI_SETMARGINMASKN parameter: 2 value: SC_MASK_FOLDERS]; - [mEditor setGeneralProperty: SCI_SETMARGINSENSITIVEN parameter: 2 value: 1]; - [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDEROPEN value: SC_MARK_BOXMINUS]; - [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDER value: SC_MARK_BOXPLUS]; - [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDERSUB value: SC_MARK_VLINE]; - [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDERTAIL value: SC_MARK_LCORNER]; - [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDEREND value: SC_MARK_BOXPLUSCONNECTED]; - [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDEROPENMID value: SC_MARK_BOXMINUSCONNECTED]; - [mEditor setGeneralProperty - : SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDERMIDTAIL value: SC_MARK_TCORNER]; - for (int n= 25; n < 32; ++n) // Markers 25..31 are reserved for folding. - { - [mEditor setColorProperty: SCI_MARKERSETFORE parameter: n value: [NSColor whiteColor]]; - [mEditor setColorProperty: SCI_MARKERSETBACK parameter: n value: [NSColor blackColor]]; - } - - // Init markers & indicators for highlighting of syntax errors. - [mEditor setColorProperty: SCI_INDICSETFORE parameter: 0 value: [NSColor redColor]]; - [mEditor setGeneralProperty: SCI_INDICSETUNDER parameter: 0 value: 1]; - [mEditor setGeneralProperty: SCI_INDICSETSTYLE parameter: 0 value: INDIC_SQUIGGLE]; - - [mEditor setColorProperty: SCI_MARKERSETBACK parameter: 0 fromHTML: @"#B1151C"]; - - [mEditor setColorProperty: SCI_SETSELBACK parameter: 1 value: [NSColor selectedTextBackgroundColor]]; - - // Uncomment if you wanna see auto wrapping in action. - //[mEditor setGeneralProperty: SCI_SETWRAPMODE parameter: SC_WRAP_WORD value: 0]; - - InfoBar* infoBar = [[[InfoBar alloc] initWithFrame: NSMakeRect(0, 0, 400, 0)] autorelease]; - [infoBar setDisplay: IBShowAll]; - [mEditor setInfoBar: infoBar top: NO]; - [mEditor setStatusText: @"Operation complete"]; -} - -//-------------------------------------------------------------------------------------------------- - -/* XPM */ -static const char * box_xpm[] = { - "12 12 2 1", - " c None", - ". c #800000", - " .........", - " . . ..", - " . . . .", - "......... .", - ". . . .", - ". . . ..", - ". . .. .", - "......... .", - ". . . .", - ". . . . ", - ". . .. ", - "......... "}; - - -- (void) showAutocompletion -{ - const char *words = "Babylon-5?1 Battlestar-Galactica Millenium-Falcon?2 Moya?2 Serenity Voyager"; - [mEditor setGeneralProperty: SCI_AUTOCSETIGNORECASE parameter: 1 value:0]; - [mEditor setGeneralProperty: SCI_REGISTERIMAGE parameter: 1 value:(sptr_t)box_xpm]; - const int imSize = 12; - [mEditor setGeneralProperty: SCI_RGBAIMAGESETWIDTH parameter: imSize value:0]; - [mEditor setGeneralProperty: SCI_RGBAIMAGESETHEIGHT parameter: imSize value:0]; - char image[imSize * imSize * 4]; - for (size_t y = 0; y < imSize; y++) { - for (size_t x = 0; x < imSize; x++) { - char *p = image + (y * imSize + x) * 4; - p[0] = 0xFF; - p[1] = 0xA0; - p[2] = 0; - p[3] = x * 23; - } - } - [mEditor setGeneralProperty: SCI_REGISTERRGBAIMAGE parameter: 2 value:(sptr_t)image]; - [mEditor setGeneralProperty: SCI_AUTOCSHOW parameter: 0 value:(sptr_t)words]; -} - -- (IBAction) searchText: (id) sender -{ - NSSearchField* searchField = (NSSearchField*) sender; - [mEditor findAndHighlightText: [searchField stringValue] - matchCase: NO - wholeWord: NO - scrollTo: YES - wrap: YES]; - if ([[searchField stringValue] isEqualToString: @"XX"]) - [self showAutocompletion]; -} - -@end - -//-------------------------------------------------------------------------------------------------- - +/** + * AppController.m + * ScintillaTest + * + * Created by Mike Lischke on 01.04.09. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). + */ + +#import "AppController.h" + +const char major_keywords[] = + "accessible add all alter analyze and as asc asensitive " + "before between bigint binary blob both by " + "call cascade case change char character check collate column condition connection constraint " + "continue convert create cross current_date current_time current_timestamp current_user cursor " + "database databases day_hour day_microsecond day_minute day_second dec decimal declare default " + "delayed delete desc describe deterministic distinct distinctrow div double drop dual " + "each else elseif enclosed escaped exists exit explain " + "false fetch float float4 float8 for force foreign from fulltext " + "goto grant group " + "having high_priority hour_microsecond hour_minute hour_second " + "if ignore in index infile inner inout insensitive insert int int1 int2 int3 int4 int8 integer " + "interval into is iterate " + "join " + "key keys kill " + "label leading leave left like limit linear lines load localtime localtimestamp lock long " + "longblob longtext loop low_priority " + "master_ssl_verify_server_cert match mediumblob mediumint mediumtext middleint minute_microsecond " + "minute_second mod modifies " + "natural not no_write_to_binlog null numeric " + "on optimize option optionally or order out outer outfile " + "precision primary procedure purge " + "range read reads read_only read_write real references regexp release rename repeat replace " + "require restrict return revoke right rlike " + "schema schemas second_microsecond select sensitive separator set show smallint spatial specific " + "sql sqlexception sqlstate sqlwarning sql_big_result sql_calc_found_rows sql_small_result ssl " + "starting straight_join " + "table terminated then tinyblob tinyint tinytext to trailing trigger true " + "undo union unique unlock unsigned update upgrade usage use using utc_date utc_time utc_timestamp " + "values varbinary varchar varcharacter varying " + "when where while with write " + "xor " + "year_month " + "zerofill"; + +const char procedure_keywords[] = // Not reserved words but intrinsic part of procedure definitions. + "begin comment end"; + +const char client_keywords[] = // Definition of keywords only used by clients, not the server itself. + "delimiter"; + +const char user_keywords[] = // Definition of own keywords, not used by MySQL. + "edit"; + +//-------------------------------------------------------------------------------------------------- + +@implementation AppController + +- (void) awakeFromNib +{ + // Manually set up the scintilla editor. Create an instance and dock it to our edit host. + // Leave some free space around the new view to avoid overlapping with the box borders. + NSRect newFrame = mEditHost.frame; + newFrame.size.width -= 2 * newFrame.origin.x; + newFrame.size.height -= 3 * newFrame.origin.y; + + mEditor = [[[ScintillaView alloc] initWithFrame: newFrame] autorelease]; + + [mEditHost.contentView addSubview: mEditor]; + [mEditor setAutoresizesSubviews: YES]; + [mEditor setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; + + // Let's load some text for the editor, as initial content. + NSError* error = nil; + + NSString* path = [[NSBundle mainBundle] pathForResource: @"TestData" + ofType: @"sql" inDirectory: nil]; + + NSString* sql = [NSString stringWithContentsOfFile: path + encoding: NSUTF8StringEncoding + error: &error]; + if (error && [[error domain] isEqual: NSCocoaErrorDomain]) + NSLog(@"%@", error); + + [mEditor setString: sql]; + + [self setupEditor]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Initialize scintilla editor (styles, colors, markers, folding etc.]. + */ +- (void) setupEditor +{ + // Lexer type is MySQL. + [mEditor setGeneralProperty: SCI_SETLEXER parameter: SCLEX_MYSQL value: 0]; + // alternatively: [mEditor setEditorProperty: SCI_SETLEXERLANGUAGE parameter: nil value: (sptr_t) "mysql"]; + + // Number of styles we use with this lexer. + [mEditor setGeneralProperty: SCI_SETSTYLEBITS value: [mEditor getGeneralProperty: SCI_GETSTYLEBITSNEEDED]]; + + // Keywords to highlight. Indices are: + // 0 - Major keywords (reserved keywords) + // 1 - Normal keywords (everything not reserved but integral part of the language) + // 2 - Database objects + // 3 - Function keywords + // 4 - System variable keywords + // 5 - Procedure keywords (keywords used in procedures like "begin" and "end") + // 6..8 - User keywords 1..3 + [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 0 value: major_keywords]; + [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 5 value: procedure_keywords]; + [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 6 value: client_keywords]; + [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 7 value: user_keywords]; + + // Colors and styles for various syntactic elements. First the default style. + [mEditor setStringProperty: SCI_STYLESETFONT parameter: STYLE_DEFAULT value: @"Helvetica"]; + // [mEditor setStringProperty: SCI_STYLESETFONT parameter: STYLE_DEFAULT value: @"Monospac821 BT"]; // Very pleasing programmer's font. + [mEditor setGeneralProperty: SCI_STYLESETSIZE parameter: STYLE_DEFAULT value: 14]; + [mEditor setColorProperty: SCI_STYLESETFORE parameter: STYLE_DEFAULT value: [NSColor blackColor]]; + + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_DEFAULT value: [NSColor blackColor]]; + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_COMMENT fromHTML: @"#097BF7"]; + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_COMMENTLINE fromHTML: @"#097BF7"]; + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_HIDDENCOMMAND fromHTML: @"#097BF7"]; + [mEditor setColorProperty: SCI_STYLESETBACK parameter: SCE_MYSQL_HIDDENCOMMAND fromHTML: @"#F0F0F0"]; + + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_VARIABLE fromHTML: @"378EA5"]; + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_SYSTEMVARIABLE fromHTML: @"378EA5"]; + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_KNOWNSYSTEMVARIABLE fromHTML: @"#3A37A5"]; + + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_NUMBER fromHTML: @"#7F7F00"]; + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_SQSTRING fromHTML: @"#FFAA3E"]; + + // Note: if we were using ANSI quotes we would set the DQSTRING to the same color as the + // the back tick string. + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_DQSTRING fromHTML: @"#274A6D"]; + + // Keyword highlighting. + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_MAJORKEYWORD fromHTML: @"#007F00"]; + [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_MYSQL_MAJORKEYWORD value: 1]; + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_KEYWORD fromHTML: @"#007F00"]; + [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_MYSQL_KEYWORD value: 1]; + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_PROCEDUREKEYWORD fromHTML: @"#56007F"]; + [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_MYSQL_PROCEDUREKEYWORD value: 1]; + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_USER1 fromHTML: @"#808080"]; + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_USER2 fromHTML: @"#808080"]; + [mEditor setColorProperty: SCI_STYLESETBACK parameter: SCE_MYSQL_USER2 fromHTML: @"#F0E0E0"]; + + // The following 3 styles have no impact as we did not set a keyword list for any of them. + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_DATABASEOBJECT value: [NSColor redColor]]; + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_FUNCTION value: [NSColor redColor]]; + + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_IDENTIFIER value: [NSColor blackColor]]; + [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_QUOTEDIDENTIFIER fromHTML: @"#274A6D"]; + [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_SQL_OPERATOR value: 1]; + + // Line number style. + [mEditor setColorProperty: SCI_STYLESETFORE parameter: STYLE_LINENUMBER fromHTML: @"#F0F0F0"]; + [mEditor setColorProperty: SCI_STYLESETBACK parameter: STYLE_LINENUMBER fromHTML: @"#808080"]; + + [mEditor setGeneralProperty: SCI_SETMARGINTYPEN parameter: 0 value: SC_MARGIN_NUMBER]; + [mEditor setGeneralProperty: SCI_SETMARGINWIDTHN parameter: 0 value: 35]; + + // Markers. + [mEditor setGeneralProperty: SCI_SETMARGINWIDTHN parameter: 1 value: 16]; + + // Some special lexer properties. + [mEditor setLexerProperty: @"fold" value: @"1"]; + [mEditor setLexerProperty: @"fold.compact" value: @"0"]; + [mEditor setLexerProperty: @"fold.comment" value: @"1"]; + [mEditor setLexerProperty: @"fold.preprocessor" value: @"1"]; + + // Folder setup. + [mEditor setGeneralProperty: SCI_SETMARGINWIDTHN parameter: 2 value: 16]; + [mEditor setGeneralProperty: SCI_SETMARGINMASKN parameter: 2 value: SC_MASK_FOLDERS]; + [mEditor setGeneralProperty: SCI_SETMARGINSENSITIVEN parameter: 2 value: 1]; + [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDEROPEN value: SC_MARK_BOXMINUS]; + [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDER value: SC_MARK_BOXPLUS]; + [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDERSUB value: SC_MARK_VLINE]; + [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDERTAIL value: SC_MARK_LCORNER]; + [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDEREND value: SC_MARK_BOXPLUSCONNECTED]; + [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDEROPENMID value: SC_MARK_BOXMINUSCONNECTED]; + [mEditor setGeneralProperty + : SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDERMIDTAIL value: SC_MARK_TCORNER]; + for (int n= 25; n < 32; ++n) // Markers 25..31 are reserved for folding. + { + [mEditor setColorProperty: SCI_MARKERSETFORE parameter: n value: [NSColor whiteColor]]; + [mEditor setColorProperty: SCI_MARKERSETBACK parameter: n value: [NSColor blackColor]]; + } + + // Init markers & indicators for highlighting of syntax errors. + [mEditor setColorProperty: SCI_INDICSETFORE parameter: 0 value: [NSColor redColor]]; + [mEditor setGeneralProperty: SCI_INDICSETUNDER parameter: 0 value: 1]; + [mEditor setGeneralProperty: SCI_INDICSETSTYLE parameter: 0 value: INDIC_SQUIGGLE]; + + [mEditor setColorProperty: SCI_MARKERSETBACK parameter: 0 fromHTML: @"#B1151C"]; + + [mEditor setColorProperty: SCI_SETSELBACK parameter: 1 value: [NSColor selectedTextBackgroundColor]]; + + // Uncomment if you wanna see auto wrapping in action. + //[mEditor setGeneralProperty: SCI_SETWRAPMODE parameter: SC_WRAP_WORD value: 0]; + + InfoBar* infoBar = [[[InfoBar alloc] initWithFrame: NSMakeRect(0, 0, 400, 0)] autorelease]; + [infoBar setDisplay: IBShowAll]; + [mEditor setInfoBar: infoBar top: NO]; + [mEditor setStatusText: @"Operation complete"]; +} + +//-------------------------------------------------------------------------------------------------- + +/* XPM */ +static const char * box_xpm[] = { + "12 12 2 1", + " c None", + ". c #800000", + " .........", + " . . ..", + " . . . .", + "......... .", + ". . . .", + ". . . ..", + ". . .. .", + "......... .", + ". . . .", + ". . . . ", + ". . .. ", + "......... "}; + + +- (void) showAutocompletion +{ + const char *words = "Babylon-5?1 Battlestar-Galactica Millenium-Falcon?2 Moya?2 Serenity Voyager"; + [mEditor setGeneralProperty: SCI_AUTOCSETIGNORECASE parameter: 1 value:0]; + [mEditor setGeneralProperty: SCI_REGISTERIMAGE parameter: 1 value:(sptr_t)box_xpm]; + const int imSize = 12; + [mEditor setGeneralProperty: SCI_RGBAIMAGESETWIDTH parameter: imSize value:0]; + [mEditor setGeneralProperty: SCI_RGBAIMAGESETHEIGHT parameter: imSize value:0]; + char image[imSize * imSize * 4]; + for (size_t y = 0; y < imSize; y++) { + for (size_t x = 0; x < imSize; x++) { + char *p = image + (y * imSize + x) * 4; + p[0] = 0xFF; + p[1] = 0xA0; + p[2] = 0; + p[3] = x * 23; + } + } + [mEditor setGeneralProperty: SCI_REGISTERRGBAIMAGE parameter: 2 value:(sptr_t)image]; + [mEditor setGeneralProperty: SCI_AUTOCSHOW parameter: 0 value:(sptr_t)words]; +} + +- (IBAction) searchText: (id) sender +{ + NSSearchField* searchField = (NSSearchField*) sender; + [mEditor findAndHighlightText: [searchField stringValue] + matchCase: NO + wholeWord: NO + scrollTo: YES + wrap: YES]; + if ([[searchField stringValue] isEqualToString: @"XX"]) + [self showAutocompletion]; +} + +@end + +//-------------------------------------------------------------------------------------------------- + diff --git a/scintilla/cocoa/ScintillaTest/English.lproj/InfoPlist.strings b/ThirdLibs/scintilla/cocoa/ScintillaTest/English.lproj/InfoPlist.strings similarity index 100% rename from scintilla/cocoa/ScintillaTest/English.lproj/InfoPlist.strings rename to ThirdLibs/scintilla/cocoa/ScintillaTest/English.lproj/InfoPlist.strings diff --git a/scintilla/cocoa/ScintillaTest/English.lproj/MainMenu.xib b/ThirdLibs/scintilla/cocoa/ScintillaTest/English.lproj/MainMenu.xib similarity index 100% rename from scintilla/cocoa/ScintillaTest/English.lproj/MainMenu.xib rename to ThirdLibs/scintilla/cocoa/ScintillaTest/English.lproj/MainMenu.xib diff --git a/scintilla/cocoa/ScintillaTest/Info.plist b/ThirdLibs/scintilla/cocoa/ScintillaTest/Info.plist similarity index 100% rename from scintilla/cocoa/ScintillaTest/Info.plist rename to ThirdLibs/scintilla/cocoa/ScintillaTest/Info.plist diff --git a/scintilla/cocoa/ScintillaTest/Scintilla-Info.plist b/ThirdLibs/scintilla/cocoa/ScintillaTest/Scintilla-Info.plist similarity index 100% rename from scintilla/cocoa/ScintillaTest/Scintilla-Info.plist rename to ThirdLibs/scintilla/cocoa/ScintillaTest/Scintilla-Info.plist diff --git a/scintilla/cocoa/ScintillaTest/ScintillaTest.xcodeproj/project.pbxproj b/ThirdLibs/scintilla/cocoa/ScintillaTest/ScintillaTest.xcodeproj/project.pbxproj similarity index 100% rename from scintilla/cocoa/ScintillaTest/ScintillaTest.xcodeproj/project.pbxproj rename to ThirdLibs/scintilla/cocoa/ScintillaTest/ScintillaTest.xcodeproj/project.pbxproj diff --git a/scintilla/cocoa/ScintillaTest/TestData.sql b/ThirdLibs/scintilla/cocoa/ScintillaTest/TestData.sql similarity index 100% rename from scintilla/cocoa/ScintillaTest/TestData.sql rename to ThirdLibs/scintilla/cocoa/ScintillaTest/TestData.sql diff --git a/scintilla/cocoa/ScintillaTest/main.m b/ThirdLibs/scintilla/cocoa/ScintillaTest/main.m similarity index 96% rename from scintilla/cocoa/ScintillaTest/main.m rename to ThirdLibs/scintilla/cocoa/ScintillaTest/main.m index 59ff6b2e..9b0c5858 100644 --- a/scintilla/cocoa/ScintillaTest/main.m +++ b/ThirdLibs/scintilla/cocoa/ScintillaTest/main.m @@ -1,15 +1,15 @@ -/** - * main.m - * ScintillaTest - * - * Created by Mike Lischke on 02.04.09. - * Copyright Sun Microsystems, Inc 2009. All rights reserved. - * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). - */ - -#import - -int main(int argc, char *argv[]) -{ - return NSApplicationMain(argc, (const char **) argv); -} +/** + * main.m + * ScintillaTest + * + * Created by Mike Lischke on 02.04.09. + * Copyright Sun Microsystems, Inc 2009. All rights reserved. + * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). + */ + +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/scintilla/cocoa/ScintillaView.h b/ThirdLibs/scintilla/cocoa/ScintillaView.h similarity index 97% rename from scintilla/cocoa/ScintillaView.h rename to ThirdLibs/scintilla/cocoa/ScintillaView.h index f9c83698..4dac0ad0 100644 --- a/scintilla/cocoa/ScintillaView.h +++ b/ThirdLibs/scintilla/cocoa/ScintillaView.h @@ -1,140 +1,140 @@ - -/** - * Declaration of the native Cocoa View that serves as container for the scintilla parts. - * - * Created by Mike Lischke. - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). - */ - -#import - -#import "Platform.h" -#import "Scintilla.h" -#import "SciLexer.h" - -#import "InfoBarCommunicator.h" -#import "ScintillaCocoa.h" - -@class ScintillaView; - -extern NSString *SCIUpdateUINotification; - -/** - * InnerView is the Cocoa interface to the Scintilla backend. It handles text input and - * provides a canvas for painting the output. - */ -@interface InnerView : NSView -{ -@private - ScintillaView* mOwner; - NSCursor* mCurrentCursor; - NSTrackingRectTag mCurrentTrackingRect; - - // Set when we are in composition mode and partial input is displayed. - NSRange mMarkedTextRange; -} - -- (void) dealloc; -- (void) removeMarkedText; -- (void) setCursor: (Scintilla::Window::Cursor) cursor; - -- (BOOL) canUndo; -- (BOOL) canRedo; - -@property (retain) ScintillaView* owner; -@end - -@interface ScintillaView : NSView -{ -@private - // The back end is kind of a controller and model in one. - // It uses the content view for display. - Scintilla::ScintillaCocoa* mBackend; - - // The object (eg NSDocument) that controls the ScintillaView. - NSObject* mOwner; - - // This is the actual content to which the backend renders itself. - InnerView* mContent; - - NSScroller* mHorizontalScroller; - NSScroller* mVerticalScroller; - - // Area to display additional controls (e.g. zoom info, caret position, status info). - NSView * mInfoBar; - BOOL mInfoBarAtTop; - int mInitialInfoBarWidth; -} - -- (void) dealloc; -- (void) layout; - -- (void) sendNotification: (NSString*) notificationName; -- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location - value: (float) value; -- (void) setCallback: (id ) callback; - -- (void) suspendDrawing: (BOOL) suspend; - -// Scroller handling -- (BOOL) setVerticalScrollRange: (int) range page: (int) page; -- (void) setVerticalScrollPosition: (float) position; -- (BOOL) setHorizontalScrollRange: (int) range page: (int) page; -- (void) setHorizontalScrollPosition: (float) position; - -- (void) scrollerAction: (id) sender; -- (InnerView*) content; - -// NSTextView compatibility layer. -- (NSString*) string; -- (void) setString: (NSString*) aString; -- (void) insertText: (NSString*) aString; -- (void) setEditable: (BOOL) editable; -- (BOOL) isEditable; -- (NSRange) selectedRange; - -- (NSString*) selectedString; - -- (void)setFontName: (NSString*) font - size: (int) size - bold: (BOOL) bold - italic: (BOOL) italic; - -// Native call through to the backend. -+ (sptr_t) directCall: (ScintillaView*) sender message: (unsigned int) message wParam: (uptr_t) wParam - lParam: (sptr_t) lParam; - -// Back end properties getters and setters. -- (void) setGeneralProperty: (int) property parameter: (long) parameter value: (long) value; -- (void) setGeneralProperty: (int) property value: (long) value; - -- (long) getGeneralProperty: (int) property; -- (long) getGeneralProperty: (int) property parameter: (long) parameter; -- (long) getGeneralProperty: (int) property parameter: (long) parameter extra: (long) extra; -- (long) getGeneralProperty: (int) property ref: (const void*) ref; -- (void) setColorProperty: (int) property parameter: (long) parameter value: (NSColor*) value; -- (void) setColorProperty: (int) property parameter: (long) parameter fromHTML: (NSString*) fromHTML; -- (NSColor*) getColorProperty: (int) property parameter: (long) parameter; -- (void) setReferenceProperty: (int) property parameter: (long) parameter value: (const void*) value; -- (const void*) getReferenceProperty: (int) property parameter: (long) parameter; -- (void) setStringProperty: (int) property parameter: (long) parameter value: (NSString*) value; -- (NSString*) getStringProperty: (int) property parameter: (long) parameter; -- (void) setLexerProperty: (NSString*) name value: (NSString*) value; -- (NSString*) getLexerProperty: (NSString*) name; - -- (void) registerNotifyCallback: (intptr_t) windowid value: (Scintilla::SciNotifyFunc) callback; - -- (void) setInfoBar: (NSView *) aView top: (BOOL) top; -- (void) setStatusText: (NSString*) text; - -- (void) findAndHighlightText: (NSString*) searchText - matchCase: (BOOL) matchCase - wholeWord: (BOOL) wholeWord - scrollTo: (BOOL) scrollTo - wrap: (BOOL) wrap; - -@property Scintilla::ScintillaCocoa* backend; -@property (retain) NSObject* owner; -@end + +/** + * Declaration of the native Cocoa View that serves as container for the scintilla parts. + * + * Created by Mike Lischke. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). + */ + +#import + +#import "Platform.h" +#import "Scintilla.h" +#import "SciLexer.h" + +#import "InfoBarCommunicator.h" +#import "ScintillaCocoa.h" + +@class ScintillaView; + +extern NSString *SCIUpdateUINotification; + +/** + * InnerView is the Cocoa interface to the Scintilla backend. It handles text input and + * provides a canvas for painting the output. + */ +@interface InnerView : NSView +{ +@private + ScintillaView* mOwner; + NSCursor* mCurrentCursor; + NSTrackingRectTag mCurrentTrackingRect; + + // Set when we are in composition mode and partial input is displayed. + NSRange mMarkedTextRange; +} + +- (void) dealloc; +- (void) removeMarkedText; +- (void) setCursor: (Scintilla::Window::Cursor) cursor; + +- (BOOL) canUndo; +- (BOOL) canRedo; + +@property (retain) ScintillaView* owner; +@end + +@interface ScintillaView : NSView +{ +@private + // The back end is kind of a controller and model in one. + // It uses the content view for display. + Scintilla::ScintillaCocoa* mBackend; + + // The object (eg NSDocument) that controls the ScintillaView. + NSObject* mOwner; + + // This is the actual content to which the backend renders itself. + InnerView* mContent; + + NSScroller* mHorizontalScroller; + NSScroller* mVerticalScroller; + + // Area to display additional controls (e.g. zoom info, caret position, status info). + NSView * mInfoBar; + BOOL mInfoBarAtTop; + int mInitialInfoBarWidth; +} + +- (void) dealloc; +- (void) layout; + +- (void) sendNotification: (NSString*) notificationName; +- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location + value: (float) value; +- (void) setCallback: (id ) callback; + +- (void) suspendDrawing: (BOOL) suspend; + +// Scroller handling +- (BOOL) setVerticalScrollRange: (int) range page: (int) page; +- (void) setVerticalScrollPosition: (float) position; +- (BOOL) setHorizontalScrollRange: (int) range page: (int) page; +- (void) setHorizontalScrollPosition: (float) position; + +- (void) scrollerAction: (id) sender; +- (InnerView*) content; + +// NSTextView compatibility layer. +- (NSString*) string; +- (void) setString: (NSString*) aString; +- (void) insertText: (NSString*) aString; +- (void) setEditable: (BOOL) editable; +- (BOOL) isEditable; +- (NSRange) selectedRange; + +- (NSString*) selectedString; + +- (void)setFontName: (NSString*) font + size: (int) size + bold: (BOOL) bold + italic: (BOOL) italic; + +// Native call through to the backend. ++ (sptr_t) directCall: (ScintillaView*) sender message: (unsigned int) message wParam: (uptr_t) wParam + lParam: (sptr_t) lParam; + +// Back end properties getters and setters. +- (void) setGeneralProperty: (int) property parameter: (long) parameter value: (long) value; +- (void) setGeneralProperty: (int) property value: (long) value; + +- (long) getGeneralProperty: (int) property; +- (long) getGeneralProperty: (int) property parameter: (long) parameter; +- (long) getGeneralProperty: (int) property parameter: (long) parameter extra: (long) extra; +- (long) getGeneralProperty: (int) property ref: (const void*) ref; +- (void) setColorProperty: (int) property parameter: (long) parameter value: (NSColor*) value; +- (void) setColorProperty: (int) property parameter: (long) parameter fromHTML: (NSString*) fromHTML; +- (NSColor*) getColorProperty: (int) property parameter: (long) parameter; +- (void) setReferenceProperty: (int) property parameter: (long) parameter value: (const void*) value; +- (const void*) getReferenceProperty: (int) property parameter: (long) parameter; +- (void) setStringProperty: (int) property parameter: (long) parameter value: (NSString*) value; +- (NSString*) getStringProperty: (int) property parameter: (long) parameter; +- (void) setLexerProperty: (NSString*) name value: (NSString*) value; +- (NSString*) getLexerProperty: (NSString*) name; + +- (void) registerNotifyCallback: (intptr_t) windowid value: (Scintilla::SciNotifyFunc) callback; + +- (void) setInfoBar: (NSView *) aView top: (BOOL) top; +- (void) setStatusText: (NSString*) text; + +- (void) findAndHighlightText: (NSString*) searchText + matchCase: (BOOL) matchCase + wholeWord: (BOOL) wholeWord + scrollTo: (BOOL) scrollTo + wrap: (BOOL) wrap; + +@property Scintilla::ScintillaCocoa* backend; +@property (retain) NSObject* owner; +@end diff --git a/scintilla/cocoa/ScintillaView.mm b/ThirdLibs/scintilla/cocoa/ScintillaView.mm similarity index 96% rename from scintilla/cocoa/ScintillaView.mm rename to ThirdLibs/scintilla/cocoa/ScintillaView.mm index 30d01f63..0659eb2c 100644 --- a/scintilla/cocoa/ScintillaView.mm +++ b/ThirdLibs/scintilla/cocoa/ScintillaView.mm @@ -1,1569 +1,1569 @@ - -/** - * Implementation of the native Cocoa View that serves as container for the scintilla parts. - * - * Created by Mike Lischke. - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). - */ - -#import "ScintillaView.h" - -using namespace Scintilla; - -// Two additional cursors we need, which aren't provided by Cocoa. -static NSCursor* reverseArrowCursor; -static NSCursor* waitCursor; - -// The scintilla indicator used for keyboard input. -#define INPUT_INDICATOR INDIC_MAX - 1 - -NSString *SCIUpdateUINotification = @"SCIUpdateUI"; - -@implementation InnerView - -@synthesize owner = mOwner; - -//-------------------------------------------------------------------------------------------------- - -- (NSView*) initWithFrame: (NSRect) frame -{ - self = [super initWithFrame: frame]; - - if (self != nil) - { - // Some initialization for our view. - mCurrentCursor = [[NSCursor arrowCursor] retain]; - mCurrentTrackingRect = 0; - mMarkedTextRange = NSMakeRange(NSNotFound, 0); - - [self registerForDraggedTypes: [NSArray arrayWithObjects: - NSStringPboardType, ScintillaRecPboardType, NSFilenamesPboardType, nil]]; - } - - return self; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * When the view is resized we need to update our tracking rectangle and let the backend know. - */ -- (void) setFrame: (NSRect) frame -{ - [super setFrame: frame]; - - // Make the content also a tracking rectangle for mouse events. - if (mCurrentTrackingRect != 0) - [self removeTrackingRect: mCurrentTrackingRect]; - mCurrentTrackingRect = [self addTrackingRect: [self bounds] - owner: self - userData: nil - assumeInside: YES]; - mOwner.backend->Resize(); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called by the backend if a new cursor must be set for the view. - */ -- (void) setCursor: (Window::Cursor) cursor -{ - [mCurrentCursor autorelease]; - switch (cursor) - { - case Window::cursorText: - mCurrentCursor = [NSCursor IBeamCursor]; - break; - case Window::cursorArrow: - mCurrentCursor = [NSCursor arrowCursor]; - break; - case Window::cursorWait: - mCurrentCursor = waitCursor; - break; - case Window::cursorHoriz: - mCurrentCursor = [NSCursor resizeLeftRightCursor]; - break; - case Window::cursorVert: - mCurrentCursor = [NSCursor resizeUpDownCursor]; - break; - case Window::cursorReverseArrow: - mCurrentCursor = reverseArrowCursor; - break; - case Window::cursorUp: - default: - mCurrentCursor = [NSCursor arrowCursor]; - break; - } - - [mCurrentCursor retain]; - - // Trigger recreation of the cursor rectangle(s). - [[self window] invalidateCursorRectsForView: self]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * This method is called to give us the opportunity to define our mouse sensitive rectangle. - */ -- (void) resetCursorRects -{ - [super resetCursorRects]; - - // We only have one cursor rect: our bounds. - [self addCursorRect: [self bounds] cursor: mCurrentCursor]; - [mCurrentCursor setOnMouseEntered: YES]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Gets called by the runtime when the view needs repainting. - */ -- (void) drawRect: (NSRect) rect -{ - CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; - - mOwner.backend->Draw(rect, context); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Windows uses a client coordinate system where the upper left corner is the origin in a window - * (and so does Scintilla). We have to adjust for that. However by returning YES here, we are - * already done with that. - * Note that because of returning YES here most coordinates we use now (e.g. for painting, - * invalidating rectangles etc.) are given with +Y pointing down! - */ -- (BOOL) isFlipped -{ - return YES; -} - -//-------------------------------------------------------------------------------------------------- - -- (BOOL) isOpaque -{ - return YES; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Implement the "click through" behavior by telling the caller we accept the first mouse event too. - */ -- (BOOL) acceptsFirstMouse: (NSEvent *) theEvent -{ -#pragma unused(theEvent) - return YES; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Make this view accepting events as first responder. - */ -- (BOOL) acceptsFirstResponder -{ - return YES; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called by the framework if it wants to show a context menu for the editor. - */ -- (NSMenu*) menuForEvent: (NSEvent*) theEvent -{ - if (![mOwner respondsToSelector: @selector(menuForEvent:)]) - return mOwner.backend->CreateContextMenu(theEvent); - else - return [mOwner menuForEvent: theEvent]; -} - -//-------------------------------------------------------------------------------------------------- - -// Adoption of NSTextInput protocol. - -- (NSAttributedString*) attributedSubstringFromRange: (NSRange) range -{ - return nil; -} - -//-------------------------------------------------------------------------------------------------- - -- (NSUInteger) characterIndexForPoint: (NSPoint) point -{ - return NSNotFound; -} - -//-------------------------------------------------------------------------------------------------- - -- (NSInteger) conversationIdentifier -{ - return (NSInteger) self; - -} - -//-------------------------------------------------------------------------------------------------- - -- (void) doCommandBySelector: (SEL) selector -{ - if ([self respondsToSelector: @selector(selector)]) - [self performSelector: selector withObject: nil]; -} - -//-------------------------------------------------------------------------------------------------- - -- (NSRect) firstRectForCharacterRange: (NSRange) range -{ - return NSZeroRect; -} - -//-------------------------------------------------------------------------------------------------- - -- (BOOL) hasMarkedText -{ - return mMarkedTextRange.length > 0; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * General text input. Used to insert new text at the current input position, replacing the current - * selection if there is any. - */ -- (void) insertText: (id) aString -{ - // Remove any previously marked text first. - [self removeMarkedText]; - NSString* newText = @""; - if ([aString isKindOfClass:[NSString class]]) - newText = (NSString*) aString; - else if ([aString isKindOfClass:[NSAttributedString class]]) - newText = (NSString*) [aString string]; - - mOwner.backend->InsertText(newText); -} - -//-------------------------------------------------------------------------------------------------- - -- (NSRange) markedRange -{ - return mMarkedTextRange; -} - -//-------------------------------------------------------------------------------------------------- - -- (NSRange) selectedRange -{ - long begin = [mOwner getGeneralProperty: SCI_GETSELECTIONSTART parameter: 0]; - long end = [mOwner getGeneralProperty: SCI_GETSELECTIONEND parameter: 0]; - return NSMakeRange(begin, end - begin); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called by the input manager to set text which might be combined with further input to form - * the final text (e.g. composition of ^ and a to â). - * - * @param aString The text to insert, either what has been marked already or what is selected already - * or simply added at the current insertion point. Depending on what is available. - * @param range The range of the new text to select (given relative to the insertion point of the new text). - */ -- (void) setMarkedText: (id) aString selectedRange: (NSRange) range -{ - // Since we did not return any valid attribute for marked text (see validAttributesForMarkedText) - // we can safely assume the passed in text is an NSString instance. - NSString* newText = @""; - if ([aString isKindOfClass:[NSString class]]) - newText = (NSString*) aString; - else if ([aString isKindOfClass:[NSAttributedString class]]) - newText = (NSString*) [aString string]; - - long currentPosition = [mOwner getGeneralProperty: SCI_GETCURRENTPOS parameter: 0]; - - // Replace marked text if there is one. - if (mMarkedTextRange.length > 0) - { - // We have already marked text. Replace that. - [mOwner setGeneralProperty: SCI_SETSELECTIONSTART - value: mMarkedTextRange.location]; - [mOwner setGeneralProperty: SCI_SETSELECTIONEND - value: mMarkedTextRange.location + mMarkedTextRange.length]; - currentPosition = mMarkedTextRange.location; - } - - // Note: Scintilla internally works almost always with bytes instead chars, so we need to take - // this into account when determining selection ranges and such. - std::string raw_text = [newText UTF8String]; - int lengthInserted = mOwner.backend->InsertText(newText); - - mMarkedTextRange.location = currentPosition; - mMarkedTextRange.length = lengthInserted; - - // Mark the just inserted text. Keep the marked range for later reset. - [mOwner setGeneralProperty: SCI_SETINDICATORCURRENT value: INPUT_INDICATOR]; - [mOwner setGeneralProperty: SCI_INDICATORFILLRANGE - parameter: mMarkedTextRange.location - value: mMarkedTextRange.length]; - - // Select the part which is indicated in the given range. It does not scroll the caret into view. - if (range.length > 0) - { - [mOwner setGeneralProperty: SCI_SETSELECTIONSTART - value: currentPosition + range.location]; - [mOwner setGeneralProperty: SCI_SETSELECTIONEND - value: currentPosition + range.location + range.length]; - } -} - -//-------------------------------------------------------------------------------------------------- - -- (void) unmarkText -{ - if (mMarkedTextRange.length > 0) - { - [mOwner setGeneralProperty: SCI_SETINDICATORCURRENT value: INPUT_INDICATOR]; - [mOwner setGeneralProperty: SCI_INDICATORCLEARRANGE - parameter: mMarkedTextRange.location - value: mMarkedTextRange.length]; - mMarkedTextRange = NSMakeRange(NSNotFound, 0); - } -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Removes any currently marked text. - */ -- (void) removeMarkedText -{ - if (mMarkedTextRange.length > 0) - { - // We have already marked text. Replace that. - [mOwner setGeneralProperty: SCI_SETSELECTIONSTART - value: mMarkedTextRange.location]; - [mOwner setGeneralProperty: SCI_SETSELECTIONEND - value: mMarkedTextRange.location + mMarkedTextRange.length]; - mOwner.backend->InsertText(@""); - mMarkedTextRange = NSMakeRange(NSNotFound, 0); - } -} - -//-------------------------------------------------------------------------------------------------- - -- (NSArray*) validAttributesForMarkedText -{ - return nil; -} - -// End of the NSTextInput protocol adoption. - -//-------------------------------------------------------------------------------------------------- - -/** - * Generic input method. It is used to pass on keyboard input to Scintilla. The control itself only - * handles shortcuts. The input is then forwarded to the Cocoa text input system, which in turn does - * its own input handling (character composition via NSTextInput protocol): - */ -- (void) keyDown: (NSEvent *) theEvent -{ - if (mMarkedTextRange.length == 0) - mOwner.backend->KeyboardInput(theEvent); - NSArray* events = [NSArray arrayWithObject: theEvent]; - [self interpretKeyEvents: events]; -} - -//-------------------------------------------------------------------------------------------------- - -- (void) mouseDown: (NSEvent *) theEvent -{ - mOwner.backend->MouseDown(theEvent); -} - -//-------------------------------------------------------------------------------------------------- - -- (void) mouseDragged: (NSEvent *) theEvent -{ - mOwner.backend->MouseMove(theEvent); -} - -//-------------------------------------------------------------------------------------------------- - -- (void) mouseUp: (NSEvent *) theEvent -{ - mOwner.backend->MouseUp(theEvent); -} - -//-------------------------------------------------------------------------------------------------- - -- (void) mouseMoved: (NSEvent *) theEvent -{ - mOwner.backend->MouseMove(theEvent); -} - -//-------------------------------------------------------------------------------------------------- - -- (void) mouseEntered: (NSEvent *) theEvent -{ - mOwner.backend->MouseEntered(theEvent); -} - -//-------------------------------------------------------------------------------------------------- - -- (void) mouseExited: (NSEvent *) theEvent -{ - mOwner.backend->MouseExited(theEvent); -} - -//-------------------------------------------------------------------------------------------------- - -- (void) scrollWheel: (NSEvent *) theEvent -{ - mOwner.backend->MouseWheel(theEvent); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * The editor is getting the foreground control (the one getting the input focus). - */ -- (BOOL) becomeFirstResponder -{ - mOwner.backend->WndProc(SCI_SETFOCUS, 1, 0); - return YES; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * The editor is losing the input focus. - */ -- (BOOL) resignFirstResponder -{ - mOwner.backend->WndProc(SCI_SETFOCUS, 0, 0); - return YES; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called when an external drag operation enters the view. - */ -- (NSDragOperation) draggingEntered: (id ) sender -{ - return mOwner.backend->DraggingEntered(sender); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called frequently during an external drag operation if we are the target. - */ -- (NSDragOperation) draggingUpdated: (id ) sender -{ - return mOwner.backend->DraggingUpdated(sender); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Drag image left the view. Clean up if necessary. - */ -- (void) draggingExited: (id ) sender -{ - mOwner.backend->DraggingExited(sender); -} - -//-------------------------------------------------------------------------------------------------- - -- (BOOL) prepareForDragOperation: (id ) sender -{ -#pragma unused(sender) - return YES; -} - -//-------------------------------------------------------------------------------------------------- - -- (BOOL) performDragOperation: (id ) sender -{ - return mOwner.backend->PerformDragOperation(sender); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Returns operations we allow as drag source. - */ -- (NSDragOperation) draggingSourceOperationMaskForLocal: (BOOL) flag -{ - return NSDragOperationCopy | NSDragOperationMove | NSDragOperationDelete; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Finished a drag: may need to delete selection. - */ - -- (void)draggedImage:(NSImage *)image endedAt:(NSPoint)screenPoint operation:(NSDragOperation)operation { - if (operation == NSDragOperationDelete) { - mOwner.backend->WndProc(SCI_CLEAR, 0, 0); - } -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Drag operation is done. Notify editor. - */ -- (void) concludeDragOperation: (id ) sender -{ - // Clean up is the same as if we are no longer the drag target. - mOwner.backend->DraggingExited(sender); -} - -//-------------------------------------------------------------------------------------------------- - -// NSResponder actions. - -- (void) selectAll: (id) sender -{ -#pragma unused(sender) - mOwner.backend->SelectAll(); -} - -- (void) deleteBackward: (id) sender -{ -#pragma unused(sender) - mOwner.backend->DeleteBackward(); -} - -- (void) cut: (id) sender -{ -#pragma unused(sender) - mOwner.backend->Cut(); -} - -- (void) copy: (id) sender -{ -#pragma unused(sender) - mOwner.backend->Copy(); -} - -- (void) paste: (id) sender -{ -#pragma unused(sender) - mOwner.backend->Paste(); -} - -- (void) undo: (id) sender -{ -#pragma unused(sender) - mOwner.backend->Undo(); -} - -- (void) redo: (id) sender -{ -#pragma unused(sender) - mOwner.backend->Redo(); -} - -- (BOOL) canUndo -{ - return mOwner.backend->CanUndo(); -} - -- (BOOL) canRedo -{ - return mOwner.backend->CanRedo(); -} - - -- (BOOL) isEditable -{ - return mOwner.backend->WndProc(SCI_GETREADONLY, 0, 0) == 0; -} - -//-------------------------------------------------------------------------------------------------- - -- (void) dealloc -{ - [mCurrentCursor release]; - [super dealloc]; -} - -@end - -//-------------------------------------------------------------------------------------------------- - -@implementation ScintillaView - -@synthesize backend = mBackend; -@synthesize owner = mOwner; - -/** - * ScintiallView is a composite control made from an NSView and an embedded NSView that is - * used as canvas for the output (by the backend, using its CGContext), plus other elements - * (scrollers, info bar). - */ - -//-------------------------------------------------------------------------------------------------- - -/** - * Initialize custom cursor. - */ -+ (void) initialize -{ - if (self == [ScintillaView class]) - { - NSBundle* bundle = [NSBundle bundleForClass: [ScintillaView class]]; - - NSString* path = [bundle pathForResource: @"mac_cursor_busy" ofType: @"png" inDirectory: nil]; - NSImage* image = [[[NSImage alloc] initWithContentsOfFile: path] autorelease]; - waitCursor = [[NSCursor alloc] initWithImage: image hotSpot: NSMakePoint(2, 2)]; - - path = [bundle pathForResource: @"mac_cursor_flipped" ofType: @"png" inDirectory: nil]; - image = [[[NSImage alloc] initWithContentsOfFile: path] autorelease]; - reverseArrowCursor = [[NSCursor alloc] initWithImage: image hotSpot: NSMakePoint(12, 2)]; - } -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Sends a new notification of the given type to the default notification center. - */ -- (void) sendNotification: (NSString*) notificationName -{ - NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; - [center postNotificationName: notificationName object: self]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called by a connected component (usually the info bar) if something changed there. - * - * @param type The type of the notification. - * @param message Carries the new status message if the type is a status message change. - * @param location Carries the new location (e.g. caret) if the type is a caret change or similar type. - * @param location Carries the new zoom value if the type is a zoom change. - */ -- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location - value: (float) value -{ - switch (type) - { - case IBNZoomChanged: - { - // Compute point increase/decrease based on default font size. - long fontSize = [self getGeneralProperty: SCI_STYLEGETSIZE parameter: STYLE_DEFAULT]; - int zoom = (int) (fontSize * (value - 1)); - [self setGeneralProperty: SCI_SETZOOM value: zoom]; - break; - } - default: - break; - }; -} - -//-------------------------------------------------------------------------------------------------- - -- (void) setCallback: (id ) callback -{ - // Not used. Only here to satisfy protocol. -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Prevents drawing of the inner view to avoid flickering when doing many visual updates - * (like clearing all marks and setting new ones etc.). - */ -- (void) suspendDrawing: (BOOL) suspend -{ - if (suspend) - [[self window] disableFlushWindow]; - else - [[self window] enableFlushWindow]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Notification function used by Scintilla to call us back (e.g. for handling clicks on the - * folder margin or changes in the editor). - */ -static void notification(intptr_t windowid, unsigned int iMessage, uintptr_t wParam, uintptr_t lParam) -{ - // WM_NOTIFY means we got a parent notification with a special notification structure. - // Here we don't really differentiate between parent and own notifications and handle both. - ScintillaView* editor; - switch (iMessage) - { - case WM_NOTIFY: - { - // Parent notification. Details are passed as SCNotification structure. - SCNotification* scn = reinterpret_cast(lParam); - ScintillaCocoa *psc = reinterpret_cast(scn->nmhdr.hwndFrom); - editor = reinterpret_cast(psc->ContentView()).owner; - switch (scn->nmhdr.code) - { - case SCN_MARGINCLICK: - { - if (scn->margin == 2) - { - // Click on the folder margin. Toggle the current line if possible. - long line = [editor getGeneralProperty: SCI_LINEFROMPOSITION parameter: scn->position]; - [editor setGeneralProperty: SCI_TOGGLEFOLD value: line]; - } - break; - }; - case SCN_MODIFIED: - { - // Decide depending on the modification type what to do. - // There can be more than one modification carried by one notification. - if (scn->modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) - [editor sendNotification: NSTextDidChangeNotification]; - break; - } - case SCN_ZOOM: - { - // A zoom change happend. Notify info bar if there is one. - float zoom = [editor getGeneralProperty: SCI_GETZOOM parameter: 0]; - long fontSize = [editor getGeneralProperty: SCI_STYLEGETSIZE parameter: STYLE_DEFAULT]; - float factor = (zoom / fontSize) + 1; - [editor->mInfoBar notify: IBNZoomChanged message: nil location: NSZeroPoint value: factor]; - break; - } - case SCN_UPDATEUI: - { - // Triggered whenever changes in the UI state need to be reflected. - // These can be: caret changes, selection changes etc. - NSPoint caretPosition = editor->mBackend->GetCaretPosition(); - [editor->mInfoBar notify: IBNCaretChanged message: nil location: caretPosition value: 0]; - [editor sendNotification: SCIUpdateUINotification]; - [editor sendNotification: NSTextViewDidChangeSelectionNotification]; - break; - } - } - break; - } - case WM_COMMAND: - { - // Notifications for the editor itself. - ScintillaCocoa* backend = reinterpret_cast(lParam); - editor = backend->TopContainer(); - switch (wParam >> 16) - { - case SCEN_KILLFOCUS: - [editor sendNotification: NSTextDidEndEditingNotification]; - break; - case SCEN_SETFOCUS: // Nothing to do for now. - break; - } - break; - } - }; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Initialization of the view. Used to setup a few other things we need. - */ -- (id) initWithFrame: (NSRect) frame -{ - self = [super initWithFrame:frame]; - if (self) - { - mContent = [[[InnerView alloc] init] autorelease]; - mBackend = new ScintillaCocoa(mContent); - mContent.owner = self; - [self addSubview: mContent]; - - // Initialize the scrollers but don't show them yet. - // Pick an arbitrary size, just to make NSScroller selecting the proper scroller direction - // (horizontal or vertical). - NSRect scrollerRect = NSMakeRect(0, 0, 100, 10); - mHorizontalScroller = [[[NSScroller alloc] initWithFrame: scrollerRect] autorelease]; - [mHorizontalScroller setHidden: YES]; - [mHorizontalScroller setTarget: self]; - [mHorizontalScroller setAction: @selector(scrollerAction:)]; - [self addSubview: mHorizontalScroller]; - - scrollerRect.size = NSMakeSize(10, 100); - mVerticalScroller = [[[NSScroller alloc] initWithFrame: scrollerRect] autorelease]; - [mVerticalScroller setHidden: YES]; - [mVerticalScroller setTarget: self]; - [mVerticalScroller setAction: @selector(scrollerAction:)]; - [self addSubview: mVerticalScroller]; - - // Establish a connection from the back end to this container so we can handle situations - // which require our attention. - mBackend->RegisterNotifyCallback(nil, notification); - - // Setup a special indicator used in the editor to provide visual feedback for - // input composition, depending on language, keyboard etc. - [self setColorProperty: SCI_INDICSETFORE parameter: INPUT_INDICATOR fromHTML: @"#FF0000"]; - [self setGeneralProperty: SCI_INDICSETUNDER parameter: INPUT_INDICATOR value: 1]; - [self setGeneralProperty: SCI_INDICSETSTYLE parameter: INPUT_INDICATOR value: INDIC_PLAIN]; - [self setGeneralProperty: SCI_INDICSETALPHA parameter: INPUT_INDICATOR value: 100]; - - NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; - [center addObserver:self - selector:@selector(applicationDidResignActive:) - name:NSApplicationDidResignActiveNotification - object:nil]; - - [center addObserver:self - selector:@selector(applicationDidBecomeActive:) - name:NSApplicationDidBecomeActiveNotification - object:nil]; - } - return self; -} - -//-------------------------------------------------------------------------------------------------- - -- (void) dealloc -{ - [mInfoBar release]; - delete mBackend; - [super dealloc]; -} - -//-------------------------------------------------------------------------------------------------- - -- (void) applicationDidResignActive: (NSNotification *)note { -#pragma unused(note) - mBackend->ActiveStateChanged(false); -} - -//-------------------------------------------------------------------------------------------------- - -- (void) applicationDidBecomeActive: (NSNotification *)note { -#pragma unused(note) - mBackend->ActiveStateChanged(true); -} - -//-------------------------------------------------------------------------------------------------- - -- (void) viewDidMoveToWindow -{ - [super viewDidMoveToWindow]; - - [self layout]; - - // Enable also mouse move events for our window (and so this view). - [[self window] setAcceptsMouseMovedEvents: YES]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Used to position and size the parts of the editor (content, scrollers, info bar). - */ -- (void) layout -{ - int scrollerWidth = [NSScroller scrollerWidth]; - - NSSize size = [self frame].size; - NSRect hScrollerRect = {0, 0, size.width, scrollerWidth}; - NSRect vScrollerRect = {size.width - scrollerWidth, 0, scrollerWidth, size.height}; - NSRect barFrame = {0, size.height - scrollerWidth, size.width, scrollerWidth}; - BOOL infoBarVisible = mInfoBar != nil && ![mInfoBar isHidden]; - - // Horizontal offset of the content. Almost always 0 unless the vertical scroller - // is on the left side. - int contentX = 0; - - // Vertical scroller frame calculation. - if (![mVerticalScroller isHidden]) - { - // Consider user settings (left vs right vertical scrollbar). - BOOL isLeft = [[[NSUserDefaults standardUserDefaults] stringForKey: @"NSScrollerPosition"] - isEqualToString: @"left"]; - if (isLeft) - { - vScrollerRect.origin.x = 0; - hScrollerRect.origin.x = scrollerWidth; - contentX = scrollerWidth; - }; - - size.width -= scrollerWidth; - hScrollerRect.size.width -= scrollerWidth; - } - - // Same for horizontal scroller. - if (![mHorizontalScroller isHidden]) - { - // Make room for the h-scroller. - size.height -= scrollerWidth; - vScrollerRect.size.height -= scrollerWidth; - vScrollerRect.origin.y += scrollerWidth; - }; - - // Info bar frame. - if (infoBarVisible) - { - // Initial value already is as if the bar is at top. - if (mInfoBarAtTop) - { - vScrollerRect.size.height -= scrollerWidth; - size.height -= scrollerWidth; - } - else - { - // Layout info bar and h-scroller side by side in a friendly manner. - int nativeWidth = mInitialInfoBarWidth; - int remainingWidth = barFrame.size.width; - - barFrame.origin.y = 0; - - if ([mHorizontalScroller isHidden]) - { - // H-scroller is not visible, so take the full space. - vScrollerRect.origin.y += scrollerWidth; - vScrollerRect.size.height -= scrollerWidth; - size.height -= scrollerWidth; - } - else - { - // If the left offset of the h-scroller is > 0 then the v-scroller is on the left side. - // In this case we take the full width, otherwise what has been given to the h-scroller - // and content up to now. - if (hScrollerRect.origin.x == 0) - remainingWidth = size.width; - - // Note: remainingWidth can become < 0, which hides the scroller. - remainingWidth -= nativeWidth; - - hScrollerRect.origin.x = nativeWidth; - hScrollerRect.size.width = remainingWidth; - barFrame.size.width = nativeWidth; - } - } - } - - NSRect contentRect = {contentX, vScrollerRect.origin.y, size.width, size.height}; - [mContent setFrame: contentRect]; - - if (infoBarVisible) - [mInfoBar setFrame: barFrame]; - if (![mHorizontalScroller isHidden]) - [mHorizontalScroller setFrame: hScrollerRect]; - if (![mVerticalScroller isHidden]) - [mVerticalScroller setFrame: vScrollerRect]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called by the backend to adjust the vertical scroller (range and page). - * - * @param range Determines the total size of the scroll area used in the editor. - * @param page Determines how many pixels a page is. - * @result Returns YES if anything changed, otherwise NO. - */ -- (BOOL) setVerticalScrollRange: (int) range page: (int) page -{ - BOOL result = NO; - BOOL hideScroller = page >= range; - - if ([mVerticalScroller isHidden] != hideScroller) - { - result = YES; - [mVerticalScroller setHidden: hideScroller]; - if (!hideScroller) - [mVerticalScroller setFloatValue: 0]; - [self layout]; - } - - if (!hideScroller) - { - [mVerticalScroller setEnabled: YES]; - - CGFloat currentProportion = [mVerticalScroller knobProportion]; - CGFloat newProportion = page / (CGFloat) range; - if (currentProportion != newProportion) - { - result = YES; - [mVerticalScroller setKnobProportion: newProportion]; - } - } - - return result; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Used to set the position of the vertical scroll thumb. - * - * @param position The relative position in the rang [0..1]; - */ -- (void) setVerticalScrollPosition: (float) position -{ - [mVerticalScroller setFloatValue: position]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Called by the backend to adjust the horizontal scroller (range and page). - * - * @param range Determines the total size of the scroll area used in the editor. - * @param page Determines how many pixels a page is. - * @result Returns YES if anything changed, otherwise NO. - */ -- (BOOL) setHorizontalScrollRange: (int) range page: (int) page -{ - BOOL result = NO; - BOOL hideScroller = (page >= range) || - (mBackend->WndProc(SCI_GETWRAPMODE, 0, 0) != SC_WRAP_NONE); - - if ([mHorizontalScroller isHidden] != hideScroller) - { - result = YES; - [mHorizontalScroller setHidden: hideScroller]; - [self layout]; - } - - if (!hideScroller) - { - [mHorizontalScroller setEnabled: YES]; - - CGFloat currentProportion = [mHorizontalScroller knobProportion]; - CGFloat newProportion = page / (CGFloat) range; - if (currentProportion != newProportion) - { - result = YES; - [mHorizontalScroller setKnobProportion: newProportion]; - } - } - - return result; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Used to set the position of the vertical scroll thumb. - * - * @param position The relative position in the rang [0..1]; - */ -- (void) setHorizontalScrollPosition: (float) position -{ - [mHorizontalScroller setFloatValue: position]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Triggered by one of the scrollers when it gets manipulated by the user. Notify the backend - * about the change. - */ -- (void) scrollerAction: (id) sender -{ - float position = [sender doubleValue]; - mBackend->DoScroll(position, [sender hitPart], sender == mHorizontalScroller); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Used to reposition our content depending on the size of the view. - */ -- (void) setFrame: (NSRect) newFrame -{ - [super setFrame: newFrame]; - [self layout]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Getter for the currently selected text in raw form (no formatting information included). - * If there is no text available an empty string is returned. - */ -- (NSString*) selectedString -{ - NSString *result = @""; - - char *buffer(0); - const long length = mBackend->WndProc(SCI_GETSELTEXT, 0, 0); - if (length > 0) - { - buffer = new char[length + 1]; - try - { - mBackend->WndProc(SCI_GETSELTEXT, length + 1, (sptr_t) buffer); - mBackend->WndProc(SCI_SETSAVEPOINT, 0, 0); - - result = [NSString stringWithUTF8String: buffer]; - delete[] buffer; - } - catch (...) - { - delete[] buffer; - buffer = 0; - } - } - - return result; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Getter for the current text in raw form (no formatting information included). - * If there is no text available an empty string is returned. - */ -- (NSString*) string -{ - NSString *result = @""; - - char *buffer(0); - const long length = mBackend->WndProc(SCI_GETLENGTH, 0, 0); - if (length > 0) - { - buffer = new char[length + 1]; - try - { - mBackend->WndProc(SCI_GETTEXT, length + 1, (sptr_t) buffer); - mBackend->WndProc(SCI_SETSAVEPOINT, 0, 0); - - result = [NSString stringWithUTF8String: buffer]; - delete[] buffer; - } - catch (...) - { - delete[] buffer; - buffer = 0; - } - } - - return result; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Setter for the current text (no formatting included). - */ -- (void) setString: (NSString*) aString -{ - const char* text = [aString UTF8String]; - mBackend->WndProc(SCI_SETTEXT, 0, (long) text); -} - -//-------------------------------------------------------------------------------------------------- - -- (void) insertString: (NSString*) aString atOffset: (int)offset -{ - const char* text = [aString UTF8String]; - mBackend->WndProc(SCI_ADDTEXT, offset, (long) text); -} - -//-------------------------------------------------------------------------------------------------- - -- (void) setEditable: (BOOL) editable -{ - mBackend->WndProc(SCI_SETREADONLY, editable ? 0 : 1, 0); -} - -//-------------------------------------------------------------------------------------------------- - -- (BOOL) isEditable -{ - return mBackend->WndProc(SCI_GETREADONLY, 0, 0) == 0; -} - -//-------------------------------------------------------------------------------------------------- - -- (InnerView*) content -{ - return mContent; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Direct call into the backend to allow uninterpreted access to it. The values to be passed in and - * the result heavily depend on the message that is used for the call. Refer to the Scintilla - * documentation to learn what can be used here. - */ -+ (sptr_t) directCall: (ScintillaView*) sender message: (unsigned int) message wParam: (uptr_t) wParam - lParam: (sptr_t) lParam -{ - return ScintillaCocoa::DirectFunction(sender->mBackend, message, wParam, lParam); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * This is a helper method to set properties in the backend, with native parameters. - * - * @param property Main property like SCI_STYLESETFORE for which a value is to be set. - * @param parameter Additional info for this property like a parameter or index. - * @param value The actual value. It depends on the property what this parameter means. - */ -- (void) setGeneralProperty: (int) property parameter: (long) parameter value: (long) value -{ - mBackend->WndProc(property, parameter, value); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * A simplified version for setting properties which only require one parameter. - * - * @param property Main property like SCI_STYLESETFORE for which a value is to be set. - * @param value The actual value. It depends on the property what this parameter means. - */ -- (void) setGeneralProperty: (int) property value: (long) value -{ - mBackend->WndProc(property, value, 0); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * This is a helper method to get a property in the backend, with native parameters. - * - * @param property Main property like SCI_STYLESETFORE for which a value is to get. - * @param parameter Additional info for this property like a parameter or index. - * @param extra Yet another parameter if needed. - * @result A generic value which must be interpreted depending on the property queried. - */ -- (long) getGeneralProperty: (int) property parameter: (long) parameter extra: (long) extra -{ - return mBackend->WndProc(property, parameter, extra); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Convenience function to avoid unneeded extra parameter. - */ -- (long) getGeneralProperty: (int) property parameter: (long) parameter -{ - return mBackend->WndProc(property, parameter, 0); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Convenience function to avoid unneeded parameters. - */ -- (long) getGeneralProperty: (int) property -{ - return mBackend->WndProc(property, 0, 0); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Use this variant if you have to pass in a reference to something (e.g. a text range). - */ -- (long) getGeneralProperty: (int) property ref: (const void*) ref -{ - return mBackend->WndProc(property, 0, (sptr_t) ref); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Specialized property setter for colors. - */ -- (void) setColorProperty: (int) property parameter: (long) parameter value: (NSColor*) value -{ - if ([value colorSpaceName] != NSDeviceRGBColorSpace) - value = [value colorUsingColorSpaceName: NSDeviceRGBColorSpace]; - long red = [value redComponent] * 255; - long green = [value greenComponent] * 255; - long blue = [value blueComponent] * 255; - - long color = (blue << 16) + (green << 8) + red; - mBackend->WndProc(property, parameter, color); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Another color property setting, which allows to specify the color as string like in HTML - * documents (i.e. with leading # and either 3 hex digits or 6). - */ -- (void) setColorProperty: (int) property parameter: (long) parameter fromHTML: (NSString*) fromHTML -{ - if ([fromHTML length] > 3 && [fromHTML characterAtIndex: 0] == '#') - { - bool longVersion = [fromHTML length] > 6; - int index = 1; - - char value[3] = {0, 0, 0}; - value[0] = [fromHTML characterAtIndex: index++]; - if (longVersion) - value[1] = [fromHTML characterAtIndex: index++]; - else - value[1] = value[0]; - - unsigned rawRed; - [[NSScanner scannerWithString: [NSString stringWithUTF8String: value]] scanHexInt: &rawRed]; - - value[0] = [fromHTML characterAtIndex: index++]; - if (longVersion) - value[1] = [fromHTML characterAtIndex: index++]; - else - value[1] = value[0]; - - unsigned rawGreen; - [[NSScanner scannerWithString: [NSString stringWithUTF8String: value]] scanHexInt: &rawGreen]; - - value[0] = [fromHTML characterAtIndex: index++]; - if (longVersion) - value[1] = [fromHTML characterAtIndex: index++]; - else - value[1] = value[0]; - - unsigned rawBlue; - [[NSScanner scannerWithString: [NSString stringWithUTF8String: value]] scanHexInt: &rawBlue]; - - long color = (rawBlue << 16) + (rawGreen << 8) + rawRed; - mBackend->WndProc(property, parameter, color); - } -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Specialized property getter for colors. - */ -- (NSColor*) getColorProperty: (int) property parameter: (long) parameter -{ - long color = mBackend->WndProc(property, parameter, 0); - float red = (color & 0xFF) / 255.0; - float green = ((color >> 8) & 0xFF) / 255.0; - float blue = ((color >> 16) & 0xFF) / 255.0; - NSColor* result = [NSColor colorWithDeviceRed: red green: green blue: blue alpha: 1]; - return result; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Specialized property setter for references (pointers, addresses). - */ -- (void) setReferenceProperty: (int) property parameter: (long) parameter value: (const void*) value -{ - mBackend->WndProc(property, parameter, (sptr_t) value); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Specialized property getter for references (pointers, addresses). - */ -- (const void*) getReferenceProperty: (int) property parameter: (long) parameter -{ - return (const void*) mBackend->WndProc(property, parameter, 0); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Specialized property setter for string values. - */ -- (void) setStringProperty: (int) property parameter: (long) parameter value: (NSString*) value -{ - const char* rawValue = [value UTF8String]; - mBackend->WndProc(property, parameter, (sptr_t) rawValue); -} - - -//-------------------------------------------------------------------------------------------------- - -/** - * Specialized property getter for string values. - */ -- (NSString*) getStringProperty: (int) property parameter: (long) parameter -{ - const char* rawValue = (const char*) mBackend->WndProc(property, parameter, 0); - return [NSString stringWithUTF8String: rawValue]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Specialized property setter for lexer properties, which are commonly passed as strings. - */ -- (void) setLexerProperty: (NSString*) name value: (NSString*) value -{ - const char* rawName = [name UTF8String]; - const char* rawValue = [value UTF8String]; - mBackend->WndProc(SCI_SETPROPERTY, (sptr_t) rawName, (sptr_t) rawValue); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Specialized property getter for references (pointers, addresses). - */ -- (NSString*) getLexerProperty: (NSString*) name -{ - const char* rawName = [name UTF8String]; - const char* result = (const char*) mBackend->WndProc(SCI_SETPROPERTY, (sptr_t) rawName, 0); - return [NSString stringWithUTF8String: result]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Sets the notification callback - */ -- (void) registerNotifyCallback: (intptr_t) windowid value: (Scintilla::SciNotifyFunc) callback -{ - mBackend->RegisterNotifyCallback(windowid, callback); -} - - -//-------------------------------------------------------------------------------------------------- - -/** - * Sets the new control which is displayed as info bar at the top or bottom of the editor. - * Set newBar to nil if you want to hide the bar again. - * When aligned to bottom position then the info bar and the horizontal scroller share the available - * space. The info bar will then only get the width it is currently set to less a minimal amount - * reserved for the scroller. At the top position it gets the full width of the control. - * The info bar's height is set to the height of the scrollbar. - */ -- (void) setInfoBar: (NSView *) newBar top: (BOOL) top -{ - if (mInfoBar != newBar) - { - [mInfoBar removeFromSuperview]; - - mInfoBar = newBar; - mInfoBarAtTop = top; - if (mInfoBar != nil) - { - [self addSubview: mInfoBar]; - [mInfoBar setCallback: self]; - - // Keep the initial width as reference for layout changes. - mInitialInfoBarWidth = [mInfoBar frame].size.width; - } - - [self layout]; - } -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Sets the edit's info bar status message. This call only has an effect if there is an info bar. - */ -- (void) setStatusText: (NSString*) text -{ - if (mInfoBar != nil) - [mInfoBar notify: IBNStatusChanged message: text location: NSZeroPoint value: 0]; -} - -//-------------------------------------------------------------------------------------------------- - -- (NSRange) selectedRange -{ - return [mContent selectedRange]; -} - -//-------------------------------------------------------------------------------------------------- - -- (void)insertText: (NSString*)text -{ - [mContent insertText: text]; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Searches and marks the first occurance of the given text and optionally scrolls it into view. - */ -- (void) findAndHighlightText: (NSString*) searchText - matchCase: (BOOL) matchCase - wholeWord: (BOOL) wholeWord - scrollTo: (BOOL) scrollTo - wrap: (BOOL) wrap -{ - // The current position is where we start searching. That is either the end of the current - // (main) selection or the caret position. That ensures we do proper "search next" too. - long currentPosition = [self getGeneralProperty: SCI_GETCURRENTPOS parameter: 0]; - long length = [self getGeneralProperty: SCI_GETTEXTLENGTH parameter: 0]; - - int searchFlags= 0; - if (matchCase) - searchFlags |= SCFIND_MATCHCASE; - if (wholeWord) - searchFlags |= SCFIND_WHOLEWORD; - - Sci_TextToFind ttf; - ttf.chrg.cpMin = currentPosition; - ttf.chrg.cpMax = length; - ttf.lpstrText = (char*) [searchText UTF8String]; - long position = mBackend->WndProc(SCI_FINDTEXT, searchFlags, (sptr_t) &ttf); - - if (position < 0 && wrap) - { - ttf.chrg.cpMin = 0; - ttf.chrg.cpMax = currentPosition; - position = mBackend->WndProc(SCI_FINDTEXT, searchFlags, (sptr_t) &ttf); - } - - if (position >= 0) - { - // Highlight the found text. - [self setGeneralProperty: SCI_SETSELECTIONSTART - value: position]; - [self setGeneralProperty: SCI_SETSELECTIONEND - value: position + [searchText length]]; - - if (scrollTo) - [self setGeneralProperty: SCI_SCROLLCARET value: 0]; - } -} - -//-------------------------------------------------------------------------------------------------- - -- (void) setFontName: (NSString*) font - size: (int) size - bold: (BOOL) bold - italic: (BOOL) italic -{ - for (int i = 0; i < 32; i++) - { - [self setGeneralProperty: SCI_STYLESETFONT - parameter: i - value: (sptr_t)[font UTF8String]]; - [self setGeneralProperty: SCI_STYLESETSIZE - parameter: i - value: size]; - [self setGeneralProperty: SCI_STYLESETBOLD - parameter: i - value: bold]; - [self setGeneralProperty: SCI_STYLESETITALIC - parameter: i - value: italic]; - } -} - -//-------------------------------------------------------------------------------------------------- - -@end - + +/** + * Implementation of the native Cocoa View that serves as container for the scintilla parts. + * + * Created by Mike Lischke. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). + */ + +#import "ScintillaView.h" + +using namespace Scintilla; + +// Two additional cursors we need, which aren't provided by Cocoa. +static NSCursor* reverseArrowCursor; +static NSCursor* waitCursor; + +// The scintilla indicator used for keyboard input. +#define INPUT_INDICATOR INDIC_MAX - 1 + +NSString *SCIUpdateUINotification = @"SCIUpdateUI"; + +@implementation InnerView + +@synthesize owner = mOwner; + +//-------------------------------------------------------------------------------------------------- + +- (NSView*) initWithFrame: (NSRect) frame +{ + self = [super initWithFrame: frame]; + + if (self != nil) + { + // Some initialization for our view. + mCurrentCursor = [[NSCursor arrowCursor] retain]; + mCurrentTrackingRect = 0; + mMarkedTextRange = NSMakeRange(NSNotFound, 0); + + [self registerForDraggedTypes: [NSArray arrayWithObjects: + NSStringPboardType, ScintillaRecPboardType, NSFilenamesPboardType, nil]]; + } + + return self; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * When the view is resized we need to update our tracking rectangle and let the backend know. + */ +- (void) setFrame: (NSRect) frame +{ + [super setFrame: frame]; + + // Make the content also a tracking rectangle for mouse events. + if (mCurrentTrackingRect != 0) + [self removeTrackingRect: mCurrentTrackingRect]; + mCurrentTrackingRect = [self addTrackingRect: [self bounds] + owner: self + userData: nil + assumeInside: YES]; + mOwner.backend->Resize(); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called by the backend if a new cursor must be set for the view. + */ +- (void) setCursor: (Window::Cursor) cursor +{ + [mCurrentCursor autorelease]; + switch (cursor) + { + case Window::cursorText: + mCurrentCursor = [NSCursor IBeamCursor]; + break; + case Window::cursorArrow: + mCurrentCursor = [NSCursor arrowCursor]; + break; + case Window::cursorWait: + mCurrentCursor = waitCursor; + break; + case Window::cursorHoriz: + mCurrentCursor = [NSCursor resizeLeftRightCursor]; + break; + case Window::cursorVert: + mCurrentCursor = [NSCursor resizeUpDownCursor]; + break; + case Window::cursorReverseArrow: + mCurrentCursor = reverseArrowCursor; + break; + case Window::cursorUp: + default: + mCurrentCursor = [NSCursor arrowCursor]; + break; + } + + [mCurrentCursor retain]; + + // Trigger recreation of the cursor rectangle(s). + [[self window] invalidateCursorRectsForView: self]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * This method is called to give us the opportunity to define our mouse sensitive rectangle. + */ +- (void) resetCursorRects +{ + [super resetCursorRects]; + + // We only have one cursor rect: our bounds. + [self addCursorRect: [self bounds] cursor: mCurrentCursor]; + [mCurrentCursor setOnMouseEntered: YES]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Gets called by the runtime when the view needs repainting. + */ +- (void) drawRect: (NSRect) rect +{ + CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; + + mOwner.backend->Draw(rect, context); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Windows uses a client coordinate system where the upper left corner is the origin in a window + * (and so does Scintilla). We have to adjust for that. However by returning YES here, we are + * already done with that. + * Note that because of returning YES here most coordinates we use now (e.g. for painting, + * invalidating rectangles etc.) are given with +Y pointing down! + */ +- (BOOL) isFlipped +{ + return YES; +} + +//-------------------------------------------------------------------------------------------------- + +- (BOOL) isOpaque +{ + return YES; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Implement the "click through" behavior by telling the caller we accept the first mouse event too. + */ +- (BOOL) acceptsFirstMouse: (NSEvent *) theEvent +{ +#pragma unused(theEvent) + return YES; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Make this view accepting events as first responder. + */ +- (BOOL) acceptsFirstResponder +{ + return YES; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called by the framework if it wants to show a context menu for the editor. + */ +- (NSMenu*) menuForEvent: (NSEvent*) theEvent +{ + if (![mOwner respondsToSelector: @selector(menuForEvent:)]) + return mOwner.backend->CreateContextMenu(theEvent); + else + return [mOwner menuForEvent: theEvent]; +} + +//-------------------------------------------------------------------------------------------------- + +// Adoption of NSTextInput protocol. + +- (NSAttributedString*) attributedSubstringFromRange: (NSRange) range +{ + return nil; +} + +//-------------------------------------------------------------------------------------------------- + +- (NSUInteger) characterIndexForPoint: (NSPoint) point +{ + return NSNotFound; +} + +//-------------------------------------------------------------------------------------------------- + +- (NSInteger) conversationIdentifier +{ + return (NSInteger) self; + +} + +//-------------------------------------------------------------------------------------------------- + +- (void) doCommandBySelector: (SEL) selector +{ + if ([self respondsToSelector: @selector(selector)]) + [self performSelector: selector withObject: nil]; +} + +//-------------------------------------------------------------------------------------------------- + +- (NSRect) firstRectForCharacterRange: (NSRange) range +{ + return NSZeroRect; +} + +//-------------------------------------------------------------------------------------------------- + +- (BOOL) hasMarkedText +{ + return mMarkedTextRange.length > 0; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * General text input. Used to insert new text at the current input position, replacing the current + * selection if there is any. + */ +- (void) insertText: (id) aString +{ + // Remove any previously marked text first. + [self removeMarkedText]; + NSString* newText = @""; + if ([aString isKindOfClass:[NSString class]]) + newText = (NSString*) aString; + else if ([aString isKindOfClass:[NSAttributedString class]]) + newText = (NSString*) [aString string]; + + mOwner.backend->InsertText(newText); +} + +//-------------------------------------------------------------------------------------------------- + +- (NSRange) markedRange +{ + return mMarkedTextRange; +} + +//-------------------------------------------------------------------------------------------------- + +- (NSRange) selectedRange +{ + long begin = [mOwner getGeneralProperty: SCI_GETSELECTIONSTART parameter: 0]; + long end = [mOwner getGeneralProperty: SCI_GETSELECTIONEND parameter: 0]; + return NSMakeRange(begin, end - begin); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called by the input manager to set text which might be combined with further input to form + * the final text (e.g. composition of ^ and a to â). + * + * @param aString The text to insert, either what has been marked already or what is selected already + * or simply added at the current insertion point. Depending on what is available. + * @param range The range of the new text to select (given relative to the insertion point of the new text). + */ +- (void) setMarkedText: (id) aString selectedRange: (NSRange) range +{ + // Since we did not return any valid attribute for marked text (see validAttributesForMarkedText) + // we can safely assume the passed in text is an NSString instance. + NSString* newText = @""; + if ([aString isKindOfClass:[NSString class]]) + newText = (NSString*) aString; + else if ([aString isKindOfClass:[NSAttributedString class]]) + newText = (NSString*) [aString string]; + + long currentPosition = [mOwner getGeneralProperty: SCI_GETCURRENTPOS parameter: 0]; + + // Replace marked text if there is one. + if (mMarkedTextRange.length > 0) + { + // We have already marked text. Replace that. + [mOwner setGeneralProperty: SCI_SETSELECTIONSTART + value: mMarkedTextRange.location]; + [mOwner setGeneralProperty: SCI_SETSELECTIONEND + value: mMarkedTextRange.location + mMarkedTextRange.length]; + currentPosition = mMarkedTextRange.location; + } + + // Note: Scintilla internally works almost always with bytes instead chars, so we need to take + // this into account when determining selection ranges and such. + std::string raw_text = [newText UTF8String]; + int lengthInserted = mOwner.backend->InsertText(newText); + + mMarkedTextRange.location = currentPosition; + mMarkedTextRange.length = lengthInserted; + + // Mark the just inserted text. Keep the marked range for later reset. + [mOwner setGeneralProperty: SCI_SETINDICATORCURRENT value: INPUT_INDICATOR]; + [mOwner setGeneralProperty: SCI_INDICATORFILLRANGE + parameter: mMarkedTextRange.location + value: mMarkedTextRange.length]; + + // Select the part which is indicated in the given range. It does not scroll the caret into view. + if (range.length > 0) + { + [mOwner setGeneralProperty: SCI_SETSELECTIONSTART + value: currentPosition + range.location]; + [mOwner setGeneralProperty: SCI_SETSELECTIONEND + value: currentPosition + range.location + range.length]; + } +} + +//-------------------------------------------------------------------------------------------------- + +- (void) unmarkText +{ + if (mMarkedTextRange.length > 0) + { + [mOwner setGeneralProperty: SCI_SETINDICATORCURRENT value: INPUT_INDICATOR]; + [mOwner setGeneralProperty: SCI_INDICATORCLEARRANGE + parameter: mMarkedTextRange.location + value: mMarkedTextRange.length]; + mMarkedTextRange = NSMakeRange(NSNotFound, 0); + } +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Removes any currently marked text. + */ +- (void) removeMarkedText +{ + if (mMarkedTextRange.length > 0) + { + // We have already marked text. Replace that. + [mOwner setGeneralProperty: SCI_SETSELECTIONSTART + value: mMarkedTextRange.location]; + [mOwner setGeneralProperty: SCI_SETSELECTIONEND + value: mMarkedTextRange.location + mMarkedTextRange.length]; + mOwner.backend->InsertText(@""); + mMarkedTextRange = NSMakeRange(NSNotFound, 0); + } +} + +//-------------------------------------------------------------------------------------------------- + +- (NSArray*) validAttributesForMarkedText +{ + return nil; +} + +// End of the NSTextInput protocol adoption. + +//-------------------------------------------------------------------------------------------------- + +/** + * Generic input method. It is used to pass on keyboard input to Scintilla. The control itself only + * handles shortcuts. The input is then forwarded to the Cocoa text input system, which in turn does + * its own input handling (character composition via NSTextInput protocol): + */ +- (void) keyDown: (NSEvent *) theEvent +{ + if (mMarkedTextRange.length == 0) + mOwner.backend->KeyboardInput(theEvent); + NSArray* events = [NSArray arrayWithObject: theEvent]; + [self interpretKeyEvents: events]; +} + +//-------------------------------------------------------------------------------------------------- + +- (void) mouseDown: (NSEvent *) theEvent +{ + mOwner.backend->MouseDown(theEvent); +} + +//-------------------------------------------------------------------------------------------------- + +- (void) mouseDragged: (NSEvent *) theEvent +{ + mOwner.backend->MouseMove(theEvent); +} + +//-------------------------------------------------------------------------------------------------- + +- (void) mouseUp: (NSEvent *) theEvent +{ + mOwner.backend->MouseUp(theEvent); +} + +//-------------------------------------------------------------------------------------------------- + +- (void) mouseMoved: (NSEvent *) theEvent +{ + mOwner.backend->MouseMove(theEvent); +} + +//-------------------------------------------------------------------------------------------------- + +- (void) mouseEntered: (NSEvent *) theEvent +{ + mOwner.backend->MouseEntered(theEvent); +} + +//-------------------------------------------------------------------------------------------------- + +- (void) mouseExited: (NSEvent *) theEvent +{ + mOwner.backend->MouseExited(theEvent); +} + +//-------------------------------------------------------------------------------------------------- + +- (void) scrollWheel: (NSEvent *) theEvent +{ + mOwner.backend->MouseWheel(theEvent); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * The editor is getting the foreground control (the one getting the input focus). + */ +- (BOOL) becomeFirstResponder +{ + mOwner.backend->WndProc(SCI_SETFOCUS, 1, 0); + return YES; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * The editor is losing the input focus. + */ +- (BOOL) resignFirstResponder +{ + mOwner.backend->WndProc(SCI_SETFOCUS, 0, 0); + return YES; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called when an external drag operation enters the view. + */ +- (NSDragOperation) draggingEntered: (id ) sender +{ + return mOwner.backend->DraggingEntered(sender); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called frequently during an external drag operation if we are the target. + */ +- (NSDragOperation) draggingUpdated: (id ) sender +{ + return mOwner.backend->DraggingUpdated(sender); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Drag image left the view. Clean up if necessary. + */ +- (void) draggingExited: (id ) sender +{ + mOwner.backend->DraggingExited(sender); +} + +//-------------------------------------------------------------------------------------------------- + +- (BOOL) prepareForDragOperation: (id ) sender +{ +#pragma unused(sender) + return YES; +} + +//-------------------------------------------------------------------------------------------------- + +- (BOOL) performDragOperation: (id ) sender +{ + return mOwner.backend->PerformDragOperation(sender); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Returns operations we allow as drag source. + */ +- (NSDragOperation) draggingSourceOperationMaskForLocal: (BOOL) flag +{ + return NSDragOperationCopy | NSDragOperationMove | NSDragOperationDelete; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Finished a drag: may need to delete selection. + */ + +- (void)draggedImage:(NSImage *)image endedAt:(NSPoint)screenPoint operation:(NSDragOperation)operation { + if (operation == NSDragOperationDelete) { + mOwner.backend->WndProc(SCI_CLEAR, 0, 0); + } +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Drag operation is done. Notify editor. + */ +- (void) concludeDragOperation: (id ) sender +{ + // Clean up is the same as if we are no longer the drag target. + mOwner.backend->DraggingExited(sender); +} + +//-------------------------------------------------------------------------------------------------- + +// NSResponder actions. + +- (void) selectAll: (id) sender +{ +#pragma unused(sender) + mOwner.backend->SelectAll(); +} + +- (void) deleteBackward: (id) sender +{ +#pragma unused(sender) + mOwner.backend->DeleteBackward(); +} + +- (void) cut: (id) sender +{ +#pragma unused(sender) + mOwner.backend->Cut(); +} + +- (void) copy: (id) sender +{ +#pragma unused(sender) + mOwner.backend->Copy(); +} + +- (void) paste: (id) sender +{ +#pragma unused(sender) + mOwner.backend->Paste(); +} + +- (void) undo: (id) sender +{ +#pragma unused(sender) + mOwner.backend->Undo(); +} + +- (void) redo: (id) sender +{ +#pragma unused(sender) + mOwner.backend->Redo(); +} + +- (BOOL) canUndo +{ + return mOwner.backend->CanUndo(); +} + +- (BOOL) canRedo +{ + return mOwner.backend->CanRedo(); +} + + +- (BOOL) isEditable +{ + return mOwner.backend->WndProc(SCI_GETREADONLY, 0, 0) == 0; +} + +//-------------------------------------------------------------------------------------------------- + +- (void) dealloc +{ + [mCurrentCursor release]; + [super dealloc]; +} + +@end + +//-------------------------------------------------------------------------------------------------- + +@implementation ScintillaView + +@synthesize backend = mBackend; +@synthesize owner = mOwner; + +/** + * ScintiallView is a composite control made from an NSView and an embedded NSView that is + * used as canvas for the output (by the backend, using its CGContext), plus other elements + * (scrollers, info bar). + */ + +//-------------------------------------------------------------------------------------------------- + +/** + * Initialize custom cursor. + */ ++ (void) initialize +{ + if (self == [ScintillaView class]) + { + NSBundle* bundle = [NSBundle bundleForClass: [ScintillaView class]]; + + NSString* path = [bundle pathForResource: @"mac_cursor_busy" ofType: @"png" inDirectory: nil]; + NSImage* image = [[[NSImage alloc] initWithContentsOfFile: path] autorelease]; + waitCursor = [[NSCursor alloc] initWithImage: image hotSpot: NSMakePoint(2, 2)]; + + path = [bundle pathForResource: @"mac_cursor_flipped" ofType: @"png" inDirectory: nil]; + image = [[[NSImage alloc] initWithContentsOfFile: path] autorelease]; + reverseArrowCursor = [[NSCursor alloc] initWithImage: image hotSpot: NSMakePoint(12, 2)]; + } +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Sends a new notification of the given type to the default notification center. + */ +- (void) sendNotification: (NSString*) notificationName +{ + NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; + [center postNotificationName: notificationName object: self]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called by a connected component (usually the info bar) if something changed there. + * + * @param type The type of the notification. + * @param message Carries the new status message if the type is a status message change. + * @param location Carries the new location (e.g. caret) if the type is a caret change or similar type. + * @param location Carries the new zoom value if the type is a zoom change. + */ +- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location + value: (float) value +{ + switch (type) + { + case IBNZoomChanged: + { + // Compute point increase/decrease based on default font size. + long fontSize = [self getGeneralProperty: SCI_STYLEGETSIZE parameter: STYLE_DEFAULT]; + int zoom = (int) (fontSize * (value - 1)); + [self setGeneralProperty: SCI_SETZOOM value: zoom]; + break; + } + default: + break; + }; +} + +//-------------------------------------------------------------------------------------------------- + +- (void) setCallback: (id ) callback +{ + // Not used. Only here to satisfy protocol. +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Prevents drawing of the inner view to avoid flickering when doing many visual updates + * (like clearing all marks and setting new ones etc.). + */ +- (void) suspendDrawing: (BOOL) suspend +{ + if (suspend) + [[self window] disableFlushWindow]; + else + [[self window] enableFlushWindow]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Notification function used by Scintilla to call us back (e.g. for handling clicks on the + * folder margin or changes in the editor). + */ +static void notification(intptr_t windowid, unsigned int iMessage, uintptr_t wParam, uintptr_t lParam) +{ + // WM_NOTIFY means we got a parent notification with a special notification structure. + // Here we don't really differentiate between parent and own notifications and handle both. + ScintillaView* editor; + switch (iMessage) + { + case WM_NOTIFY: + { + // Parent notification. Details are passed as SCNotification structure. + SCNotification* scn = reinterpret_cast(lParam); + ScintillaCocoa *psc = reinterpret_cast(scn->nmhdr.hwndFrom); + editor = reinterpret_cast(psc->ContentView()).owner; + switch (scn->nmhdr.code) + { + case SCN_MARGINCLICK: + { + if (scn->margin == 2) + { + // Click on the folder margin. Toggle the current line if possible. + long line = [editor getGeneralProperty: SCI_LINEFROMPOSITION parameter: scn->position]; + [editor setGeneralProperty: SCI_TOGGLEFOLD value: line]; + } + break; + }; + case SCN_MODIFIED: + { + // Decide depending on the modification type what to do. + // There can be more than one modification carried by one notification. + if (scn->modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) + [editor sendNotification: NSTextDidChangeNotification]; + break; + } + case SCN_ZOOM: + { + // A zoom change happend. Notify info bar if there is one. + float zoom = [editor getGeneralProperty: SCI_GETZOOM parameter: 0]; + long fontSize = [editor getGeneralProperty: SCI_STYLEGETSIZE parameter: STYLE_DEFAULT]; + float factor = (zoom / fontSize) + 1; + [editor->mInfoBar notify: IBNZoomChanged message: nil location: NSZeroPoint value: factor]; + break; + } + case SCN_UPDATEUI: + { + // Triggered whenever changes in the UI state need to be reflected. + // These can be: caret changes, selection changes etc. + NSPoint caretPosition = editor->mBackend->GetCaretPosition(); + [editor->mInfoBar notify: IBNCaretChanged message: nil location: caretPosition value: 0]; + [editor sendNotification: SCIUpdateUINotification]; + [editor sendNotification: NSTextViewDidChangeSelectionNotification]; + break; + } + } + break; + } + case WM_COMMAND: + { + // Notifications for the editor itself. + ScintillaCocoa* backend = reinterpret_cast(lParam); + editor = backend->TopContainer(); + switch (wParam >> 16) + { + case SCEN_KILLFOCUS: + [editor sendNotification: NSTextDidEndEditingNotification]; + break; + case SCEN_SETFOCUS: // Nothing to do for now. + break; + } + break; + } + }; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Initialization of the view. Used to setup a few other things we need. + */ +- (id) initWithFrame: (NSRect) frame +{ + self = [super initWithFrame:frame]; + if (self) + { + mContent = [[[InnerView alloc] init] autorelease]; + mBackend = new ScintillaCocoa(mContent); + mContent.owner = self; + [self addSubview: mContent]; + + // Initialize the scrollers but don't show them yet. + // Pick an arbitrary size, just to make NSScroller selecting the proper scroller direction + // (horizontal or vertical). + NSRect scrollerRect = NSMakeRect(0, 0, 100, 10); + mHorizontalScroller = [[[NSScroller alloc] initWithFrame: scrollerRect] autorelease]; + [mHorizontalScroller setHidden: YES]; + [mHorizontalScroller setTarget: self]; + [mHorizontalScroller setAction: @selector(scrollerAction:)]; + [self addSubview: mHorizontalScroller]; + + scrollerRect.size = NSMakeSize(10, 100); + mVerticalScroller = [[[NSScroller alloc] initWithFrame: scrollerRect] autorelease]; + [mVerticalScroller setHidden: YES]; + [mVerticalScroller setTarget: self]; + [mVerticalScroller setAction: @selector(scrollerAction:)]; + [self addSubview: mVerticalScroller]; + + // Establish a connection from the back end to this container so we can handle situations + // which require our attention. + mBackend->RegisterNotifyCallback(nil, notification); + + // Setup a special indicator used in the editor to provide visual feedback for + // input composition, depending on language, keyboard etc. + [self setColorProperty: SCI_INDICSETFORE parameter: INPUT_INDICATOR fromHTML: @"#FF0000"]; + [self setGeneralProperty: SCI_INDICSETUNDER parameter: INPUT_INDICATOR value: 1]; + [self setGeneralProperty: SCI_INDICSETSTYLE parameter: INPUT_INDICATOR value: INDIC_PLAIN]; + [self setGeneralProperty: SCI_INDICSETALPHA parameter: INPUT_INDICATOR value: 100]; + + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center addObserver:self + selector:@selector(applicationDidResignActive:) + name:NSApplicationDidResignActiveNotification + object:nil]; + + [center addObserver:self + selector:@selector(applicationDidBecomeActive:) + name:NSApplicationDidBecomeActiveNotification + object:nil]; + } + return self; +} + +//-------------------------------------------------------------------------------------------------- + +- (void) dealloc +{ + [mInfoBar release]; + delete mBackend; + [super dealloc]; +} + +//-------------------------------------------------------------------------------------------------- + +- (void) applicationDidResignActive: (NSNotification *)note { +#pragma unused(note) + mBackend->ActiveStateChanged(false); +} + +//-------------------------------------------------------------------------------------------------- + +- (void) applicationDidBecomeActive: (NSNotification *)note { +#pragma unused(note) + mBackend->ActiveStateChanged(true); +} + +//-------------------------------------------------------------------------------------------------- + +- (void) viewDidMoveToWindow +{ + [super viewDidMoveToWindow]; + + [self layout]; + + // Enable also mouse move events for our window (and so this view). + [[self window] setAcceptsMouseMovedEvents: YES]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Used to position and size the parts of the editor (content, scrollers, info bar). + */ +- (void) layout +{ + int scrollerWidth = [NSScroller scrollerWidth]; + + NSSize size = [self frame].size; + NSRect hScrollerRect = {0, 0, size.width, scrollerWidth}; + NSRect vScrollerRect = {size.width - scrollerWidth, 0, scrollerWidth, size.height}; + NSRect barFrame = {0, size.height - scrollerWidth, size.width, scrollerWidth}; + BOOL infoBarVisible = mInfoBar != nil && ![mInfoBar isHidden]; + + // Horizontal offset of the content. Almost always 0 unless the vertical scroller + // is on the left side. + int contentX = 0; + + // Vertical scroller frame calculation. + if (![mVerticalScroller isHidden]) + { + // Consider user settings (left vs right vertical scrollbar). + BOOL isLeft = [[[NSUserDefaults standardUserDefaults] stringForKey: @"NSScrollerPosition"] + isEqualToString: @"left"]; + if (isLeft) + { + vScrollerRect.origin.x = 0; + hScrollerRect.origin.x = scrollerWidth; + contentX = scrollerWidth; + }; + + size.width -= scrollerWidth; + hScrollerRect.size.width -= scrollerWidth; + } + + // Same for horizontal scroller. + if (![mHorizontalScroller isHidden]) + { + // Make room for the h-scroller. + size.height -= scrollerWidth; + vScrollerRect.size.height -= scrollerWidth; + vScrollerRect.origin.y += scrollerWidth; + }; + + // Info bar frame. + if (infoBarVisible) + { + // Initial value already is as if the bar is at top. + if (mInfoBarAtTop) + { + vScrollerRect.size.height -= scrollerWidth; + size.height -= scrollerWidth; + } + else + { + // Layout info bar and h-scroller side by side in a friendly manner. + int nativeWidth = mInitialInfoBarWidth; + int remainingWidth = barFrame.size.width; + + barFrame.origin.y = 0; + + if ([mHorizontalScroller isHidden]) + { + // H-scroller is not visible, so take the full space. + vScrollerRect.origin.y += scrollerWidth; + vScrollerRect.size.height -= scrollerWidth; + size.height -= scrollerWidth; + } + else + { + // If the left offset of the h-scroller is > 0 then the v-scroller is on the left side. + // In this case we take the full width, otherwise what has been given to the h-scroller + // and content up to now. + if (hScrollerRect.origin.x == 0) + remainingWidth = size.width; + + // Note: remainingWidth can become < 0, which hides the scroller. + remainingWidth -= nativeWidth; + + hScrollerRect.origin.x = nativeWidth; + hScrollerRect.size.width = remainingWidth; + barFrame.size.width = nativeWidth; + } + } + } + + NSRect contentRect = {contentX, vScrollerRect.origin.y, size.width, size.height}; + [mContent setFrame: contentRect]; + + if (infoBarVisible) + [mInfoBar setFrame: barFrame]; + if (![mHorizontalScroller isHidden]) + [mHorizontalScroller setFrame: hScrollerRect]; + if (![mVerticalScroller isHidden]) + [mVerticalScroller setFrame: vScrollerRect]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called by the backend to adjust the vertical scroller (range and page). + * + * @param range Determines the total size of the scroll area used in the editor. + * @param page Determines how many pixels a page is. + * @result Returns YES if anything changed, otherwise NO. + */ +- (BOOL) setVerticalScrollRange: (int) range page: (int) page +{ + BOOL result = NO; + BOOL hideScroller = page >= range; + + if ([mVerticalScroller isHidden] != hideScroller) + { + result = YES; + [mVerticalScroller setHidden: hideScroller]; + if (!hideScroller) + [mVerticalScroller setFloatValue: 0]; + [self layout]; + } + + if (!hideScroller) + { + [mVerticalScroller setEnabled: YES]; + + CGFloat currentProportion = [mVerticalScroller knobProportion]; + CGFloat newProportion = page / (CGFloat) range; + if (currentProportion != newProportion) + { + result = YES; + [mVerticalScroller setKnobProportion: newProportion]; + } + } + + return result; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Used to set the position of the vertical scroll thumb. + * + * @param position The relative position in the rang [0..1]; + */ +- (void) setVerticalScrollPosition: (float) position +{ + [mVerticalScroller setFloatValue: position]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Called by the backend to adjust the horizontal scroller (range and page). + * + * @param range Determines the total size of the scroll area used in the editor. + * @param page Determines how many pixels a page is. + * @result Returns YES if anything changed, otherwise NO. + */ +- (BOOL) setHorizontalScrollRange: (int) range page: (int) page +{ + BOOL result = NO; + BOOL hideScroller = (page >= range) || + (mBackend->WndProc(SCI_GETWRAPMODE, 0, 0) != SC_WRAP_NONE); + + if ([mHorizontalScroller isHidden] != hideScroller) + { + result = YES; + [mHorizontalScroller setHidden: hideScroller]; + [self layout]; + } + + if (!hideScroller) + { + [mHorizontalScroller setEnabled: YES]; + + CGFloat currentProportion = [mHorizontalScroller knobProportion]; + CGFloat newProportion = page / (CGFloat) range; + if (currentProportion != newProportion) + { + result = YES; + [mHorizontalScroller setKnobProportion: newProportion]; + } + } + + return result; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Used to set the position of the vertical scroll thumb. + * + * @param position The relative position in the rang [0..1]; + */ +- (void) setHorizontalScrollPosition: (float) position +{ + [mHorizontalScroller setFloatValue: position]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Triggered by one of the scrollers when it gets manipulated by the user. Notify the backend + * about the change. + */ +- (void) scrollerAction: (id) sender +{ + float position = [sender doubleValue]; + mBackend->DoScroll(position, [sender hitPart], sender == mHorizontalScroller); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Used to reposition our content depending on the size of the view. + */ +- (void) setFrame: (NSRect) newFrame +{ + [super setFrame: newFrame]; + [self layout]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Getter for the currently selected text in raw form (no formatting information included). + * If there is no text available an empty string is returned. + */ +- (NSString*) selectedString +{ + NSString *result = @""; + + char *buffer(0); + const long length = mBackend->WndProc(SCI_GETSELTEXT, 0, 0); + if (length > 0) + { + buffer = new char[length + 1]; + try + { + mBackend->WndProc(SCI_GETSELTEXT, length + 1, (sptr_t) buffer); + mBackend->WndProc(SCI_SETSAVEPOINT, 0, 0); + + result = [NSString stringWithUTF8String: buffer]; + delete[] buffer; + } + catch (...) + { + delete[] buffer; + buffer = 0; + } + } + + return result; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Getter for the current text in raw form (no formatting information included). + * If there is no text available an empty string is returned. + */ +- (NSString*) string +{ + NSString *result = @""; + + char *buffer(0); + const long length = mBackend->WndProc(SCI_GETLENGTH, 0, 0); + if (length > 0) + { + buffer = new char[length + 1]; + try + { + mBackend->WndProc(SCI_GETTEXT, length + 1, (sptr_t) buffer); + mBackend->WndProc(SCI_SETSAVEPOINT, 0, 0); + + result = [NSString stringWithUTF8String: buffer]; + delete[] buffer; + } + catch (...) + { + delete[] buffer; + buffer = 0; + } + } + + return result; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Setter for the current text (no formatting included). + */ +- (void) setString: (NSString*) aString +{ + const char* text = [aString UTF8String]; + mBackend->WndProc(SCI_SETTEXT, 0, (long) text); +} + +//-------------------------------------------------------------------------------------------------- + +- (void) insertString: (NSString*) aString atOffset: (int)offset +{ + const char* text = [aString UTF8String]; + mBackend->WndProc(SCI_ADDTEXT, offset, (long) text); +} + +//-------------------------------------------------------------------------------------------------- + +- (void) setEditable: (BOOL) editable +{ + mBackend->WndProc(SCI_SETREADONLY, editable ? 0 : 1, 0); +} + +//-------------------------------------------------------------------------------------------------- + +- (BOOL) isEditable +{ + return mBackend->WndProc(SCI_GETREADONLY, 0, 0) == 0; +} + +//-------------------------------------------------------------------------------------------------- + +- (InnerView*) content +{ + return mContent; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Direct call into the backend to allow uninterpreted access to it. The values to be passed in and + * the result heavily depend on the message that is used for the call. Refer to the Scintilla + * documentation to learn what can be used here. + */ ++ (sptr_t) directCall: (ScintillaView*) sender message: (unsigned int) message wParam: (uptr_t) wParam + lParam: (sptr_t) lParam +{ + return ScintillaCocoa::DirectFunction(sender->mBackend, message, wParam, lParam); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * This is a helper method to set properties in the backend, with native parameters. + * + * @param property Main property like SCI_STYLESETFORE for which a value is to be set. + * @param parameter Additional info for this property like a parameter or index. + * @param value The actual value. It depends on the property what this parameter means. + */ +- (void) setGeneralProperty: (int) property parameter: (long) parameter value: (long) value +{ + mBackend->WndProc(property, parameter, value); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * A simplified version for setting properties which only require one parameter. + * + * @param property Main property like SCI_STYLESETFORE for which a value is to be set. + * @param value The actual value. It depends on the property what this parameter means. + */ +- (void) setGeneralProperty: (int) property value: (long) value +{ + mBackend->WndProc(property, value, 0); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * This is a helper method to get a property in the backend, with native parameters. + * + * @param property Main property like SCI_STYLESETFORE for which a value is to get. + * @param parameter Additional info for this property like a parameter or index. + * @param extra Yet another parameter if needed. + * @result A generic value which must be interpreted depending on the property queried. + */ +- (long) getGeneralProperty: (int) property parameter: (long) parameter extra: (long) extra +{ + return mBackend->WndProc(property, parameter, extra); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Convenience function to avoid unneeded extra parameter. + */ +- (long) getGeneralProperty: (int) property parameter: (long) parameter +{ + return mBackend->WndProc(property, parameter, 0); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Convenience function to avoid unneeded parameters. + */ +- (long) getGeneralProperty: (int) property +{ + return mBackend->WndProc(property, 0, 0); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Use this variant if you have to pass in a reference to something (e.g. a text range). + */ +- (long) getGeneralProperty: (int) property ref: (const void*) ref +{ + return mBackend->WndProc(property, 0, (sptr_t) ref); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Specialized property setter for colors. + */ +- (void) setColorProperty: (int) property parameter: (long) parameter value: (NSColor*) value +{ + if ([value colorSpaceName] != NSDeviceRGBColorSpace) + value = [value colorUsingColorSpaceName: NSDeviceRGBColorSpace]; + long red = [value redComponent] * 255; + long green = [value greenComponent] * 255; + long blue = [value blueComponent] * 255; + + long color = (blue << 16) + (green << 8) + red; + mBackend->WndProc(property, parameter, color); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Another color property setting, which allows to specify the color as string like in HTML + * documents (i.e. with leading # and either 3 hex digits or 6). + */ +- (void) setColorProperty: (int) property parameter: (long) parameter fromHTML: (NSString*) fromHTML +{ + if ([fromHTML length] > 3 && [fromHTML characterAtIndex: 0] == '#') + { + bool longVersion = [fromHTML length] > 6; + int index = 1; + + char value[3] = {0, 0, 0}; + value[0] = [fromHTML characterAtIndex: index++]; + if (longVersion) + value[1] = [fromHTML characterAtIndex: index++]; + else + value[1] = value[0]; + + unsigned rawRed; + [[NSScanner scannerWithString: [NSString stringWithUTF8String: value]] scanHexInt: &rawRed]; + + value[0] = [fromHTML characterAtIndex: index++]; + if (longVersion) + value[1] = [fromHTML characterAtIndex: index++]; + else + value[1] = value[0]; + + unsigned rawGreen; + [[NSScanner scannerWithString: [NSString stringWithUTF8String: value]] scanHexInt: &rawGreen]; + + value[0] = [fromHTML characterAtIndex: index++]; + if (longVersion) + value[1] = [fromHTML characterAtIndex: index++]; + else + value[1] = value[0]; + + unsigned rawBlue; + [[NSScanner scannerWithString: [NSString stringWithUTF8String: value]] scanHexInt: &rawBlue]; + + long color = (rawBlue << 16) + (rawGreen << 8) + rawRed; + mBackend->WndProc(property, parameter, color); + } +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Specialized property getter for colors. + */ +- (NSColor*) getColorProperty: (int) property parameter: (long) parameter +{ + long color = mBackend->WndProc(property, parameter, 0); + float red = (color & 0xFF) / 255.0; + float green = ((color >> 8) & 0xFF) / 255.0; + float blue = ((color >> 16) & 0xFF) / 255.0; + NSColor* result = [NSColor colorWithDeviceRed: red green: green blue: blue alpha: 1]; + return result; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Specialized property setter for references (pointers, addresses). + */ +- (void) setReferenceProperty: (int) property parameter: (long) parameter value: (const void*) value +{ + mBackend->WndProc(property, parameter, (sptr_t) value); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Specialized property getter for references (pointers, addresses). + */ +- (const void*) getReferenceProperty: (int) property parameter: (long) parameter +{ + return (const void*) mBackend->WndProc(property, parameter, 0); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Specialized property setter for string values. + */ +- (void) setStringProperty: (int) property parameter: (long) parameter value: (NSString*) value +{ + const char* rawValue = [value UTF8String]; + mBackend->WndProc(property, parameter, (sptr_t) rawValue); +} + + +//-------------------------------------------------------------------------------------------------- + +/** + * Specialized property getter for string values. + */ +- (NSString*) getStringProperty: (int) property parameter: (long) parameter +{ + const char* rawValue = (const char*) mBackend->WndProc(property, parameter, 0); + return [NSString stringWithUTF8String: rawValue]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Specialized property setter for lexer properties, which are commonly passed as strings. + */ +- (void) setLexerProperty: (NSString*) name value: (NSString*) value +{ + const char* rawName = [name UTF8String]; + const char* rawValue = [value UTF8String]; + mBackend->WndProc(SCI_SETPROPERTY, (sptr_t) rawName, (sptr_t) rawValue); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Specialized property getter for references (pointers, addresses). + */ +- (NSString*) getLexerProperty: (NSString*) name +{ + const char* rawName = [name UTF8String]; + const char* result = (const char*) mBackend->WndProc(SCI_SETPROPERTY, (sptr_t) rawName, 0); + return [NSString stringWithUTF8String: result]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Sets the notification callback + */ +- (void) registerNotifyCallback: (intptr_t) windowid value: (Scintilla::SciNotifyFunc) callback +{ + mBackend->RegisterNotifyCallback(windowid, callback); +} + + +//-------------------------------------------------------------------------------------------------- + +/** + * Sets the new control which is displayed as info bar at the top or bottom of the editor. + * Set newBar to nil if you want to hide the bar again. + * When aligned to bottom position then the info bar and the horizontal scroller share the available + * space. The info bar will then only get the width it is currently set to less a minimal amount + * reserved for the scroller. At the top position it gets the full width of the control. + * The info bar's height is set to the height of the scrollbar. + */ +- (void) setInfoBar: (NSView *) newBar top: (BOOL) top +{ + if (mInfoBar != newBar) + { + [mInfoBar removeFromSuperview]; + + mInfoBar = newBar; + mInfoBarAtTop = top; + if (mInfoBar != nil) + { + [self addSubview: mInfoBar]; + [mInfoBar setCallback: self]; + + // Keep the initial width as reference for layout changes. + mInitialInfoBarWidth = [mInfoBar frame].size.width; + } + + [self layout]; + } +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Sets the edit's info bar status message. This call only has an effect if there is an info bar. + */ +- (void) setStatusText: (NSString*) text +{ + if (mInfoBar != nil) + [mInfoBar notify: IBNStatusChanged message: text location: NSZeroPoint value: 0]; +} + +//-------------------------------------------------------------------------------------------------- + +- (NSRange) selectedRange +{ + return [mContent selectedRange]; +} + +//-------------------------------------------------------------------------------------------------- + +- (void)insertText: (NSString*)text +{ + [mContent insertText: text]; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Searches and marks the first occurance of the given text and optionally scrolls it into view. + */ +- (void) findAndHighlightText: (NSString*) searchText + matchCase: (BOOL) matchCase + wholeWord: (BOOL) wholeWord + scrollTo: (BOOL) scrollTo + wrap: (BOOL) wrap +{ + // The current position is where we start searching. That is either the end of the current + // (main) selection or the caret position. That ensures we do proper "search next" too. + long currentPosition = [self getGeneralProperty: SCI_GETCURRENTPOS parameter: 0]; + long length = [self getGeneralProperty: SCI_GETTEXTLENGTH parameter: 0]; + + int searchFlags= 0; + if (matchCase) + searchFlags |= SCFIND_MATCHCASE; + if (wholeWord) + searchFlags |= SCFIND_WHOLEWORD; + + Sci_TextToFind ttf; + ttf.chrg.cpMin = currentPosition; + ttf.chrg.cpMax = length; + ttf.lpstrText = (char*) [searchText UTF8String]; + long position = mBackend->WndProc(SCI_FINDTEXT, searchFlags, (sptr_t) &ttf); + + if (position < 0 && wrap) + { + ttf.chrg.cpMin = 0; + ttf.chrg.cpMax = currentPosition; + position = mBackend->WndProc(SCI_FINDTEXT, searchFlags, (sptr_t) &ttf); + } + + if (position >= 0) + { + // Highlight the found text. + [self setGeneralProperty: SCI_SETSELECTIONSTART + value: position]; + [self setGeneralProperty: SCI_SETSELECTIONEND + value: position + [searchText length]]; + + if (scrollTo) + [self setGeneralProperty: SCI_SCROLLCARET value: 0]; + } +} + +//-------------------------------------------------------------------------------------------------- + +- (void) setFontName: (NSString*) font + size: (int) size + bold: (BOOL) bold + italic: (BOOL) italic +{ + for (int i = 0; i < 32; i++) + { + [self setGeneralProperty: SCI_STYLESETFONT + parameter: i + value: (sptr_t)[font UTF8String]]; + [self setGeneralProperty: SCI_STYLESETSIZE + parameter: i + value: size]; + [self setGeneralProperty: SCI_STYLESETBOLD + parameter: i + value: bold]; + [self setGeneralProperty: SCI_STYLESETITALIC + parameter: i + value: italic]; + } +} + +//-------------------------------------------------------------------------------------------------- + +@end + diff --git a/scintilla/cocoa/common.mk b/ThirdLibs/scintilla/cocoa/common.mk similarity index 95% rename from scintilla/cocoa/common.mk rename to ThirdLibs/scintilla/cocoa/common.mk index 600e3ada..beb3b0f4 100644 --- a/scintilla/cocoa/common.mk +++ b/ThirdLibs/scintilla/cocoa/common.mk @@ -1,57 +1,57 @@ -### shared variables and targets between Framework.mk and SciTest.mk ### - -# build directories -BLD=build -APP_BLD=$(BLD)/Application -FRM_BLD=$(BLD)/Framework - -ifdef DBG -CFLAGS=-g -O0 -else -CFLAGS=-Os -endif - -# compiler and compiler options -ARCH=-arch i386 $(CFLAGS) -CC=gcc -x c++ $(ARCH) -CO=gcc -x objective-c++ $(ARCH) -CCX=$(CC) $(gDEFs) $(INCS) -CCO=$(CO) $(gDEFs) $(INCS) - -# include directories and global #define -gDEFs=-DSCI_NAMESPACE -DSCI_LEXER - -# source directories -SRC_DIRS=../src ./ScintillaFramework ./ScintillaTest ./ \ - ../lexers ../lexlib - -INC_DIRS=$(SRC_DIRS) ../include - -INCS=$(addprefix -I,$(INC_DIRS)) - -vpath %.m $(SRC_DIRS) -vpath %.mm $(SRC_DIRS) -vpath %.cpp $(SRC_DIRS) -vpath %.cxx $(SRC_DIRS) -vpath %.c $(SRC_DIRS) -vpath %.h $(INC_DIRS) - -# clean everything -clean: - -rm -rf $(BLD) - -# build application objective-c++ files -$(APP_BLD)/%.o : %.mm - $(CCO) -c $< -o $@ - -# build application objective-c files -$(APP_BLD)/%.o : %.m - $(CCO) -c $< -o $@ - -# build framework c++ files -$(FRM_BLD)/%.o : %.cxx - $(CCX) -c $< -o $@ - -# build framework objective-c++ files -$(FRM_BLD)/%.o : %.mm +### shared variables and targets between Framework.mk and SciTest.mk ### + +# build directories +BLD=build +APP_BLD=$(BLD)/Application +FRM_BLD=$(BLD)/Framework + +ifdef DBG +CFLAGS=-g -O0 +else +CFLAGS=-Os +endif + +# compiler and compiler options +ARCH=-arch i386 $(CFLAGS) +CC=gcc -x c++ $(ARCH) +CO=gcc -x objective-c++ $(ARCH) +CCX=$(CC) $(gDEFs) $(INCS) +CCO=$(CO) $(gDEFs) $(INCS) + +# include directories and global #define +gDEFs=-DSCI_NAMESPACE -DSCI_LEXER + +# source directories +SRC_DIRS=../src ./ScintillaFramework ./ScintillaTest ./ \ + ../lexers ../lexlib + +INC_DIRS=$(SRC_DIRS) ../include + +INCS=$(addprefix -I,$(INC_DIRS)) + +vpath %.m $(SRC_DIRS) +vpath %.mm $(SRC_DIRS) +vpath %.cpp $(SRC_DIRS) +vpath %.cxx $(SRC_DIRS) +vpath %.c $(SRC_DIRS) +vpath %.h $(INC_DIRS) + +# clean everything +clean: + -rm -rf $(BLD) + +# build application objective-c++ files +$(APP_BLD)/%.o : %.mm + $(CCO) -c $< -o $@ + +# build application objective-c files +$(APP_BLD)/%.o : %.m + $(CCO) -c $< -o $@ + +# build framework c++ files +$(FRM_BLD)/%.o : %.cxx + $(CCX) -c $< -o $@ + +# build framework objective-c++ files +$(FRM_BLD)/%.o : %.mm $(CCO) -c $< -o $@ \ No newline at end of file diff --git a/scintilla/cocoa/res/info_bar_bg.png b/ThirdLibs/scintilla/cocoa/res/info_bar_bg.png similarity index 100% rename from scintilla/cocoa/res/info_bar_bg.png rename to ThirdLibs/scintilla/cocoa/res/info_bar_bg.png diff --git a/scintilla/cocoa/res/mac_cursor_busy.png b/ThirdLibs/scintilla/cocoa/res/mac_cursor_busy.png similarity index 100% rename from scintilla/cocoa/res/mac_cursor_busy.png rename to ThirdLibs/scintilla/cocoa/res/mac_cursor_busy.png diff --git a/scintilla/cocoa/res/mac_cursor_flipped.png b/ThirdLibs/scintilla/cocoa/res/mac_cursor_flipped.png similarity index 100% rename from scintilla/cocoa/res/mac_cursor_flipped.png rename to ThirdLibs/scintilla/cocoa/res/mac_cursor_flipped.png diff --git a/scintilla/delbin.bat b/ThirdLibs/scintilla/delbin.bat similarity index 99% rename from scintilla/delbin.bat rename to ThirdLibs/scintilla/delbin.bat index 8d29322f..8d6b642e 100644 --- a/scintilla/delbin.bat +++ b/ThirdLibs/scintilla/delbin.bat @@ -1 +1 @@ -del /S /Q *.a *.aps *.bsc *.dll *.dsw *.exe *.idb *.ilc *.ild *.ilf *.ilk *.ils *.lib *.map *.ncb *.obj *.o *.opt *.pdb *.plg *.res *.sbr *.tds *.exp >NUL: +del /S /Q *.a *.aps *.bsc *.dll *.dsw *.exe *.idb *.ilc *.ild *.ilf *.ilk *.ils *.lib *.map *.ncb *.obj *.o *.opt *.pdb *.plg *.res *.sbr *.tds *.exp >NUL: diff --git a/scintilla/delcvs.bat b/ThirdLibs/scintilla/delcvs.bat similarity index 95% rename from scintilla/delcvs.bat rename to ThirdLibs/scintilla/delcvs.bat index d3ed21ce..6c326531 100644 --- a/scintilla/delcvs.bat +++ b/ThirdLibs/scintilla/delcvs.bat @@ -1 +1 @@ -del /S /Q .cvsignore +del /S /Q .cvsignore diff --git a/scintilla/deltemp.bat b/ThirdLibs/scintilla/deltemp.bat similarity index 99% rename from scintilla/deltemp.bat rename to ThirdLibs/scintilla/deltemp.bat index ba352404..42da74dc 100644 --- a/scintilla/deltemp.bat +++ b/ThirdLibs/scintilla/deltemp.bat @@ -1 +1 @@ -del /S /Q *.a *.aps *.bsc *.dsw *.idb *.ilc *.ild *.ilf *.ilk *.ils *.map *.ncb *.obj *.o *.opt *.plg *.res *.sbr *.tds *.exp >NUL: +del /S /Q *.a *.aps *.bsc *.dsw *.idb *.ilc *.ild *.ilf *.ilk *.ils *.map *.ncb *.obj *.o *.opt *.plg *.res *.sbr *.tds *.exp >NUL: diff --git a/scintilla/doc/Design.html b/ThirdLibs/scintilla/doc/Design.html similarity index 97% rename from scintilla/doc/Design.html rename to ThirdLibs/scintilla/doc/Design.html index d426cb36..0ca231e8 100644 --- a/scintilla/doc/Design.html +++ b/ThirdLibs/scintilla/doc/Design.html @@ -1,249 +1,249 @@ - - - - - - - - - Scintilla and SciTE - - - - - - - - -
- Scintilla icon - - Scintilla - Component Design -
-

- Top level structure -

-

- Scintilla consists of three major layers of C++ code -

-
    -
  • - Portability Library -
  • -
  • - Core Code -
  • -
  • - Platform Events and API -
  • -
-

- The primary purpose of this structure is to separate the platform dependent code from the - platform independent core code. This makes it easier to port Scintilla to a new platform and - ensures that most readers of the code do not have to deal with platform details. To minimise - portability problems and avoid code bloat, a conservative subset of C++ is used in Scintilla - with no exception handling, run time type information or use of the standard C++ - library and with limited use of templates. -

-

- The currently supported platforms, Windows, GTK+/Linux and wxWindows are fairly similar in - many ways. - Each has windows, menus and bitmaps. These features generally work in similar ways so each - has a way to move a window or draw a red line. Sometimes one platform requires a sequence of - calls rather than a single call. At other times, the differences are more profound. Reading - the Windows clipboard occurs synchronously but reading the GTK+ clipboard requires a request - call that will be asynchronously answered with a message containing the clipboard data. - The wxWindows platform is available from the wxWindows site -

-
-

- Portability Library -

-

- This is a fairly small and thin layer over the platform's native capabilities. -

-

- The portability library is defined in Platform.h and is implemented once for each platform. - PlatWin.cxx defines the Windows variants of the methods and PlatGTK.cxx the GTK+ variants. -

-

- Several of the classes here hold platform specific object identifiers and act as proxies to - these platform objects. Most client code can thus manipulate the platform objects without - caring which is the current platform. Sometimes client code needs access to the underlying - object identifiers and this is provided by the GetID method. The underlying types of the - platform specific identifiers are typedefed to common names to allow them to be transferred - around in client code where needed. -

-

- Point, PRectangle -

-

- These are simple classes provided to hold the commonly used geometric primitives. A - PRectangle follows the Mac / Windows convention of not including its bottom and right sides - instead of including all its sides as is normal in GTK+. It is not called Rectangle as this may be - the name of a macro on Windows. -

-

- Colour, ColourPair, Palette -

-

- Colour holds a platform specific colour identifier - COLORREF for Windows and GdkColor for - GTK+. The red, green and blue components that make up the colour are limited to the 8 bits of - precision available on Windows. ColourPairs are used because not all possible colours are - always available. Using an 8 bit colour mode, which is a common setting for both Windows and - GTK+, only 256 colours are possible on the display. Thus when an application asks for a dull - red, say #400000, it may only be allocated an already available colour such as #800000 or - #330000. With 16 or 2 colour modes even less choice is available and the application will - have to use the limited set of already available colours. -

- A Palette object holds a set of colour pairs and can make the appropriate calls to ask to - allocate these colours and to see what the platform has decided will be allowed. -

- Font -

-

- Font holds a platform specific font identifier - HFONT for Windows, GdkFont* for GTK+. It - does not own the identifier and so will not delete the platform font object in its - destructor. Client code should call Destroy at appropriate times. -

-

- Surface -

-

- Surface is an abstraction over each platform's concept of somewhere that graphical drawing - operations can be done. It may wrap an already created drawing place such as a window or be - used to create a bitmap that can be drawn into and later copied onto another surface. On - Windows it wraps a HDC and possibly a HBITMAP. On GTK+ it wraps a GdkDrawable* and possibly a - GdkPixmap*. Other platform specific objects are created (and correctly destroyed) whenever - required to perform drawing actions. -

-

- Drawing operations provided include drawing filled and unfilled polygons, lines, rectangles, - ellipses and text. The height and width of text as well as other details can be measured. - Operations can be clipped to a rectangle. Most of the calls are stateless with all parameters - being passed at each call. The exception to this is line drawing which is performed by - calling MoveTo and then LineTo. -

-

- Window -

-

- Window acts as a proxy to a platform window allowing operations such as showing, moving, - redrawing, and destroying to be performed. It contains a platform specific window identifier - - HWND for Windows, GtkWidget* for GTK+. -

-

- ListBox -

-

- ListBox is a subclass of Window and acts as a proxy to a platform listbox adding methods for - operations such as adding, retrieving, and selecting items. -

-

- Menu -

-

- Menu is a small helper class for constructing popup menus. It contains the platform specific - menu identifier - HMENU for Windows, GtkItemFactory* for GTK+. Most of the work in - constructing menus requires access to platform events and so is done in the Platform Events - and API layer. -

-

- Platform -

-

- The Platform class is used to access the facilities of the platform. System wide parameters - such as double click speed and chrome colour are available from Platform. Utility functions - such as DebugPrintf are also available from Platform. -

-

- Core Code -

-

- The bulk of Scintilla's code is platform independent. This is made up of the CellBuffer, - ContractionState, Document, Editor, Indicator, LineMarker, Style, ViewStyle, KeyMap, - ScintillaBase, CallTip, - and AutoComplete primary classes. -

-

- CellBuffer -

-

- A CellBuffer holds text and styling information, the undo stack, the assignment of line - markers to lines, and the fold structure. -

-

- A cell contains a character byte and its associated style byte. The current state of the - cell buffer is the sequence of cells that make up the text and a sequence of line information - containing the starting position of each line and any markers assigned to each line. -

-

- The undo stack holds a sequence of actions on the cell buffer. Each action is one of a text - insertion, a text deletion or an undo start action. The start actions are used to group - sequences of text insertions and deletions together so they can be undone together. To - perform an undo operation, each insertion or deletion is undone in reverse sequence. - Similarly, redo reapplies each action to the buffer in sequence. Whenever a character is - inserted in the buffer either directly through a call such as InsertString or through undo or - redo, its styling byte is initially set to zero. Client code is responsible for styling each - character whenever convenient. Styling information is not stored in undo actions. -

-

- Document -

-

- A document contains a CellBuffer and deals with some higher level abstractions such as - words, DBCS character sequences and line end character sequences. It is responsible for - managing the styling process and for notifying other objects when changes occur to the - document. -

-

- Editor -

-

- The Editor object is central to Scintilla. It is responsible for displaying a document and - responding to user actions and requests from the container. It uses ContractionState, Indicator, - LineMarker, Style, and ViewStyle objects to display the document and a KeyMap class to - map key presses to functions. - The visibility of each line is kept in the ContractionState which is also responsible for mapping - from display lines to documents lines and vice versa. -

-

- There may be multiple Editor objects attached to one Document object. Changes to a - document are broadcast to the editors through the DocWatcher mechanism. -

-

- ScintillaBase -

-

- ScintillaBase is a subclass of Editor and adds extra windowing features including display of - calltips, autocompletion lists and context menus. These features use CallTip and AutoComplete - objects. This class is optional so a lightweight implementation of Scintilla may bypass it if - the added functionality is not required. -

-

- Platform Events and API -

-

- Each platform uses different mechanisms for receiving events. On Windows, events are - received through messages and COM. On GTK+, callback functions are used. -

-

- For each platform, a class is derived from ScintillaBase (and thus from Editor). This is - ScintillaWin on Windows and ScintillaGTK on GTK+. These classes are responsible for - connecting to the platforms event mechanism and also to implement some virtual methods in - Editor and ScintillaBase which are different on the platforms. For example, this layer has to - support this difference between the synchronous Windows clipboard and the asynchronous GTK+ - clipboard. -

-

- The external API is defined in this layer as each platform has different preferred styles of - API - messages on Windows and function calls on GTK+. This also allows multiple APIs to be - defined on a platform. The currently available API on GTK+ is similar to the Windows API and - does not follow platform conventions well. A second API could be implemented here that did - follow platform conventions. -

- - - + + + + + + + + + Scintilla and SciTE + + + + + + + + +
+ Scintilla icon + + Scintilla + Component Design +
+

+ Top level structure +

+

+ Scintilla consists of three major layers of C++ code +

+
    +
  • + Portability Library +
  • +
  • + Core Code +
  • +
  • + Platform Events and API +
  • +
+

+ The primary purpose of this structure is to separate the platform dependent code from the + platform independent core code. This makes it easier to port Scintilla to a new platform and + ensures that most readers of the code do not have to deal with platform details. To minimise + portability problems and avoid code bloat, a conservative subset of C++ is used in Scintilla + with no exception handling, run time type information or use of the standard C++ + library and with limited use of templates. +

+

+ The currently supported platforms, Windows, GTK+/Linux and wxWindows are fairly similar in + many ways. + Each has windows, menus and bitmaps. These features generally work in similar ways so each + has a way to move a window or draw a red line. Sometimes one platform requires a sequence of + calls rather than a single call. At other times, the differences are more profound. Reading + the Windows clipboard occurs synchronously but reading the GTK+ clipboard requires a request + call that will be asynchronously answered with a message containing the clipboard data. + The wxWindows platform is available from the wxWindows site +

+
+

+ Portability Library +

+

+ This is a fairly small and thin layer over the platform's native capabilities. +

+

+ The portability library is defined in Platform.h and is implemented once for each platform. + PlatWin.cxx defines the Windows variants of the methods and PlatGTK.cxx the GTK+ variants. +

+

+ Several of the classes here hold platform specific object identifiers and act as proxies to + these platform objects. Most client code can thus manipulate the platform objects without + caring which is the current platform. Sometimes client code needs access to the underlying + object identifiers and this is provided by the GetID method. The underlying types of the + platform specific identifiers are typedefed to common names to allow them to be transferred + around in client code where needed. +

+

+ Point, PRectangle +

+

+ These are simple classes provided to hold the commonly used geometric primitives. A + PRectangle follows the Mac / Windows convention of not including its bottom and right sides + instead of including all its sides as is normal in GTK+. It is not called Rectangle as this may be + the name of a macro on Windows. +

+

+ Colour, ColourPair, Palette +

+

+ Colour holds a platform specific colour identifier - COLORREF for Windows and GdkColor for + GTK+. The red, green and blue components that make up the colour are limited to the 8 bits of + precision available on Windows. ColourPairs are used because not all possible colours are + always available. Using an 8 bit colour mode, which is a common setting for both Windows and + GTK+, only 256 colours are possible on the display. Thus when an application asks for a dull + red, say #400000, it may only be allocated an already available colour such as #800000 or + #330000. With 16 or 2 colour modes even less choice is available and the application will + have to use the limited set of already available colours. +

+ A Palette object holds a set of colour pairs and can make the appropriate calls to ask to + allocate these colours and to see what the platform has decided will be allowed. +

+ Font +

+

+ Font holds a platform specific font identifier - HFONT for Windows, GdkFont* for GTK+. It + does not own the identifier and so will not delete the platform font object in its + destructor. Client code should call Destroy at appropriate times. +

+

+ Surface +

+

+ Surface is an abstraction over each platform's concept of somewhere that graphical drawing + operations can be done. It may wrap an already created drawing place such as a window or be + used to create a bitmap that can be drawn into and later copied onto another surface. On + Windows it wraps a HDC and possibly a HBITMAP. On GTK+ it wraps a GdkDrawable* and possibly a + GdkPixmap*. Other platform specific objects are created (and correctly destroyed) whenever + required to perform drawing actions. +

+

+ Drawing operations provided include drawing filled and unfilled polygons, lines, rectangles, + ellipses and text. The height and width of text as well as other details can be measured. + Operations can be clipped to a rectangle. Most of the calls are stateless with all parameters + being passed at each call. The exception to this is line drawing which is performed by + calling MoveTo and then LineTo. +

+

+ Window +

+

+ Window acts as a proxy to a platform window allowing operations such as showing, moving, + redrawing, and destroying to be performed. It contains a platform specific window identifier + - HWND for Windows, GtkWidget* for GTK+. +

+

+ ListBox +

+

+ ListBox is a subclass of Window and acts as a proxy to a platform listbox adding methods for + operations such as adding, retrieving, and selecting items. +

+

+ Menu +

+

+ Menu is a small helper class for constructing popup menus. It contains the platform specific + menu identifier - HMENU for Windows, GtkItemFactory* for GTK+. Most of the work in + constructing menus requires access to platform events and so is done in the Platform Events + and API layer. +

+

+ Platform +

+

+ The Platform class is used to access the facilities of the platform. System wide parameters + such as double click speed and chrome colour are available from Platform. Utility functions + such as DebugPrintf are also available from Platform. +

+

+ Core Code +

+

+ The bulk of Scintilla's code is platform independent. This is made up of the CellBuffer, + ContractionState, Document, Editor, Indicator, LineMarker, Style, ViewStyle, KeyMap, + ScintillaBase, CallTip, + and AutoComplete primary classes. +

+

+ CellBuffer +

+

+ A CellBuffer holds text and styling information, the undo stack, the assignment of line + markers to lines, and the fold structure. +

+

+ A cell contains a character byte and its associated style byte. The current state of the + cell buffer is the sequence of cells that make up the text and a sequence of line information + containing the starting position of each line and any markers assigned to each line. +

+

+ The undo stack holds a sequence of actions on the cell buffer. Each action is one of a text + insertion, a text deletion or an undo start action. The start actions are used to group + sequences of text insertions and deletions together so they can be undone together. To + perform an undo operation, each insertion or deletion is undone in reverse sequence. + Similarly, redo reapplies each action to the buffer in sequence. Whenever a character is + inserted in the buffer either directly through a call such as InsertString or through undo or + redo, its styling byte is initially set to zero. Client code is responsible for styling each + character whenever convenient. Styling information is not stored in undo actions. +

+

+ Document +

+

+ A document contains a CellBuffer and deals with some higher level abstractions such as + words, DBCS character sequences and line end character sequences. It is responsible for + managing the styling process and for notifying other objects when changes occur to the + document. +

+

+ Editor +

+

+ The Editor object is central to Scintilla. It is responsible for displaying a document and + responding to user actions and requests from the container. It uses ContractionState, Indicator, + LineMarker, Style, and ViewStyle objects to display the document and a KeyMap class to + map key presses to functions. + The visibility of each line is kept in the ContractionState which is also responsible for mapping + from display lines to documents lines and vice versa. +

+

+ There may be multiple Editor objects attached to one Document object. Changes to a + document are broadcast to the editors through the DocWatcher mechanism. +

+

+ ScintillaBase +

+

+ ScintillaBase is a subclass of Editor and adds extra windowing features including display of + calltips, autocompletion lists and context menus. These features use CallTip and AutoComplete + objects. This class is optional so a lightweight implementation of Scintilla may bypass it if + the added functionality is not required. +

+

+ Platform Events and API +

+

+ Each platform uses different mechanisms for receiving events. On Windows, events are + received through messages and COM. On GTK+, callback functions are used. +

+

+ For each platform, a class is derived from ScintillaBase (and thus from Editor). This is + ScintillaWin on Windows and ScintillaGTK on GTK+. These classes are responsible for + connecting to the platforms event mechanism and also to implement some virtual methods in + Editor and ScintillaBase which are different on the platforms. For example, this layer has to + support this difference between the synchronous Windows clipboard and the asynchronous GTK+ + clipboard. +

+

+ The external API is defined in this layer as each platform has different preferred styles of + API - messages on Windows and function calls on GTK+. This also allows multiple APIs to be + defined on a platform. The currently available API on GTK+ is similar to the Windows API and + does not follow platform conventions well. A second API could be implemented here that did + follow platform conventions. +

+ + + diff --git a/scintilla/doc/Icons.html b/ThirdLibs/scintilla/doc/Icons.html similarity index 96% rename from scintilla/doc/Icons.html rename to ThirdLibs/scintilla/doc/Icons.html index 0d8b8bf5..0bf302d1 100644 --- a/scintilla/doc/Icons.html +++ b/ThirdLibs/scintilla/doc/Icons.html @@ -1,56 +1,56 @@ - - - - - - - - - Scintilla icons - - - - - - - - -
- Scintilla icon - - Scintilla - and SciTE -
-

- Icons -

-

- These images may be used under the same license as Scintilla. -

-

- Drawn by Iago Rubio, Philippe Lhoste, and Neil Hodgson. -

-

- zip format (70K) -

- - - - - - - - - - - - - - - - - -
For autocompletion listsFor margin markers
12x1216x1624x2432x32
- - + + + + + + + + + Scintilla icons + + + + + + + + +
+ Scintilla icon + + Scintilla + and SciTE +
+

+ Icons +

+

+ These images may be used under the same license as Scintilla. +

+

+ Drawn by Iago Rubio, Philippe Lhoste, and Neil Hodgson. +

+

+ zip format (70K) +

+ + + + + + + + + + + + + + + + + +
For autocompletion listsFor margin markers
12x1216x1624x2432x32
+ + diff --git a/scintilla/doc/Lexer.txt b/ThirdLibs/scintilla/doc/Lexer.txt similarity index 97% rename from scintilla/doc/Lexer.txt rename to ThirdLibs/scintilla/doc/Lexer.txt index 5f118e73..9d4ab50f 100644 --- a/scintilla/doc/Lexer.txt +++ b/ThirdLibs/scintilla/doc/Lexer.txt @@ -1,226 +1,226 @@ -How to write a scintilla lexer - -A lexer for a particular language determines how a specified range of -text shall be colored. Writing a lexer is relatively straightforward -because the lexer need only color given text. The harder job of -determining how much text actually needs to be colored is handled by -Scintilla itself, that is, the lexer's caller. - - -Parameters - -The lexer for language LLL has the following prototype: - - static void ColouriseLLLDoc ( - unsigned int startPos, int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler); - -The styler parameter is an Accessor object. The lexer must use this -object to access the text to be colored. The lexer gets the character -at position i using styler.SafeGetCharAt(i); - -The startPos and length parameters indicate the range of text to be -recolored; the lexer must determine the proper color for all characters -in positions startPos through startPos+length. - -The initStyle parameter indicates the initial state, that is, the state -at the character before startPos. States also indicate the coloring to -be used for a particular range of text. - -Note: the character at StartPos is assumed to start a line, so if a -newline terminates the initStyle state the lexer should enter its -default state (or whatever state should follow initStyle). - -The keywordlists parameter specifies the keywords that the lexer must -recognize. A WordList class object contains methods that make simplify -the recognition of keywords. Present lexers use a helper function -called classifyWordLLL to recognize keywords. These functions show how -to use the keywordlists parameter to recognize keywords. This -documentation will not discuss keywords further. - - -The lexer code - -The task of a lexer can be summarized briefly: for each range r of -characters that are to be colored the same, the lexer should call - - styler.ColourTo(i, state) - -where i is the position of the last character of the range r. The lexer -should set the state variable to the coloring state of the character at -position i and continue until the entire text has been colored. - -Note 1: the styler (Accessor) object remembers the i parameter in the -previous calls to styler.ColourTo, so the single i parameter suffices to -indicate a range of characters. - -Note 2: As a side effect of calling styler.ColourTo(i,state), the -coloring states of all characters in the range are remembered so that -Scintilla may set the initStyle parameter correctly on future calls to -the -lexer. - - -Lexer organization - -There are at least two ways to organize the code of each lexer. Present -lexers use what might be called a "character-based" approach: the outer -loop iterates over characters, like this: - - lengthDoc = startPos + length ; - for (unsigned int i = startPos; i < lengthDoc; i++) { - chNext = styler.SafeGetCharAt(i + 1); - << handle special cases >> - switch(state) { - // Handlers examine only ch and chNext. - // Handlers call styler.ColorTo(i,state) if the state changes. - case state_1: << handle ch in state 1 >> - case state_2: << handle ch in state 2 >> - ... - case state_n: << handle ch in state n >> - } - chPrev = ch; - } - styler.ColourTo(lengthDoc - 1, state); - - -An alternative would be to use a "state-based" approach. The outer loop -would iterate over states, like this: - - lengthDoc = startPos+lenth ; - for ( unsigned int i = startPos ;; ) { - char ch = styler.SafeGetCharAt(i); - int new_state = 0 ; - switch ( state ) { - // scanners set new_state if they set the next state. - case state_1: << scan to the end of state 1 >> break ; - case state_2: << scan to the end of state 2 >> break ; - case default_state: - << scan to the next non-default state and set new_state >> - } - styler.ColourTo(i, state); - if ( i >= lengthDoc ) break ; - if ( ! new_state ) { - ch = styler.SafeGetCharAt(i); - << set state based on ch in the default state >> - } - } - styler.ColourTo(lengthDoc - 1, state); - -This approach might seem to be more natural. State scanners are simpler -than character scanners because less needs to be done. For example, -there is no need to test for the start of a C string inside the scanner -for a C comment. Also this way makes it natural to define routines that -could be used by more than one scanner; for example, a scanToEndOfLine -routine. - -However, the special cases handled in the main loop in the -character-based approach would have to be handled by each state scanner, -so both approaches have advantages. These special cases are discussed -below. - -Special case: Lead characters - -Lead bytes are part of DBCS processing for languages such as Japanese -using an encoding such as Shift-JIS. In these encodings, extended -(16-bit) characters are encoded as a lead byte followed by a trail byte. - -Lead bytes are rarely of any lexical significance, normally only being -allowed within strings and comments. In such contexts, lexers should -ignore ch if styler.IsLeadByte(ch) returns TRUE. - -Note: UTF-8 is simpler than Shift-JIS, so no special handling is -applied for it. All UTF-8 extended characters are >= 128 and none are -lexically significant in programming languages which, so far, use only -characters in ASCII for operators, comment markers, etc. - - -Special case: Folding - -Folding may be performed in the lexer function. It is better to use a -separate folder function as that avoids some troublesome interaction -between styling and folding. The folder function will be run after the -lexer function if folding is enabled. The rest of this section explains -how to perform folding within the lexer function. - -During initialization, lexers that support folding set - - bool fold = styler.GetPropertyInt("fold"); - -If folding is enabled in the editor, fold will be TRUE and the lexer -should call: - - styler.SetLevel(line, level); - -at the end of each line and just before exiting. - -The line parameter is simply the count of the number of newlines seen. -It's initial value is styler.GetLine(startPos) and it is incremented -(after calling styler.SetLevel) whenever a newline is seen. - -The level parameter is the desired indentation level in the low 12 bits, -along with flag bits in the upper four bits. The indentation level -depends on the language. For C++, it is incremented when the lexer sees -a '{' and decremented when the lexer sees a '}' (outside of strings and -comments, of course). - -The following flag bits, defined in Scintilla.h, may be set or cleared -in the flags parameter. The SC_FOLDLEVELWHITEFLAG flag is set if the -lexer considers that the line contains nothing but whitespace. The -SC_FOLDLEVELHEADERFLAG flag indicates that the line is a fold point. -This normally means that the next line has a greater level than present -line. However, the lexer may have some other basis for determining a -fold point. For example, a lexer might create a header line for the -first line of a function definition rather than the last. - -The SC_FOLDLEVELNUMBERMASK mask denotes the level number in the low 12 -bits of the level param. This mask may be used to isolate either flags -or level numbers. - -For example, the C++ lexer contains the following code when a newline is -seen: - - if (fold) { - int lev = levelPrev; - - // Set the "all whitespace" bit if the line is blank. - if (visChars == 0) - lev |= SC_FOLDLEVELWHITEFLAG; - - // Set the "header" bit if needed. - if ((levelCurrent > levelPrev) && (visChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - styler.SetLevel(lineCurrent, lev); - - // reinitialize the folding vars describing the present line. - lineCurrent++; - visChars = 0; // Number of non-whitespace characters on the line. - levelPrev = levelCurrent; - } - -The following code appears in the C++ lexer just before exit: - - // Fill in the real level of the next line, keeping the current flags - // as they will be filled in later. - if (fold) { - // Mask off the level number, leaving only the previous flags. - int flagsNext = styler.LevelAt(lineCurrent); - flagsNext &= ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); - } - - -Don't worry about performance - -The writer of a lexer may safely ignore performance considerations: the -cost of redrawing the screen is several orders of magnitude greater than -the cost of function calls, etc. Moreover, Scintilla performs all the -important optimizations; Scintilla ensures that a lexer will be called -only to recolor text that actually needs to be recolored. Finally, it -is not necessary to avoid extra calls to styler.ColourTo: the sytler -object buffers calls to ColourTo to avoid multiple updates of the -screen. - +How to write a scintilla lexer + +A lexer for a particular language determines how a specified range of +text shall be colored. Writing a lexer is relatively straightforward +because the lexer need only color given text. The harder job of +determining how much text actually needs to be colored is handled by +Scintilla itself, that is, the lexer's caller. + + +Parameters + +The lexer for language LLL has the following prototype: + + static void ColouriseLLLDoc ( + unsigned int startPos, int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler); + +The styler parameter is an Accessor object. The lexer must use this +object to access the text to be colored. The lexer gets the character +at position i using styler.SafeGetCharAt(i); + +The startPos and length parameters indicate the range of text to be +recolored; the lexer must determine the proper color for all characters +in positions startPos through startPos+length. + +The initStyle parameter indicates the initial state, that is, the state +at the character before startPos. States also indicate the coloring to +be used for a particular range of text. + +Note: the character at StartPos is assumed to start a line, so if a +newline terminates the initStyle state the lexer should enter its +default state (or whatever state should follow initStyle). + +The keywordlists parameter specifies the keywords that the lexer must +recognize. A WordList class object contains methods that make simplify +the recognition of keywords. Present lexers use a helper function +called classifyWordLLL to recognize keywords. These functions show how +to use the keywordlists parameter to recognize keywords. This +documentation will not discuss keywords further. + + +The lexer code + +The task of a lexer can be summarized briefly: for each range r of +characters that are to be colored the same, the lexer should call + + styler.ColourTo(i, state) + +where i is the position of the last character of the range r. The lexer +should set the state variable to the coloring state of the character at +position i and continue until the entire text has been colored. + +Note 1: the styler (Accessor) object remembers the i parameter in the +previous calls to styler.ColourTo, so the single i parameter suffices to +indicate a range of characters. + +Note 2: As a side effect of calling styler.ColourTo(i,state), the +coloring states of all characters in the range are remembered so that +Scintilla may set the initStyle parameter correctly on future calls to +the +lexer. + + +Lexer organization + +There are at least two ways to organize the code of each lexer. Present +lexers use what might be called a "character-based" approach: the outer +loop iterates over characters, like this: + + lengthDoc = startPos + length ; + for (unsigned int i = startPos; i < lengthDoc; i++) { + chNext = styler.SafeGetCharAt(i + 1); + << handle special cases >> + switch(state) { + // Handlers examine only ch and chNext. + // Handlers call styler.ColorTo(i,state) if the state changes. + case state_1: << handle ch in state 1 >> + case state_2: << handle ch in state 2 >> + ... + case state_n: << handle ch in state n >> + } + chPrev = ch; + } + styler.ColourTo(lengthDoc - 1, state); + + +An alternative would be to use a "state-based" approach. The outer loop +would iterate over states, like this: + + lengthDoc = startPos+lenth ; + for ( unsigned int i = startPos ;; ) { + char ch = styler.SafeGetCharAt(i); + int new_state = 0 ; + switch ( state ) { + // scanners set new_state if they set the next state. + case state_1: << scan to the end of state 1 >> break ; + case state_2: << scan to the end of state 2 >> break ; + case default_state: + << scan to the next non-default state and set new_state >> + } + styler.ColourTo(i, state); + if ( i >= lengthDoc ) break ; + if ( ! new_state ) { + ch = styler.SafeGetCharAt(i); + << set state based on ch in the default state >> + } + } + styler.ColourTo(lengthDoc - 1, state); + +This approach might seem to be more natural. State scanners are simpler +than character scanners because less needs to be done. For example, +there is no need to test for the start of a C string inside the scanner +for a C comment. Also this way makes it natural to define routines that +could be used by more than one scanner; for example, a scanToEndOfLine +routine. + +However, the special cases handled in the main loop in the +character-based approach would have to be handled by each state scanner, +so both approaches have advantages. These special cases are discussed +below. + +Special case: Lead characters + +Lead bytes are part of DBCS processing for languages such as Japanese +using an encoding such as Shift-JIS. In these encodings, extended +(16-bit) characters are encoded as a lead byte followed by a trail byte. + +Lead bytes are rarely of any lexical significance, normally only being +allowed within strings and comments. In such contexts, lexers should +ignore ch if styler.IsLeadByte(ch) returns TRUE. + +Note: UTF-8 is simpler than Shift-JIS, so no special handling is +applied for it. All UTF-8 extended characters are >= 128 and none are +lexically significant in programming languages which, so far, use only +characters in ASCII for operators, comment markers, etc. + + +Special case: Folding + +Folding may be performed in the lexer function. It is better to use a +separate folder function as that avoids some troublesome interaction +between styling and folding. The folder function will be run after the +lexer function if folding is enabled. The rest of this section explains +how to perform folding within the lexer function. + +During initialization, lexers that support folding set + + bool fold = styler.GetPropertyInt("fold"); + +If folding is enabled in the editor, fold will be TRUE and the lexer +should call: + + styler.SetLevel(line, level); + +at the end of each line and just before exiting. + +The line parameter is simply the count of the number of newlines seen. +It's initial value is styler.GetLine(startPos) and it is incremented +(after calling styler.SetLevel) whenever a newline is seen. + +The level parameter is the desired indentation level in the low 12 bits, +along with flag bits in the upper four bits. The indentation level +depends on the language. For C++, it is incremented when the lexer sees +a '{' and decremented when the lexer sees a '}' (outside of strings and +comments, of course). + +The following flag bits, defined in Scintilla.h, may be set or cleared +in the flags parameter. The SC_FOLDLEVELWHITEFLAG flag is set if the +lexer considers that the line contains nothing but whitespace. The +SC_FOLDLEVELHEADERFLAG flag indicates that the line is a fold point. +This normally means that the next line has a greater level than present +line. However, the lexer may have some other basis for determining a +fold point. For example, a lexer might create a header line for the +first line of a function definition rather than the last. + +The SC_FOLDLEVELNUMBERMASK mask denotes the level number in the low 12 +bits of the level param. This mask may be used to isolate either flags +or level numbers. + +For example, the C++ lexer contains the following code when a newline is +seen: + + if (fold) { + int lev = levelPrev; + + // Set the "all whitespace" bit if the line is blank. + if (visChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + + // Set the "header" bit if needed. + if ((levelCurrent > levelPrev) && (visChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + styler.SetLevel(lineCurrent, lev); + + // reinitialize the folding vars describing the present line. + lineCurrent++; + visChars = 0; // Number of non-whitespace characters on the line. + levelPrev = levelCurrent; + } + +The following code appears in the C++ lexer just before exit: + + // Fill in the real level of the next line, keeping the current flags + // as they will be filled in later. + if (fold) { + // Mask off the level number, leaving only the previous flags. + int flagsNext = styler.LevelAt(lineCurrent); + flagsNext &= ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); + } + + +Don't worry about performance + +The writer of a lexer may safely ignore performance considerations: the +cost of redrawing the screen is several orders of magnitude greater than +the cost of function calls, etc. Moreover, Scintilla performs all the +important optimizations; Scintilla ensures that a lexer will be called +only to recolor text that actually needs to be recolored. Finally, it +is not necessary to avoid extra calls to styler.ColourTo: the sytler +object buffers calls to ColourTo to avoid multiple updates of the +screen. + Page contributed by Edward K. Ream \ No newline at end of file diff --git a/scintilla/doc/SciBreak.jpg b/ThirdLibs/scintilla/doc/SciBreak.jpg similarity index 100% rename from scintilla/doc/SciBreak.jpg rename to ThirdLibs/scintilla/doc/SciBreak.jpg diff --git a/scintilla/doc/SciCoding.html b/ThirdLibs/scintilla/doc/SciCoding.html similarity index 98% rename from scintilla/doc/SciCoding.html rename to ThirdLibs/scintilla/doc/SciCoding.html index 1d45f0a7..d51e3165 100644 --- a/scintilla/doc/SciCoding.html +++ b/ThirdLibs/scintilla/doc/SciCoding.html @@ -1,259 +1,259 @@ - - - - - - - - Scintilla and SciTE Code Style Preferences - - - - - - - - - -
- Scintilla icon - - Scintilla - and SciTE -
-

- Code Style -

-

- Introduction -

-

- The source code of Scintilla and SciTE follow my preferences. - Some of these decisions are arbitrary and based on my sense of aesthetics - but its good to have all the code look the same even if its not exactly how - everyone would prefer. -

-

- Code that does not follow these conventions will be accepted, but will be modified - as time goes by to fit the conventions. Scintilla code follows the conventions more - closely than SciTE except for lexers which are relatively independent modules. - Lexers that are maintained by others are left as they are submitted except that - warnings will be fixed so the whole project can compile cleanly. -

-

- The AStyle formatting - program with '-taOHUKk3 -M8' arguments formats code in much the right way although - there are a few bugs in AStyle. -

-

- Language features -

-

- Design goals for Scintilla and SciTE include portability to currently available C++ - compilers on diverse platforms with high performance and low resource usage. - Scintilla has stricter portability requirements to SciTE as it may be ported to - low capability platforms. -

-

- To achieve portability, only a subset of C++ features are used. - Exceptions and templates may be used but, since Scintilla can be used from C as well as - C++, exceptions may not be thrown out of Scintilla and all exceptions should be caught - before returning from Scintilla. - Run-time type information adds to memory use so is turned off. - A 'Scintilla' name spaces is optionally used based on the SCI_NAMESPACE - definition. This helps with name clashes on OS X. -

-

- The goto statement is not used because of bad memories from my first job - maintaining FORTRAN programs. The union feature is not used as it can lead to - non-type-safe value access. -

-

- Casting -

-

- Do not use old C style casts like (char *)s. Instead use the most strict form of C++ - cast possible like const_cast<char *>(s). Use static_cast and const_cast - where possible rather than reinterpret_cast. Because the code is compiled with - run-time type information turned off, dynamic_cast will not work. -

-

- The benefit to using the new style casts is that they explicitly detail what evil is - occurring and act as signals that something potentially unsafe is being done. -

-

- Code that treats const seriously is easier to reason about both for humans - and compilers, so use const parameters and avoid const_cast. -

-

- Warnings -

-

- To help ensure code is well written and portable, it is compiled with almost all - warnings turned on. This sometimes results in warnings about code that is - completely good (false positives) but changing the code to avoid the warnings - is generally fast and has little impact on readability. -

-

- Initialise all variables and minimise the scope of variables. If a variable is defined - just before its use then it can't be misused by code before that point. - Use loop declarations that are compatible with both the C++ standard and currently - available compilers. -

-

- Allocation -

-

- Memory exhaustion can occur in many Scintilla methods. - This should be checked for and handled but once it has happened, it is very difficult to do - anything as Scintilla's data structures may be in an inconsistent state. - Fixed length buffers are often used as these are simple and avoid the need to - worry about memory exhaustion but then require that buffer lengths are - respected. -

-

- The C++ new and delete operators are preferred over C's malloc and free - as new and delete are type safe. -

-

- Bracketing -

-

- Start brackets, '{', should be located on the line of the control structure they - start and end brackets, '}', should be at the indented start of a line. When there is - an else clause, this occurs on the same line as the '}'. - This format uses less lines than alternatives, allowing more code to be seen on screen. - Fully bracketed control - structures are preferred because this makes it more likely that modifications will - be correct and it allows Scintilla's folder to work. No braces on returned - expressions as return is a keyword, not a function call. -

-bool fn(int a) {
-        
if (a) {
-                
s();
-                
t();
-        
} else {
-                
u();
-        
}
-        
return !a;
-
}
-

- Spacing -

-

- Spaces on both sides of '=' and comparison operators and no attempt to line up '='. - No space before or after '(', when used in calls, but a space after every ','. - No spaces between tokens in short expressions but may be present in - longer expressions. Space before '{'. No space before ';'. - No space after '*' when used to mean pointer and no space after '[' or ']'. - One space between keywords and '('. -

-void StoreConditionally(int c, const char *s) {
-        
if (c && (baseSegment == trustSegment["html"])) {
-                
baseSegment = s+1;
-                
Store(s, baseSegment, "html");
-        
}
-
} -

- Names -

-

- Identifiers use mixed case and no underscores. - Class, function and method names start with an uppercase letter and use - further upper case letters to distinguish words. Variables start with a lower - case letter and use upper case letters to distinguish words. - Loop counters and similar variables can have simple names like 'i'. - Function calls should be differentiated from method calls with an initial '::' - global scope modifier. -

-class StorageZone {
-
public:
-        
void Store(const char *s) {
-                
Media *mediaStore = ::GetBaseMedia(zoneDefault);
-                
for (int i=mediaStore->cursor; mediaStore[i], i++) {
-                        
mediaStore->Persist(s[i]);
-                
}
-        
}
-
}; -

- Submitting a lexer -

- -

Add a public feature request to the Feature Request Tracker.

-

Send all the modified and new files as full text (not patches) in an archive (.zip or .tgz).

-

Define all of the lexical states in a modified Scintilla.iface.

-

Ensure there are no warnings under the compiler you use. Warnings from other compilers - will be noted on the feature request.

-

sc.ch is an int: do not pass this around as a char.

- - + + + + + + + + Scintilla and SciTE Code Style Preferences + + + + + + + + + +
+ Scintilla icon + + Scintilla + and SciTE +
+

+ Code Style +

+

+ Introduction +

+

+ The source code of Scintilla and SciTE follow my preferences. + Some of these decisions are arbitrary and based on my sense of aesthetics + but its good to have all the code look the same even if its not exactly how + everyone would prefer. +

+

+ Code that does not follow these conventions will be accepted, but will be modified + as time goes by to fit the conventions. Scintilla code follows the conventions more + closely than SciTE except for lexers which are relatively independent modules. + Lexers that are maintained by others are left as they are submitted except that + warnings will be fixed so the whole project can compile cleanly. +

+

+ The AStyle formatting + program with '-taOHUKk3 -M8' arguments formats code in much the right way although + there are a few bugs in AStyle. +

+

+ Language features +

+

+ Design goals for Scintilla and SciTE include portability to currently available C++ + compilers on diverse platforms with high performance and low resource usage. + Scintilla has stricter portability requirements to SciTE as it may be ported to + low capability platforms. +

+

+ To achieve portability, only a subset of C++ features are used. + Exceptions and templates may be used but, since Scintilla can be used from C as well as + C++, exceptions may not be thrown out of Scintilla and all exceptions should be caught + before returning from Scintilla. + Run-time type information adds to memory use so is turned off. + A 'Scintilla' name spaces is optionally used based on the SCI_NAMESPACE + definition. This helps with name clashes on OS X. +

+

+ The goto statement is not used because of bad memories from my first job + maintaining FORTRAN programs. The union feature is not used as it can lead to + non-type-safe value access. +

+

+ Casting +

+

+ Do not use old C style casts like (char *)s. Instead use the most strict form of C++ + cast possible like const_cast<char *>(s). Use static_cast and const_cast + where possible rather than reinterpret_cast. Because the code is compiled with + run-time type information turned off, dynamic_cast will not work. +

+

+ The benefit to using the new style casts is that they explicitly detail what evil is + occurring and act as signals that something potentially unsafe is being done. +

+

+ Code that treats const seriously is easier to reason about both for humans + and compilers, so use const parameters and avoid const_cast. +

+

+ Warnings +

+

+ To help ensure code is well written and portable, it is compiled with almost all + warnings turned on. This sometimes results in warnings about code that is + completely good (false positives) but changing the code to avoid the warnings + is generally fast and has little impact on readability. +

+

+ Initialise all variables and minimise the scope of variables. If a variable is defined + just before its use then it can't be misused by code before that point. + Use loop declarations that are compatible with both the C++ standard and currently + available compilers. +

+

+ Allocation +

+

+ Memory exhaustion can occur in many Scintilla methods. + This should be checked for and handled but once it has happened, it is very difficult to do + anything as Scintilla's data structures may be in an inconsistent state. + Fixed length buffers are often used as these are simple and avoid the need to + worry about memory exhaustion but then require that buffer lengths are + respected. +

+

+ The C++ new and delete operators are preferred over C's malloc and free + as new and delete are type safe. +

+

+ Bracketing +

+

+ Start brackets, '{', should be located on the line of the control structure they + start and end brackets, '}', should be at the indented start of a line. When there is + an else clause, this occurs on the same line as the '}'. + This format uses less lines than alternatives, allowing more code to be seen on screen. + Fully bracketed control + structures are preferred because this makes it more likely that modifications will + be correct and it allows Scintilla's folder to work. No braces on returned + expressions as return is a keyword, not a function call. +

+bool fn(int a) {
+        
if (a) {
+                
s();
+                
t();
+        
} else {
+                
u();
+        
}
+        
return !a;
+
}
+

+ Spacing +

+

+ Spaces on both sides of '=' and comparison operators and no attempt to line up '='. + No space before or after '(', when used in calls, but a space after every ','. + No spaces between tokens in short expressions but may be present in + longer expressions. Space before '{'. No space before ';'. + No space after '*' when used to mean pointer and no space after '[' or ']'. + One space between keywords and '('. +

+void StoreConditionally(int c, const char *s) {
+        
if (c && (baseSegment == trustSegment["html"])) {
+                
baseSegment = s+1;
+                
Store(s, baseSegment, "html");
+        
}
+
} +

+ Names +

+

+ Identifiers use mixed case and no underscores. + Class, function and method names start with an uppercase letter and use + further upper case letters to distinguish words. Variables start with a lower + case letter and use upper case letters to distinguish words. + Loop counters and similar variables can have simple names like 'i'. + Function calls should be differentiated from method calls with an initial '::' + global scope modifier. +

+class StorageZone {
+
public:
+        
void Store(const char *s) {
+                
Media *mediaStore = ::GetBaseMedia(zoneDefault);
+                
for (int i=mediaStore->cursor; mediaStore[i], i++) {
+                        
mediaStore->Persist(s[i]);
+                
}
+        
}
+
}; +

+ Submitting a lexer +

+ +

Add a public feature request to the Feature Request Tracker.

+

Send all the modified and new files as full text (not patches) in an archive (.zip or .tgz).

+

Define all of the lexical states in a modified Scintilla.iface.

+

Ensure there are no warnings under the compiler you use. Warnings from other compilers + will be noted on the feature request.

+

sc.ch is an int: do not pass this around as a char.

+ + diff --git a/scintilla/doc/SciRest.jpg b/ThirdLibs/scintilla/doc/SciRest.jpg similarity index 100% rename from scintilla/doc/SciRest.jpg rename to ThirdLibs/scintilla/doc/SciRest.jpg diff --git a/scintilla/doc/SciTEIco.png b/ThirdLibs/scintilla/doc/SciTEIco.png similarity index 100% rename from scintilla/doc/SciTEIco.png rename to ThirdLibs/scintilla/doc/SciTEIco.png diff --git a/scintilla/doc/SciWord.jpg b/ThirdLibs/scintilla/doc/SciWord.jpg similarity index 100% rename from scintilla/doc/SciWord.jpg rename to ThirdLibs/scintilla/doc/SciWord.jpg diff --git a/scintilla/doc/ScintillaDoc.html b/ThirdLibs/scintilla/doc/ScintillaDoc.html similarity index 98% rename from scintilla/doc/ScintillaDoc.html rename to ThirdLibs/scintilla/doc/ScintillaDoc.html index 539c4f9b..2e8406ba 100644 --- a/scintilla/doc/ScintillaDoc.html +++ b/ThirdLibs/scintilla/doc/ScintillaDoc.html @@ -1,6968 +1,6968 @@ - - - - - - - - - - Scintilla Documentation - - - - - - - - - - - -
Scintilla iconScintilla
- -

Scintilla Documentation

- -

Last edited 24/January/2012 NH

- -

There is an overview of the internal design of - Scintilla.
- Some notes on using Scintilla.
- How to use the Scintilla Edit Control on Windows.
- A simple sample using Scintilla from - C++ on Windows.
- A simple sample using Scintilla from - Visual Basic.
- Bait is a tiny sample using Scintilla - on GTK+.
- A detailed description of how to write a lexer, including a - discussion of folding.
- - How to implement a lexer in the container.
- - How to implement folding.
- The coding style used in Scintilla and SciTE is - worth following if you want to contribute code to Scintilla but is not compulsory.

- -

Introduction

- -

The Windows version of Scintilla is a Windows Control. As such, its primary programming - interface is through Windows messages. Early versions of Scintilla emulated much of the API - defined by the standard Windows Edit and RichEdit controls but those APIs are now deprecated in - favour of Scintilla's own, more consistent API. In addition to messages performing the actions - of a normal Edit control, Scintilla allows control of syntax styling, folding, markers, autocompletion - and call tips.

- -

The GTK+ version also uses messages in a similar way to the Windows version. This is - different to normal GTK+ practice but made it easier to implement rapidly.

- -

Scintilla does not properly support right-to-left languages like Arabic and Hebrew. - While text in these languages may appear correct, it is not possible to interact with this text - as is normal with other editing components.

- -

This documentation describes the individual messages and notifications used by Scintilla. It - does not describe how to link them together to form a useful editor. For now, the best way to - work out how to develop using Scintilla is to see how SciTE uses it. SciTE exercises most of - Scintilla's facilities.

- -

In the descriptions that follow, the messages are described as function calls with zero, one - or two arguments. These two arguments are the standard wParam and - lParam familiar to Windows programmers. These parameters are integers that - are large enough to hold pointers, and the return value is also an integer large enough to contain a - pointer. - Although the commands only use the - arguments described, because all messages have two arguments whether Scintilla uses them or - not, it is strongly recommended that any unused arguments are set to 0. This allows future - enhancement of messages without the risk of breaking existing code. Common argument types - are:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
boolArguments expect the values 0 for false and 1 for - true.
intArguments are 32-bit signed integers.
const char *Arguments point at text that is being passed to Scintilla but not modified. The text - may be zero terminated or another argument may specify the character count, the - description will make this clear.
char *Arguments point at text buffers that Scintilla will fill with text. In some cases, - another argument will tell Scintilla the buffer size. In others, you must make sure that - the buffer is big enough to hold the requested text. If a NULL pointer (0) is passed - then, for SCI_* calls, the length that should be allocated is returned.
colourColours are set using the RGB format (Red, Green, Blue). The intensity of each colour - is set in the range 0 to 255. If you have three such intensities, they are combined as: - red | (green << 8) | (blue << 16). If you set all intensities to 255, the - colour is white. If you set all intensities to 0, the colour is black. When you set a - colour, you are making a request. What you will get depends on the capabilities of the - system and the current screen mode.
alphaTranslucency is set using an alpha value. - Alpha ranges from 0 (SC_ALPHA_TRANSPARENT) which is completely transparent to - 255 (SC_ALPHA_OPAQUE) which is opaque. The value 256 (SC_ALPHA_NOALPHA) - is opaque and uses code that is not alpha-aware and may be faster. Not all platforms support - translucency and only some Scintilla features implement translucency. - The default alpha value for most features is SC_ALPHA_NOALPHA.
<unused>This is an unused argument. Setting it to 0 will ensure compatibility with future - enhancements.
- -

Contents

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
o Text retrieval and - modificationo Searching and replacingo Overtype
o Cut, copy and pasteo Error handlingo Undo and Redo
o Selection and informationo Multiple Selection and Virtual Spaceo Scrolling and automatic - scrolling
o White spaceo Cursoro Mouse capture
o Line endingso Stylingo Style definition
o Caret, selection, and hotspot styleso Marginso Annotations
o Other settingso Brace highlightingo Tabs and Indentation - Guides
o Markerso Indicatorso Autocompletion
o User listso Call tipso Keyboard commands
o Key bindingso Popup edit menuo Macro recording
o Printingo Direct accesso Multiple views
o Background loading and savingo Foldingo Line wrapping
o Zoomingo Long lineso Lexer
o Lexer objectso Notificationso Images
o GTK+o Deprecated messageso Edit messages never - supported by Scintilla
o Building Scintilla
- -

Messages with names of the form SCI_SETxxxxx often have a companion - SCI_GETxxxxx. To save tedious repetition, if the SCI_GETxxxxx message - returns the value set by the SCI_SETxxxxx message, the SET routine is - described and the GET routine is left to your imagination.

- -

Text retrieval and modification

- -

Each byte in a Scintilla document is followed by an associated byte of styling - information. The combination of a character byte and a style byte is called a cell. Style bytes - are interpreted an index into an array of styles. - Style bytes may be split into an index and a set of indicator bits - but this use is discouraged and indicators should now use - SCI_INDICATORFILLRANGE - and related calls. - The default split is with the index in the low 5 bits and 3 high bits as indicators. This allows 32 fundamental styles, which is enough for most - languages, and three independent indicators so that, for example, syntax errors, deprecated - names and bad indentation could all be displayed at once. The number of bits used for styles - can be altered with SCI_SETSTYLEBITS up to a maximum of 8 bits. - The remaining bits can be used for indicators.

- -

In this document, 'character' normally refers to a byte even when multi-byte characters are used. - Lengths measure the numbers of bytes, not the amount of characters in those bytes.

- -

Positions within the Scintilla document refer to a character or the gap before that - character. The first character in a document is 0, the second 1 and so on. If a document - contains nLen characters, the last character is numbered nLen-1. - The caret exists between character positions and can be located from before the first character (0) - to after the last character (nLen).

- -

There are places where the caret can not go where two character bytes make up one character. - This occurs when a DBCS character from a language like Japanese is included in the document or - when line ends are marked with the CP/M standard of a carriage return followed by a line feed. - The INVALID_POSITION constant (-1) represents an invalid position within the - document.

- -

All lines of text in Scintilla are the same height, and this height is calculated from the - largest font in any current style. This restriction is for performance; if lines differed in - height then calculations involving positioning of text would require the text to be styled - first.

- SCI_GETTEXT(int length, char *text)
- SCI_SETTEXT(<unused>, const char *text)
- SCI_SETSAVEPOINT
- SCI_GETLINE(int line, char *text)
- SCI_REPLACESEL(<unused>, const char - *text)
- SCI_SETREADONLY(bool readOnly)
- SCI_GETREADONLY
- SCI_GETTEXTRANGE(<unused>, Sci_TextRange - *tr)
- SCI_ALLOCATE(int bytes, <unused>)
- SCI_ADDTEXT(int length, const char *s)
- SCI_ADDSTYLEDTEXT(int length, cell *s)
- SCI_APPENDTEXT(int length, const char *s)
- SCI_INSERTTEXT(int pos, const char *text)
- SCI_CLEARALL
- SCI_CLEARDOCUMENTSTYLE
- SCI_GETCHARAT(int position)
- SCI_GETSTYLEAT(int position)
- SCI_GETSTYLEDTEXT(<unused>, Sci_TextRange - *tr)
- SCI_SETSTYLEBITS(int bits)
- SCI_GETSTYLEBITS
- SCI_TARGETASUTF8(<unused>, char *s)
- SCI_ENCODEDFROMUTF8(const char *utf8, char *encoded)
- SCI_SETLENGTHFORENCODE(int bytes)
-
- -

SCI_GETTEXT(int length, char *text)
- This returns length-1 characters of text from the start of the document plus one - terminating 0 character. To collect all the text in a document, use SCI_GETLENGTH - to get the number of characters in the document (nLen), allocate a character - buffer of length nLen+1 bytes, then call SCI_GETTEXT(nLen+1, char - *text). If the text argument is 0 then the length that should be allocated to store the - entire document is returned. - If you then save the text, you should use SCI_SETSAVEPOINT to mark - the text as unmodified.

- -

See also: SCI_GETSELTEXT, SCI_GETCURLINE, SCI_GETLINE, SCI_GETSTYLEDTEXT, SCI_GETTEXTRANGE

- -

SCI_SETTEXT(<unused>, const char *text)
- This replaces all the text in the document with the zero terminated text string you pass - in.

- -

SCI_SETSAVEPOINT
- This message tells Scintilla that the current state of the document is unmodified. This is - usually done when the file is saved or loaded, hence the name "save point". As Scintilla - performs undo and redo operations, it notifies the container that it has entered or left the - save point with SCN_SAVEPOINTREACHED and SCN_SAVEPOINTLEFT notification messages, allowing the container to know if the file - should be considered dirty or not.

- -

See also: SCI_EMPTYUNDOBUFFER, SCI_GETMODIFY

- -

SCI_GETLINE(int line, char *text)
- This fills the buffer defined by text with the contents of the nominated line (lines start at - 0). The buffer is not terminated by a 0 character. It is up to you to make sure that the buffer - is long enough for the text, use SCI_LINELENGTH(int line). The returned value is the - number of characters copied to the buffer. The returned text includes any end of line - characters. If you ask for a line number outside the range of lines in the document, 0 - characters are copied. If the text argument is 0 then the length that should be allocated - to store the entire line is returned.

- -

See also: SCI_GETCURLINE, SCI_GETSELTEXT, SCI_GETTEXTRANGE, SCI_GETSTYLEDTEXT, SCI_GETTEXT

- -

SCI_REPLACESEL(<unused>, const char *text)
- The currently selected text between the anchor - and the current position is replaced by the 0 terminated text string. If the anchor and - current position are the same, the text is inserted at the caret position. The caret is - positioned after the inserted text and the caret is scrolled into view.

- -

SCI_SETREADONLY(bool readOnly)
- SCI_GETREADONLY
- These messages set and get the read-only flag for the document. If you mark a document as read - only, attempts to modify the text cause the SCN_MODIFYATTEMPTRO notification.

- -

SCI_GETTEXTRANGE(<unused>, Sci_TextRange *tr)
- This collects the text between the positions cpMin and cpMax and - copies it to lpstrText (see struct Sci_TextRange in - Scintilla.h). If cpMax is -1, text is returned to the end of the - document. The text is 0 terminated, so you must supply a buffer that is at least 1 character - longer than the number of characters you wish to read. The return value is the length of the - returned text not including the terminating 0.

- -

See also: SCI_GETSELTEXT, SCI_GETLINE, SCI_GETCURLINE, SCI_GETSTYLEDTEXT, SCI_GETTEXT

- -

SCI_GETSTYLEDTEXT(<unused>, Sci_TextRange *tr)
- This collects styled text into a buffer using two bytes for each cell, with the character at - the lower address of each pair and the style byte at the upper address. Characters between the - positions cpMin and cpMax are copied to lpstrText (see - struct Sci_TextRange in Scintilla.h). Two 0 bytes are added to the end of - the text, so the buffer that lpstrText points at must be at least - 2*(cpMax-cpMin)+2 bytes long. No check is made for sensible values of - cpMin or cpMax. Positions outside the document return character codes - and style bytes of 0.

- -

See also: SCI_GETSELTEXT, SCI_GETLINE, SCI_GETCURLINE, SCI_GETTEXTRANGE, SCI_GETTEXT

- -

SCI_ALLOCATE(int bytes, <unused>)
- Allocate a document buffer large enough to store a given number of bytes. - The document will not be made smaller than its current contents.

- -

SCI_ADDTEXT(int length, const char *s)
- This inserts the first length characters from the string s - at the current position. This will include any 0's in the string that you might have expected - to stop the insert operation. The current position is set at the end of the inserted text, - but it is not scrolled into view.

- -

SCI_ADDSTYLEDTEXT(int length, cell *s)
- This behaves just like SCI_ADDTEXT, but inserts styled text.

- -

SCI_APPENDTEXT(int length, const char *s)
- This adds the first length characters from the string s to the end - of the document. This will include any 0's in the string that you might have expected to stop - the operation. The current selection is not changed and the new text is not scrolled into - view.

- -

SCI_INSERTTEXT(int pos, const char *text)
- This inserts the zero terminated text string at position pos or at - the current position if pos is -1. If the current position is after the insertion point - then it is moved along with its surrounding text but no scrolling is performed.

- -

SCI_CLEARALL
- Unless the document is read-only, this deletes all the text.

- -

SCI_CLEARDOCUMENTSTYLE
- When wanting to completely restyle the document, for example after choosing a lexer, the - SCI_CLEARDOCUMENTSTYLE can be used to clear all styling information and reset the - folding state.

- -

SCI_GETCHARAT(int pos)
- This returns the character at pos in the document or 0 if pos is - negative or past the end of the document.

- -

SCI_GETSTYLEAT(int pos)
- This returns the style at pos in the document, or 0 if pos is - negative or past the end of the document.

- -

SCI_SETSTYLEBITS(int bits)
- SCI_GETSTYLEBITS
- This pair of routines sets and reads back the number of bits in each cell to use for styling, - to a maximum of 8 style bits. The remaining bits can be used as indicators. The standard - setting is SCI_SETSTYLEBITS(5). - The number of styling bits needed by the current lexer can be found with - SCI_GETSTYLEBITSNEEDED.

- -

Sci_TextRange and Sci_CharacterRange
- These structures are defined to be exactly the same shape as the Win32 TEXTRANGE - and CHARRANGE, so that older code that treats Scintilla as a RichEdit will - work.

-
-struct Sci_CharacterRange {
-    long cpMin;
-    long cpMax;
-};
-
-struct Sci_TextRange {
-    struct Sci_CharacterRange chrg;
-    char *lpstrText;
-};
-
- -

GTK+-specific: Access to encoded text

- -

SCI_TARGETASUTF8(<unused>, char *s)
- This method retrieves the value of the target encoded as UTF-8 which is the default - encoding of GTK+ so is useful for retrieving text for use in other parts of the user interface, - such as find and replace dialogs. The length of the encoded text in bytes is returned. -

- -

SCI_ENCODEDFROMUTF8(const char *utf8, char *encoded)
- SCI_SETLENGTHFORENCODE(int bytes)
- SCI_ENCODEDFROMUTF8 converts a UTF-8 string into the document's - encoding which is useful for taking the results of a find dialog, for example, and receiving - a string of bytes that can be searched for in the document. Since the text can contain nul bytes, - the SCI_SETLENGTHFORENCODE method can be used to set the - length that will be converted. If set to -1, the length is determined by finding a nul byte. - The length of the converted string is returned. -

- - -

Searching

-

- There are methods to search for text and for regular expressions. The regular expression support - is limited and should only be used for simple cases and initial development. A different regular expression - library can be integrated into Scintilla - or can be called from the container using direct access to the buffer contents through - SCI_GETCHARACTERPOINTER. -

- SCI_FINDTEXT(int flags, Sci_TextToFind - *ttf)
- SCI_SEARCHANCHOR
- SCI_SEARCHNEXT(int searchFlags, const char - *text)
- SCI_SEARCHPREV(int searchFlags, const char - *text)
- Search and replace using the - target
-
- -

searchFlags
- Several of the search routines use flag options, which include a simple regular expression - search. Combine the flag options by adding them:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SCFIND_MATCHCASEA match only occurs with text that matches the case of the search string.
SCFIND_WHOLEWORDA match only occurs if the characters before and after are not word characters.
SCFIND_WORDSTARTA match only occurs if the character before is not a word character.
SCFIND_REGEXPThe search string should be interpreted as a regular expression.
SCFIND_POSIXTreat regular expression in a more POSIX compatible manner - by interpreting bare ( and ) for tagged sections rather than \( and \).
- -

You can - search backwards to find the previous occurrence of a search string by setting the end of the - search range before the start.

- -

In a regular expression, special characters interpreted are:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
.Matches any character
\(This marks the start of a region for tagging a match.
\)This marks the end of a tagged region.
\nWhere n is 1 through 9 refers to the first through ninth tagged region - when replacing. For example, if the search string was Fred\([1-9]\)XXX and - the replace string was Sam\1YYY, when applied to Fred2XXX this - would generate Sam2YYY.
\<This matches the start of a word using Scintilla's definitions of words.
\>This matches the end of a word using Scintilla's definition of words.
\xThis allows you to use a character x that would otherwise have a special meaning. For - example, \[ would be interpreted as [ and not as the start of a character set.
[...]This indicates a set of characters, for example, [abc] means any of the characters a, - b or c. You can also use ranges, for example [a-z] for any lower case character.
[^...]The complement of the characters in the set. For example, [^A-Za-z] means any - character except an alphabetic character.
^This matches the start of a line (unless used inside a set, see above).
$This matches the end of a line.
*This matches 0 or more times. For example, Sa*m matches Sm, - Sam, Saam, Saaam and so on.
+This matches 1 or more times. For example, Sa+m matches - Sam, Saam, Saaam and so on.
- -

Regular expressions will only match ranges within a single line, never matching over multiple lines.

- -

SCI_FINDTEXT(int searchFlags, Sci_TextToFind *ttf)
- This message searches for text in the document. It does not use or move the current selection. - The searchFlags argument controls the - search type, which includes regular expression searches.

- -

The Sci_TextToFind structure is defined in Scintilla.h; set - chrg.cpMin and chrg.cpMax with the range of positions in the document - to search. You can search backwards by - setting chrg.cpMax less than chrg.cpMin. - Set the lpstrText member of Sci_TextToFind to point at a zero terminated - text string holding the search pattern. If your language makes the use of Sci_TextToFind - difficult, you should consider using SCI_SEARCHINTARGET instead.

- -

The return value is -1 if the search fails or the position of the start of the found text if - it succeeds. The chrgText.cpMin and chrgText.cpMax members of - Sci_TextToFind are filled in with the start and end positions of the found text.

- -

See also: SCI_SEARCHINTARGET

- -

Sci_TextToFind
- This structure is defined to have exactly the same shape as the Win32 structure - FINDTEXTEX for old code that treated Scintilla as a RichEdit control.

-
-struct Sci_TextToFind {
-    struct Sci_CharacterRange chrg;     // range to search
-    char *lpstrText;                // the search pattern (zero terminated)
-    struct Sci_CharacterRange chrgText; // returned as position of matching text
-};
-
- -

SCI_SEARCHANCHOR
- SCI_SEARCHNEXT(int searchFlags, const char *text)
- SCI_SEARCHPREV(int searchFlags, const char *text)
- These messages provide relocatable search support. This allows multiple incremental - interactive searches to be macro recorded while still setting the selection to found text so - the find/select operation is self-contained. These three messages send SCN_MACRORECORD notifications if macro recording is enabled.

- -

SCI_SEARCHANCHOR sets the search start point used by - SCI_SEARCHNEXT and SCI_SEARCHPREV to the start of the current - selection, that is, the end of the selection that is nearer to the start of the document. You - should always call this before calling either of SCI_SEARCHNEXT or - SCI_SEARCHPREV.

- -

SCI_SEARCHNEXT and SCI_SEARCHPREV search for the next and previous - occurrence of the zero terminated search string pointed at by text. The search is modified by - the searchFlags.

- -

The return value is -1 if nothing is found, otherwise the return value is the start position - of the matching text. The selection is updated to show the matched text, but is not scrolled - into view.

- -

See also: SCI_SEARCHINTARGET, - SCI_FINDTEXT

- -

Search and replace using the target

- -

Using SCI_REPLACESEL, - modifications cause scrolling and other visible changes, which may take some time and cause - unwanted display updates. If performing many changes, such as a replace all command, the target - can be used instead. First, set the target, ie. the range to be replaced. Then call - SCI_REPLACETARGET or SCI_REPLACETARGETRE.

- -

Searching can be performed within the target range with SCI_SEARCHINTARGET, - which uses a counted string to allow searching for null characters. It returns the - position of the start of the matching text range or -1 for failure, in which case the target is not moved. The flags used by - SCI_SEARCHINTARGET such as SCFIND_MATCHCASE, - SCFIND_WHOLEWORD, SCFIND_WORDSTART, and SCFIND_REGEXP - can be set with SCI_SETSEARCHFLAGS. SCI_SEARCHINTARGET may be simpler - for some clients to use than SCI_FINDTEXT, as that requires using a pointer to a - structure.

- SCI_SETTARGETSTART(int pos)
- SCI_GETTARGETSTART
- SCI_SETTARGETEND(int pos)
- SCI_GETTARGETEND
- SCI_TARGETFROMSELECTION
- SCI_SETSEARCHFLAGS(int searchFlags)
- SCI_GETSEARCHFLAGS
- SCI_SEARCHINTARGET(int length, const char - *text)
- SCI_REPLACETARGET(int length, const char - *text)
- SCI_REPLACETARGETRE(int length, const char - *text)
- SCI_GETTAG(int tagNumber, char *tagValue)
-
- -

SCI_SETTARGETSTART(int pos)
- SCI_GETTARGETSTART
- SCI_SETTARGETEND(int pos)
- SCI_GETTARGETEND
- These functions set and return the start and end of the target. When searching in non-regular - expression mode, you can set start greater than end to find the last matching text in the - target rather than the first matching text. The target is also set by a successful - SCI_SEARCHINTARGET.

- -

SCI_TARGETFROMSELECTION
- Set the target start and end to the start and end positions of the selection.

- -

SCI_SETSEARCHFLAGS(int searchFlags)
- SCI_GETSEARCHFLAGS
- These get and set the searchFlags used by - SCI_SEARCHINTARGET. There are several option flags including a simple regular - expression search.

- -

SCI_SEARCHINTARGET(int length, const char *text)
- This searches for the first occurrence of a text string in the target defined by - SCI_SETTARGETSTART and SCI_SETTARGETEND. The text string is not zero - terminated; the size is set by length. The search is modified by the search flags - set by SCI_SETSEARCHFLAGS. If the search succeeds, the target is set to the found - text and the return value is the position of the start of the matching text. If the search - fails, the result is -1.

- -

SCI_REPLACETARGET(int length, const char *text)
- If length is -1, text is a zero terminated string, otherwise - length sets the number of character to replace the target with. - After replacement, the target range refers to the replacement text. - The return value - is the length of the replacement string.
- Note that the recommended way to delete text in the document is to set the target to the text to be removed, - and to perform a replace target with an empty string.

- -

SCI_REPLACETARGETRE(int length, const char *text)
- This replaces the target using regular expressions. If length is -1, - text is a zero terminated string, otherwise length is the number of - characters to use. The replacement string is formed from the text string with any sequences of - \1 through \9 replaced by tagged matches from the most recent regular - expression search. - After replacement, the target range refers to the replacement text. - The return value is the length of the replacement string.

- -

SCI_GETTAG(int tagNumber, char *tagValue)
- Discover what text was matched by tagged expressions in a regular expression search. - This is useful if the application wants to interpret the replacement string itself.

- -

See also: SCI_FINDTEXT

- -

Overtype

- -

SCI_SETOVERTYPE(bool overType)
- SCI_GETOVERTYPE
- When overtype is enabled, each typed character replaces the character to the right of the text - caret. When overtype is disabled, characters are inserted at the caret. - SCI_GETOVERTYPE returns TRUE (1) if overtyping is active, otherwise - FALSE (0) will be returned. Use SCI_SETOVERTYPE to set the overtype - mode.

- -

Cut, copy and paste

- - SCI_CUT
- SCI_COPY
- SCI_PASTE
- SCI_CLEAR
- SCI_CANPASTE
- SCI_COPYRANGE(int start, int end)
- SCI_COPYTEXT(int length, - const char *text)
- SCI_COPYALLOWLINE
- SCI_SETPASTECONVERTENDINGS(bool convert)
- SCI_GETPASTECONVERTENDINGS
-
- -

SCI_CUT
- SCI_COPY
- SCI_PASTE
- SCI_CLEAR
- SCI_CANPASTE
- SCI_COPYALLOWLINE
- These commands perform the standard tasks of cutting and copying data to the clipboard, - pasting from the clipboard into the document, and clearing the document. - SCI_CANPASTE returns non-zero if the document isn't read-only and if the selection - doesn't contain protected text. If you need a "can copy" or "can cut", use - SCI_GETSELECTIONSTART()-SCI_GETSELECTIONEND(), which will be non-zero if you can - copy or cut to the clipboard.

- -

GTK+ does not really support SCI_CANPASTE and always returns TRUE - unless the document is read-only.

- -

On X, the clipboard is asynchronous and may require several messages between - the destination and source applications. Data from SCI_PASTE will not arrive in the - document immediately.

- -

SCI_COPYALLOWLINE works the same as SCI_COPY except that if the - selection is empty then the current line is copied. On Windows, an extra "MSDEVLineSelect" marker - is added to the clipboard which is then used in SCI_PASTE to paste - the whole line before the current line.

- - SCI_COPYRANGE(int start, int end)
- SCI_COPYTEXT(int length, const char *text)
-

SCI_COPYRANGE copies a range of text from the document to - the system clipboard and SCI_COPYTEXT copies a supplied piece of - text to the system clipboard.

- -

SCI_SETPASTECONVERTENDINGS(bool convert)
- SCI_GETPASTECONVERTENDINGS
- If this property is set then when text is pasted any line ends are converted to match the document's - end of line mode as set with - SCI_SETEOLMODE. - Currently only changeable on Windows. On GTK+ pasted text is always converted.

- -

Error handling

- -

SCI_SETSTATUS(int status)
- SCI_GETSTATUS
- If an error occurs, Scintilla may set an internal error number that can be retrieved with - SCI_GETSTATUS. - To clear the error status call SCI_SETSTATUS(0). - The currently defined statuses are: -

- - - - - - - - - - - - - - - - - - - - - - -
SC_STATUS_OK0No failures
SC_STATUS_FAILURE1Generic failure
SC_STATUS_BADALLOC2Memory is exhausted
- -

Undo and Redo

- -

Scintilla has multiple level undo and redo. It will continue to collect undoable actions - until memory runs out. Scintilla saves actions that change the document. Scintilla does not - save caret and selection movements, view scrolling and the like. Sequences of typing or - deleting are compressed into single transactions to make it easier to undo and redo at a sensible - level of detail. Sequences of actions can be combined into transactions that are undone as a unit. - These sequences occur between SCI_BEGINUNDOACTION and - SCI_ENDUNDOACTION messages. These transactions can be nested and only the top-level - sequences are undone as units.

- SCI_UNDO
- SCI_CANUNDO
- SCI_EMPTYUNDOBUFFER
- SCI_REDO
- SCI_CANREDO
- SCI_SETUNDOCOLLECTION(bool - collectUndo)
- SCI_GETUNDOCOLLECTION
- SCI_BEGINUNDOACTION
- SCI_ENDUNDOACTION
- SCI_ADDUNDOACTION(int token, int flags)
-
- -

SCI_UNDO
- SCI_CANUNDO
- SCI_UNDO undoes one action, or if the undo buffer has reached a - SCI_ENDUNDOACTION point, all the actions back to the corresponding - SCI_BEGINUNDOACTION.

- -

SCI_CANUNDO returns 0 if there is nothing to undo, and 1 if there is. You would - typically use the result of this message to enable/disable the Edit menu Undo command.

- -

SCI_REDO
- SCI_CANREDO
- SCI_REDO undoes the effect of the last SCI_UNDO operation.

- -

SCI_CANREDO returns 0 if there is no action to redo and 1 if there are undo - actions to redo. You could typically use the result of this message to enable/disable the Edit - menu Redo command.

- -

SCI_EMPTYUNDOBUFFER
- This command tells Scintilla to forget any saved undo or redo history. It also sets the save - point to the start of the undo buffer, so the document will appear to be unmodified. This does - not cause the SCN_SAVEPOINTREACHED notification to be sent to the - container.

- -

See also: SCI_SETSAVEPOINT

- -

SCI_SETUNDOCOLLECTION(bool collectUndo)
- SCI_GETUNDOCOLLECTION
- You can control whether Scintilla collects undo information with - SCI_SETUNDOCOLLECTION. Pass in true (1) to collect information and - false (0) to stop collecting. If you stop collection, you should also use - SCI_EMPTYUNDOBUFFER to avoid the undo buffer being unsynchronized with the data in - the buffer.

- -

You might wish to turn off saving undo information if you use the Scintilla to store text - generated by a program (a Log view) or in a display window where text is often deleted and - regenerated.

- -

SCI_BEGINUNDOACTION
- SCI_ENDUNDOACTION
- Send these two messages to Scintilla to mark the beginning and end of a set of operations that - you want to undo all as one operation but that you have to generate as several operations. - Alternatively, you can use these to mark a set of operations that you do not want to have - combined with the preceding or following operations if they are undone.

- -

SCI_ADDUNDOACTION(int token, int flags)
- The container can add its own actions into the undo stack by calling - SCI_ADDUNDOACTION and an SCN_MODIFIED - notification will be sent to the container with the - SC_MOD_CONTAINER - flag when it is time to undo (SC_PERFORMED_UNDO) or - redo (SC_PERFORMED_REDO) the action. The token argument supplied is - returned in the token field of the notification.

-

For example, if the container wanted to allow undo and redo of a 'toggle bookmark' command then - it could call SCI_ADDUNDOACTION(line, 0) each time the command is performed. - Then when it receives a notification to undo or redo it toggles a bookmark on the line given by - the token field. If there are different types of commands or parameters that need to be stored into the undo - stack then the container should maintain a stack of its own for the document and use the current - position in that stack as the argument to SCI_ADDUNDOACTION(line). - SCI_ADDUNDOACTION commands are not combined together - into a single undo transaction unless grouped with SCI_BEGINUNDOACTION - and SCI_ENDUNDOACTION.

- -

The flags argument can be UNDO_MAY_COALESCE (1) if the container action may be - coalesced along with any insertion and deletion actions into a single compound action, otherwise 0. - Coalescing treats coalescible container actions as transparent so will still only group together insertions that - look like typing or deletions that look like multiple uses of the Backspace or Delete keys. -

-

Selection and information

- -

Scintilla maintains a selection that stretches between two points, the anchor and the - current position. If the anchor and the current position are the same, there is no selected - text. Positions in the document range from 0 (before the first character), to the document size - (after the last character). If you use messages, there is nothing to stop you setting a - position that is in the middle of a CRLF pair, or in the middle of a 2 byte character. However, - keyboard commands will not move the caret into such positions.

- SCI_GETTEXTLENGTH
- SCI_GETLENGTH
- SCI_GETLINECOUNT
- SCI_SETFIRSTVISIBLELINE(int lineDisplay)
- SCI_GETFIRSTVISIBLELINE
- SCI_LINESONSCREEN
- SCI_GETMODIFY
- SCI_SETSEL(int anchorPos, int currentPos)
- SCI_GOTOPOS(int position)
- SCI_GOTOLINE(int line)
- SCI_SETCURRENTPOS(int position)
- SCI_GETCURRENTPOS
- SCI_SETANCHOR(int position)
- SCI_GETANCHOR
- SCI_SETSELECTIONSTART(int position)
- SCI_GETSELECTIONSTART
- SCI_SETSELECTIONEND(int position)
- SCI_GETSELECTIONEND
- SCI_SETEMPTYSELECTION(int pos)
- SCI_SELECTALL
- SCI_LINEFROMPOSITION(int position)
- SCI_POSITIONFROMLINE(int line)
- SCI_GETLINEENDPOSITION(int line)
- SCI_LINELENGTH(int line)
- SCI_GETCOLUMN(int position)
- SCI_FINDCOLUMN(int line, int column)
- SCI_POSITIONFROMPOINT(int x, int y)
- SCI_POSITIONFROMPOINTCLOSE(int x, int - y)
- SCI_CHARPOSITIONFROMPOINT(int x, int y)
- SCI_CHARPOSITIONFROMPOINTCLOSE(int x, int - y)
- SCI_POINTXFROMPOSITION(<unused>, int - position)
- SCI_POINTYFROMPOSITION(<unused>, int - position)
- SCI_HIDESELECTION(bool hide)
- SCI_GETSELTEXT(<unused>, char *text)
- SCI_GETCURLINE(int textLen, char *text)
- SCI_SELECTIONISRECTANGLE
- SCI_SETSELECTIONMODE(int mode)
- SCI_GETSELECTIONMODE
- SCI_GETLINESELSTARTPOSITION(int line)
- SCI_GETLINESELENDPOSITION(int line)
- SCI_MOVECARETINSIDEVIEW
- SCI_WORDENDPOSITION(int position, bool - onlyWordCharacters)
- SCI_WORDSTARTPOSITION(int position, bool - onlyWordCharacters)
- SCI_POSITIONBEFORE(int position)
- SCI_POSITIONAFTER(int position)
- SCI_COUNTCHARACTERS(int startPos, int endPos)
- SCI_TEXTWIDTH(int styleNumber, const char *text)
- SCI_TEXTHEIGHT(int line)
- SCI_CHOOSECARETX
- SCI_MOVESELECTEDLINESUP
- SCI_MOVESELECTEDLINESDOWN
-
- -

SCI_GETTEXTLENGTH
- SCI_GETLENGTH
- Both these messages return the length of the document in bytes.

- -

SCI_GETLINECOUNT
- This returns the number of lines in the document. An empty document contains 1 line. A - document holding only an end of line sequence has 2 lines.

- -

SCI_SETFIRSTVISIBLELINE(int lineDisplay)
- SCI_GETFIRSTVISIBLELINE
- These messages retrieve and set the line number of the first visible line in the Scintilla view. The first line - in the document is numbered 0. The value is a visible line rather than a document line.

- -

SCI_LINESONSCREEN
- This returns the number of complete lines visible on the screen. With a constant line height, - this is the vertical space available divided by the line separation. Unless you arrange to size - your window to an integral number of lines, there may be a partial line visible at the bottom - of the view.

- -

SCI_GETMODIFY
- This returns non-zero if the document is modified and 0 if it is unmodified. The modified - status of a document is determined by the undo position relative to the save point. The save - point is set by SCI_SETSAVEPOINT, - usually when you have saved data to a file.

- -

If you need to be notified when the document becomes modified, Scintilla notifies the - container that it has entered or left the save point with the SCN_SAVEPOINTREACHED and SCN_SAVEPOINTLEFT notification messages.

- -

SCI_SETSEL(int anchorPos, int currentPos)
- This message sets both the anchor and the current position. If currentPos is - negative, it means the end of the document. If anchorPos is negative, it means - remove any selection (i.e. set the anchor to the same position as currentPos). The - caret is scrolled into view after this operation.

- -

SCI_GOTOPOS(int pos)
- This removes any selection, sets the caret at pos and scrolls the view to make - the caret visible, if necessary. It is equivalent to - SCI_SETSEL(pos, pos). The anchor position is set the same as the current - position.

- -

SCI_GOTOLINE(int line)
- This removes any selection and sets the caret at the start of line number line - and scrolls the view (if needed) to make it visible. The anchor position is set the same as the - current position. If line is outside the lines in the document (first line is 0), - the line set is the first or last.

- -

SCI_SETCURRENTPOS(int pos)
- This sets the current position and creates a selection between the anchor and the current - position. The caret is not scrolled into view.

- -

See also: SCI_SCROLLCARET

- -

SCI_GETCURRENTPOS
- This returns the current position.

- -

SCI_SETANCHOR(int pos)
- This sets the anchor position and creates a selection between the anchor position and the - current position. The caret is not scrolled into view.

- -

See also: SCI_SCROLLCARET

- -

SCI_GETANCHOR
- This returns the current anchor position.

- -

SCI_SETSELECTIONSTART(int pos)
- SCI_SETSELECTIONEND(int pos)
- These set the selection based on the assumption that the anchor position is less than the - current position. They do not make the caret visible. The table shows the positions of the - anchor and the current position after using these messages.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- anchorcurrent
SCI_SETSELECTIONSTARTposMax(pos, current)
SCI_SETSELECTIONENDMin(anchor, pos)pos
- -

See also: SCI_SCROLLCARET

- -

SCI_GETSELECTIONSTART
- SCI_GETSELECTIONEND
- These return the start and end of the selection without regard to which end is the current - position and which is the anchor. SCI_GETSELECTIONSTART returns the smaller of the - current position or the anchor position. SCI_GETSELECTIONEND returns the larger of - the two values.

- -

SCI_SETEMPTYSELECTION(int pos)
- This removes any selection and sets the caret at pos. The caret is not scrolled into view.

- -

SCI_SELECTALL
- This selects all the text in the document. The current position is not scrolled into view.

- -

SCI_LINEFROMPOSITION(int pos)
- This message returns the line that contains the position pos in the document. The - return value is 0 if pos <= 0. The return value is the last line if - pos is beyond the end of the document.

- -

SCI_POSITIONFROMLINE(int line)
- This returns the document position that corresponds with the start of the line. If - line is negative, the position of the line holding the start of the selection is - returned. If line is greater than the lines in the document, the return value is - -1. If line is equal to the number of lines in the document (i.e. 1 line past the - last line), the return value is the end of the document.

- -

SCI_GETLINEENDPOSITION(int line)
- This returns the position at the end of the line, before any line end characters. If line - is the last line in the document (which does not have any end of line characters), the result is the size of the - document. If line is negative or line >= SCI_GETLINECOUNT(), the result is undefined.

- -

SCI_LINELENGTH(int line)
- This returns the length of the line, including any line end characters. If line - is negative or beyond the last line in the document, the result is 0. If you want the length of - the line not including any end of line characters, use SCI_GETLINEENDPOSITION(line) - SCI_POSITIONFROMLINE(line).

- -

SCI_GETSELTEXT(<unused>, char *text)
- This copies the currently selected text and a terminating 0 byte to the text - buffer. The buffer size should be determined by calling with a NULL pointer for the text argument - SCI_GETSELTEXT(0,0). - This allows for rectangular and discontiguous selections as well as simple selections. - See Multiple Selection for information on - how multiple and rectangular selections and virtual space are copied.

- -

See also: SCI_GETCURLINE, - SCI_GETLINE, - SCI_GETTEXT, - SCI_GETSTYLEDTEXT, - SCI_GETTEXTRANGE -

- -

SCI_GETCURLINE(int textLen, char *text)
- This retrieves the text of the line containing the caret and returns the position within the - line of the caret. Pass in char* text pointing at a buffer large enough to hold - the text you wish to retrieve and a terminating 0 character. - Set textLen to the - length of the buffer which must be at least 1 to hold the terminating 0 character. - If the text argument is 0 then the length that should be allocated - to store the entire current line is returned.

- -

See also: SCI_GETSELTEXT, SCI_GETLINE, SCI_GETTEXT, SCI_GETSTYLEDTEXT, SCI_GETTEXTRANGE

- -

SCI_SELECTIONISRECTANGLE
- This returns 1 if the current selection is in rectangle mode, 0 if not.

- -

SCI_SETSELECTIONMODE(int mode)
- SCI_GETSELECTIONMODE
- The two functions set and get the selection mode, which can be - stream (SC_SEL_STREAM=0) or - rectangular (SC_SEL_RECTANGLE=1) or - by lines (SC_SEL_LINES=2) - or thin rectangular (SC_SEL_THIN=3). - When set in these modes, regular caret moves will extend or reduce the selection, - until the mode is cancelled by a call with same value or with SCI_CANCEL. - The get function returns the current mode even if the selection was made by mouse - or with regular extended moves. - SC_SEL_THIN is the mode after a rectangular selection has been typed into and ensures - that no characters are selected.

- -

SCI_GETLINESELSTARTPOSITION(int line)
- SCI_GETLINESELENDPOSITION(int line)
- Retrieve the position of the start and end of the selection at the given line with - INVALID_POSITION returned if no selection on this line.

- -

SCI_MOVECARETINSIDEVIEW
- If the caret is off the top or bottom of the view, it is moved to the nearest line that is - visible to its current position. Any selection is lost.

- -

SCI_WORDENDPOSITION(int position, bool - onlyWordCharacters)
- SCI_WORDSTARTPOSITION(int position, bool - onlyWordCharacters)
- These messages return the start and end of words using the same definition of words as used - internally within Scintilla. You can set your own list of characters that count as words with - SCI_SETWORDCHARS. The position - sets the start or the search, which is forwards when searching for the end and backwards when - searching for the start.

- -

Set onlyWordCharacters to true (1) to stop searching at the first - non-word character in the search direction. If onlyWordCharacters is - false (0), the first character in the search direction sets the type of the search - as word or non-word and the search stops at the first non-matching character. Searches are also - terminated by the start or end of the document.

- -

If "w" represents word characters and "." represents non-word characters and "|" represents - the position and true or false is the state of - onlyWordCharacters:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Initial stateend, trueend, falsestart, truestart, false
..ww..|..ww....ww..|..ww....ww....|ww....ww..|..ww....ww|....ww..
....ww|ww........wwww|........wwww|........|wwww........|wwww....
..ww|....ww....ww|....ww....ww....|ww....|ww....ww....|ww....ww..
..ww....|ww....ww....ww|....ww....ww|....ww....|ww....ww|....ww..
- -

SCI_POSITIONBEFORE(int position)
- SCI_POSITIONAFTER(int position)
- These messages return the position before and after another position - in the document taking into account the current code page. The minimum - position returned is 0 and the maximum is the last position in the document. - If called with a position within a multi byte character will return the position - of the start/end of that character.

- -

SCI_COUNTCHARACTERS(int startPos, int endPos)
- Returns the number of whole characters between two positions..

- -

SCI_TEXTWIDTH(int styleNumber, const char *text)
- This returns the pixel width of a string drawn in the given styleNumber which can - be used, for example, to decide how wide to make the line number margin in order to display a - given number of numerals.

- -

SCI_TEXTHEIGHT(int line)
- This returns the height in pixels of a particular line. Currently all lines are the same - height.

- -

SCI_GETCOLUMN(int pos)
- This message returns the column number of a position pos within the document - taking the width of tabs into account. This returns the column number of the last tab on the - line before pos, plus the number of characters between the last tab and - pos. If there are no tab characters on the line, the return value is the number of - characters up to the position on the line. In both cases, double byte characters count as a - single character. This is probably only useful with monospaced fonts.

- -

SCI_FINDCOLUMN(int line, int column)
- This message returns the position of a column on a line - taking the width of tabs into account. It treats a multi-byte character as a single column. - Column numbers, like lines start at 0.

- -

SCI_POSITIONFROMPOINT(int x, int y)
- SCI_POSITIONFROMPOINTCLOSE(int x, int y)
- SCI_POSITIONFROMPOINT finds the closest character position to a point and - SCI_POSITIONFROMPOINTCLOSE is similar but returns -1 if the point is outside the - window or not close to any characters.

- -

SCI_CHARPOSITIONFROMPOINT(int x, int y)
- SCI_CHARPOSITIONFROMPOINTCLOSE(int x, int y)
- SCI_CHARPOSITIONFROMPOINT finds the closest character to a point and - SCI_CHARPOSITIONFROMPOINTCLOSE is similar but returns -1 if the point is outside the - window or not close to any characters. This is similar to the previous methods but finds characters rather than - inter-character positions.

- -

SCI_POINTXFROMPOSITION(<unused>, int pos)
- SCI_POINTYFROMPOSITION(<unused>, int pos)
- These messages return the x and y display pixel location of text at position pos - in the document.

- -

SCI_HIDESELECTION(bool hide)
- The normal state is to make the selection visible by drawing it as set by SCI_SETSELFORE and SCI_SETSELBACK. However, if you hide the selection, it - is drawn as normal text.

- -

SCI_CHOOSECARETX
- Scintilla remembers the x value of the last position horizontally moved to explicitly by the - user and this value is then used when moving vertically such as by using the up and down keys. - This message sets the current x position of the caret as the remembered value.

- -

SCI_MOVESELECTEDLINESUP
- Move the selected lines up one line, shifting the line above after the selection. - The selection will be automatically extended to the beginning of the selection's first line and the end of the seletion's last line. - If nothing was selected, the line the cursor is currently at will be selected.

- -

SCI_MOVESELECTEDLINESDOWN
- Move the selected lines down one line, shifting the line below before the selection. - The selection will be automatically extended to the beginning of the selection's first line and the end of the seletion's last line. - If nothing was selected, the line the cursor is currently at will be selected.

- -

Multiple Selection and Virtual Space

- - - SCI_SETMULTIPLESELECTION(bool multipleSelection)
- SCI_GETMULTIPLESELECTION
- SCI_SETADDITIONALSELECTIONTYPING(bool additionalSelectionTyping)
- SCI_GETADDITIONALSELECTIONTYPING
- SCI_SETMULTIPASTE(int multiPaste)
- SCI_GETMULTIPASTE
- SCI_SETVIRTUALSPACEOPTIONS(int virtualSpaceOptions)
- SCI_GETVIRTUALSPACEOPTIONS
- SCI_SETRECTANGULARSELECTIONMODIFIER(int modifier)
- SCI_GETRECTANGULARSELECTIONMODIFIER
-
- - SCI_GETSELECTIONS
- SCI_CLEARSELECTIONS
- SCI_SETSELECTION(int caret, int anchor)
- SCI_ADDSELECTION(int caret, int anchor)
- SCI_SETMAINSELECTION(int selection)
- SCI_GETMAINSELECTION
-
- - SCI_SETSELECTIONNCARET(int selection, int pos)
- SCI_GETSELECTIONNCARET(int selection)
- SCI_SETSELECTIONNCARETVIRTUALSPACE(int selection, int space)
- SCI_GETSELECTIONNCARETVIRTUALSPACE(int selection)
- SCI_SETSELECTIONNANCHOR(int selection, int posAnchor)
- SCI_GETSELECTIONNANCHOR(int selection)
- SCI_SETSELECTIONNANCHORVIRTUALSPACE(int selection, int space)
- SCI_GETSELECTIONNANCHORVIRTUALSPACE(int selection)
- SCI_SETSELECTIONNSTART(int selection, int pos)
- SCI_GETSELECTIONNSTART(int selection)
- SCI_SETSELECTIONNEND(int selection, int pos)
- SCI_GETSELECTIONNEND(int selection)
-
- - SCI_SETRECTANGULARSELECTIONCARET(int pos)
- SCI_GETRECTANGULARSELECTIONCARET
- SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE(int space)
- SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE
- SCI_SETRECTANGULARSELECTIONANCHOR(int posAnchor)
- SCI_GETRECTANGULARSELECTIONANCHOR
- SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE(int space)
- SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE
-
- - SCI_SETADDITIONALSELALPHA(int alpha)
- SCI_GETADDITIONALSELALPHA
- SCI_SETADDITIONALSELFORE(int colour)
- SCI_SETADDITIONALSELBACK(int colour)
- SCI_SETADDITIONALCARETFORE(int colour)
- SCI_GETADDITIONALCARETFORE
- SCI_SETADDITIONALCARETSBLINK(bool additionalCaretsBlink)
- SCI_GETADDITIONALCARETSBLINK
- SCI_SETADDITIONALCARETSVISIBLE(bool additionalCaretsVisible)
- SCI_GETADDITIONALCARETSVISIBLE
-
- - SCI_SWAPMAINANCHORCARET
- SCI_ROTATESELECTION
-
- -

- There may be multiple selections active at one time. - More selections are made by holding down the Ctrl key while dragging with the mouse. - The most recent selection is the main selection and determines which part of the document is shown automatically. - Any selection apart from the main selection is called an additional selection. - The calls in the previous section operate on the main selection. - There is always at least one selection. -

- -

- Rectangular selections are handled as multiple selections although the original rectangular range is remembered so that - subsequent operations may be handled differently for rectangular selections. For example, pasting a rectangular selection - places each piece in a vertical column. -

- -

- Virtual space is space beyond the end of each line. The caret may be moved into virtual space but no real space will be - added to the document until there is some text typed or some other text insertion command is used. -

- -

When discontiguous selections are copied to the clipboard, each selection is added to the clipboard text - in order with no delimiting characters. - For rectangular selections the document's line end is added after each line's text. Rectangular selections - are always copied from top line to bottom, not in the in order of selection.Virtual space is not copied.

- -

- SCI_SETMULTIPLESELECTION(bool multipleSelection)
- SCI_GETMULTIPLESELECTION
- Enable or disable multiple selection. When multiple selection is disabled, it is not possible to select - multiple ranges by holding down the Ctrl key while dragging with the mouse.

- -

- SCI_SETADDITIONALSELECTIONTYPING(bool additionalSelectionTyping)
- SCI_GETADDITIONALSELECTIONTYPING
- Whether typing, backspace, or delete works with multiple selections simultaneously.

- -

- SCI_SETMULTIPASTE(int multiPaste)
- SCI_GETMULTIPASTE
- When pasting into multiple selections, the pasted text can go into just the main selection with SC_MULTIPASTE_ONCE=0 - or into each selection with SC_MULTIPASTE_EACH=1. SC_MULTIPASTE_ONCE is the default.

- -

- SCI_SETVIRTUALSPACEOPTIONS(int virtualSpace)
- SCI_GETVIRTUALSPACEOPTIONS
- Virtual space can be enabled or disabled for rectangular selections or in other circumstances or in both. - There are two bit flags SCVS_RECTANGULARSELECTION=1 and - SCVS_USERACCESSIBLE=2 which can be set independently. - SCVS_NONE=0, the default, disables all use of virtual space.

- -

- SCI_SETRECTANGULARSELECTIONMODIFIER(int modifier)
- SCI_GETRECTANGULARSELECTIONMODIFIER
- On GTK+, the key used to indicate that a rectangular selection should be created when combined with a mouse drag can be set. - The three possible values are SCMOD_CTRL=2 (default), SCMOD_ALT=4 or SCMOD_SUPER=8. - Since SCMOD_ALT is often already used by a window manager, the window manager may need configuring to allow this choice. - SCMOD_SUPER is often a system dependent modifier key such as the Left Windows key on a Windows keyboard or the - Command key on a Mac.

- -

- SCI_GETSELECTIONS
- Return the number of selections currently active.

- -

- SCI_CLEARSELECTIONS
- Set a single empty selection at 0 as the only selection.

- -

- SCI_SETSELECTION(int caret, int anchor)
- Set a single selection from anchor to caret as the only selection.

- -

- SCI_ADDSELECTION(int caret, int anchor)
- Add a new selection from anchor to caret as the main selection retaining all other - selections as additional selections. - Since there is always at least one selection, to set a list of selections, the first selection should be - added with SCI_SETSELECTION and later selections added with SCI_ADDSELECTION

- -

- SCI_SETMAINSELECTION(int selection)
- SCI_GETMAINSELECTION
- One of the selections is the main selection which is used to determine what range of text is automatically visible. - The main selection may be displayed in different colours or with a differently styled caret. - Only an already existing selection can be made main.

- -

- SCI_SETSELECTIONNCARET(int selection, int pos)
- SCI_GETSELECTIONNCARET(int selection)
- SCI_SETSELECTIONNCARETVIRTUALSPACE(int selection, int space)
- SCI_GETSELECTIONNCARETVIRTUALSPACE(int selection)
- SCI_SETSELECTIONNANCHOR(int selection, int posAnchor)
- SCI_GETSELECTIONNANCHOR(int selection)
- SCI_SETSELECTIONNANCHORVIRTUALSPACE(int selection, int space)
- SCI_GETSELECTIONNANCHORVIRTUALSPACE(int selection)
- Set or query the position and amount of virtual space for the caret and anchor of each already existing selection.

- -

- SCI_SETSELECTIONNSTART(int selection, int pos)
- SCI_GETSELECTIONNSTART(int selection)
- SCI_SETSELECTIONNEND(int selection, int pos)
- SCI_GETSELECTIONNEND(int selection)
- Set or query the start and end position of each already existing selection. - Mostly of use to query each range for its text.

- -

- SCI_SETRECTANGULARSELECTIONCARET(int pos)
- SCI_GETRECTANGULARSELECTIONCARET
- SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE(int space)
- SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE
- SCI_SETRECTANGULARSELECTIONANCHOR(int posAnchor)
- SCI_GETRECTANGULARSELECTIONANCHOR
- SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE(int space)
- SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE
- Set or query the position and amount of virtual space for the caret and anchor of the rectangular selection. - After setting the rectangular selection, this is broken down into multiple selections, one for each line.

- -

- SCI_SETADDITIONALSELALPHA(int alpha)
- SCI_GETADDITIONALSELALPHA
- SCI_SETADDITIONALSELFORE(int colour)
- SCI_SETADDITIONALSELBACK(int colour)
- Modify the appearence of additional selections so that they can be differentiated from the main selection which has its appearence set with - SCI_SETSELALPHA, - SCI_GETSELALPHA, - SCI_SETSELFORE, and - SCI_SETSELBACK.

- -

- SCI_SETADDITIONALCARETFORE(int colour)
- SCI_GETADDITIONALCARETFORE
- SCI_SETADDITIONALCARETSBLINK(bool additionalCaretsBlink)
- SCI_GETADDITIONALCARETSBLINK
- Modify the appearence of additional carets so that they can be differentiated from the main caret which has its appearence set with - SCI_SETCARETFORE, - SCI_GETCARETFORE, - SCI_SETCARETPERIOD, and - SCI_GETCARETPERIOD.

- -

- SCI_SETADDITIONALCARETSVISIBLE(bool additionalCaretsVisible)
- SCI_GETADDITIONALCARETSVISIBLE
- Determine whether to show additional carets (defaults to true).

- -

- SCI_SWAPMAINANCHORCARET
- SCI_ROTATESELECTION
- These commands may be assigned to keys to make it possible to manipulate multiple selections. - SCI_SWAPMAINANCHORCARET moves the caret to the opposite end of the main selection. - SCI_ROTATESELECTION makes the next selection be the main selection. -

- -

Scrolling and automatic scrolling

- SCI_LINESCROLL(int column, int line)
- SCI_SCROLLCARET
- SCI_SETXCARETPOLICY(int caretPolicy, int - caretSlop)
- SCI_SETYCARETPOLICY(int caretPolicy, int - caretSlop)
- SCI_SETVISIBLEPOLICY(int caretPolicy, int - caretSlop)
- SCI_SETHSCROLLBAR(bool visible)
- SCI_GETHSCROLLBAR
- SCI_SETVSCROLLBAR(bool visible)
- SCI_GETVSCROLLBAR
- SCI_GETXOFFSET
- SCI_SETXOFFSET(int xOffset)
- SCI_SETSCROLLWIDTH(int pixelWidth)
- SCI_GETSCROLLWIDTH
- SCI_SETSCROLLWIDTHTRACKING(bool tracking)
- SCI_GETSCROLLWIDTHTRACKING
- SCI_SETENDATLASTLINE(bool - endAtLastLine)
- SCI_GETENDATLASTLINE
-
- -

SCI_LINESCROLL(int column, int line)
- This will attempt to scroll the display by the number of columns and lines that you specify. - Positive line values increase the line number at the top of the screen (i.e. they move the text - upwards as far as the user is concerned), Negative line values do the reverse.

- -

The column measure is the width of a space in the default style. Positive values increase - the column at the left edge of the view (i.e. they move the text leftwards as far as the user - is concerned). Negative values do the reverse.

- -

See also: SCI_SETXOFFSET

- -

SCI_SCROLLCARET
- If the current position (this is the caret if there is no selection) is not visible, the view - is scrolled to make it visible according to the current caret policy.

- -

SCI_SETXCARETPOLICY(int caretPolicy, int caretSlop)
- SCI_SETYCARETPOLICY(int caretPolicy, int caretSlop)
- These set the caret policy. The value of caretPolicy is a combination of - CARET_SLOP, CARET_STRICT, CARET_JUMPS and - CARET_EVEN.

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
CARET_SLOPIf set, we can define a slop value: caretSlop. This value defines an - unwanted zone (UZ) where the caret is... unwanted. This zone is defined as a number of - pixels near the vertical margins, and as a number of lines near the horizontal margins. - By keeping the caret away from the edges, it is seen within its context. This makes it - likely that the identifier that the caret is on can be completely seen, and that the - current line is seen with some of the lines following it, which are often dependent on - that line.
CARET_STRICTIf set, the policy set by CARET_SLOP is enforced... strictly. The caret - is centred on the display if caretSlop is not set, and cannot go in the UZ - if caretSlop is set.
CARET_JUMPSIf set, the display is moved more energetically so the caret can move in the same - direction longer before the policy is applied again. '3UZ' notation is used to indicate - three time the size of the UZ as a distance to the margin.
CARET_EVENIf not set, instead of having symmetrical UZs, the left and bottom UZs are extended - up to right and top UZs respectively. This way, we favour the displaying of useful - information: the beginning of lines, where most code reside, and the lines after the - caret, for example, the body of a function.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
slopstrictjumpsevenCaret can go to the marginOn reaching limit (going out of visibility
- or going into the UZ) display is...
0000Yesmoved to put caret on top/on right
0001Yesmoved by one position
0010Yesmoved to put caret on top/on right
0011Yescentred on the caret
01-0Caret is always on top/on right of display-
01-1No, caret is always centred-
1000Yesmoved to put caret out of the asymmetrical UZ
1001Yesmoved to put caret out of the UZ
1010Yesmoved to put caret at 3UZ of the top or right margin
1011Yesmoved to put caret at 3UZ of the margin
11-0Caret is always at UZ of top/right margin-
1101No, kept out of UZmoved by one position
1110No, kept out of UZmoved to put caret at 3UZ of the margin
- -

SCI_SETVISIBLEPOLICY(int caretPolicy, int caretSlop)
- This determines how the vertical positioning is determined when SCI_ENSUREVISIBLEENFORCEPOLICY is - called. It takes VISIBLE_SLOP and VISIBLE_STRICT flags for the policy - parameter. It is similar in operation to SCI_SETYCARETPOLICY(int caretPolicy, int - caretSlop).

- -

SCI_SETHSCROLLBAR(bool visible)
- SCI_GETHSCROLLBAR
- The horizontal scroll bar is only displayed if it is needed for the assumed width. - If you never wish to see it, call - SCI_SETHSCROLLBAR(0). Use SCI_SETHSCROLLBAR(1) to enable it again. - SCI_GETHSCROLLBAR returns the current state. The default state is to display it - when needed.

-

See also: SCI_SETSCROLLWIDTH.

- -

SCI_SETVSCROLLBAR(bool visible)
- SCI_GETVSCROLLBAR
- By default, the vertical scroll bar is always displayed when required. You can choose to hide - or show it with SCI_SETVSCROLLBAR and get the current state with - SCI_GETVSCROLLBAR.

- -

SCI_SETXOFFSET(int xOffset)
- SCI_GETXOFFSET
- The xOffset is the horizontal scroll position in pixels of the start of the text - view. A value of 0 is the normal position with the first text column visible at the left of the - view.

- -

See also: SCI_LINESCROLL

- -

SCI_SETSCROLLWIDTH(int pixelWidth)
- SCI_GETSCROLLWIDTH
- For performance, Scintilla does not measure the display width of the document to determine - the properties of the horizontal scroll bar. Instead, an assumed width is used. - These messages set and get the document width in pixels assumed by Scintilla. - The default value is 2000. - To ensure the width of the currently visible lines can be scrolled use - SCI_SETSCROLLWIDTHTRACKING

- -

SCI_SETSCROLLWIDTHTRACKING(bool tracking)
- SCI_GETSCROLLWIDTHTRACKING
- If scroll width tracking is enabled then the scroll width is adjusted to ensure that all of the lines currently - displayed can be completely scrolled. This mode never adjusts the scroll width to be narrower.

- -

SCI_SETENDATLASTLINE(bool endAtLastLine)
- SCI_GETENDATLASTLINE
- SCI_SETENDATLASTLINE sets the scroll range so that maximum scroll position has - the last line at the bottom of the view (default). Setting this to false allows - scrolling one page below the last line.

- -

White space

- SCI_SETVIEWWS(int wsMode)
- SCI_GETVIEWWS
- SCI_SETWHITESPACEFORE(bool - useWhitespaceForeColour, int colour)
- SCI_SETWHITESPACEBACK(bool - useWhitespaceBackColour, int colour)
- SCI_SETWHITESPACESIZE(int - size)
- SCI_GETWHITESPACESIZE
- SCI_SETEXTRAASCENT(int extraAscent)
- SCI_GETEXTRAASCENT
- SCI_SETEXTRADESCENT(int extraDescent)
- SCI_GETEXTRADESCENT
-
- -

SCI_SETVIEWWS(int wsMode)
- SCI_GETVIEWWS
- White space can be made visible which may be useful for languages in which white space is - significant, such as Python. Space characters appear as small centred dots and tab characters - as light arrows pointing to the right. There are also ways to control the display of end of line characters. The two messages set and get the - white space display mode. The wsMode argument can be one of:

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
SCWS_INVISIBLE0The normal display mode with white space displayed as an empty background - colour.
SCWS_VISIBLEALWAYS1White space characters are drawn as dots and arrows,
SCWS_VISIBLEAFTERINDENT2White space used for indentation is displayed normally but after the first visible - character, it is shown as dots and arrows.
- -

The effect of using any other wsMode value is undefined.

- -

SCI_SETWHITESPACEFORE(bool useWhitespaceForeColour, int colour)
- SCI_SETWHITESPACEBACK(bool useWhitespaceBackColour, int colour)
- By default, the colour of visible white space is determined by the lexer in use. The - foreground and/or background colour of all visible white space can be set globally, overriding - the lexer's colours with SCI_SETWHITESPACEFORE and - SCI_SETWHITESPACEBACK.

- -

SCI_SETWHITESPACESIZE(int size)
- SCI_GETWHITESPACESIZE
- SCI_SETWHITESPACESIZE sets the size of the dots used for mark space characters. - The SCI_GETWHITESPACESIZE message retrieves the current size. -

- -

- SCI_SETEXTRAASCENT(int extraAscent)
- SCI_GETEXTRAASCENT
- SCI_SETEXTRADESCENT(int extraDescent)
- SCI_GETEXTRADESCENT
- Text is drawn with the base of each character on a 'baseline'. The height of a line is found from the maximum - that any style extends above the baseline (its 'ascent'), added to the maximum that any style extends below the - baseline (its 'descent'). - Space may be added to the maximum ascent (SCI_SETEXTRAASCENT) and the - maximum descent (SCI_SETEXTRADESCENT) to allow for more space between lines. - This may done to make the text easier to read or to accomodate underlines or highlights. -

- -

Cursor

- -

SCI_SETCURSOR(int curType)
- SCI_GETCURSOR
- The cursor is normally chosen in a context sensitive way, so it will be different over the - margin than when over the text. When performing a slow action, you may wish to change to a wait - cursor. You set the cursor type with SCI_SETCURSOR. The curType - argument can be:

- - - - - - - - - - - - - - - - - - - -
SC_CURSORNORMAL-1The normal cursor is displayed.
SC_CURSORWAIT 4The wait cursor is displayed when the mouse is over or owned by the Scintilla - window.
- -

Cursor values 1 through 7 have defined cursors, but only SC_CURSORWAIT is - usefully controllable. Other values of curType cause a pointer to be displayed. - The SCI_GETCURSOR message returns the last cursor type you set, or - SC_CURSORNORMAL (-1) if you have not set a cursor type.

- -

Mouse capture

- -

SCI_SETMOUSEDOWNCAPTURES(bool captures)
- SCI_GETMOUSEDOWNCAPTURES
- When the mouse is pressed inside Scintilla, it is captured so future mouse movement events are - sent to Scintilla. This behavior may be turned off with - SCI_SETMOUSEDOWNCAPTURES(0).

- -

Line endings

- -

Scintilla can interpret any of the three major line end conventions, Macintosh (\r), Unix - (\n) and CP/M / DOS / Windows (\r\n). When the user presses the Enter key, one of these line - end strings is inserted into the buffer. The default is \r\n in Windows and \n in Unix, but - this can be changed with the SCI_SETEOLMODE message. You can also convert the - entire document to one of these line endings with SCI_CONVERTEOLS. Finally, you - can choose to display the line endings with SCI_SETVIEWEOL.

- SCI_SETEOLMODE(int eolMode)
- SCI_GETEOLMODE
- SCI_CONVERTEOLS(int eolMode)
- SCI_SETVIEWEOL(bool visible)
- SCI_GETVIEWEOL
-
- -

SCI_SETEOLMODE(int eolMode)
- SCI_GETEOLMODE
- SCI_SETEOLMODE sets the characters that are added into the document when the user - presses the Enter key. You can set eolMode to one of SC_EOL_CRLF (0), - SC_EOL_CR (1), or SC_EOL_LF (2). The SCI_GETEOLMODE - message retrieves the current state.

- -

SCI_CONVERTEOLS(int eolMode)
- This message changes all the end of line characters in the document to match - eolMode. Valid values are: SC_EOL_CRLF (0), SC_EOL_CR - (1), or SC_EOL_LF (2).

- -

SCI_SETVIEWEOL(bool visible)
- SCI_GETVIEWEOL
- Normally, the end of line characters are hidden, but SCI_SETVIEWEOL allows you to - display (or hide) them by setting visible true (or - false). The visible rendering of the end of line characters is similar to - (CR), (LF), or (CR)(LF). SCI_GETVIEWEOL - returns the current state.

- -

Styling

- -

The styling messages allow you to assign styles to text. The standard Scintilla settings - divide the 8 style bits available for each character into 5 bits (0 to 4 = styles 0 to 31) that set a style and three bits (5 to 7) that - define indicators. You can change the balance between - styles and indicators with SCI_SETSTYLEBITS. If your styling needs can be met by - one of the standard lexers, or if you can write your own, then a lexer is probably the easiest - way to style your document. If you choose to use the container to do the styling you can use - the SCI_SETLEXER command to select - SCLEX_CONTAINER, in which case the container is sent a SCN_STYLENEEDED notification each time text needs styling for display. As another - alternative, you might use idle time to style the document. Even if you use a lexer, you might - use the styling commands to mark errors detected by a compiler. The following commands can be - used.

- SCI_GETENDSTYLED
- SCI_STARTSTYLING(int position, int mask)
- SCI_SETSTYLING(int length, int style)
- SCI_SETSTYLINGEX(int length, const char - *styles)
- SCI_SETLINESTATE(int line, int value)
- SCI_GETLINESTATE(int line)
- SCI_GETMAXLINESTATE
-
- -

SCI_GETENDSTYLED
- Scintilla keeps a record of the last character that is likely to be styled correctly. This is - moved forwards when characters after it are styled and moved backwards if changes are made to - the text of the document before it. Before drawing text, this position is checked to see if any - styling is needed and, if so, a SCN_STYLENEEDED notification message is sent to the - container. The container can send SCI_GETENDSTYLED to work out where it needs to - start styling. Scintilla will always ask to style whole lines.

- -

SCI_STARTSTYLING(int pos, int mask)
- This prepares for styling by setting the styling position pos to start at and a - mask indicating which bits of the style bytes can be set. The mask allows styling - to occur over several passes, with, for example, basic styling done on an initial pass to - ensure that the text of the code is seen quickly and correctly, and then a second slower pass, - detecting syntax errors and using indicators to show where these are. For example, with the - standard settings of 5 style bits and 3 indicator bits, you would use a mask value - of 31 (0x1f) if you were setting text styles and did not want to change the indicators. After - SCI_STARTSTYLING, send multiple SCI_SETSTYLING messages for each - lexical entity to style.

- -

SCI_SETSTYLING(int length, int style)
- This message sets the style of length characters starting at the styling position - and then increases the styling position by length, ready for the next call. If - sCell is the style byte, the operation is:
- if ((sCell & mask) != style) sCell = (sCell & ~mask) | (style & - mask);
-

- -

SCI_SETSTYLINGEX(int length, const char *styles)
- As an alternative to SCI_SETSTYLING, which applies the same style to each byte, - you can use this message which specifies the styles for each of length bytes from - the styling position and then increases the styling position by length, ready for - the next call. The length styling bytes pointed at by styles should - not contain any bits not set in mask.

- -

SCI_SETLINESTATE(int line, int value)
- SCI_GETLINESTATE(int line)
- As well as the 8 bits of lexical state stored for each character there is also an integer - stored for each line. This can be used for longer lived parse states such as what the current - scripting language is in an ASP page. Use SCI_SETLINESTATE to set the integer - value and SCI_GETLINESTATE to get the value. - Changing the value produces a SC_MOD_CHANGELINESTATE notification. -

- -

SCI_GETMAXLINESTATE
- This returns the last line that has any line state.

- -

Style definition

- -

While the style setting messages mentioned above change the style numbers associated with - text, these messages define how those style numbers are interpreted visually. There are 256 - lexer styles that can be set, numbered 0 to STYLE_MAX (255). Unless you use SCI_SETSTYLEBITS to change the number - of style bits, styles 0 to 31 are used to set the text attributes. There are also some - predefined numbered styles starting at 32, The following STYLE_* constants are - defined.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
STYLE_DEFAULT32This style defines the attributes that all styles receive when the - SCI_STYLECLEARALL message is used.
STYLE_LINENUMBER33This style sets the attributes of the text used to display line numbers in a line - number margin. The background colour set for this style also sets the background colour - for all margins that do not have any folding mask bits set. That is, any margin for which - mask & SC_MASK_FOLDERS is 0. See SCI_SETMARGINMASKN for more about masks.
STYLE_BRACELIGHT34This style sets the attributes used when highlighting braces with the SCI_BRACEHIGHLIGHT message and - when highlighting the corresponding indentation with SCI_SETHIGHLIGHTGUIDE.
STYLE_BRACEBAD35This style sets the display attributes used when marking an unmatched brace with the - SCI_BRACEBADLIGHT - message.
STYLE_CONTROLCHAR36This style sets the font used when drawing control characters. - Only the font, size, bold, italics, and character set attributes are used and not - the colour attributes. See - also: SCI_SETCONTROLCHARSYMBOL.
STYLE_INDENTGUIDE37This style sets the foreground and background colours used when drawing the - indentation guides.
STYLE_CALLTIP38 Call tips normally use the font attributes defined by STYLE_DEFAULT. - Use of SCI_CALLTIPUSESTYLE - causes call tips to use this style instead. Only the font face name, font size, - foreground and background colours and character set attributes are used.
STYLE_LASTPREDEFINED39To make it easier for client code to discover the range of styles that are - predefined, this is set to the style number of the last predefined style. This is - currently set to 39 and the last style with an identifier is 38, which reserves space - for one future predefined style.
STYLE_MAX255This is not a style but is the number of the maximum style that can be set. Styles - between STYLE_LASTPREDEFINED and STYLE_MAX would be appropriate - if you used SCI_SETSTYLEBITS - to set more than 5 style bits.
- -

For each style you can set the font name, size and use of bold, italic and underline, - foreground and background colour and the character set. You can also choose to hide text with a - given style, display all characters as upper or lower case and fill from the last character on - a line to the end of the line (for embedded languages). There is also an experimental attribute - to make text read-only.

- -

It is entirely up to you how you use styles. If you want to use syntax colouring you might - use style 0 for white space, style 1 for numbers, style 2 for keywords, style 3 for strings, - style 4 for preprocessor, style 5 for operators, and so on.

- SCI_STYLERESETDEFAULT
- SCI_STYLECLEARALL
- SCI_STYLESETFONT(int styleNumber, char - *fontName)
- SCI_STYLEGETFONT(int styleNumber, char *fontName)
- SCI_STYLESETSIZE(int styleNumber, int - sizeInPoints)
- SCI_STYLEGETSIZE(int styleNumber)
- SCI_STYLESETSIZEFRACTIONAL(int styleNumber, int - sizeInHundredthPoints)
- SCI_STYLEGETSIZEFRACTIONAL(int styleNumber)
- SCI_STYLESETBOLD(int styleNumber, bool - bold)
- SCI_STYLEGETBOLD(int styleNumber)
- SCI_STYLESETWEIGHT(int styleNumber, int - weight)
- SCI_STYLEGETWEIGHT(int styleNumber)
- SCI_STYLESETITALIC(int styleNumber, bool - italic)
- SCI_STYLEGETITALIC(int styleNumber)
- SCI_STYLESETUNDERLINE(int styleNumber, bool - underline)
- SCI_STYLEGETUNDERLINE(int styleNumber)
- SCI_STYLESETFORE(int styleNumber, int - colour)
- SCI_STYLEGETFORE(int styleNumber)
- SCI_STYLESETBACK(int styleNumber, int - colour)
- SCI_STYLEGETBACK(int styleNumber)
- SCI_STYLESETEOLFILLED(int styleNumber, bool - eolFilled)
- SCI_STYLEGETEOLFILLED(int styleNumber)
- SCI_STYLESETCHARACTERSET(int styleNumber, - int charSet)
- SCI_STYLEGETCHARACTERSET(int styleNumber)
- SCI_STYLESETCASE(int styleNumber, int - caseMode)
- SCI_STYLEGETCASE(int styleNumber)
- SCI_STYLESETVISIBLE(int styleNumber, bool - visible)
- SCI_STYLEGETVISIBLE(int styleNumber)
- SCI_STYLESETCHANGEABLE(int styleNumber, bool - changeable)
- SCI_STYLEGETCHANGEABLE(int styleNumber)
- SCI_STYLESETHOTSPOT(int styleNumber, bool - hotspot)
- SCI_STYLEGETHOTSPOT(int styleNumber)
-
- -

SCI_STYLERESETDEFAULT
- This message resets STYLE_DEFAULT to its state when Scintilla was - initialised.

- -

SCI_STYLECLEARALL
- This message sets all styles to have the same attributes as STYLE_DEFAULT. If you - are setting up Scintilla for syntax colouring, it is likely that the lexical styles you set - will be very similar. One way to set the styles is to:
- 1. Set STYLE_DEFAULT to the common features of all styles.
- 2. Use SCI_STYLECLEARALL to copy this to all styles.
- 3. Set the style attributes that make your lexical styles different.

- -

SCI_STYLESETFONT(int styleNumber, const char *fontName)
- SCI_STYLEGETFONT(int styleNumber, char *fontName)
- SCI_STYLESETSIZE(int styleNumber, int sizeInPoints)
- SCI_STYLEGETSIZE(int styleNumber)
- SCI_STYLESETSIZEFRACTIONAL(int styleNumber, int sizeInHundredthPoints)
- SCI_STYLEGETSIZEFRACTIONAL(int styleNumber)
- SCI_STYLESETBOLD(int styleNumber, bool bold)
- SCI_STYLEGETBOLD(int styleNumber)
- SCI_STYLESETWEIGHT(int styleNumber, int weight)
- SCI_STYLEGETWEIGHT(int styleNumber)
- SCI_STYLESETITALIC(int styleNumber, bool italic)
- SCI_STYLEGETITALIC(int styleNumber)
- These messages (plus SCI_STYLESETCHARACTERSET) set the font - attributes that are used to match the fonts you request to those available. The - fontName is a zero terminated string holding the name of a font. Under Windows, - only the first 32 characters of the name are used and the name is not case sensitive. For - internal caching, Scintilla tracks fonts by name and does care about the casing of font names, - so please be consistent. On GTK+, Pango is used to display text.

-

Sizes can be set to a whole number of points with SCI_STYLESETSIZE - or to a fractional point size in hundredths of a point with SCI_STYLESETSIZEFRACTIONAL - by multiplying the size by 100 (SC_FONT_SIZE_MULTIPLIER). - For example, a text size of 9.4 points is set with SCI_STYLESETSIZEFRACTIONAL(<style>, 940). -

-

The weight or boldness of a font can be set with SCI_STYLESETBOLD - or SCI_STYLESETWEIGHT. The weight is a number between 1 and 999 with 1 being very light - and 999 very heavy. While any value can be used, fonts often only support between 2 and 4 weights with three weights - being common enough to have symbolic names: - SC_WEIGHT_NORMAL (400), - SC_WEIGHT_SEMIBOLD (600), and - SC_WEIGHT_BOLD (700). - The SCI_STYLESETBOLD message takes a boolean argument with 0 choosing SC_WEIGHT_NORMAL - and 1 SC_WEIGHT_BOLD. -

- -

SCI_STYLESETUNDERLINE(int styleNumber, bool - underline)
- SCI_STYLEGETUNDERLINE(int styleNumber)
- You can set a style to be underlined. The underline is drawn in the foreground colour. All - characters with a style that includes the underline attribute are underlined, even if they are - white space.

- -

SCI_STYLESETFORE(int styleNumber, int colour)
- SCI_STYLEGETFORE(int styleNumber)
- SCI_STYLESETBACK(int styleNumber, int colour)
- SCI_STYLEGETBACK(int styleNumber)
- Text is drawn in the foreground colour. The space in each character cell that is not occupied - by the character is drawn in the background colour.

- -

SCI_STYLESETEOLFILLED(int styleNumber, bool - eolFilled)
- SCI_STYLEGETEOLFILLED(int styleNumber)
- If the last character in the line has a style with this attribute set, the remainder of the - line up to the right edge of the window is filled with the background colour set for the last - character. This is useful when a document contains embedded sections in another language such - as HTML pages with embedded JavaScript. By setting eolFilled to true - and a consistent background colour (different from the background colour set for the HTML - styles) to all JavaScript styles then JavaScript sections will be easily distinguished from - HTML.

- -

SCI_STYLESETCHARACTERSET(int styleNumber, int - charSet)
- SCI_STYLEGETCHARACTERSET(int styleNumber)
- You can set a style to use a different character set than the default. The places where such - characters sets are likely to be useful are comments and literal strings. For example, - SCI_STYLESETCHARACTERSET(SCE_C_STRING, SC_CHARSET_RUSSIAN) would ensure that - strings in Russian would display correctly in C and C++ (SCE_C_STRING is the style - number used by the C and C++ lexer to display literal strings; it has the value 6). This - feature works differently on Windows and GTK+.

- -

The character sets supported on Windows are:
- SC_CHARSET_ANSI, SC_CHARSET_ARABIC, SC_CHARSET_BALTIC, - SC_CHARSET_CHINESEBIG5, SC_CHARSET_DEFAULT, - SC_CHARSET_EASTEUROPE, SC_CHARSET_GB2312, - SC_CHARSET_GREEK, SC_CHARSET_HANGUL, SC_CHARSET_HEBREW, - SC_CHARSET_JOHAB, SC_CHARSET_MAC, SC_CHARSET_OEM, - SC_CHARSET_RUSSIAN (code page 1251), - SC_CHARSET_SHIFTJIS, SC_CHARSET_SYMBOL, SC_CHARSET_THAI, - SC_CHARSET_TURKISH, and SC_CHARSET_VIETNAMESE.

- -

The character sets supported on GTK+ are:
- SC_CHARSET_ANSI, SC_CHARSET_CYRILLIC (code page 1251), - SC_CHARSET_EASTEUROPE, - SC_CHARSET_GB2312, SC_CHARSET_HANGUL, - SC_CHARSET_RUSSIAN (KOI8-R), SC_CHARSET_SHIFTJIS, and - SC_CHARSET_8859_15.

- -

SCI_STYLESETCASE(int styleNumber, int caseMode)
- SCI_STYLEGETCASE(int styleNumber)
- The value of caseMode determines how text is displayed. You can set upper case - (SC_CASE_UPPER, 1) or lower case (SC_CASE_LOWER, 2) or display - normally (SC_CASE_MIXED, 0). This does not change the stored text, only how it is - displayed.

- -

SCI_STYLESETVISIBLE(int styleNumber, bool visible)
- SCI_STYLEGETVISIBLE(int styleNumber)
- Text is normally visible. However, you can completely hide it by giving it a style with the - visible set to 0. This could be used to hide embedded formatting instructions or - hypertext keywords in HTML or XML.

- -

SCI_STYLESETCHANGEABLE(int styleNumber, bool - changeable)
- SCI_STYLEGETCHANGEABLE(int styleNumber)
- This is an experimental and incompletely implemented style attribute. The default setting is - changeable set true but when set false it makes text - read-only. Currently it only stops the caret from being within not-changeable text and does not - yet stop deleting a range that contains not-changeable text.

- -

SCI_STYLESETHOTSPOT(int styleNumber, bool - hotspot)
- SCI_STYLEGETHOTSPOT(int styleNumber)
- This style is used to mark ranges of text that can detect mouse clicks. - The cursor changes to a hand over hotspots, and the foreground, and background colours - may change and an underline appear to indicate that these areas are sensitive to clicking. - This may be used to allow hyperlinks to other documents.

- -

Caret, selection, and hotspot styles

- -

The selection is shown by changing the foreground and/or background colours. If one of these - is not set then that attribute is not changed for the selection. The default is to show the - selection by changing the background to light gray and leaving the foreground the same as when - it was not selected. When there is no selection, the current insertion point is marked by the - text caret. This is a vertical line that is normally blinking on and off to attract the users - attention.

- SCI_SETSELFORE(bool useSelectionForeColour, int colour)
- SCI_SETSELBACK(bool useSelectionBackColour, int colour)
- SCI_SETSELALPHA(int alpha)
- SCI_GETSELALPHA
- SCI_SETSELEOLFILLED(bool filled)
- SCI_GETSELEOLFILLED
- SCI_SETCARETFORE(int colour)
- SCI_GETCARETFORE
- SCI_SETCARETLINEVISIBLE(bool show)
- SCI_GETCARETLINEVISIBLE
- SCI_SETCARETLINEBACK(int colour)
- SCI_GETCARETLINEBACK
- SCI_SETCARETLINEBACKALPHA(int alpha)
- SCI_GETCARETLINEBACKALPHA
- SCI_SETCARETPERIOD(int milliseconds)
- SCI_GETCARETPERIOD
- SCI_SETCARETSTYLE(int style)
- SCI_GETCARETSTYLE
- SCI_SETCARETWIDTH(int pixels)
- SCI_GETCARETWIDTH
- SCI_SETHOTSPOTACTIVEFORE(bool useSetting, int colour)
- SCI_GETHOTSPOTACTIVEFORE
- SCI_SETHOTSPOTACTIVEBACK(bool useSetting, int colour)
- SCI_GETHOTSPOTACTIVEBACK
- SCI_SETHOTSPOTACTIVEUNDERLINE(bool underline)
- SCI_GETHOTSPOTACTIVEUNDERLINE
- SCI_SETHOTSPOTSINGLELINE(bool singleLine)
- SCI_GETHOTSPOTSINGLELINE
- SCI_SETCONTROLCHARSYMBOL(int symbol)
- SCI_GETCONTROLCHARSYMBOL
- SCI_SETCARETSTICKY(int useCaretStickyBehaviour)
- SCI_GETCARETSTICKY
- SCI_TOGGLECARETSTICKY
-
- -

SCI_SETSELFORE(bool useSelectionForeColour, int colour)
- SCI_SETSELBACK(bool useSelectionBackColour, int colour)
- You can choose to override the default selection colouring with these two messages. The colour - you provide is used if you set useSelection*Colour to true. If it is - set to false, the default styled colouring is used and the colour - argument has no effect.

-

SCI_SETSELALPHA(int alpha)
- SCI_GETSELALPHA
- The selection can be drawn translucently in the selection background colour by - setting an alpha value.

- -

SCI_SETSELEOLFILLED(bool filled)
- SCI_GETSELEOLFILLED
- The selection can be drawn up to the right hand border by setting this property.

- -

SCI_SETCARETFORE(int colour)
- SCI_GETCARETFORE
- The colour of the caret can be set with SCI_SETCARETFORE and retrieved with - SCI_GETCARETFORE.

- -

SCI_SETCARETLINEVISIBLE(bool show)
- SCI_GETCARETLINEVISIBLE
- SCI_SETCARETLINEBACK(int colour)
- SCI_GETCARETLINEBACK
- SCI_SETCARETLINEBACKALPHA(int alpha)
- SCI_GETCARETLINEBACKALPHA
- You can choose to make the background colour of the line containing the caret different with - these messages. To do this, set the desired background colour with - SCI_SETCARETLINEBACK, then use SCI_SETCARETLINEVISIBLE(true) to - enable the effect. You can cancel the effect with SCI_SETCARETLINEVISIBLE(false). - The two SCI_GETCARET* functions return the state and the colour. This form of - background colouring has highest priority when a line has markers that would otherwise change - the background colour. - The caret line may also be drawn translucently which allows other background colours to show - through. This is done by setting the alpha (translucency) value by calling - SCI_SETCARETLINEBACKALPHA. When the alpha is not SC_ALPHA_NOALPHA, - the caret line is drawn after all other features so will affect the colour of all other features. -

- -

SCI_SETCARETPERIOD(int milliseconds)
- SCI_GETCARETPERIOD
- The rate at which the caret blinks can be set with SCI_SETCARETPERIOD which - determines the time in milliseconds that the caret is visible or invisible before changing - state. Setting the period to 0 stops the caret blinking. The default value is 500 milliseconds. - SCI_GETCARETPERIOD returns the current setting.

- -

SCI_SETCARETSTYLE(int style)
- SCI_GETCARETSTYLE
- The style of the caret can be set with SCI_SETCARETSTYLE to be a line caret - (CARETSTYLE_LINE=1), a block caret (CARETSTYLE_BLOCK=2) or to not draw at all - (CARETSTYLE_INVISIBLE=0). The default value is the line caret (CARETSTYLE_LINE=1). - You can determine the current caret style setting using SCI_GETCARETSTYLE.

- -

The block character draws most combining and multibyte character sequences successfully, - though some fonts like Thai Fonts (and possibly others) can sometimes appear strange when - the cursor is positioned at these characters, which may result in only drawing a part of the - cursor character sequence. This is most notable on Windows platforms.

- -

SCI_SETCARETWIDTH(int pixels)
- SCI_GETCARETWIDTH
- The width of the line caret can be set with SCI_SETCARETWIDTH to a value of - 0, 1, 2 or 3 pixels. The default width is 1 pixel. You can read back the current width with - SCI_GETCARETWIDTH. A width of 0 makes the caret invisible (added at version - 1.50), similar to setting the caret style to CARETSTYLE_INVISIBLE (though not interchangable). - This setting only affects the width of the cursor when the cursor style is set to line caret - mode, it does not affect the width for a block caret.

- -

SCI_SETHOTSPOTACTIVEFORE(bool useHotSpotForeColour, int colour)
- SCI_GETHOTSPOTACTIVEFORE
- SCI_SETHOTSPOTACTIVEBACK(bool useHotSpotBackColour, int colour)
- SCI_GETHOTSPOTACTIVEBACK
- SCI_SETHOTSPOTACTIVEUNDERLINE(bool underline)
- SCI_GETHOTSPOTACTIVEUNDERLINE
- SCI_SETHOTSPOTSINGLELINE(bool singleLine)
- SCI_GETHOTSPOTSINGLELINE
- While the cursor hovers over text in a style with the hotspot attribute set, - the default colouring can be modified and an underline drawn with these settings. - Single line mode stops a hotspot from wrapping onto next line.

- -

SCI_SETCONTROLCHARSYMBOL(int symbol)
- SCI_GETCONTROLCHARSYMBOL
- By default, Scintilla displays control characters (characters with codes less than 32) in a - rounded rectangle as ASCII mnemonics: "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", - "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", - "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US". These mnemonics come from the - early days of signaling, though some are still used (LF = Line Feed, BS = Back Space, CR = - Carriage Return, for example).

- -

You can choose to replace these mnemonics by a nominated symbol with an ASCII code in the - range 32 to 255. If you set a symbol value less than 32, all control characters are displayed - as mnemonics. The symbol you set is rendered in the font of the style set for the character. - You can read back the current symbol with the SCI_GETCONTROLCHARSYMBOL message. - The default symbol value is 0.

- -

SCI_SETCARETSTICKY(int useCaretStickyBehaviour)
- SCI_GETCARETSTICKY
- SCI_TOGGLECARETSTICKY
- These messages set, get or toggle the caretSticky setting which controls when the last position - of the caret on the line is saved.

- -

When set to SC_CARETSTICKY_OFF (0), the sticky flag is off; all text changes - (and all caret position changes) will remember the - caret's new horizontal position when moving to different lines. This is the default.

- -

When set to SC_CARETSTICKY_ON (1), the sticky flag is on, and the only thing which will cause the editor to remember the - horizontal caret position is moving the caret with mouse or keyboard (left/right arrow keys, home/end keys, etc).

- -

When set to SC_CARETSTICKY_WHITESPACE (2), the caret acts like mode 0 (sticky off) except under one - special case; when space or tab characters are inserted. (Including pasting only space/tabs -- undo, redo, - etc. do not exhibit this behavior..).

- -

SCI_TOGGLECARETSTICKY switches from SC_CARETSTICKY_ON and SC_CARETSTICKY_WHITESPACE - to SC_CARETSTICKY_OFF and from SC_CARETSTICKY_OFF to SC_CARETSTICKY_ON.

- -

Margins

- -

There may be up to five margins to the left of the text display, plus a gap either side of - the text. Each margin can be set to display only symbols, line numbers, or text with SCI_SETMARGINTYPEN. - Textual margins may also display symbols. - The markers - that can be displayed in each margin are set with SCI_SETMARGINMASKN. Any markers not associated with - a visible margin will be displayed as changes in background colour in the text. A width in - pixels can be set for each margin. Margins with a zero width are ignored completely. You can - choose if a mouse click in a margin sends a SCN_MARGINCLICK notification to the container or - selects a line of text.

- -

The margins are numbered 0 to 4. Using a margin number outside the valid range has no - effect. By default, margin 0 is set to display line numbers, but is given a width of 0, so it - is hidden. Margin 1 is set to display non-folding symbols and is given a width of 16 pixels, so - it is visible. Margin 2 is set to display the folding symbols, but is given a width of 0, so it - is hidden. Of course, you can set the margins to be whatever you wish.

- -

Styled text margins used to show revision and blame information:

-

Styled text margins used to show revision and blame information

- - SCI_SETMARGINTYPEN(int margin, int - type)
- SCI_GETMARGINTYPEN(int margin)
- SCI_SETMARGINWIDTHN(int margin, int - pixelWidth)
- SCI_GETMARGINWIDTHN(int margin)
- SCI_SETMARGINMASKN(int margin, int - mask)
- SCI_GETMARGINMASKN(int margin)
- SCI_SETMARGINSENSITIVEN(int margin, bool - sensitive)
- SCI_GETMARGINSENSITIVEN(int - margin)
- SCI_SETMARGINCURSORN(int margin, int - cursor)
- SCI_GETMARGINCURSORN(int - margin)
- SCI_SETMARGINLEFT(<unused>, int - pixels)
- SCI_GETMARGINLEFT
- SCI_SETMARGINRIGHT(<unused>, int - pixels)
- SCI_GETMARGINRIGHT
- SCI_SETFOLDMARGINCOLOUR(bool useSetting, int colour)
- SCI_SETFOLDMARGINHICOLOUR(bool useSetting, int colour)
- SCI_MARGINSETTEXT(int line, char *text)
- SCI_MARGINGETTEXT(int line, char *text)
- SCI_MARGINSETSTYLE(int line, int style)
- SCI_MARGINGETSTYLE(int line)
- SCI_MARGINSETSTYLES(int line, char *styles)
- SCI_MARGINGETSTYLES(int line, char *styles)
- SCI_MARGINTEXTCLEARALL
- SCI_MARGINSETSTYLEOFFSET(int style)
- SCI_MARGINGETSTYLEOFFSET
- SCI_SETMARGINOPTIONS(int marginOptions)
- SCI_GETMARGINOPTIONS
-
- -

SCI_SETMARGINTYPEN(int margin, int iType)
- SCI_GETMARGINTYPEN(int margin)
- These two routines set and get the type of a margin. The margin argument should be 0, 1, 2, 3 or 4. - You can use the predefined constants SC_MARGIN_SYMBOL (0) and - SC_MARGIN_NUMBER (1) to set a margin as either a line number or a symbol margin. - A margin with application defined text may use SC_MARGIN_TEXT (4) or - SC_MARGIN_RTEXT (5) to right justify the text. - By convention, margin 0 is used for line numbers and the next two are used for symbols. You can - also use the constants SC_MARGIN_BACK (2) and SC_MARGIN_FORE (3) for - symbol margins that set their background colour to match the STYLE_DEFAULT background and - foreground colours.

- -

SCI_SETMARGINWIDTHN(int margin, int pixelWidth)
- SCI_GETMARGINWIDTHN(int margin)
- These routines set and get the width of a margin in pixels. A margin with zero width is - invisible. By default, Scintilla sets margin 1 for symbols with a width of 16 pixels, so this - is a reasonable guess if you are not sure what would be appropriate. Line number margins widths - should take into account the number of lines in the document and the line number style. You - could use something like SCI_TEXTWIDTH(STYLE_LINENUMBER, "_99999") to get a - suitable width.

- -

SCI_SETMARGINMASKN(int margin, int mask)
- SCI_GETMARGINMASKN(int margin)
- The mask is a 32-bit value. Each bit corresponds to one of 32 logical symbols that can be - displayed in a margin that is enabled for symbols. There is a useful constant, - SC_MASK_FOLDERS (0xFE000000 or -33554432), that is a mask for the 7 logical - symbols used to denote folding. You can assign a wide range of symbols and colours to each of - the 32 logical symbols, see Markers for more information. If (mask - & SC_MASK_FOLDERS)==0, the margin background colour is controlled by style 33 (STYLE_LINENUMBER).

- -

You add logical markers to a line with SCI_MARKERADD. If a line has an associated marker that - does not appear in the mask of any margin with a non-zero width, the marker changes the - background colour of the line. For example, suppose you decide to use logical marker 10 to mark - lines with a syntax error and you want to show such lines by changing the background colour. - The mask for this marker is 1 shifted left 10 times (1<<10) which is 0x400. If you make - sure that no symbol margin includes 0x400 in its mask, any line with the marker gets the - background colour changed.

- -

To set a non-folding margin 1 use SCI_SETMARGINMASKN(1, ~SC_MASK_FOLDERS) - which is the default set by Scintilla. - To set a folding margin 2 use SCI_SETMARGINMASKN(2, SC_MASK_FOLDERS). - ~SC_MASK_FOLDERS is 0x1FFFFFF in hexadecimal or 33554431 - decimal. Of course, you may need to display all 32 symbols in a margin, in which case use - SCI_SETMARGINMASKN(margin, -1).

- -

SCI_SETMARGINSENSITIVEN(int margin, bool - sensitive)
- SCI_GETMARGINSENSITIVEN(int margin)
- Each of the five margins can be set sensitive or insensitive to mouse clicks. A click in a - sensitive margin sends a SCN_MARGINCLICK notification to the container. Margins that are not sensitive act as - selection margins which make it easy to select ranges of lines. By default, all margins are - insensitive.

- -

SCI_SETMARGINCURSORN(int margin, int - cursor)
- SCI_GETMARGINCURSORN(int margin)
- A reversed arrow cursor is normally shown over all margins. This may be changed to a normal arrow with - SCI_SETMARGINCURSORN(margin, SC_CURSORARROW) or restored to a - reversed arrow with - SCI_SETMARGINCURSORN(margin, SC_CURSORREVERSEARROW).

- -

SCI_SETMARGINLEFT(<unused>, int pixels)
- SCI_GETMARGINLEFT
- SCI_SETMARGINRIGHT(<unused>, int pixels)
- SCI_GETMARGINRIGHT
- These messages set and get the width of the blank margin on both sides of the text in pixels. - The default is to one pixel on each side.

- -

SCI_SETFOLDMARGINCOLOUR(bool useSetting, int colour)
- SCI_SETFOLDMARGINHICOLOUR(bool useSetting, int colour)
- These messages allow changing the colour of the fold margin and fold margin highlight. - On Windows the fold margin colour defaults to ::GetSysColor(COLOR_3DFACE) and the fold margin highlight - colour to ::GetSysColor(COLOR_3DHIGHLIGHT).

- -

- SCI_MARGINSETTEXT(int line, char *text)
- SCI_MARGINGETTEXT(int line, char *text)
- SCI_MARGINSETSTYLE(int line, int style)
- SCI_MARGINGETSTYLE(int line)
- SCI_MARGINSETSTYLES(int line, char *styles)
- SCI_MARGINGETSTYLES(int line, char *styles)
- SCI_MARGINTEXTCLEARALL
- Text margins are created with the type SC_MARGIN_TEXT or SC_MARGIN_RTEXT. - A different string may be set for each line with SCI_MARGINSETTEXT. - The whole of the text margin on a line may be displayed in a particular style with - SCI_MARGINSETSTYLE or each character may be individually styled with - SCI_MARGINSETSTYLES which uses an array of bytes with each byte setting the style - of the corresponding text byte similar to SCI_SETSTYLINGEX. - Setting a text margin will cause a - SC_MOD_CHANGEMARGIN - notification to be sent. -

-

- SCI_MARGINSETSTYLEOFFSET(int style)
- SCI_MARGINGETSTYLEOFFSET
- Margin styles may be completely separated from standard text styles by setting a style offset. For example, - SCI_MARGINSETSTYLEOFFSET(256) would allow the margin styles to be numbered from - 256 upto 511 so they do not overlap styles set by lexers. Each style number set with SCI_MARGINSETSTYLE - or SCI_MARGINSETSTYLES has the offset added before looking up the style. -

-

- SCI_SETMARGINOPTIONS(int marginOptions)
- SCI_GETMARGINOPTIONS
- Define margin options by enabling appropriate bit flags. At the moment, only one flag is available - SC_MARGINOPTION_SUBLINESELECT=1, which controls how wrapped lines are selected when clicking - on margin in front of them. If SC_MARGINOPTION_SUBLINESELECT is set only sub line of wrapped - line is selected, otherwise whole wrapped line is selected. Margin options are set to - SC_MARGINOPTION_NONE=0 by default. -

- -

Annotations

- -

Annotations are read-only lines of text underneath each line of editable text. - An annotation may consist of multiple lines separated by '\n'. - Annotations can be used to display an assembler version of code for debugging or to show diagnostic messages inline or to - line up different versions of text in a merge tool.

-

Annotations used for inline diagnostics:

-

Annotations used for inline diagnostics

- - - SCI_ANNOTATIONSETTEXT(int line, char *text)
- SCI_ANNOTATIONGETTEXT(int line, char *text)
- SCI_ANNOTATIONSETSTYLE(int line, int style)
- SCI_ANNOTATIONGETSTYLE(int line)
- SCI_ANNOTATIONSETSTYLES(int line, char *styles)
- SCI_ANNOTATIONGETSTYLES(int line, char *styles)
- SCI_ANNOTATIONGETLINES(int line)
- SCI_ANNOTATIONCLEARALL
- SCI_ANNOTATIONSETVISIBLE(int visible)
- SCI_ANNOTATIONGETVISIBLE
- SCI_ANNOTATIONSETSTYLEOFFSET(int style)
- SCI_ANNOTATIONGETSTYLEOFFSET
-
- -

- SCI_ANNOTATIONSETTEXT(int line, char *text)
- SCI_ANNOTATIONGETTEXT(int line, char *text)
- SCI_ANNOTATIONSETSTYLE(int line, int style)
- SCI_ANNOTATIONGETSTYLE(int line)
- SCI_ANNOTATIONSETSTYLES(int line, char *styles)
- SCI_ANNOTATIONGETSTYLES(int line, char *styles)
- SCI_ANNOTATIONGETLINES(int line)
- SCI_ANNOTATIONCLEARALL
- A different string may be set for each line with SCI_ANNOTATIONSETTEXT. - To clear annotations call SCI_ANNOTATIONSETTEXT with a NULL pointer. - The whole of the text ANNOTATION on a line may be displayed in a particular style with - SCI_ANNOTATIONSETSTYLE or each character may be individually styled with - SCI_ANNOTATIONSETSTYLES which uses an array of bytes with each byte setting the style - of the corresponding text byte similar to SCI_SETSTYLINGEX. The text must be set first as it - specifies how long the annotation is so how many bytes of styling to read. - Setting an annotation will cause a - SC_MOD_CHANGEANNOTATION - notification to be sent. -

-

- The number of lines annotating a line can be retrieved with SCI_ANNOTATIONGETLINES. - All the lines can be cleared of annotations with SCI_ANNOTATIONCLEARALL - which is equivalent to clearing each line (setting to 0) and then deleting other memory used for this feature. -

-

- SCI_ANNOTATIONSETVISIBLE(int visible)
- SCI_ANNOTATIONGETVISIBLE
- Annotations can be made visible in a view and there is a choice of display style when visible. - The two messages set and get the annotation display mode. The visible - argument can be one of:

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
ANNOTATION_HIDDEN0Annotations are not displayed.
ANNOTATION_STANDARD1Annotations are drawn left justified with no adornment.
ANNOTATION_BOXED2Annotations are indented to match the text and are surrounded by a box.
- -

- SCI_ANNOTATIONSETSTYLEOFFSET(int style)
- SCI_ANNOTATIONGETSTYLEOFFSET
- Annotation styles may be completely separated from standard text styles by setting a style offset. For example, - SCI_ANNOTATIONSETSTYLEOFFSET(512) would allow the annotation styles to be numbered from - 512 upto 767 so they do not overlap styles set by lexers (or margins if margins offset is 256). - Each style number set with SCI_ANNOTATIONSETSTYLE - or SCI_ANNOTATIONSETSTYLES has the offset added before looking up the style. -

- -

Other settings

- SCI_SETUSEPALETTE(bool - allowPaletteUse)
- SCI_GETUSEPALETTE
- SCI_SETBUFFEREDDRAW(bool isBuffered)
- SCI_GETBUFFEREDDRAW
- SCI_SETTWOPHASEDRAW(bool twoPhase)
- SCI_GETTWOPHASEDRAW
- SCI_SETTECHNOLOGY(int technology)
- SCI_GETTECHNOLOGY
- SCI_SETFONTQUALITY(int fontQuality)
- SCI_GETFONTQUALITY
- SCI_SETCODEPAGE(int codePage)
- SCI_GETCODEPAGE
- SCI_SETKEYSUNICODE(bool keysUnicode)
- SCI_GETKEYSUNICODE
- SCI_SETWORDCHARS(<unused>, const char - *chars)
- SCI_SETWHITESPACECHARS(<unused>, const char - *chars)
- SCI_SETCHARSDEFAULT
- SCI_GRABFOCUS
- SCI_SETFOCUS(bool focus)
- SCI_GETFOCUS
-
- -

To forward a message (WM_XXXX, WPARAM, LPARAM) to Scintilla, you can use - SendMessage(hScintilla, WM_XXXX, WPARAM, LPARAM) where hScintilla is - the handle to the Scintilla window you created as your editor.

- -

While we are on the subject of forwarding messages in Windows, the top level window should - forward any WM_SETTINGCHANGE messages to Scintilla (this is currently used to - collect changes to mouse settings, but could be used for other user interface items in the - future).

- -

SCI_SETBUFFEREDDRAW(bool isBuffered)
- SCI_GETBUFFEREDDRAW
- These messages turn buffered drawing on or off and report the buffered drawing state. Buffered - drawing draws each line into a bitmap rather than directly to the screen and then copies the - bitmap to the screen. This avoids flickering although it does take longer. The default is for - drawing to be buffered.

- -

SCI_SETTWOPHASEDRAW(bool twoPhase)
- SCI_GETTWOPHASEDRAW
- Two phase drawing is a better but slower way of drawing text. - In single phase drawing each run of characters in one style is drawn along with its background. - If a character overhangs the end of a run, such as in "V_" where the - "V" is in a different style from the "_", then this can cause the right hand - side of the "V" to be overdrawn by the background of the "_" which - cuts it off. Two phase drawing - fixes this by drawing all the backgrounds first and then drawing the text in - transparent mode. Two phase drawing may flicker more than single phase - unless buffered drawing is on. The default is for drawing to be two phase.

- -

SCI_SETTECHNOLOGY(int technology)
- SCI_GETTECHNOLOGY
- The technology property allows choosing between different drawing APIs and options. - On most platforms, the only choice is SC_TECHNOLOGY_DEFAULT (0). - On Windows Vista or later, SC_TECHNOLOGY_DIRECTWRITE (1) - can be chosen to use the Direct2D and DirectWrite APIs for higher quality antialiased drawing.

-

Since Direct2D buffers drawing, Scintilla's buffering should be turned off with - SCI_SETBUFFEREDDRAW(0);. This causes DirectWrite to use better quality antialiasing.

- -

SCI_SETFONTQUALITY(int fontQuality)
- SCI_GETFONTQUALITY
- Manage font quality (antialiasing method). Currently, the following values are available on Windows: - SC_EFF_QUALITY_DEFAULT (backward compatible), - SC_EFF_QUALITY_NON_ANTIALIASED, - SC_EFF_QUALITY_ANTIALIASED, - SC_EFF_QUALITY_LCD_OPTIMIZED.

-

In case it is necessary to squeeze more options into this property, only a limited number of bits defined - by SC_EFF_QUALITY_MASK (0xf) will be used for quality.

- -

SCI_SETCODEPAGE(int codePage)
- SCI_GETCODEPAGE
- Scintilla has some support for Japanese, Chinese and Korean DBCS. Use this message with - codePage set to the code page number to set Scintilla to use code page information - to ensure double byte characters are treated as one character rather than two. This also stops - the caret from moving between the two bytes in a double byte character. - Do not use this message to choose between different single byte character sets: it doesn't do that. - Call with - codePage set to zero to disable DBCS support. The default is - SCI_SETCODEPAGE(0).

- -

Code page SC_CP_UTF8 (65001) sets Scintilla into Unicode mode with the document - treated as a sequence of characters expressed in UTF-8. The text is converted to the platform's - normal Unicode encoding before being drawn by the OS and thus can display Hebrew, Arabic, - Cyrillic, and Han characters. Languages which can use two characters stacked vertically in one - horizontal space, such as Thai, will mostly work but there are some issues where the characters - are drawn separately leading to visual glitches. Bi-directional text is not supported.

- -

Code page can be set to 932 (Japanese Shift-JIS), 936 (Simplified Chinese GBK), - 949 (Korean Unified Hangul Code), 950 (Traditional Chinese Big5), or 1361 (Korean Johab) - although these may require installation of language specific support.

- -

SCI_SETKEYSUNICODE(bool keysUnicode)
- SCI_GETKEYSUNICODE
- On Windows, character keys are normally handled differently depending on whether Scintilla is a wide - or narrow character window with character messages treated as Unicode when wide and as 8 bit otherwise. - Set this property to always treat as Unicode. This option is needed for Delphi.

- -

SCI_SETWORDCHARS(<unused>, const char *chars)
- Scintilla has several functions that operate on words, which are defined to be contiguous - sequences of characters from a particular set of characters. This message defines which - characters are members of that set. The character sets are set to default values before processing this - function. - For example, if you don't allow '_' in your set of characters - use:
- SCI_SETWORDCHARS(0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");

- -

SCI_SETWHITESPACECHARS(<unused>, const char *chars)
- Similar to SCI_SETWORDCHARS, this message allows the user to define which chars Scintilla considers - as whitespace. Setting the whitespace chars allows the user to fine-tune Scintilla's behaviour doing - such things as moving the cursor to the start or end of a word; for example, by defining punctuation chars - as whitespace, they will be skipped over when the user presses ctrl+left or ctrl+right. - This function should be called after SCI_SETWORDCHARS as it will - reset the whitespace characters to the default set.

-

SCI_SETCHARSDEFAULT
- Use the default sets of word and whitespace characters. This sets whitespace to space, tab and other - characters with codes less than 0x20, with word characters set to alphanumeric and '_'. -

- - -

SCI_GRABFOCUS
- SCI_SETFOCUS(bool focus)
- SCI_GETFOCUS
- Scintilla can be told to grab the focus with this message. This is needed more on GTK+ where - focus handling is more complicated than on Windows.

- -

The internal focus flag can be set with SCI_SETFOCUS. This is used by clients - that have complex focus requirements such as having their own window that gets the real focus - but with the need to indicate that Scintilla has the logical focus.

- -

Brace highlighting

- SCI_BRACEHIGHLIGHT(int pos1, int - pos2)
- SCI_BRACEBADLIGHT(int pos1)
- SCI_BRACEHIGHLIGHTINDICATOR(bool useBraceHighlightIndicator, int indicatorNumber)
- SCI_BRACEBADLIGHTINDICATOR(bool useBraceBadLightIndicator, int indicatorNumber)
- SCI_BRACEMATCH(int position, int - maxReStyle)
-
- -

SCI_BRACEHIGHLIGHT(int pos1, int pos2)
- Up to two characters can be highlighted in a 'brace highlighting style', which is defined as - style number STYLE_BRACELIGHT (34). - If you have enabled indent guides, you may also wish to highlight the indent that corresponds - with the brace. You can locate the column with SCI_GETCOLUMN and highlight the indent with SCI_SETHIGHLIGHTGUIDE.

- -

SCI_BRACEBADLIGHT(int pos1)
- If there is no matching brace then the brace - badlighting style, style STYLE_BRACEBAD (35), can be used to show the brace - that is unmatched. Using a position of INVALID_POSITION (-1) removes the - highlight.

- -

SCI_BRACEHIGHLIGHTINDICATOR(bool useBraceHighlightIndicator, int indicatorNumber)
- Use specified indicator to highlight matching braces instead of changing their style.

- -

SCI_BRACEBADLIGHTINDICATOR(bool useBraceBadLightIndicator, int indicatorNumber)
- Use specified indicator to highlight non matching brace instead of changing its style.

- -

SCI_BRACEMATCH(int pos, int maxReStyle)
- The SCI_BRACEMATCH message finds a corresponding matching brace given - pos, the position of one brace. The brace characters handled are '(', ')', '[', - ']', '{', '}', '<', and '>'. The search is forwards from an opening brace and backwards - from a closing brace. If the character at position is not a brace character, or a matching - brace cannot be found, the return value is -1. Otherwise, the return value is the position of - the matching brace.

- -

A match only occurs if the style of the matching brace is the same as the starting brace or - the matching brace is beyond the end of styling. Nested braces are handled correctly. The - maxReStyle parameter must currently be 0 - it may be used in the future to limit - the length of brace searches.

- -

Tabs and Indentation Guides

- -

Indentation (the white space at the start of a line) is often used by programmers to clarify - program structure and in some languages, for example Python, it may be part of the language - syntax. Tabs are normally used in editors to insert a tab character or to pad text with spaces - up to the next tab.

- -

Scintilla can be set to treat tab and backspace in the white space at the start of a line in - a special way: inserting a tab indents the line to the next indent position rather than just - inserting a tab at the current character position and backspace unindents the line rather than - deleting a character. Scintilla can also display indentation guides (vertical lines) to help - you to generate code.

- SCI_SETTABWIDTH(int widthInChars)
- SCI_GETTABWIDTH
- SCI_SETUSETABS(bool useTabs)
- SCI_GETUSETABS
- SCI_SETINDENT(int widthInChars)
- SCI_GETINDENT
- SCI_SETTABINDENTS(bool tabIndents)
- SCI_GETTABINDENTS
- SCI_SETBACKSPACEUNINDENTS(bool - bsUnIndents)
- SCI_GETBACKSPACEUNINDENTS
- SCI_SETLINEINDENTATION(int line, int - indentation)
- SCI_GETLINEINDENTATION(int line)
- SCI_GETLINEINDENTPOSITION(int - line)
- SCI_SETINDENTATIONGUIDES(int indentView)
- SCI_GETINDENTATIONGUIDES
- SCI_SETHIGHLIGHTGUIDE(int column)
- SCI_GETHIGHLIGHTGUIDE
-
- -

SCI_SETTABWIDTH(int widthInChars)
- SCI_GETTABWIDTH
- SCI_SETTABWIDTH sets the size of a tab as a multiple of the size of a space - character in STYLE_DEFAULT. The default tab width is 8 characters. There are no - limits on tab sizes, but values less than 1 or large values may have undesirable effects.

- -

SCI_SETUSETABS(bool useTabs)
- SCI_GETUSETABS
- SCI_SETUSETABS determines whether indentation should be created out of a mixture - of tabs and spaces or be based purely on spaces. Set useTabs to false - (0) to create all tabs and indents out of spaces. The default is true. You can use - SCI_GETCOLUMN to get the column of a - position taking the width of a tab into account.

-

SCI_SETINDENT(int widthInChars)
- SCI_GETINDENT
- SCI_SETINDENT sets the size of indentation in terms of the width of a space in STYLE_DEFAULT. If you set a width of - 0, the indent size is the same as the tab size. There are no limits on indent sizes, but values - less than 0 or large values may have undesirable effects. -

- -

SCI_SETTABINDENTS(bool tabIndents)
- SCI_GETTABINDENTS
- SCI_SETBACKSPACEUNINDENTS(bool bsUnIndents)
- SCI_GETBACKSPACEUNINDENTS
-

- -

Inside indentation white space, the tab and backspace keys can be made to indent and - unindent rather than insert a tab character or delete a character with the - SCI_SETTABINDENTS and SCI_SETBACKSPACEUNINDENTS functions.

- -

SCI_SETLINEINDENTATION(int line, int indentation)
- SCI_GETLINEINDENTATION(int line)
- The amount of indentation on a line can be discovered and set with - SCI_GETLINEINDENTATION and SCI_SETLINEINDENTATION. The indentation is - measured in character columns, which correspond to the width of space characters.

- -

SCI_GETLINEINDENTPOSITION(int line)
- This returns the position at the end of indentation of a line.

- -

SCI_SETINDENTATIONGUIDES(int indentView)
- SCI_GETINDENTATIONGUIDES
- Indentation guides are dotted vertical lines that appear within indentation white space every - indent size columns. They make it easy to see which constructs line up especially when they - extend over multiple pages. Style STYLE_INDENTGUIDE (37) is used to specify the - foreground and background colour of the indentation guides.

- -

There are 4 indentation guide views. - SC_IV_NONE turns the feature off but the other 3 states determine how far the guides appear on - empty lines.

- - - - - - - - - - - - - - - - - - - - - - - -
SC_IV_NONENo indentation guides are shown.
SC_IV_REALIndentation guides are shown inside real indentation white space.
SC_IV_LOOKFORWARDIndentation guides are shown beyond the actual indentation up to the level of the - next non-empty line. - If the previous non-empty line was a fold header then indentation guides are shown for - one more level of indent than that line. This setting is good for Python.
SC_IV_LOOKBOTHIndentation guides are shown beyond the actual indentation up to the level of the - next non-empty line or previous non-empty line whichever is the greater. - This setting is good for most languages.
- -

SCI_SETHIGHLIGHTGUIDE(int column)
- SCI_GETHIGHLIGHTGUIDE
- When brace highlighting occurs, the indentation guide corresponding to the braces may be - highlighted with the brace highlighting style, STYLE_BRACELIGHT (34). Set column to 0 to - cancel this highlight.

- -

Markers

- -

There are 32 markers, numbered 0 to MARKER_MAX (31), and you can assign any combination of them to each - line in the document. Markers appear in the selection - margin to the left of the text. If the selection margin is set to zero width, the - background colour of the whole line is changed instead. Marker numbers 25 to 31 are used by - Scintilla in folding margins, and have symbolic names of the form SC_MARKNUM_*, - for example SC_MARKNUM_FOLDEROPEN.

- -

Marker numbers 0 to 24 have no pre-defined function; you can use them to mark syntax errors - or the current point of execution, break points, or whatever you need marking. If you do not - need folding, you can use all 32 for any purpose you wish.

- -

Each marker number has a symbol associated with it. You can also set the foreground and - background colour for each marker number, so you can use the same symbol more than once with - different colouring for different uses. Scintilla has a set of symbols you can assign - (SC_MARK_*) or you can use characters. By default, all 32 markers are set to - SC_MARK_CIRCLE with a black foreground and a white background.

- -

The markers are drawn in the order of their numbers, so higher numbered markers appear on - top of lower numbered ones. Markers try to move with their text by tracking where the start of - their line moves. When a line is deleted, its markers are combined, by an OR - operation, with the markers of the previous line.

- SCI_MARKERDEFINE(int markerNumber, int - markerSymbols)
- SCI_MARKERDEFINEPIXMAP(int markerNumber, - const char *xpm)
- SCI_RGBAIMAGESETWIDTH(int width)
- SCI_RGBAIMAGESETHEIGHT(int height)
- SCI_MARKERDEFINERGBAIMAGE(int markerNumber, - const char *pixels)
- SCI_MARKERSYMBOLDEFINED(int markerNumber) -
- SCI_MARKERSETFORE(int markerNumber, int - colour)
- SCI_MARKERSETBACK(int markerNumber, int - colour)
- SCI_MARKERSETBACKSELECTED(int markerNumber, int - colour)
- SCI_MARKERENABLEHIGHLIGHT(int enabled)
- SCI_MARKERSETALPHA(int markerNumber, int - alpha)
- SCI_MARKERADD(int line, int markerNumber)
- SCI_MARKERADDSET(int line, int markerMask)
- SCI_MARKERDELETE(int line, int - markerNumber)
- SCI_MARKERDELETEALL(int markerNumber)
- SCI_MARKERGET(int line)
- SCI_MARKERNEXT(int lineStart, int - markerMask)
- SCI_MARKERPREVIOUS(int lineStart, int - markerMask)
- SCI_MARKERLINEFROMHANDLE(int - handle)
- SCI_MARKERDELETEHANDLE(int handle)
-
- -

SCI_MARKERDEFINE(int markerNumber, int markerSymbols)
- This message associates a marker number in the range 0 to 31 with one of the marker symbols or - an ASCII character. The general-purpose marker symbols currently available are:
- SC_MARK_CIRCLE, SC_MARK_ROUNDRECT, SC_MARK_ARROW, - SC_MARK_SMALLRECT, SC_MARK_SHORTARROW, SC_MARK_EMPTY, - SC_MARK_ARROWDOWN, SC_MARK_MINUS, SC_MARK_PLUS, - SC_MARK_ARROWS, SC_MARK_DOTDOTDOT, - SC_MARK_BACKGROUND, SC_MARK_LEFTRECT, - SC_MARK_FULLRECT, and SC_MARK_UNDERLINE.

- -

The SC_MARK_BACKGROUND marker changes the background colour of the line only. - The SC_MARK_FULLRECT symbol mirrors this, changing only the margin background colour. - SC_MARK_UNDERLINE draws an underline across the text. - The SC_MARK_EMPTY symbol is invisible, allowing client code to track the movement - of lines. You would also use it if you changed the folding style and wanted one or more of the - SC_FOLDERNUM_* markers to have no associated symbol.

- -

Applications may use the marker symbol SC_MARK_AVAILABLE to indicate that - plugins may allocate that marker number. -

- -

There are also marker symbols designed for use in the folding margin in a flattened tree - style.
- SC_MARK_BOXMINUS, SC_MARK_BOXMINUSCONNECTED, - SC_MARK_BOXPLUS, SC_MARK_BOXPLUSCONNECTED, - SC_MARK_CIRCLEMINUS, SC_MARK_CIRCLEMINUSCONNECTED, - SC_MARK_CIRCLEPLUS, SC_MARK_CIRCLEPLUSCONNECTED, - SC_MARK_LCORNER, SC_MARK_LCORNERCURVE, SC_MARK_TCORNER, - SC_MARK_TCORNERCURVE, and SC_MARK_VLINE.

- Characters can be used as markers by adding the ASCII value of the character to - SC_MARK_CHARACTER (10000). For example, to use 'A' (ASCII code 65) as marker - number 1 use:
- SCI_MARKERDEFINE(1, SC_MARK_CHARACTER+65).
- -

The marker numbers SC_MARKNUM_FOLDER and SC_MARKNUM_FOLDEROPEN are - used for showing that a fold is present and open or closed. Any symbols may be assigned for - this purpose although the (SC_MARK_PLUS, SC_MARK_MINUS) pair or the - (SC_MARK_ARROW, SC_MARK_ARROWDOWN) pair are good choices. As well as - these two, more assignments are needed for the flattened tree style: - SC_MARKNUM_FOLDEREND, SC_MARKNUM_FOLDERMIDTAIL, - SC_MARKNUM_FOLDEROPENMID, SC_MARKNUM_FOLDERSUB, and - SC_MARKNUM_FOLDERTAIL. The bits used for folding are specified by - SC_MASK_FOLDERS, which is commonly used as an argument to - SCI_SETMARGINMASKN when defining a margin to be used for folding.

- -

This table shows which SC_MARK_* symbols should be assigned to which - SC_MARKNUM_* marker numbers to obtain four folding styles: Arrow (mimics - Macintosh), plus/minus shows folded lines as '+' and opened folds as '-', Circle tree, Box - tree.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SC_MARKNUM_*ArrowPlus/minusCircle treeBox tree
FOLDEROPENARROWDOWNMINUSCIRCLEMINUSBOXMINUS
FOLDERARROWPLUSCIRCLEPLUSBOXPLUS
FOLDERSUBEMPTYEMPTYVLINEVLINE
FOLDERTAILEMPTYEMPTYLCORNERCURVELCORNER
FOLDERENDEMPTYEMPTYCIRCLEPLUSCONNECTEDBOXPLUSCONNECTED
FOLDEROPENMIDEMPTYEMPTYCIRCLEMINUSCONNECTEDBOXMINUSCONNECTED
FOLDERMIDTAILEMPTYEMPTYTCORNERCURVETCORNER
- -

SCI_MARKERDEFINEPIXMAP(int markerNumber, const char - *xpm)
- Markers can be set to pixmaps with this message. The - XPM format is used for the pixmap. - Pixmaps use the SC_MARK_PIXMAP marker symbol.

- -

- SCI_RGBAIMAGESETWIDTH(int width)
- SCI_RGBAIMAGESETHEIGHT(int height)
- SCI_MARKERDEFINERGBAIMAGE(int markerNumber, const char *pixels)
- Markers can be set to translucent pixmaps with this message. The - RGBA format is used for the pixmap. - The width and height must previously been set with the SCI_RGBAIMAGESETWIDTH and - SCI_RGBAIMAGESETHEIGHT messages. - Pixmaps use the SC_MARK_RGBAIMAGE marker symbol.

- -

SCI_MARKERSYMBOLDEFINED(int markerNumber)
- Returns the symbol defined for a markerNumber with SCI_MARKERDEFINE - or SC_MARK_PIXMAP if defined with SCI_MARKERDEFINEPIXMAP - or SC_MARK_RGBAIMAGE if defined with SCI_MARKERDEFINERGBAIMAGE.

- -

SCI_MARKERSETFORE(int markerNumber, int colour)
- SCI_MARKERSETBACK(int markerNumber, int colour)
- These two messages set the foreground and background colour of a marker number.
- SCI_MARKERSETBACKSELECTED(int markerNumber, int colour)
- This message sets the highlight background colour of a marker number when its folding block is selected. The default colour is #FF0000.

-

SCI_MARKERENABLEHIGHLIGHT(bool enabled)
- This message allows to enable/disable the highlight folding block when it is selected. (i.e. block that contains the caret)

-

SCI_MARKERSETALPHA(int markerNumber, int alpha)
- When markers are drawn in the content area, either because there is no margin for them or - they are of SC_MARK_BACKGROUND or SC_MARK_UNDERLINE types, they may be drawn translucently by - setting an alpha value.

- -

SCI_MARKERADD(int line, int markerNumber)
- This message adds marker number markerNumber to a line. The message returns -1 if - this fails (illegal line number, out of memory) or it returns a marker handle number that - identifies the added marker. You can use this returned handle with SCI_MARKERLINEFROMHANDLE to find where a - marker is after moving or combining lines and with SCI_MARKERDELETEHANDLE to delete the marker - based on its handle. The message does not check the value of markerNumber, nor does it - check if the line already contains the marker.

- -

SCI_MARKERADDSET(int line, int markerMask)
- This message can add one or more markers to a line with a single call, specified in the same "one-bit-per-marker" 32-bit integer format returned by - SCI_MARKERGET - (and used by the mask-based marker search functions - SCI_MARKERNEXT and - SCI_MARKERPREVIOUS). - As with - SCI_MARKERADD, no check is made - to see if any of the markers are already present on the targeted line.

- -

SCI_MARKERDELETE(int line, int markerNumber)
- This searches the given line number for the given marker number and deletes it if it is - present. If you added the same marker more than once to the line, this will delete one copy - each time it is used. If you pass in a marker number of -1, all markers are deleted from the - line.

- -

SCI_MARKERDELETEALL(int markerNumber)
- This removes markers of the given number from all lines. If markerNumber is -1, it deletes all - markers from all lines.

- -

SCI_MARKERGET(int line)
- This returns a 32-bit integer that indicates which markers were present on the line. Bit 0 is - set if marker 0 is present, bit 1 for marker 1 and so on.

- -

SCI_MARKERNEXT(int lineStart, int markerMask)
- SCI_MARKERPREVIOUS(int lineStart, int markerMask)
- These messages search efficiently for lines that include a given set of markers. The search - starts at line number lineStart and continues forwards to the end of the file - (SCI_MARKERNEXT) or backwards to the start of the file - (SCI_MARKERPREVIOUS). The markerMask argument should have one bit set - for each marker you wish to find. Set bit 0 to find marker 0, bit 1 for marker 1 and so on. The - message returns the line number of the first line that contains one of the markers in - markerMask or -1 if no marker is found.

- -

SCI_MARKERLINEFROMHANDLE(int markerHandle)
- The markerHandle argument is an identifier for a marker returned by SCI_MARKERADD. This function searches - the document for the marker with this handle and returns the line number that contains it or -1 - if it is not found.

- -

SCI_MARKERDELETEHANDLE(int markerHandle)
- The markerHandle argument is an identifier for a marker returned by SCI_MARKERADD. This function searches - the document for the marker with this handle and deletes the marker if it is found.

- -

Indicators

- -

Indicators are used to display additional information over the top of styling. - They can be used to show, for example, syntax errors, deprecated names and bad indentation - by drawing underlines under text or boxes around text. Originally, Scintilla stored indicator information in - the style bytes but this has proved limiting, so now up to 32 separately stored indicators may be used. - While style byte indicators currently still work, they will soon be removed so all the bits in each style - byte can be used for lexical states.

- -

Indicators may be displayed as simple underlines, squiggly underlines, a - line of small 'T' shapes, a line of diagonal hatching, a strike-out or a rectangle around the text.

- -

The SCI_INDIC* messages allow you to get and set the visual appearance of the - indicators. They all use an indicatorNumber argument in the range 0 to INDIC_MAX(31) - to set the indicator to style. To prevent interference the set of indicators is divided up into a range for use - by lexers (0..7) and a range for use by containers - (8=INDIC_CONTAINER .. 31=INDIC_MAX).

- - SCI_INDICSETSTYLE(int indicatorNumber, int - indicatorStyle)
- SCI_INDICGETSTYLE(int indicatorNumber)
- SCI_INDICSETFORE(int indicatorNumber, int - colour)
- SCI_INDICGETFORE(int indicatorNumber)
- SCI_INDICSETALPHA(int indicatorNumber, int alpha)
- SCI_INDICGETALPHA(int indicatorNumber)
- SCI_INDICSETOUTLINEALPHA(int indicatorNumber, int alpha)
- SCI_INDICGETOUTLINEALPHA(int indicatorNumber)
- SCI_INDICSETUNDER(int indicatorNumber, bool under)
- SCI_INDICGETUNDER(int indicatorNumber)
-
- -

SCI_INDICSETSTYLE(int indicatorNumber, int - indicatorStyle)
- SCI_INDICGETSTYLE(int indicatorNumber)
- These two messages set and get the style for a particular indicator. The indicator styles - currently available are:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SymbolValueVisual effect
INDIC_PLAIN0Underlined with a single, straight line.
INDIC_SQUIGGLE1A squiggly underline. Requires 3 pixels of descender space.
INDIC_TT2A line of small T shapes.
INDIC_DIAGONAL3Diagonal hatching.
INDIC_STRIKE4Strike out.
INDIC_HIDDEN5An indicator with no visual effect.
INDIC_BOX6A rectangle around the text.
INDIC_ROUNDBOX7A rectangle with rounded corners around the text using translucent drawing with the - interior usually more transparent than the border. You can use - SCI_INDICSETALPHA and - SCI_INDICSETOUTLINEALPHA - to control the alpha transparency values. The default alpha values are 30 for fill colour and 50 for outline colour.
INDIC_STRAIGHTBOX8A rectangle around the text using translucent drawing with the - interior usually more transparent than the border. You can use - SCI_INDICSETALPHA and - SCI_INDICSETOUTLINEALPHA - to control the alpha transparency values. The default alpha values are 30 for fill colour and 50 for outline colour.
INDIC_DASH9A dashed underline.
INDIC_DOTS10A dotted underline.
INDIC_SQUIGGLELOW11Similar to INDIC_SQUIGGLE but only using 2 vertical pixels - so will fit under small fonts.
INDIC_DOTBOX12A dotted rectangle around the text using translucent drawing. - Translucency alternates between the alpha and outline alpha settings with the top-left pixel using the alpha setting. - SCI_INDICSETALPHA and - SCI_INDICSETOUTLINEALPHA - control the alpha transparency values. The default values are 30 for alpha and 50 for outline alpha. - To avoid excessive memory allocation the maximum width of a dotted box is 4000 pixels. - Not available for OS X Carbon.
- -

The default indicator styles are equivalent to:
- SCI_INDICSETSTYLE(0, INDIC_SQUIGGLE);
- SCI_INDICSETSTYLE(1, INDIC_TT);
- SCI_INDICSETSTYLE(2, INDIC_PLAIN);

- -

SCI_INDICSETFORE(int indicatorNumber, int colour)
- SCI_INDICGETFORE(int indicatorNumber)
- These two messages set and get the colour used to draw an indicator. The default indicator - colours are equivalent to:
- SCI_INDICSETFORE(0, 0x007f00); (dark green)
- SCI_INDICSETFORE(1, 0xff0000); (light blue)
- SCI_INDICSETFORE(2, 0x0000ff); (light red)

- -

SCI_INDICSETALPHA(int indicatorNumber, int alpha)
- SCI_INDICGETALPHA(int indicatorNumber)
- These two messages set and get the alpha transparency used for drawing the - fill colour of the INDIC_ROUNDBOX and INDIC_STRAIGHTBOX rectangle. The alpha value can range from - 0 (completely transparent) to 255 (no transparency). -

- -

SCI_INDICSETOUTLINEALPHA(int indicatorNumber, int alpha)
- SCI_INDICGETOUTLINEALPHA(int indicatorNumber)
- These two messages set and get the alpha transparency used for drawing the - outline colour of the INDIC_ROUNDBOX and INDIC_STRAIGHTBOX rectangle. The alpha value can range from - 0 (completely transparent) to 255 (no transparency). -

- -

SCI_INDICSETUNDER(int indicatorNumber, bool under)
- SCI_INDICGETUNDER(int indicatorNumber)
- These two messages set and get whether an indicator is drawn under text or over(default). - Drawing under text works only for modern indicators when two phase drawing - is enabled.

- -

Modern Indicators

- -

Modern indicators are stored in a format similar to run length encoding which is efficient in both - speed and storage for sparse information.

-

An indicator may store different values for each range but currently all values are drawn the same. - In the future, it may be possible to draw different values in different styles.

-

- SCI_SETINDICATORCURRENT(int indicator)
- SCI_GETINDICATORCURRENT
- These two messages set and get the indicator that will be affected by calls to - SCI_INDICATORFILLRANGE(int position, int fillLength) and - SCI_INDICATORCLEARRANGE(int position, int clearLength). -

- -

- SCI_SETINDICATORVALUE(int value)
- SCI_GETINDICATORVALUE
- These two messages set and get the value that will be set by calls to - SCI_INDICATORFILLRANGE. -

- -

- SCI_INDICATORFILLRANGE(int position, int fillLength)
- SCI_INDICATORCLEARRANGE(int position, int clearLength)
- These two messages fill or clear a range for the current indicator. - SCI_INDICATORFILLRANGE fills with the - the current value. -

- -

- SCI_INDICATORALLONFOR(int position)
- Retrieve a bitmap value representing which indicators are non-zero at a position. -

- -

- SCI_INDICATORVALUEAT(int indicator, int position)
- Retrieve the value of a particular indicator at a position. -

- -

- SCI_INDICATORSTART(int indicator, int position)
- SCI_INDICATOREND(int indicator, int position)
- Find the start or end of a range with one value from a position within the range. - Can be used to iterate through the document to discover all the indicator positions. -

- -

Style Byte Indicators (deprecated)

-

By default, Scintilla organizes the style byte associated with each text byte as 5 bits of - style information (for 32 styles) and 3 bits of indicator information for 3 independent - indicators so that, for example, syntax errors, deprecated names and bad indentation could all - be displayed at once.

- -

The indicators are set using SCI_STARTSTYLING with a INDICS_MASK mask - and SCI_SETSTYLING with the values - INDIC0_MASK, INDIC1_MASK and INDIC2_MASK.

- -

If you are using indicators in a buffer that has a lexer active - (see SCI_SETLEXER), - you must save lexing state information before setting any indicators and restore it afterwards. - Use SCI_GETENDSTYLED - to retrieve the current "styled to" position and - SCI_STARTSTYLING - to reset the styling position and mask (0x1f in the default layout of 5 style bits and 3 indicator bits) - when you are done.

- -

The number of bits used for styles can be altered with SCI_SETSTYLEBITS from 0 to 8 bits. The remaining bits - can be used for indicators, so there can be from 1 to 8 indicators. However, the - INDIC*_MASK constants defined in Scintilla.h all assume 5 bits of - styling information and 3 indicators. If you use a different arrangement, you must define your - own constants.

- - -

Autocompletion

- -

Autocompletion displays a list box showing likely identifiers based upon the user's typing. - The user chooses the currently selected item by pressing the tab character or another character - that is a member of the fillup character set defined with SCI_AUTOCSETFILLUPS. - Autocompletion is triggered by your application. For example, in C if you detect that the user - has just typed fred. you could look up fred, and if it has a known - list of members, you could offer them in an autocompletion list. Alternatively, you could - monitor the user's typing and offer a list of likely items once their typing has narrowed down - the choice to a reasonable list. As yet another alternative, you could define a key code to - activate the list.

- -

When the user makes a selection from the list the container is sent a SCN_AUTOCSELECTION notification message. On return from the notification Scintilla will insert - the selected text unless the autocompletion list has been cancelled, for example by the container sending - SCI_AUTOCCANCEL.

- -

To make use of autocompletion you must monitor each character added to the document. See - SciTEBase::CharAdded() in SciTEBase.cxx for an example of autocompletion.

- SCI_AUTOCSHOW(int lenEntered, const char - *list)
- SCI_AUTOCCANCEL
- SCI_AUTOCACTIVE
- SCI_AUTOCPOSSTART
- SCI_AUTOCCOMPLETE
- SCI_AUTOCSTOPS(<unused>, const char - *chars)
- SCI_AUTOCSETSEPARATOR(char - separator)
- SCI_AUTOCGETSEPARATOR
- SCI_AUTOCSELECT(<unused>, const char - *select)
- SCI_AUTOCGETCURRENT
- SCI_AUTOCGETCURRENTTEXT(<unused>, - char *text)
- SCI_AUTOCSETCANCELATSTART(bool - cancel)
- SCI_AUTOCGETCANCELATSTART
- SCI_AUTOCSETFILLUPS(<unused>, const char - *chars)
- SCI_AUTOCSETCHOOSESINGLE(bool - chooseSingle)
- SCI_AUTOCGETCHOOSESINGLE
- SCI_AUTOCSETIGNORECASE(bool - ignoreCase)
- SCI_AUTOCGETIGNORECASE
- SCI_AUTOCSETAUTOHIDE(bool autoHide)
- SCI_AUTOCGETAUTOHIDE
- SCI_AUTOCSETDROPRESTOFWORD(bool - dropRestOfWord)
- SCI_AUTOCGETDROPRESTOFWORD
- SCI_REGISTERIMAGE(int type, const char *xpmData)
- SCI_REGISTERRGBAIMAGE(int type, const char *pixels)
- SCI_CLEARREGISTEREDIMAGES
- SCI_AUTOCSETTYPESEPARATOR(char separatorCharacter)
- SCI_AUTOCGETTYPESEPARATOR
- SCI_AUTOCSETMAXHEIGHT(int rowCount)
- SCI_AUTOCGETMAXHEIGHT
- SCI_AUTOCSETMAXWIDTH(int characterCount)
- SCI_AUTOCGETMAXWIDTH
-
- -

SCI_AUTOCSHOW(int lenEntered, const char *list)
- This message causes a list to be displayed. lenEntered is the number of - characters of the word already entered and list is the list of words separated by - separator characters. The initial separator character is a space but this can be set or got - with SCI_AUTOCSETSEPARATOR - and SCI_AUTOCGETSEPARATOR.

- -

The list of words should be in sorted order. If set to ignore case mode with SCI_AUTOCSETIGNORECASE, then - strings are matched after being converted to upper case. One result of this is that the list - should be sorted with the punctuation characters '[', '\', ']', '^', '_', and '`' sorted after - letters.

- -

SCI_AUTOCCANCEL
- This message cancels any displayed autocompletion list. When in autocompletion mode, the list - should disappear when the user types a character that can not be part of the autocompletion, - such as '.', '(' or '[' when typing an identifier. A set of characters that will cancel - autocompletion can be specified with SCI_AUTOCSTOPS.

- -

SCI_AUTOCACTIVE
- This message returns non-zero if there is an active autocompletion list and zero if there is - not.

- -

SCI_AUTOCPOSSTART
- This returns the value of the current position when SCI_AUTOCSHOW started display - of the list.

- -

SCI_AUTOCCOMPLETE
- This message triggers autocompletion. This has the same effect as the tab key.

- -

SCI_AUTOCSTOPS(<unused>, const char *chars)
- The chars argument is a string containing a list of characters that will - automatically cancel the autocompletion list. When you start the editor, this list is - empty.

- -

SCI_AUTOCSETSEPARATOR(char separator)
- SCI_AUTOCGETSEPARATOR
- These two messages set and get the separator character used to separate words in the - SCI_AUTOCSHOW list. The default is the space character.

- -

SCI_AUTOCSELECT(<unused>, const char *select)
- SCI_AUTOCGETCURRENT
- This message selects an item in the autocompletion list. It searches the list of words for the - first that matches select. By default, comparisons are case sensitive, but you can - change this with SCI_AUTOCSETIGNORECASE. The match is character - by character for the length of the select string. That is, if select is "Fred" it - will match "Frederick" if this is the first item in the list that begins with "Fred". If an - item is found, it is selected. If the item is not found, the autocompletion list closes if - auto-hide is true (see SCI_AUTOCSETAUTOHIDE).
- The current selection index can be retrieved with SCI_AUTOCGETCURRENT.

- -

SCI_AUTOCGETCURRENTTEXT(<unused>, char *text)
- This message retrieves the current selected text in the autocompletion list. Normally the - SCN_AUTOCSELECTION notification - is used instead.

- -

The value is copied to the text buffer, returning the length (not including the - terminating 0). If not found, an empty string is copied to the buffer and 0 is returned.

- -

If the value argument is 0 then the length that should be allocated to store the value is - returned; again, the terminating 0 is not included.

- -

SCI_AUTOCSETCANCELATSTART(bool cancel)
- SCI_AUTOCGETCANCELATSTART
- The default behavior is for the list to be cancelled if the caret moves to the location it - was at when the list was displayed. By calling this message with a false argument, - the list is not cancelled until the caret moves before the first character of the word being - completed.

- -

SCI_AUTOCSETFILLUPS(<unused>, const char *chars)
- If a fillup character is typed with an autocompletion list active, the currently selected item - in the list is added into the document, then the fillup character is added. Common fillup - characters are '(', '[' and '.' but others are possible depending on the language. By default, - no fillup characters are set.

- -

SCI_AUTOCSETCHOOSESINGLE(bool chooseSingle)
- SCI_AUTOCGETCHOOSESINGLE
- If you use SCI_AUTOCSETCHOOSESINGLE(1) and a list has only one item, it is - automatically added and no list is displayed. The default is to display the list even if there - is only a single item.

- -

SCI_AUTOCSETIGNORECASE(bool ignoreCase)
- SCI_AUTOCGETIGNORECASE
- By default, matching of characters to list members is case sensitive. These messages let you - set and get case sensitivity.

- -

SCI_AUTOCSETAUTOHIDE(bool autoHide)
- SCI_AUTOCGETAUTOHIDE
- By default, the list is cancelled if there are no viable matches (the user has typed - characters that no longer match a list entry). If you want to keep displaying the original - list, set autoHide to false. This also effects SCI_AUTOCSELECT.

- -

SCI_AUTOCSETDROPRESTOFWORD(bool dropRestOfWord)
- SCI_AUTOCGETDROPRESTOFWORD
- When an item is selected, any word characters following the caret are first erased if - dropRestOfWord is set true. The default is false.

- -

- SCI_REGISTERIMAGE(int type, const char *xpmData)
- SCI_REGISTERRGBAIMAGE(int type, const char *pixels)
- SCI_CLEARREGISTEREDIMAGES
- SCI_AUTOCSETTYPESEPARATOR(char separatorCharacter)
- SCI_AUTOCGETTYPESEPARATOR
- - Autocompletion list items may display an image as well as text. Each image is first registered with an integer - type. Then this integer is included in the text of the list separated by a '?' from the text. For example, - "fclose?2 fopen" displays image 2 before the string "fclose" and no image before "fopen". - The images are in either the XPM format (SCI_REGISTERIMAGE) or - RGBA format (SCI_REGISTERRGBAIMAGE). - For SCI_REGISTERRGBAIMAGE the width and height must previously been set with - the SCI_RGBAIMAGESETWIDTH and - SCI_RGBAIMAGESETHEIGHT messages. - The set of registered images can be cleared with SCI_CLEARREGISTEREDIMAGES and the '?' separator changed - with SCI_AUTOCSETTYPESEPARATOR. -

- -

- SCI_AUTOCSETMAXHEIGHT(int rowCount)
- SCI_AUTOCGETMAXHEIGHT
- - Get or set the maximum number of rows that will be visible in an autocompletion list. If there are more rows in the list, then a vertical - scrollbar is shown. The default is 5. -

- -

- SCI_AUTOCSETMAXWIDTH(int characterCount)
- SCI_AUTOCGETMAXWIDTH
- - Get or set the maximum width of an autocompletion list expressed as the number of characters in the longest item that will be totally visible. - If zero (the default) then the list's width is calculated to fit the item with the most characters. Any items that cannot be fully displayed within - the available width are indicated by the presence of ellipsis. -

- -

User lists

- -

User lists use the same internal mechanisms as autocompletion lists, and all the calls - listed for autocompletion work on them; you cannot display a user list at the same time as an - autocompletion list is active. They differ in the following respects:

- -

o The SCI_AUTOCSETCHOOSESINGLE message has no - effect.
- o When the user makes a selection you are sent a SCN_USERLISTSELECTION notification message rather than SCN_AUTOCSELECTION.

- -

BEWARE: if you have set fillup characters or stop characters, these will still be active - with the user list, and may result in items being selected or the user list cancelled due to - the user typing into the editor.

- -

SCI_USERLISTSHOW(int listType, const char *list)
- The listType parameter is returned to the container as the wParam - field of the SCNotification - structure. It must be greater than 0 as this is how Scintilla tells the difference between an - autocompletion list and a user list. If you have different types of list, for example a list of - buffers and a list of macros, you can use listType to tell which one has returned - a selection.

- -

Call tips

- -

Call tips are small windows displaying the arguments to a function and are displayed after - the user has typed the name of the function. They normally display characters using the font - facename, size and character set defined by - STYLE_DEFAULT. You can choose to - use STYLE_CALLTIP to define the - facename, size, foreground and background colours and character set with - SCI_CALLTIPUSESTYLE. - This also enables support for Tab characters. - - There is some interaction between call tips and autocompletion lists in that showing a - call tip cancels any active autocompletion list, and vice versa.

- -

Call tips can highlight part of the text within them. You could use this to highlight the - current argument to a function by counting the number of commas (or whatever separator your - language uses). See SciTEBase::CharAdded() in SciTEBase.cxx for an - example of call tip use.

- -

The mouse may be clicked on call tips and this causes a - SCN_CALLTIPCLICK - notification to be sent to the container. Small up and down arrows may be displayed within - a call tip by, respectively, including the characters '\001', or '\002'. This is useful - for showing that there are overloaded variants of one function name and that the user can - click on the arrows to cycle through the overloads.

- -

Alternatively, call tips can be displayed when you leave the mouse pointer for a while over - a word in response to the SCN_DWELLSTART notification and cancelled in response to SCN_DWELLEND. This method could be used in a debugger to give - the value of a variable, or during editing to give information about the word under the - pointer.

- SCI_CALLTIPSHOW(int posStart, const char - *definition)
- SCI_CALLTIPCANCEL
- SCI_CALLTIPACTIVE
- SCI_CALLTIPPOSSTART
- SCI_CALLTIPSETHLT(int highlightStart, int - highlightEnd)
- SCI_CALLTIPSETBACK(int colour)
- SCI_CALLTIPSETFORE(int colour)
- SCI_CALLTIPSETFOREHLT(int colour)
- SCI_CALLTIPUSESTYLE(int tabsize)
- SCI_CALLTIPSETPOSITION(bool above)
-
- -

SCI_CALLTIPSHOW(int posStart, const char *definition)
- This message starts the process by displaying the call tip window. If a call tip is already - active, this has no effect.
- posStart is the position in the document at which to align the call tip. The call - tip text is aligned to start 1 line below this character unless you have included up and/or - down arrows in the call tip text in which case the tip is aligned to the right-hand edge of - the rightmost arrow. The assumption is that you will start the text with something like - "\001 1 of 3 \002".
- definition is the call tip text. This can contain multiple lines separated by - '\n' (Line Feed, ASCII code 10) characters. Do not include '\r' (Carriage Return, ASCII - code 13), as this will most likely print as an empty box. '\t' (Tab, ASCII code 9) is - supported if you set a tabsize with - SCI_CALLTIPUSESTYLE.

- -

SCI_CALLTIPCANCEL
- This message cancels any displayed call tip. Scintilla will also cancel call tips for you if - you use any keyboard commands that are not compatible with editing the argument list of a - function.

- -

SCI_CALLTIPACTIVE
- This returns 1 if a call tip is active and 0 if it is not active.

- -

SCI_CALLTIPPOSSTART
- This message returns the value of the current position when SCI_CALLTIPSHOW - started to display the tip.

- -

SCI_CALLTIPSETHLT(int hlStart, int hlEnd)
- This sets the region of the call tips text to display in a highlighted style. - hlStart is the zero-based index into the string of the first character to - highlight and hlEnd is the index of the first character after the highlight. - hlEnd must be greater than hlStart; hlEnd-hlStart is the - number of characters to highlight. Highlights can extend over line ends if this is - required.

- -

Unhighlighted text is drawn in a mid gray. Selected text is drawn in a dark blue. The - background is white. These can be changed with - SCI_CALLTIPSETBACK, - SCI_CALLTIPSETFORE, and - SCI_CALLTIPSETFOREHLT. -

- -

SCI_CALLTIPSETBACK(int colour)
- The background colour of call tips can be set with this message; the default colour is white. - It is not a good idea to set a dark colour as the background as the default colour for normal - calltip text is mid gray and the defaultcolour for highlighted text is dark blue. This also - sets the background colour of STYLE_CALLTIP.

- -

SCI_CALLTIPSETFORE(int colour)
- The colour of call tip text can be set with this message; the default colour is mid gray. - This also sets the foreground colour of STYLE_CALLTIP.

- -

SCI_CALLTIPSETFOREHLT(int colour)
- The colour of highlighted call tip text can be set with this message; the default colour - is dark blue.

- -

SCI_CALLTIPUSESTYLE(int tabsize)
- This message changes the style used for call tips from STYLE_DEFAULT to - STYLE_CALLTIP and sets a tab size in screen pixels. If tabsize is - less than 1, Tab characters are not treated specially. Once this call has been used, the - call tip foreground and background colours are also taken from the style.

- -

SCI_CALLTIPSETPOSITION(bool above)
- By default the calltip is displayed below the text, setting above to true - (1) will display it above the text.

- - -

Keyboard commands

- -

To allow the container application to perform any of the actions available to the user with - keyboard, all the keyboard actions are messages. They do not take any parameters. These - commands are also used when redefining the key bindings with the SCI_ASSIGNCMDKEY message.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SCI_LINEDOWNSCI_LINEDOWNEXTENDSCI_LINEDOWNRECTEXTENDSCI_LINESCROLLDOWN
SCI_LINEUPSCI_LINEUPEXTENDSCI_LINEUPRECTEXTENDSCI_LINESCROLLUP
SCI_PARADOWNSCI_PARADOWNEXTENDSCI_PARAUPSCI_PARAUPEXTEND
SCI_CHARLEFTSCI_CHARLEFTEXTENDSCI_CHARLEFTRECTEXTEND
SCI_CHARRIGHTSCI_CHARRIGHTEXTENDSCI_CHARRIGHTRECTEXTEND
SCI_WORDLEFTSCI_WORDLEFTEXTENDSCI_WORDRIGHTSCI_WORDRIGHTEXTEND
SCI_WORDLEFTENDSCI_WORDLEFTENDEXTENDSCI_WORDRIGHTENDSCI_WORDRIGHTENDEXTEND
SCI_WORDPARTLEFTSCI_WORDPARTLEFTEXTENDSCI_WORDPARTRIGHTSCI_WORDPARTRIGHTEXTEND
SCI_HOMESCI_HOMEEXTENDSCI_HOMERECTEXTEND
SCI_HOMEDISPLAYSCI_HOMEDISPLAYEXTENDSCI_HOMEWRAPSCI_HOMEWRAPEXTEND
SCI_VCHOMESCI_VCHOMEEXTENDSCI_VCHOMERECTEXTEND
SCI_VCHOMEWRAPSCI_VCHOMEWRAPEXTEND
SCI_LINEENDSCI_LINEENDEXTENDSCI_LINEENDRECTEXTEND
SCI_LINEENDDISPLAYSCI_LINEENDDISPLAYEXTENDSCI_LINEENDWRAPSCI_LINEENDWRAPEXTEND
SCI_DOCUMENTSTARTSCI_DOCUMENTSTARTEXTENDSCI_DOCUMENTENDSCI_DOCUMENTENDEXTEND
SCI_PAGEUPSCI_PAGEUPEXTENDSCI_PAGEUPRECTEXTEND
SCI_PAGEDOWNSCI_PAGEDOWNEXTENDSCI_PAGEDOWNRECTEXTEND
SCI_STUTTEREDPAGEUPSCI_STUTTEREDPAGEUPEXTEND
SCI_STUTTEREDPAGEDOWNSCI_STUTTEREDPAGEDOWNEXTEND
SCI_DELETEBACKSCI_DELETEBACKNOTLINE
SCI_DELWORDLEFTSCI_DELWORDRIGHTSCI_DELWORDRIGHTEND
SCI_DELLINELEFTSCI_DELLINERIGHTSCI_LINEDELETE
SCI_LINECUTSCI_LINECOPYSCI_LINETRANSPOSESCI_LINEDUPLICATE
SCI_LOWERCASESCI_UPPERCASESCI_CANCELSCI_EDITTOGGLEOVERTYPE
SCI_NEWLINESCI_FORMFEEDSCI_TABSCI_BACKTAB
SCI_SELECTIONDUPLICATESCI_VERTICALCENTRECARET
SCI_MOVESELECTEDLINESUPSCI_MOVESELECTEDLINESDOWN
SCI_SCROLLTOSTARTSCI_SCROLLTOEND
- -

The SCI_*EXTEND messages extend the selection.

- -

The SCI_*RECTEXTEND messages extend the rectangular selection - (and convert regular selection to rectangular one, if any).

- -

The SCI_WORDPART* commands are used to move between word segments marked by - capitalisation (aCamelCaseIdentifier) or underscores (an_under_bar_ident).

- -

The SCI_HOME* commands move the caret to the start of the line, while the - SCI_VCHOME* commands move the caret to the first non-blank character of the line - (ie. just after the indentation) unless it is already there; in this case, it acts as SCI_HOME*.

- -

The SCI_[HOME|LINEEND]DISPLAY* commands are used when in line wrap mode to - allow movement to the start or end of display lines as opposed to the normal - SCI_[HOME|LINEEND] commands which move to the start or end of document lines.

- -

The SCI_[[VC]HOME|LINEEND]WRAP* commands are like their namesakes - SCI_[[VC]HOME|LINEEND]* except they behave differently when word-wrap is enabled: - They go first to the start / end of the display line, like SCI_[HOME|LINEEND]DISPLAY*, - but if the cursor is already at the point, it goes on to the start or end of the document line, - as appropriate for SCI_[[VC]HOME|LINEEND]*. -

- -

The SCI_SCROLLTO[START|END] commands scroll the document to the start - or end without changing the selection. These commands match OS X platform conventions for the behaviour of the - home and end keys. Scintilla can be made to match OS X applications - by binding the home and end keys to these commands. -

- -

Key bindings

- -

There is a default binding of keys to commands that is defined in the Scintilla source in - the file KeyMap.cxx by the constant KeyMap::MapDefault[]. This table - maps key definitions to SCI_* messages with no parameters (mostly the keyboard commands discussed above, but any Scintilla - command that has no arguments can be mapped). You can change the mapping to suit your own - requirements.

- SCI_ASSIGNCMDKEY(int keyDefinition, int - sciCommand)
- SCI_CLEARCMDKEY(int keyDefinition)
- SCI_CLEARALLCMDKEYS
- SCI_NULL
-
- -

keyDefinition
- A key definition contains the key code in the low 16-bits and the key modifiers in the high - 16-bits. To combine keyCode and keyMod set:
-
- keyDefinition = keyCode + (keyMod << 16)

- -

The key code is a visible or control character or a key from the SCK_* - enumeration, which contains:
- SCK_ADD, SCK_BACK, SCK_DELETE, SCK_DIVIDE, - SCK_DOWN, SCK_END, SCK_ESCAPE, SCK_HOME, - SCK_INSERT, SCK_LEFT, SCK_MENU, SCK_NEXT (Page Down), - SCK_PRIOR (Page Up), SCK_RETURN, SCK_RIGHT, - SCK_RWIN, - SCK_SUBTRACT, SCK_TAB, SCK_UP, and - SCK_WIN.

- -

The modifiers are a combination of zero or more of SCMOD_ALT, - SCMOD_CTRL, SCMOD_SHIFT, and SCMOD_META. - On OS X, the Command key is mapped to SCMOD_CTRL and the Control key to - SCMOD_META. - If you are building a table, you might - want to use SCMOD_NORM, which has the value 0, to mean no modifiers.

- -

SCI_ASSIGNCMDKEY(int keyDefinition, int sciCommand)
- This assigns the given key definition to a Scintilla command identified by - sciCommand. sciCommand can be any SCI_* command that has - no arguments.

- -

SCI_CLEARCMDKEY(int keyDefinition)
- This makes the given key definition do nothing by assigning the action SCI_NULL - to it.

- -

SCI_CLEARALLCMDKEYS
- This command removes all keyboard command mapping by setting an empty mapping table.

- -

SCI_NULL
- The SCI_NULL does nothing and is the value assigned to keys that perform no - action. SCI_NULL ensures that keys do not propagate to the parent window as that may - cause focus to move. If you want the standard platform behaviour use the constant 0 instead.

- -

Popup edit menu

- -

SCI_USEPOPUP(bool bEnablePopup)
- Clicking the wrong button on the mouse pops up a short default editing menu. This may be - turned off with SCI_USEPOPUP(0). If you turn it off, context menu commands (in - Windows, WM_CONTEXTMENU) will not be handled by Scintilla, so the parent of the - Scintilla window will have the opportunity to handle the message.

- -

Macro recording

- -

Start and stop macro recording mode. In macro recording mode, actions are reported to the - container through SCN_MACRORECORD - notifications. It is then up to the container to - record these actions for future replay.

- -

SCI_STARTRECORD
- SCI_STOPRECORD
- These two messages turn macro recording on and off.

- -

Printing

- -

SCI_FORMATRANGE can be used to draw the text onto a display surface - which can include a printer display surface. Printed output shows text styling as on the - screen, but it hides all margins except a line number margin. All special marker effects are - removed and the selection and caret are hidden.

- -

Different platforms use different display surface ID types to print on. On Windows, these are - HDCs., on GTK+ 3.x cairo_t *, - and on Cocoa CGContextRef is used.

- -

SCI_FORMATRANGE is not supported on GTK+ 2.x.

- - SCI_FORMATRANGE(bool bDraw, Sci_RangeToFormat - *pfr)
- SCI_SETPRINTMAGNIFICATION(int - magnification)
- SCI_GETPRINTMAGNIFICATION
- SCI_SETPRINTCOLOURMODE(int mode)
- SCI_GETPRINTCOLOURMODE
- SCI_SETPRINTWRAPMODE
- SCI_GETPRINTWRAPMODE
-
- -

SCI_FORMATRANGE(bool bDraw, Sci_RangeToFormat *pfr)
- This call renders a range of text into a device context. If you use - this for printing, you will probably want to arrange a page header and footer; Scintilla does - not do this for you. See SciTEWin::Print() in SciTEWinDlg.cxx for an - example. Each use of this message renders a range of text into a rectangular area and returns - the position in the document of the next character to print.

- -

bDraw controls if any output is done. Set this to false if you are paginating - (for example, if you use this with MFC you will need to paginate in - OnBeginPrinting() before you output each page.

-
-struct Sci_Rectangle { int left; int top; int right; int bottom; };
-
-struct Sci_RangeToFormat {
-    Sci_SurfaceID hdc;        // The Surface ID we print to
-    Sci_SurfaceID hdcTarget;  // The Surface ID we use for measuring (may be same as hdc)
-    Sci_Rectangle rc;         // Rectangle in which to print
-    Sci_Rectangle rcPage;     // Physically printable page size
-    Sci_CharacterRange chrg;  // Range of characters to print
-};
-
- -

On Windows, hdc and hdcTarget should both be set to the device context handle - of the output device (usually a printer). If you print to a metafile these will not be the same - as Windows metafiles (unlike extended metafiles) do not implement the full API for returning - information. In this case, set hdcTarget to the screen DC.
- rcPage is the rectangle {0, 0, maxX, maxY} where maxX+1 - and maxY+1 are the number of physically printable pixels in x and y.
- rc is the rectangle to render the text in (which will, of course, fit within the - rectangle defined by rcPage).
- chrg.cpMin and chrg.cpMax define the start position and maximum - position of characters to output. All of each line within this character range is drawn.

- -

On Cocoa, the surface IDs for printing (bDraw=1) should be the graphics port of the current context - ((CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]) when the view's drawRect method is called. - The Surface IDs are not really used for measurement (bDraw=0) but can be set - to a bitmap context (created with CGBitmapContextCreate) to avoid runtime warnings.

- -

On GTK+, the surface IDs to use can be found from the printing context with - gtk_print_context_get_cairo_context(context).

- - chrg.cpMin and chrg.cpMax define the start position and maximum - position of characters to output. All of each line within this character range is drawn.

- -

When printing, the most tedious part is always working out what the margins should be to - allow for the non-printable area of the paper and printing a header and footer. If you look at - the printing code in SciTE, you will find that most of it is taken up with this. The loop that - causes Scintilla to render text is quite simple if you strip out all the margin, non-printable - area, header and footer code.

- -

SCI_SETPRINTMAGNIFICATION(int magnification)
- SCI_GETPRINTMAGNIFICATION
- SCI_GETPRINTMAGNIFICATION lets you to print at a different size than the screen - font. magnification is the number of points to add to the size of each screen - font. A value of -3 or -4 gives reasonably small print. You can get this value with - SCI_GETPRINTMAGNIFICATION.

- -

SCI_SETPRINTCOLOURMODE(int mode)
- SCI_GETPRINTCOLOURMODE
- These two messages set and get the method used to render coloured text on a printer that is - probably using white paper. It is especially important to consider the treatment of colour if - you use a dark or black screen background. Printing white on black uses up toner and ink very - many times faster than the other way around. You can set the mode to one of:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SymbolValuePurpose
SC_PRINT_NORMAL0Print using the current screen colours. This is the default.
SC_PRINT_INVERTLIGHT1If you use a dark screen background this saves ink by inverting the light value of - all colours and printing on a white background.
SC_PRINT_BLACKONWHITE2Print all text as black on a white background.
SC_PRINT_COLOURONWHITE3Everything prints in its own colour on a white background.
SC_PRINT_COLOURONWHITEDEFAULTBG4Everything prints in its own colour on a white background except that line numbers - use their own background colour.
- -

SCI_SETPRINTWRAPMODE(int wrapMode)
- SCI_GETPRINTWRAPMODE
- These two functions get and set the printer wrap mode. wrapMode can be - set to SC_WRAP_NONE (0), SC_WRAP_WORD (1) or - SC_WRAP_CHAR (2). The default is - SC_WRAP_WORD, which wraps printed output so that all characters fit - into the print rectangle. If you set SC_WRAP_NONE, each line of text - generates one line of output and the line is truncated if it is too long to fit - into the print area.
- SC_WRAP_WORD tries to wrap only between words as indicated by - white space or style changes although if a word is longer than a line, it will be wrapped before - the line end. SC_WRAP_CHAR is preferred to - SC_WRAP_WORD for Asian languages where there is no white space - between words.

- -

Direct access

- SCI_GETDIRECTFUNCTION
- SCI_GETDIRECTPOINTER
- SCI_GETCHARACTERPOINTER
-
- -

On Windows, the message-passing scheme used to communicate between the container and - Scintilla is mediated by the operating system SendMessage function and can lead to - bad performance when calling intensively. To avoid this overhead, Scintilla provides messages - that allow you to call the Scintilla message function directly. The code to do this in C/C++ is - of the form:

-
-#include "Scintilla.h"
-SciFnDirect pSciMsg = (SciFnDirect)SendMessage(hSciWnd, SCI_GETDIRECTFUNCTION, 0, 0);
-sptr_t pSciWndData = (sptr_t)SendMessage(hSciWnd, SCI_GETDIRECTPOINTER, 0, 0);
-
-// now a wrapper to call Scintilla directly
-sptr_t CallScintilla(unsigned int iMessage, uptr_t wParam, sptr_t lParam){
-    return pSciMsg(pSciWndData, iMessage, wParam, lParam);
-}
-
- -

SciFnDirect, sptr_t and uptr_t are declared in - Scintilla.h. hSciWnd is the window handle returned when you created - the Scintilla window.

- -

While faster, this direct calling will cause problems if performed from a different thread - to the native thread of the Scintilla window in which case SendMessage(hSciWnd, SCI_*, - wParam, lParam) should be used to synchronize with the window's thread.

- -

This feature also works on GTK+ but has no significant impact on speed.

- -

From version 1.47 on Windows, Scintilla exports a function called - Scintilla_DirectFunction that can be used the same as the function returned by - SCI_GETDIRECTFUNCTION. This saves you the call to - SCI_GETDIRECTFUNCTION and the need to call Scintilla indirectly via the function - pointer.

- -

SCI_GETDIRECTFUNCTION
- This message returns the address of the function to call to handle Scintilla messages without - the overhead of passing through the Windows messaging system. You need only call this once, - regardless of the number of Scintilla windows you create.

- -

SCI_GETDIRECTPOINTER
- This returns a pointer to data that identifies which Scintilla window is in use. You must call - this once for each Scintilla window you create. When you call the direct function, you must - pass in the direct pointer associated with the target window.

- -

SCI_GETCHARACTERPOINTER
- Move the gap within Scintilla so that the text of the document is stored consecutively - and ensure there is a NUL character after the text, then return a pointer to the first character. - Applications may then pass this to a function that accepts a character pointer such as a regular - expression search or a parser. The pointer should not be written to as that may desynchronize - the internal state of Scintilla.

-

Since any action in Scintilla may change its internal state - this pointer becomes invalid after any call or by allowing user interface activity. The application - should reacquire the pointer after making any call to Scintilla or performing any user-interface calls such - as modifying a progress indicator.

-

This call takes similar time to inserting a character at the end of the document and this may - include moving the document contents. Specifically, all the characters after the document gap - are moved to before the gap. This compacted state should persist over calls and user interface - actions that do not change the document contents so reacquiring the pointer afterwards is very - quick. If this call is used to implement a global replace operation, then each replacement will - move the gap so if SCI_GETCHARACTERPOINTER is called after - each replacement then the operation will become O(n^2) rather than O(n). Instead, all - matches should be found and remembered, then all the replacements performed.

- -

Multiple views

- -

A Scintilla window and the document that it displays are separate entities. When you create - a new window, you also create a new, empty document. Each document has a reference count that - is initially set to 1. The document also has a list of the Scintilla windows that are linked to - it so when any window changes the document, all other windows in which it appears are notified - to cause them to update. The system is arranged in this way so that you can work with many - documents in a single Scintilla window and so you can display a single document in multiple - windows (for use with splitter windows).

- -

Although these messages use document *pDoc, to ensure compatibility with future - releases of Scintilla you should treat pDoc as an opaque void*. That - is, you can use and store the pointer as described in this section but you should not - dereference it.

- SCI_GETDOCPOINTER
- SCI_SETDOCPOINTER(<unused>, document - *pDoc)
- SCI_CREATEDOCUMENT
- SCI_ADDREFDOCUMENT(<unused>, document - *pDoc)
- SCI_RELEASEDOCUMENT(<unused>, document - *pDoc)
-
- -

SCI_GETDOCPOINTER
- This returns a pointer to the document currently in use by the window. It has no other - effect.

- -

SCI_SETDOCPOINTER(<unused>, document *pDoc)
- This message does the following:
- 1. It removes the current window from the list held by the current document.
- 2. It reduces the reference count of the current document by 1.
- 3. If the reference count reaches 0, the document is deleted.
- 4. pDoc is set as the new document for the window.
- 5. If pDoc was 0, a new, empty document is created and attached to the - window.
- 6. If pDoc was not 0, its reference count is increased by 1.

- -

SCI_CREATEDOCUMENT
- This message creates a new, empty document and returns a pointer to it. This document is not - selected into the editor and starts with a reference count of 1. This means that you have - ownership of it and must either reduce its reference count by 1 after using - SCI_SETDOCPOINTER so that the Scintilla window owns it or you must make sure that - you reduce the reference count by 1 with SCI_RELEASEDOCUMENT before you close the - application to avoid memory leaks.

- -

SCI_ADDREFDOCUMENT(<unused>, document *pDoc)
- This increases the reference count of a document by 1. If you want to replace the current - document in the Scintilla window and take ownership of the current document, for example if you - are editing many documents in one window, do the following:
- 1. Use SCI_GETDOCPOINTER to get a pointer to the document, - pDoc.
- 2. Use SCI_ADDREFDOCUMENT(0, pDoc) to increment the reference count.
- 3. Use SCI_SETDOCPOINTER(0, pNewDoc) to set a different document or - SCI_SETDOCPOINTER(0, 0) to set a new, empty document.

- -

SCI_RELEASEDOCUMENT(<unused>, document *pDoc)
- This message reduces the reference count of the document identified by pDoc. pDoc - must be the result of SCI_GETDOCPOINTER or SCI_CREATEDOCUMENT and - must point at a document that still exists. If you call this on a document with a reference - count of 1 that is still attached to a Scintilla window, bad things will happen. To keep the - world spinning in its orbit you must balance each call to SCI_CREATEDOCUMENT or - SCI_ADDREFDOCUMENT with a call to SCI_RELEASEDOCUMENT.

- -

Background loading and saving

- -

To ensure a responsive user interface, applications may decide to load and save documents using a separate thread - from the user interface.

- -

Loading in the background

- -

An application can load all of a file into a buffer it allocates on a background thread and then add the data in that buffer - into a Scintilla document on the user interface thread. That technique uses extra memory to store a complete copy of the - file and also means that the time that Scintilla takes to perform initial line end discovery blocks the user interface.

- -

To avoid these issues, a loader object may be created and used to load the file. The loader object supports the ILoader interface.

- -

SCI_CREATELOADER(int bytes)
- Create an object that supports the ILoader interface which can be used to load data and then - be turned into a Scintilla document object for attachment to a view object. - The bytes argument determines the initial memory allocation for the document as it is more efficient - to allocate once rather than rely on the buffer growing as data is added. - If SCI_CREATELOADER fails then 0 is returned.

- -

ILoader

- -
-class ILoader {
-public:
-        virtual int SCI_METHOD Release() = 0;
-        // Returns a status code from SC_STATUS_*
-        virtual int SCI_METHOD AddData(char *data, int length) = 0;
-        virtual void * SCI_METHOD ConvertToDocument() = 0;
-};
-
- -

The application should call the AddData method with each block of data read from the file. - AddData will return SC_STATUS_OK unless a failure, such as memory exhaustion occurs. - If a failure occurs in AddData or in a file reading call then loading can be abandoned and the loader released with - the Release call. - When the whole file has been read, the ConvertToDocument method should be called to produce a Scintilla - document pointer which can be used in the same way as a document pointer returned from - SCI_CREATEDOCUMENT. - There is no need to call Release after ConvertToDocument.

- -

Saving in the background

- -

An application that wants to save in the background should lock the document with SCI_SETREADONLY(1) - to prevent modifications and retrieve a pointer to the unified document contents with - SCI_GETCHARACTERPOINTER. - The buffer of a locked document will not move so the pointer is valid until the application calls SCI_SETREADONLY(0).

- -

If the user tries to performs a modification while the document is locked then a SCN_MODIFYATTEMPTRO notification is sent to the application. - The application may then decide to ignore the modification or to terminate the background saving thread and reenable - modification before returning from the notification.

- -

Folding

- -

The fundamental operation in folding is making lines invisible or visible. Line visibility - is a property of the view rather than the document so each view may be displaying a different - set of lines. From the point of view of the user, lines are hidden and displayed using fold - points. Generally, the fold points of a document are based on the hierarchical structure of the - document contents. In Python, the hierarchy is determined by indentation and in C++ by brace - characters. This hierarchy can be represented within a Scintilla document object by attaching a - numeric "fold level" to each line. The fold level is most easily set by a lexer, but you can - also set it with messages.

- -

It is up to your code to set the connection between user actions and folding and unfolding. - The best way to see how this is done is to search the SciTE source code for the messages used - in this section of the documentation and see how they are used. You will also need to use - markers and a folding margin to complete your folding implementation. - The "fold" property should be set to "1" with - SCI_SETPROPERTY("fold", "1") to enable folding.

- SCI_VISIBLEFROMDOCLINE(int - docLine)
- SCI_DOCLINEFROMVISIBLE(int - displayLine)
- SCI_SHOWLINES(int lineStart, int lineEnd)
- SCI_HIDELINES(int lineStart, int lineEnd)
- SCI_GETLINEVISIBLE(int line)
- SCI_GETALLLINESVISIBLE
- SCI_SETFOLDLEVEL(int line, int level)
- SCI_GETFOLDLEVEL(int line)
- SCI_SETFOLDFLAGS(int flags)
- SCI_GETLASTCHILD(int line, int level)
- SCI_GETFOLDPARENT(int line)
- SCI_SETFOLDEXPANDED(int line, bool - expanded)
- SCI_GETFOLDEXPANDED(int line)
- SCI_CONTRACTEDFOLDNEXT(int lineStart)
- SCI_TOGGLEFOLD(int line)
- SCI_ENSUREVISIBLE(int line)
- SCI_ENSUREVISIBLEENFORCEPOLICY(int - line)
-
- -

SCI_VISIBLEFROMDOCLINE(int docLine)
- When some lines are folded, then a particular line in the document may be displayed at a - different position to its document position. If no lines are folded, this message returns - docLine. Otherwise, this returns the display line (counting the very first visible - line as 0). The display line of an invisible line is the same as the previous visible line. The - display line number of the first line in the document is 0. If there is folding and - docLine is outside the range of lines in the document, the return value is -1. - Lines can occupy more than one display line if they wrap.

- -

SCI_DOCLINEFROMVISIBLE(int displayLine)
- When some lines are hidden, then a particular line in the document may be displayed at a - different position to its document position. This message returns the document line number that - corresponds to a display line (counting the display line of the first line in the document as - 0). If displayLine is less than or equal to 0, the result is 0. If - displayLine is greater than or equal to the number of displayed lines, the result - is the number of lines in the document.

- -

SCI_SHOWLINES(int lineStart, int lineEnd)
- SCI_HIDELINES(int lineStart, int lineEnd)
- SCI_GETLINEVISIBLE(int line)
- SCI_GETALLLINESVISIBLE
- The first two messages mark a range of lines as visible or invisible and then redraw the - display. - SCI_GETLINEVISIBLE reports on the visible state of a line and returns 1 if it is - visible and 0 if it is not visible. - SCI_GETALLLINESVISIBLE returns 1 if all lines are visible and 0 - if some lines are hidden. - These messages have no effect on fold levels or fold - flags. The first line can not be hidden.

- -

SCI_SETFOLDLEVEL(int line, int level)
- SCI_GETFOLDLEVEL(int line)
- These two messages set and get a 32-bit value that contains the fold level of a line and some - flags associated with folding. The fold level is a number in the range 0 to - SC_FOLDLEVELNUMBERMASK (4095). However, the initial fold level is set to - SC_FOLDLEVELBASE (1024) to allow unsigned arithmetic on folding levels. There are - two addition flag bits. SC_FOLDLEVELWHITEFLAG indicates that the line is blank and - allows it to be treated slightly different then its level may indicate. For example, blank - lines should generally not be fold points and will be considered part of the preceding section even though - they may have a lesser fold level. - SC_FOLDLEVELHEADERFLAG indicates that - the line is a header (fold point).

- -

Use SCI_GETFOLDLEVEL(line) & SC_FOLDLEVELNUMBERMASK to get the fold level - of a line. Likewise, use SCI_GETFOLDLEVEL(line) & SC_FOLDLEVEL*FLAG to get the - state of the flags. To set the fold level you must or in the associated flags. For instance, to - set the level to thisLevel and mark a line as being a fold point use: - SCI_SETFOLDLEVEL(line, thisLevel | SC_FOLDLEVELHEADERFLAG).

- If you use a lexer, you should not need to use SCI_SETFOLDLEVEL as this is far - better handled by the lexer. You will need to use SCI_GETFOLDLEVEL to decide how - to handle user folding requests. If you do change the fold levels, the folding margin will - update to match your changes. - -

SCI_SETFOLDFLAGS(int flags)
- In addition to showing markers in the folding margin, you can indicate folds to the user by - drawing lines in the text area. The lines are drawn in the foreground colour set for STYLE_DEFAULT. Bits set in - flags determine where folding lines are drawn:
-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SymbolValueEffect
1Experimental feature that has been removed.
SC_FOLDFLAG_LINEBEFORE_EXPANDED2Draw above if expanded
SC_FOLDFLAG_LINEBEFORE_CONTRACTED4Draw above if not expanded
SC_FOLDFLAG_LINEAFTER_EXPANDED8Draw below if expanded
SC_FOLDFLAG_LINEAFTER_CONTRACTED16Draw below if not expanded
SC_FOLDFLAG_LEVELNUMBERS64display hexadecimal fold levels in line margin to aid debugging of - folding. The appearance of this feature may change in the future.
- -

This message causes the display to redraw.

- -

SCI_GETLASTCHILD(int startLine, int level)
- This message searches for the next line after startLine, that has a folding level - that is less than or equal to level and then returns the previous line number. If - you set level to -1, level is set to the folding level of line - startLine. If from is a fold point, SCI_GETLASTCHILD(from, - -1) returns the last line that would be in made visible or hidden by toggling the fold - state.

- -

SCI_GETFOLDPARENT(int startLine)
- This message returns the line number of the first line before startLine that is - marked as a fold point with SC_FOLDLEVELHEADERFLAG and has a fold level less than - the startLine. If no line is found, or if the header flags and fold levels are - inconsistent, the return value is -1.

- -

SCI_TOGGLEFOLD(int line)
- Each fold point may be either expanded, displaying all its child lines, or contracted, hiding - all the child lines. This message toggles the folding state of the given line as long as it has - the SC_FOLDLEVELHEADERFLAG set. This message takes care of folding or expanding - all the lines that depend on the line. The display updates after this message.

- -

SCI_SETFOLDEXPANDED(int line, bool expanded)
- SCI_GETFOLDEXPANDED(int line)
- These messages set and get the expanded state of a single line. The set message has no effect - on the visible state of the line or any lines that depend on it. It does change the markers in - the folding margin. If you ask for the expansion state of a line that is outside the document, - the result is false (0).

- -

If you just want to toggle the fold state of one line and handle all the lines that are - dependent on it, it is much easier to use SCI_TOGGLEFOLD. You would use the - SCI_SETFOLDEXPANDED message to process many folds without updating the display - until you had finished. See SciTEBase::FoldAll() and - SciTEBase::Expand() for examples of the use of these messages.

- -

SCI_CONTRACTEDFOLDNEXT(int lineStart)
- Search efficiently for lines that are contracted fold headers. - This is useful when saving the user's folding when switching documents or saving folding with a file. - The search starts at line number lineStart and continues forwards to the end of the file. - lineStart is returned if it is a contracted fold header otherwise the next contracted - fold header is returned. If there are no more contracted fold headers then -1 is returned.

- -

SCI_ENSUREVISIBLE(int line)
- SCI_ENSUREVISIBLEENFORCEPOLICY(int line)
- A line may be hidden because more than one of its parent lines is contracted. Both these - message travels up the fold hierarchy, expanding any contracted folds until they reach the top - level. The line will then be visible. If you use SCI_ENSUREVISIBLEENFORCEPOLICY, - the vertical caret policy set by SCI_SETVISIBLEPOLICY is then applied.

- -

Line wrapping

- - SCI_SETWRAPMODE(int wrapMode)
- SCI_GETWRAPMODE
- SCI_SETWRAPVISUALFLAGS(int wrapVisualFlags)
- SCI_GETWRAPVISUALFLAGS
- SCI_SETWRAPVISUALFLAGSLOCATION(int wrapVisualFlagsLocation)
- SCI_GETWRAPVISUALFLAGSLOCATION
- SCI_SETWRAPINDENTMODE(int indentMode)
- SCI_GETWRAPINDENTMODE
- SCI_SETWRAPSTARTINDENT(int indent)
- SCI_GETWRAPSTARTINDENT
- SCI_SETLAYOUTCACHE(int cacheMode)
- SCI_GETLAYOUTCACHE
- SCI_SETPOSITIONCACHE(int size)
- SCI_GETPOSITIONCACHE
- SCI_LINESSPLIT(int pixelWidth)
- SCI_LINESJOIN
- SCI_WRAPCOUNT(int docLine)
-
- -

By default, Scintilla does not wrap lines of text. If you enable line wrapping, lines wider - than the window width are continued on the following lines. Lines are broken after space or tab - characters or between runs of different styles. If this is not possible because a word in one - style is wider than the window then the break occurs after the last character that completely - fits on the line. The horizontal scroll bar does not appear when wrap mode is on.

- -

For wrapped lines Scintilla can draw visual flags (little arrows) at end of a a subline of a - wrapped line and at begin of the next subline. These can be enabled individually, but if Scintilla - draws the visual flag at the beginning of the next subline this subline will be indented by one char. - Independent from drawing a visual flag at the begin the subline can have an indention.

- -

Much of the time used by Scintilla is spent on laying out and drawing text. The same text - layout calculations may be performed many times even when the data used in these calculations - does not change. To avoid these unnecessary calculations in some circumstances, the line layout - cache can store the results of the calculations. The cache is invalidated whenever the - underlying data, such as the contents or styling of the document changes. Caching the layout of - the whole document has the most effect, making dynamic line wrap as much as 20 times faster but - this requires 7 times the memory required by the document contents plus around 80 bytes per - line.

- -

Wrapping is not performed immediately there is a change but is delayed until the display - is redrawn. This delay improves peformance by allowing a set of changes to be performed - and then wrapped and displayed once. Because of this, some operations may not occur as - expected. If a file is read and the scroll position moved to a particular line in the text, - such as occurs when a container tries to restore a previous editing session, then - the scroll position will have been determined before wrapping so an unexpected range - of text will be displayed. To scroll to the position correctly, delay the scroll until the - wrapping has been performed by waiting for an initial - SCN_PAINTED notification.

- -

SCI_SETWRAPMODE(int wrapMode)
- SCI_GETWRAPMODE
- Set wrapMode to SC_WRAP_WORD (1) to enable wrapping - on word boundaries, SC_WRAP_CHAR (2) to enable wrapping - between any characters, and to SC_WRAP_NONE (0) to disable line - wrapping. SC_WRAP_CHAR is preferred to - SC_WRAP_WORD for Asian languages where there is no white space - between words.

- - -

SCI_SETWRAPVISUALFLAGS(int wrapVisualFlags)
- SCI_GETWRAPVISUALFLAGS
- You can enable the drawing of visual flags to indicate a line is wrapped. Bits set in - wrapVisualFlags determine which visual flags are drawn. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SymbolValueEffect
SC_WRAPVISUALFLAG_NONE0No visual flags
SC_WRAPVISUALFLAG_END1Visual flag at end of subline of a wrapped line.
SC_WRAPVISUALFLAG_START2Visual flag at begin of subline of a wrapped line.
- Subline is indented by at least 1 to make room for the flag.
-
- -

SCI_SETWRAPVISUALFLAGSLOCATION(int wrapVisualFlagsLocation)
- SCI_GETWRAPVISUALFLAGSLOCATION
- You can set whether the visual flags to indicate a line is wrapped are drawn near the border or near the text. - Bits set in wrapVisualFlagsLocation set the location to near the text for the corresponding visual flag. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SymbolValueEffect
SC_WRAPVISUALFLAGLOC_DEFAULT0Visual flags drawn near border
SC_WRAPVISUALFLAGLOC_END_BY_TEXT1Visual flag at end of subline drawn near text
SC_WRAPVISUALFLAGLOC_START_BY_TEXT2Visual flag at beginning of subline drawn near text
- -

SCI_SETWRAPINDENTMODE(int indentMode)
- SCI_GETWRAPINDENTMODE
- Wrapped sublines can be indented to the position of their first subline or one more indent level. - The default is SC_WRAPINDENT_FIXED. - The modes are: -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SymbolValueEffect
SC_WRAPINDENT_FIXED0Wrapped sublines aligned to left of window plus amount set by - SCI_SETWRAPSTARTINDENT
SC_WRAPINDENT_SAME1Wrapped sublines are aligned to first subline indent
SC_WRAPINDENT_INDENT2Wrapped sublines are aligned to first subline indent plus one more level of indentation
- -

SCI_SETWRAPSTARTINDENT(int indent)
- SCI_GETWRAPSTARTINDENT
- SCI_SETWRAPSTARTINDENT sets the size of indentation of sublines for - wrapped lines in terms of the average character width in - STYLE_DEFAULT. - There are no limits on indent sizes, but values less than 0 or large values may have - undesirable effects.
- The indention of sublines is independent of visual flags, but if - SC_WRAPVISUALFLAG_START is set an indent of at least 1 is used. -

- -

SCI_SETLAYOUTCACHE(int cacheMode)
- SCI_GETLAYOUTCACHE
- You can set cacheMode to one of the symbols in the table:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SymbolValueLayout cached for these lines
SC_CACHE_NONE0No lines are cached.
SC_CACHE_CARET1The line containing the text caret. This is the default.
SC_CACHE_PAGE2Visible lines plus the line containing the caret.
SC_CACHE_DOCUMENT3All lines in the document.
- -

SCI_SETPOSITIONCACHE(int size)
- SCI_GETPOSITIONCACHE
- The position cache stores position information for short runs of text - so that their layout can be determined more quickly if the run recurs. - The size in entries of this cache can be set with SCI_SETPOSITIONCACHE.

- -

SCI_LINESSPLIT(int pixelWidth)
- Split a range of lines indicated by the target into lines that are at most pixelWidth wide. - Splitting occurs on word boundaries wherever possible in a similar manner to line wrapping. - When pixelWidth is 0 then the width of the window is used. -

- -

SCI_LINESJOIN
- Join a range of lines indicated by the target into one line by - removing line end characters. - Where this would lead to no space between words, an extra space is inserted. -

- -

SCI_WRAPCOUNT(int docLine)
- Document lines can occupy more than one display line if they wrap and this - returns the number of display lines needed to wrap a document line.

- -

Zooming

- -

Scintilla incorporates a "zoom factor" that lets you make all the text in the document - larger or smaller in steps of one point. The displayed point size never goes below 2, whatever - zoom factor you set. You can set zoom factors in the range -10 to +20 points.

- SCI_ZOOMIN
- SCI_ZOOMOUT
- SCI_SETZOOM(int zoomInPoints)
- SCI_GETZOOM
-
- -

SCI_ZOOMIN
- SCI_ZOOMOUT
- SCI_ZOOMIN increases the zoom factor by one point if the current zoom factor is - less than 20 points. SCI_ZOOMOUT decreases the zoom factor by one point if the - current zoom factor is greater than -10 points.

- -

SCI_SETZOOM(int zoomInPoints)
- SCI_GETZOOM
- These messages let you set and get the zoom factor directly. There is no limit set on the - factors you can set, so limiting yourself to -10 to +20 to match the incremental zoom functions - is a good idea.

- -

Long lines

- -

You can choose to mark lines that exceed a given length by drawing a vertical line or by - colouring the background of characters that exceed the set length.

- SCI_SETEDGEMODE(int mode)
- SCI_GETEDGEMODE
- SCI_SETEDGECOLUMN(int column)
- SCI_GETEDGECOLUMN
- SCI_SETEDGECOLOUR(int colour)
- SCI_GETEDGECOLOUR
-
- -

SCI_SETEDGEMODE(int edgeMode)
- SCI_GETEDGEMODE
- These two messages set and get the mode used to display long lines. You can set one of the - values in the table:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SymbolValueLong line display mode
EDGE_NONE0Long lines are not marked. This is the default state.
EDGE_LINE1A vertical line is drawn at the column number set by SCI_SETEDGECOLUMN. - This works well for monospaced fonts. The line is drawn at a position based on the width - of a space character in STYLE_DEFAULT, so it may not work very well if - your styles use proportional fonts or if your style have varied font sizes or you use a - mixture of bold, italic and normal text.
EDGE_BACKGROUND2The background colour of characters after the column limit is changed to the colour - set by SCI_SETEDGECOLOUR. This is recommended for proportional fonts.
- -

SCI_SETEDGECOLUMN(int column)
- SCI_GETEDGECOLUMN
- These messages set and get the column number at which to display the long line marker. When - drawing lines, the column sets a position in units of the width of a space character in - STYLE_DEFAULT. When setting the background colour, the column is a character count - (allowing for tabs) into the line.

- -

SCI_SETEDGECOLOUR(int colour)
- SCI_GETEDGECOLOUR
- These messages set and get the colour of the marker used to show that a line has exceeded the - length set by SCI_SETEDGECOLUMN.

- -

Lexer

- -

If you define the symbol SCI_LEXER when building Scintilla, (this is sometimes - called the SciLexer version of Scintilla), lexing support for a wide range of programming - languages is included and the messages in this section are supported. If you want to set - styling and fold points for an unsupported language you can either do this in the container or - better still, write your own lexer following the pattern of one of the existing ones.

- -

Scintilla also supports external lexers. These are DLLs (on Windows) or .so modules (on GTK+/Linux) that export three - functions: GetLexerCount, GetLexerName, and - GetLexerFactory. See externalLexer.cxx for more.

- SCI_SETLEXER(int lexer)
- SCI_GETLEXER
- SCI_SETLEXERLANGUAGE(<unused>, const char - *name)
- SCI_GETLEXERLANGUAGE(<unused>, char - *name)
- SCI_LOADLEXERLIBRARY(<unused>, const char - *path)
- SCI_COLOURISE(int start, int end)
- SCI_CHANGELEXERSTATE(int start, int end)
- SCI_PROPERTYNAMES(<unused>, char *names)
- SCI_PROPERTYTYPE(const char *name)
- SCI_DESCRIBEPROPERTY(const char *name, char *description)
- SCI_SETPROPERTY(const char *key, const char *value)
- SCI_GETPROPERTY(const char *key, char *value)
- SCI_GETPROPERTYEXPANDED(const char *key, char *value)
- SCI_GETPROPERTYINT(const char *key, int default)
- SCI_DESCRIBEKEYWORDSETS(<unused>, char *descriptions)
- SCI_SETKEYWORDS(int keyWordSet, const char - *keyWordList)
- SCI_GETSTYLEBITSNEEDED -
-
- -

SCI_SETLEXER(int lexer)
- SCI_GETLEXER
- You can select the lexer to use with an integer code from the SCLEX_* enumeration - in Scintilla.h. There are two codes in this sequence that do not use lexers: - SCLEX_NULL to select no lexing action and SCLEX_CONTAINER which sends - the SCN_STYLENEEDED notification to - the container whenever a range of text needs to be styled. You cannot use the - SCLEX_AUTOMATIC value; this identifies additional external lexers that Scintilla - assigns unused lexer numbers to.

- -

SCI_SETLEXERLANGUAGE(<unused>, const char *name)
- SCI_GETLEXERLANGUAGE(<unused>, char *name)
- SCI_SETLEXERLANGUAGE lets you select a lexer by name, and is the only method if you are using an - external lexer or if you have written a lexer module for a language of your own and do not wish - to assign it an explicit lexer number. To select an existing lexer, set name to - match the (case sensitive) name given to the module, for example "ada" or "python", not "Ada" - or "Python". To locate the name for the built-in lexers, open the relevant - Lex*.cxx file and search for LexerModule. The third argument in the - LexerModule constructor is the name to use.

- -

To test if your lexer assignment worked, use SCI_GETLEXER before and after setting the new lexer to - see if the lexer number changed.

- -

SCI_GETLEXERLANGUAGE retrieves the name of the lexer.

- -

SCI_LOADLEXERLIBRARY(<unused>, const char *path)
- Load a lexer implemented in a shared library. This is a .so file on GTK+/Linux or a .DLL file on Windows. -

- -

SCI_COLOURISE(int startPos, int endPos)
- This requests the current lexer or the container (if the lexer is set to - SCLEX_CONTAINER) to style the document between startPos and - endPos. If endPos is -1, the document is styled from - startPos to the end. If the "fold" property is set to - "1" and your lexer or container supports folding, fold levels are also set. This - message causes a redraw.

- -

SCI_CHANGELEXERSTATE(int startPos, int endPos)
- Indicate that the internal state of a lexer has changed over a range and therefore - there may be a need to redraw.

- -

SCI_PROPERTYNAMES(<unused>, char *names)
- SCI_PROPERTYTYPE(const char *name)
- SCI_DESCRIBEPROPERTY(const char *name, char *description)
- Information may be retrieved about the properties that can be set for the current lexer. - This information is only available for newer lexers. - SCI_PROPERTYNAMES returns a string with all of the valid properties separated by "\n". - If the lexer does not support this call then an empty string is returned. - Properties may be boolean (SC_TYPE_BOOLEAN), integer (SC_TYPE_INTEGER), - or string (SC_TYPE_STRING) and this is found with SCI_PROPERTYTYPE. - A description of a property in English is returned by SCI_DESCRIBEPROPERTY.

- -

SCI_SETPROPERTY(const char *key, const char *value)
- You can communicate settings to lexers with keyword:value string pairs. There is no limit to - the number of keyword pairs you can set, other than available memory. key is a - case sensitive keyword, value is a string that is associated with the keyword. If - there is already a value string associated with the keyword, it is replaced. If you pass a zero - length string, the message does nothing. Both key and value are used - without modification; extra spaces at the beginning or end of key are - significant.

- -

The value string can refer to other keywords. For example, - SCI_SETPROPERTY("foldTimes10", "$(fold)0") stores the string - "$(fold)0", but when this is accessed, the $(fold) is replaced by the - value of the "fold" keyword (or by nothing if this keyword does not exist).

- -

Currently the "fold" property is defined for most of the lexers to set the fold structure if - set to "1". SCLEX_PYTHON understands "tab.timmy.whinge.level" as a - setting that determines how to indicate bad indentation. Most keywords have values that are - interpreted as integers. Search the lexer sources for GetPropertyInt to see how - properties are used.

- -

There is a convention for naming properties used by lexers so that the set of properties can be found by scripts. - Property names should start with "lexer.<lexer>." or "fold.<lexer>." when they apply to one - lexer or start with "lexer." or "fold." if they apply to multiple lexers.

- -

Applications may discover the set of properties used by searching the source code of lexers for lines that contain - GetProperty and a double quoted string and extract the value of the double quoted string as the property name. - The scintilla/src/LexGen.py script does this and can be used as an example. - Documentation for the property may be located above the call as a multi-line comment starting with -
// property <property-name>

- -

SCI_GETPROPERTY(const char *key, char *value)
- Lookup a keyword:value pair using the specified key; if found, copy the value to the user-supplied - buffer and return the length (not including the terminating 0). If not found, copy an empty string - to the buffer and return 0.

- -

Note that "keyword replacement" as described in - SCI_SETPROPERTY will not be performed.

- -

If the value argument is 0 then the length that should be allocated to store the value is returned; - again, the terminating 0 is not included.

- -

SCI_GETPROPERTYEXPANDED(const char *key, char *value)
- Lookup a keyword:value pair using the specified key; if found, copy the value to the user-supplied - buffer and return the length (not including the terminating 0). If not found, copy an empty string - to the buffer and return 0.

- -

Note that "keyword replacement" as described in - SCI_SETPROPERTY will be performed.

- -

If the value argument is 0 then the length that should be allocated to store the value (including any indicated keyword replacement) - is returned; again, the terminating 0 is not included.

- -

SCI_GETPROPERTYINT(const char *key, int default)
- Lookup a keyword:value pair using the specified key; if found, interpret the value as an integer and return it. - If not found (or the value is an empty string) then return the supplied default. If the keyword:value pair is found but is not - a number, then return 0.

- -

Note that "keyword replacement" as described in - SCI_SETPROPERTY will be performed before any numeric interpretation.

- -

SCI_SETKEYWORDS(int keyWordSet, const char *keyWordList)
- You can set up to 9 lists of keywords for use by the current lexer. This was increased from 6 - at revision 1.50. keyWordSet can be 0 to 8 (actually 0 to KEYWORDSET_MAX) - and selects which keyword list to replace. keyWordList is a list of keywords - separated by spaces, tabs, "\n" or "\r" or any combination of these. - It is expected that the keywords will be composed of standard ASCII printing characters, - but there is nothing to stop you using any non-separator character codes from 1 to 255 - (except common sense).

- -

How these keywords are used is entirely up to the lexer. Some languages, such as HTML may - contain embedded languages, VBScript and JavaScript are common for HTML. For HTML, key word set - 0 is for HTML, 1 is for JavaScript and 2 is for VBScript, 3 is for Python, 4 is for PHP and 5 - is for SGML and DTD keywords. Review the lexer code to see examples of keyword list. A fully - conforming lexer sets the fourth argument of the LexerModule constructor to be a - list of strings that describe the uses of the keyword lists.

- -

Alternatively, you might use set 0 for general keywords, set 1 for keywords that cause - indentation and set 2 for keywords that cause unindentation. Yet again, you might have a simple - lexer that colours keywords and you could change languages by changing the keywords in set 0. - There is nothing to stop you building your own keyword lists into the lexer, but this means - that the lexer must be rebuilt if more keywords are added.

- -

SCI_DESCRIBEKEYWORDSETS(<unused>, char *descriptions)
- A description of all of the keyword sets separated by "\n" is returned by SCI_DESCRIBEKEYWORDSETS.

- -

SCI_GETSTYLEBITSNEEDED
- Retrieve the number of bits the current lexer needs for styling. This should normally be the argument - to SCI_SETSTYLEBITS. -

- -

Lexer Objects

- -

Lexers are programmed as objects that implement the ILexer interface and that interact - with the document they are lexing through the IDocument interface. - Previously lexers were defined by providing lexing and folding functions but creating an object - to handle the interaction of a lexer with a document allows the lexer to store state information that - can be used during lexing. For example a C++ lexer may store a set of preprocessor definitions - or variable declarations and style these depending on their role.

- -

A set of helper classes allows older lexers defined by functions to be used in Scintilla.

-

ILexer

- -
-class ILexer {
-public:
-    virtual - int SCI_METHOD - Version() -const = - 0;
-    virtual - void SCI_METHOD - Release() -= 0;
-    virtual -const -char -* -SCI_METHOD PropertyNames() - = 0;
-    virtual - int SCI_METHOD PropertyType(const char *name) = 0;
-    virtual - const char * SCI_METHOD DescribeProperty(const char *name) = 0;
-    virtual - int SCI_METHOD - PropertySet(const - char - *key, - const -char *val) - = - 0;
-    virtual -const char -* SCI_METHOD DescribeWordListSets() - = -0;
-    virtual - int SCI_METHOD - WordListSet(int - n, - const -char *wl) - = - 0;
-    virtual - void SCI_METHOD - Lex(unsigned - int - startPos, - int - lengthDoc, -int initStyle, - IDocument -*pAccess) - = -0;
-    virtual - void SCI_METHOD - Fold(unsigned - int startPos, - int - lengthDoc, -int initStyle, - IDocument -*pAccess) - = -0;
-    virtual - void -* SCI_METHOD -PrivateCall(int - operation, -void -*pointer) -= 0;
-};
-
- -

-The return values from PropertySet and WordListSet are used to indicate whether the change requires -performing lexing or folding over any of the document. It is the position at which to restart lexing and folding or -1 -if the change does not require any extra work on the document. -A simple approach is to return 0 if there is any possibility that a change requires lexing the document again while an -optimisation could be to remember where a setting first affects the document and return that position. -

- -

Release is called to destroy the lexer object.

- -

PrivateCall allows for direct communication between the -application and a lexer. An example would be where an application -maintains a single large data structure containing symbolic information -about system headers (like Windows.h) and provides this to the lexer -where it can be applied to each document. This avoids the costs of -constructing the system header information for each document. This is -invoked with the SCI_PRIVATELEXERCALL API.

- -

Fold is called with the exact range that needs folding. -Previously, lexers were called with a range that started one line before the range that -needs to be folded as this allowed fixing up the last line from the previous folding. -The new approach allows the lexer to decide whether to backtrack or to handle this -more efficiently.

- -

IDocument

- -
-class IDocument - {
-public:
-    virtual - int SCI_METHOD - Version() -const = - 0;
-    virtual - void SCI_METHOD - SetErrorStatus(int - status) - = -0;
-    virtual - int SCI_METHOD - Length() -const = - 0;
-    virtual - void SCI_METHOD - GetCharRange(char - *buffer, - int -position, -int lengthRetrieve) - const - = -0;
-    virtual - char SCI_METHOD - StyleAt(int - position) -const = - 0;
-    virtual - int SCI_METHOD - LineFromPosition(int position) - const = - 0;
-    virtual -int SCI_METHOD - LineStart(int line) - const = - 0;
-    virtual -int SCI_METHOD - GetLevel(int line) - -const = -0;
-    virtual -int SCI_METHOD - SetLevel(int - line, -int level) - = -0;
-    virtual - int SCI_METHOD - GetLineState(int - line) - const -= 0 -;
-    virtual - int SCI_METHOD - SetLineState(int - line, - int state) - = - 0;
-    virtual - void SCI_METHOD - StartStyling(int - position, - char mask) - = - 0;
-    virtual bool - SCI_METHOD - SetStyleFor(int - length, - char style) - = 0 -;
-     virtual - bool SCI_METHOD - SetStyles(int - length, -const char - *styles) - = -0;
-    virtual void - SCI_METHOD - DecorationSetCurrentIndicator(int - indicator) - = - 0;
-    virtual - void SCI_METHOD - DecorationFillRange(int - position, - int value, - int fillLength) - - = -0;
-    virtual - void SCI_METHOD - ChangeLexerState(int - start, - int end) - = - 0;
-    virtual - int SCI_METHOD - CodePage() - const -= 0 -;
-    virtual bool - SCI_METHOD - IsDBCSLeadByte(char - ch) - const = - 0;
-};
-
- -

Scintilla tries to minimize the consequences of modifying text to -only relex and redraw the line of the change where possible. Lexer -objects contain their own private extra state which can affect later -lines. For example, if the C++ lexer is greying out inactive code -segments then changing the statement #define BEOS 0 to #define - BEOS 1 may require restyling and redisplaying later parts of the - document. The lexer can call ChangeLexerState to signal to - the document that it should relex and display more.

- -

SetErrorStatus is used to notify the document of -exceptions. Exceptions should not be thrown over build boundaries as the - two sides may be built with different compilers or incompatible -exception options.

- -

The ILexer and IDocument interfaces may be -expanded in the future with extended versions (ILexer2...). - The Version method indicates which interface is -implemented and thus which methods may be called.

- -

Notifications

- -

Notifications are sent (fired) from the Scintilla control to its container when an event has - occurred that may interest the container. Notifications are sent using the - WM_NOTIFY message on Windows and the "notify" signal on GTK+. The container is - passed a SCNotification structure containing information about the event.

-
-struct NotifyHeader {   // This matches the Win32 NMHDR structure
-    void *hwndFrom;     // environment specific window handle/pointer
-    uptr_t idFrom;        // CtrlID of the window issuing the notification
-    unsigned int code;  // The SCN_* notification code
-};
-
-struct SCNotification {
-	struct Sci_NotifyHeader nmhdr;
-	int position;
-	/* SCN_STYLENEEDED, SCN_DOUBLECLICK, SCN_MODIFIED, SCN_MARGINCLICK, */
-	/* SCN_NEEDSHOWN, SCN_DWELLSTART, SCN_DWELLEND, SCN_CALLTIPCLICK, */
-	/* SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, SCN_HOTSPOTRELEASECLICK, */
-	/* SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */
-	/* SCN_USERLISTSELECTION, SCN_AUTOCSELECTION */
-
-	int ch;		/* SCN_CHARADDED, SCN_KEY */
-	int modifiers;
-	/* SCN_KEY, SCN_DOUBLECLICK, SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, */
-	/* SCN_HOTSPOTRELEASECLICK, SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */
-
-	int modificationType;	/* SCN_MODIFIED */
-	const char *text;
-	/* SCN_MODIFIED, SCN_USERLISTSELECTION, SCN_AUTOCSELECTION, SCN_URIDROPPED */
-
-	int length;		/* SCN_MODIFIED */
-	int linesAdded;	/* SCN_MODIFIED */
-	int message;	/* SCN_MACRORECORD */
-	uptr_t wParam;	/* SCN_MACRORECORD */
-	sptr_t lParam;	/* SCN_MACRORECORD */
-	int line;		/* SCN_MODIFIED */
-	int foldLevelNow;	/* SCN_MODIFIED */
-	int foldLevelPrev;	/* SCN_MODIFIED */
-	int margin;		/* SCN_MARGINCLICK */
-	int listType;	/* SCN_USERLISTSELECTION */
-	int x;			/* SCN_DWELLSTART, SCN_DWELLEND */
-	int y;		/* SCN_DWELLSTART, SCN_DWELLEND */
-	int token;		/* SCN_MODIFIED with SC_MOD_CONTAINER */
-	int annotationLinesAdded;	/* SCN_MODIFIED with SC_MOD_CHANGEANNOTATION */
-	int updated;	/* SCN_UPDATEUI */
-};
-
- -

The notification messages that your container can choose to handle and the messages - associated with them are:

- SCN_STYLENEEDED
- SCN_CHARADDED
- SCN_SAVEPOINTREACHED
- SCN_SAVEPOINTLEFT
- SCN_MODIFYATTEMPTRO
- SCN_KEY
- SCN_DOUBLECLICK
- SCN_UPDATEUI
- SCN_MODIFIED
- SCN_MACRORECORD
- SCN_MARGINCLICK
- SCN_NEEDSHOWN
- SCN_PAINTED
- SCN_USERLISTSELECTION
- SCN_URIDROPPED
- SCN_DWELLSTART
- SCN_DWELLEND
- SCN_ZOOM
- SCN_HOTSPOTCLICK
- SCN_HOTSPOTDOUBLECLICK
- SCN_HOTSPOTRELEASECLICK
- SCN_INDICATORCLICK
- SCN_INDICATORRELEASE
- SCN_CALLTIPCLICK
- SCN_AUTOCSELECTION
- SCN_AUTOCCANCELLED
- SCN_AUTOCCHARDELETED
-
- -

The following SCI_* messages are associated with these notifications:

- SCI_SETMODEVENTMASK(int eventMask)
- SCI_GETMODEVENTMASK
- SCI_SETMOUSEDWELLTIME(int milliseconds)
- SCI_GETMOUSEDWELLTIME
- SCI_SETIDENTIFIER(int identifier)
- SCI_GETIDENTIFIER
-
- -

The following additional notifications are sent using the WM_COMMAND message on - Windows and the "Command" signal on GTK+. This emulates the Windows Edit control. Only the lower - 16 bits of the control's ID is passed in these notifications.

- SCEN_CHANGE
- SCEN_SETFOCUS
- SCEN_KILLFOCUS
-
- -

SCI_SETIDENTIFIER(int identifier)
- SCI_GETIDENTIFIER
- These two messages set and get the identifier of the Scintilla instance which is included in notifications as the - idFrom field. - When an application creates multiple Scintilla widgets, this allows the source of each notification to be found. - On Windows, this value is initialised in the CreateWindow call and stored as the - GWLP_ID attribute of the window. - The value should be small, preferrably less than 16 bits, - rather than a pointer as some of the functions will only transmit 16 or 32 bits. -

- -

SCN_STYLENEEDED
- If you used SCI_SETLEXER(SCLEX_CONTAINER) to make the container act as the - lexer, you will receive this notification when Scintilla is about to display or print text that - requires styling. You are required to style the text from the line that contains the position - returned by SCI_GETENDSTYLED up to - the position passed in SCNotification.position. Symbolically, you need code of the - form:

-
-    startPos = SCI_GETENDSTYLED()
-    lineNumber = SCI_LINEFROMPOSITION(startPos);
-    startPos = SCI_POSITIONFROMLINE(lineNumber);
-    MyStyleRoutine(startPos, SCNotification.position);
-
- -

SCN_CHARADDED
- This is sent when the user types an ordinary text character (as opposed to a command - character) that is entered into the text. The container can use this to decide to display a call tip or an auto - completion list. The character is in SCNotification.ch. - This notification is sent before the character has been styled so processing that depends on - styling should instead be performed in the SCN_UPDATEUI notification.

- -

SCN_SAVEPOINTREACHED
- SCN_SAVEPOINTLEFT
- Sent to the container when the save point is entered or left, allowing the container to - display a "document dirty" indicator and change its menus.
- See also: SCI_SETSAVEPOINT, SCI_GETMODIFY

- -

SCN_MODIFYATTEMPTRO
- When in read-only mode, this notification is sent to the container if the user tries to change - the text. This can be used to check the document out of a version control system. You can set - the read-only state of a document with SCI_SETREADONLY.

- -

SCN_KEY
- Reports all keys pressed but not consumed by Scintilla. Used on GTK+ because of - some problems with keyboard focus and is not sent by the Windows version. SCNotification.ch holds the key code and - SCNotification.modifiers holds the modifiers. This notification is sent if the - modifiers include SCMOD_ALT or SCMOD_CTRL and the key code is less - than 256.

- -

SCN_DOUBLECLICK
- The mouse button was double clicked in editor. The position field is set to the text position of the - double click, the line field is set to the line of the double click, and - the modifiers field is set to the key modifiers - held down in a similar manner to SCN_KEY.

- -

SCN_UPDATEUI
- Either the text or styling of the document has changed or the selection range or scroll position has changed. - Now would be a good time to update any container UI elements that depend on document or view state. - The updated field is set to the bit set of things changed since the previous notification.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SymbolValueMeaning
SC_UPDATE_CONTENT0x01Contents, styling or markers have been changed.
SC_UPDATE_SELECTION0x02Selection has been changed.
SC_UPDATE_V_SCROLL0x04Scrolled vertically.
SC_UPDATE_H_SCROLL0x08Scrolled horizontally.
- -

SCN_MODIFIED
- This notification is sent when the text or styling of the document changes or is about to - change. You can set a mask for the notifications that are sent to the container with SCI_SETMODEVENTMASK. The - notification structure contains information about what changed, how the change occurred and - whether this changed the number of lines in the document. No modifications may be performed - while in a SCN_MODIFIED event. The SCNotification fields used - are:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FieldUsage
modificationTypeA set of flags that identify the change(s) made. See the next - table.
positionStart position of a text or styling change. Set to 0 if not used.
lengthLength of the change in cells or characters when the text or styling - changes. Set to 0 if not used.
linesAddedNumber of added lines. If negative, the number of deleted lines. Set to - 0 if not used or no lines added or deleted.
textValid for text changes, not for style changes. If we are collecting undo - information this holds a pointer to the text that is handed to the Undo system, otherwise - it is zero. For user performed SC_MOD_BEFOREDELETE the text field is 0 and - for user performed SC_MOD_BEFOREINSERT the text field points to an array of cells, - not bytes and the length is the number of cells.
lineThe line number at which a fold level or marker change occurred. This is - 0 if unused and may be -1 if more than one line changed.
foldLevelNowThe new fold level applied to the line or 0 if this field is - unused.
foldLevelPrevThe previous folding level of the line or 0 if this field is - unused.
- -

The SCNotification.modificationType field has bits set to tell you what has - been done. The SC_MOD_* bits correspond to actions. The - SC_PERFORMED_* bits tell you if the action was done by the user, or the result of - Undo or Redo of a previous action.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SymbolValueMeaningSCNotification fields
SC_MOD_INSERTTEXT0x01Text has been inserted into the document.position, length, text, linesAdded
SC_MOD_DELETETEXT0x02Text has been removed from the document.position, length, text, linesAdded
SC_MOD_CHANGESTYLE0x04A style change has occurred.position, length
SC_MOD_CHANGEFOLD0x08A folding change has occurred.line, foldLevelNow, foldLevelPrev
SC_PERFORMED_USER0x10Information: the operation was done by the user.None
SC_PERFORMED_UNDO0x20Information: this was the result of an Undo.None
SC_PERFORMED_REDO0x40Information: this was the result of a Redo.None
SC_MULTISTEPUNDOREDO0x80This is part of a multi-step Undo or Redo transaction.None
SC_LASTSTEPINUNDOREDO0x100This is the final step in an Undo or Redo transaction.None
SC_MOD_CHANGEMARKER0x200One or more markers has changed in a line.line
SC_MOD_BEFOREINSERT0x400Text is about to be inserted into the document.position, if performed by user then text in cells, length in cells
SC_MOD_BEFOREDELETE0x800Text is about to be deleted from the document.position, length
SC_MOD_CHANGEINDICATOR0x4000An indicator has been added or removed from a range of text.position, length
SC_MOD_CHANGELINESTATE0x8000A line state has changed because SCI_SETLINESTATE - was called.line
SC_MOD_LEXERSTATE0x80000The internal state of a lexer has changed over a range.position, length
SC_MOD_CHANGEMARGIN0x10000A text margin has changed.line
SC_MOD_CHANGEANNOTATION0x20000An annotation has changed.line
SC_MULTILINEUNDOREDO0x1000This is part of an Undo or Redo with multi-line changes.None
SC_STARTACTION0x2000This is set on a SC_PERFORMED_USER action when it is the - first or only step in an undo transaction. This can be used to integrate the Scintilla - undo stack with an undo stack in the container application by adding a Scintilla - action to the container's stack for the currently opened container transaction or - to open a new container transaction if there is no open container transaction. - None
SC_MOD_CONTAINER0x40000This is set on for actions that the container stored into the undo stack with - SCI_ADDUNDOACTION. - token
SC_MODEVENTMASKALL0x7FFFFThis is a mask for all valid flags. This is the default mask state set by SCI_SETMODEVENTMASK.None
- -

SCEN_CHANGE
- SCEN_CHANGE (768) is fired when the text (not the style) of the document changes. - This notification is sent using the WM_COMMAND message on Windows and the - "Command" signal on GTK+ as this is the behavior of the standard Edit control - (SCEN_CHANGE has the same value as the Windows Edit control - EN_CHANGE). No other information is sent. If you need more detailed information - use SCN_MODIFIED. You can filter the - types of changes you are notified about with SCI_SETMODEVENTMASK.

- -

SCI_SETMODEVENTMASK(int eventMask)
- SCI_GETMODEVENTMASK
- These messages set and get an event mask that determines which document change events are - notified to the container with SCN_MODIFIED and SCEN_CHANGE. For example, a container may decide to see - only notifications about changes to text and not styling changes by calling - SCI_SETMODEVENTMASK(SC_MOD_INSERTTEXT|SC_MOD_DELETETEXT).

- -

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.

- -

SCEN_SETFOCUS
- SCEN_KILLFOCUS
- SCEN_SETFOCUS (512) is fired when Scintilla receives focus and - SCEN_KILLFOCUS (256) when it loses focus. These notifications are sent using the - WM_COMMAND message on Windows and the "Command" signal on GTK+ as this is the - behavior of the standard Edit control. Unfortunately, these codes do not match the Windows Edit - notification codes EN_SETFOCUS (256) and EN_KILLFOCUS (512). It is - now too late to change the Scintilla codes as clients depend on the current values.

- -

SCN_MACRORECORD
- The SCI_STARTRECORD and SCI_STOPRECORD messages enable and - disable macro recording. When enabled, each time a recordable change occurs, the - SCN_MACRORECORD notification is sent to the container. It is up to the container - to record the action. To see the complete list of SCI_* messages that are - recordable, search the Scintilla source Editor.cxx for - Editor::NotifyMacroRecord. The fields of SCNotification set in this - notification are:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FieldUsage
messageThe SCI_* message that caused the notification.
wParamThe value of wParam in the SCI_* message.
lParamThe value of lParam in the SCI_* message.
- -

SCN_MARGINCLICK
- This notification tells the container that the mouse was clicked inside a margin that was marked as sensitive (see SCI_SETMARGINSENSITIVEN). This can be used to - perform folding or to place breakpoints. The following SCNotification fields are - used:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FieldUsage
modifiersThe appropriate combination of SCI_SHIFT, - SCI_CTRL and SCI_ALT to indicate the keys that were held down - at the time of the margin click.
positionThe position of the start of the line in the document that corresponds - to the margin click.
marginThe margin number that was clicked.
- -

SCN_NEEDSHOWN
- Scintilla has determined that a range of lines that is currently invisible should be made - visible. An example of where this may be needed is if the end of line of a contracted fold - point is deleted. This message is sent to the container in case it wants to make the line - visible in some unusual way such as making the whole document visible. Most containers will - just ensure each line in the range is visible by calling SCI_ENSUREVISIBLE. The position and - length fields of SCNotification indicate the range of the document - that should be made visible. The container code will be similar to the following code - skeleton:

-
-firstLine = SCI_LINEFROMPOSITION(scn.position)
-lastLine = SCI_LINEFROMPOSITION(scn.position+scn.length-1)
-for line = lineStart to lineEnd do SCI_ENSUREVISIBLE(line) next
-
- -

SCN_PAINTED
- Painting has just been done. Useful when you want to update some other widgets based on a - change in Scintilla, but want to have the paint occur first to appear more responsive. There is - no other information in SCNotification.

- -

SCN_USERLISTSELECTION
- The user has selected an item in a user list. The - SCNotification fields used are:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FieldUsage
listTypeThis is set to the listType parameter from the SCI_USERLISTSHOW message that - initiated the list.
textThe text of the selection.
positionThe position the list was displayed at.
-
- - -

SCN_URIDROPPED
- Only on the GTK+ version. Indicates that the user has dragged a URI such as a file name or Web - address onto Scintilla. The container could interpret this as a request to open the file. The - text field of SCNotification points at the URI text.

- -

SCN_DWELLSTART
- SCN_DWELLEND
- SCN_DWELLSTART is generated when the user keeps the mouse in one position for the - dwell period (see SCI_SETMOUSEDWELLTIME). SCN_DWELLEND is - generated after a SCN_DWELLSTART and the mouse is moved or other activity such as - key press indicates the dwell is over. Both notifications set the same fields in - SCNotification:

- - - - - - - - - - - - - - - - - - - - - - - -
FieldUsage
positionThis is the nearest position in the document to the position where the - mouse pointer was lingering.
x, yWhere the pointer lingered. The position field is set to - SCI_POSITIONFROMPOINTCLOSE(x, y).
-
- -

SCI_SETMOUSEDWELLTIME(int milliseconds)
- SCI_GETMOUSEDWELLTIME
- These two messages set and get the time the mouse must sit still, in milliseconds, to generate - a SCN_DWELLSTART notification. If - set to SC_TIME_FOREVER, the default, no dwell events are generated.

- -

SCN_ZOOM
- This notification is generated when the user zooms the display using the keyboard or the - SCI_SETZOOM method is called. This - notification can be used to recalculate positions, such as the width of the line number margin - to maintain sizes in terms of characters rather than pixels. SCNotification has no - additional information.

- -

- SCN_HOTSPOTCLICK
- SCN_HOTSPOTDOUBLECLICK
- SCN_HOTSPOTRELEASECLICK
- These notifications are generated when the user clicks or double clicks on - text that is in a style with the hotspot attribute set. - This notification can be used to link to variable definitions or web pages. - The position field is set the text position of the click or - double click and the modifiers field set to the key modifiers - held down in a similar manner to SCN_KEY. - Only the state of the Ctrl key is reported for SCN_HOTSPOTRELEASECLICK.

- -

- SCN_INDICATORCLICK
- SCN_INDICATORRELEASE
- These notifications are generated when the user clicks or releases the mouse on - text that has an indicator. - The position field is set the text position of the click or - double click and the modifiers field set to the key modifiers - held down in a similar manner to SCN_KEY.

- -

SCN_CALLTIPCLICK
- This notification is generated when the user clicks on a calltip. - This notification can be used to display the next function prototype when a - function name is overloaded with different arguments. - The position field is set to 1 if the click is in an up arrow, - 2 if in a down arrow, and 0 if elsewhere.

- -

SCN_AUTOCSELECTION
- The user has selected an item in an autocompletion list. The - notification is sent before the selection is inserted. Automatic insertion can be cancelled by sending a - SCI_AUTOCCANCEL message - before returning from the notification. The SCNotification fields used are:

- - - - - - - - - - - - - - - - - - - - - - -
FieldUsage
positionThe start position of the word being completed.
textThe text of the selection.
- -

SCN_AUTOCCANCELLED
- The user has cancelled an autocompletion list. - There is no other information in SCNotification.

- -

SCN_AUTOCCHARDELETED
- The user deleted a character while autocompletion list was active. - There is no other information in SCNotification.

- -

Images

- -

Two formats are supported for images used in margin markers and autocompletion lists, RGBA and XPM.

- -

RGBA

- -

The RGBA format allows translucency with an alpha - value for each pixel. It is simpler than - XPM and more capable.

- -

The data is a sequence of 4 byte pixel values starting with the pixels for the top line, with the - leftmost pixel first, then continuing with the pixels for subsequent lines. There is no gap between - lines for alignment reasons.

- -

Each pixel consists of, in order, a red byte, a green byte, a blue byte and an alpha byte. - The colour bytes are not premultiplied by the alpha value. That is, a fully red pixel that is - 25% opaque will be [FF, 00, 00, 3F]

- -

Since the RGBA pixel data does not include any size information the - width and height must previously been set with the - SCI_RGBAIMAGESETWIDTH and - SCI_RGBAIMAGESETHEIGHT messages.

- -

GUI platforms often include functions for reading image file formats like PNG into memory - in the RGBA form or a similar form. - If there is no suitable platform support, the LodePNG and picoPNG libraries are small libraries - for loading and decoding PNG files available under a BSD-style license.

- -

RGBA format is supported on Windows, GTK+ and OS X Cocoa. - It is not supported on OS X Carbon.

- -

XPM

- -

The XPM format is - described here. - Scintilla is only able to handle XPM pixmaps that use one character per pixel with no named colours. - There may be a completely transparent colour named "None".

-

There are two forms of data structure used for XPM images, the first "lines form" format is well suited - to embedding an image inside C source code and the "text form" is suited to reading from a file. - In the lines form, an array of strings is used with the first string indicating the dimensions and number of colours - used. This is followed by a string for each colour and that section is followed by the image with one string per line. - The text form contains the same data as one null terminated block formatted as C source code starting - with a "/* XPM */" comment to mark the format.

-

Either format may be used with Scintilla APIs with the bytes at the location pointed to examined - to determine which format: if the bytes start with "/* XPM */" then it is treated as text form, - otherwise it is treated as lines form.

- -

XPM format is supported on on all platforms.

- -

GTK+

-

On GTK+, the following functions create a Scintilla widget, communicate with it and allow - resources to be released after all Scintilla widgets have been destroyed.

- GtkWidget *scintilla_new()
- void scintilla_set_id(ScintillaObject *sci, uptr_t id)
- sptr_t scintilla_send_message(ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam)
- void scintilla_release_resources()
-
- -

GtkWidget *scintilla_new()
- Create a new Scintilla widget. The returned pointer can be added to a container and displayed in the same way as other - widgets.

- -

void scintilla_set_id(ScintillaObject *sci, uptr_t id)
- Set the control ID which will be used in the idFrom field of the NotifyHeader structure of all - notifications for this instance. - This is equivalent to SCI_SETIDENTIFIER.

- -

sptr_t scintilla_send_message(ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam)
- The main entry point allows sending any of the messages described in this document.

- -

void scintilla_release_resources()
- Call this to free any remaining resources after all the Scintilla widgets have been destroyed.

- -

Deprecated messages and notifications

- -

The following messages are currently supported to emulate existing Windows controls, but - they will be removed in future versions of Scintilla. If you use these messages you should - replace them with the Scintilla equivalent.

-
-WM_GETTEXT(int length, char *text)
-WM_SETTEXT(<unused>, const char *text)
-EM_GETLINE(int line, char *text)
-EM_REPLACESEL(<unused>, const char *text)
-EM_SETREADONLY
-EM_GETTEXTRANGE(<unused>, TEXTRANGE *tr)
-WM_CUT
-WM_COPY
-WM_PASTE
-WM_CLEAR
-WM_UNDO
-EM_CANUNDO
-EM_EMPTYUNDOBUFFER
-WM_GETTEXTLENGTH
-EM_GETFIRSTVISIBLELINE
-EM_GETLINECOUNT
-EM_GETMODIFY
-EM_SETMODIFY(bool isModified)
-EM_GETRECT(RECT *rect)
-EM_GETSEL(int *start, int *end)
-EM_EXGETSEL(<unused>, CHARRANGE *cr)
-EM_SETSEL(int start, int end)
-EM_EXSETSEL(<unused>, CHARRANGE *cr)
-EM_GETSELTEXT(<unused>, char *text)
-EM_LINEFROMCHAR(int position)
-EM_EXLINEFROMCHAR(int position)
-EM_LINEINDEX(int line)
-EM_LINELENGTH(int position)
-EM_SCROLL(int line)
-EM_LINESCROLL(int column, int line)
-EM_SCROLLCARET()
-EM_CANPASTE
-EM_CHARFROMPOS(<unused>, POINT *location)
-EM_POSFROMCHAR(int position, POINT *location)
-EM_SELECTIONTYPE
-EM_HIDESELECTION(bool hide)
-EM_FINDTEXT(int flags, FINDTEXTEX *ft)
-EM_FINDTEXTEX(int flags, FINDTEXTEX *ft)
-EM_GETMARGINS
-EM_SETMARGINS(EC_LEFTMARGIN or EC_RIGHTMARGIN or EC_USEFONTINFO, int val)
-EM_FORMATRANGE
-
- -

The following are features that are only included if you define - INCLUDE_DEPRECATED_FEATURES in Scintilla.h. To ensure future - compatibility you should change them as indicated.

- -

SC_CP_DBCS Deprecated
- This was used to set a DBCS (Double Byte Character Set) mode on GTK+. - An explicit DBCS code page should be used when calling SCI_SETCODEPAGE

- -

SCI_SETUSEPALETTE(bool allowPaletteUse) Deprecated
- SCI_GETUSEPALETTE Deprecated
- Scintilla no longer supports palette mode. The last version to support palettes was 2.29. - Any calls to these methods should be removed.

- -

Edit messages never supported by Scintilla

-
-EM_GETWORDBREAKPROC EM_GETWORDBREAKPROCEX
-EM_SETWORDBREAKPROC EM_SETWORDBREAKPROCEX
-EM_GETWORDWRAPMODE EM_SETWORDWRAPMODE
-EM_LIMITTEXT EM_EXLIMITTEXT
-EM_SETRECT EM_SETRECTNP
-EM_FMTLINES
-EM_GETHANDLE EM_SETHANDLE
-EM_GETPASSWORDCHAR EM_SETPASSWORDCHAR
-EM_SETTABSTOPS
-EM_FINDWORDBREAK
-EM_GETCHARFORMAT EM_SETCHARFORMAT
-EM_GETOLEINTERFACE EM_SETOLEINTERFACE
-EM_SETOLECALLBACK
-EM_GETPARAFORMAT EM_SETPARAFORMAT
-EM_PASTESPECIAL
-EM_REQUESTRESIZE
-EM_GETBKGNDCOLOR EM_SETBKGNDCOLOR
-EM_STREAMIN EM_STREAMOUT
-EM_GETIMECOLOR EM_SETIMECOLOR
-EM_GETIMEOPTIONS EM_SETIMEOPTIONS
-EM_GETOPTIONS EM_SETOPTIONS
-EM_GETPUNCTUATION EM_SETPUNCTUATION
-EM_GETTHUMB
-EM_GETEVENTMASK
-EM_SETEVENTMASK
-EM_DISPLAYBAND
-EM_SETTARGETDEVICE
-
- -

Scintilla tries to be a superset of the standard windows Edit and RichEdit controls wherever - that makes sense. As it is not intended for use in a word processor, some edit messages can not - be sensibly handled. Unsupported messages have no effect.

- -

Building Scintilla

- -

To build Scintilla or SciTE, see the README file present in both the Scintilla and SciTE - directories. For Windows, GCC 3.2, Borland C++ or Microsoft Visual Studio .NET can be used - for building. There is a make file for building Scintilla but not SciTE with Visual C++ 6 at - scintilla/win32/scintilla_vc6.mak. For GTK+, GCC 3.1 should be used. GTK+ 1.2x and 2.0x are - supported. The version of GTK+ installed should be detected automatically. - When both GTK+ 1 and GTK+ 2 are present, building for GTK+ 1.x requires defining GTK1 - on the command line.

- -

Static linking

- -

On Windows, Scintilla is normally used as a dynamic library as a .DLL file. If you want to - link Scintilla directly into your application .EXE or .DLL file, then the - STATIC_BUILD preprocessor symbol should be defined and - Scintilla_RegisterClasses called. STATIC_BUILD prevents compiling the - DllMain function which will conflict with any DllMain defined in your - code. Scintilla_RegisterClasses takes the HINSTANCE of your - application and ensures that the "Scintilla" window class is registered.

- -

Ensuring lexers are linked into Scintilla

- -

Depending on the compiler and linker used, the lexers may be stripped out. This is most - often caused when building a static library. To ensure the lexers are linked in, the - Scintilla_LinkLexers() function may be called.

- -

Changing set of lexers

- -

To change the set of lexers in Scintilla, add and remove lexer source files - (Lex*.cxx) from the scintilla/src directory and run the - src/LexGen.py script from the src directory to update the make files - and KeyWords.cxx. LexGen.py requires Python 2.1 or later. If you do - not have access to Python, you can hand edit KeyWords.cxx in a simple-minded way, - following the patterns of other lexers. The important thing is to include - LINK_LEXER(lmMyLexer); to correspond with the LexerModule - lmMyLexer(...); in your lexer source code.

- -

Building with an alternative Regular Expression implementation

- -

A simple interface provides support for switching the Regular Expressions engine at - compile time. You must implement RegexSearchBase for your chosen engine, - look at the built-in implementation BuiltinRegex to see how this is done. - You then need to implement the factory method CreateRegexSearch - to create an instance of your class. You must disable the built-in implementation by defining - SCI_OWNREGEX.

- - - - + + + + + + + + + + Scintilla Documentation + + + + + + + + + + + +
Scintilla iconScintilla
+ +

Scintilla Documentation

+ +

Last edited 24/January/2012 NH

+ +

There is an overview of the internal design of + Scintilla.
+ Some notes on using Scintilla.
+ How to use the Scintilla Edit Control on Windows.
+ A simple sample using Scintilla from + C++ on Windows.
+ A simple sample using Scintilla from + Visual Basic.
+ Bait is a tiny sample using Scintilla + on GTK+.
+ A detailed description of how to write a lexer, including a + discussion of folding.
+ + How to implement a lexer in the container.
+ + How to implement folding.
+ The coding style used in Scintilla and SciTE is + worth following if you want to contribute code to Scintilla but is not compulsory.

+ +

Introduction

+ +

The Windows version of Scintilla is a Windows Control. As such, its primary programming + interface is through Windows messages. Early versions of Scintilla emulated much of the API + defined by the standard Windows Edit and RichEdit controls but those APIs are now deprecated in + favour of Scintilla's own, more consistent API. In addition to messages performing the actions + of a normal Edit control, Scintilla allows control of syntax styling, folding, markers, autocompletion + and call tips.

+ +

The GTK+ version also uses messages in a similar way to the Windows version. This is + different to normal GTK+ practice but made it easier to implement rapidly.

+ +

Scintilla does not properly support right-to-left languages like Arabic and Hebrew. + While text in these languages may appear correct, it is not possible to interact with this text + as is normal with other editing components.

+ +

This documentation describes the individual messages and notifications used by Scintilla. It + does not describe how to link them together to form a useful editor. For now, the best way to + work out how to develop using Scintilla is to see how SciTE uses it. SciTE exercises most of + Scintilla's facilities.

+ +

In the descriptions that follow, the messages are described as function calls with zero, one + or two arguments. These two arguments are the standard wParam and + lParam familiar to Windows programmers. These parameters are integers that + are large enough to hold pointers, and the return value is also an integer large enough to contain a + pointer. + Although the commands only use the + arguments described, because all messages have two arguments whether Scintilla uses them or + not, it is strongly recommended that any unused arguments are set to 0. This allows future + enhancement of messages without the risk of breaking existing code. Common argument types + are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
boolArguments expect the values 0 for false and 1 for + true.
intArguments are 32-bit signed integers.
const char *Arguments point at text that is being passed to Scintilla but not modified. The text + may be zero terminated or another argument may specify the character count, the + description will make this clear.
char *Arguments point at text buffers that Scintilla will fill with text. In some cases, + another argument will tell Scintilla the buffer size. In others, you must make sure that + the buffer is big enough to hold the requested text. If a NULL pointer (0) is passed + then, for SCI_* calls, the length that should be allocated is returned.
colourColours are set using the RGB format (Red, Green, Blue). The intensity of each colour + is set in the range 0 to 255. If you have three such intensities, they are combined as: + red | (green << 8) | (blue << 16). If you set all intensities to 255, the + colour is white. If you set all intensities to 0, the colour is black. When you set a + colour, you are making a request. What you will get depends on the capabilities of the + system and the current screen mode.
alphaTranslucency is set using an alpha value. + Alpha ranges from 0 (SC_ALPHA_TRANSPARENT) which is completely transparent to + 255 (SC_ALPHA_OPAQUE) which is opaque. The value 256 (SC_ALPHA_NOALPHA) + is opaque and uses code that is not alpha-aware and may be faster. Not all platforms support + translucency and only some Scintilla features implement translucency. + The default alpha value for most features is SC_ALPHA_NOALPHA.
<unused>This is an unused argument. Setting it to 0 will ensure compatibility with future + enhancements.
+ +

Contents

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
o Text retrieval and + modificationo Searching and replacingo Overtype
o Cut, copy and pasteo Error handlingo Undo and Redo
o Selection and informationo Multiple Selection and Virtual Spaceo Scrolling and automatic + scrolling
o White spaceo Cursoro Mouse capture
o Line endingso Stylingo Style definition
o Caret, selection, and hotspot styleso Marginso Annotations
o Other settingso Brace highlightingo Tabs and Indentation + Guides
o Markerso Indicatorso Autocompletion
o User listso Call tipso Keyboard commands
o Key bindingso Popup edit menuo Macro recording
o Printingo Direct accesso Multiple views
o Background loading and savingo Foldingo Line wrapping
o Zoomingo Long lineso Lexer
o Lexer objectso Notificationso Images
o GTK+o Deprecated messageso Edit messages never + supported by Scintilla
o Building Scintilla
+ +

Messages with names of the form SCI_SETxxxxx often have a companion + SCI_GETxxxxx. To save tedious repetition, if the SCI_GETxxxxx message + returns the value set by the SCI_SETxxxxx message, the SET routine is + described and the GET routine is left to your imagination.

+ +

Text retrieval and modification

+ +

Each byte in a Scintilla document is followed by an associated byte of styling + information. The combination of a character byte and a style byte is called a cell. Style bytes + are interpreted an index into an array of styles. + Style bytes may be split into an index and a set of indicator bits + but this use is discouraged and indicators should now use + SCI_INDICATORFILLRANGE + and related calls. + The default split is with the index in the low 5 bits and 3 high bits as indicators. This allows 32 fundamental styles, which is enough for most + languages, and three independent indicators so that, for example, syntax errors, deprecated + names and bad indentation could all be displayed at once. The number of bits used for styles + can be altered with SCI_SETSTYLEBITS up to a maximum of 8 bits. + The remaining bits can be used for indicators.

+ +

In this document, 'character' normally refers to a byte even when multi-byte characters are used. + Lengths measure the numbers of bytes, not the amount of characters in those bytes.

+ +

Positions within the Scintilla document refer to a character or the gap before that + character. The first character in a document is 0, the second 1 and so on. If a document + contains nLen characters, the last character is numbered nLen-1. + The caret exists between character positions and can be located from before the first character (0) + to after the last character (nLen).

+ +

There are places where the caret can not go where two character bytes make up one character. + This occurs when a DBCS character from a language like Japanese is included in the document or + when line ends are marked with the CP/M standard of a carriage return followed by a line feed. + The INVALID_POSITION constant (-1) represents an invalid position within the + document.

+ +

All lines of text in Scintilla are the same height, and this height is calculated from the + largest font in any current style. This restriction is for performance; if lines differed in + height then calculations involving positioning of text would require the text to be styled + first.

+ SCI_GETTEXT(int length, char *text)
+ SCI_SETTEXT(<unused>, const char *text)
+ SCI_SETSAVEPOINT
+ SCI_GETLINE(int line, char *text)
+ SCI_REPLACESEL(<unused>, const char + *text)
+ SCI_SETREADONLY(bool readOnly)
+ SCI_GETREADONLY
+ SCI_GETTEXTRANGE(<unused>, Sci_TextRange + *tr)
+ SCI_ALLOCATE(int bytes, <unused>)
+ SCI_ADDTEXT(int length, const char *s)
+ SCI_ADDSTYLEDTEXT(int length, cell *s)
+ SCI_APPENDTEXT(int length, const char *s)
+ SCI_INSERTTEXT(int pos, const char *text)
+ SCI_CLEARALL
+ SCI_CLEARDOCUMENTSTYLE
+ SCI_GETCHARAT(int position)
+ SCI_GETSTYLEAT(int position)
+ SCI_GETSTYLEDTEXT(<unused>, Sci_TextRange + *tr)
+ SCI_SETSTYLEBITS(int bits)
+ SCI_GETSTYLEBITS
+ SCI_TARGETASUTF8(<unused>, char *s)
+ SCI_ENCODEDFROMUTF8(const char *utf8, char *encoded)
+ SCI_SETLENGTHFORENCODE(int bytes)
+
+ +

SCI_GETTEXT(int length, char *text)
+ This returns length-1 characters of text from the start of the document plus one + terminating 0 character. To collect all the text in a document, use SCI_GETLENGTH + to get the number of characters in the document (nLen), allocate a character + buffer of length nLen+1 bytes, then call SCI_GETTEXT(nLen+1, char + *text). If the text argument is 0 then the length that should be allocated to store the + entire document is returned. + If you then save the text, you should use SCI_SETSAVEPOINT to mark + the text as unmodified.

+ +

See also: SCI_GETSELTEXT, SCI_GETCURLINE, SCI_GETLINE, SCI_GETSTYLEDTEXT, SCI_GETTEXTRANGE

+ +

SCI_SETTEXT(<unused>, const char *text)
+ This replaces all the text in the document with the zero terminated text string you pass + in.

+ +

SCI_SETSAVEPOINT
+ This message tells Scintilla that the current state of the document is unmodified. This is + usually done when the file is saved or loaded, hence the name "save point". As Scintilla + performs undo and redo operations, it notifies the container that it has entered or left the + save point with SCN_SAVEPOINTREACHED and SCN_SAVEPOINTLEFT notification messages, allowing the container to know if the file + should be considered dirty or not.

+ +

See also: SCI_EMPTYUNDOBUFFER, SCI_GETMODIFY

+ +

SCI_GETLINE(int line, char *text)
+ This fills the buffer defined by text with the contents of the nominated line (lines start at + 0). The buffer is not terminated by a 0 character. It is up to you to make sure that the buffer + is long enough for the text, use SCI_LINELENGTH(int line). The returned value is the + number of characters copied to the buffer. The returned text includes any end of line + characters. If you ask for a line number outside the range of lines in the document, 0 + characters are copied. If the text argument is 0 then the length that should be allocated + to store the entire line is returned.

+ +

See also: SCI_GETCURLINE, SCI_GETSELTEXT, SCI_GETTEXTRANGE, SCI_GETSTYLEDTEXT, SCI_GETTEXT

+ +

SCI_REPLACESEL(<unused>, const char *text)
+ The currently selected text between the anchor + and the current position is replaced by the 0 terminated text string. If the anchor and + current position are the same, the text is inserted at the caret position. The caret is + positioned after the inserted text and the caret is scrolled into view.

+ +

SCI_SETREADONLY(bool readOnly)
+ SCI_GETREADONLY
+ These messages set and get the read-only flag for the document. If you mark a document as read + only, attempts to modify the text cause the SCN_MODIFYATTEMPTRO notification.

+ +

SCI_GETTEXTRANGE(<unused>, Sci_TextRange *tr)
+ This collects the text between the positions cpMin and cpMax and + copies it to lpstrText (see struct Sci_TextRange in + Scintilla.h). If cpMax is -1, text is returned to the end of the + document. The text is 0 terminated, so you must supply a buffer that is at least 1 character + longer than the number of characters you wish to read. The return value is the length of the + returned text not including the terminating 0.

+ +

See also: SCI_GETSELTEXT, SCI_GETLINE, SCI_GETCURLINE, SCI_GETSTYLEDTEXT, SCI_GETTEXT

+ +

SCI_GETSTYLEDTEXT(<unused>, Sci_TextRange *tr)
+ This collects styled text into a buffer using two bytes for each cell, with the character at + the lower address of each pair and the style byte at the upper address. Characters between the + positions cpMin and cpMax are copied to lpstrText (see + struct Sci_TextRange in Scintilla.h). Two 0 bytes are added to the end of + the text, so the buffer that lpstrText points at must be at least + 2*(cpMax-cpMin)+2 bytes long. No check is made for sensible values of + cpMin or cpMax. Positions outside the document return character codes + and style bytes of 0.

+ +

See also: SCI_GETSELTEXT, SCI_GETLINE, SCI_GETCURLINE, SCI_GETTEXTRANGE, SCI_GETTEXT

+ +

SCI_ALLOCATE(int bytes, <unused>)
+ Allocate a document buffer large enough to store a given number of bytes. + The document will not be made smaller than its current contents.

+ +

SCI_ADDTEXT(int length, const char *s)
+ This inserts the first length characters from the string s + at the current position. This will include any 0's in the string that you might have expected + to stop the insert operation. The current position is set at the end of the inserted text, + but it is not scrolled into view.

+ +

SCI_ADDSTYLEDTEXT(int length, cell *s)
+ This behaves just like SCI_ADDTEXT, but inserts styled text.

+ +

SCI_APPENDTEXT(int length, const char *s)
+ This adds the first length characters from the string s to the end + of the document. This will include any 0's in the string that you might have expected to stop + the operation. The current selection is not changed and the new text is not scrolled into + view.

+ +

SCI_INSERTTEXT(int pos, const char *text)
+ This inserts the zero terminated text string at position pos or at + the current position if pos is -1. If the current position is after the insertion point + then it is moved along with its surrounding text but no scrolling is performed.

+ +

SCI_CLEARALL
+ Unless the document is read-only, this deletes all the text.

+ +

SCI_CLEARDOCUMENTSTYLE
+ When wanting to completely restyle the document, for example after choosing a lexer, the + SCI_CLEARDOCUMENTSTYLE can be used to clear all styling information and reset the + folding state.

+ +

SCI_GETCHARAT(int pos)
+ This returns the character at pos in the document or 0 if pos is + negative or past the end of the document.

+ +

SCI_GETSTYLEAT(int pos)
+ This returns the style at pos in the document, or 0 if pos is + negative or past the end of the document.

+ +

SCI_SETSTYLEBITS(int bits)
+ SCI_GETSTYLEBITS
+ This pair of routines sets and reads back the number of bits in each cell to use for styling, + to a maximum of 8 style bits. The remaining bits can be used as indicators. The standard + setting is SCI_SETSTYLEBITS(5). + The number of styling bits needed by the current lexer can be found with + SCI_GETSTYLEBITSNEEDED.

+ +

Sci_TextRange and Sci_CharacterRange
+ These structures are defined to be exactly the same shape as the Win32 TEXTRANGE + and CHARRANGE, so that older code that treats Scintilla as a RichEdit will + work.

+
+struct Sci_CharacterRange {
+    long cpMin;
+    long cpMax;
+};
+
+struct Sci_TextRange {
+    struct Sci_CharacterRange chrg;
+    char *lpstrText;
+};
+
+ +

GTK+-specific: Access to encoded text

+ +

SCI_TARGETASUTF8(<unused>, char *s)
+ This method retrieves the value of the target encoded as UTF-8 which is the default + encoding of GTK+ so is useful for retrieving text for use in other parts of the user interface, + such as find and replace dialogs. The length of the encoded text in bytes is returned. +

+ +

SCI_ENCODEDFROMUTF8(const char *utf8, char *encoded)
+ SCI_SETLENGTHFORENCODE(int bytes)
+ SCI_ENCODEDFROMUTF8 converts a UTF-8 string into the document's + encoding which is useful for taking the results of a find dialog, for example, and receiving + a string of bytes that can be searched for in the document. Since the text can contain nul bytes, + the SCI_SETLENGTHFORENCODE method can be used to set the + length that will be converted. If set to -1, the length is determined by finding a nul byte. + The length of the converted string is returned. +

+ + +

Searching

+

+ There are methods to search for text and for regular expressions. The regular expression support + is limited and should only be used for simple cases and initial development. A different regular expression + library can be integrated into Scintilla + or can be called from the container using direct access to the buffer contents through + SCI_GETCHARACTERPOINTER. +

+ SCI_FINDTEXT(int flags, Sci_TextToFind + *ttf)
+ SCI_SEARCHANCHOR
+ SCI_SEARCHNEXT(int searchFlags, const char + *text)
+ SCI_SEARCHPREV(int searchFlags, const char + *text)
+ Search and replace using the + target
+
+ +

searchFlags
+ Several of the search routines use flag options, which include a simple regular expression + search. Combine the flag options by adding them:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SCFIND_MATCHCASEA match only occurs with text that matches the case of the search string.
SCFIND_WHOLEWORDA match only occurs if the characters before and after are not word characters.
SCFIND_WORDSTARTA match only occurs if the character before is not a word character.
SCFIND_REGEXPThe search string should be interpreted as a regular expression.
SCFIND_POSIXTreat regular expression in a more POSIX compatible manner + by interpreting bare ( and ) for tagged sections rather than \( and \).
+ +

You can + search backwards to find the previous occurrence of a search string by setting the end of the + search range before the start.

+ +

In a regular expression, special characters interpreted are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
.Matches any character
\(This marks the start of a region for tagging a match.
\)This marks the end of a tagged region.
\nWhere n is 1 through 9 refers to the first through ninth tagged region + when replacing. For example, if the search string was Fred\([1-9]\)XXX and + the replace string was Sam\1YYY, when applied to Fred2XXX this + would generate Sam2YYY.
\<This matches the start of a word using Scintilla's definitions of words.
\>This matches the end of a word using Scintilla's definition of words.
\xThis allows you to use a character x that would otherwise have a special meaning. For + example, \[ would be interpreted as [ and not as the start of a character set.
[...]This indicates a set of characters, for example, [abc] means any of the characters a, + b or c. You can also use ranges, for example [a-z] for any lower case character.
[^...]The complement of the characters in the set. For example, [^A-Za-z] means any + character except an alphabetic character.
^This matches the start of a line (unless used inside a set, see above).
$This matches the end of a line.
*This matches 0 or more times. For example, Sa*m matches Sm, + Sam, Saam, Saaam and so on.
+This matches 1 or more times. For example, Sa+m matches + Sam, Saam, Saaam and so on.
+ +

Regular expressions will only match ranges within a single line, never matching over multiple lines.

+ +

SCI_FINDTEXT(int searchFlags, Sci_TextToFind *ttf)
+ This message searches for text in the document. It does not use or move the current selection. + The searchFlags argument controls the + search type, which includes regular expression searches.

+ +

The Sci_TextToFind structure is defined in Scintilla.h; set + chrg.cpMin and chrg.cpMax with the range of positions in the document + to search. You can search backwards by + setting chrg.cpMax less than chrg.cpMin. + Set the lpstrText member of Sci_TextToFind to point at a zero terminated + text string holding the search pattern. If your language makes the use of Sci_TextToFind + difficult, you should consider using SCI_SEARCHINTARGET instead.

+ +

The return value is -1 if the search fails or the position of the start of the found text if + it succeeds. The chrgText.cpMin and chrgText.cpMax members of + Sci_TextToFind are filled in with the start and end positions of the found text.

+ +

See also: SCI_SEARCHINTARGET

+ +

Sci_TextToFind
+ This structure is defined to have exactly the same shape as the Win32 structure + FINDTEXTEX for old code that treated Scintilla as a RichEdit control.

+
+struct Sci_TextToFind {
+    struct Sci_CharacterRange chrg;     // range to search
+    char *lpstrText;                // the search pattern (zero terminated)
+    struct Sci_CharacterRange chrgText; // returned as position of matching text
+};
+
+ +

SCI_SEARCHANCHOR
+ SCI_SEARCHNEXT(int searchFlags, const char *text)
+ SCI_SEARCHPREV(int searchFlags, const char *text)
+ These messages provide relocatable search support. This allows multiple incremental + interactive searches to be macro recorded while still setting the selection to found text so + the find/select operation is self-contained. These three messages send SCN_MACRORECORD notifications if macro recording is enabled.

+ +

SCI_SEARCHANCHOR sets the search start point used by + SCI_SEARCHNEXT and SCI_SEARCHPREV to the start of the current + selection, that is, the end of the selection that is nearer to the start of the document. You + should always call this before calling either of SCI_SEARCHNEXT or + SCI_SEARCHPREV.

+ +

SCI_SEARCHNEXT and SCI_SEARCHPREV search for the next and previous + occurrence of the zero terminated search string pointed at by text. The search is modified by + the searchFlags.

+ +

The return value is -1 if nothing is found, otherwise the return value is the start position + of the matching text. The selection is updated to show the matched text, but is not scrolled + into view.

+ +

See also: SCI_SEARCHINTARGET, + SCI_FINDTEXT

+ +

Search and replace using the target

+ +

Using SCI_REPLACESEL, + modifications cause scrolling and other visible changes, which may take some time and cause + unwanted display updates. If performing many changes, such as a replace all command, the target + can be used instead. First, set the target, ie. the range to be replaced. Then call + SCI_REPLACETARGET or SCI_REPLACETARGETRE.

+ +

Searching can be performed within the target range with SCI_SEARCHINTARGET, + which uses a counted string to allow searching for null characters. It returns the + position of the start of the matching text range or -1 for failure, in which case the target is not moved. The flags used by + SCI_SEARCHINTARGET such as SCFIND_MATCHCASE, + SCFIND_WHOLEWORD, SCFIND_WORDSTART, and SCFIND_REGEXP + can be set with SCI_SETSEARCHFLAGS. SCI_SEARCHINTARGET may be simpler + for some clients to use than SCI_FINDTEXT, as that requires using a pointer to a + structure.

+ SCI_SETTARGETSTART(int pos)
+ SCI_GETTARGETSTART
+ SCI_SETTARGETEND(int pos)
+ SCI_GETTARGETEND
+ SCI_TARGETFROMSELECTION
+ SCI_SETSEARCHFLAGS(int searchFlags)
+ SCI_GETSEARCHFLAGS
+ SCI_SEARCHINTARGET(int length, const char + *text)
+ SCI_REPLACETARGET(int length, const char + *text)
+ SCI_REPLACETARGETRE(int length, const char + *text)
+ SCI_GETTAG(int tagNumber, char *tagValue)
+
+ +

SCI_SETTARGETSTART(int pos)
+ SCI_GETTARGETSTART
+ SCI_SETTARGETEND(int pos)
+ SCI_GETTARGETEND
+ These functions set and return the start and end of the target. When searching in non-regular + expression mode, you can set start greater than end to find the last matching text in the + target rather than the first matching text. The target is also set by a successful + SCI_SEARCHINTARGET.

+ +

SCI_TARGETFROMSELECTION
+ Set the target start and end to the start and end positions of the selection.

+ +

SCI_SETSEARCHFLAGS(int searchFlags)
+ SCI_GETSEARCHFLAGS
+ These get and set the searchFlags used by + SCI_SEARCHINTARGET. There are several option flags including a simple regular + expression search.

+ +

SCI_SEARCHINTARGET(int length, const char *text)
+ This searches for the first occurrence of a text string in the target defined by + SCI_SETTARGETSTART and SCI_SETTARGETEND. The text string is not zero + terminated; the size is set by length. The search is modified by the search flags + set by SCI_SETSEARCHFLAGS. If the search succeeds, the target is set to the found + text and the return value is the position of the start of the matching text. If the search + fails, the result is -1.

+ +

SCI_REPLACETARGET(int length, const char *text)
+ If length is -1, text is a zero terminated string, otherwise + length sets the number of character to replace the target with. + After replacement, the target range refers to the replacement text. + The return value + is the length of the replacement string.
+ Note that the recommended way to delete text in the document is to set the target to the text to be removed, + and to perform a replace target with an empty string.

+ +

SCI_REPLACETARGETRE(int length, const char *text)
+ This replaces the target using regular expressions. If length is -1, + text is a zero terminated string, otherwise length is the number of + characters to use. The replacement string is formed from the text string with any sequences of + \1 through \9 replaced by tagged matches from the most recent regular + expression search. + After replacement, the target range refers to the replacement text. + The return value is the length of the replacement string.

+ +

SCI_GETTAG(int tagNumber, char *tagValue)
+ Discover what text was matched by tagged expressions in a regular expression search. + This is useful if the application wants to interpret the replacement string itself.

+ +

See also: SCI_FINDTEXT

+ +

Overtype

+ +

SCI_SETOVERTYPE(bool overType)
+ SCI_GETOVERTYPE
+ When overtype is enabled, each typed character replaces the character to the right of the text + caret. When overtype is disabled, characters are inserted at the caret. + SCI_GETOVERTYPE returns TRUE (1) if overtyping is active, otherwise + FALSE (0) will be returned. Use SCI_SETOVERTYPE to set the overtype + mode.

+ +

Cut, copy and paste

+ + SCI_CUT
+ SCI_COPY
+ SCI_PASTE
+ SCI_CLEAR
+ SCI_CANPASTE
+ SCI_COPYRANGE(int start, int end)
+ SCI_COPYTEXT(int length, + const char *text)
+ SCI_COPYALLOWLINE
+ SCI_SETPASTECONVERTENDINGS(bool convert)
+ SCI_GETPASTECONVERTENDINGS
+
+ +

SCI_CUT
+ SCI_COPY
+ SCI_PASTE
+ SCI_CLEAR
+ SCI_CANPASTE
+ SCI_COPYALLOWLINE
+ These commands perform the standard tasks of cutting and copying data to the clipboard, + pasting from the clipboard into the document, and clearing the document. + SCI_CANPASTE returns non-zero if the document isn't read-only and if the selection + doesn't contain protected text. If you need a "can copy" or "can cut", use + SCI_GETSELECTIONSTART()-SCI_GETSELECTIONEND(), which will be non-zero if you can + copy or cut to the clipboard.

+ +

GTK+ does not really support SCI_CANPASTE and always returns TRUE + unless the document is read-only.

+ +

On X, the clipboard is asynchronous and may require several messages between + the destination and source applications. Data from SCI_PASTE will not arrive in the + document immediately.

+ +

SCI_COPYALLOWLINE works the same as SCI_COPY except that if the + selection is empty then the current line is copied. On Windows, an extra "MSDEVLineSelect" marker + is added to the clipboard which is then used in SCI_PASTE to paste + the whole line before the current line.

+ + SCI_COPYRANGE(int start, int end)
+ SCI_COPYTEXT(int length, const char *text)
+

SCI_COPYRANGE copies a range of text from the document to + the system clipboard and SCI_COPYTEXT copies a supplied piece of + text to the system clipboard.

+ +

SCI_SETPASTECONVERTENDINGS(bool convert)
+ SCI_GETPASTECONVERTENDINGS
+ If this property is set then when text is pasted any line ends are converted to match the document's + end of line mode as set with + SCI_SETEOLMODE. + Currently only changeable on Windows. On GTK+ pasted text is always converted.

+ +

Error handling

+ +

SCI_SETSTATUS(int status)
+ SCI_GETSTATUS
+ If an error occurs, Scintilla may set an internal error number that can be retrieved with + SCI_GETSTATUS. + To clear the error status call SCI_SETSTATUS(0). + The currently defined statuses are: +

+ + + + + + + + + + + + + + + + + + + + + + +
SC_STATUS_OK0No failures
SC_STATUS_FAILURE1Generic failure
SC_STATUS_BADALLOC2Memory is exhausted
+ +

Undo and Redo

+ +

Scintilla has multiple level undo and redo. It will continue to collect undoable actions + until memory runs out. Scintilla saves actions that change the document. Scintilla does not + save caret and selection movements, view scrolling and the like. Sequences of typing or + deleting are compressed into single transactions to make it easier to undo and redo at a sensible + level of detail. Sequences of actions can be combined into transactions that are undone as a unit. + These sequences occur between SCI_BEGINUNDOACTION and + SCI_ENDUNDOACTION messages. These transactions can be nested and only the top-level + sequences are undone as units.

+ SCI_UNDO
+ SCI_CANUNDO
+ SCI_EMPTYUNDOBUFFER
+ SCI_REDO
+ SCI_CANREDO
+ SCI_SETUNDOCOLLECTION(bool + collectUndo)
+ SCI_GETUNDOCOLLECTION
+ SCI_BEGINUNDOACTION
+ SCI_ENDUNDOACTION
+ SCI_ADDUNDOACTION(int token, int flags)
+
+ +

SCI_UNDO
+ SCI_CANUNDO
+ SCI_UNDO undoes one action, or if the undo buffer has reached a + SCI_ENDUNDOACTION point, all the actions back to the corresponding + SCI_BEGINUNDOACTION.

+ +

SCI_CANUNDO returns 0 if there is nothing to undo, and 1 if there is. You would + typically use the result of this message to enable/disable the Edit menu Undo command.

+ +

SCI_REDO
+ SCI_CANREDO
+ SCI_REDO undoes the effect of the last SCI_UNDO operation.

+ +

SCI_CANREDO returns 0 if there is no action to redo and 1 if there are undo + actions to redo. You could typically use the result of this message to enable/disable the Edit + menu Redo command.

+ +

SCI_EMPTYUNDOBUFFER
+ This command tells Scintilla to forget any saved undo or redo history. It also sets the save + point to the start of the undo buffer, so the document will appear to be unmodified. This does + not cause the SCN_SAVEPOINTREACHED notification to be sent to the + container.

+ +

See also: SCI_SETSAVEPOINT

+ +

SCI_SETUNDOCOLLECTION(bool collectUndo)
+ SCI_GETUNDOCOLLECTION
+ You can control whether Scintilla collects undo information with + SCI_SETUNDOCOLLECTION. Pass in true (1) to collect information and + false (0) to stop collecting. If you stop collection, you should also use + SCI_EMPTYUNDOBUFFER to avoid the undo buffer being unsynchronized with the data in + the buffer.

+ +

You might wish to turn off saving undo information if you use the Scintilla to store text + generated by a program (a Log view) or in a display window where text is often deleted and + regenerated.

+ +

SCI_BEGINUNDOACTION
+ SCI_ENDUNDOACTION
+ Send these two messages to Scintilla to mark the beginning and end of a set of operations that + you want to undo all as one operation but that you have to generate as several operations. + Alternatively, you can use these to mark a set of operations that you do not want to have + combined with the preceding or following operations if they are undone.

+ +

SCI_ADDUNDOACTION(int token, int flags)
+ The container can add its own actions into the undo stack by calling + SCI_ADDUNDOACTION and an SCN_MODIFIED + notification will be sent to the container with the + SC_MOD_CONTAINER + flag when it is time to undo (SC_PERFORMED_UNDO) or + redo (SC_PERFORMED_REDO) the action. The token argument supplied is + returned in the token field of the notification.

+

For example, if the container wanted to allow undo and redo of a 'toggle bookmark' command then + it could call SCI_ADDUNDOACTION(line, 0) each time the command is performed. + Then when it receives a notification to undo or redo it toggles a bookmark on the line given by + the token field. If there are different types of commands or parameters that need to be stored into the undo + stack then the container should maintain a stack of its own for the document and use the current + position in that stack as the argument to SCI_ADDUNDOACTION(line). + SCI_ADDUNDOACTION commands are not combined together + into a single undo transaction unless grouped with SCI_BEGINUNDOACTION + and SCI_ENDUNDOACTION.

+ +

The flags argument can be UNDO_MAY_COALESCE (1) if the container action may be + coalesced along with any insertion and deletion actions into a single compound action, otherwise 0. + Coalescing treats coalescible container actions as transparent so will still only group together insertions that + look like typing or deletions that look like multiple uses of the Backspace or Delete keys. +

+

Selection and information

+ +

Scintilla maintains a selection that stretches between two points, the anchor and the + current position. If the anchor and the current position are the same, there is no selected + text. Positions in the document range from 0 (before the first character), to the document size + (after the last character). If you use messages, there is nothing to stop you setting a + position that is in the middle of a CRLF pair, or in the middle of a 2 byte character. However, + keyboard commands will not move the caret into such positions.

+ SCI_GETTEXTLENGTH
+ SCI_GETLENGTH
+ SCI_GETLINECOUNT
+ SCI_SETFIRSTVISIBLELINE(int lineDisplay)
+ SCI_GETFIRSTVISIBLELINE
+ SCI_LINESONSCREEN
+ SCI_GETMODIFY
+ SCI_SETSEL(int anchorPos, int currentPos)
+ SCI_GOTOPOS(int position)
+ SCI_GOTOLINE(int line)
+ SCI_SETCURRENTPOS(int position)
+ SCI_GETCURRENTPOS
+ SCI_SETANCHOR(int position)
+ SCI_GETANCHOR
+ SCI_SETSELECTIONSTART(int position)
+ SCI_GETSELECTIONSTART
+ SCI_SETSELECTIONEND(int position)
+ SCI_GETSELECTIONEND
+ SCI_SETEMPTYSELECTION(int pos)
+ SCI_SELECTALL
+ SCI_LINEFROMPOSITION(int position)
+ SCI_POSITIONFROMLINE(int line)
+ SCI_GETLINEENDPOSITION(int line)
+ SCI_LINELENGTH(int line)
+ SCI_GETCOLUMN(int position)
+ SCI_FINDCOLUMN(int line, int column)
+ SCI_POSITIONFROMPOINT(int x, int y)
+ SCI_POSITIONFROMPOINTCLOSE(int x, int + y)
+ SCI_CHARPOSITIONFROMPOINT(int x, int y)
+ SCI_CHARPOSITIONFROMPOINTCLOSE(int x, int + y)
+ SCI_POINTXFROMPOSITION(<unused>, int + position)
+ SCI_POINTYFROMPOSITION(<unused>, int + position)
+ SCI_HIDESELECTION(bool hide)
+ SCI_GETSELTEXT(<unused>, char *text)
+ SCI_GETCURLINE(int textLen, char *text)
+ SCI_SELECTIONISRECTANGLE
+ SCI_SETSELECTIONMODE(int mode)
+ SCI_GETSELECTIONMODE
+ SCI_GETLINESELSTARTPOSITION(int line)
+ SCI_GETLINESELENDPOSITION(int line)
+ SCI_MOVECARETINSIDEVIEW
+ SCI_WORDENDPOSITION(int position, bool + onlyWordCharacters)
+ SCI_WORDSTARTPOSITION(int position, bool + onlyWordCharacters)
+ SCI_POSITIONBEFORE(int position)
+ SCI_POSITIONAFTER(int position)
+ SCI_COUNTCHARACTERS(int startPos, int endPos)
+ SCI_TEXTWIDTH(int styleNumber, const char *text)
+ SCI_TEXTHEIGHT(int line)
+ SCI_CHOOSECARETX
+ SCI_MOVESELECTEDLINESUP
+ SCI_MOVESELECTEDLINESDOWN
+
+ +

SCI_GETTEXTLENGTH
+ SCI_GETLENGTH
+ Both these messages return the length of the document in bytes.

+ +

SCI_GETLINECOUNT
+ This returns the number of lines in the document. An empty document contains 1 line. A + document holding only an end of line sequence has 2 lines.

+ +

SCI_SETFIRSTVISIBLELINE(int lineDisplay)
+ SCI_GETFIRSTVISIBLELINE
+ These messages retrieve and set the line number of the first visible line in the Scintilla view. The first line + in the document is numbered 0. The value is a visible line rather than a document line.

+ +

SCI_LINESONSCREEN
+ This returns the number of complete lines visible on the screen. With a constant line height, + this is the vertical space available divided by the line separation. Unless you arrange to size + your window to an integral number of lines, there may be a partial line visible at the bottom + of the view.

+ +

SCI_GETMODIFY
+ This returns non-zero if the document is modified and 0 if it is unmodified. The modified + status of a document is determined by the undo position relative to the save point. The save + point is set by SCI_SETSAVEPOINT, + usually when you have saved data to a file.

+ +

If you need to be notified when the document becomes modified, Scintilla notifies the + container that it has entered or left the save point with the SCN_SAVEPOINTREACHED and SCN_SAVEPOINTLEFT notification messages.

+ +

SCI_SETSEL(int anchorPos, int currentPos)
+ This message sets both the anchor and the current position. If currentPos is + negative, it means the end of the document. If anchorPos is negative, it means + remove any selection (i.e. set the anchor to the same position as currentPos). The + caret is scrolled into view after this operation.

+ +

SCI_GOTOPOS(int pos)
+ This removes any selection, sets the caret at pos and scrolls the view to make + the caret visible, if necessary. It is equivalent to + SCI_SETSEL(pos, pos). The anchor position is set the same as the current + position.

+ +

SCI_GOTOLINE(int line)
+ This removes any selection and sets the caret at the start of line number line + and scrolls the view (if needed) to make it visible. The anchor position is set the same as the + current position. If line is outside the lines in the document (first line is 0), + the line set is the first or last.

+ +

SCI_SETCURRENTPOS(int pos)
+ This sets the current position and creates a selection between the anchor and the current + position. The caret is not scrolled into view.

+ +

See also: SCI_SCROLLCARET

+ +

SCI_GETCURRENTPOS
+ This returns the current position.

+ +

SCI_SETANCHOR(int pos)
+ This sets the anchor position and creates a selection between the anchor position and the + current position. The caret is not scrolled into view.

+ +

See also: SCI_SCROLLCARET

+ +

SCI_GETANCHOR
+ This returns the current anchor position.

+ +

SCI_SETSELECTIONSTART(int pos)
+ SCI_SETSELECTIONEND(int pos)
+ These set the selection based on the assumption that the anchor position is less than the + current position. They do not make the caret visible. The table shows the positions of the + anchor and the current position after using these messages.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ anchorcurrent
SCI_SETSELECTIONSTARTposMax(pos, current)
SCI_SETSELECTIONENDMin(anchor, pos)pos
+ +

See also: SCI_SCROLLCARET

+ +

SCI_GETSELECTIONSTART
+ SCI_GETSELECTIONEND
+ These return the start and end of the selection without regard to which end is the current + position and which is the anchor. SCI_GETSELECTIONSTART returns the smaller of the + current position or the anchor position. SCI_GETSELECTIONEND returns the larger of + the two values.

+ +

SCI_SETEMPTYSELECTION(int pos)
+ This removes any selection and sets the caret at pos. The caret is not scrolled into view.

+ +

SCI_SELECTALL
+ This selects all the text in the document. The current position is not scrolled into view.

+ +

SCI_LINEFROMPOSITION(int pos)
+ This message returns the line that contains the position pos in the document. The + return value is 0 if pos <= 0. The return value is the last line if + pos is beyond the end of the document.

+ +

SCI_POSITIONFROMLINE(int line)
+ This returns the document position that corresponds with the start of the line. If + line is negative, the position of the line holding the start of the selection is + returned. If line is greater than the lines in the document, the return value is + -1. If line is equal to the number of lines in the document (i.e. 1 line past the + last line), the return value is the end of the document.

+ +

SCI_GETLINEENDPOSITION(int line)
+ This returns the position at the end of the line, before any line end characters. If line + is the last line in the document (which does not have any end of line characters), the result is the size of the + document. If line is negative or line >= SCI_GETLINECOUNT(), the result is undefined.

+ +

SCI_LINELENGTH(int line)
+ This returns the length of the line, including any line end characters. If line + is negative or beyond the last line in the document, the result is 0. If you want the length of + the line not including any end of line characters, use SCI_GETLINEENDPOSITION(line) - SCI_POSITIONFROMLINE(line).

+ +

SCI_GETSELTEXT(<unused>, char *text)
+ This copies the currently selected text and a terminating 0 byte to the text + buffer. The buffer size should be determined by calling with a NULL pointer for the text argument + SCI_GETSELTEXT(0,0). + This allows for rectangular and discontiguous selections as well as simple selections. + See Multiple Selection for information on + how multiple and rectangular selections and virtual space are copied.

+ +

See also: SCI_GETCURLINE, + SCI_GETLINE, + SCI_GETTEXT, + SCI_GETSTYLEDTEXT, + SCI_GETTEXTRANGE +

+ +

SCI_GETCURLINE(int textLen, char *text)
+ This retrieves the text of the line containing the caret and returns the position within the + line of the caret. Pass in char* text pointing at a buffer large enough to hold + the text you wish to retrieve and a terminating 0 character. + Set textLen to the + length of the buffer which must be at least 1 to hold the terminating 0 character. + If the text argument is 0 then the length that should be allocated + to store the entire current line is returned.

+ +

See also: SCI_GETSELTEXT, SCI_GETLINE, SCI_GETTEXT, SCI_GETSTYLEDTEXT, SCI_GETTEXTRANGE

+ +

SCI_SELECTIONISRECTANGLE
+ This returns 1 if the current selection is in rectangle mode, 0 if not.

+ +

SCI_SETSELECTIONMODE(int mode)
+ SCI_GETSELECTIONMODE
+ The two functions set and get the selection mode, which can be + stream (SC_SEL_STREAM=0) or + rectangular (SC_SEL_RECTANGLE=1) or + by lines (SC_SEL_LINES=2) + or thin rectangular (SC_SEL_THIN=3). + When set in these modes, regular caret moves will extend or reduce the selection, + until the mode is cancelled by a call with same value or with SCI_CANCEL. + The get function returns the current mode even if the selection was made by mouse + or with regular extended moves. + SC_SEL_THIN is the mode after a rectangular selection has been typed into and ensures + that no characters are selected.

+ +

SCI_GETLINESELSTARTPOSITION(int line)
+ SCI_GETLINESELENDPOSITION(int line)
+ Retrieve the position of the start and end of the selection at the given line with + INVALID_POSITION returned if no selection on this line.

+ +

SCI_MOVECARETINSIDEVIEW
+ If the caret is off the top or bottom of the view, it is moved to the nearest line that is + visible to its current position. Any selection is lost.

+ +

SCI_WORDENDPOSITION(int position, bool + onlyWordCharacters)
+ SCI_WORDSTARTPOSITION(int position, bool + onlyWordCharacters)
+ These messages return the start and end of words using the same definition of words as used + internally within Scintilla. You can set your own list of characters that count as words with + SCI_SETWORDCHARS. The position + sets the start or the search, which is forwards when searching for the end and backwards when + searching for the start.

+ +

Set onlyWordCharacters to true (1) to stop searching at the first + non-word character in the search direction. If onlyWordCharacters is + false (0), the first character in the search direction sets the type of the search + as word or non-word and the search stops at the first non-matching character. Searches are also + terminated by the start or end of the document.

+ +

If "w" represents word characters and "." represents non-word characters and "|" represents + the position and true or false is the state of + onlyWordCharacters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Initial stateend, trueend, falsestart, truestart, false
..ww..|..ww....ww..|..ww....ww....|ww....ww..|..ww....ww|....ww..
....ww|ww........wwww|........wwww|........|wwww........|wwww....
..ww|....ww....ww|....ww....ww....|ww....|ww....ww....|ww....ww..
..ww....|ww....ww....ww|....ww....ww|....ww....|ww....ww|....ww..
+ +

SCI_POSITIONBEFORE(int position)
+ SCI_POSITIONAFTER(int position)
+ These messages return the position before and after another position + in the document taking into account the current code page. The minimum + position returned is 0 and the maximum is the last position in the document. + If called with a position within a multi byte character will return the position + of the start/end of that character.

+ +

SCI_COUNTCHARACTERS(int startPos, int endPos)
+ Returns the number of whole characters between two positions..

+ +

SCI_TEXTWIDTH(int styleNumber, const char *text)
+ This returns the pixel width of a string drawn in the given styleNumber which can + be used, for example, to decide how wide to make the line number margin in order to display a + given number of numerals.

+ +

SCI_TEXTHEIGHT(int line)
+ This returns the height in pixels of a particular line. Currently all lines are the same + height.

+ +

SCI_GETCOLUMN(int pos)
+ This message returns the column number of a position pos within the document + taking the width of tabs into account. This returns the column number of the last tab on the + line before pos, plus the number of characters between the last tab and + pos. If there are no tab characters on the line, the return value is the number of + characters up to the position on the line. In both cases, double byte characters count as a + single character. This is probably only useful with monospaced fonts.

+ +

SCI_FINDCOLUMN(int line, int column)
+ This message returns the position of a column on a line + taking the width of tabs into account. It treats a multi-byte character as a single column. + Column numbers, like lines start at 0.

+ +

SCI_POSITIONFROMPOINT(int x, int y)
+ SCI_POSITIONFROMPOINTCLOSE(int x, int y)
+ SCI_POSITIONFROMPOINT finds the closest character position to a point and + SCI_POSITIONFROMPOINTCLOSE is similar but returns -1 if the point is outside the + window or not close to any characters.

+ +

SCI_CHARPOSITIONFROMPOINT(int x, int y)
+ SCI_CHARPOSITIONFROMPOINTCLOSE(int x, int y)
+ SCI_CHARPOSITIONFROMPOINT finds the closest character to a point and + SCI_CHARPOSITIONFROMPOINTCLOSE is similar but returns -1 if the point is outside the + window or not close to any characters. This is similar to the previous methods but finds characters rather than + inter-character positions.

+ +

SCI_POINTXFROMPOSITION(<unused>, int pos)
+ SCI_POINTYFROMPOSITION(<unused>, int pos)
+ These messages return the x and y display pixel location of text at position pos + in the document.

+ +

SCI_HIDESELECTION(bool hide)
+ The normal state is to make the selection visible by drawing it as set by SCI_SETSELFORE and SCI_SETSELBACK. However, if you hide the selection, it + is drawn as normal text.

+ +

SCI_CHOOSECARETX
+ Scintilla remembers the x value of the last position horizontally moved to explicitly by the + user and this value is then used when moving vertically such as by using the up and down keys. + This message sets the current x position of the caret as the remembered value.

+ +

SCI_MOVESELECTEDLINESUP
+ Move the selected lines up one line, shifting the line above after the selection. + The selection will be automatically extended to the beginning of the selection's first line and the end of the seletion's last line. + If nothing was selected, the line the cursor is currently at will be selected.

+ +

SCI_MOVESELECTEDLINESDOWN
+ Move the selected lines down one line, shifting the line below before the selection. + The selection will be automatically extended to the beginning of the selection's first line and the end of the seletion's last line. + If nothing was selected, the line the cursor is currently at will be selected.

+ +

Multiple Selection and Virtual Space

+ + + SCI_SETMULTIPLESELECTION(bool multipleSelection)
+ SCI_GETMULTIPLESELECTION
+ SCI_SETADDITIONALSELECTIONTYPING(bool additionalSelectionTyping)
+ SCI_GETADDITIONALSELECTIONTYPING
+ SCI_SETMULTIPASTE(int multiPaste)
+ SCI_GETMULTIPASTE
+ SCI_SETVIRTUALSPACEOPTIONS(int virtualSpaceOptions)
+ SCI_GETVIRTUALSPACEOPTIONS
+ SCI_SETRECTANGULARSELECTIONMODIFIER(int modifier)
+ SCI_GETRECTANGULARSELECTIONMODIFIER
+
+ + SCI_GETSELECTIONS
+ SCI_CLEARSELECTIONS
+ SCI_SETSELECTION(int caret, int anchor)
+ SCI_ADDSELECTION(int caret, int anchor)
+ SCI_SETMAINSELECTION(int selection)
+ SCI_GETMAINSELECTION
+
+ + SCI_SETSELECTIONNCARET(int selection, int pos)
+ SCI_GETSELECTIONNCARET(int selection)
+ SCI_SETSELECTIONNCARETVIRTUALSPACE(int selection, int space)
+ SCI_GETSELECTIONNCARETVIRTUALSPACE(int selection)
+ SCI_SETSELECTIONNANCHOR(int selection, int posAnchor)
+ SCI_GETSELECTIONNANCHOR(int selection)
+ SCI_SETSELECTIONNANCHORVIRTUALSPACE(int selection, int space)
+ SCI_GETSELECTIONNANCHORVIRTUALSPACE(int selection)
+ SCI_SETSELECTIONNSTART(int selection, int pos)
+ SCI_GETSELECTIONNSTART(int selection)
+ SCI_SETSELECTIONNEND(int selection, int pos)
+ SCI_GETSELECTIONNEND(int selection)
+
+ + SCI_SETRECTANGULARSELECTIONCARET(int pos)
+ SCI_GETRECTANGULARSELECTIONCARET
+ SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE(int space)
+ SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE
+ SCI_SETRECTANGULARSELECTIONANCHOR(int posAnchor)
+ SCI_GETRECTANGULARSELECTIONANCHOR
+ SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE(int space)
+ SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE
+
+ + SCI_SETADDITIONALSELALPHA(int alpha)
+ SCI_GETADDITIONALSELALPHA
+ SCI_SETADDITIONALSELFORE(int colour)
+ SCI_SETADDITIONALSELBACK(int colour)
+ SCI_SETADDITIONALCARETFORE(int colour)
+ SCI_GETADDITIONALCARETFORE
+ SCI_SETADDITIONALCARETSBLINK(bool additionalCaretsBlink)
+ SCI_GETADDITIONALCARETSBLINK
+ SCI_SETADDITIONALCARETSVISIBLE(bool additionalCaretsVisible)
+ SCI_GETADDITIONALCARETSVISIBLE
+
+ + SCI_SWAPMAINANCHORCARET
+ SCI_ROTATESELECTION
+
+ +

+ There may be multiple selections active at one time. + More selections are made by holding down the Ctrl key while dragging with the mouse. + The most recent selection is the main selection and determines which part of the document is shown automatically. + Any selection apart from the main selection is called an additional selection. + The calls in the previous section operate on the main selection. + There is always at least one selection. +

+ +

+ Rectangular selections are handled as multiple selections although the original rectangular range is remembered so that + subsequent operations may be handled differently for rectangular selections. For example, pasting a rectangular selection + places each piece in a vertical column. +

+ +

+ Virtual space is space beyond the end of each line. The caret may be moved into virtual space but no real space will be + added to the document until there is some text typed or some other text insertion command is used. +

+ +

When discontiguous selections are copied to the clipboard, each selection is added to the clipboard text + in order with no delimiting characters. + For rectangular selections the document's line end is added after each line's text. Rectangular selections + are always copied from top line to bottom, not in the in order of selection.Virtual space is not copied.

+ +

+ SCI_SETMULTIPLESELECTION(bool multipleSelection)
+ SCI_GETMULTIPLESELECTION
+ Enable or disable multiple selection. When multiple selection is disabled, it is not possible to select + multiple ranges by holding down the Ctrl key while dragging with the mouse.

+ +

+ SCI_SETADDITIONALSELECTIONTYPING(bool additionalSelectionTyping)
+ SCI_GETADDITIONALSELECTIONTYPING
+ Whether typing, backspace, or delete works with multiple selections simultaneously.

+ +

+ SCI_SETMULTIPASTE(int multiPaste)
+ SCI_GETMULTIPASTE
+ When pasting into multiple selections, the pasted text can go into just the main selection with SC_MULTIPASTE_ONCE=0 + or into each selection with SC_MULTIPASTE_EACH=1. SC_MULTIPASTE_ONCE is the default.

+ +

+ SCI_SETVIRTUALSPACEOPTIONS(int virtualSpace)
+ SCI_GETVIRTUALSPACEOPTIONS
+ Virtual space can be enabled or disabled for rectangular selections or in other circumstances or in both. + There are two bit flags SCVS_RECTANGULARSELECTION=1 and + SCVS_USERACCESSIBLE=2 which can be set independently. + SCVS_NONE=0, the default, disables all use of virtual space.

+ +

+ SCI_SETRECTANGULARSELECTIONMODIFIER(int modifier)
+ SCI_GETRECTANGULARSELECTIONMODIFIER
+ On GTK+, the key used to indicate that a rectangular selection should be created when combined with a mouse drag can be set. + The three possible values are SCMOD_CTRL=2 (default), SCMOD_ALT=4 or SCMOD_SUPER=8. + Since SCMOD_ALT is often already used by a window manager, the window manager may need configuring to allow this choice. + SCMOD_SUPER is often a system dependent modifier key such as the Left Windows key on a Windows keyboard or the + Command key on a Mac.

+ +

+ SCI_GETSELECTIONS
+ Return the number of selections currently active.

+ +

+ SCI_CLEARSELECTIONS
+ Set a single empty selection at 0 as the only selection.

+ +

+ SCI_SETSELECTION(int caret, int anchor)
+ Set a single selection from anchor to caret as the only selection.

+ +

+ SCI_ADDSELECTION(int caret, int anchor)
+ Add a new selection from anchor to caret as the main selection retaining all other + selections as additional selections. + Since there is always at least one selection, to set a list of selections, the first selection should be + added with SCI_SETSELECTION and later selections added with SCI_ADDSELECTION

+ +

+ SCI_SETMAINSELECTION(int selection)
+ SCI_GETMAINSELECTION
+ One of the selections is the main selection which is used to determine what range of text is automatically visible. + The main selection may be displayed in different colours or with a differently styled caret. + Only an already existing selection can be made main.

+ +

+ SCI_SETSELECTIONNCARET(int selection, int pos)
+ SCI_GETSELECTIONNCARET(int selection)
+ SCI_SETSELECTIONNCARETVIRTUALSPACE(int selection, int space)
+ SCI_GETSELECTIONNCARETVIRTUALSPACE(int selection)
+ SCI_SETSELECTIONNANCHOR(int selection, int posAnchor)
+ SCI_GETSELECTIONNANCHOR(int selection)
+ SCI_SETSELECTIONNANCHORVIRTUALSPACE(int selection, int space)
+ SCI_GETSELECTIONNANCHORVIRTUALSPACE(int selection)
+ Set or query the position and amount of virtual space for the caret and anchor of each already existing selection.

+ +

+ SCI_SETSELECTIONNSTART(int selection, int pos)
+ SCI_GETSELECTIONNSTART(int selection)
+ SCI_SETSELECTIONNEND(int selection, int pos)
+ SCI_GETSELECTIONNEND(int selection)
+ Set or query the start and end position of each already existing selection. + Mostly of use to query each range for its text.

+ +

+ SCI_SETRECTANGULARSELECTIONCARET(int pos)
+ SCI_GETRECTANGULARSELECTIONCARET
+ SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE(int space)
+ SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE
+ SCI_SETRECTANGULARSELECTIONANCHOR(int posAnchor)
+ SCI_GETRECTANGULARSELECTIONANCHOR
+ SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE(int space)
+ SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE
+ Set or query the position and amount of virtual space for the caret and anchor of the rectangular selection. + After setting the rectangular selection, this is broken down into multiple selections, one for each line.

+ +

+ SCI_SETADDITIONALSELALPHA(int alpha)
+ SCI_GETADDITIONALSELALPHA
+ SCI_SETADDITIONALSELFORE(int colour)
+ SCI_SETADDITIONALSELBACK(int colour)
+ Modify the appearence of additional selections so that they can be differentiated from the main selection which has its appearence set with + SCI_SETSELALPHA, + SCI_GETSELALPHA, + SCI_SETSELFORE, and + SCI_SETSELBACK.

+ +

+ SCI_SETADDITIONALCARETFORE(int colour)
+ SCI_GETADDITIONALCARETFORE
+ SCI_SETADDITIONALCARETSBLINK(bool additionalCaretsBlink)
+ SCI_GETADDITIONALCARETSBLINK
+ Modify the appearence of additional carets so that they can be differentiated from the main caret which has its appearence set with + SCI_SETCARETFORE, + SCI_GETCARETFORE, + SCI_SETCARETPERIOD, and + SCI_GETCARETPERIOD.

+ +

+ SCI_SETADDITIONALCARETSVISIBLE(bool additionalCaretsVisible)
+ SCI_GETADDITIONALCARETSVISIBLE
+ Determine whether to show additional carets (defaults to true).

+ +

+ SCI_SWAPMAINANCHORCARET
+ SCI_ROTATESELECTION
+ These commands may be assigned to keys to make it possible to manipulate multiple selections. + SCI_SWAPMAINANCHORCARET moves the caret to the opposite end of the main selection. + SCI_ROTATESELECTION makes the next selection be the main selection. +

+ +

Scrolling and automatic scrolling

+ SCI_LINESCROLL(int column, int line)
+ SCI_SCROLLCARET
+ SCI_SETXCARETPOLICY(int caretPolicy, int + caretSlop)
+ SCI_SETYCARETPOLICY(int caretPolicy, int + caretSlop)
+ SCI_SETVISIBLEPOLICY(int caretPolicy, int + caretSlop)
+ SCI_SETHSCROLLBAR(bool visible)
+ SCI_GETHSCROLLBAR
+ SCI_SETVSCROLLBAR(bool visible)
+ SCI_GETVSCROLLBAR
+ SCI_GETXOFFSET
+ SCI_SETXOFFSET(int xOffset)
+ SCI_SETSCROLLWIDTH(int pixelWidth)
+ SCI_GETSCROLLWIDTH
+ SCI_SETSCROLLWIDTHTRACKING(bool tracking)
+ SCI_GETSCROLLWIDTHTRACKING
+ SCI_SETENDATLASTLINE(bool + endAtLastLine)
+ SCI_GETENDATLASTLINE
+
+ +

SCI_LINESCROLL(int column, int line)
+ This will attempt to scroll the display by the number of columns and lines that you specify. + Positive line values increase the line number at the top of the screen (i.e. they move the text + upwards as far as the user is concerned), Negative line values do the reverse.

+ +

The column measure is the width of a space in the default style. Positive values increase + the column at the left edge of the view (i.e. they move the text leftwards as far as the user + is concerned). Negative values do the reverse.

+ +

See also: SCI_SETXOFFSET

+ +

SCI_SCROLLCARET
+ If the current position (this is the caret if there is no selection) is not visible, the view + is scrolled to make it visible according to the current caret policy.

+ +

SCI_SETXCARETPOLICY(int caretPolicy, int caretSlop)
+ SCI_SETYCARETPOLICY(int caretPolicy, int caretSlop)
+ These set the caret policy. The value of caretPolicy is a combination of + CARET_SLOP, CARET_STRICT, CARET_JUMPS and + CARET_EVEN.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
CARET_SLOPIf set, we can define a slop value: caretSlop. This value defines an + unwanted zone (UZ) where the caret is... unwanted. This zone is defined as a number of + pixels near the vertical margins, and as a number of lines near the horizontal margins. + By keeping the caret away from the edges, it is seen within its context. This makes it + likely that the identifier that the caret is on can be completely seen, and that the + current line is seen with some of the lines following it, which are often dependent on + that line.
CARET_STRICTIf set, the policy set by CARET_SLOP is enforced... strictly. The caret + is centred on the display if caretSlop is not set, and cannot go in the UZ + if caretSlop is set.
CARET_JUMPSIf set, the display is moved more energetically so the caret can move in the same + direction longer before the policy is applied again. '3UZ' notation is used to indicate + three time the size of the UZ as a distance to the margin.
CARET_EVENIf not set, instead of having symmetrical UZs, the left and bottom UZs are extended + up to right and top UZs respectively. This way, we favour the displaying of useful + information: the beginning of lines, where most code reside, and the lines after the + caret, for example, the body of a function.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
slopstrictjumpsevenCaret can go to the marginOn reaching limit (going out of visibility
+ or going into the UZ) display is...
0000Yesmoved to put caret on top/on right
0001Yesmoved by one position
0010Yesmoved to put caret on top/on right
0011Yescentred on the caret
01-0Caret is always on top/on right of display-
01-1No, caret is always centred-
1000Yesmoved to put caret out of the asymmetrical UZ
1001Yesmoved to put caret out of the UZ
1010Yesmoved to put caret at 3UZ of the top or right margin
1011Yesmoved to put caret at 3UZ of the margin
11-0Caret is always at UZ of top/right margin-
1101No, kept out of UZmoved by one position
1110No, kept out of UZmoved to put caret at 3UZ of the margin
+ +

SCI_SETVISIBLEPOLICY(int caretPolicy, int caretSlop)
+ This determines how the vertical positioning is determined when SCI_ENSUREVISIBLEENFORCEPOLICY is + called. It takes VISIBLE_SLOP and VISIBLE_STRICT flags for the policy + parameter. It is similar in operation to SCI_SETYCARETPOLICY(int caretPolicy, int + caretSlop).

+ +

SCI_SETHSCROLLBAR(bool visible)
+ SCI_GETHSCROLLBAR
+ The horizontal scroll bar is only displayed if it is needed for the assumed width. + If you never wish to see it, call + SCI_SETHSCROLLBAR(0). Use SCI_SETHSCROLLBAR(1) to enable it again. + SCI_GETHSCROLLBAR returns the current state. The default state is to display it + when needed.

+

See also: SCI_SETSCROLLWIDTH.

+ +

SCI_SETVSCROLLBAR(bool visible)
+ SCI_GETVSCROLLBAR
+ By default, the vertical scroll bar is always displayed when required. You can choose to hide + or show it with SCI_SETVSCROLLBAR and get the current state with + SCI_GETVSCROLLBAR.

+ +

SCI_SETXOFFSET(int xOffset)
+ SCI_GETXOFFSET
+ The xOffset is the horizontal scroll position in pixels of the start of the text + view. A value of 0 is the normal position with the first text column visible at the left of the + view.

+ +

See also: SCI_LINESCROLL

+ +

SCI_SETSCROLLWIDTH(int pixelWidth)
+ SCI_GETSCROLLWIDTH
+ For performance, Scintilla does not measure the display width of the document to determine + the properties of the horizontal scroll bar. Instead, an assumed width is used. + These messages set and get the document width in pixels assumed by Scintilla. + The default value is 2000. + To ensure the width of the currently visible lines can be scrolled use + SCI_SETSCROLLWIDTHTRACKING

+ +

SCI_SETSCROLLWIDTHTRACKING(bool tracking)
+ SCI_GETSCROLLWIDTHTRACKING
+ If scroll width tracking is enabled then the scroll width is adjusted to ensure that all of the lines currently + displayed can be completely scrolled. This mode never adjusts the scroll width to be narrower.

+ +

SCI_SETENDATLASTLINE(bool endAtLastLine)
+ SCI_GETENDATLASTLINE
+ SCI_SETENDATLASTLINE sets the scroll range so that maximum scroll position has + the last line at the bottom of the view (default). Setting this to false allows + scrolling one page below the last line.

+ +

White space

+ SCI_SETVIEWWS(int wsMode)
+ SCI_GETVIEWWS
+ SCI_SETWHITESPACEFORE(bool + useWhitespaceForeColour, int colour)
+ SCI_SETWHITESPACEBACK(bool + useWhitespaceBackColour, int colour)
+ SCI_SETWHITESPACESIZE(int + size)
+ SCI_GETWHITESPACESIZE
+ SCI_SETEXTRAASCENT(int extraAscent)
+ SCI_GETEXTRAASCENT
+ SCI_SETEXTRADESCENT(int extraDescent)
+ SCI_GETEXTRADESCENT
+
+ +

SCI_SETVIEWWS(int wsMode)
+ SCI_GETVIEWWS
+ White space can be made visible which may be useful for languages in which white space is + significant, such as Python. Space characters appear as small centred dots and tab characters + as light arrows pointing to the right. There are also ways to control the display of end of line characters. The two messages set and get the + white space display mode. The wsMode argument can be one of:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
SCWS_INVISIBLE0The normal display mode with white space displayed as an empty background + colour.
SCWS_VISIBLEALWAYS1White space characters are drawn as dots and arrows,
SCWS_VISIBLEAFTERINDENT2White space used for indentation is displayed normally but after the first visible + character, it is shown as dots and arrows.
+ +

The effect of using any other wsMode value is undefined.

+ +

SCI_SETWHITESPACEFORE(bool useWhitespaceForeColour, int colour)
+ SCI_SETWHITESPACEBACK(bool useWhitespaceBackColour, int colour)
+ By default, the colour of visible white space is determined by the lexer in use. The + foreground and/or background colour of all visible white space can be set globally, overriding + the lexer's colours with SCI_SETWHITESPACEFORE and + SCI_SETWHITESPACEBACK.

+ +

SCI_SETWHITESPACESIZE(int size)
+ SCI_GETWHITESPACESIZE
+ SCI_SETWHITESPACESIZE sets the size of the dots used for mark space characters. + The SCI_GETWHITESPACESIZE message retrieves the current size. +

+ +

+ SCI_SETEXTRAASCENT(int extraAscent)
+ SCI_GETEXTRAASCENT
+ SCI_SETEXTRADESCENT(int extraDescent)
+ SCI_GETEXTRADESCENT
+ Text is drawn with the base of each character on a 'baseline'. The height of a line is found from the maximum + that any style extends above the baseline (its 'ascent'), added to the maximum that any style extends below the + baseline (its 'descent'). + Space may be added to the maximum ascent (SCI_SETEXTRAASCENT) and the + maximum descent (SCI_SETEXTRADESCENT) to allow for more space between lines. + This may done to make the text easier to read or to accomodate underlines or highlights. +

+ +

Cursor

+ +

SCI_SETCURSOR(int curType)
+ SCI_GETCURSOR
+ The cursor is normally chosen in a context sensitive way, so it will be different over the + margin than when over the text. When performing a slow action, you may wish to change to a wait + cursor. You set the cursor type with SCI_SETCURSOR. The curType + argument can be:

+ + + + + + + + + + + + + + + + + + + +
SC_CURSORNORMAL-1The normal cursor is displayed.
SC_CURSORWAIT 4The wait cursor is displayed when the mouse is over or owned by the Scintilla + window.
+ +

Cursor values 1 through 7 have defined cursors, but only SC_CURSORWAIT is + usefully controllable. Other values of curType cause a pointer to be displayed. + The SCI_GETCURSOR message returns the last cursor type you set, or + SC_CURSORNORMAL (-1) if you have not set a cursor type.

+ +

Mouse capture

+ +

SCI_SETMOUSEDOWNCAPTURES(bool captures)
+ SCI_GETMOUSEDOWNCAPTURES
+ When the mouse is pressed inside Scintilla, it is captured so future mouse movement events are + sent to Scintilla. This behavior may be turned off with + SCI_SETMOUSEDOWNCAPTURES(0).

+ +

Line endings

+ +

Scintilla can interpret any of the three major line end conventions, Macintosh (\r), Unix + (\n) and CP/M / DOS / Windows (\r\n). When the user presses the Enter key, one of these line + end strings is inserted into the buffer. The default is \r\n in Windows and \n in Unix, but + this can be changed with the SCI_SETEOLMODE message. You can also convert the + entire document to one of these line endings with SCI_CONVERTEOLS. Finally, you + can choose to display the line endings with SCI_SETVIEWEOL.

+ SCI_SETEOLMODE(int eolMode)
+ SCI_GETEOLMODE
+ SCI_CONVERTEOLS(int eolMode)
+ SCI_SETVIEWEOL(bool visible)
+ SCI_GETVIEWEOL
+
+ +

SCI_SETEOLMODE(int eolMode)
+ SCI_GETEOLMODE
+ SCI_SETEOLMODE sets the characters that are added into the document when the user + presses the Enter key. You can set eolMode to one of SC_EOL_CRLF (0), + SC_EOL_CR (1), or SC_EOL_LF (2). The SCI_GETEOLMODE + message retrieves the current state.

+ +

SCI_CONVERTEOLS(int eolMode)
+ This message changes all the end of line characters in the document to match + eolMode. Valid values are: SC_EOL_CRLF (0), SC_EOL_CR + (1), or SC_EOL_LF (2).

+ +

SCI_SETVIEWEOL(bool visible)
+ SCI_GETVIEWEOL
+ Normally, the end of line characters are hidden, but SCI_SETVIEWEOL allows you to + display (or hide) them by setting visible true (or + false). The visible rendering of the end of line characters is similar to + (CR), (LF), or (CR)(LF). SCI_GETVIEWEOL + returns the current state.

+ +

Styling

+ +

The styling messages allow you to assign styles to text. The standard Scintilla settings + divide the 8 style bits available for each character into 5 bits (0 to 4 = styles 0 to 31) that set a style and three bits (5 to 7) that + define indicators. You can change the balance between + styles and indicators with SCI_SETSTYLEBITS. If your styling needs can be met by + one of the standard lexers, or if you can write your own, then a lexer is probably the easiest + way to style your document. If you choose to use the container to do the styling you can use + the SCI_SETLEXER command to select + SCLEX_CONTAINER, in which case the container is sent a SCN_STYLENEEDED notification each time text needs styling for display. As another + alternative, you might use idle time to style the document. Even if you use a lexer, you might + use the styling commands to mark errors detected by a compiler. The following commands can be + used.

+ SCI_GETENDSTYLED
+ SCI_STARTSTYLING(int position, int mask)
+ SCI_SETSTYLING(int length, int style)
+ SCI_SETSTYLINGEX(int length, const char + *styles)
+ SCI_SETLINESTATE(int line, int value)
+ SCI_GETLINESTATE(int line)
+ SCI_GETMAXLINESTATE
+
+ +

SCI_GETENDSTYLED
+ Scintilla keeps a record of the last character that is likely to be styled correctly. This is + moved forwards when characters after it are styled and moved backwards if changes are made to + the text of the document before it. Before drawing text, this position is checked to see if any + styling is needed and, if so, a SCN_STYLENEEDED notification message is sent to the + container. The container can send SCI_GETENDSTYLED to work out where it needs to + start styling. Scintilla will always ask to style whole lines.

+ +

SCI_STARTSTYLING(int pos, int mask)
+ This prepares for styling by setting the styling position pos to start at and a + mask indicating which bits of the style bytes can be set. The mask allows styling + to occur over several passes, with, for example, basic styling done on an initial pass to + ensure that the text of the code is seen quickly and correctly, and then a second slower pass, + detecting syntax errors and using indicators to show where these are. For example, with the + standard settings of 5 style bits and 3 indicator bits, you would use a mask value + of 31 (0x1f) if you were setting text styles and did not want to change the indicators. After + SCI_STARTSTYLING, send multiple SCI_SETSTYLING messages for each + lexical entity to style.

+ +

SCI_SETSTYLING(int length, int style)
+ This message sets the style of length characters starting at the styling position + and then increases the styling position by length, ready for the next call. If + sCell is the style byte, the operation is:
+ if ((sCell & mask) != style) sCell = (sCell & ~mask) | (style & + mask);
+

+ +

SCI_SETSTYLINGEX(int length, const char *styles)
+ As an alternative to SCI_SETSTYLING, which applies the same style to each byte, + you can use this message which specifies the styles for each of length bytes from + the styling position and then increases the styling position by length, ready for + the next call. The length styling bytes pointed at by styles should + not contain any bits not set in mask.

+ +

SCI_SETLINESTATE(int line, int value)
+ SCI_GETLINESTATE(int line)
+ As well as the 8 bits of lexical state stored for each character there is also an integer + stored for each line. This can be used for longer lived parse states such as what the current + scripting language is in an ASP page. Use SCI_SETLINESTATE to set the integer + value and SCI_GETLINESTATE to get the value. + Changing the value produces a SC_MOD_CHANGELINESTATE notification. +

+ +

SCI_GETMAXLINESTATE
+ This returns the last line that has any line state.

+ +

Style definition

+ +

While the style setting messages mentioned above change the style numbers associated with + text, these messages define how those style numbers are interpreted visually. There are 256 + lexer styles that can be set, numbered 0 to STYLE_MAX (255). Unless you use SCI_SETSTYLEBITS to change the number + of style bits, styles 0 to 31 are used to set the text attributes. There are also some + predefined numbered styles starting at 32, The following STYLE_* constants are + defined.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
STYLE_DEFAULT32This style defines the attributes that all styles receive when the + SCI_STYLECLEARALL message is used.
STYLE_LINENUMBER33This style sets the attributes of the text used to display line numbers in a line + number margin. The background colour set for this style also sets the background colour + for all margins that do not have any folding mask bits set. That is, any margin for which + mask & SC_MASK_FOLDERS is 0. See SCI_SETMARGINMASKN for more about masks.
STYLE_BRACELIGHT34This style sets the attributes used when highlighting braces with the SCI_BRACEHIGHLIGHT message and + when highlighting the corresponding indentation with SCI_SETHIGHLIGHTGUIDE.
STYLE_BRACEBAD35This style sets the display attributes used when marking an unmatched brace with the + SCI_BRACEBADLIGHT + message.
STYLE_CONTROLCHAR36This style sets the font used when drawing control characters. + Only the font, size, bold, italics, and character set attributes are used and not + the colour attributes. See + also: SCI_SETCONTROLCHARSYMBOL.
STYLE_INDENTGUIDE37This style sets the foreground and background colours used when drawing the + indentation guides.
STYLE_CALLTIP38 Call tips normally use the font attributes defined by STYLE_DEFAULT. + Use of SCI_CALLTIPUSESTYLE + causes call tips to use this style instead. Only the font face name, font size, + foreground and background colours and character set attributes are used.
STYLE_LASTPREDEFINED39To make it easier for client code to discover the range of styles that are + predefined, this is set to the style number of the last predefined style. This is + currently set to 39 and the last style with an identifier is 38, which reserves space + for one future predefined style.
STYLE_MAX255This is not a style but is the number of the maximum style that can be set. Styles + between STYLE_LASTPREDEFINED and STYLE_MAX would be appropriate + if you used SCI_SETSTYLEBITS + to set more than 5 style bits.
+ +

For each style you can set the font name, size and use of bold, italic and underline, + foreground and background colour and the character set. You can also choose to hide text with a + given style, display all characters as upper or lower case and fill from the last character on + a line to the end of the line (for embedded languages). There is also an experimental attribute + to make text read-only.

+ +

It is entirely up to you how you use styles. If you want to use syntax colouring you might + use style 0 for white space, style 1 for numbers, style 2 for keywords, style 3 for strings, + style 4 for preprocessor, style 5 for operators, and so on.

+ SCI_STYLERESETDEFAULT
+ SCI_STYLECLEARALL
+ SCI_STYLESETFONT(int styleNumber, char + *fontName)
+ SCI_STYLEGETFONT(int styleNumber, char *fontName)
+ SCI_STYLESETSIZE(int styleNumber, int + sizeInPoints)
+ SCI_STYLEGETSIZE(int styleNumber)
+ SCI_STYLESETSIZEFRACTIONAL(int styleNumber, int + sizeInHundredthPoints)
+ SCI_STYLEGETSIZEFRACTIONAL(int styleNumber)
+ SCI_STYLESETBOLD(int styleNumber, bool + bold)
+ SCI_STYLEGETBOLD(int styleNumber)
+ SCI_STYLESETWEIGHT(int styleNumber, int + weight)
+ SCI_STYLEGETWEIGHT(int styleNumber)
+ SCI_STYLESETITALIC(int styleNumber, bool + italic)
+ SCI_STYLEGETITALIC(int styleNumber)
+ SCI_STYLESETUNDERLINE(int styleNumber, bool + underline)
+ SCI_STYLEGETUNDERLINE(int styleNumber)
+ SCI_STYLESETFORE(int styleNumber, int + colour)
+ SCI_STYLEGETFORE(int styleNumber)
+ SCI_STYLESETBACK(int styleNumber, int + colour)
+ SCI_STYLEGETBACK(int styleNumber)
+ SCI_STYLESETEOLFILLED(int styleNumber, bool + eolFilled)
+ SCI_STYLEGETEOLFILLED(int styleNumber)
+ SCI_STYLESETCHARACTERSET(int styleNumber, + int charSet)
+ SCI_STYLEGETCHARACTERSET(int styleNumber)
+ SCI_STYLESETCASE(int styleNumber, int + caseMode)
+ SCI_STYLEGETCASE(int styleNumber)
+ SCI_STYLESETVISIBLE(int styleNumber, bool + visible)
+ SCI_STYLEGETVISIBLE(int styleNumber)
+ SCI_STYLESETCHANGEABLE(int styleNumber, bool + changeable)
+ SCI_STYLEGETCHANGEABLE(int styleNumber)
+ SCI_STYLESETHOTSPOT(int styleNumber, bool + hotspot)
+ SCI_STYLEGETHOTSPOT(int styleNumber)
+
+ +

SCI_STYLERESETDEFAULT
+ This message resets STYLE_DEFAULT to its state when Scintilla was + initialised.

+ +

SCI_STYLECLEARALL
+ This message sets all styles to have the same attributes as STYLE_DEFAULT. If you + are setting up Scintilla for syntax colouring, it is likely that the lexical styles you set + will be very similar. One way to set the styles is to:
+ 1. Set STYLE_DEFAULT to the common features of all styles.
+ 2. Use SCI_STYLECLEARALL to copy this to all styles.
+ 3. Set the style attributes that make your lexical styles different.

+ +

SCI_STYLESETFONT(int styleNumber, const char *fontName)
+ SCI_STYLEGETFONT(int styleNumber, char *fontName)
+ SCI_STYLESETSIZE(int styleNumber, int sizeInPoints)
+ SCI_STYLEGETSIZE(int styleNumber)
+ SCI_STYLESETSIZEFRACTIONAL(int styleNumber, int sizeInHundredthPoints)
+ SCI_STYLEGETSIZEFRACTIONAL(int styleNumber)
+ SCI_STYLESETBOLD(int styleNumber, bool bold)
+ SCI_STYLEGETBOLD(int styleNumber)
+ SCI_STYLESETWEIGHT(int styleNumber, int weight)
+ SCI_STYLEGETWEIGHT(int styleNumber)
+ SCI_STYLESETITALIC(int styleNumber, bool italic)
+ SCI_STYLEGETITALIC(int styleNumber)
+ These messages (plus SCI_STYLESETCHARACTERSET) set the font + attributes that are used to match the fonts you request to those available. The + fontName is a zero terminated string holding the name of a font. Under Windows, + only the first 32 characters of the name are used and the name is not case sensitive. For + internal caching, Scintilla tracks fonts by name and does care about the casing of font names, + so please be consistent. On GTK+, Pango is used to display text.

+

Sizes can be set to a whole number of points with SCI_STYLESETSIZE + or to a fractional point size in hundredths of a point with SCI_STYLESETSIZEFRACTIONAL + by multiplying the size by 100 (SC_FONT_SIZE_MULTIPLIER). + For example, a text size of 9.4 points is set with SCI_STYLESETSIZEFRACTIONAL(<style>, 940). +

+

The weight or boldness of a font can be set with SCI_STYLESETBOLD + or SCI_STYLESETWEIGHT. The weight is a number between 1 and 999 with 1 being very light + and 999 very heavy. While any value can be used, fonts often only support between 2 and 4 weights with three weights + being common enough to have symbolic names: + SC_WEIGHT_NORMAL (400), + SC_WEIGHT_SEMIBOLD (600), and + SC_WEIGHT_BOLD (700). + The SCI_STYLESETBOLD message takes a boolean argument with 0 choosing SC_WEIGHT_NORMAL + and 1 SC_WEIGHT_BOLD. +

+ +

SCI_STYLESETUNDERLINE(int styleNumber, bool + underline)
+ SCI_STYLEGETUNDERLINE(int styleNumber)
+ You can set a style to be underlined. The underline is drawn in the foreground colour. All + characters with a style that includes the underline attribute are underlined, even if they are + white space.

+ +

SCI_STYLESETFORE(int styleNumber, int colour)
+ SCI_STYLEGETFORE(int styleNumber)
+ SCI_STYLESETBACK(int styleNumber, int colour)
+ SCI_STYLEGETBACK(int styleNumber)
+ Text is drawn in the foreground colour. The space in each character cell that is not occupied + by the character is drawn in the background colour.

+ +

SCI_STYLESETEOLFILLED(int styleNumber, bool + eolFilled)
+ SCI_STYLEGETEOLFILLED(int styleNumber)
+ If the last character in the line has a style with this attribute set, the remainder of the + line up to the right edge of the window is filled with the background colour set for the last + character. This is useful when a document contains embedded sections in another language such + as HTML pages with embedded JavaScript. By setting eolFilled to true + and a consistent background colour (different from the background colour set for the HTML + styles) to all JavaScript styles then JavaScript sections will be easily distinguished from + HTML.

+ +

SCI_STYLESETCHARACTERSET(int styleNumber, int + charSet)
+ SCI_STYLEGETCHARACTERSET(int styleNumber)
+ You can set a style to use a different character set than the default. The places where such + characters sets are likely to be useful are comments and literal strings. For example, + SCI_STYLESETCHARACTERSET(SCE_C_STRING, SC_CHARSET_RUSSIAN) would ensure that + strings in Russian would display correctly in C and C++ (SCE_C_STRING is the style + number used by the C and C++ lexer to display literal strings; it has the value 6). This + feature works differently on Windows and GTK+.

+ +

The character sets supported on Windows are:
+ SC_CHARSET_ANSI, SC_CHARSET_ARABIC, SC_CHARSET_BALTIC, + SC_CHARSET_CHINESEBIG5, SC_CHARSET_DEFAULT, + SC_CHARSET_EASTEUROPE, SC_CHARSET_GB2312, + SC_CHARSET_GREEK, SC_CHARSET_HANGUL, SC_CHARSET_HEBREW, + SC_CHARSET_JOHAB, SC_CHARSET_MAC, SC_CHARSET_OEM, + SC_CHARSET_RUSSIAN (code page 1251), + SC_CHARSET_SHIFTJIS, SC_CHARSET_SYMBOL, SC_CHARSET_THAI, + SC_CHARSET_TURKISH, and SC_CHARSET_VIETNAMESE.

+ +

The character sets supported on GTK+ are:
+ SC_CHARSET_ANSI, SC_CHARSET_CYRILLIC (code page 1251), + SC_CHARSET_EASTEUROPE, + SC_CHARSET_GB2312, SC_CHARSET_HANGUL, + SC_CHARSET_RUSSIAN (KOI8-R), SC_CHARSET_SHIFTJIS, and + SC_CHARSET_8859_15.

+ +

SCI_STYLESETCASE(int styleNumber, int caseMode)
+ SCI_STYLEGETCASE(int styleNumber)
+ The value of caseMode determines how text is displayed. You can set upper case + (SC_CASE_UPPER, 1) or lower case (SC_CASE_LOWER, 2) or display + normally (SC_CASE_MIXED, 0). This does not change the stored text, only how it is + displayed.

+ +

SCI_STYLESETVISIBLE(int styleNumber, bool visible)
+ SCI_STYLEGETVISIBLE(int styleNumber)
+ Text is normally visible. However, you can completely hide it by giving it a style with the + visible set to 0. This could be used to hide embedded formatting instructions or + hypertext keywords in HTML or XML.

+ +

SCI_STYLESETCHANGEABLE(int styleNumber, bool + changeable)
+ SCI_STYLEGETCHANGEABLE(int styleNumber)
+ This is an experimental and incompletely implemented style attribute. The default setting is + changeable set true but when set false it makes text + read-only. Currently it only stops the caret from being within not-changeable text and does not + yet stop deleting a range that contains not-changeable text.

+ +

SCI_STYLESETHOTSPOT(int styleNumber, bool + hotspot)
+ SCI_STYLEGETHOTSPOT(int styleNumber)
+ This style is used to mark ranges of text that can detect mouse clicks. + The cursor changes to a hand over hotspots, and the foreground, and background colours + may change and an underline appear to indicate that these areas are sensitive to clicking. + This may be used to allow hyperlinks to other documents.

+ +

Caret, selection, and hotspot styles

+ +

The selection is shown by changing the foreground and/or background colours. If one of these + is not set then that attribute is not changed for the selection. The default is to show the + selection by changing the background to light gray and leaving the foreground the same as when + it was not selected. When there is no selection, the current insertion point is marked by the + text caret. This is a vertical line that is normally blinking on and off to attract the users + attention.

+ SCI_SETSELFORE(bool useSelectionForeColour, int colour)
+ SCI_SETSELBACK(bool useSelectionBackColour, int colour)
+ SCI_SETSELALPHA(int alpha)
+ SCI_GETSELALPHA
+ SCI_SETSELEOLFILLED(bool filled)
+ SCI_GETSELEOLFILLED
+ SCI_SETCARETFORE(int colour)
+ SCI_GETCARETFORE
+ SCI_SETCARETLINEVISIBLE(bool show)
+ SCI_GETCARETLINEVISIBLE
+ SCI_SETCARETLINEBACK(int colour)
+ SCI_GETCARETLINEBACK
+ SCI_SETCARETLINEBACKALPHA(int alpha)
+ SCI_GETCARETLINEBACKALPHA
+ SCI_SETCARETPERIOD(int milliseconds)
+ SCI_GETCARETPERIOD
+ SCI_SETCARETSTYLE(int style)
+ SCI_GETCARETSTYLE
+ SCI_SETCARETWIDTH(int pixels)
+ SCI_GETCARETWIDTH
+ SCI_SETHOTSPOTACTIVEFORE(bool useSetting, int colour)
+ SCI_GETHOTSPOTACTIVEFORE
+ SCI_SETHOTSPOTACTIVEBACK(bool useSetting, int colour)
+ SCI_GETHOTSPOTACTIVEBACK
+ SCI_SETHOTSPOTACTIVEUNDERLINE(bool underline)
+ SCI_GETHOTSPOTACTIVEUNDERLINE
+ SCI_SETHOTSPOTSINGLELINE(bool singleLine)
+ SCI_GETHOTSPOTSINGLELINE
+ SCI_SETCONTROLCHARSYMBOL(int symbol)
+ SCI_GETCONTROLCHARSYMBOL
+ SCI_SETCARETSTICKY(int useCaretStickyBehaviour)
+ SCI_GETCARETSTICKY
+ SCI_TOGGLECARETSTICKY
+
+ +

SCI_SETSELFORE(bool useSelectionForeColour, int colour)
+ SCI_SETSELBACK(bool useSelectionBackColour, int colour)
+ You can choose to override the default selection colouring with these two messages. The colour + you provide is used if you set useSelection*Colour to true. If it is + set to false, the default styled colouring is used and the colour + argument has no effect.

+

SCI_SETSELALPHA(int alpha)
+ SCI_GETSELALPHA
+ The selection can be drawn translucently in the selection background colour by + setting an alpha value.

+ +

SCI_SETSELEOLFILLED(bool filled)
+ SCI_GETSELEOLFILLED
+ The selection can be drawn up to the right hand border by setting this property.

+ +

SCI_SETCARETFORE(int colour)
+ SCI_GETCARETFORE
+ The colour of the caret can be set with SCI_SETCARETFORE and retrieved with + SCI_GETCARETFORE.

+ +

SCI_SETCARETLINEVISIBLE(bool show)
+ SCI_GETCARETLINEVISIBLE
+ SCI_SETCARETLINEBACK(int colour)
+ SCI_GETCARETLINEBACK
+ SCI_SETCARETLINEBACKALPHA(int alpha)
+ SCI_GETCARETLINEBACKALPHA
+ You can choose to make the background colour of the line containing the caret different with + these messages. To do this, set the desired background colour with + SCI_SETCARETLINEBACK, then use SCI_SETCARETLINEVISIBLE(true) to + enable the effect. You can cancel the effect with SCI_SETCARETLINEVISIBLE(false). + The two SCI_GETCARET* functions return the state and the colour. This form of + background colouring has highest priority when a line has markers that would otherwise change + the background colour. + The caret line may also be drawn translucently which allows other background colours to show + through. This is done by setting the alpha (translucency) value by calling + SCI_SETCARETLINEBACKALPHA. When the alpha is not SC_ALPHA_NOALPHA, + the caret line is drawn after all other features so will affect the colour of all other features. +

+ +

SCI_SETCARETPERIOD(int milliseconds)
+ SCI_GETCARETPERIOD
+ The rate at which the caret blinks can be set with SCI_SETCARETPERIOD which + determines the time in milliseconds that the caret is visible or invisible before changing + state. Setting the period to 0 stops the caret blinking. The default value is 500 milliseconds. + SCI_GETCARETPERIOD returns the current setting.

+ +

SCI_SETCARETSTYLE(int style)
+ SCI_GETCARETSTYLE
+ The style of the caret can be set with SCI_SETCARETSTYLE to be a line caret + (CARETSTYLE_LINE=1), a block caret (CARETSTYLE_BLOCK=2) or to not draw at all + (CARETSTYLE_INVISIBLE=0). The default value is the line caret (CARETSTYLE_LINE=1). + You can determine the current caret style setting using SCI_GETCARETSTYLE.

+ +

The block character draws most combining and multibyte character sequences successfully, + though some fonts like Thai Fonts (and possibly others) can sometimes appear strange when + the cursor is positioned at these characters, which may result in only drawing a part of the + cursor character sequence. This is most notable on Windows platforms.

+ +

SCI_SETCARETWIDTH(int pixels)
+ SCI_GETCARETWIDTH
+ The width of the line caret can be set with SCI_SETCARETWIDTH to a value of + 0, 1, 2 or 3 pixels. The default width is 1 pixel. You can read back the current width with + SCI_GETCARETWIDTH. A width of 0 makes the caret invisible (added at version + 1.50), similar to setting the caret style to CARETSTYLE_INVISIBLE (though not interchangable). + This setting only affects the width of the cursor when the cursor style is set to line caret + mode, it does not affect the width for a block caret.

+ +

SCI_SETHOTSPOTACTIVEFORE(bool useHotSpotForeColour, int colour)
+ SCI_GETHOTSPOTACTIVEFORE
+ SCI_SETHOTSPOTACTIVEBACK(bool useHotSpotBackColour, int colour)
+ SCI_GETHOTSPOTACTIVEBACK
+ SCI_SETHOTSPOTACTIVEUNDERLINE(bool underline)
+ SCI_GETHOTSPOTACTIVEUNDERLINE
+ SCI_SETHOTSPOTSINGLELINE(bool singleLine)
+ SCI_GETHOTSPOTSINGLELINE
+ While the cursor hovers over text in a style with the hotspot attribute set, + the default colouring can be modified and an underline drawn with these settings. + Single line mode stops a hotspot from wrapping onto next line.

+ +

SCI_SETCONTROLCHARSYMBOL(int symbol)
+ SCI_GETCONTROLCHARSYMBOL
+ By default, Scintilla displays control characters (characters with codes less than 32) in a + rounded rectangle as ASCII mnemonics: "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", + "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", + "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US". These mnemonics come from the + early days of signaling, though some are still used (LF = Line Feed, BS = Back Space, CR = + Carriage Return, for example).

+ +

You can choose to replace these mnemonics by a nominated symbol with an ASCII code in the + range 32 to 255. If you set a symbol value less than 32, all control characters are displayed + as mnemonics. The symbol you set is rendered in the font of the style set for the character. + You can read back the current symbol with the SCI_GETCONTROLCHARSYMBOL message. + The default symbol value is 0.

+ +

SCI_SETCARETSTICKY(int useCaretStickyBehaviour)
+ SCI_GETCARETSTICKY
+ SCI_TOGGLECARETSTICKY
+ These messages set, get or toggle the caretSticky setting which controls when the last position + of the caret on the line is saved.

+ +

When set to SC_CARETSTICKY_OFF (0), the sticky flag is off; all text changes + (and all caret position changes) will remember the + caret's new horizontal position when moving to different lines. This is the default.

+ +

When set to SC_CARETSTICKY_ON (1), the sticky flag is on, and the only thing which will cause the editor to remember the + horizontal caret position is moving the caret with mouse or keyboard (left/right arrow keys, home/end keys, etc).

+ +

When set to SC_CARETSTICKY_WHITESPACE (2), the caret acts like mode 0 (sticky off) except under one + special case; when space or tab characters are inserted. (Including pasting only space/tabs -- undo, redo, + etc. do not exhibit this behavior..).

+ +

SCI_TOGGLECARETSTICKY switches from SC_CARETSTICKY_ON and SC_CARETSTICKY_WHITESPACE + to SC_CARETSTICKY_OFF and from SC_CARETSTICKY_OFF to SC_CARETSTICKY_ON.

+ +

Margins

+ +

There may be up to five margins to the left of the text display, plus a gap either side of + the text. Each margin can be set to display only symbols, line numbers, or text with SCI_SETMARGINTYPEN. + Textual margins may also display symbols. + The markers + that can be displayed in each margin are set with SCI_SETMARGINMASKN. Any markers not associated with + a visible margin will be displayed as changes in background colour in the text. A width in + pixels can be set for each margin. Margins with a zero width are ignored completely. You can + choose if a mouse click in a margin sends a SCN_MARGINCLICK notification to the container or + selects a line of text.

+ +

The margins are numbered 0 to 4. Using a margin number outside the valid range has no + effect. By default, margin 0 is set to display line numbers, but is given a width of 0, so it + is hidden. Margin 1 is set to display non-folding symbols and is given a width of 16 pixels, so + it is visible. Margin 2 is set to display the folding symbols, but is given a width of 0, so it + is hidden. Of course, you can set the margins to be whatever you wish.

+ +

Styled text margins used to show revision and blame information:

+

Styled text margins used to show revision and blame information

+ + SCI_SETMARGINTYPEN(int margin, int + type)
+ SCI_GETMARGINTYPEN(int margin)
+ SCI_SETMARGINWIDTHN(int margin, int + pixelWidth)
+ SCI_GETMARGINWIDTHN(int margin)
+ SCI_SETMARGINMASKN(int margin, int + mask)
+ SCI_GETMARGINMASKN(int margin)
+ SCI_SETMARGINSENSITIVEN(int margin, bool + sensitive)
+ SCI_GETMARGINSENSITIVEN(int + margin)
+ SCI_SETMARGINCURSORN(int margin, int + cursor)
+ SCI_GETMARGINCURSORN(int + margin)
+ SCI_SETMARGINLEFT(<unused>, int + pixels)
+ SCI_GETMARGINLEFT
+ SCI_SETMARGINRIGHT(<unused>, int + pixels)
+ SCI_GETMARGINRIGHT
+ SCI_SETFOLDMARGINCOLOUR(bool useSetting, int colour)
+ SCI_SETFOLDMARGINHICOLOUR(bool useSetting, int colour)
+ SCI_MARGINSETTEXT(int line, char *text)
+ SCI_MARGINGETTEXT(int line, char *text)
+ SCI_MARGINSETSTYLE(int line, int style)
+ SCI_MARGINGETSTYLE(int line)
+ SCI_MARGINSETSTYLES(int line, char *styles)
+ SCI_MARGINGETSTYLES(int line, char *styles)
+ SCI_MARGINTEXTCLEARALL
+ SCI_MARGINSETSTYLEOFFSET(int style)
+ SCI_MARGINGETSTYLEOFFSET
+ SCI_SETMARGINOPTIONS(int marginOptions)
+ SCI_GETMARGINOPTIONS
+
+ +

SCI_SETMARGINTYPEN(int margin, int iType)
+ SCI_GETMARGINTYPEN(int margin)
+ These two routines set and get the type of a margin. The margin argument should be 0, 1, 2, 3 or 4. + You can use the predefined constants SC_MARGIN_SYMBOL (0) and + SC_MARGIN_NUMBER (1) to set a margin as either a line number or a symbol margin. + A margin with application defined text may use SC_MARGIN_TEXT (4) or + SC_MARGIN_RTEXT (5) to right justify the text. + By convention, margin 0 is used for line numbers and the next two are used for symbols. You can + also use the constants SC_MARGIN_BACK (2) and SC_MARGIN_FORE (3) for + symbol margins that set their background colour to match the STYLE_DEFAULT background and + foreground colours.

+ +

SCI_SETMARGINWIDTHN(int margin, int pixelWidth)
+ SCI_GETMARGINWIDTHN(int margin)
+ These routines set and get the width of a margin in pixels. A margin with zero width is + invisible. By default, Scintilla sets margin 1 for symbols with a width of 16 pixels, so this + is a reasonable guess if you are not sure what would be appropriate. Line number margins widths + should take into account the number of lines in the document and the line number style. You + could use something like SCI_TEXTWIDTH(STYLE_LINENUMBER, "_99999") to get a + suitable width.

+ +

SCI_SETMARGINMASKN(int margin, int mask)
+ SCI_GETMARGINMASKN(int margin)
+ The mask is a 32-bit value. Each bit corresponds to one of 32 logical symbols that can be + displayed in a margin that is enabled for symbols. There is a useful constant, + SC_MASK_FOLDERS (0xFE000000 or -33554432), that is a mask for the 7 logical + symbols used to denote folding. You can assign a wide range of symbols and colours to each of + the 32 logical symbols, see Markers for more information. If (mask + & SC_MASK_FOLDERS)==0, the margin background colour is controlled by style 33 (STYLE_LINENUMBER).

+ +

You add logical markers to a line with SCI_MARKERADD. If a line has an associated marker that + does not appear in the mask of any margin with a non-zero width, the marker changes the + background colour of the line. For example, suppose you decide to use logical marker 10 to mark + lines with a syntax error and you want to show such lines by changing the background colour. + The mask for this marker is 1 shifted left 10 times (1<<10) which is 0x400. If you make + sure that no symbol margin includes 0x400 in its mask, any line with the marker gets the + background colour changed.

+ +

To set a non-folding margin 1 use SCI_SETMARGINMASKN(1, ~SC_MASK_FOLDERS) + which is the default set by Scintilla. + To set a folding margin 2 use SCI_SETMARGINMASKN(2, SC_MASK_FOLDERS). + ~SC_MASK_FOLDERS is 0x1FFFFFF in hexadecimal or 33554431 + decimal. Of course, you may need to display all 32 symbols in a margin, in which case use + SCI_SETMARGINMASKN(margin, -1).

+ +

SCI_SETMARGINSENSITIVEN(int margin, bool + sensitive)
+ SCI_GETMARGINSENSITIVEN(int margin)
+ Each of the five margins can be set sensitive or insensitive to mouse clicks. A click in a + sensitive margin sends a SCN_MARGINCLICK notification to the container. Margins that are not sensitive act as + selection margins which make it easy to select ranges of lines. By default, all margins are + insensitive.

+ +

SCI_SETMARGINCURSORN(int margin, int + cursor)
+ SCI_GETMARGINCURSORN(int margin)
+ A reversed arrow cursor is normally shown over all margins. This may be changed to a normal arrow with + SCI_SETMARGINCURSORN(margin, SC_CURSORARROW) or restored to a + reversed arrow with + SCI_SETMARGINCURSORN(margin, SC_CURSORREVERSEARROW).

+ +

SCI_SETMARGINLEFT(<unused>, int pixels)
+ SCI_GETMARGINLEFT
+ SCI_SETMARGINRIGHT(<unused>, int pixels)
+ SCI_GETMARGINRIGHT
+ These messages set and get the width of the blank margin on both sides of the text in pixels. + The default is to one pixel on each side.

+ +

SCI_SETFOLDMARGINCOLOUR(bool useSetting, int colour)
+ SCI_SETFOLDMARGINHICOLOUR(bool useSetting, int colour)
+ These messages allow changing the colour of the fold margin and fold margin highlight. + On Windows the fold margin colour defaults to ::GetSysColor(COLOR_3DFACE) and the fold margin highlight + colour to ::GetSysColor(COLOR_3DHIGHLIGHT).

+ +

+ SCI_MARGINSETTEXT(int line, char *text)
+ SCI_MARGINGETTEXT(int line, char *text)
+ SCI_MARGINSETSTYLE(int line, int style)
+ SCI_MARGINGETSTYLE(int line)
+ SCI_MARGINSETSTYLES(int line, char *styles)
+ SCI_MARGINGETSTYLES(int line, char *styles)
+ SCI_MARGINTEXTCLEARALL
+ Text margins are created with the type SC_MARGIN_TEXT or SC_MARGIN_RTEXT. + A different string may be set for each line with SCI_MARGINSETTEXT. + The whole of the text margin on a line may be displayed in a particular style with + SCI_MARGINSETSTYLE or each character may be individually styled with + SCI_MARGINSETSTYLES which uses an array of bytes with each byte setting the style + of the corresponding text byte similar to SCI_SETSTYLINGEX. + Setting a text margin will cause a + SC_MOD_CHANGEMARGIN + notification to be sent. +

+

+ SCI_MARGINSETSTYLEOFFSET(int style)
+ SCI_MARGINGETSTYLEOFFSET
+ Margin styles may be completely separated from standard text styles by setting a style offset. For example, + SCI_MARGINSETSTYLEOFFSET(256) would allow the margin styles to be numbered from + 256 upto 511 so they do not overlap styles set by lexers. Each style number set with SCI_MARGINSETSTYLE + or SCI_MARGINSETSTYLES has the offset added before looking up the style. +

+

+ SCI_SETMARGINOPTIONS(int marginOptions)
+ SCI_GETMARGINOPTIONS
+ Define margin options by enabling appropriate bit flags. At the moment, only one flag is available + SC_MARGINOPTION_SUBLINESELECT=1, which controls how wrapped lines are selected when clicking + on margin in front of them. If SC_MARGINOPTION_SUBLINESELECT is set only sub line of wrapped + line is selected, otherwise whole wrapped line is selected. Margin options are set to + SC_MARGINOPTION_NONE=0 by default. +

+ +

Annotations

+ +

Annotations are read-only lines of text underneath each line of editable text. + An annotation may consist of multiple lines separated by '\n'. + Annotations can be used to display an assembler version of code for debugging or to show diagnostic messages inline or to + line up different versions of text in a merge tool.

+

Annotations used for inline diagnostics:

+

Annotations used for inline diagnostics

+ + + SCI_ANNOTATIONSETTEXT(int line, char *text)
+ SCI_ANNOTATIONGETTEXT(int line, char *text)
+ SCI_ANNOTATIONSETSTYLE(int line, int style)
+ SCI_ANNOTATIONGETSTYLE(int line)
+ SCI_ANNOTATIONSETSTYLES(int line, char *styles)
+ SCI_ANNOTATIONGETSTYLES(int line, char *styles)
+ SCI_ANNOTATIONGETLINES(int line)
+ SCI_ANNOTATIONCLEARALL
+ SCI_ANNOTATIONSETVISIBLE(int visible)
+ SCI_ANNOTATIONGETVISIBLE
+ SCI_ANNOTATIONSETSTYLEOFFSET(int style)
+ SCI_ANNOTATIONGETSTYLEOFFSET
+
+ +

+ SCI_ANNOTATIONSETTEXT(int line, char *text)
+ SCI_ANNOTATIONGETTEXT(int line, char *text)
+ SCI_ANNOTATIONSETSTYLE(int line, int style)
+ SCI_ANNOTATIONGETSTYLE(int line)
+ SCI_ANNOTATIONSETSTYLES(int line, char *styles)
+ SCI_ANNOTATIONGETSTYLES(int line, char *styles)
+ SCI_ANNOTATIONGETLINES(int line)
+ SCI_ANNOTATIONCLEARALL
+ A different string may be set for each line with SCI_ANNOTATIONSETTEXT. + To clear annotations call SCI_ANNOTATIONSETTEXT with a NULL pointer. + The whole of the text ANNOTATION on a line may be displayed in a particular style with + SCI_ANNOTATIONSETSTYLE or each character may be individually styled with + SCI_ANNOTATIONSETSTYLES which uses an array of bytes with each byte setting the style + of the corresponding text byte similar to SCI_SETSTYLINGEX. The text must be set first as it + specifies how long the annotation is so how many bytes of styling to read. + Setting an annotation will cause a + SC_MOD_CHANGEANNOTATION + notification to be sent. +

+

+ The number of lines annotating a line can be retrieved with SCI_ANNOTATIONGETLINES. + All the lines can be cleared of annotations with SCI_ANNOTATIONCLEARALL + which is equivalent to clearing each line (setting to 0) and then deleting other memory used for this feature. +

+

+ SCI_ANNOTATIONSETVISIBLE(int visible)
+ SCI_ANNOTATIONGETVISIBLE
+ Annotations can be made visible in a view and there is a choice of display style when visible. + The two messages set and get the annotation display mode. The visible + argument can be one of:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ANNOTATION_HIDDEN0Annotations are not displayed.
ANNOTATION_STANDARD1Annotations are drawn left justified with no adornment.
ANNOTATION_BOXED2Annotations are indented to match the text and are surrounded by a box.
+ +

+ SCI_ANNOTATIONSETSTYLEOFFSET(int style)
+ SCI_ANNOTATIONGETSTYLEOFFSET
+ Annotation styles may be completely separated from standard text styles by setting a style offset. For example, + SCI_ANNOTATIONSETSTYLEOFFSET(512) would allow the annotation styles to be numbered from + 512 upto 767 so they do not overlap styles set by lexers (or margins if margins offset is 256). + Each style number set with SCI_ANNOTATIONSETSTYLE + or SCI_ANNOTATIONSETSTYLES has the offset added before looking up the style. +

+ +

Other settings

+ SCI_SETUSEPALETTE(bool + allowPaletteUse)
+ SCI_GETUSEPALETTE
+ SCI_SETBUFFEREDDRAW(bool isBuffered)
+ SCI_GETBUFFEREDDRAW
+ SCI_SETTWOPHASEDRAW(bool twoPhase)
+ SCI_GETTWOPHASEDRAW
+ SCI_SETTECHNOLOGY(int technology)
+ SCI_GETTECHNOLOGY
+ SCI_SETFONTQUALITY(int fontQuality)
+ SCI_GETFONTQUALITY
+ SCI_SETCODEPAGE(int codePage)
+ SCI_GETCODEPAGE
+ SCI_SETKEYSUNICODE(bool keysUnicode)
+ SCI_GETKEYSUNICODE
+ SCI_SETWORDCHARS(<unused>, const char + *chars)
+ SCI_SETWHITESPACECHARS(<unused>, const char + *chars)
+ SCI_SETCHARSDEFAULT
+ SCI_GRABFOCUS
+ SCI_SETFOCUS(bool focus)
+ SCI_GETFOCUS
+
+ +

To forward a message (WM_XXXX, WPARAM, LPARAM) to Scintilla, you can use + SendMessage(hScintilla, WM_XXXX, WPARAM, LPARAM) where hScintilla is + the handle to the Scintilla window you created as your editor.

+ +

While we are on the subject of forwarding messages in Windows, the top level window should + forward any WM_SETTINGCHANGE messages to Scintilla (this is currently used to + collect changes to mouse settings, but could be used for other user interface items in the + future).

+ +

SCI_SETBUFFEREDDRAW(bool isBuffered)
+ SCI_GETBUFFEREDDRAW
+ These messages turn buffered drawing on or off and report the buffered drawing state. Buffered + drawing draws each line into a bitmap rather than directly to the screen and then copies the + bitmap to the screen. This avoids flickering although it does take longer. The default is for + drawing to be buffered.

+ +

SCI_SETTWOPHASEDRAW(bool twoPhase)
+ SCI_GETTWOPHASEDRAW
+ Two phase drawing is a better but slower way of drawing text. + In single phase drawing each run of characters in one style is drawn along with its background. + If a character overhangs the end of a run, such as in "V_" where the + "V" is in a different style from the "_", then this can cause the right hand + side of the "V" to be overdrawn by the background of the "_" which + cuts it off. Two phase drawing + fixes this by drawing all the backgrounds first and then drawing the text in + transparent mode. Two phase drawing may flicker more than single phase + unless buffered drawing is on. The default is for drawing to be two phase.

+ +

SCI_SETTECHNOLOGY(int technology)
+ SCI_GETTECHNOLOGY
+ The technology property allows choosing between different drawing APIs and options. + On most platforms, the only choice is SC_TECHNOLOGY_DEFAULT (0). + On Windows Vista or later, SC_TECHNOLOGY_DIRECTWRITE (1) + can be chosen to use the Direct2D and DirectWrite APIs for higher quality antialiased drawing.

+

Since Direct2D buffers drawing, Scintilla's buffering should be turned off with + SCI_SETBUFFEREDDRAW(0);. This causes DirectWrite to use better quality antialiasing.

+ +

SCI_SETFONTQUALITY(int fontQuality)
+ SCI_GETFONTQUALITY
+ Manage font quality (antialiasing method). Currently, the following values are available on Windows: + SC_EFF_QUALITY_DEFAULT (backward compatible), + SC_EFF_QUALITY_NON_ANTIALIASED, + SC_EFF_QUALITY_ANTIALIASED, + SC_EFF_QUALITY_LCD_OPTIMIZED.

+

In case it is necessary to squeeze more options into this property, only a limited number of bits defined + by SC_EFF_QUALITY_MASK (0xf) will be used for quality.

+ +

SCI_SETCODEPAGE(int codePage)
+ SCI_GETCODEPAGE
+ Scintilla has some support for Japanese, Chinese and Korean DBCS. Use this message with + codePage set to the code page number to set Scintilla to use code page information + to ensure double byte characters are treated as one character rather than two. This also stops + the caret from moving between the two bytes in a double byte character. + Do not use this message to choose between different single byte character sets: it doesn't do that. + Call with + codePage set to zero to disable DBCS support. The default is + SCI_SETCODEPAGE(0).

+ +

Code page SC_CP_UTF8 (65001) sets Scintilla into Unicode mode with the document + treated as a sequence of characters expressed in UTF-8. The text is converted to the platform's + normal Unicode encoding before being drawn by the OS and thus can display Hebrew, Arabic, + Cyrillic, and Han characters. Languages which can use two characters stacked vertically in one + horizontal space, such as Thai, will mostly work but there are some issues where the characters + are drawn separately leading to visual glitches. Bi-directional text is not supported.

+ +

Code page can be set to 932 (Japanese Shift-JIS), 936 (Simplified Chinese GBK), + 949 (Korean Unified Hangul Code), 950 (Traditional Chinese Big5), or 1361 (Korean Johab) + although these may require installation of language specific support.

+ +

SCI_SETKEYSUNICODE(bool keysUnicode)
+ SCI_GETKEYSUNICODE
+ On Windows, character keys are normally handled differently depending on whether Scintilla is a wide + or narrow character window with character messages treated as Unicode when wide and as 8 bit otherwise. + Set this property to always treat as Unicode. This option is needed for Delphi.

+ +

SCI_SETWORDCHARS(<unused>, const char *chars)
+ Scintilla has several functions that operate on words, which are defined to be contiguous + sequences of characters from a particular set of characters. This message defines which + characters are members of that set. The character sets are set to default values before processing this + function. + For example, if you don't allow '_' in your set of characters + use:
+ SCI_SETWORDCHARS(0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");

+ +

SCI_SETWHITESPACECHARS(<unused>, const char *chars)
+ Similar to SCI_SETWORDCHARS, this message allows the user to define which chars Scintilla considers + as whitespace. Setting the whitespace chars allows the user to fine-tune Scintilla's behaviour doing + such things as moving the cursor to the start or end of a word; for example, by defining punctuation chars + as whitespace, they will be skipped over when the user presses ctrl+left or ctrl+right. + This function should be called after SCI_SETWORDCHARS as it will + reset the whitespace characters to the default set.

+

SCI_SETCHARSDEFAULT
+ Use the default sets of word and whitespace characters. This sets whitespace to space, tab and other + characters with codes less than 0x20, with word characters set to alphanumeric and '_'. +

+ + +

SCI_GRABFOCUS
+ SCI_SETFOCUS(bool focus)
+ SCI_GETFOCUS
+ Scintilla can be told to grab the focus with this message. This is needed more on GTK+ where + focus handling is more complicated than on Windows.

+ +

The internal focus flag can be set with SCI_SETFOCUS. This is used by clients + that have complex focus requirements such as having their own window that gets the real focus + but with the need to indicate that Scintilla has the logical focus.

+ +

Brace highlighting

+ SCI_BRACEHIGHLIGHT(int pos1, int + pos2)
+ SCI_BRACEBADLIGHT(int pos1)
+ SCI_BRACEHIGHLIGHTINDICATOR(bool useBraceHighlightIndicator, int indicatorNumber)
+ SCI_BRACEBADLIGHTINDICATOR(bool useBraceBadLightIndicator, int indicatorNumber)
+ SCI_BRACEMATCH(int position, int + maxReStyle)
+
+ +

SCI_BRACEHIGHLIGHT(int pos1, int pos2)
+ Up to two characters can be highlighted in a 'brace highlighting style', which is defined as + style number STYLE_BRACELIGHT (34). + If you have enabled indent guides, you may also wish to highlight the indent that corresponds + with the brace. You can locate the column with SCI_GETCOLUMN and highlight the indent with SCI_SETHIGHLIGHTGUIDE.

+ +

SCI_BRACEBADLIGHT(int pos1)
+ If there is no matching brace then the brace + badlighting style, style STYLE_BRACEBAD (35), can be used to show the brace + that is unmatched. Using a position of INVALID_POSITION (-1) removes the + highlight.

+ +

SCI_BRACEHIGHLIGHTINDICATOR(bool useBraceHighlightIndicator, int indicatorNumber)
+ Use specified indicator to highlight matching braces instead of changing their style.

+ +

SCI_BRACEBADLIGHTINDICATOR(bool useBraceBadLightIndicator, int indicatorNumber)
+ Use specified indicator to highlight non matching brace instead of changing its style.

+ +

SCI_BRACEMATCH(int pos, int maxReStyle)
+ The SCI_BRACEMATCH message finds a corresponding matching brace given + pos, the position of one brace. The brace characters handled are '(', ')', '[', + ']', '{', '}', '<', and '>'. The search is forwards from an opening brace and backwards + from a closing brace. If the character at position is not a brace character, or a matching + brace cannot be found, the return value is -1. Otherwise, the return value is the position of + the matching brace.

+ +

A match only occurs if the style of the matching brace is the same as the starting brace or + the matching brace is beyond the end of styling. Nested braces are handled correctly. The + maxReStyle parameter must currently be 0 - it may be used in the future to limit + the length of brace searches.

+ +

Tabs and Indentation Guides

+ +

Indentation (the white space at the start of a line) is often used by programmers to clarify + program structure and in some languages, for example Python, it may be part of the language + syntax. Tabs are normally used in editors to insert a tab character or to pad text with spaces + up to the next tab.

+ +

Scintilla can be set to treat tab and backspace in the white space at the start of a line in + a special way: inserting a tab indents the line to the next indent position rather than just + inserting a tab at the current character position and backspace unindents the line rather than + deleting a character. Scintilla can also display indentation guides (vertical lines) to help + you to generate code.

+ SCI_SETTABWIDTH(int widthInChars)
+ SCI_GETTABWIDTH
+ SCI_SETUSETABS(bool useTabs)
+ SCI_GETUSETABS
+ SCI_SETINDENT(int widthInChars)
+ SCI_GETINDENT
+ SCI_SETTABINDENTS(bool tabIndents)
+ SCI_GETTABINDENTS
+ SCI_SETBACKSPACEUNINDENTS(bool + bsUnIndents)
+ SCI_GETBACKSPACEUNINDENTS
+ SCI_SETLINEINDENTATION(int line, int + indentation)
+ SCI_GETLINEINDENTATION(int line)
+ SCI_GETLINEINDENTPOSITION(int + line)
+ SCI_SETINDENTATIONGUIDES(int indentView)
+ SCI_GETINDENTATIONGUIDES
+ SCI_SETHIGHLIGHTGUIDE(int column)
+ SCI_GETHIGHLIGHTGUIDE
+
+ +

SCI_SETTABWIDTH(int widthInChars)
+ SCI_GETTABWIDTH
+ SCI_SETTABWIDTH sets the size of a tab as a multiple of the size of a space + character in STYLE_DEFAULT. The default tab width is 8 characters. There are no + limits on tab sizes, but values less than 1 or large values may have undesirable effects.

+ +

SCI_SETUSETABS(bool useTabs)
+ SCI_GETUSETABS
+ SCI_SETUSETABS determines whether indentation should be created out of a mixture + of tabs and spaces or be based purely on spaces. Set useTabs to false + (0) to create all tabs and indents out of spaces. The default is true. You can use + SCI_GETCOLUMN to get the column of a + position taking the width of a tab into account.

+

SCI_SETINDENT(int widthInChars)
+ SCI_GETINDENT
+ SCI_SETINDENT sets the size of indentation in terms of the width of a space in STYLE_DEFAULT. If you set a width of + 0, the indent size is the same as the tab size. There are no limits on indent sizes, but values + less than 0 or large values may have undesirable effects. +

+ +

SCI_SETTABINDENTS(bool tabIndents)
+ SCI_GETTABINDENTS
+ SCI_SETBACKSPACEUNINDENTS(bool bsUnIndents)
+ SCI_GETBACKSPACEUNINDENTS
+

+ +

Inside indentation white space, the tab and backspace keys can be made to indent and + unindent rather than insert a tab character or delete a character with the + SCI_SETTABINDENTS and SCI_SETBACKSPACEUNINDENTS functions.

+ +

SCI_SETLINEINDENTATION(int line, int indentation)
+ SCI_GETLINEINDENTATION(int line)
+ The amount of indentation on a line can be discovered and set with + SCI_GETLINEINDENTATION and SCI_SETLINEINDENTATION. The indentation is + measured in character columns, which correspond to the width of space characters.

+ +

SCI_GETLINEINDENTPOSITION(int line)
+ This returns the position at the end of indentation of a line.

+ +

SCI_SETINDENTATIONGUIDES(int indentView)
+ SCI_GETINDENTATIONGUIDES
+ Indentation guides are dotted vertical lines that appear within indentation white space every + indent size columns. They make it easy to see which constructs line up especially when they + extend over multiple pages. Style STYLE_INDENTGUIDE (37) is used to specify the + foreground and background colour of the indentation guides.

+ +

There are 4 indentation guide views. + SC_IV_NONE turns the feature off but the other 3 states determine how far the guides appear on + empty lines.

+ + + + + + + + + + + + + + + + + + + + + + + +
SC_IV_NONENo indentation guides are shown.
SC_IV_REALIndentation guides are shown inside real indentation white space.
SC_IV_LOOKFORWARDIndentation guides are shown beyond the actual indentation up to the level of the + next non-empty line. + If the previous non-empty line was a fold header then indentation guides are shown for + one more level of indent than that line. This setting is good for Python.
SC_IV_LOOKBOTHIndentation guides are shown beyond the actual indentation up to the level of the + next non-empty line or previous non-empty line whichever is the greater. + This setting is good for most languages.
+ +

SCI_SETHIGHLIGHTGUIDE(int column)
+ SCI_GETHIGHLIGHTGUIDE
+ When brace highlighting occurs, the indentation guide corresponding to the braces may be + highlighted with the brace highlighting style, STYLE_BRACELIGHT (34). Set column to 0 to + cancel this highlight.

+ +

Markers

+ +

There are 32 markers, numbered 0 to MARKER_MAX (31), and you can assign any combination of them to each + line in the document. Markers appear in the selection + margin to the left of the text. If the selection margin is set to zero width, the + background colour of the whole line is changed instead. Marker numbers 25 to 31 are used by + Scintilla in folding margins, and have symbolic names of the form SC_MARKNUM_*, + for example SC_MARKNUM_FOLDEROPEN.

+ +

Marker numbers 0 to 24 have no pre-defined function; you can use them to mark syntax errors + or the current point of execution, break points, or whatever you need marking. If you do not + need folding, you can use all 32 for any purpose you wish.

+ +

Each marker number has a symbol associated with it. You can also set the foreground and + background colour for each marker number, so you can use the same symbol more than once with + different colouring for different uses. Scintilla has a set of symbols you can assign + (SC_MARK_*) or you can use characters. By default, all 32 markers are set to + SC_MARK_CIRCLE with a black foreground and a white background.

+ +

The markers are drawn in the order of their numbers, so higher numbered markers appear on + top of lower numbered ones. Markers try to move with their text by tracking where the start of + their line moves. When a line is deleted, its markers are combined, by an OR + operation, with the markers of the previous line.

+ SCI_MARKERDEFINE(int markerNumber, int + markerSymbols)
+ SCI_MARKERDEFINEPIXMAP(int markerNumber, + const char *xpm)
+ SCI_RGBAIMAGESETWIDTH(int width)
+ SCI_RGBAIMAGESETHEIGHT(int height)
+ SCI_MARKERDEFINERGBAIMAGE(int markerNumber, + const char *pixels)
+ SCI_MARKERSYMBOLDEFINED(int markerNumber) +
+ SCI_MARKERSETFORE(int markerNumber, int + colour)
+ SCI_MARKERSETBACK(int markerNumber, int + colour)
+ SCI_MARKERSETBACKSELECTED(int markerNumber, int + colour)
+ SCI_MARKERENABLEHIGHLIGHT(int enabled)
+ SCI_MARKERSETALPHA(int markerNumber, int + alpha)
+ SCI_MARKERADD(int line, int markerNumber)
+ SCI_MARKERADDSET(int line, int markerMask)
+ SCI_MARKERDELETE(int line, int + markerNumber)
+ SCI_MARKERDELETEALL(int markerNumber)
+ SCI_MARKERGET(int line)
+ SCI_MARKERNEXT(int lineStart, int + markerMask)
+ SCI_MARKERPREVIOUS(int lineStart, int + markerMask)
+ SCI_MARKERLINEFROMHANDLE(int + handle)
+ SCI_MARKERDELETEHANDLE(int handle)
+
+ +

SCI_MARKERDEFINE(int markerNumber, int markerSymbols)
+ This message associates a marker number in the range 0 to 31 with one of the marker symbols or + an ASCII character. The general-purpose marker symbols currently available are:
+ SC_MARK_CIRCLE, SC_MARK_ROUNDRECT, SC_MARK_ARROW, + SC_MARK_SMALLRECT, SC_MARK_SHORTARROW, SC_MARK_EMPTY, + SC_MARK_ARROWDOWN, SC_MARK_MINUS, SC_MARK_PLUS, + SC_MARK_ARROWS, SC_MARK_DOTDOTDOT, + SC_MARK_BACKGROUND, SC_MARK_LEFTRECT, + SC_MARK_FULLRECT, and SC_MARK_UNDERLINE.

+ +

The SC_MARK_BACKGROUND marker changes the background colour of the line only. + The SC_MARK_FULLRECT symbol mirrors this, changing only the margin background colour. + SC_MARK_UNDERLINE draws an underline across the text. + The SC_MARK_EMPTY symbol is invisible, allowing client code to track the movement + of lines. You would also use it if you changed the folding style and wanted one or more of the + SC_FOLDERNUM_* markers to have no associated symbol.

+ +

Applications may use the marker symbol SC_MARK_AVAILABLE to indicate that + plugins may allocate that marker number. +

+ +

There are also marker symbols designed for use in the folding margin in a flattened tree + style.
+ SC_MARK_BOXMINUS, SC_MARK_BOXMINUSCONNECTED, + SC_MARK_BOXPLUS, SC_MARK_BOXPLUSCONNECTED, + SC_MARK_CIRCLEMINUS, SC_MARK_CIRCLEMINUSCONNECTED, + SC_MARK_CIRCLEPLUS, SC_MARK_CIRCLEPLUSCONNECTED, + SC_MARK_LCORNER, SC_MARK_LCORNERCURVE, SC_MARK_TCORNER, + SC_MARK_TCORNERCURVE, and SC_MARK_VLINE.

+ Characters can be used as markers by adding the ASCII value of the character to + SC_MARK_CHARACTER (10000). For example, to use 'A' (ASCII code 65) as marker + number 1 use:
+ SCI_MARKERDEFINE(1, SC_MARK_CHARACTER+65).
+ +

The marker numbers SC_MARKNUM_FOLDER and SC_MARKNUM_FOLDEROPEN are + used for showing that a fold is present and open or closed. Any symbols may be assigned for + this purpose although the (SC_MARK_PLUS, SC_MARK_MINUS) pair or the + (SC_MARK_ARROW, SC_MARK_ARROWDOWN) pair are good choices. As well as + these two, more assignments are needed for the flattened tree style: + SC_MARKNUM_FOLDEREND, SC_MARKNUM_FOLDERMIDTAIL, + SC_MARKNUM_FOLDEROPENMID, SC_MARKNUM_FOLDERSUB, and + SC_MARKNUM_FOLDERTAIL. The bits used for folding are specified by + SC_MASK_FOLDERS, which is commonly used as an argument to + SCI_SETMARGINMASKN when defining a margin to be used for folding.

+ +

This table shows which SC_MARK_* symbols should be assigned to which + SC_MARKNUM_* marker numbers to obtain four folding styles: Arrow (mimics + Macintosh), plus/minus shows folded lines as '+' and opened folds as '-', Circle tree, Box + tree.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SC_MARKNUM_*ArrowPlus/minusCircle treeBox tree
FOLDEROPENARROWDOWNMINUSCIRCLEMINUSBOXMINUS
FOLDERARROWPLUSCIRCLEPLUSBOXPLUS
FOLDERSUBEMPTYEMPTYVLINEVLINE
FOLDERTAILEMPTYEMPTYLCORNERCURVELCORNER
FOLDERENDEMPTYEMPTYCIRCLEPLUSCONNECTEDBOXPLUSCONNECTED
FOLDEROPENMIDEMPTYEMPTYCIRCLEMINUSCONNECTEDBOXMINUSCONNECTED
FOLDERMIDTAILEMPTYEMPTYTCORNERCURVETCORNER
+ +

SCI_MARKERDEFINEPIXMAP(int markerNumber, const char + *xpm)
+ Markers can be set to pixmaps with this message. The + XPM format is used for the pixmap. + Pixmaps use the SC_MARK_PIXMAP marker symbol.

+ +

+ SCI_RGBAIMAGESETWIDTH(int width)
+ SCI_RGBAIMAGESETHEIGHT(int height)
+ SCI_MARKERDEFINERGBAIMAGE(int markerNumber, const char *pixels)
+ Markers can be set to translucent pixmaps with this message. The + RGBA format is used for the pixmap. + The width and height must previously been set with the SCI_RGBAIMAGESETWIDTH and + SCI_RGBAIMAGESETHEIGHT messages. + Pixmaps use the SC_MARK_RGBAIMAGE marker symbol.

+ +

SCI_MARKERSYMBOLDEFINED(int markerNumber)
+ Returns the symbol defined for a markerNumber with SCI_MARKERDEFINE + or SC_MARK_PIXMAP if defined with SCI_MARKERDEFINEPIXMAP + or SC_MARK_RGBAIMAGE if defined with SCI_MARKERDEFINERGBAIMAGE.

+ +

SCI_MARKERSETFORE(int markerNumber, int colour)
+ SCI_MARKERSETBACK(int markerNumber, int colour)
+ These two messages set the foreground and background colour of a marker number.
+ SCI_MARKERSETBACKSELECTED(int markerNumber, int colour)
+ This message sets the highlight background colour of a marker number when its folding block is selected. The default colour is #FF0000.

+

SCI_MARKERENABLEHIGHLIGHT(bool enabled)
+ This message allows to enable/disable the highlight folding block when it is selected. (i.e. block that contains the caret)

+

SCI_MARKERSETALPHA(int markerNumber, int alpha)
+ When markers are drawn in the content area, either because there is no margin for them or + they are of SC_MARK_BACKGROUND or SC_MARK_UNDERLINE types, they may be drawn translucently by + setting an alpha value.

+ +

SCI_MARKERADD(int line, int markerNumber)
+ This message adds marker number markerNumber to a line. The message returns -1 if + this fails (illegal line number, out of memory) or it returns a marker handle number that + identifies the added marker. You can use this returned handle with SCI_MARKERLINEFROMHANDLE to find where a + marker is after moving or combining lines and with SCI_MARKERDELETEHANDLE to delete the marker + based on its handle. The message does not check the value of markerNumber, nor does it + check if the line already contains the marker.

+ +

SCI_MARKERADDSET(int line, int markerMask)
+ This message can add one or more markers to a line with a single call, specified in the same "one-bit-per-marker" 32-bit integer format returned by + SCI_MARKERGET + (and used by the mask-based marker search functions + SCI_MARKERNEXT and + SCI_MARKERPREVIOUS). + As with + SCI_MARKERADD, no check is made + to see if any of the markers are already present on the targeted line.

+ +

SCI_MARKERDELETE(int line, int markerNumber)
+ This searches the given line number for the given marker number and deletes it if it is + present. If you added the same marker more than once to the line, this will delete one copy + each time it is used. If you pass in a marker number of -1, all markers are deleted from the + line.

+ +

SCI_MARKERDELETEALL(int markerNumber)
+ This removes markers of the given number from all lines. If markerNumber is -1, it deletes all + markers from all lines.

+ +

SCI_MARKERGET(int line)
+ This returns a 32-bit integer that indicates which markers were present on the line. Bit 0 is + set if marker 0 is present, bit 1 for marker 1 and so on.

+ +

SCI_MARKERNEXT(int lineStart, int markerMask)
+ SCI_MARKERPREVIOUS(int lineStart, int markerMask)
+ These messages search efficiently for lines that include a given set of markers. The search + starts at line number lineStart and continues forwards to the end of the file + (SCI_MARKERNEXT) or backwards to the start of the file + (SCI_MARKERPREVIOUS). The markerMask argument should have one bit set + for each marker you wish to find. Set bit 0 to find marker 0, bit 1 for marker 1 and so on. The + message returns the line number of the first line that contains one of the markers in + markerMask or -1 if no marker is found.

+ +

SCI_MARKERLINEFROMHANDLE(int markerHandle)
+ The markerHandle argument is an identifier for a marker returned by SCI_MARKERADD. This function searches + the document for the marker with this handle and returns the line number that contains it or -1 + if it is not found.

+ +

SCI_MARKERDELETEHANDLE(int markerHandle)
+ The markerHandle argument is an identifier for a marker returned by SCI_MARKERADD. This function searches + the document for the marker with this handle and deletes the marker if it is found.

+ +

Indicators

+ +

Indicators are used to display additional information over the top of styling. + They can be used to show, for example, syntax errors, deprecated names and bad indentation + by drawing underlines under text or boxes around text. Originally, Scintilla stored indicator information in + the style bytes but this has proved limiting, so now up to 32 separately stored indicators may be used. + While style byte indicators currently still work, they will soon be removed so all the bits in each style + byte can be used for lexical states.

+ +

Indicators may be displayed as simple underlines, squiggly underlines, a + line of small 'T' shapes, a line of diagonal hatching, a strike-out or a rectangle around the text.

+ +

The SCI_INDIC* messages allow you to get and set the visual appearance of the + indicators. They all use an indicatorNumber argument in the range 0 to INDIC_MAX(31) + to set the indicator to style. To prevent interference the set of indicators is divided up into a range for use + by lexers (0..7) and a range for use by containers + (8=INDIC_CONTAINER .. 31=INDIC_MAX).

+ + SCI_INDICSETSTYLE(int indicatorNumber, int + indicatorStyle)
+ SCI_INDICGETSTYLE(int indicatorNumber)
+ SCI_INDICSETFORE(int indicatorNumber, int + colour)
+ SCI_INDICGETFORE(int indicatorNumber)
+ SCI_INDICSETALPHA(int indicatorNumber, int alpha)
+ SCI_INDICGETALPHA(int indicatorNumber)
+ SCI_INDICSETOUTLINEALPHA(int indicatorNumber, int alpha)
+ SCI_INDICGETOUTLINEALPHA(int indicatorNumber)
+ SCI_INDICSETUNDER(int indicatorNumber, bool under)
+ SCI_INDICGETUNDER(int indicatorNumber)
+
+ +

SCI_INDICSETSTYLE(int indicatorNumber, int + indicatorStyle)
+ SCI_INDICGETSTYLE(int indicatorNumber)
+ These two messages set and get the style for a particular indicator. The indicator styles + currently available are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SymbolValueVisual effect
INDIC_PLAIN0Underlined with a single, straight line.
INDIC_SQUIGGLE1A squiggly underline. Requires 3 pixels of descender space.
INDIC_TT2A line of small T shapes.
INDIC_DIAGONAL3Diagonal hatching.
INDIC_STRIKE4Strike out.
INDIC_HIDDEN5An indicator with no visual effect.
INDIC_BOX6A rectangle around the text.
INDIC_ROUNDBOX7A rectangle with rounded corners around the text using translucent drawing with the + interior usually more transparent than the border. You can use + SCI_INDICSETALPHA and + SCI_INDICSETOUTLINEALPHA + to control the alpha transparency values. The default alpha values are 30 for fill colour and 50 for outline colour.
INDIC_STRAIGHTBOX8A rectangle around the text using translucent drawing with the + interior usually more transparent than the border. You can use + SCI_INDICSETALPHA and + SCI_INDICSETOUTLINEALPHA + to control the alpha transparency values. The default alpha values are 30 for fill colour and 50 for outline colour.
INDIC_DASH9A dashed underline.
INDIC_DOTS10A dotted underline.
INDIC_SQUIGGLELOW11Similar to INDIC_SQUIGGLE but only using 2 vertical pixels + so will fit under small fonts.
INDIC_DOTBOX12A dotted rectangle around the text using translucent drawing. + Translucency alternates between the alpha and outline alpha settings with the top-left pixel using the alpha setting. + SCI_INDICSETALPHA and + SCI_INDICSETOUTLINEALPHA + control the alpha transparency values. The default values are 30 for alpha and 50 for outline alpha. + To avoid excessive memory allocation the maximum width of a dotted box is 4000 pixels. + Not available for OS X Carbon.
+ +

The default indicator styles are equivalent to:
+ SCI_INDICSETSTYLE(0, INDIC_SQUIGGLE);
+ SCI_INDICSETSTYLE(1, INDIC_TT);
+ SCI_INDICSETSTYLE(2, INDIC_PLAIN);

+ +

SCI_INDICSETFORE(int indicatorNumber, int colour)
+ SCI_INDICGETFORE(int indicatorNumber)
+ These two messages set and get the colour used to draw an indicator. The default indicator + colours are equivalent to:
+ SCI_INDICSETFORE(0, 0x007f00); (dark green)
+ SCI_INDICSETFORE(1, 0xff0000); (light blue)
+ SCI_INDICSETFORE(2, 0x0000ff); (light red)

+ +

SCI_INDICSETALPHA(int indicatorNumber, int alpha)
+ SCI_INDICGETALPHA(int indicatorNumber)
+ These two messages set and get the alpha transparency used for drawing the + fill colour of the INDIC_ROUNDBOX and INDIC_STRAIGHTBOX rectangle. The alpha value can range from + 0 (completely transparent) to 255 (no transparency). +

+ +

SCI_INDICSETOUTLINEALPHA(int indicatorNumber, int alpha)
+ SCI_INDICGETOUTLINEALPHA(int indicatorNumber)
+ These two messages set and get the alpha transparency used for drawing the + outline colour of the INDIC_ROUNDBOX and INDIC_STRAIGHTBOX rectangle. The alpha value can range from + 0 (completely transparent) to 255 (no transparency). +

+ +

SCI_INDICSETUNDER(int indicatorNumber, bool under)
+ SCI_INDICGETUNDER(int indicatorNumber)
+ These two messages set and get whether an indicator is drawn under text or over(default). + Drawing under text works only for modern indicators when two phase drawing + is enabled.

+ +

Modern Indicators

+ +

Modern indicators are stored in a format similar to run length encoding which is efficient in both + speed and storage for sparse information.

+

An indicator may store different values for each range but currently all values are drawn the same. + In the future, it may be possible to draw different values in different styles.

+

+ SCI_SETINDICATORCURRENT(int indicator)
+ SCI_GETINDICATORCURRENT
+ These two messages set and get the indicator that will be affected by calls to + SCI_INDICATORFILLRANGE(int position, int fillLength) and + SCI_INDICATORCLEARRANGE(int position, int clearLength). +

+ +

+ SCI_SETINDICATORVALUE(int value)
+ SCI_GETINDICATORVALUE
+ These two messages set and get the value that will be set by calls to + SCI_INDICATORFILLRANGE. +

+ +

+ SCI_INDICATORFILLRANGE(int position, int fillLength)
+ SCI_INDICATORCLEARRANGE(int position, int clearLength)
+ These two messages fill or clear a range for the current indicator. + SCI_INDICATORFILLRANGE fills with the + the current value. +

+ +

+ SCI_INDICATORALLONFOR(int position)
+ Retrieve a bitmap value representing which indicators are non-zero at a position. +

+ +

+ SCI_INDICATORVALUEAT(int indicator, int position)
+ Retrieve the value of a particular indicator at a position. +

+ +

+ SCI_INDICATORSTART(int indicator, int position)
+ SCI_INDICATOREND(int indicator, int position)
+ Find the start or end of a range with one value from a position within the range. + Can be used to iterate through the document to discover all the indicator positions. +

+ +

Style Byte Indicators (deprecated)

+

By default, Scintilla organizes the style byte associated with each text byte as 5 bits of + style information (for 32 styles) and 3 bits of indicator information for 3 independent + indicators so that, for example, syntax errors, deprecated names and bad indentation could all + be displayed at once.

+ +

The indicators are set using SCI_STARTSTYLING with a INDICS_MASK mask + and SCI_SETSTYLING with the values + INDIC0_MASK, INDIC1_MASK and INDIC2_MASK.

+ +

If you are using indicators in a buffer that has a lexer active + (see SCI_SETLEXER), + you must save lexing state information before setting any indicators and restore it afterwards. + Use SCI_GETENDSTYLED + to retrieve the current "styled to" position and + SCI_STARTSTYLING + to reset the styling position and mask (0x1f in the default layout of 5 style bits and 3 indicator bits) + when you are done.

+ +

The number of bits used for styles can be altered with SCI_SETSTYLEBITS from 0 to 8 bits. The remaining bits + can be used for indicators, so there can be from 1 to 8 indicators. However, the + INDIC*_MASK constants defined in Scintilla.h all assume 5 bits of + styling information and 3 indicators. If you use a different arrangement, you must define your + own constants.

+ + +

Autocompletion

+ +

Autocompletion displays a list box showing likely identifiers based upon the user's typing. + The user chooses the currently selected item by pressing the tab character or another character + that is a member of the fillup character set defined with SCI_AUTOCSETFILLUPS. + Autocompletion is triggered by your application. For example, in C if you detect that the user + has just typed fred. you could look up fred, and if it has a known + list of members, you could offer them in an autocompletion list. Alternatively, you could + monitor the user's typing and offer a list of likely items once their typing has narrowed down + the choice to a reasonable list. As yet another alternative, you could define a key code to + activate the list.

+ +

When the user makes a selection from the list the container is sent a SCN_AUTOCSELECTION notification message. On return from the notification Scintilla will insert + the selected text unless the autocompletion list has been cancelled, for example by the container sending + SCI_AUTOCCANCEL.

+ +

To make use of autocompletion you must monitor each character added to the document. See + SciTEBase::CharAdded() in SciTEBase.cxx for an example of autocompletion.

+ SCI_AUTOCSHOW(int lenEntered, const char + *list)
+ SCI_AUTOCCANCEL
+ SCI_AUTOCACTIVE
+ SCI_AUTOCPOSSTART
+ SCI_AUTOCCOMPLETE
+ SCI_AUTOCSTOPS(<unused>, const char + *chars)
+ SCI_AUTOCSETSEPARATOR(char + separator)
+ SCI_AUTOCGETSEPARATOR
+ SCI_AUTOCSELECT(<unused>, const char + *select)
+ SCI_AUTOCGETCURRENT
+ SCI_AUTOCGETCURRENTTEXT(<unused>, + char *text)
+ SCI_AUTOCSETCANCELATSTART(bool + cancel)
+ SCI_AUTOCGETCANCELATSTART
+ SCI_AUTOCSETFILLUPS(<unused>, const char + *chars)
+ SCI_AUTOCSETCHOOSESINGLE(bool + chooseSingle)
+ SCI_AUTOCGETCHOOSESINGLE
+ SCI_AUTOCSETIGNORECASE(bool + ignoreCase)
+ SCI_AUTOCGETIGNORECASE
+ SCI_AUTOCSETAUTOHIDE(bool autoHide)
+ SCI_AUTOCGETAUTOHIDE
+ SCI_AUTOCSETDROPRESTOFWORD(bool + dropRestOfWord)
+ SCI_AUTOCGETDROPRESTOFWORD
+ SCI_REGISTERIMAGE(int type, const char *xpmData)
+ SCI_REGISTERRGBAIMAGE(int type, const char *pixels)
+ SCI_CLEARREGISTEREDIMAGES
+ SCI_AUTOCSETTYPESEPARATOR(char separatorCharacter)
+ SCI_AUTOCGETTYPESEPARATOR
+ SCI_AUTOCSETMAXHEIGHT(int rowCount)
+ SCI_AUTOCGETMAXHEIGHT
+ SCI_AUTOCSETMAXWIDTH(int characterCount)
+ SCI_AUTOCGETMAXWIDTH
+
+ +

SCI_AUTOCSHOW(int lenEntered, const char *list)
+ This message causes a list to be displayed. lenEntered is the number of + characters of the word already entered and list is the list of words separated by + separator characters. The initial separator character is a space but this can be set or got + with SCI_AUTOCSETSEPARATOR + and SCI_AUTOCGETSEPARATOR.

+ +

The list of words should be in sorted order. If set to ignore case mode with SCI_AUTOCSETIGNORECASE, then + strings are matched after being converted to upper case. One result of this is that the list + should be sorted with the punctuation characters '[', '\', ']', '^', '_', and '`' sorted after + letters.

+ +

SCI_AUTOCCANCEL
+ This message cancels any displayed autocompletion list. When in autocompletion mode, the list + should disappear when the user types a character that can not be part of the autocompletion, + such as '.', '(' or '[' when typing an identifier. A set of characters that will cancel + autocompletion can be specified with SCI_AUTOCSTOPS.

+ +

SCI_AUTOCACTIVE
+ This message returns non-zero if there is an active autocompletion list and zero if there is + not.

+ +

SCI_AUTOCPOSSTART
+ This returns the value of the current position when SCI_AUTOCSHOW started display + of the list.

+ +

SCI_AUTOCCOMPLETE
+ This message triggers autocompletion. This has the same effect as the tab key.

+ +

SCI_AUTOCSTOPS(<unused>, const char *chars)
+ The chars argument is a string containing a list of characters that will + automatically cancel the autocompletion list. When you start the editor, this list is + empty.

+ +

SCI_AUTOCSETSEPARATOR(char separator)
+ SCI_AUTOCGETSEPARATOR
+ These two messages set and get the separator character used to separate words in the + SCI_AUTOCSHOW list. The default is the space character.

+ +

SCI_AUTOCSELECT(<unused>, const char *select)
+ SCI_AUTOCGETCURRENT
+ This message selects an item in the autocompletion list. It searches the list of words for the + first that matches select. By default, comparisons are case sensitive, but you can + change this with SCI_AUTOCSETIGNORECASE. The match is character + by character for the length of the select string. That is, if select is "Fred" it + will match "Frederick" if this is the first item in the list that begins with "Fred". If an + item is found, it is selected. If the item is not found, the autocompletion list closes if + auto-hide is true (see SCI_AUTOCSETAUTOHIDE).
+ The current selection index can be retrieved with SCI_AUTOCGETCURRENT.

+ +

SCI_AUTOCGETCURRENTTEXT(<unused>, char *text)
+ This message retrieves the current selected text in the autocompletion list. Normally the + SCN_AUTOCSELECTION notification + is used instead.

+ +

The value is copied to the text buffer, returning the length (not including the + terminating 0). If not found, an empty string is copied to the buffer and 0 is returned.

+ +

If the value argument is 0 then the length that should be allocated to store the value is + returned; again, the terminating 0 is not included.

+ +

SCI_AUTOCSETCANCELATSTART(bool cancel)
+ SCI_AUTOCGETCANCELATSTART
+ The default behavior is for the list to be cancelled if the caret moves to the location it + was at when the list was displayed. By calling this message with a false argument, + the list is not cancelled until the caret moves before the first character of the word being + completed.

+ +

SCI_AUTOCSETFILLUPS(<unused>, const char *chars)
+ If a fillup character is typed with an autocompletion list active, the currently selected item + in the list is added into the document, then the fillup character is added. Common fillup + characters are '(', '[' and '.' but others are possible depending on the language. By default, + no fillup characters are set.

+ +

SCI_AUTOCSETCHOOSESINGLE(bool chooseSingle)
+ SCI_AUTOCGETCHOOSESINGLE
+ If you use SCI_AUTOCSETCHOOSESINGLE(1) and a list has only one item, it is + automatically added and no list is displayed. The default is to display the list even if there + is only a single item.

+ +

SCI_AUTOCSETIGNORECASE(bool ignoreCase)
+ SCI_AUTOCGETIGNORECASE
+ By default, matching of characters to list members is case sensitive. These messages let you + set and get case sensitivity.

+ +

SCI_AUTOCSETAUTOHIDE(bool autoHide)
+ SCI_AUTOCGETAUTOHIDE
+ By default, the list is cancelled if there are no viable matches (the user has typed + characters that no longer match a list entry). If you want to keep displaying the original + list, set autoHide to false. This also effects SCI_AUTOCSELECT.

+ +

SCI_AUTOCSETDROPRESTOFWORD(bool dropRestOfWord)
+ SCI_AUTOCGETDROPRESTOFWORD
+ When an item is selected, any word characters following the caret are first erased if + dropRestOfWord is set true. The default is false.

+ +

+ SCI_REGISTERIMAGE(int type, const char *xpmData)
+ SCI_REGISTERRGBAIMAGE(int type, const char *pixels)
+ SCI_CLEARREGISTEREDIMAGES
+ SCI_AUTOCSETTYPESEPARATOR(char separatorCharacter)
+ SCI_AUTOCGETTYPESEPARATOR
+ + Autocompletion list items may display an image as well as text. Each image is first registered with an integer + type. Then this integer is included in the text of the list separated by a '?' from the text. For example, + "fclose?2 fopen" displays image 2 before the string "fclose" and no image before "fopen". + The images are in either the XPM format (SCI_REGISTERIMAGE) or + RGBA format (SCI_REGISTERRGBAIMAGE). + For SCI_REGISTERRGBAIMAGE the width and height must previously been set with + the SCI_RGBAIMAGESETWIDTH and + SCI_RGBAIMAGESETHEIGHT messages. + The set of registered images can be cleared with SCI_CLEARREGISTEREDIMAGES and the '?' separator changed + with SCI_AUTOCSETTYPESEPARATOR. +

+ +

+ SCI_AUTOCSETMAXHEIGHT(int rowCount)
+ SCI_AUTOCGETMAXHEIGHT
+ + Get or set the maximum number of rows that will be visible in an autocompletion list. If there are more rows in the list, then a vertical + scrollbar is shown. The default is 5. +

+ +

+ SCI_AUTOCSETMAXWIDTH(int characterCount)
+ SCI_AUTOCGETMAXWIDTH
+ + Get or set the maximum width of an autocompletion list expressed as the number of characters in the longest item that will be totally visible. + If zero (the default) then the list's width is calculated to fit the item with the most characters. Any items that cannot be fully displayed within + the available width are indicated by the presence of ellipsis. +

+ +

User lists

+ +

User lists use the same internal mechanisms as autocompletion lists, and all the calls + listed for autocompletion work on them; you cannot display a user list at the same time as an + autocompletion list is active. They differ in the following respects:

+ +

o The SCI_AUTOCSETCHOOSESINGLE message has no + effect.
+ o When the user makes a selection you are sent a SCN_USERLISTSELECTION notification message rather than SCN_AUTOCSELECTION.

+ +

BEWARE: if you have set fillup characters or stop characters, these will still be active + with the user list, and may result in items being selected or the user list cancelled due to + the user typing into the editor.

+ +

SCI_USERLISTSHOW(int listType, const char *list)
+ The listType parameter is returned to the container as the wParam + field of the SCNotification + structure. It must be greater than 0 as this is how Scintilla tells the difference between an + autocompletion list and a user list. If you have different types of list, for example a list of + buffers and a list of macros, you can use listType to tell which one has returned + a selection.

+ +

Call tips

+ +

Call tips are small windows displaying the arguments to a function and are displayed after + the user has typed the name of the function. They normally display characters using the font + facename, size and character set defined by + STYLE_DEFAULT. You can choose to + use STYLE_CALLTIP to define the + facename, size, foreground and background colours and character set with + SCI_CALLTIPUSESTYLE. + This also enables support for Tab characters. + + There is some interaction between call tips and autocompletion lists in that showing a + call tip cancels any active autocompletion list, and vice versa.

+ +

Call tips can highlight part of the text within them. You could use this to highlight the + current argument to a function by counting the number of commas (or whatever separator your + language uses). See SciTEBase::CharAdded() in SciTEBase.cxx for an + example of call tip use.

+ +

The mouse may be clicked on call tips and this causes a + SCN_CALLTIPCLICK + notification to be sent to the container. Small up and down arrows may be displayed within + a call tip by, respectively, including the characters '\001', or '\002'. This is useful + for showing that there are overloaded variants of one function name and that the user can + click on the arrows to cycle through the overloads.

+ +

Alternatively, call tips can be displayed when you leave the mouse pointer for a while over + a word in response to the SCN_DWELLSTART notification and cancelled in response to SCN_DWELLEND. This method could be used in a debugger to give + the value of a variable, or during editing to give information about the word under the + pointer.

+ SCI_CALLTIPSHOW(int posStart, const char + *definition)
+ SCI_CALLTIPCANCEL
+ SCI_CALLTIPACTIVE
+ SCI_CALLTIPPOSSTART
+ SCI_CALLTIPSETHLT(int highlightStart, int + highlightEnd)
+ SCI_CALLTIPSETBACK(int colour)
+ SCI_CALLTIPSETFORE(int colour)
+ SCI_CALLTIPSETFOREHLT(int colour)
+ SCI_CALLTIPUSESTYLE(int tabsize)
+ SCI_CALLTIPSETPOSITION(bool above)
+
+ +

SCI_CALLTIPSHOW(int posStart, const char *definition)
+ This message starts the process by displaying the call tip window. If a call tip is already + active, this has no effect.
+ posStart is the position in the document at which to align the call tip. The call + tip text is aligned to start 1 line below this character unless you have included up and/or + down arrows in the call tip text in which case the tip is aligned to the right-hand edge of + the rightmost arrow. The assumption is that you will start the text with something like + "\001 1 of 3 \002".
+ definition is the call tip text. This can contain multiple lines separated by + '\n' (Line Feed, ASCII code 10) characters. Do not include '\r' (Carriage Return, ASCII + code 13), as this will most likely print as an empty box. '\t' (Tab, ASCII code 9) is + supported if you set a tabsize with + SCI_CALLTIPUSESTYLE.

+ +

SCI_CALLTIPCANCEL
+ This message cancels any displayed call tip. Scintilla will also cancel call tips for you if + you use any keyboard commands that are not compatible with editing the argument list of a + function.

+ +

SCI_CALLTIPACTIVE
+ This returns 1 if a call tip is active and 0 if it is not active.

+ +

SCI_CALLTIPPOSSTART
+ This message returns the value of the current position when SCI_CALLTIPSHOW + started to display the tip.

+ +

SCI_CALLTIPSETHLT(int hlStart, int hlEnd)
+ This sets the region of the call tips text to display in a highlighted style. + hlStart is the zero-based index into the string of the first character to + highlight and hlEnd is the index of the first character after the highlight. + hlEnd must be greater than hlStart; hlEnd-hlStart is the + number of characters to highlight. Highlights can extend over line ends if this is + required.

+ +

Unhighlighted text is drawn in a mid gray. Selected text is drawn in a dark blue. The + background is white. These can be changed with + SCI_CALLTIPSETBACK, + SCI_CALLTIPSETFORE, and + SCI_CALLTIPSETFOREHLT. +

+ +

SCI_CALLTIPSETBACK(int colour)
+ The background colour of call tips can be set with this message; the default colour is white. + It is not a good idea to set a dark colour as the background as the default colour for normal + calltip text is mid gray and the defaultcolour for highlighted text is dark blue. This also + sets the background colour of STYLE_CALLTIP.

+ +

SCI_CALLTIPSETFORE(int colour)
+ The colour of call tip text can be set with this message; the default colour is mid gray. + This also sets the foreground colour of STYLE_CALLTIP.

+ +

SCI_CALLTIPSETFOREHLT(int colour)
+ The colour of highlighted call tip text can be set with this message; the default colour + is dark blue.

+ +

SCI_CALLTIPUSESTYLE(int tabsize)
+ This message changes the style used for call tips from STYLE_DEFAULT to + STYLE_CALLTIP and sets a tab size in screen pixels. If tabsize is + less than 1, Tab characters are not treated specially. Once this call has been used, the + call tip foreground and background colours are also taken from the style.

+ +

SCI_CALLTIPSETPOSITION(bool above)
+ By default the calltip is displayed below the text, setting above to true + (1) will display it above the text.

+ + +

Keyboard commands

+ +

To allow the container application to perform any of the actions available to the user with + keyboard, all the keyboard actions are messages. They do not take any parameters. These + commands are also used when redefining the key bindings with the SCI_ASSIGNCMDKEY message.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SCI_LINEDOWNSCI_LINEDOWNEXTENDSCI_LINEDOWNRECTEXTENDSCI_LINESCROLLDOWN
SCI_LINEUPSCI_LINEUPEXTENDSCI_LINEUPRECTEXTENDSCI_LINESCROLLUP
SCI_PARADOWNSCI_PARADOWNEXTENDSCI_PARAUPSCI_PARAUPEXTEND
SCI_CHARLEFTSCI_CHARLEFTEXTENDSCI_CHARLEFTRECTEXTEND
SCI_CHARRIGHTSCI_CHARRIGHTEXTENDSCI_CHARRIGHTRECTEXTEND
SCI_WORDLEFTSCI_WORDLEFTEXTENDSCI_WORDRIGHTSCI_WORDRIGHTEXTEND
SCI_WORDLEFTENDSCI_WORDLEFTENDEXTENDSCI_WORDRIGHTENDSCI_WORDRIGHTENDEXTEND
SCI_WORDPARTLEFTSCI_WORDPARTLEFTEXTENDSCI_WORDPARTRIGHTSCI_WORDPARTRIGHTEXTEND
SCI_HOMESCI_HOMEEXTENDSCI_HOMERECTEXTEND
SCI_HOMEDISPLAYSCI_HOMEDISPLAYEXTENDSCI_HOMEWRAPSCI_HOMEWRAPEXTEND
SCI_VCHOMESCI_VCHOMEEXTENDSCI_VCHOMERECTEXTEND
SCI_VCHOMEWRAPSCI_VCHOMEWRAPEXTEND
SCI_LINEENDSCI_LINEENDEXTENDSCI_LINEENDRECTEXTEND
SCI_LINEENDDISPLAYSCI_LINEENDDISPLAYEXTENDSCI_LINEENDWRAPSCI_LINEENDWRAPEXTEND
SCI_DOCUMENTSTARTSCI_DOCUMENTSTARTEXTENDSCI_DOCUMENTENDSCI_DOCUMENTENDEXTEND
SCI_PAGEUPSCI_PAGEUPEXTENDSCI_PAGEUPRECTEXTEND
SCI_PAGEDOWNSCI_PAGEDOWNEXTENDSCI_PAGEDOWNRECTEXTEND
SCI_STUTTEREDPAGEUPSCI_STUTTEREDPAGEUPEXTEND
SCI_STUTTEREDPAGEDOWNSCI_STUTTEREDPAGEDOWNEXTEND
SCI_DELETEBACKSCI_DELETEBACKNOTLINE
SCI_DELWORDLEFTSCI_DELWORDRIGHTSCI_DELWORDRIGHTEND
SCI_DELLINELEFTSCI_DELLINERIGHTSCI_LINEDELETE
SCI_LINECUTSCI_LINECOPYSCI_LINETRANSPOSESCI_LINEDUPLICATE
SCI_LOWERCASESCI_UPPERCASESCI_CANCELSCI_EDITTOGGLEOVERTYPE
SCI_NEWLINESCI_FORMFEEDSCI_TABSCI_BACKTAB
SCI_SELECTIONDUPLICATESCI_VERTICALCENTRECARET
SCI_MOVESELECTEDLINESUPSCI_MOVESELECTEDLINESDOWN
SCI_SCROLLTOSTARTSCI_SCROLLTOEND
+ +

The SCI_*EXTEND messages extend the selection.

+ +

The SCI_*RECTEXTEND messages extend the rectangular selection + (and convert regular selection to rectangular one, if any).

+ +

The SCI_WORDPART* commands are used to move between word segments marked by + capitalisation (aCamelCaseIdentifier) or underscores (an_under_bar_ident).

+ +

The SCI_HOME* commands move the caret to the start of the line, while the + SCI_VCHOME* commands move the caret to the first non-blank character of the line + (ie. just after the indentation) unless it is already there; in this case, it acts as SCI_HOME*.

+ +

The SCI_[HOME|LINEEND]DISPLAY* commands are used when in line wrap mode to + allow movement to the start or end of display lines as opposed to the normal + SCI_[HOME|LINEEND] commands which move to the start or end of document lines.

+ +

The SCI_[[VC]HOME|LINEEND]WRAP* commands are like their namesakes + SCI_[[VC]HOME|LINEEND]* except they behave differently when word-wrap is enabled: + They go first to the start / end of the display line, like SCI_[HOME|LINEEND]DISPLAY*, + but if the cursor is already at the point, it goes on to the start or end of the document line, + as appropriate for SCI_[[VC]HOME|LINEEND]*. +

+ +

The SCI_SCROLLTO[START|END] commands scroll the document to the start + or end without changing the selection. These commands match OS X platform conventions for the behaviour of the + home and end keys. Scintilla can be made to match OS X applications + by binding the home and end keys to these commands. +

+ +

Key bindings

+ +

There is a default binding of keys to commands that is defined in the Scintilla source in + the file KeyMap.cxx by the constant KeyMap::MapDefault[]. This table + maps key definitions to SCI_* messages with no parameters (mostly the keyboard commands discussed above, but any Scintilla + command that has no arguments can be mapped). You can change the mapping to suit your own + requirements.

+ SCI_ASSIGNCMDKEY(int keyDefinition, int + sciCommand)
+ SCI_CLEARCMDKEY(int keyDefinition)
+ SCI_CLEARALLCMDKEYS
+ SCI_NULL
+
+ +

keyDefinition
+ A key definition contains the key code in the low 16-bits and the key modifiers in the high + 16-bits. To combine keyCode and keyMod set:
+
+ keyDefinition = keyCode + (keyMod << 16)

+ +

The key code is a visible or control character or a key from the SCK_* + enumeration, which contains:
+ SCK_ADD, SCK_BACK, SCK_DELETE, SCK_DIVIDE, + SCK_DOWN, SCK_END, SCK_ESCAPE, SCK_HOME, + SCK_INSERT, SCK_LEFT, SCK_MENU, SCK_NEXT (Page Down), + SCK_PRIOR (Page Up), SCK_RETURN, SCK_RIGHT, + SCK_RWIN, + SCK_SUBTRACT, SCK_TAB, SCK_UP, and + SCK_WIN.

+ +

The modifiers are a combination of zero or more of SCMOD_ALT, + SCMOD_CTRL, SCMOD_SHIFT, and SCMOD_META. + On OS X, the Command key is mapped to SCMOD_CTRL and the Control key to + SCMOD_META. + If you are building a table, you might + want to use SCMOD_NORM, which has the value 0, to mean no modifiers.

+ +

SCI_ASSIGNCMDKEY(int keyDefinition, int sciCommand)
+ This assigns the given key definition to a Scintilla command identified by + sciCommand. sciCommand can be any SCI_* command that has + no arguments.

+ +

SCI_CLEARCMDKEY(int keyDefinition)
+ This makes the given key definition do nothing by assigning the action SCI_NULL + to it.

+ +

SCI_CLEARALLCMDKEYS
+ This command removes all keyboard command mapping by setting an empty mapping table.

+ +

SCI_NULL
+ The SCI_NULL does nothing and is the value assigned to keys that perform no + action. SCI_NULL ensures that keys do not propagate to the parent window as that may + cause focus to move. If you want the standard platform behaviour use the constant 0 instead.

+ +

Popup edit menu

+ +

SCI_USEPOPUP(bool bEnablePopup)
+ Clicking the wrong button on the mouse pops up a short default editing menu. This may be + turned off with SCI_USEPOPUP(0). If you turn it off, context menu commands (in + Windows, WM_CONTEXTMENU) will not be handled by Scintilla, so the parent of the + Scintilla window will have the opportunity to handle the message.

+ +

Macro recording

+ +

Start and stop macro recording mode. In macro recording mode, actions are reported to the + container through SCN_MACRORECORD + notifications. It is then up to the container to + record these actions for future replay.

+ +

SCI_STARTRECORD
+ SCI_STOPRECORD
+ These two messages turn macro recording on and off.

+ +

Printing

+ +

SCI_FORMATRANGE can be used to draw the text onto a display surface + which can include a printer display surface. Printed output shows text styling as on the + screen, but it hides all margins except a line number margin. All special marker effects are + removed and the selection and caret are hidden.

+ +

Different platforms use different display surface ID types to print on. On Windows, these are + HDCs., on GTK+ 3.x cairo_t *, + and on Cocoa CGContextRef is used.

+ +

SCI_FORMATRANGE is not supported on GTK+ 2.x.

+ + SCI_FORMATRANGE(bool bDraw, Sci_RangeToFormat + *pfr)
+ SCI_SETPRINTMAGNIFICATION(int + magnification)
+ SCI_GETPRINTMAGNIFICATION
+ SCI_SETPRINTCOLOURMODE(int mode)
+ SCI_GETPRINTCOLOURMODE
+ SCI_SETPRINTWRAPMODE
+ SCI_GETPRINTWRAPMODE
+
+ +

SCI_FORMATRANGE(bool bDraw, Sci_RangeToFormat *pfr)
+ This call renders a range of text into a device context. If you use + this for printing, you will probably want to arrange a page header and footer; Scintilla does + not do this for you. See SciTEWin::Print() in SciTEWinDlg.cxx for an + example. Each use of this message renders a range of text into a rectangular area and returns + the position in the document of the next character to print.

+ +

bDraw controls if any output is done. Set this to false if you are paginating + (for example, if you use this with MFC you will need to paginate in + OnBeginPrinting() before you output each page.

+
+struct Sci_Rectangle { int left; int top; int right; int bottom; };
+
+struct Sci_RangeToFormat {
+    Sci_SurfaceID hdc;        // The Surface ID we print to
+    Sci_SurfaceID hdcTarget;  // The Surface ID we use for measuring (may be same as hdc)
+    Sci_Rectangle rc;         // Rectangle in which to print
+    Sci_Rectangle rcPage;     // Physically printable page size
+    Sci_CharacterRange chrg;  // Range of characters to print
+};
+
+ +

On Windows, hdc and hdcTarget should both be set to the device context handle + of the output device (usually a printer). If you print to a metafile these will not be the same + as Windows metafiles (unlike extended metafiles) do not implement the full API for returning + information. In this case, set hdcTarget to the screen DC.
+ rcPage is the rectangle {0, 0, maxX, maxY} where maxX+1 + and maxY+1 are the number of physically printable pixels in x and y.
+ rc is the rectangle to render the text in (which will, of course, fit within the + rectangle defined by rcPage).
+ chrg.cpMin and chrg.cpMax define the start position and maximum + position of characters to output. All of each line within this character range is drawn.

+ +

On Cocoa, the surface IDs for printing (bDraw=1) should be the graphics port of the current context + ((CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]) when the view's drawRect method is called. + The Surface IDs are not really used for measurement (bDraw=0) but can be set + to a bitmap context (created with CGBitmapContextCreate) to avoid runtime warnings.

+ +

On GTK+, the surface IDs to use can be found from the printing context with + gtk_print_context_get_cairo_context(context).

+ + chrg.cpMin and chrg.cpMax define the start position and maximum + position of characters to output. All of each line within this character range is drawn.

+ +

When printing, the most tedious part is always working out what the margins should be to + allow for the non-printable area of the paper and printing a header and footer. If you look at + the printing code in SciTE, you will find that most of it is taken up with this. The loop that + causes Scintilla to render text is quite simple if you strip out all the margin, non-printable + area, header and footer code.

+ +

SCI_SETPRINTMAGNIFICATION(int magnification)
+ SCI_GETPRINTMAGNIFICATION
+ SCI_GETPRINTMAGNIFICATION lets you to print at a different size than the screen + font. magnification is the number of points to add to the size of each screen + font. A value of -3 or -4 gives reasonably small print. You can get this value with + SCI_GETPRINTMAGNIFICATION.

+ +

SCI_SETPRINTCOLOURMODE(int mode)
+ SCI_GETPRINTCOLOURMODE
+ These two messages set and get the method used to render coloured text on a printer that is + probably using white paper. It is especially important to consider the treatment of colour if + you use a dark or black screen background. Printing white on black uses up toner and ink very + many times faster than the other way around. You can set the mode to one of:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SymbolValuePurpose
SC_PRINT_NORMAL0Print using the current screen colours. This is the default.
SC_PRINT_INVERTLIGHT1If you use a dark screen background this saves ink by inverting the light value of + all colours and printing on a white background.
SC_PRINT_BLACKONWHITE2Print all text as black on a white background.
SC_PRINT_COLOURONWHITE3Everything prints in its own colour on a white background.
SC_PRINT_COLOURONWHITEDEFAULTBG4Everything prints in its own colour on a white background except that line numbers + use their own background colour.
+ +

SCI_SETPRINTWRAPMODE(int wrapMode)
+ SCI_GETPRINTWRAPMODE
+ These two functions get and set the printer wrap mode. wrapMode can be + set to SC_WRAP_NONE (0), SC_WRAP_WORD (1) or + SC_WRAP_CHAR (2). The default is + SC_WRAP_WORD, which wraps printed output so that all characters fit + into the print rectangle. If you set SC_WRAP_NONE, each line of text + generates one line of output and the line is truncated if it is too long to fit + into the print area.
+ SC_WRAP_WORD tries to wrap only between words as indicated by + white space or style changes although if a word is longer than a line, it will be wrapped before + the line end. SC_WRAP_CHAR is preferred to + SC_WRAP_WORD for Asian languages where there is no white space + between words.

+ +

Direct access

+ SCI_GETDIRECTFUNCTION
+ SCI_GETDIRECTPOINTER
+ SCI_GETCHARACTERPOINTER
+
+ +

On Windows, the message-passing scheme used to communicate between the container and + Scintilla is mediated by the operating system SendMessage function and can lead to + bad performance when calling intensively. To avoid this overhead, Scintilla provides messages + that allow you to call the Scintilla message function directly. The code to do this in C/C++ is + of the form:

+
+#include "Scintilla.h"
+SciFnDirect pSciMsg = (SciFnDirect)SendMessage(hSciWnd, SCI_GETDIRECTFUNCTION, 0, 0);
+sptr_t pSciWndData = (sptr_t)SendMessage(hSciWnd, SCI_GETDIRECTPOINTER, 0, 0);
+
+// now a wrapper to call Scintilla directly
+sptr_t CallScintilla(unsigned int iMessage, uptr_t wParam, sptr_t lParam){
+    return pSciMsg(pSciWndData, iMessage, wParam, lParam);
+}
+
+ +

SciFnDirect, sptr_t and uptr_t are declared in + Scintilla.h. hSciWnd is the window handle returned when you created + the Scintilla window.

+ +

While faster, this direct calling will cause problems if performed from a different thread + to the native thread of the Scintilla window in which case SendMessage(hSciWnd, SCI_*, + wParam, lParam) should be used to synchronize with the window's thread.

+ +

This feature also works on GTK+ but has no significant impact on speed.

+ +

From version 1.47 on Windows, Scintilla exports a function called + Scintilla_DirectFunction that can be used the same as the function returned by + SCI_GETDIRECTFUNCTION. This saves you the call to + SCI_GETDIRECTFUNCTION and the need to call Scintilla indirectly via the function + pointer.

+ +

SCI_GETDIRECTFUNCTION
+ This message returns the address of the function to call to handle Scintilla messages without + the overhead of passing through the Windows messaging system. You need only call this once, + regardless of the number of Scintilla windows you create.

+ +

SCI_GETDIRECTPOINTER
+ This returns a pointer to data that identifies which Scintilla window is in use. You must call + this once for each Scintilla window you create. When you call the direct function, you must + pass in the direct pointer associated with the target window.

+ +

SCI_GETCHARACTERPOINTER
+ Move the gap within Scintilla so that the text of the document is stored consecutively + and ensure there is a NUL character after the text, then return a pointer to the first character. + Applications may then pass this to a function that accepts a character pointer such as a regular + expression search or a parser. The pointer should not be written to as that may desynchronize + the internal state of Scintilla.

+

Since any action in Scintilla may change its internal state + this pointer becomes invalid after any call or by allowing user interface activity. The application + should reacquire the pointer after making any call to Scintilla or performing any user-interface calls such + as modifying a progress indicator.

+

This call takes similar time to inserting a character at the end of the document and this may + include moving the document contents. Specifically, all the characters after the document gap + are moved to before the gap. This compacted state should persist over calls and user interface + actions that do not change the document contents so reacquiring the pointer afterwards is very + quick. If this call is used to implement a global replace operation, then each replacement will + move the gap so if SCI_GETCHARACTERPOINTER is called after + each replacement then the operation will become O(n^2) rather than O(n). Instead, all + matches should be found and remembered, then all the replacements performed.

+ +

Multiple views

+ +

A Scintilla window and the document that it displays are separate entities. When you create + a new window, you also create a new, empty document. Each document has a reference count that + is initially set to 1. The document also has a list of the Scintilla windows that are linked to + it so when any window changes the document, all other windows in which it appears are notified + to cause them to update. The system is arranged in this way so that you can work with many + documents in a single Scintilla window and so you can display a single document in multiple + windows (for use with splitter windows).

+ +

Although these messages use document *pDoc, to ensure compatibility with future + releases of Scintilla you should treat pDoc as an opaque void*. That + is, you can use and store the pointer as described in this section but you should not + dereference it.

+ SCI_GETDOCPOINTER
+ SCI_SETDOCPOINTER(<unused>, document + *pDoc)
+ SCI_CREATEDOCUMENT
+ SCI_ADDREFDOCUMENT(<unused>, document + *pDoc)
+ SCI_RELEASEDOCUMENT(<unused>, document + *pDoc)
+
+ +

SCI_GETDOCPOINTER
+ This returns a pointer to the document currently in use by the window. It has no other + effect.

+ +

SCI_SETDOCPOINTER(<unused>, document *pDoc)
+ This message does the following:
+ 1. It removes the current window from the list held by the current document.
+ 2. It reduces the reference count of the current document by 1.
+ 3. If the reference count reaches 0, the document is deleted.
+ 4. pDoc is set as the new document for the window.
+ 5. If pDoc was 0, a new, empty document is created and attached to the + window.
+ 6. If pDoc was not 0, its reference count is increased by 1.

+ +

SCI_CREATEDOCUMENT
+ This message creates a new, empty document and returns a pointer to it. This document is not + selected into the editor and starts with a reference count of 1. This means that you have + ownership of it and must either reduce its reference count by 1 after using + SCI_SETDOCPOINTER so that the Scintilla window owns it or you must make sure that + you reduce the reference count by 1 with SCI_RELEASEDOCUMENT before you close the + application to avoid memory leaks.

+ +

SCI_ADDREFDOCUMENT(<unused>, document *pDoc)
+ This increases the reference count of a document by 1. If you want to replace the current + document in the Scintilla window and take ownership of the current document, for example if you + are editing many documents in one window, do the following:
+ 1. Use SCI_GETDOCPOINTER to get a pointer to the document, + pDoc.
+ 2. Use SCI_ADDREFDOCUMENT(0, pDoc) to increment the reference count.
+ 3. Use SCI_SETDOCPOINTER(0, pNewDoc) to set a different document or + SCI_SETDOCPOINTER(0, 0) to set a new, empty document.

+ +

SCI_RELEASEDOCUMENT(<unused>, document *pDoc)
+ This message reduces the reference count of the document identified by pDoc. pDoc + must be the result of SCI_GETDOCPOINTER or SCI_CREATEDOCUMENT and + must point at a document that still exists. If you call this on a document with a reference + count of 1 that is still attached to a Scintilla window, bad things will happen. To keep the + world spinning in its orbit you must balance each call to SCI_CREATEDOCUMENT or + SCI_ADDREFDOCUMENT with a call to SCI_RELEASEDOCUMENT.

+ +

Background loading and saving

+ +

To ensure a responsive user interface, applications may decide to load and save documents using a separate thread + from the user interface.

+ +

Loading in the background

+ +

An application can load all of a file into a buffer it allocates on a background thread and then add the data in that buffer + into a Scintilla document on the user interface thread. That technique uses extra memory to store a complete copy of the + file and also means that the time that Scintilla takes to perform initial line end discovery blocks the user interface.

+ +

To avoid these issues, a loader object may be created and used to load the file. The loader object supports the ILoader interface.

+ +

SCI_CREATELOADER(int bytes)
+ Create an object that supports the ILoader interface which can be used to load data and then + be turned into a Scintilla document object for attachment to a view object. + The bytes argument determines the initial memory allocation for the document as it is more efficient + to allocate once rather than rely on the buffer growing as data is added. + If SCI_CREATELOADER fails then 0 is returned.

+ +

ILoader

+ +
+class ILoader {
+public:
+        virtual int SCI_METHOD Release() = 0;
+        // Returns a status code from SC_STATUS_*
+        virtual int SCI_METHOD AddData(char *data, int length) = 0;
+        virtual void * SCI_METHOD ConvertToDocument() = 0;
+};
+
+ +

The application should call the AddData method with each block of data read from the file. + AddData will return SC_STATUS_OK unless a failure, such as memory exhaustion occurs. + If a failure occurs in AddData or in a file reading call then loading can be abandoned and the loader released with + the Release call. + When the whole file has been read, the ConvertToDocument method should be called to produce a Scintilla + document pointer which can be used in the same way as a document pointer returned from + SCI_CREATEDOCUMENT. + There is no need to call Release after ConvertToDocument.

+ +

Saving in the background

+ +

An application that wants to save in the background should lock the document with SCI_SETREADONLY(1) + to prevent modifications and retrieve a pointer to the unified document contents with + SCI_GETCHARACTERPOINTER. + The buffer of a locked document will not move so the pointer is valid until the application calls SCI_SETREADONLY(0).

+ +

If the user tries to performs a modification while the document is locked then a SCN_MODIFYATTEMPTRO notification is sent to the application. + The application may then decide to ignore the modification or to terminate the background saving thread and reenable + modification before returning from the notification.

+ +

Folding

+ +

The fundamental operation in folding is making lines invisible or visible. Line visibility + is a property of the view rather than the document so each view may be displaying a different + set of lines. From the point of view of the user, lines are hidden and displayed using fold + points. Generally, the fold points of a document are based on the hierarchical structure of the + document contents. In Python, the hierarchy is determined by indentation and in C++ by brace + characters. This hierarchy can be represented within a Scintilla document object by attaching a + numeric "fold level" to each line. The fold level is most easily set by a lexer, but you can + also set it with messages.

+ +

It is up to your code to set the connection between user actions and folding and unfolding. + The best way to see how this is done is to search the SciTE source code for the messages used + in this section of the documentation and see how they are used. You will also need to use + markers and a folding margin to complete your folding implementation. + The "fold" property should be set to "1" with + SCI_SETPROPERTY("fold", "1") to enable folding.

+ SCI_VISIBLEFROMDOCLINE(int + docLine)
+ SCI_DOCLINEFROMVISIBLE(int + displayLine)
+ SCI_SHOWLINES(int lineStart, int lineEnd)
+ SCI_HIDELINES(int lineStart, int lineEnd)
+ SCI_GETLINEVISIBLE(int line)
+ SCI_GETALLLINESVISIBLE
+ SCI_SETFOLDLEVEL(int line, int level)
+ SCI_GETFOLDLEVEL(int line)
+ SCI_SETFOLDFLAGS(int flags)
+ SCI_GETLASTCHILD(int line, int level)
+ SCI_GETFOLDPARENT(int line)
+ SCI_SETFOLDEXPANDED(int line, bool + expanded)
+ SCI_GETFOLDEXPANDED(int line)
+ SCI_CONTRACTEDFOLDNEXT(int lineStart)
+ SCI_TOGGLEFOLD(int line)
+ SCI_ENSUREVISIBLE(int line)
+ SCI_ENSUREVISIBLEENFORCEPOLICY(int + line)
+
+ +

SCI_VISIBLEFROMDOCLINE(int docLine)
+ When some lines are folded, then a particular line in the document may be displayed at a + different position to its document position. If no lines are folded, this message returns + docLine. Otherwise, this returns the display line (counting the very first visible + line as 0). The display line of an invisible line is the same as the previous visible line. The + display line number of the first line in the document is 0. If there is folding and + docLine is outside the range of lines in the document, the return value is -1. + Lines can occupy more than one display line if they wrap.

+ +

SCI_DOCLINEFROMVISIBLE(int displayLine)
+ When some lines are hidden, then a particular line in the document may be displayed at a + different position to its document position. This message returns the document line number that + corresponds to a display line (counting the display line of the first line in the document as + 0). If displayLine is less than or equal to 0, the result is 0. If + displayLine is greater than or equal to the number of displayed lines, the result + is the number of lines in the document.

+ +

SCI_SHOWLINES(int lineStart, int lineEnd)
+ SCI_HIDELINES(int lineStart, int lineEnd)
+ SCI_GETLINEVISIBLE(int line)
+ SCI_GETALLLINESVISIBLE
+ The first two messages mark a range of lines as visible or invisible and then redraw the + display. + SCI_GETLINEVISIBLE reports on the visible state of a line and returns 1 if it is + visible and 0 if it is not visible. + SCI_GETALLLINESVISIBLE returns 1 if all lines are visible and 0 + if some lines are hidden. + These messages have no effect on fold levels or fold + flags. The first line can not be hidden.

+ +

SCI_SETFOLDLEVEL(int line, int level)
+ SCI_GETFOLDLEVEL(int line)
+ These two messages set and get a 32-bit value that contains the fold level of a line and some + flags associated with folding. The fold level is a number in the range 0 to + SC_FOLDLEVELNUMBERMASK (4095). However, the initial fold level is set to + SC_FOLDLEVELBASE (1024) to allow unsigned arithmetic on folding levels. There are + two addition flag bits. SC_FOLDLEVELWHITEFLAG indicates that the line is blank and + allows it to be treated slightly different then its level may indicate. For example, blank + lines should generally not be fold points and will be considered part of the preceding section even though + they may have a lesser fold level. + SC_FOLDLEVELHEADERFLAG indicates that + the line is a header (fold point).

+ +

Use SCI_GETFOLDLEVEL(line) & SC_FOLDLEVELNUMBERMASK to get the fold level + of a line. Likewise, use SCI_GETFOLDLEVEL(line) & SC_FOLDLEVEL*FLAG to get the + state of the flags. To set the fold level you must or in the associated flags. For instance, to + set the level to thisLevel and mark a line as being a fold point use: + SCI_SETFOLDLEVEL(line, thisLevel | SC_FOLDLEVELHEADERFLAG).

+ If you use a lexer, you should not need to use SCI_SETFOLDLEVEL as this is far + better handled by the lexer. You will need to use SCI_GETFOLDLEVEL to decide how + to handle user folding requests. If you do change the fold levels, the folding margin will + update to match your changes. + +

SCI_SETFOLDFLAGS(int flags)
+ In addition to showing markers in the folding margin, you can indicate folds to the user by + drawing lines in the text area. The lines are drawn in the foreground colour set for STYLE_DEFAULT. Bits set in + flags determine where folding lines are drawn:
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SymbolValueEffect
1Experimental feature that has been removed.
SC_FOLDFLAG_LINEBEFORE_EXPANDED2Draw above if expanded
SC_FOLDFLAG_LINEBEFORE_CONTRACTED4Draw above if not expanded
SC_FOLDFLAG_LINEAFTER_EXPANDED8Draw below if expanded
SC_FOLDFLAG_LINEAFTER_CONTRACTED16Draw below if not expanded
SC_FOLDFLAG_LEVELNUMBERS64display hexadecimal fold levels in line margin to aid debugging of + folding. The appearance of this feature may change in the future.
+ +

This message causes the display to redraw.

+ +

SCI_GETLASTCHILD(int startLine, int level)
+ This message searches for the next line after startLine, that has a folding level + that is less than or equal to level and then returns the previous line number. If + you set level to -1, level is set to the folding level of line + startLine. If from is a fold point, SCI_GETLASTCHILD(from, + -1) returns the last line that would be in made visible or hidden by toggling the fold + state.

+ +

SCI_GETFOLDPARENT(int startLine)
+ This message returns the line number of the first line before startLine that is + marked as a fold point with SC_FOLDLEVELHEADERFLAG and has a fold level less than + the startLine. If no line is found, or if the header flags and fold levels are + inconsistent, the return value is -1.

+ +

SCI_TOGGLEFOLD(int line)
+ Each fold point may be either expanded, displaying all its child lines, or contracted, hiding + all the child lines. This message toggles the folding state of the given line as long as it has + the SC_FOLDLEVELHEADERFLAG set. This message takes care of folding or expanding + all the lines that depend on the line. The display updates after this message.

+ +

SCI_SETFOLDEXPANDED(int line, bool expanded)
+ SCI_GETFOLDEXPANDED(int line)
+ These messages set and get the expanded state of a single line. The set message has no effect + on the visible state of the line or any lines that depend on it. It does change the markers in + the folding margin. If you ask for the expansion state of a line that is outside the document, + the result is false (0).

+ +

If you just want to toggle the fold state of one line and handle all the lines that are + dependent on it, it is much easier to use SCI_TOGGLEFOLD. You would use the + SCI_SETFOLDEXPANDED message to process many folds without updating the display + until you had finished. See SciTEBase::FoldAll() and + SciTEBase::Expand() for examples of the use of these messages.

+ +

SCI_CONTRACTEDFOLDNEXT(int lineStart)
+ Search efficiently for lines that are contracted fold headers. + This is useful when saving the user's folding when switching documents or saving folding with a file. + The search starts at line number lineStart and continues forwards to the end of the file. + lineStart is returned if it is a contracted fold header otherwise the next contracted + fold header is returned. If there are no more contracted fold headers then -1 is returned.

+ +

SCI_ENSUREVISIBLE(int line)
+ SCI_ENSUREVISIBLEENFORCEPOLICY(int line)
+ A line may be hidden because more than one of its parent lines is contracted. Both these + message travels up the fold hierarchy, expanding any contracted folds until they reach the top + level. The line will then be visible. If you use SCI_ENSUREVISIBLEENFORCEPOLICY, + the vertical caret policy set by SCI_SETVISIBLEPOLICY is then applied.

+ +

Line wrapping

+ + SCI_SETWRAPMODE(int wrapMode)
+ SCI_GETWRAPMODE
+ SCI_SETWRAPVISUALFLAGS(int wrapVisualFlags)
+ SCI_GETWRAPVISUALFLAGS
+ SCI_SETWRAPVISUALFLAGSLOCATION(int wrapVisualFlagsLocation)
+ SCI_GETWRAPVISUALFLAGSLOCATION
+ SCI_SETWRAPINDENTMODE(int indentMode)
+ SCI_GETWRAPINDENTMODE
+ SCI_SETWRAPSTARTINDENT(int indent)
+ SCI_GETWRAPSTARTINDENT
+ SCI_SETLAYOUTCACHE(int cacheMode)
+ SCI_GETLAYOUTCACHE
+ SCI_SETPOSITIONCACHE(int size)
+ SCI_GETPOSITIONCACHE
+ SCI_LINESSPLIT(int pixelWidth)
+ SCI_LINESJOIN
+ SCI_WRAPCOUNT(int docLine)
+
+ +

By default, Scintilla does not wrap lines of text. If you enable line wrapping, lines wider + than the window width are continued on the following lines. Lines are broken after space or tab + characters or between runs of different styles. If this is not possible because a word in one + style is wider than the window then the break occurs after the last character that completely + fits on the line. The horizontal scroll bar does not appear when wrap mode is on.

+ +

For wrapped lines Scintilla can draw visual flags (little arrows) at end of a a subline of a + wrapped line and at begin of the next subline. These can be enabled individually, but if Scintilla + draws the visual flag at the beginning of the next subline this subline will be indented by one char. + Independent from drawing a visual flag at the begin the subline can have an indention.

+ +

Much of the time used by Scintilla is spent on laying out and drawing text. The same text + layout calculations may be performed many times even when the data used in these calculations + does not change. To avoid these unnecessary calculations in some circumstances, the line layout + cache can store the results of the calculations. The cache is invalidated whenever the + underlying data, such as the contents or styling of the document changes. Caching the layout of + the whole document has the most effect, making dynamic line wrap as much as 20 times faster but + this requires 7 times the memory required by the document contents plus around 80 bytes per + line.

+ +

Wrapping is not performed immediately there is a change but is delayed until the display + is redrawn. This delay improves peformance by allowing a set of changes to be performed + and then wrapped and displayed once. Because of this, some operations may not occur as + expected. If a file is read and the scroll position moved to a particular line in the text, + such as occurs when a container tries to restore a previous editing session, then + the scroll position will have been determined before wrapping so an unexpected range + of text will be displayed. To scroll to the position correctly, delay the scroll until the + wrapping has been performed by waiting for an initial + SCN_PAINTED notification.

+ +

SCI_SETWRAPMODE(int wrapMode)
+ SCI_GETWRAPMODE
+ Set wrapMode to SC_WRAP_WORD (1) to enable wrapping + on word boundaries, SC_WRAP_CHAR (2) to enable wrapping + between any characters, and to SC_WRAP_NONE (0) to disable line + wrapping. SC_WRAP_CHAR is preferred to + SC_WRAP_WORD for Asian languages where there is no white space + between words.

+ + +

SCI_SETWRAPVISUALFLAGS(int wrapVisualFlags)
+ SCI_GETWRAPVISUALFLAGS
+ You can enable the drawing of visual flags to indicate a line is wrapped. Bits set in + wrapVisualFlags determine which visual flags are drawn. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SymbolValueEffect
SC_WRAPVISUALFLAG_NONE0No visual flags
SC_WRAPVISUALFLAG_END1Visual flag at end of subline of a wrapped line.
SC_WRAPVISUALFLAG_START2Visual flag at begin of subline of a wrapped line.
+ Subline is indented by at least 1 to make room for the flag.
+
+ +

SCI_SETWRAPVISUALFLAGSLOCATION(int wrapVisualFlagsLocation)
+ SCI_GETWRAPVISUALFLAGSLOCATION
+ You can set whether the visual flags to indicate a line is wrapped are drawn near the border or near the text. + Bits set in wrapVisualFlagsLocation set the location to near the text for the corresponding visual flag. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SymbolValueEffect
SC_WRAPVISUALFLAGLOC_DEFAULT0Visual flags drawn near border
SC_WRAPVISUALFLAGLOC_END_BY_TEXT1Visual flag at end of subline drawn near text
SC_WRAPVISUALFLAGLOC_START_BY_TEXT2Visual flag at beginning of subline drawn near text
+ +

SCI_SETWRAPINDENTMODE(int indentMode)
+ SCI_GETWRAPINDENTMODE
+ Wrapped sublines can be indented to the position of their first subline or one more indent level. + The default is SC_WRAPINDENT_FIXED. + The modes are: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SymbolValueEffect
SC_WRAPINDENT_FIXED0Wrapped sublines aligned to left of window plus amount set by + SCI_SETWRAPSTARTINDENT
SC_WRAPINDENT_SAME1Wrapped sublines are aligned to first subline indent
SC_WRAPINDENT_INDENT2Wrapped sublines are aligned to first subline indent plus one more level of indentation
+ +

SCI_SETWRAPSTARTINDENT(int indent)
+ SCI_GETWRAPSTARTINDENT
+ SCI_SETWRAPSTARTINDENT sets the size of indentation of sublines for + wrapped lines in terms of the average character width in + STYLE_DEFAULT. + There are no limits on indent sizes, but values less than 0 or large values may have + undesirable effects.
+ The indention of sublines is independent of visual flags, but if + SC_WRAPVISUALFLAG_START is set an indent of at least 1 is used. +

+ +

SCI_SETLAYOUTCACHE(int cacheMode)
+ SCI_GETLAYOUTCACHE
+ You can set cacheMode to one of the symbols in the table:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SymbolValueLayout cached for these lines
SC_CACHE_NONE0No lines are cached.
SC_CACHE_CARET1The line containing the text caret. This is the default.
SC_CACHE_PAGE2Visible lines plus the line containing the caret.
SC_CACHE_DOCUMENT3All lines in the document.
+ +

SCI_SETPOSITIONCACHE(int size)
+ SCI_GETPOSITIONCACHE
+ The position cache stores position information for short runs of text + so that their layout can be determined more quickly if the run recurs. + The size in entries of this cache can be set with SCI_SETPOSITIONCACHE.

+ +

SCI_LINESSPLIT(int pixelWidth)
+ Split a range of lines indicated by the target into lines that are at most pixelWidth wide. + Splitting occurs on word boundaries wherever possible in a similar manner to line wrapping. + When pixelWidth is 0 then the width of the window is used. +

+ +

SCI_LINESJOIN
+ Join a range of lines indicated by the target into one line by + removing line end characters. + Where this would lead to no space between words, an extra space is inserted. +

+ +

SCI_WRAPCOUNT(int docLine)
+ Document lines can occupy more than one display line if they wrap and this + returns the number of display lines needed to wrap a document line.

+ +

Zooming

+ +

Scintilla incorporates a "zoom factor" that lets you make all the text in the document + larger or smaller in steps of one point. The displayed point size never goes below 2, whatever + zoom factor you set. You can set zoom factors in the range -10 to +20 points.

+ SCI_ZOOMIN
+ SCI_ZOOMOUT
+ SCI_SETZOOM(int zoomInPoints)
+ SCI_GETZOOM
+
+ +

SCI_ZOOMIN
+ SCI_ZOOMOUT
+ SCI_ZOOMIN increases the zoom factor by one point if the current zoom factor is + less than 20 points. SCI_ZOOMOUT decreases the zoom factor by one point if the + current zoom factor is greater than -10 points.

+ +

SCI_SETZOOM(int zoomInPoints)
+ SCI_GETZOOM
+ These messages let you set and get the zoom factor directly. There is no limit set on the + factors you can set, so limiting yourself to -10 to +20 to match the incremental zoom functions + is a good idea.

+ +

Long lines

+ +

You can choose to mark lines that exceed a given length by drawing a vertical line or by + colouring the background of characters that exceed the set length.

+ SCI_SETEDGEMODE(int mode)
+ SCI_GETEDGEMODE
+ SCI_SETEDGECOLUMN(int column)
+ SCI_GETEDGECOLUMN
+ SCI_SETEDGECOLOUR(int colour)
+ SCI_GETEDGECOLOUR
+
+ +

SCI_SETEDGEMODE(int edgeMode)
+ SCI_GETEDGEMODE
+ These two messages set and get the mode used to display long lines. You can set one of the + values in the table:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SymbolValueLong line display mode
EDGE_NONE0Long lines are not marked. This is the default state.
EDGE_LINE1A vertical line is drawn at the column number set by SCI_SETEDGECOLUMN. + This works well for monospaced fonts. The line is drawn at a position based on the width + of a space character in STYLE_DEFAULT, so it may not work very well if + your styles use proportional fonts or if your style have varied font sizes or you use a + mixture of bold, italic and normal text.
EDGE_BACKGROUND2The background colour of characters after the column limit is changed to the colour + set by SCI_SETEDGECOLOUR. This is recommended for proportional fonts.
+ +

SCI_SETEDGECOLUMN(int column)
+ SCI_GETEDGECOLUMN
+ These messages set and get the column number at which to display the long line marker. When + drawing lines, the column sets a position in units of the width of a space character in + STYLE_DEFAULT. When setting the background colour, the column is a character count + (allowing for tabs) into the line.

+ +

SCI_SETEDGECOLOUR(int colour)
+ SCI_GETEDGECOLOUR
+ These messages set and get the colour of the marker used to show that a line has exceeded the + length set by SCI_SETEDGECOLUMN.

+ +

Lexer

+ +

If you define the symbol SCI_LEXER when building Scintilla, (this is sometimes + called the SciLexer version of Scintilla), lexing support for a wide range of programming + languages is included and the messages in this section are supported. If you want to set + styling and fold points for an unsupported language you can either do this in the container or + better still, write your own lexer following the pattern of one of the existing ones.

+ +

Scintilla also supports external lexers. These are DLLs (on Windows) or .so modules (on GTK+/Linux) that export three + functions: GetLexerCount, GetLexerName, and + GetLexerFactory. See externalLexer.cxx for more.

+ SCI_SETLEXER(int lexer)
+ SCI_GETLEXER
+ SCI_SETLEXERLANGUAGE(<unused>, const char + *name)
+ SCI_GETLEXERLANGUAGE(<unused>, char + *name)
+ SCI_LOADLEXERLIBRARY(<unused>, const char + *path)
+ SCI_COLOURISE(int start, int end)
+ SCI_CHANGELEXERSTATE(int start, int end)
+ SCI_PROPERTYNAMES(<unused>, char *names)
+ SCI_PROPERTYTYPE(const char *name)
+ SCI_DESCRIBEPROPERTY(const char *name, char *description)
+ SCI_SETPROPERTY(const char *key, const char *value)
+ SCI_GETPROPERTY(const char *key, char *value)
+ SCI_GETPROPERTYEXPANDED(const char *key, char *value)
+ SCI_GETPROPERTYINT(const char *key, int default)
+ SCI_DESCRIBEKEYWORDSETS(<unused>, char *descriptions)
+ SCI_SETKEYWORDS(int keyWordSet, const char + *keyWordList)
+ SCI_GETSTYLEBITSNEEDED +
+
+ +

SCI_SETLEXER(int lexer)
+ SCI_GETLEXER
+ You can select the lexer to use with an integer code from the SCLEX_* enumeration + in Scintilla.h. There are two codes in this sequence that do not use lexers: + SCLEX_NULL to select no lexing action and SCLEX_CONTAINER which sends + the SCN_STYLENEEDED notification to + the container whenever a range of text needs to be styled. You cannot use the + SCLEX_AUTOMATIC value; this identifies additional external lexers that Scintilla + assigns unused lexer numbers to.

+ +

SCI_SETLEXERLANGUAGE(<unused>, const char *name)
+ SCI_GETLEXERLANGUAGE(<unused>, char *name)
+ SCI_SETLEXERLANGUAGE lets you select a lexer by name, and is the only method if you are using an + external lexer or if you have written a lexer module for a language of your own and do not wish + to assign it an explicit lexer number. To select an existing lexer, set name to + match the (case sensitive) name given to the module, for example "ada" or "python", not "Ada" + or "Python". To locate the name for the built-in lexers, open the relevant + Lex*.cxx file and search for LexerModule. The third argument in the + LexerModule constructor is the name to use.

+ +

To test if your lexer assignment worked, use SCI_GETLEXER before and after setting the new lexer to + see if the lexer number changed.

+ +

SCI_GETLEXERLANGUAGE retrieves the name of the lexer.

+ +

SCI_LOADLEXERLIBRARY(<unused>, const char *path)
+ Load a lexer implemented in a shared library. This is a .so file on GTK+/Linux or a .DLL file on Windows. +

+ +

SCI_COLOURISE(int startPos, int endPos)
+ This requests the current lexer or the container (if the lexer is set to + SCLEX_CONTAINER) to style the document between startPos and + endPos. If endPos is -1, the document is styled from + startPos to the end. If the "fold" property is set to + "1" and your lexer or container supports folding, fold levels are also set. This + message causes a redraw.

+ +

SCI_CHANGELEXERSTATE(int startPos, int endPos)
+ Indicate that the internal state of a lexer has changed over a range and therefore + there may be a need to redraw.

+ +

SCI_PROPERTYNAMES(<unused>, char *names)
+ SCI_PROPERTYTYPE(const char *name)
+ SCI_DESCRIBEPROPERTY(const char *name, char *description)
+ Information may be retrieved about the properties that can be set for the current lexer. + This information is only available for newer lexers. + SCI_PROPERTYNAMES returns a string with all of the valid properties separated by "\n". + If the lexer does not support this call then an empty string is returned. + Properties may be boolean (SC_TYPE_BOOLEAN), integer (SC_TYPE_INTEGER), + or string (SC_TYPE_STRING) and this is found with SCI_PROPERTYTYPE. + A description of a property in English is returned by SCI_DESCRIBEPROPERTY.

+ +

SCI_SETPROPERTY(const char *key, const char *value)
+ You can communicate settings to lexers with keyword:value string pairs. There is no limit to + the number of keyword pairs you can set, other than available memory. key is a + case sensitive keyword, value is a string that is associated with the keyword. If + there is already a value string associated with the keyword, it is replaced. If you pass a zero + length string, the message does nothing. Both key and value are used + without modification; extra spaces at the beginning or end of key are + significant.

+ +

The value string can refer to other keywords. For example, + SCI_SETPROPERTY("foldTimes10", "$(fold)0") stores the string + "$(fold)0", but when this is accessed, the $(fold) is replaced by the + value of the "fold" keyword (or by nothing if this keyword does not exist).

+ +

Currently the "fold" property is defined for most of the lexers to set the fold structure if + set to "1". SCLEX_PYTHON understands "tab.timmy.whinge.level" as a + setting that determines how to indicate bad indentation. Most keywords have values that are + interpreted as integers. Search the lexer sources for GetPropertyInt to see how + properties are used.

+ +

There is a convention for naming properties used by lexers so that the set of properties can be found by scripts. + Property names should start with "lexer.<lexer>." or "fold.<lexer>." when they apply to one + lexer or start with "lexer." or "fold." if they apply to multiple lexers.

+ +

Applications may discover the set of properties used by searching the source code of lexers for lines that contain + GetProperty and a double quoted string and extract the value of the double quoted string as the property name. + The scintilla/src/LexGen.py script does this and can be used as an example. + Documentation for the property may be located above the call as a multi-line comment starting with +
// property <property-name>

+ +

SCI_GETPROPERTY(const char *key, char *value)
+ Lookup a keyword:value pair using the specified key; if found, copy the value to the user-supplied + buffer and return the length (not including the terminating 0). If not found, copy an empty string + to the buffer and return 0.

+ +

Note that "keyword replacement" as described in + SCI_SETPROPERTY will not be performed.

+ +

If the value argument is 0 then the length that should be allocated to store the value is returned; + again, the terminating 0 is not included.

+ +

SCI_GETPROPERTYEXPANDED(const char *key, char *value)
+ Lookup a keyword:value pair using the specified key; if found, copy the value to the user-supplied + buffer and return the length (not including the terminating 0). If not found, copy an empty string + to the buffer and return 0.

+ +

Note that "keyword replacement" as described in + SCI_SETPROPERTY will be performed.

+ +

If the value argument is 0 then the length that should be allocated to store the value (including any indicated keyword replacement) + is returned; again, the terminating 0 is not included.

+ +

SCI_GETPROPERTYINT(const char *key, int default)
+ Lookup a keyword:value pair using the specified key; if found, interpret the value as an integer and return it. + If not found (or the value is an empty string) then return the supplied default. If the keyword:value pair is found but is not + a number, then return 0.

+ +

Note that "keyword replacement" as described in + SCI_SETPROPERTY will be performed before any numeric interpretation.

+ +

SCI_SETKEYWORDS(int keyWordSet, const char *keyWordList)
+ You can set up to 9 lists of keywords for use by the current lexer. This was increased from 6 + at revision 1.50. keyWordSet can be 0 to 8 (actually 0 to KEYWORDSET_MAX) + and selects which keyword list to replace. keyWordList is a list of keywords + separated by spaces, tabs, "\n" or "\r" or any combination of these. + It is expected that the keywords will be composed of standard ASCII printing characters, + but there is nothing to stop you using any non-separator character codes from 1 to 255 + (except common sense).

+ +

How these keywords are used is entirely up to the lexer. Some languages, such as HTML may + contain embedded languages, VBScript and JavaScript are common for HTML. For HTML, key word set + 0 is for HTML, 1 is for JavaScript and 2 is for VBScript, 3 is for Python, 4 is for PHP and 5 + is for SGML and DTD keywords. Review the lexer code to see examples of keyword list. A fully + conforming lexer sets the fourth argument of the LexerModule constructor to be a + list of strings that describe the uses of the keyword lists.

+ +

Alternatively, you might use set 0 for general keywords, set 1 for keywords that cause + indentation and set 2 for keywords that cause unindentation. Yet again, you might have a simple + lexer that colours keywords and you could change languages by changing the keywords in set 0. + There is nothing to stop you building your own keyword lists into the lexer, but this means + that the lexer must be rebuilt if more keywords are added.

+ +

SCI_DESCRIBEKEYWORDSETS(<unused>, char *descriptions)
+ A description of all of the keyword sets separated by "\n" is returned by SCI_DESCRIBEKEYWORDSETS.

+ +

SCI_GETSTYLEBITSNEEDED
+ Retrieve the number of bits the current lexer needs for styling. This should normally be the argument + to SCI_SETSTYLEBITS. +

+ +

Lexer Objects

+ +

Lexers are programmed as objects that implement the ILexer interface and that interact + with the document they are lexing through the IDocument interface. + Previously lexers were defined by providing lexing and folding functions but creating an object + to handle the interaction of a lexer with a document allows the lexer to store state information that + can be used during lexing. For example a C++ lexer may store a set of preprocessor definitions + or variable declarations and style these depending on their role.

+ +

A set of helper classes allows older lexers defined by functions to be used in Scintilla.

+

ILexer

+ +
+class ILexer {
+public:
+    virtual + int SCI_METHOD + Version() +const = + 0;
+    virtual + void SCI_METHOD + Release() += 0;
+    virtual +const +char +* +SCI_METHOD PropertyNames() + = 0;
+    virtual + int SCI_METHOD PropertyType(const char *name) = 0;
+    virtual + const char * SCI_METHOD DescribeProperty(const char *name) = 0;
+    virtual + int SCI_METHOD + PropertySet(const + char + *key, + const +char *val) + = + 0;
+    virtual +const char +* SCI_METHOD DescribeWordListSets() + = +0;
+    virtual + int SCI_METHOD + WordListSet(int + n, + const +char *wl) + = + 0;
+    virtual + void SCI_METHOD + Lex(unsigned + int + startPos, + int + lengthDoc, +int initStyle, + IDocument +*pAccess) + = +0;
+    virtual + void SCI_METHOD + Fold(unsigned + int startPos, + int + lengthDoc, +int initStyle, + IDocument +*pAccess) + = +0;
+    virtual + void +* SCI_METHOD +PrivateCall(int + operation, +void +*pointer) += 0;
+};
+
+ +

+The return values from PropertySet and WordListSet are used to indicate whether the change requires +performing lexing or folding over any of the document. It is the position at which to restart lexing and folding or -1 +if the change does not require any extra work on the document. +A simple approach is to return 0 if there is any possibility that a change requires lexing the document again while an +optimisation could be to remember where a setting first affects the document and return that position. +

+ +

Release is called to destroy the lexer object.

+ +

PrivateCall allows for direct communication between the +application and a lexer. An example would be where an application +maintains a single large data structure containing symbolic information +about system headers (like Windows.h) and provides this to the lexer +where it can be applied to each document. This avoids the costs of +constructing the system header information for each document. This is +invoked with the SCI_PRIVATELEXERCALL API.

+ +

Fold is called with the exact range that needs folding. +Previously, lexers were called with a range that started one line before the range that +needs to be folded as this allowed fixing up the last line from the previous folding. +The new approach allows the lexer to decide whether to backtrack or to handle this +more efficiently.

+ +

IDocument

+ +
+class IDocument + {
+public:
+    virtual + int SCI_METHOD + Version() +const = + 0;
+    virtual + void SCI_METHOD + SetErrorStatus(int + status) + = +0;
+    virtual + int SCI_METHOD + Length() +const = + 0;
+    virtual + void SCI_METHOD + GetCharRange(char + *buffer, + int +position, +int lengthRetrieve) + const + = +0;
+    virtual + char SCI_METHOD + StyleAt(int + position) +const = + 0;
+    virtual + int SCI_METHOD + LineFromPosition(int position) + const = + 0;
+    virtual +int SCI_METHOD + LineStart(int line) + const = + 0;
+    virtual +int SCI_METHOD + GetLevel(int line) + +const = +0;
+    virtual +int SCI_METHOD + SetLevel(int + line, +int level) + = +0;
+    virtual + int SCI_METHOD + GetLineState(int + line) + const += 0 +;
+    virtual + int SCI_METHOD + SetLineState(int + line, + int state) + = + 0;
+    virtual + void SCI_METHOD + StartStyling(int + position, + char mask) + = + 0;
+    virtual bool + SCI_METHOD + SetStyleFor(int + length, + char style) + = 0 +;
+     virtual + bool SCI_METHOD + SetStyles(int + length, +const char + *styles) + = +0;
+    virtual void + SCI_METHOD + DecorationSetCurrentIndicator(int + indicator) + = + 0;
+    virtual + void SCI_METHOD + DecorationFillRange(int + position, + int value, + int fillLength) + + = +0;
+    virtual + void SCI_METHOD + ChangeLexerState(int + start, + int end) + = + 0;
+    virtual + int SCI_METHOD + CodePage() + const += 0 +;
+    virtual bool + SCI_METHOD + IsDBCSLeadByte(char + ch) + const = + 0;
+};
+
+ +

Scintilla tries to minimize the consequences of modifying text to +only relex and redraw the line of the change where possible. Lexer +objects contain their own private extra state which can affect later +lines. For example, if the C++ lexer is greying out inactive code +segments then changing the statement #define BEOS 0 to #define + BEOS 1 may require restyling and redisplaying later parts of the + document. The lexer can call ChangeLexerState to signal to + the document that it should relex and display more.

+ +

SetErrorStatus is used to notify the document of +exceptions. Exceptions should not be thrown over build boundaries as the + two sides may be built with different compilers or incompatible +exception options.

+ +

The ILexer and IDocument interfaces may be +expanded in the future with extended versions (ILexer2...). + The Version method indicates which interface is +implemented and thus which methods may be called.

+ +

Notifications

+ +

Notifications are sent (fired) from the Scintilla control to its container when an event has + occurred that may interest the container. Notifications are sent using the + WM_NOTIFY message on Windows and the "notify" signal on GTK+. The container is + passed a SCNotification structure containing information about the event.

+
+struct NotifyHeader {   // This matches the Win32 NMHDR structure
+    void *hwndFrom;     // environment specific window handle/pointer
+    uptr_t idFrom;        // CtrlID of the window issuing the notification
+    unsigned int code;  // The SCN_* notification code
+};
+
+struct SCNotification {
+	struct Sci_NotifyHeader nmhdr;
+	int position;
+	/* SCN_STYLENEEDED, SCN_DOUBLECLICK, SCN_MODIFIED, SCN_MARGINCLICK, */
+	/* SCN_NEEDSHOWN, SCN_DWELLSTART, SCN_DWELLEND, SCN_CALLTIPCLICK, */
+	/* SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, SCN_HOTSPOTRELEASECLICK, */
+	/* SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */
+	/* SCN_USERLISTSELECTION, SCN_AUTOCSELECTION */
+
+	int ch;		/* SCN_CHARADDED, SCN_KEY */
+	int modifiers;
+	/* SCN_KEY, SCN_DOUBLECLICK, SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, */
+	/* SCN_HOTSPOTRELEASECLICK, SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */
+
+	int modificationType;	/* SCN_MODIFIED */
+	const char *text;
+	/* SCN_MODIFIED, SCN_USERLISTSELECTION, SCN_AUTOCSELECTION, SCN_URIDROPPED */
+
+	int length;		/* SCN_MODIFIED */
+	int linesAdded;	/* SCN_MODIFIED */
+	int message;	/* SCN_MACRORECORD */
+	uptr_t wParam;	/* SCN_MACRORECORD */
+	sptr_t lParam;	/* SCN_MACRORECORD */
+	int line;		/* SCN_MODIFIED */
+	int foldLevelNow;	/* SCN_MODIFIED */
+	int foldLevelPrev;	/* SCN_MODIFIED */
+	int margin;		/* SCN_MARGINCLICK */
+	int listType;	/* SCN_USERLISTSELECTION */
+	int x;			/* SCN_DWELLSTART, SCN_DWELLEND */
+	int y;		/* SCN_DWELLSTART, SCN_DWELLEND */
+	int token;		/* SCN_MODIFIED with SC_MOD_CONTAINER */
+	int annotationLinesAdded;	/* SCN_MODIFIED with SC_MOD_CHANGEANNOTATION */
+	int updated;	/* SCN_UPDATEUI */
+};
+
+ +

The notification messages that your container can choose to handle and the messages + associated with them are:

+ SCN_STYLENEEDED
+ SCN_CHARADDED
+ SCN_SAVEPOINTREACHED
+ SCN_SAVEPOINTLEFT
+ SCN_MODIFYATTEMPTRO
+ SCN_KEY
+ SCN_DOUBLECLICK
+ SCN_UPDATEUI
+ SCN_MODIFIED
+ SCN_MACRORECORD
+ SCN_MARGINCLICK
+ SCN_NEEDSHOWN
+ SCN_PAINTED
+ SCN_USERLISTSELECTION
+ SCN_URIDROPPED
+ SCN_DWELLSTART
+ SCN_DWELLEND
+ SCN_ZOOM
+ SCN_HOTSPOTCLICK
+ SCN_HOTSPOTDOUBLECLICK
+ SCN_HOTSPOTRELEASECLICK
+ SCN_INDICATORCLICK
+ SCN_INDICATORRELEASE
+ SCN_CALLTIPCLICK
+ SCN_AUTOCSELECTION
+ SCN_AUTOCCANCELLED
+ SCN_AUTOCCHARDELETED
+
+ +

The following SCI_* messages are associated with these notifications:

+ SCI_SETMODEVENTMASK(int eventMask)
+ SCI_GETMODEVENTMASK
+ SCI_SETMOUSEDWELLTIME(int milliseconds)
+ SCI_GETMOUSEDWELLTIME
+ SCI_SETIDENTIFIER(int identifier)
+ SCI_GETIDENTIFIER
+
+ +

The following additional notifications are sent using the WM_COMMAND message on + Windows and the "Command" signal on GTK+. This emulates the Windows Edit control. Only the lower + 16 bits of the control's ID is passed in these notifications.

+ SCEN_CHANGE
+ SCEN_SETFOCUS
+ SCEN_KILLFOCUS
+
+ +

SCI_SETIDENTIFIER(int identifier)
+ SCI_GETIDENTIFIER
+ These two messages set and get the identifier of the Scintilla instance which is included in notifications as the + idFrom field. + When an application creates multiple Scintilla widgets, this allows the source of each notification to be found. + On Windows, this value is initialised in the CreateWindow call and stored as the + GWLP_ID attribute of the window. + The value should be small, preferrably less than 16 bits, + rather than a pointer as some of the functions will only transmit 16 or 32 bits. +

+ +

SCN_STYLENEEDED
+ If you used SCI_SETLEXER(SCLEX_CONTAINER) to make the container act as the + lexer, you will receive this notification when Scintilla is about to display or print text that + requires styling. You are required to style the text from the line that contains the position + returned by SCI_GETENDSTYLED up to + the position passed in SCNotification.position. Symbolically, you need code of the + form:

+
+    startPos = SCI_GETENDSTYLED()
+    lineNumber = SCI_LINEFROMPOSITION(startPos);
+    startPos = SCI_POSITIONFROMLINE(lineNumber);
+    MyStyleRoutine(startPos, SCNotification.position);
+
+ +

SCN_CHARADDED
+ This is sent when the user types an ordinary text character (as opposed to a command + character) that is entered into the text. The container can use this to decide to display a call tip or an auto + completion list. The character is in SCNotification.ch. + This notification is sent before the character has been styled so processing that depends on + styling should instead be performed in the SCN_UPDATEUI notification.

+ +

SCN_SAVEPOINTREACHED
+ SCN_SAVEPOINTLEFT
+ Sent to the container when the save point is entered or left, allowing the container to + display a "document dirty" indicator and change its menus.
+ See also: SCI_SETSAVEPOINT, SCI_GETMODIFY

+ +

SCN_MODIFYATTEMPTRO
+ When in read-only mode, this notification is sent to the container if the user tries to change + the text. This can be used to check the document out of a version control system. You can set + the read-only state of a document with SCI_SETREADONLY.

+ +

SCN_KEY
+ Reports all keys pressed but not consumed by Scintilla. Used on GTK+ because of + some problems with keyboard focus and is not sent by the Windows version. SCNotification.ch holds the key code and + SCNotification.modifiers holds the modifiers. This notification is sent if the + modifiers include SCMOD_ALT or SCMOD_CTRL and the key code is less + than 256.

+ +

SCN_DOUBLECLICK
+ The mouse button was double clicked in editor. The position field is set to the text position of the + double click, the line field is set to the line of the double click, and + the modifiers field is set to the key modifiers + held down in a similar manner to SCN_KEY.

+ +

SCN_UPDATEUI
+ Either the text or styling of the document has changed or the selection range or scroll position has changed. + Now would be a good time to update any container UI elements that depend on document or view state. + The updated field is set to the bit set of things changed since the previous notification.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SymbolValueMeaning
SC_UPDATE_CONTENT0x01Contents, styling or markers have been changed.
SC_UPDATE_SELECTION0x02Selection has been changed.
SC_UPDATE_V_SCROLL0x04Scrolled vertically.
SC_UPDATE_H_SCROLL0x08Scrolled horizontally.
+ +

SCN_MODIFIED
+ This notification is sent when the text or styling of the document changes or is about to + change. You can set a mask for the notifications that are sent to the container with SCI_SETMODEVENTMASK. The + notification structure contains information about what changed, how the change occurred and + whether this changed the number of lines in the document. No modifications may be performed + while in a SCN_MODIFIED event. The SCNotification fields used + are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldUsage
modificationTypeA set of flags that identify the change(s) made. See the next + table.
positionStart position of a text or styling change. Set to 0 if not used.
lengthLength of the change in cells or characters when the text or styling + changes. Set to 0 if not used.
linesAddedNumber of added lines. If negative, the number of deleted lines. Set to + 0 if not used or no lines added or deleted.
textValid for text changes, not for style changes. If we are collecting undo + information this holds a pointer to the text that is handed to the Undo system, otherwise + it is zero. For user performed SC_MOD_BEFOREDELETE the text field is 0 and + for user performed SC_MOD_BEFOREINSERT the text field points to an array of cells, + not bytes and the length is the number of cells.
lineThe line number at which a fold level or marker change occurred. This is + 0 if unused and may be -1 if more than one line changed.
foldLevelNowThe new fold level applied to the line or 0 if this field is + unused.
foldLevelPrevThe previous folding level of the line or 0 if this field is + unused.
+ +

The SCNotification.modificationType field has bits set to tell you what has + been done. The SC_MOD_* bits correspond to actions. The + SC_PERFORMED_* bits tell you if the action was done by the user, or the result of + Undo or Redo of a previous action.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SymbolValueMeaningSCNotification fields
SC_MOD_INSERTTEXT0x01Text has been inserted into the document.position, length, text, linesAdded
SC_MOD_DELETETEXT0x02Text has been removed from the document.position, length, text, linesAdded
SC_MOD_CHANGESTYLE0x04A style change has occurred.position, length
SC_MOD_CHANGEFOLD0x08A folding change has occurred.line, foldLevelNow, foldLevelPrev
SC_PERFORMED_USER0x10Information: the operation was done by the user.None
SC_PERFORMED_UNDO0x20Information: this was the result of an Undo.None
SC_PERFORMED_REDO0x40Information: this was the result of a Redo.None
SC_MULTISTEPUNDOREDO0x80This is part of a multi-step Undo or Redo transaction.None
SC_LASTSTEPINUNDOREDO0x100This is the final step in an Undo or Redo transaction.None
SC_MOD_CHANGEMARKER0x200One or more markers has changed in a line.line
SC_MOD_BEFOREINSERT0x400Text is about to be inserted into the document.position, if performed by user then text in cells, length in cells
SC_MOD_BEFOREDELETE0x800Text is about to be deleted from the document.position, length
SC_MOD_CHANGEINDICATOR0x4000An indicator has been added or removed from a range of text.position, length
SC_MOD_CHANGELINESTATE0x8000A line state has changed because SCI_SETLINESTATE + was called.line
SC_MOD_LEXERSTATE0x80000The internal state of a lexer has changed over a range.position, length
SC_MOD_CHANGEMARGIN0x10000A text margin has changed.line
SC_MOD_CHANGEANNOTATION0x20000An annotation has changed.line
SC_MULTILINEUNDOREDO0x1000This is part of an Undo or Redo with multi-line changes.None
SC_STARTACTION0x2000This is set on a SC_PERFORMED_USER action when it is the + first or only step in an undo transaction. This can be used to integrate the Scintilla + undo stack with an undo stack in the container application by adding a Scintilla + action to the container's stack for the currently opened container transaction or + to open a new container transaction if there is no open container transaction. + None
SC_MOD_CONTAINER0x40000This is set on for actions that the container stored into the undo stack with + SCI_ADDUNDOACTION. + token
SC_MODEVENTMASKALL0x7FFFFThis is a mask for all valid flags. This is the default mask state set by SCI_SETMODEVENTMASK.None
+ +

SCEN_CHANGE
+ SCEN_CHANGE (768) is fired when the text (not the style) of the document changes. + This notification is sent using the WM_COMMAND message on Windows and the + "Command" signal on GTK+ as this is the behavior of the standard Edit control + (SCEN_CHANGE has the same value as the Windows Edit control + EN_CHANGE). No other information is sent. If you need more detailed information + use SCN_MODIFIED. You can filter the + types of changes you are notified about with SCI_SETMODEVENTMASK.

+ +

SCI_SETMODEVENTMASK(int eventMask)
+ SCI_GETMODEVENTMASK
+ These messages set and get an event mask that determines which document change events are + notified to the container with SCN_MODIFIED and SCEN_CHANGE. For example, a container may decide to see + only notifications about changes to text and not styling changes by calling + SCI_SETMODEVENTMASK(SC_MOD_INSERTTEXT|SC_MOD_DELETETEXT).

+ +

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.

+ +

SCEN_SETFOCUS
+ SCEN_KILLFOCUS
+ SCEN_SETFOCUS (512) is fired when Scintilla receives focus and + SCEN_KILLFOCUS (256) when it loses focus. These notifications are sent using the + WM_COMMAND message on Windows and the "Command" signal on GTK+ as this is the + behavior of the standard Edit control. Unfortunately, these codes do not match the Windows Edit + notification codes EN_SETFOCUS (256) and EN_KILLFOCUS (512). It is + now too late to change the Scintilla codes as clients depend on the current values.

+ +

SCN_MACRORECORD
+ The SCI_STARTRECORD and SCI_STOPRECORD messages enable and + disable macro recording. When enabled, each time a recordable change occurs, the + SCN_MACRORECORD notification is sent to the container. It is up to the container + to record the action. To see the complete list of SCI_* messages that are + recordable, search the Scintilla source Editor.cxx for + Editor::NotifyMacroRecord. The fields of SCNotification set in this + notification are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldUsage
messageThe SCI_* message that caused the notification.
wParamThe value of wParam in the SCI_* message.
lParamThe value of lParam in the SCI_* message.
+ +

SCN_MARGINCLICK
+ This notification tells the container that the mouse was clicked inside a margin that was marked as sensitive (see SCI_SETMARGINSENSITIVEN). This can be used to + perform folding or to place breakpoints. The following SCNotification fields are + used:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldUsage
modifiersThe appropriate combination of SCI_SHIFT, + SCI_CTRL and SCI_ALT to indicate the keys that were held down + at the time of the margin click.
positionThe position of the start of the line in the document that corresponds + to the margin click.
marginThe margin number that was clicked.
+ +

SCN_NEEDSHOWN
+ Scintilla has determined that a range of lines that is currently invisible should be made + visible. An example of where this may be needed is if the end of line of a contracted fold + point is deleted. This message is sent to the container in case it wants to make the line + visible in some unusual way such as making the whole document visible. Most containers will + just ensure each line in the range is visible by calling SCI_ENSUREVISIBLE. The position and + length fields of SCNotification indicate the range of the document + that should be made visible. The container code will be similar to the following code + skeleton:

+
+firstLine = SCI_LINEFROMPOSITION(scn.position)
+lastLine = SCI_LINEFROMPOSITION(scn.position+scn.length-1)
+for line = lineStart to lineEnd do SCI_ENSUREVISIBLE(line) next
+
+ +

SCN_PAINTED
+ Painting has just been done. Useful when you want to update some other widgets based on a + change in Scintilla, but want to have the paint occur first to appear more responsive. There is + no other information in SCNotification.

+ +

SCN_USERLISTSELECTION
+ The user has selected an item in a user list. The + SCNotification fields used are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldUsage
listTypeThis is set to the listType parameter from the SCI_USERLISTSHOW message that + initiated the list.
textThe text of the selection.
positionThe position the list was displayed at.
+
+ + +

SCN_URIDROPPED
+ Only on the GTK+ version. Indicates that the user has dragged a URI such as a file name or Web + address onto Scintilla. The container could interpret this as a request to open the file. The + text field of SCNotification points at the URI text.

+ +

SCN_DWELLSTART
+ SCN_DWELLEND
+ SCN_DWELLSTART is generated when the user keeps the mouse in one position for the + dwell period (see SCI_SETMOUSEDWELLTIME). SCN_DWELLEND is + generated after a SCN_DWELLSTART and the mouse is moved or other activity such as + key press indicates the dwell is over. Both notifications set the same fields in + SCNotification:

+ + + + + + + + + + + + + + + + + + + + + + + +
FieldUsage
positionThis is the nearest position in the document to the position where the + mouse pointer was lingering.
x, yWhere the pointer lingered. The position field is set to + SCI_POSITIONFROMPOINTCLOSE(x, y).
+
+ +

SCI_SETMOUSEDWELLTIME(int milliseconds)
+ SCI_GETMOUSEDWELLTIME
+ These two messages set and get the time the mouse must sit still, in milliseconds, to generate + a SCN_DWELLSTART notification. If + set to SC_TIME_FOREVER, the default, no dwell events are generated.

+ +

SCN_ZOOM
+ This notification is generated when the user zooms the display using the keyboard or the + SCI_SETZOOM method is called. This + notification can be used to recalculate positions, such as the width of the line number margin + to maintain sizes in terms of characters rather than pixels. SCNotification has no + additional information.

+ +

+ SCN_HOTSPOTCLICK
+ SCN_HOTSPOTDOUBLECLICK
+ SCN_HOTSPOTRELEASECLICK
+ These notifications are generated when the user clicks or double clicks on + text that is in a style with the hotspot attribute set. + This notification can be used to link to variable definitions or web pages. + The position field is set the text position of the click or + double click and the modifiers field set to the key modifiers + held down in a similar manner to SCN_KEY. + Only the state of the Ctrl key is reported for SCN_HOTSPOTRELEASECLICK.

+ +

+ SCN_INDICATORCLICK
+ SCN_INDICATORRELEASE
+ These notifications are generated when the user clicks or releases the mouse on + text that has an indicator. + The position field is set the text position of the click or + double click and the modifiers field set to the key modifiers + held down in a similar manner to SCN_KEY.

+ +

SCN_CALLTIPCLICK
+ This notification is generated when the user clicks on a calltip. + This notification can be used to display the next function prototype when a + function name is overloaded with different arguments. + The position field is set to 1 if the click is in an up arrow, + 2 if in a down arrow, and 0 if elsewhere.

+ +

SCN_AUTOCSELECTION
+ The user has selected an item in an autocompletion list. The + notification is sent before the selection is inserted. Automatic insertion can be cancelled by sending a + SCI_AUTOCCANCEL message + before returning from the notification. The SCNotification fields used are:

+ + + + + + + + + + + + + + + + + + + + + + +
FieldUsage
positionThe start position of the word being completed.
textThe text of the selection.
+ +

SCN_AUTOCCANCELLED
+ The user has cancelled an autocompletion list. + There is no other information in SCNotification.

+ +

SCN_AUTOCCHARDELETED
+ The user deleted a character while autocompletion list was active. + There is no other information in SCNotification.

+ +

Images

+ +

Two formats are supported for images used in margin markers and autocompletion lists, RGBA and XPM.

+ +

RGBA

+ +

The RGBA format allows translucency with an alpha + value for each pixel. It is simpler than + XPM and more capable.

+ +

The data is a sequence of 4 byte pixel values starting with the pixels for the top line, with the + leftmost pixel first, then continuing with the pixels for subsequent lines. There is no gap between + lines for alignment reasons.

+ +

Each pixel consists of, in order, a red byte, a green byte, a blue byte and an alpha byte. + The colour bytes are not premultiplied by the alpha value. That is, a fully red pixel that is + 25% opaque will be [FF, 00, 00, 3F]

+ +

Since the RGBA pixel data does not include any size information the + width and height must previously been set with the + SCI_RGBAIMAGESETWIDTH and + SCI_RGBAIMAGESETHEIGHT messages.

+ +

GUI platforms often include functions for reading image file formats like PNG into memory + in the RGBA form or a similar form. + If there is no suitable platform support, the LodePNG and picoPNG libraries are small libraries + for loading and decoding PNG files available under a BSD-style license.

+ +

RGBA format is supported on Windows, GTK+ and OS X Cocoa. + It is not supported on OS X Carbon.

+ +

XPM

+ +

The XPM format is + described here. + Scintilla is only able to handle XPM pixmaps that use one character per pixel with no named colours. + There may be a completely transparent colour named "None".

+

There are two forms of data structure used for XPM images, the first "lines form" format is well suited + to embedding an image inside C source code and the "text form" is suited to reading from a file. + In the lines form, an array of strings is used with the first string indicating the dimensions and number of colours + used. This is followed by a string for each colour and that section is followed by the image with one string per line. + The text form contains the same data as one null terminated block formatted as C source code starting + with a "/* XPM */" comment to mark the format.

+

Either format may be used with Scintilla APIs with the bytes at the location pointed to examined + to determine which format: if the bytes start with "/* XPM */" then it is treated as text form, + otherwise it is treated as lines form.

+ +

XPM format is supported on on all platforms.

+ +

GTK+

+

On GTK+, the following functions create a Scintilla widget, communicate with it and allow + resources to be released after all Scintilla widgets have been destroyed.

+ GtkWidget *scintilla_new()
+ void scintilla_set_id(ScintillaObject *sci, uptr_t id)
+ sptr_t scintilla_send_message(ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam)
+ void scintilla_release_resources()
+
+ +

GtkWidget *scintilla_new()
+ Create a new Scintilla widget. The returned pointer can be added to a container and displayed in the same way as other + widgets.

+ +

void scintilla_set_id(ScintillaObject *sci, uptr_t id)
+ Set the control ID which will be used in the idFrom field of the NotifyHeader structure of all + notifications for this instance. + This is equivalent to SCI_SETIDENTIFIER.

+ +

sptr_t scintilla_send_message(ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam)
+ The main entry point allows sending any of the messages described in this document.

+ +

void scintilla_release_resources()
+ Call this to free any remaining resources after all the Scintilla widgets have been destroyed.

+ +

Deprecated messages and notifications

+ +

The following messages are currently supported to emulate existing Windows controls, but + they will be removed in future versions of Scintilla. If you use these messages you should + replace them with the Scintilla equivalent.

+
+WM_GETTEXT(int length, char *text)
+WM_SETTEXT(<unused>, const char *text)
+EM_GETLINE(int line, char *text)
+EM_REPLACESEL(<unused>, const char *text)
+EM_SETREADONLY
+EM_GETTEXTRANGE(<unused>, TEXTRANGE *tr)
+WM_CUT
+WM_COPY
+WM_PASTE
+WM_CLEAR
+WM_UNDO
+EM_CANUNDO
+EM_EMPTYUNDOBUFFER
+WM_GETTEXTLENGTH
+EM_GETFIRSTVISIBLELINE
+EM_GETLINECOUNT
+EM_GETMODIFY
+EM_SETMODIFY(bool isModified)
+EM_GETRECT(RECT *rect)
+EM_GETSEL(int *start, int *end)
+EM_EXGETSEL(<unused>, CHARRANGE *cr)
+EM_SETSEL(int start, int end)
+EM_EXSETSEL(<unused>, CHARRANGE *cr)
+EM_GETSELTEXT(<unused>, char *text)
+EM_LINEFROMCHAR(int position)
+EM_EXLINEFROMCHAR(int position)
+EM_LINEINDEX(int line)
+EM_LINELENGTH(int position)
+EM_SCROLL(int line)
+EM_LINESCROLL(int column, int line)
+EM_SCROLLCARET()
+EM_CANPASTE
+EM_CHARFROMPOS(<unused>, POINT *location)
+EM_POSFROMCHAR(int position, POINT *location)
+EM_SELECTIONTYPE
+EM_HIDESELECTION(bool hide)
+EM_FINDTEXT(int flags, FINDTEXTEX *ft)
+EM_FINDTEXTEX(int flags, FINDTEXTEX *ft)
+EM_GETMARGINS
+EM_SETMARGINS(EC_LEFTMARGIN or EC_RIGHTMARGIN or EC_USEFONTINFO, int val)
+EM_FORMATRANGE
+
+ +

The following are features that are only included if you define + INCLUDE_DEPRECATED_FEATURES in Scintilla.h. To ensure future + compatibility you should change them as indicated.

+ +

SC_CP_DBCS Deprecated
+ This was used to set a DBCS (Double Byte Character Set) mode on GTK+. + An explicit DBCS code page should be used when calling SCI_SETCODEPAGE

+ +

SCI_SETUSEPALETTE(bool allowPaletteUse) Deprecated
+ SCI_GETUSEPALETTE Deprecated
+ Scintilla no longer supports palette mode. The last version to support palettes was 2.29. + Any calls to these methods should be removed.

+ +

Edit messages never supported by Scintilla

+
+EM_GETWORDBREAKPROC EM_GETWORDBREAKPROCEX
+EM_SETWORDBREAKPROC EM_SETWORDBREAKPROCEX
+EM_GETWORDWRAPMODE EM_SETWORDWRAPMODE
+EM_LIMITTEXT EM_EXLIMITTEXT
+EM_SETRECT EM_SETRECTNP
+EM_FMTLINES
+EM_GETHANDLE EM_SETHANDLE
+EM_GETPASSWORDCHAR EM_SETPASSWORDCHAR
+EM_SETTABSTOPS
+EM_FINDWORDBREAK
+EM_GETCHARFORMAT EM_SETCHARFORMAT
+EM_GETOLEINTERFACE EM_SETOLEINTERFACE
+EM_SETOLECALLBACK
+EM_GETPARAFORMAT EM_SETPARAFORMAT
+EM_PASTESPECIAL
+EM_REQUESTRESIZE
+EM_GETBKGNDCOLOR EM_SETBKGNDCOLOR
+EM_STREAMIN EM_STREAMOUT
+EM_GETIMECOLOR EM_SETIMECOLOR
+EM_GETIMEOPTIONS EM_SETIMEOPTIONS
+EM_GETOPTIONS EM_SETOPTIONS
+EM_GETPUNCTUATION EM_SETPUNCTUATION
+EM_GETTHUMB
+EM_GETEVENTMASK
+EM_SETEVENTMASK
+EM_DISPLAYBAND
+EM_SETTARGETDEVICE
+
+ +

Scintilla tries to be a superset of the standard windows Edit and RichEdit controls wherever + that makes sense. As it is not intended for use in a word processor, some edit messages can not + be sensibly handled. Unsupported messages have no effect.

+ +

Building Scintilla

+ +

To build Scintilla or SciTE, see the README file present in both the Scintilla and SciTE + directories. For Windows, GCC 3.2, Borland C++ or Microsoft Visual Studio .NET can be used + for building. There is a make file for building Scintilla but not SciTE with Visual C++ 6 at + scintilla/win32/scintilla_vc6.mak. For GTK+, GCC 3.1 should be used. GTK+ 1.2x and 2.0x are + supported. The version of GTK+ installed should be detected automatically. + When both GTK+ 1 and GTK+ 2 are present, building for GTK+ 1.x requires defining GTK1 + on the command line.

+ +

Static linking

+ +

On Windows, Scintilla is normally used as a dynamic library as a .DLL file. If you want to + link Scintilla directly into your application .EXE or .DLL file, then the + STATIC_BUILD preprocessor symbol should be defined and + Scintilla_RegisterClasses called. STATIC_BUILD prevents compiling the + DllMain function which will conflict with any DllMain defined in your + code. Scintilla_RegisterClasses takes the HINSTANCE of your + application and ensures that the "Scintilla" window class is registered.

+ +

Ensuring lexers are linked into Scintilla

+ +

Depending on the compiler and linker used, the lexers may be stripped out. This is most + often caused when building a static library. To ensure the lexers are linked in, the + Scintilla_LinkLexers() function may be called.

+ +

Changing set of lexers

+ +

To change the set of lexers in Scintilla, add and remove lexer source files + (Lex*.cxx) from the scintilla/src directory and run the + src/LexGen.py script from the src directory to update the make files + and KeyWords.cxx. LexGen.py requires Python 2.1 or later. If you do + not have access to Python, you can hand edit KeyWords.cxx in a simple-minded way, + following the patterns of other lexers. The important thing is to include + LINK_LEXER(lmMyLexer); to correspond with the LexerModule + lmMyLexer(...); in your lexer source code.

+ +

Building with an alternative Regular Expression implementation

+ +

A simple interface provides support for switching the Regular Expressions engine at + compile time. You must implement RegexSearchBase for your chosen engine, + look at the built-in implementation BuiltinRegex to see how this is done. + You then need to implement the factory method CreateRegexSearch + to create an instance of your class. You must disable the built-in implementation by defining + SCI_OWNREGEX.

+ + + + diff --git a/scintilla/doc/ScintillaDownload.html b/ThirdLibs/scintilla/doc/ScintillaDownload.html similarity index 97% rename from scintilla/doc/ScintillaDownload.html rename to ThirdLibs/scintilla/doc/ScintillaDownload.html index 7cb12f28..1c1c033c 100644 --- a/scintilla/doc/ScintillaDownload.html +++ b/ThirdLibs/scintilla/doc/ScintillaDownload.html @@ -1,70 +1,70 @@ - - - - - - - - - Download Scintilla - - - - - - - - -
- Scintilla icon - - Download - Scintilla -
- - - - -
- - Windows   - - GTK+/Linux   - -
-

- Download. -

-

- The license for using Scintilla or SciTE is similar to that of Python - containing very few restrictions. -

-

- Release 3.0.3 -

-

- Source Code -

- The source code package contains all of the source code for Scintilla but no binary - executable code and is available in -
    -
  • zip format (1200K) commonly used on Windows
  • -
  • tgz format (1080K) commonly used on Linux and compatible operating systems
  • -
- Instructions for building on both Windows and Linux are included in the readme file. -

- Windows Executable Code -

- There is no download available containing only the Scintilla DLL. - However, it is included in the SciTE - executable full download as SciLexer.DLL. -

- SciTE is a good demonstration of Scintilla. -

-

- Previous versions can be downloaded from the history - page. -

- - + + + + + + + + + Download Scintilla + + + + + + + + +
+ Scintilla icon + + Download + Scintilla +
+ + + + +
+ + Windows   + + GTK+/Linux   + +
+

+ Download. +

+

+ The license for using Scintilla or SciTE is similar to that of Python + containing very few restrictions. +

+

+ Release 3.0.3 +

+

+ Source Code +

+ The source code package contains all of the source code for Scintilla but no binary + executable code and is available in +
    +
  • zip format (1200K) commonly used on Windows
  • +
  • tgz format (1080K) commonly used on Linux and compatible operating systems
  • +
+ Instructions for building on both Windows and Linux are included in the readme file. +

+ Windows Executable Code +

+ There is no download available containing only the Scintilla DLL. + However, it is included in the SciTE + executable full download as SciLexer.DLL. +

+ SciTE is a good demonstration of Scintilla. +

+

+ Previous versions can be downloaded from the history + page. +

+ + diff --git a/scintilla/doc/ScintillaHistory.html b/ThirdLibs/scintilla/doc/ScintillaHistory.html similarity index 97% rename from scintilla/doc/ScintillaHistory.html rename to ThirdLibs/scintilla/doc/ScintillaHistory.html index 541e2df5..44515564 100644 --- a/scintilla/doc/ScintillaHistory.html +++ b/ThirdLibs/scintilla/doc/ScintillaHistory.html @@ -1,8102 +1,8102 @@ - - - - - - - - - Scintilla and SciTE - - - - - - - - - -
- Scintilla icon - - Scintilla - and SciTE -
-

- History of Scintilla and SciTE -

-

- Contributors -

-

- Thanks to all the people that have contributed patches, bug reports and suggestions. -

-

- Source code and documentation have been contributed by -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Atsuo IshimotoMark HammondFrancois Le CoguiecDale Nagata
Ralf ReinhardtPhilippe LhosteAndrew McKinlayStephan R. A. Deibel
Hans EckardtVassili BourdoMaksim LinRobin Dunn
John EhresmanSteffen GoeldnerDeepak S.Yann Gaillard
Aubin PaulJason DiamondAhmad BaitalmalPaul Winwood
Maxim BaranovRagnar HøjlandChristian ObrechtAndreas Neukoetter
Adam GatesSteve LhommeFerdinand PrantlJan Dries
Markus GritschTahir KaracaAhmad ZawawiLaurent le Tynevez
Walter BraeuAshley CambrellGarrett SerackHolger Schmidt
ActiveStateJames LarcombeAlexey YutkinJan Hercek
Richard PeclEdward K. ReamValery KondakoffSmári McCarthy
Clemens WyssSimon SteeleSerge A. BaranovXavier Nodet
Willy DevauxDavid ClainBrendon YensonVamsi Potluru
Praveen AmbekarAlan KnowlesKengo JinnoValentin Valchev
Marcos E. WurziusMartin AldersonRobert GustavssonJosé Fonseca
Holger KiemesFrancis IrvingScott KirkwoodBrian Quinlan
UbiMichael R. DuerigDeepak TDon Paul Beletsky
Gerhard KalabOlivier DagenaisJosh WingstromBruce Dodson
Sergey KoshcheyevChuan-jian ShenShane CaraveoAlexander Scripnik
Ryan ChristiansonMartin SteffensenJakub VránaThe Black Horus
Bernd KreussThomas LauerMike LansdaalYukihiro Nakai
Jochen TuchtGreg SmithSteve SchoettlerMauritius Thinnes
Darren SchroederPedro GuerreiroDan PetittBiswapesh Chattopadhyay
Kein-Hong ManPatrizio BekerleNigel HathawayHrishikesh Desai
Sergey PuljajevMathias RauenAngelo MandatoDenis Sureau
Kaspar SchiessChristoph HöslerJoão Paulo F FariasRon Schofield
Stefan WosnikMarius GheorgheNaba KumarSean O'Dell
Stefanos TogoulidisHans HagenJim CapeRoland Walter
Brian MosherNicholas NemtsevRoy WoodPeter-Henry Mander
Robert BoucherChristoph DalitzApril WhiteS. Umar
Trent MickFilip YaghobAvi YegudinVivi Orunitia
Manfred BeckerDimitris KeletsekisYuigaDavide Scola
Jason BoggsReinhold NiesnerJos van der ZandePescuma
Pavol BosikJohannes SchmidBlair McGlashanMikael Hultgren
Florian BalmerHadar RazHerr PfarrerBen Key
Gene BarryNiki SpahievCarsten SperberPhil Reid
Iago RubioRégis VaquetteMassimo CoràElias Pschernig
Chris JonesJosiah ReynoldsRobert Roessler rftp.comSteve Donovan
Jan Martin PettersenSergey PhilippovBorujoaMichael Owens
Franck MarciaMassimo Maria GhisalbertiFrank WunderlichJosepmaria Roca
Tobias EngvallSuzumizaki KimitakaMichael CartmellPascal Hurni
AndreRandy ButlerGeorg RitterMichael Goffioul
Ben HarperAdam StrzeleckiKamen StanevSteve Menard
Oliver YeohEric PromislowJoseph GalbraithJeffrey Ren
Armel AsselinJim PatteeFriedrich VedderSebastian Pipping
Andre ArpinStanislav MaslovskiMartin StoneFabien Proriol
mimirNicola CivranSnowMitchell Foral
Pieter HoltzhausenWaldemar AugustynJason HaslamSebastian Steinlechner
Chris RickardRob McMullenStefan SchwendelerCristian Adam
Nicolas ChachereauIstvan SzollosiXie RenhuiEnrico Tröger
Todd WhitemanYuval PapishinstantonSergio Lucato
VladVRODmitry MaslovchupakabraJuan Carlos Arevalo Baeza
Nick TreleavenStephen StaggJean-Paul IribarrenTim Gerundt
Sam HarwellBorisJason OsterGertjan Kloosterman
alexbodnSergiu DotencoAnders Karlssonozlooper
Marko NjezicEugen BitterChristoph BaumannChristopher Bean
Sergey KishchenkoKai LiuAndreas RumpfJames Moffatt
Yuzhou XinNic JansmaEvan JonesMike Lischke
Eric KiddmaXmoDavid SeverwrightJon Strait
Oliver KiddleEtienne GirondelHaimag RenAndrey Moskalyov
XaviToby InksterEric ForgeotColomban Wendling
NeoJordan RussellFarshid LashkariSam Rawlins
Michael MullinCarlos SSvimMartial Demolins
Tino WeinkaufJérôme LaforgeUdo LechnerMarco Falda
Dariusz KnocińskiBen FisherDon GobinJohn Yeung
AdobeElizabeth A. IrizarryMike SchroederMorten MacFly
Jaime GimenoThomas Linder PulsArtyom ZuikovGerrit
Occam's RazorBen BluemelDavid WolfendaleChris Angelico
Marat DukhanStefan WeilRex ConnRoss McKay
Bruno Barbieri
-

- Images used in GTK+ version -

-
    -
  • - - Icons Copyright(C) 1998 by Dean S. Jones
    -
  • -
-

- Release 3.0.3 -

-
    -
  • - Released 28 January 2012. -
  • -
  • - Printing works on GTK+ version 2.x as well as 3.x. -
  • -
  • - Lexer added for the AviSynth language. - Feature #3475611. -
  • -
  • - Lexer added for the Take Command / TCC scripting language. - Feature #3462462. -
  • -
  • - CSS lexer gains support for SCSS. - Feature #3268017. -
  • -
  • - CPP lexer fixes problems in the preprocessor structure caused by continuation lines. - Bug #3458508. -
  • -
  • - Errorlist lexer handles column numbers for GCC format diagnostics. - In SciTE, Next Message goes to column where this can be decoded from GCC format diagnostics. - Feature #3453075. -
  • -
  • - HTML folder fixes spurious folds on some tags. - Bug #3459262. -
  • -
  • - Ruby lexer fixes bug where '=' at start of file caused whole file to appear as a comment. - Bug #3452488. -
  • -
  • - SQL folder folds blocks of single line comments. - Feature #3467425. -
  • -
  • - On Windows using Direct2D, defer invalidation of render target until completion of painting to avoid failures. -
  • -
  • - Further support of fractional positioning. Spaces, tabs, and single character tokens can take fractional space - and wrapped lines are positioned taking fractional positions into account. - Bug #3471998. -
  • -
  • - On Windows using Direct2D, fix extra carets appearing. - Bug #3471998. -
  • -
  • - For autocompletion lists Page Up and Down move by the list height instead of by 5 lines. - Bug #3455493. -
  • -
  • - For SCI_LINESCROLLDOWN/UP don't select into virtual space. - Bug #3451681. -
  • -
  • - Fix fold highlight not being fully drawn. - Bug #3469936. -
  • -
  • - Fix selection margin appearing black when starting in wrap mode. -
  • -
  • - Fix crash when changing end of document after adding an annotation. - Bug #3476637. -
  • -
  • - Fix problems with building to make RPMs. - Bug #3476149. -
  • -
  • - Fix problem with building on GTK+ where recent distributions could not find gmodule. - Bug #3469056. -
  • -
  • - Fix problem with installing SciTE on GTK+ due to icon definition in .desktop file including an extension. - Bug #3476117. -
  • -
  • - Fix SciTE bug where new buffers inherited some properties from previously opened file. - Bug #3457060. -
  • -
  • - Fix focus when closing tab in SciTE with middle click. Focus moves to edit pane instead of staying on tab bar. - Bug #3440142. -
  • -
  • - For SciTE on Windows fix bug where Open Selected Filename for URL would append a file extension. - Feature #3459185. -
  • -
  • - For SciTE on Windows fix key handling of control characters in Parameters dialog so normal editing (Ctrl+C, ...) works. - Bug #3459345. -
  • -
  • - Fix SciTE bug where files became read-only after saving. Drop the "*" dirty marker after save completes. - Bug #3467432. -
  • -
  • - For SciTE handling of diffs with "+++" and "---" lines, also handle case where not followed by tab. - Go to correct line for diff "+++" message. - Bug #3467143. - Bug #3467178. -
  • -
  • - SciTE on GTK+ now performs threaded actions even on GTK+ versions before 2.12. -
  • -
-

- Release 3.0.2 -

-
    -
  • - Released 9 December 2011. -
  • -
  • - SciTE saves files in the background without blocking the user interface. -
  • -
  • - Printing implemented in SciTE on GTK+ 3.x. -
  • -
  • - ILoader interface for background loading finalised and documented. -
  • -
  • - CoffeeScript lexer added. -
  • -
  • - C++ lexer fixes crash with "#if defined( XXX 1". -
  • -
  • - Crash with Direct2D on Windows fixed. -
  • -
  • - Backspace removing protected range fixed. - Bug #3445911. -
  • -
  • - Cursor setting failure on Windows when screen saver on fixed. - Bug #3438780. -
  • -
  • - SciTE on GTK+ hang fixed with -open:file option. - Bug #3441980. -
  • -
  • - Failure to evaluate shbang fixed in SciTE. - Bug #3441801. -
  • -
  • - SciTE failure to treat files starting with "<?xml" as XML fixed. - Bug #3440718. -
  • -
  • - Made untitled tab saveable when created by closing all files. - Bug #3440244. -
  • -
  • - SciTE crash fixed when using Scintillua. -
  • -
  • - SciTE revert command fixed so that undo works on individual actions instead of undoing to revert point. -
  • -
  • - Focus loss in SciTE when opening a recent file fixed. - Bug #3440142. -
  • -
  • - Fixed SciTE SelLength property to measure characters instead of bytes. - Bug #3283519. -
  • -
-

- Release 3.0.1 -

-
    -
  • - Released 15 November 2011. -
  • -
  • - SciTE on Windows now runs Lua scripts directly on the main thread instead of starting them on a - secondary thread and then moving back to the main thread. -
  • -
  • - Highlight "else" as a keyword for TCL in the same way as other languages. - Bug #1836954. -
  • -
  • - Fix problems with setting fonts for autocompletion lists on Windows where - font handles were copied and later deleted causing a system default font to be used. -
  • -
  • - Fix font size used on Windows for Asian language input methods which sometimes led to IME not being visible. - Bug #3436753. -
  • -
  • - Fixed polygon drawing on Windows so fold symbols are visible again. - Bug #3433558. -
  • -
  • - Changed background drawing on GTK+ to allow for fractional character positioning as occurs on OS X - as this avoids faint lines at lexeme boundaries. -
  • -
  • - Ensure pixmaps allocated before painting as there was a crash when Scintilla drew without common initialisation calls. - Bug #3432354. -
  • -
  • - Fixed SciTE on Windows bug causing wrong caret position after indenting a selection. - Bug #3433433. -
  • -
  • - Fixed SciTE session saving to store buffer position matching buffer. - Bug #3434372. -
  • -
  • - Fixed leak of document objects in SciTE. -
  • -
  • - Recognize URL characters '?' and '%' for Open Selected command in SciTE. - Bug #3429409. -
  • -
-

- Release 3.0.0 -

-
    -
  • - Released 1 November 2011. -
  • -
  • - Carbon platform support removed. OS X applications should switch to Cocoa. -
  • -
  • - On Windows Vista or newer, drawing may be performed with Direct2D and DirectWrite instead of GDI. -
  • -
  • - Cairo is now used for all drawing on GTK+. GDK drawing was removed. -
  • -
  • - Paletted display support removed. -
  • -
  • - Fractional font sizes can be specified. -
  • -
  • - Different weights of text supported on some platforms instead of just normal and bold. -
  • -
  • - Sub-pixel character positioning supported. -
  • -
  • - SciTE loads files in the background without blocking the user interface. -
  • -
  • - SciTE can display diagnostic messages interleaved with the text of files immediately after the - line referred to by the diagnostic. -
  • -
  • - New API to see if all lines are visible which can be used to optimize processing fold structure notifications. -
  • -
  • - Scrolling optimized by avoiding invalidation of fold margin when redrawing whole window. -
  • -
  • - Optimized SCI_MARKERNEXT. -
  • -
  • - C++ lexer supports Pike hash quoted strings when turned on with lexer.cpp.hashquoted.strings. -
  • -
  • - Fixed incorrect line height with annotations in wrapped mode when there are multiple views. - Bug #3388159. -
  • -
  • - Calltips may be displayed above the text as well as below. - Bug #3410830. -
  • -
  • - For huge files SciTE only examines the first megabyte for newline discovery. -
  • -
  • - SciTE on GTK+ removes the fileselector.show.hidden property and check box as this was buggy and GTK+ now - supports an equivalent feature. - Bug #3413630. -
  • -
  • - SciTE on GTK+ supports mnemonics in dynamic menus. -
  • -
  • - SciTE on GTK+ displays the user's home directory as '~' in menus to make them shorter. -
  • -
-

- Release 2.29 -

-
    -
  • - Released 16 September 2011. -
  • -
  • - To automatically discover the encoding of a file when opening it, SciTE can run a program set with command.discover.properties. - Feature #3324341. -
  • -
  • - Cairo always used for drawing on GTK+. -
  • -
  • - The set of properties files imported by SciTE can be controlled with the properties imports.include and imports.exclude. - The import statement has been extended to allow "import *". - The properties files for some languages are no longer automatically loaded by default. The properties files affected are - avenue, baan, escript, lot, metapost, and mmixal. -
  • -
  • - C++ lexer fixed a bug with raw strings being recognised too easily. - Bug #3388122. -
  • -
  • - LaTeX lexer improved with more states and fixes to most outstanding bugs. - Bug #1493111. - Bug #1856356. - Bug #3081692. -
  • -
  • - Lua lexer updates for Lua 5.2 beta with goto labels and "\z" string escape. - Feature #3386330. -
  • -
  • - Perl string styling highlights interpolated variables. - Feature #3394258. - Bug #3076629. -
  • -
  • - Perl lexer updated for Perl 5.14.0 with 0X and 0B numeric literal prefixes, break keyword and "+" supported in subroutine prototypes. - Feature #3388802. -
  • -
  • - Perl bug fixed with CRLF line endings. -
  • -
  • - Markdown lexer fixed to not change state with "_" in middle of word. - Bug #3398184. -
  • -
  • - Cocoa restores compatibility with OS X 10.5. -
  • -
  • - Mouse pointer changes over selection to an arrow near start when scrolled horizontally. - Bug #3389055. -
  • -
  • - Indicators that finish at the end of the document no longer expand when text is appended. - Bug #3378718. -
  • -
  • - SparseState merge fixed to check if other range is empty. - Bug #3387053. -
  • -
  • - On Windows, autocompletion lists will scroll instead of document when mouse wheel spun. - Feature #3403600. -
  • -
  • - SciTE performs more rapid polling for command completion so will return faster and report more accurate times. -
  • -
  • - SciTE resizes panes proportionally when switched between horizontal and vertical layout. - Feature #3376784. -
  • -
  • - SciTE on GTK+ opens multiple files into a single instance more reliably. - Bug #3363754. -
  • -
-

- Release 2.28 -

-
    -
  • - Released 1 August 2011. -
  • -
  • - GTK+ Cairo support works back to GTK+ version 2.8. Requires changing Scintilla source code to enable before GTK+ 2.22. - Bug #3322351. -
  • -
  • - Translucent images in RGBA format can be used for margin markers and in autocompletion lists. -
  • -
  • - INDIC_DOTBOX added as a translucent dotted rectangular indicator. -
  • -
  • - Asian text input using IME works for GTK+ 3.x and GTK+ 2.x with Cairo. -
  • -
  • - On GTK+, IME works for Ctrl+Shift+U Unicode input in Scintilla. For SciTE, Ctrl+Shift+U is still Make Selection Uppercase. -
  • -
  • - Key bindings for GTK+ on OS X made compatible with Cocoa port and platform conventions. -
  • -
  • - Cocoa port supports different character encodings, improves scrolling performance and drag image appearance. - The control ID is included in WM_COMMAND notifications. Text may be deleted by dragging to the trash. - ScrollToStart and ScrollToEnd key commands added to simplify implementation of standard OS X Home and End - behaviour. -
  • -
  • - SciTE on GTK+ uses a paned widget to contain the edit and output panes instead of custom code. - This allows the divider to be moved easily on GTK+ 3 and its appearance follows GTK+ conventions more closely. -
  • -
  • - SciTE builds and installs on BSD. - Bug #3324644. -
  • -
  • - Cobol supports fixed format comments. - Bug #3014850. -
  • -
  • - Mako template language block syntax extended and ## comments recognised. - Feature #3325178. - Bug #3318818. -
  • -
  • - Folding of Mako template language within HTML fixed. - Bug #3324563. -
  • -
  • - Python lexer has lexer.python.keywords2.no.sub.identifiers option to avoid highlighting second set of - keywords following '.'. - Bug #3325333. -
  • -
  • - Python folder fixes bug where fold would not extend to final line. - Bug #3349157. -
  • -
  • - SciTE treats LPEG lexers the same as script lexers by setting all 8 style bits. -
  • -
  • - For Cocoa, crashes with unsupported font variants and memory leaks for colour objects fixed. -
  • -
  • - Shift-JIS lead byte ranges modified to match Windows. -
  • -
  • - Mouse pointer changes over selection to an arrow more consistently. - Bug #3315756. -
  • -
  • - Bug fixed with annotations beyond end of document. - Bug #3347268. -
  • -
  • - Incorrect drawing fixed for combination of background colour change and translucent selection. - Bug #3377116. -
  • -
  • - Lexers initialized correctly when started at position other than start of line. - Bug #3377148. -
  • -
  • - Fold highlight drawing fixed for some situations. - Bug #3323015. - Bug #3323805. -
  • -
  • - Case insensitive search fixed for cases where folded character uses fewer bytes than base character. - Bug #3362038. -
  • -
  • - SciTE bookmark.alpha setting fixed. - Bug #3373907. -
  • -
-

- Release 2.27 -

-
    -
  • - Released 20 June 2011. -
  • -
  • - On recent GTK+ 2.x versions when using Cairo, bug fixed where wrong colours were drawn. -
  • -
  • - SciTE on GTK+ slow performance in menu maintenance fixed. - Bug #3315233. -
  • -
  • - Cocoa platform supports 64-bit builds and uses only non-deprecated APIs. - Asian Input Method Editors are supported. - Autocompletion lists and calltips implemented. - Control identifier used in notifications. -
  • -
  • - On Cocoa, rectangular selection now uses Option/Alt key to be compatible with Apple Human - Interface Guidelines and other applications. - The Control key is reported with an SCMOD_META modifier bit. -
  • -
  • - API added for setting and retrieving the identifier number used in notifications. -
  • -
  • - SCI_SETEMPTYSELECTION added to set selection without scrolling or redrawing more than needed. - Feature #3314877. -
  • -
  • - Added new indicators. INDIC_DASH and INDIC_DOTS are variants of underlines. - INDIC_SQUIGGLELOW indicator added as shorter alternative to INDIC_SQUIGGLE for small fonts. - Bug #3314591 -
  • -
  • - Margin line selection can be changed to select display lines instead of document lines. - Bug #3312763. -
  • -
  • - On Windows, SciTE can perform reverse searches by pressing Shift+Enter - in the Find or Replace strips or dialogs. -
  • -
  • - Matlab lexer does not special case '\' in single quoted strings. - Bug #948757 - Bug #1755950 - Bug #1888738 - Bug #3316852. -
  • -
  • - Verilog lexer supports SystemVerilog folding and keywords. -
  • -
  • - Font leak fixed. - Bug #3306156. -
  • -
  • - Automatic scrolling works for long wrapped lines. - Bug #3312763. -
  • -
  • - Multiple typing works for cases where selections collapse together. - Bug #3309906. -
  • -
  • - Fold expanded when needed in word wrap mode. - Bug #3291579. -
  • -
  • - Bug fixed with edge drawn in wrong place on wrapped lines. - Bug #3314807. -
  • -
  • - Bug fixed with unnecessary scrolling for SCI_GOTOLINE. - Bug #3303406. -
  • -
  • - Bug fixed where extra step needed to undo SCI_CLEAR in virtual space. - Bug #3159691. -
  • -
  • - Regular expression search fixed for \$ on last line of search range. - Bug #3313746. -
  • -
  • - SciTE performance improved when switching to a tab with a very large file. - Bug #3311421. -
  • -
  • - On Windows, SciTE advanced search remembers the "Search only in this style" setting. - Bug #3313344. -
  • -
  • - On GTK+, SciTE opens help using "xdg-open" instead of "netscape" as "netscape" no longer commonly installed. - Bug #3314377. -
  • -
  • - SciTE script lexers can use 256 styles. -
  • -
  • - SciTE word highlight works for words containing DBCS characters. - Bug #3315173. -
  • -
  • - Compilation fixed for wxWidgets. - Bug #3306156. -
  • -
-

- Release 2.26 -

-
    -
  • - Released 25 May 2011. -
  • -
  • - Folding margin symbols can be highlighted for the current folding block. - Feature #3147069. -
  • -
  • - Selected lines can be moved up or down together. - Feature #3304850. -
  • -
  • - SciTE can highlight all occurrences of the current word or selected text. - Feature #3291636. -
  • -
  • - Experimental GTK+ 3.0 support: build with "make GTK3=1". -
  • -
  • - INDIC_STRAIGHTBOX added. Is similar to INDIC_ROUNDBOX but without rounded corners. - Bug #3290435. -
  • -
  • - Can show brace matching and mismatching with indicators instead of text style. - Translucency of outline can be altered for INDIC_ROUNDBOX and INDIC_STRAIGHTBOX. - Feature #3290434. -
  • -
  • - SciTE can automatically indent python by examining previous line for scope-starting ':' with indent.python.colon. -
  • -
  • - Batch file lexer allows braces '(' or ')' inside variable names. -
  • -
  • - The cpp lexer only recognises Vala triple quoted strings when lexer.cpp.triplequoted.strings property is set. - Bug #3239234. -
  • -
  • - Make file lexer treats a variable with a nested variable like $(f$(qx)b) as one variable. - Bug #3298223. -
  • -
  • - Folding bug fixed for JavaScript with nested PHP. - Bug #3193530. -
  • -
  • - HTML lexer styles Django's {# #} comments. - Bug #3013798. -
  • -
  • - HTML lexer styles JavaScript regular expression correctly for /abc/i.test('abc');. - Bug #3209108. -
  • -
  • - Inno Setup Script lexer now works properly when it restarts from middle of [CODE] section. - Bug #3283880. - Bug #3129044. -
  • -
  • - Lua lexer updated for Lua 5.2 with hexadecimal floating-point numbers and '\*' whitespace escaping in strings. - Feature #3243811. -
  • -
  • - Perl folding folds "here doc"s and adds options fold.perl.at.else and fold.perl.comment.explicit. Fold structure for Perl fixed. - Feature #3112671. - Bug #3265401. -
  • -
  • - Python lexer supports cpdef keyword for Cython. - Bug #3279728. -
  • -
  • - SQL folding option lexer.sql.fold.at.else renamed to fold.sql.at.else. - Bug #3271474. -
  • -
  • - SQL lexer no longer treats ';' as terminating a comment. - Bug #3196071. -
  • -
  • - Text drawing and measurement segmented into smaller runs to avoid platform bugs. - Bug #3277449. - Bug #3165743. -
  • -
  • - SciTE on Windows adds temp.files.sync.load property to open dropped temporary files synchronously as they may - be removed before they can be opened asynchronously. - Bug #3072009. -
  • -
  • - Bug fixed with indentation guides ignoring first line in SC_IV_LOOKBOTH mode. - Bug #3291317. -
  • -
  • - Bugs fixed in backward regex search. - Bug #3292659. -
  • -
  • - Bugs with display of folding structure fixed for wrapped lines and where there is a fold header but no body. - Bug #3291579. - Bug #3265401. -
  • -
  • - SciTE on Windows cursor changes to an arrow now when over horizontal splitter near top of window. - Bug #3286620. -
  • -
  • - Fixed default widget size problem on GTK+. - Bug #3267892. -
  • -
  • - Fixed font size when using Cairo on GTK+. - Bug #3272662. -
  • -
  • - Fixed primary selection and cursor issues on GTK+ when unrealized then realized. - Bug #3256153. -
  • -
  • - Right click now cancels selection on GTK+ like on Windows. - Bug #3235190. -
  • -
  • - SciTE on GTK+ implements z-order buffer switching like on Windows. - Bug #3228384. -
  • -
  • - Improve selection position after SciTE Insert Abbreviation command when abbreviation expansion includes '|'. -
  • -
-

- Release 2.25 -

-
    -
  • - Released 21 March 2011. -
  • -
  • - SparseState class makes it easier to write lexers which have to remember complex state between lines. -
  • -
  • - Visual Studio project (.dsp) files removed. The make files should be used instead as described in the README. -
  • -
  • - Modula 3 lexer added along with SciTE support. - Feature #3173374. -
  • -
  • - Asm, Basic, and D lexers add extra folding properties. -
  • -
  • - Raw string literals for C++0x supported in C++ lexer. -
  • -
  • - Triple-quoted strings used in Vala language supported in C++ lexer. - Feature #3177601. -
  • -
  • - The errorlist lexer used in SciTE's output pane colours lines that start with '<' as diff deletions. - Feature #3172878. -
  • -
  • - The Fortran lexer correctly folds type-bound procedures from Fortran 2003. -
  • -
  • - LPeg lexer support‎ improved in SciTE. -
  • -
  • - SciTE on Windows-64 fixes for menu localisation and Lua scripts. - Bug #3204502. -
  • -
  • - SciTE on Windows avoids locking folders when using the open or save dialogs. - Bug #1795484. -
  • -
  • - Diff lexer fixes problem where diffs of diffs producing lines that start with "----". - Bug #3197952. -
  • -
  • - Bug fixed when searching upwards in Chinese code page 936. - Bug #3176271. -
  • -
  • - On Cocoa, translucent drawing performed as on other platforms instead of 2.5 times less translucent. -
  • -
  • - Performance issue and potential bug fixed on GTK+ with caret line for long lines. -
  • -
-

- Release 2.24 -

-
    -
  • - Released 3 February 2011. -
  • -
  • - Fixed memory leak in GTK+ Cairo code. - Feature #3157655. -
  • -
  • - Insert Abbreviation dialog added to SciTE on GTK+. -
  • -
  • - SCN_UPDATEUI notifications received when window scrolled. An 'updated' bit mask indicates which - types of update have occurred from SC_UPDATE_SELECTION, SC_UPDATE_CONTENT, SC_UPDATE_H_SCROLL - or SC_UPDATE_V_SCROLL. - Feature #3125977. -
  • -
  • - On Windows, to ensure reverse arrow cursor matches platform default, it is now generated by - reflecting the platform arrow cursor. - Feature #3143968. -
  • -
  • - Can choose mouse cursor used in margins. - Feature #3161326. -
  • -
  • - On GTK+, SciTE sets a mime type of text/plain in its .desktop file so that it will appear in the shell context menu. - Feature #3137126. -
  • -
  • - Bash folder handles here docs. - Feature #3118223. -
  • -
  • - C++ folder adds fold.cpp.syntax.based, fold.cpp.comment.multiline, fold.cpp.explicit.start, fold.cpp.explicit.end, - and fold.cpp.explicit.anywhere properties to allow more control over folding and choice of explicit fold markers. -
  • -
  • - C++ lexer fixed to always handle single quote strings continued past a line end. - Bug #3150522. -
  • -
  • - Ruby folder handles here docs. - Feature #3118224. -
  • -
  • - SQL lexer allows '.' to be part of words. - Feature #3103129. -
  • -
  • - SQL folder handles case statements in more situations. - Feature #3135027. -
  • -
  • - SQL folder adds fold points inside expressions based on bracket structure. - Feature #3165488. -
  • -
  • - SQL folder drops fold.sql.exists property as 'exists' is handled automatically. - Bug #3164194. -
  • -
  • - SciTE only forwards properties to lexers when they have been explicitly set so the defaults set by lexers are used - rather than 0. -
  • -
  • - Mouse double click word selection chooses the word around the character under the mouse rather than - the inter-character position under the mouse. This makes double clicking select what the user is pointing - at and avoids selecting adjacent non-word characters. - Bug #3111174. -
  • -
  • - Fixed mouse double click to always perform word select, not line select. - Bug #3143635. -
  • -
  • - Right click cancels autocompletion. - Bug #3144531. -
  • -
  • - Fixed multiPaste to work when additionalSelectionTyping off. - Bug #3126221. -
  • -
  • - Fixed virtual space problems when text modified at caret. - Bug #3154986. -
  • -
  • - Fixed memory leak in lexer object code. - Bug #3133672. -
  • -
  • - Fixed SciTE on GTK+ search failure when using regular expression. - Bug #3156217. -
  • -
  • - Avoid unnecessary full window redraw for SCI_GOTOPOS. - Feature #3146650. -
  • -
  • - Avoid unnecessary redraw when indicator fill range makes no real change. -
  • -
-

- Release 2.23 -

-
    -
  • - Released 7 December 2010. -
  • -
  • - On GTK+ version 2.22 and later, drawing is performed with Cairo rather than GDK. - This is in preparation for GTK+ 3.0 which will no longer support GDK drawing. - The appearance of some elements will be different with Cairo as it is anti-aliased and uses sub-pixel positioning. - Cairo may be turned on for GTK+ versions before 2.22 by defining USE_CAIRO although this has not - been extensively tested. -
  • -
  • - New lexer a68k for Motorola 68000 assembler. - Feature #3101598. -
  • -
  • - Borland C++ is no longer supported for building Scintilla or SciTE on Windows. -
  • -
  • - Performance improved when creating large rectangular selections. -
  • -
  • - PHP folder recognizes #region and #endregion comments. - Feature #3101624. -
  • -
  • - SQL lexer has a lexer.sql.numbersign.comment option to turn off use of '#' comments - as these are a non-standard feature only available in some implementations. - Feature #3098071. -
  • -
  • - SQL folder recognizes case statements and understands the fold.at.else property. - Bug #3104091. - Bug #3107362. -
  • -
  • - SQL folder fixes bugs with end statements when fold.sql.only.begin=1. - Bug #3104091. -
  • -
  • - SciTE on Windows bug fixed with multi-line tab bar not adjusting correctly when maximizing and demaximizing. - Bug #3097517. -
  • -
  • - Crash fixed on GTK+ when Scintilla widget destroyed while it still has an outstanding style idle pending. -
  • -
  • - Bug fixed where searching backwards in DBCS text (code page 936 or similar) failed to find occurrences at the start of the line. - Bug #3103936. -
  • -
  • - SciTE on Windows supports Unicode file names when executing help applications with winhelp and htmlhelp subsystems. -
  • -
-

- Release 2.22 -

-
    -
  • - Released 27 October 2010. -
  • -
  • - SciTE includes support for integrating with Scintillua which allows lexers to be implemented in Lua as a - Parsing Expression Grammar (PEG). -
  • -
  • - Regular expressions allow use of '?' for non-greedy matches or to match 0 or 1 instances of an item. -
  • -
  • - SCI_CONTRACTEDFOLDNEXT added to allow rapid retrieval of folding state. -
  • -
  • - SCN_HOTSPOTRELEASECLICK notification added which is similar to SCN_HOTSPOTCLICK but occurs - when the mouse is released. - Feature #3082409. -
  • -
  • - Command added for centring current line in window. - Feature #3064696. -
  • -
  • - SciTE performance improved by not examining document for line ends when switching buffers and not - storing folds when folding turned off. -
  • -
  • - Bug fixed where scrolling to ensure the caret is visible did not take into account all pixels of the line. - Bug #3081721. -
  • -
  • - Bug fixed for autocompletion list overlapping text when WS_EX_CLIENTEDGE used. - Bug #3079778. -
  • -
  • - After autocompletion, the caret's X is updated. - Bug #3079114. -
  • -
  • - On Windows, default to the system caret blink time. - Feature #3079784. -
  • -
  • - PgUp/PgDn fixed to allow virtual space. - Bug #3077452. -
  • -
  • - Crash fixed when AddMark and AddMarkSet called with negative argument. - Bug #3075074. -
  • -
  • - Dwell notifications fixed so that they do not occur when the mouse is outside Scintilla. - Bug #3073481. -
  • -
  • - Bash lexer bug fixed for here docs starting with <<-. - Bug #3063822. -
  • -
  • - C++ lexer bug fixed for // comments that are continued onto a second line by a \. - Bug #3066031. -
  • -
  • - C++ lexer fixes wrong highlighting for float literals containing +/-. - Bug #3058924. -
  • -
  • - JavaScript lexer recognize regexes following return keyword.‎ - Bug #3062287. -
  • -
  • - Ruby lexer handles % quoting better and treats range dots as operators in 1..2 and 1...2. - Ruby folder handles "if" keyword used as a modifier even when it is separated from the modified statement by an escaped new line. - Bug #2093767. - Bug #3058496. -
  • -
  • - Bug fixed where upwards search failed with DBCS code pages. - Bug #3065912. -
  • -
  • - SciTE has a default Lua startup script name distributed in SciTEGlobal.properties. - No error message is displayed if this file does not exist. -
  • -
  • - SciTE on Windows tab control height is calculated better. - Bug #2635702. -
  • -
  • - SciTE on Windows uses better themed check buttons in find and replace strips. -
  • -
  • - SciTE on Windows fixes bug with Find strip appearing along with Incremental Find strip. -
  • -
  • - SciTE setting find.close.on.find added to allow preventing the Find dialog from closing. -
  • -
  • - SciTE on Windows attempts to rerun commands that fail by prepending them with "cmd.exe /c". - This allows commands built in to the command processor like "dir" to run. -
  • -
-

- Release 2.21 -

-
    -
  • - Released 1 September 2010. -
  • -
  • - Asian Double Byte Character Set (DBCS) support improved. - Case insensitive search works and other operations are much faster. - Bug #2999125, - Bug #2774616, - Bug #2991942, - Bug #3005688. -
  • -
  • - Scintilla on GTK+ uses only non-deprecated APIs (for GTK+ 2.20) except for GdkFont and GdkFont use can be disabled - with the preprocessor symbol DISABLE_GDK_FONT. -
  • -
  • - IDocument interface used by lexers adds BufferPointer and GetLineIndentation methods. -
  • -
  • - On Windows, clicking sets focus before processing the click or sending notifications. -
  • -
  • - Bug on OS X (macosx platform) fixed where drag/drop overwrote clipboard. - Bug #3039732. -
  • -
  • - GTK+ drawing bug when the view was horizontally scrolled more than 32000 pixels fixed. -
  • -
  • - SciTE bug fixed with invoking Complete Symbol from output pane. - Bug #3050957. -
  • -
  • - Bug fixed where it was not possible to disable folding. - Bug #3040649. -
  • -
  • - Bug fixed with pressing Enter on a folded fold header line not opening the fold. - Bug #3043419. -
  • -
  • - SciTE 'Match case' option in find and replace user interfaces changed to 'Case sensitive' to allow use of 'v' - rather than 'c' as the mnemonic. -
  • -
  • - SciTE displays stack trace for Lua when error occurs.. - Bug #3051397. -
  • -
  • - SciTE on Windows fixes bug where double clicking on error message left focus in output pane. - Bug #1264835. -
  • -
  • - SciTE on Windows uses SetDllDirectory to avoid a security problem. -
  • -
  • - C++ lexer crash fixed with preprocessor expression that looked like division by 0. - Bug #3056825. -
  • -
  • - Haskell lexer improved. - Feature #3039490. -
  • -
  • - HTML lexing fixed around Django {% %} tags. - Bug #3034853. -
  • -
  • - HTML JavaScript lexing fixed when line end escaped. - Bug #3038381. -
  • -
  • - HTML lexer stores line state produced by a line on that line rather than on the next line. -
  • -
  • - Markdown lexer fixes infinite loop. - Bug #3045386. -
  • -
  • - MySQL folding bugs with END statements fixed. - Bug #3031742. -
  • -
  • - PowerShell lexer allows '_' as a word character. - Feature #3042228. -
  • -
  • - SciTE on GTK+ abandons processing of subsequent commands if a command.go.needs command fails. -
  • -
  • - When SciTE is closed, all buffers now receive an OnClose call. - Bug #3033857. -
  • -
-

- Release 2.20 -

-
    -
  • - Released 30 July 2010. -
  • -
  • - Lexers are implemented as objects so that they may retain extra state. - The interfaces defined for this are tentative and may change before the next release. - Compatibility classes allow current lexers compiled into Scintilla to run with few changes. - The interface to external lexers has changed and existing external lexers will need to have changes - made and be recompiled. - A single lexer object is attached to a document whereas previously lexers were attached to views - which could lead to different lexers being used for split views with confusing results. -
  • -
  • - C++ lexer understands the preprocessor enough to grey-out inactive code due to conditional compilation. -
  • -
  • - SciTE can use strips within the main window for find and replace rather than dialogs. - On Windows SciTE always uses a strip for incremental search. -
  • -
  • - Lexer added for Txt2Tags language. - Feature #3018736. -
  • -
  • - Sticky caret feature enhanced with additional SC_CARETSTICKY_WHITESPACE mode . - Feature #3027559. -
  • -
  • - Bash lexer implements basic parsing of compound commands and constructs. - Feature #3033135. -
  • -
  • - C++ folder allows disabling explicit fold comments. -
  • -
  • - Perl folder works for array blocks, adjacent package statements, nested PODs, and terminates package folding at __DATA__, ^D and ^Z. - Feature #3030887. -
  • -
  • - PowerShell lexer supports multiline <# .. #> comments and adds 2 keyword classes. - Feature #3015176. -
  • -
  • - Lexing performed incrementally when needed by wrapping to make user interface more responsive. -
  • -
  • - SciTE setting replaceselection:yes works on GTK+. -
  • -
  • - SciTE Lua scripts calling io.open or io.popen on Windows have arguments treated as UTF-8 and converted to Unicode - so that non-ASCII file paths will work. Lua files with non-ASCII paths run. - Bug #3016951. -
  • -
  • - Crash fixed when searching for empty string. - Bug #3017572. -
  • -
  • - Bugs fixed with folding and lexing when Enter pressed at start of line. - Bug #3032652. -
  • -
  • - Bug fixed with line selection mode not affecting selection range. - Bug #3021480. -
  • -
  • - Bug fixed where indicator alpha was limited to 100 rather than 255. - Bug #3021473. -
  • -
  • - Bug fixed where changing annotation did not cause automatic redraw. -
  • -
  • - Regular expression bug fixed when a character range included non-ASCII characters. -
  • -
  • - Compilation failure with recent compilers fixed on GTK+. - Bug #3022027. -
  • -
  • - Bug fixed on Windows with multiple monitors where autocomplete pop up would appear off-screen - or straddling monitors. - Bug #3017512. -
  • -
  • - SciTE on Windows bug fixed where changing directory to a Unicode path failed. - Bug #3011987. -
  • -
  • - SciTE on Windows bug fixed where combo boxes were not allowing Unicode characters. - Bug #3012986. -
  • -
  • - SciTE on GTK+ bug fixed when dragging files into SciTE on KDE. - Bug #3026555. -
  • -
  • - SciTE bug fixed where closing untitled file could lose data if attempt to name file same as another buffer. - Bug #3011680. -
  • -
  • - COBOL number masks now correctly highlighted. - Bug #3012164. -
  • -
  • - PHP comments can include <?PHP without triggering state change. - Bug #2854183. -
  • -
  • - VHDL lexer styles unclosed string correctly. - Bug #3029627. -
  • -
  • - Memory leak fixed in list boxes on GTK+. - Bug #3007669. -
  • -
-

- Release 2.12 -

-
    -
  • - Released 1 June 2010. -
  • -
  • - Drawing optimizations improve speed and fix some visible flashing when scrolling. -
  • -
  • - Copy Path command added to File menu in SciTE. - Feature #2986745. -
  • -
  • - Optional warning displayed by SciTE when saving a file which has been modified by another process. - Feature #2975041. -
  • -
  • - Flagship lexer for xBase languages updated to follow the language much more closely. - Feature #2992689. -
  • -
  • - HTML lexer highlights Django templates in more regions. - Feature #3002874. -
  • -
  • - Dropping files on SciTE on Windows, releases the drag object earlier and opens the files asynchronously, - leading to smoother user experience. - Feature #2986724. -
  • -
  • - SciTE HTML exports take the Use Monospaced Font setting into account. -
  • -
  • - SciTE window title "[n of m]" localised. -
  • -
  • - When new line inserted at start of line, markers are moved down. - Bug #2986727. -
  • -
  • - On Windows, dropped text has its line ends converted, similar to pasting. - Bug #3005328. -
  • -
  • - Fixed bug with middle-click paste in block select mode where text was pasted next to selection rather than at cursor. - Bug #2984460. -
  • -
  • - Fixed SciTE crash where a style had a size parameter without a value. - Bug #3003834. -
  • -
  • - Debug assertions in multiple lexers fixed. - Bug #3000566. -
  • -
  • - CSS lexer fixed bug where @font-face displayed incorrectly - Bug #2994224. -
  • -
  • - CSS lexer fixed bug where open comment caused highlighting error. - Bug #1683672. -
  • -
  • - Shell file lexer fixed highlight glitch with here docs where the first line is a comment. - Bug #2830239. -
  • -
  • - Bug fixed in SciTE openpath property that caused Open Selected File to fail to open the selected file. -
  • -
  • - Bug fixed in SciTE FileExt property when file name with no extension evaluated to whole path. -
  • -
  • - Fixed SciTE on Windows printing bug where the $(CurrentTime), $(CurrentPage) variables were not expanded. - Bug #2994612. -
  • -
  • - SciTE compiles for 64-bit Windows and runs without crashing. - Bug #2986312. -
  • -
  • - Full Screen mode in Windows Vista/7 improved to hide Start button and size borders a little better. - Bug #3002813. -
  • -
-

- Release 2.11 -

-
    -
  • - Released 9 April 2010. -
  • -
  • - Fixes compatibility of Scintilla.h with the C language. -
  • -
  • - With a rectangular selection SCI_GETSELECTIONSTART and SCI_GETSELECTIONEND return limits of the - rectangular selection rather than the limits of the main selection. -
  • -
  • - When SciTE on Windows is minimized to tray, only takes a single click to restore rather than a double click. - Feature #981917. -
  • -
-

- Release 2.10 -

-
    -
  • - Released 4 April 2010. -
  • -
  • - Version 1.x of GTK+ is no longer supported. -
  • -
  • - SciTE is no longer supported on Windows 95, 98 or ME. -
  • -
  • - Case-insensitive search works for non-ASCII characters in UTF-8 and 8-bit encodings. - Non-regex search in DBCS encodings is always case-sensitive. -
  • -
  • - Non-ASCII characters may be changed to upper and lower case. -
  • -
  • - SciTE on Windows can access all files including those with names outside the user's preferred character encoding. -
  • -
  • - SciTE may be extended with lexers written in Lua. -
  • -
  • - When there are multiple selections, the paste command can go either to the main selection or to each - selection. This is controlled with SCI_SETMULTIPASTE. -
  • -
  • - More forms of bad UTF-8 are detected including overlong sequences, surrogates, and characters outside - the valid range. Bad UTF-8 bytes are now displayed as 2 hex digits preceded by 'x'. -
  • -
  • - SCI_GETTAG retrieves the value of captured expressions within regular expression searches. -
  • -
  • - Django template highlighting added to the HTML lexer. - Feature #2974889. -
  • -
  • - Verilog line comments can be folded. -
  • -
  • - SciTE on Windows allows specifying a filter for the Save As dialog. - Feature #2943445. -
  • -
  • - Bug fixed when multiple selection disabled where rectangular selections could be expanded into multiple selections. - Bug #2948260. -
  • -
  • - Bug fixed when document horizontally scrolled and up/down-arrow did not return to the same - column after horizontal scroll occurred. - Bug #2950799. -
  • -
  • - Bug fixed to remove hotspot highlight when mouse is moved out of the document. Windows only fix. - Bug #2951353. -
  • -
  • - R lexer now performs case-sensitive check for keywords. - Bug #2956543. -
  • -
  • - Bug fixed on GTK+ where text disappeared when a wrap occurred. - Bug #2958043. -
  • -
  • - Bug fixed where regular expression replace cannot escape the '\' character by using '\\'. - Bug #2959876. -
  • -
  • - Bug fixed on GTK+ when virtual space disabled, middle-click could still paste text beyond end of line. - Bug #2971618. -
  • -
  • - SciTE crash fixed when double clicking on a malformed error message in the output pane. - Bug #2976551. -
  • -
  • - Improved performance on GTK+ when changing parameters associated with scroll bars to the same value. - Bug #2964357. -
  • -
  • - Fixed bug with pressing Shift+Tab with a rectangular selection so that it performs an un-indent - similar to how Tab performs an indent. -
  • -
-

- Release 2.03 -

-
    -
  • - Released 14 February 2010. -
  • -
  • - Added SCI_SETFIRSTVISIBLELINE to match SCI_GETFIRSTVISIBLELINE. -
  • -
  • - Erlang lexer extended set of numeric bases recognised; separate style for module:function_name; detects - built-in functions, known module attributes, and known preprocessor instructions; recognizes EDoc and EDoc macros; - separates types of comments. - Bug #2942448. -
  • -
  • - Python lexer extended with lexer.python.strings.over.newline option that allows non-triple-quoted strings to extend - past line ends. This allows use of the Ren'Py language. - Feature #2945550. -
  • -
  • - Fixed bugs with cursor movement after deleting a rectangular selection. - Bug #2942131. -
  • -
  • - Fixed bug where calling SCI_SETSEL when there is a rectangular selection left - the additional selections selected. - Bug #2947064. -
  • -
  • - Fixed macro recording bug where not all bytes in multi-byte character insertions were reported through - SCI_REPLACESEL. -
  • -
  • - Fixed SciTE bug where using Ctrl+Enter followed by Ctrl+Space produced an autocompletion list - with only a single line containing all the identifiers. -
  • -
  • - Fixed SciTE on GTK+ bug where running a tool made the user interface completely unresponsive. -
  • -
  • - Fixed SciTE on Windows Copy to RTF bug. - Bug #2108574. -
  • -
-

- Release 2.02 -

-
    -
  • - Released on 25 January 2010. -
  • -
  • - Markdown lexer added. - Feature #2844081. -
  • -
  • - On GTK+, include code that understands the ranges of lead bytes for code pages 932, 936, and 950 - so that most Chinese and Japanese text can be used on systems that are not set to the corresponding locale. -
  • -
  • - Allow changing the size of dots in visible whitespace using SCI_SETWHITESPACESIZE. - Feature #2839427. -
  • -
  • - Additional carets can be hidden with SCI_SETADDITIONALCARETSVISIBLE. -
  • -
  • - Can choose anti-aliased, non-anti-aliased or lcd-optimized text using SCI_SETFONTQUALITY. -
  • -
  • - Retrieve the current selected text in the autocompletion list with SCI_AUTOCGETCURRENTTEXT. -
  • -
  • - Retrieve the name of the current lexer with SCI_GETLEXERLANGUAGE. -
  • -
  • - Progress 4GL lexer improves handling of comments in preprocessor declaration. - Feature #2902206. -
  • -
  • - HTML lexer extended to handle Mako template language. -
  • -
  • - SQL folder extended for SQL Anywhere "EXISTS" and "ENDIF" keywords. - Feature #2887524. -
  • -
  • - SciTE adds APIPath and AbbrevPath variables. -
  • -
  • - SciTE on GTK+ uses pipes instead of temporary files for running tools. This should be more secure. -
  • -
  • - Fixed crash when calling SCI_STYLEGETFONT for a style which does not have a font set. - Bug #2857425. -
  • -
  • - Fixed crash caused by not having sufficient styles allocated after choosing a lexer. - Bug #2881279. -
  • -
  • - Fixed crash in SciTE using autocomplete word when word characters includes space. - Bug #2840141. -
  • -
  • - Fixed bug with handling upper-case file extensions SciTE on GTK+. -
  • -
  • - Fixed SciTE loading files from sessions with folded folds where it would not - be scrolled to the correct location. - Bug #2882775. -
  • -
  • - Fixed SciTE loading files from sessions when file no longer exists. - Bug #2883437. -
  • -
  • - Fixed SciTE export to HTML using the wrong background colour. -
  • -
  • - Fixed crash when adding an annotation and then adding a new line after the annotation. - Bug #2929708. -
  • -
  • - Fixed crash in SciTE setting a property to nil from Lua. -
  • -
  • - SCI_GETSELTEXT fixed to return correct length. - Bug #2929441. -
  • -
  • - Fixed text positioning problems with selection in some circumstances. -
  • -
  • - Fixed text positioning problems with ligatures on GTK+. -
  • -
  • - Fixed problem pasting into rectangular selection with caret at bottom caused text to go from the caret down - rather than replacing the selection. -
  • -
  • - Fixed problem replacing in a rectangular selection where only the final line was changed. -
  • -
  • - Fixed inability to select a rectangular area using Alt+Shift+Click at both corners. - Bug #2899746. -
  • -
  • - Fixed problem moving to start/end of a rectangular selection with left/right key. - Bug #2871358. -
  • -
  • - Fixed problem with Select All when there's a rectangular selection. - Bug #2930488. -
  • -
  • - Fixed SCI_LINEDUPLICATE on a rectangular selection to not produce multiple discontinuous selections. -
  • -
  • - Virtual space removed when performing delete word left or delete line left. - Virtual space converted to real space for delete word right. - Preserve virtual space when pressing Delete key. - Bug #2882566. -
  • -
  • - Fixed problem where Shift+Alt+Down did not move through wrapped lines. - Bug #2871749. -
  • -
  • - Fixed incorrect background colour when using coloured lines with virtual space. - Bug #2914691. -
  • -
  • - Fixed failure to display wrap symbol for SC_WRAPVISUALFLAGLOC_END_BY_TEXT. - Bug #2936108. -
  • -
  • - Fixed blank background colour with EOLFilled style on last line. - Bug #2890105. -
  • -
  • - Fixed problem in VB lexer with keyword at end of file. - Bug #2901239. -
  • -
  • - Fixed SciTE bug where double clicking on a tab closed the file. -
  • -
  • - Fixed SciTE brace matching commands to only work when the caret is next to the brace, not when - it is in virtual space. - Bug #2885560. -
  • -
  • - Fixed SciTE on Windows Vista to access files in the Program Files directory rather than allow Windows - to virtualize access. - Bug #2916685. -
  • -
  • - Fixed NSIS folder to handle keywords that start with '!'. - Bug #2872157. -
  • -
  • - Changed linkage of Scintilla_LinkLexers to "C" so that it can be used by clients written in C. - Bug #2844718. -
  • -
-

- Release 2.01 -

-
    -
  • - Released on 19 August 2009. -
  • -
  • - Fix to positioning rectangular paste when viewing line ends. -
  • -
  • - Don't insert new lines and indentation for line ends at end of rectangular paste. -
  • -
  • - When not in additional selection typing mode, cutting a rectangular selection removes all of the selected text. -
  • -
  • - Rectangular selections are copied to the clipboard in document order, not in the order of selection. -
  • -
  • - SCI_SETCURRENTPOS and SCI_SETANCHOR work in rectangular mode. -
  • -
  • - On GTK+, drag and drop to a later position in the document now drops at the position. -
  • -
  • - Fix bug where missing property did not use default value. -
  • -
-

- Release 2.0 -

-
    -
  • - Released on 11 August 2009. -
  • -
  • - Multiple pieces of text can be selected simultaneously by holding control while dragging the mouse. - Typing, backspace and delete may affect all selections together. -
  • -
  • - Virtual space allows selecting beyond the last character on a line. -
  • -
  • - SciTE on GTK+ path bar is now optional and defaults to off. -
  • -
  • - MagikSF lexer recognises numbers correctly. -
  • -
  • - Folding of Python comments and blank lines improved. Bug #210240. -
  • -
  • - Bug fixed where background colour of last character in document leaked past that character. -
  • -
  • - Crash fixed when adding marker beyond last line in document. Bug #2830307. -
  • -
  • - Resource leak fixed in SciTE for Windows when printing fails. Bug #2816524. -
  • -
  • - Bug fixed on Windows where the system caret was destroyed during destruction when another window - was using the system caret. Bug #2830223. -
  • -
  • - Bug fixed where indentation guides were drawn over text when the indentation used a style with a different - space width to the default style. -
  • -
  • - SciTE bug fixed where box comment added a bare line feed rather than the chosen line end. Bug #2818104. -
  • -
  • - Reverted fix that led to wrapping whole document when displaying the first line of the document. -
  • -
  • - Export to LaTeX in SciTE fixed to work in more cases and not use as much space. Bug #1286548. -
  • -
  • - Bug fixed where EN_CHANGE notification was sent when performing a paste operation in a - read-only document. Bug #2825485. -
  • -
  • - Refactored code so that Scintilla exposes less of its internal implementation and uses the C++ standard - library for some basic collections. Projects that linked to Scintilla's SString or PropSet classes - should copy this code from a previous version of Scintilla or from SciTE. -
  • -
-

- Release 1.79 -

-
    -
  • - Released on 1 July 2009. -
  • -
  • - Memory exhaustion and other exceptions handled by placing an error value into the - status property rather than crashing. - Scintilla now builds with exception handling enabled and requires exception handling to be enabled.
    - This is a major change and application developers should consider how they will deal with Scintilla exhausting - memory since Scintilla may not be in a stable state. -
  • -
  • - Deprecated APIs removed. The symbols removed are: -
      -
    • SCI_SETCARETPOLICY
    • -
    • CARET_CENTER
    • -
    • CARET_XEVEN
    • -
    • CARET_XJUMPS
    • -
    • SC_FOLDFLAG_BOX
    • -
    • SC_FOLDLEVELBOXHEADERFLAG
    • -
    • SC_FOLDLEVELBOXFOOTERFLAG
    • -
    • SC_FOLDLEVELCONTRACTED
    • -
    • SC_FOLDLEVELUNINDENT
    • -
    • SCN_POSCHANGED
    • -
    • SCN_CHECKBRACE
    • -
    • SCLEX_ASP
    • -
    • SCLEX_PHP
    • -
    -
  • -
  • - Cocoa platform added. -
  • -
  • - Names of struct types in Scintilla.h now start with "Sci_" to avoid possible clashes with platform - definitions. Currently, the old names still work but these will be phased out. -
  • -
  • - When lines are wrapped, subsequent lines may be indented to match the indent of the initial line, - or one more indentation level. Feature #2796119. -
  • -
  • - APIs added for finding the character at a point rather than an inter-character position. Feature #2646738. -
  • -
  • - A new marker SC_MARK_BACKGROUND_UNDERLINE is drawn in the text area as an underline - the full width of the window. -
  • -
  • - Batch file lexer understands variables surrounded by '!'. -
  • -
  • - CAML lexer also supports SML. -
  • -
  • - D lexer handles string and numeric literals more accurately. Feature #2793782. -
  • -
  • - Forth lexer is now case-insensitive and better supports numbers like $hex and %binary. Feature #2804894. -
  • -
  • - Lisp lexer treats '[', ']', '{', and '}' as balanced delimiters which is common usage. Feature #2794989. -
    - It treats keyword argument names as being equivalent to symbols. Feature #2794901. -
  • -
  • - Pascal lexer bug fixed to prevent hang when 'interface' near beginning of file. Bug #2802863. -
  • -
  • - Perl lexer bug fixed where previous lexical states persisted causing "/" special case styling and - subroutine prototype styling to not be correct. Bug #2809168. -
  • -
  • - XML lexer fixes bug where Unicode entities like '&—' were broken into fragments. Bug #2804760. -
  • -
  • - SciTE on GTK+ enables scrolling the tab bar on recent versions of GTK+. Feature #2061821. -
  • -
  • - SciTE on Windows allows tab bar tabs to be reordered by drag and drop. -
  • -
  • - Unit test script for Scintilla on Windows included with source code. -
  • -
  • - User defined menu items are now localised when there is a matching translation. -
  • -
  • - Width of icon column of autocompletion lists on GTK+ made more consistent. -
  • -
  • - Bug with slicing UTF-8 text into character fragments when there is a sequence of 100 or more 3 byte characters. Bug #2780566. -
  • -
  • - Folding bugs introduced in 1.78 fixed. Some of the fix was generic and there was also a specific fix for C++. -
  • -
  • - Bug fixed where a rectangular paste was not padding the line with sufficient spaces to align the pasted text. -
  • -
  • - Bug fixed with showing all text on each line of multi-line annotations when styling the whole annotation using SCI_ANNOTATIONSETSTYLE. Bug #2789430. -
  • -
-

- Release 1.78 -

-
    -
  • - Released on 28 April 2009. -
  • -
  • - Annotation lines may be added to each line. -
  • -
  • - A text margin may be defined with different text on each line. -
  • -
  • - Application actions may be added to the undo history. -
  • -
  • - Can query the symbol defined for a marker. - An available symbol added for applications to indicate that plugins may allocate a marker. -
  • -
  • - Can increase the amount of font ascent and descent. -
  • -
  • - COBOL lexer added. Feature #2127406. -
  • -
  • - Nimrod lexer added. Feature #2642620. -
  • -
  • - PowerPro lexer added. Feature #2195308. -
  • -
  • - SML lexer added. Feature #2710950. -
  • -
  • - SORCUS Installation file lexer added. Feature #2343375. -
  • -
  • - TACL lexer added. Feature #2127406. -
  • -
  • - TAL lexer added. Feature #2127406. -
  • -
  • - Rewritten Pascal lexer with improved folding and other fixes. Feature #2190650. -
  • -
  • - INDIC_ROUNDBOX translucency level can be modified. Feature #2586290. -
  • -
  • - C++ lexer treats angle brackets in #include directives as quotes when styling.within.preprocessor. Bug #2551033. -
  • -
  • - Inno Setup lexer is sensitive to whether within the [Code] section and handles comments better. Bug #2552973. -
  • -
  • - HTML lexer does not go into script mode when script tag is self-closing. -
  • -
  • - HTML folder fixed where confused by comments when fold.html.preprocessor off. Bug #2532774. -
  • -
  • - Perl lexer fixes problem with string matching caused by line endings. Bug #2648342. -
  • -
  • - Progress lexer fixes problem with "last-event:function" phrase. Bug #2483619. -
  • -
  • - Properties file lexer extended to handle RFC2822 text when lexer.props.allow.initial.spaces on. -
  • -
  • - Python lexer adds options for Python 3 and Cython. -
  • -
  • - Shell lexer fixes heredoc problem caused by line endings. Bug #2635257. -
  • -
  • - TeX lexer handles comment at end of line correctly. Bug #2698766. -
  • -
  • - SciTE retains selection range when performing a replace selection command. Feature #2339160. -
  • -
  • - SciTE definition of word characters fixed to match documentaiton. Bug #2464531. -
  • -
  • - SciTE on GTK+ performing Search or Replace when dialog already shown now brings dialog to foreground. - Bug #2634224. -
  • -
  • - Fixed encoding bug with calltips on GTK+. -
  • -
  • - Block caret drawn in correct place on wrapped lines. Bug #2126144. -
  • -
  • - Compilation for 64 bit Windows works using MinGW. Bug #2515578. -
  • -
  • - Incorrect memory freeing fixed on OS X. - Bug #2354098, - Bug #2671749. -
  • -
  • - SciTE on GTK+ crash fixed on startup when child process exits before initialisation complete. - Bug #2716987. -
  • -
  • - Crash fixed when AutoCompleteGetCurrent called with no active autocompletion. -
  • -
  • - Flickering diminished when pressing Tab. Bug #2723006. -
  • -
  • - Namespace compilation issues with GTK+ on OS X fixed. -
  • -
  • - Increased maximum length of SciTE's Language menu on GTK+ to 100 items. Bug #2528241. -
  • -
  • - Fixed incorrect Python lexing for multi-line continued strings. Bug #2450963. -
  • -
-

- Release 1.77 -

-
    -
  • - Released on 18 October 2008. -
  • -
  • - Direct temporary access to Scintilla's text buffer to allow simple efficient interfacing - to libraries like regular expression libraries. -
  • -
  • - Scintilla on Windows can interpret keys as Unicode even when a narrow character - window with SCI_SETKEYSUNICODE. -
  • -
  • - Notification sent when autocompletion cancelled. -
  • -
  • - MySQL lexer added. -
  • -
  • - Lexer for gettext .po files added. -
  • -
  • - Abaqus lexer handles program structure more correctly. -
  • -
  • - Assembler lexer works with non-ASCII text. -
  • -
  • - C++ lexer allows mixed case doc comment tags. -
  • -
  • - CSS lexer updated and works with non-ASCII. -
  • -
  • - Diff lexer adds style for changed lines, handles subversion diffs better and - fixes styling and folding for lines containing chunk dividers ("---"). -
  • -
  • - FORTRAN lexer accepts more styles of compiler directive. -
  • -
  • - Haskell lexer allows hexadecimal literals. -
  • -
  • - HTML lexer improves PHP and JavaScript folding. - PHP heredocs, nowdocs, strings and comments processed more accurately. - Internet Explorer's non-standard >comment< tag supported. - Script recognition in XML can be controlled with lexer.xml.allow.scripts property. -
  • -
  • - Lua lexer styles last character correctly. -
  • -
  • - Perl lexer update. -
  • -
  • - Comment folding implemented for Ruby. -
  • -
  • - Better TeX folding. -
  • -
  • - Verilog lexer updated. -
  • -
  • - Windows Batch file lexer handles %~ and %*. -
  • -
  • - YAML lexer allows non-ASCII text. -
  • -
  • - SciTE on GTK+ implements "Replace in Buffers" in advanced mode. -
  • -
  • - The extender OnBeforeSave method can override the default file saving behaviour by retuning true. -
  • -
  • - Window position and recent files list may be saved into the session file. -
  • -
  • - Right button press outside the selection moves the caret. -
  • -
  • - SciTE load.on.activate works when closing a document reveals a changed document. -
  • -
  • - SciTE bug fixed where eol.mode not used for initial buffer. -
  • -
  • - SciTE bug fixed where a file could be saved as the same name as another - buffer leading to confusing behaviour. -
  • -
  • - Fixed display bug for long lines in same style on Windows. -
  • -
  • - Fixed SciTE crash when finding matching preprocessor command used on some files. -
  • -
  • - Drawing performance improved for files with many blank lines. -
  • -
  • - Folding bugs fixed where changing program text produced a decrease in fold level on a fold header line. -
  • -
  • - Clearing document style now clears all indicators. -
  • -
  • - SciTE's embedded Lua updated to 5.1.4. -
  • -
  • - SciTE will compile with versions of GTK+ before 2.8 again. -
  • -
  • - SciTE on GTK+ bug fixed where multiple files not opened. -
  • -
  • - Bug fixed with SCI_VCHOMEWRAP and SCI_VCHOMEWRAPEXTEND on white last line. -
  • -
  • - Regular expression bug fixed where "^[^(]+$" matched empty lines. -
  • -
-

- Release 1.76 -

-
    -
  • - Released on 16 March 2008. -
  • -
  • - Support for PowerShell. -
  • -
  • - Lexer added for Magik. -
  • -
  • - Director extension working on GTK+. -
  • -
  • - Director extension may set focus to SciTE through "focus:" message on GTK+. -
  • -
  • - C++ folder handles final line better in some cases. -
  • -
  • - SCI_COPYALLOWLINE added which is similar to SCI_COPY except that if the selection is empty then - the line holding the caret is copied. On Windows an extra clipboard format allows pasting this as a whole - line before the current selection. This behaviour is compatible with Visual Studio. -
  • -
  • - On Windows, the horizontal scroll bar can handle wider files. -
  • -
  • - On Windows, a system palette leak was fixed. Should not affect many as palette mode is rarely used. -
  • -
  • - Install command on GTK+ no longer tries to set explicit owner. -
  • -
  • - Perl lexer handles defined-or operator "//". -
  • -
  • - Octave lexer fixes "!=" operator. -
  • -
  • - Optimized selection change drawing to not redraw as much when not needed. -
  • -
  • - SciTE on GTK+ no longer echoes Lua commands so is same as on Windows. -
  • -
  • - Automatic vertical scrolling limited to one line at a time so is not too fast. -
  • -
  • - Crash fixed when line states set beyond end of line states. This occurred when lexers did not - set a line state for each line. -
  • -
  • - Crash in SciTE on Windows fixed when search for 513 character string fails. -
  • -
  • - SciTE disables translucent features on Windows 9x due to crashes reported when using translucency. -
  • -
  • - Bug fixed where whitespace background was not seen on wrapped lines. -
  • -
-

- Release 1.75 -

-
    -
  • - Released on 22 November 2007. -
  • -
  • - Some WordList and PropSet functionality moved from Scintilla to SciTE. - Projects that link to Scintilla's code for these classes may need to copy - code from SciTE. -
  • -
  • - Borland C++ can no longer build Scintilla. -
  • -
  • - Invalid bytes in UTF-8 mode are displayed as hex blobs. This also prevents crashes due to - passing invalid UTF-8 to platform calls. -
  • -
  • - Indentation guides enhanced to be visible on completely empty lines when possible. -
  • -
  • - The horizontal scroll bar may grow to match the widest line displayed. -
  • -
  • - Allow autocomplete pop ups to appear outside client rectangle in some cases. -
  • -
  • - When line state changed, SC_MOD_CHANGELINESTATE modification notification sent and - margin redrawn. -
  • -
  • - SciTE scripts can access the menu command values IDM_*. -
  • -
  • - SciTE's statement.end property has been implemented again. -
  • -
  • - SciTE shows paths and matches in different styles for Find In Files. -
  • -
  • - Incremental search in SciTE for Windows is modeless to make it easier to exit. -
  • -
  • - Folding performance improved. -
  • -
  • - SciTE for GTK+ now includes a Browse button in the Find In Files dialog. -
  • -
  • - On Windows versions that support Unicode well, Scintilla is a wide character window - which allows input for some less common languages like Armenian, Devanagari, - Tamil, and Georgian. To fully benefit, applications should use wide character calls. -
  • -
  • - Lua function names are exported from SciTE to allow some extension libraries to work. -
  • -
  • - Lexers added for Abaqus, Ansys APDL, Asymptote, and R. -
  • -
  • - SCI_DELWORDRIGHTEND added for closer compatibility with GTK+ entry widget. -
  • -
  • - The styling buffer may now use all 8 bits in each byte for lexical states with 0 bits for indicators. -
  • -
  • - Multiple characters may be set for SciTE's calltip.<lexer>.parameters.start property. -
  • -
  • - Bash lexer handles octal literals. -
  • -
  • - C++/JavaScript lexer recognises regex literals in more situations. -
  • -
  • - Haskell lexer fixed for quoted strings. -
  • -
  • - HTML/XML lexer does not notice XML indicator if there is - non-whitespace between the "<?" and "XML". - ASP problem fixed where </ is used inside a comment. -
  • -
  • - Error messages from Lua 5.1 are recognised. -
  • -
  • - Folding implemented for Metapost. -
  • -
  • - Perl lexer enhanced for handling minus-prefixed barewords, - underscores in numeric literals and vector/version strings, - ^D and ^Z similar to __END__, - subroutine prototypes as a new lexical class, - formats and format blocks as new lexical classes, and - '/' suffixed keywords and barewords. -
  • -
  • - Python lexer styles all of a decorator in the decorator style rather than just the name. -
  • -
  • - YAML lexer styles colons as operators. -
  • -
  • - Fixed SciTE bug where undo would group together multiple separate modifications. -
  • -
  • - Bug fixed where setting background colour of calltip failed. -
  • -
  • - SciTE allows wildcard suffixes for file pattern based properties. -
  • -
  • - SciTE on GTK+ bug fixed where user not prompted to save untitled buffer. -
  • -
  • - SciTE bug fixed where property values from one file were not seen by lower priority files. -
  • -
  • - Bug fixed when showing selection with a foreground colour change which highlighted - an incorrect range in some positions. -
  • -
  • - Cut now invokes SCN_MODIFYATTEMPTRO notification. -
  • -
  • - Bug fixed where caret not shown at beginning of wrapped lines. - Caret made visible in some cases after wrapping and scroll bar updated after wrapping. -
  • -
  • - Modern indicators now work on wrapped lines. -
  • -
  • - Some crashes fixed for 64-bit GTK+. -
  • -
  • - On GTK+ clipboard features improved for VMWare tools copy and paste. - SciTE exports the clipboard more consistently on shut down. -
  • -
-

- Release 1.74 -

-
    -
  • - Released on 18 June 2007. -
  • -
  • - OS X support. -
  • -
  • - Indicators changed to be a separate data structure allowing more indicators. Storing indicators in high bits - of styling bytes is deprecated and will be removed in the next version. -
  • -
  • - Unicode support extended to all Unicode characters not just the Basic Multilingual Plane. -
  • -
  • - Performance improved on wide lines by breaking long runs in a single style into shorter segments. -
  • -
  • - Performance improved by caching layout of short text segments. -
  • -
  • - SciTE includes Lua 5.1. -
  • -
  • - Caret may be displayed as a block. -
  • -
  • - Lexer added for GAP. -
  • -
  • - Lexer added for PL/M. -
  • -
  • - Lexer added for Progress. -
  • -
  • - SciTE session files have changed format to be like other SciTE .properties files - and now use the extension .session. - Bookmarks and folds may optionally be saved in session files. - Session files created with previous versions of SciTE will not load into this version. -
  • -
  • - SciTE's extension and scripting interfaces add OnKey, OnDwellStart, and OnClose methods. -
  • -
  • - On GTK+, copying to the clipboard does not include the text/urilist type since this caused problems when - pasting into Open Office. -
  • -
  • - On GTK+, Scintilla defaults caret blink rate to platform preference. -
  • -
  • - Dragging does not start until the mouse has been dragged a certain amount. - This stops spurious drags when just clicking inside the selection. -
  • -
  • - Bug fixed where brace highlight not shown when caret line background set. -
  • -
  • - Bug fixed in Ruby lexer where out of bounds access could occur. -
  • -
  • - Bug fixed in XML folding where tags were not being folded because they are singletons in HTML. -
  • -
  • - Bug fixed when many font names used. -
  • -
  • - Layout bug fixed on GTK+ where fonts have ligatures available. -
  • -
  • - Bug fixed with SCI_LINETRANSPOSE on a blank line. -
  • -
  • - SciTE hang fixed when using UNC path with directory properties feature. -
  • -
  • - Bug on Windows fixed by examining dropped text for Unicode even in non-Unicode mode so it - can work when source only provides Unicode or when using an encoding different from the - system default. -
  • -
  • - SciTE bug on GTK+ fixed where Stop Executing did not work when more than a single process started. -
  • -
  • - SciTE bug on GTK+ fixed where mouse wheel was not switching between buffers. -
  • -
  • - Minor line end fix to PostScript lexer. -
  • -
-

- Release 1.73 -

-
    -
  • - Released on 31 March 2007. -
  • -
  • - SciTE adds a Directory properties file to configure behaviour for files in a directory and its subdirectories. -
  • -
  • - Style changes may be made during text modification events. -
  • -
  • - Regular expressions recognize \d, \D, \s, \S, \w, \W, and \xHH. -
  • -
  • - Support for cmake language added. -
  • -
  • - More Scintilla properties can be queried. -
  • -
  • - Edge line drawn under text. -
  • -
  • - A savesession command added to SciTE director interface. -
  • -
  • - SciTE File | Encoding menu item names changed to be less confusing. -
  • -
  • - SciTE on GTK+ dialog buttons reordered to follow guidelines. -
  • -
  • - SciTE on GTK+ removed GTK+ 1.x compatible file dialog code. -
  • -
  • - SciTE on GTK+ recognises key names KeypadMultiply and KeypadDivide. -
  • -
  • - Background colour of line wrapping visual flag changed to STYLE_DEFAULT. -
  • -
  • - Makefile lexing enhanced for ':=' operator and when lines start with tab. -
  • -
  • - TADS3 lexer and folder improved. -
  • -
  • - SCN_DOUBLECLICK notification may set SCI_SHIFT, SCI_CTRL, and SCI_ALT flags on modifiers field. -
  • -
  • - Slow folding of large constructs in Python fixed. -
  • -
  • - MSSQL folding fixed to be case-insensitive and fold at more keywords. -
  • -
  • - SciTE's brace matching works better for HTML. -
  • -
  • - Determining API list items checks for specified parameters start character before default '('. -
  • -
  • - Hang fixed in HTML lexer. -
  • -
  • - Bug fixed in with LineTranspose command where markers could move to different line. -
  • -
  • - Memory released when buffer completely emptied. -
  • -
  • - If translucency not available on Windows, draw rectangular outline instead. -
  • -
  • - Bash lexer handles "-x" in "--x-includes..." better. -
  • -
  • - AutoIt3 lexer fixes string followed by '+'. -
  • -
  • - LinesJoin fixed where it stopped early due to not adjusting for inserted spaces.. -
  • -
  • - StutteredPageDown fixed when lines wrapped. -
  • -
  • - FormatRange fixed to not double count line number width which could lead to a large space. -
  • -
  • - SciTE Export As PDF and Latex commands fixed to format floating point numbers with '.' even in locales - that use ','. -
  • -
  • - SciTE bug fixed where File | New could produce buffer with contents of previous file when using read-only mode. -
  • -
  • - SciTE retains current scroll position when switching buffers and fold.on.open set. -
  • -
  • - SciTE crash fixed where '*' used to invoke parameters dialog. -
  • -
  • - SciTE bugs when writing large UCS-2 files fixed. -
  • -
  • - Bug fixed when scrolling inside a SCN_PAINTED event by invalidating window - rather than trying to perform synchronous painting. -
  • -
  • - SciTE for GTK+ View | Full Screen works on recent versions of GTK+. -
  • -
  • - SciTE for Windows enables and disables toolbar commands correctly. -
  • -
-

- Release 1.72 -

-
    -
  • - Released on 15 January 2007. -
  • -
  • - Performance of per-line data improved. -
  • -
  • - SC_STARTACTION flag set on the first modification notification in an undo - transaction to help synchronize the container's undo stack with Scintilla's. -
  • -
  • - On GTK+ drag and drop defaults to move rather than copy. -
  • -
  • - Scintilla supports extending appearance of selection to right hand margin. -
  • -
  • - Incremental search available on GTK+. -
  • -
  • - SciTE Indentation Settings dialog available on GTK+ and adds a "Convert" button. -
  • -
  • - Find in Files can optionally ignore binary files or directories that start with ".". -
  • -
  • - Lexer added for "D" language. -
  • -
  • - Export as HTML shows folding with underline lines and +/- symbols. -
  • -
  • - Ruby lexer interprets interpolated strings as expressions. -
  • -
  • - Lua lexer fixes some cases of numeric literals. -
  • -
  • - C++ folder fixes bug with "@" in doc comments. -
  • -
  • - NSIS folder handles !if and related commands. -
  • -
  • - Inno setup lexer adds styling for single and double quoted strings. -
  • -
  • - Matlab lexer handles backslashes in string literals correctly. -
  • -
  • - HTML lexer fixed to allow "?>" in comments in Basic script. -
  • -
  • - Added key codes for Windows key and Menu key. -
  • -
  • - Lua script method scite.MenuCommand(x) performs a menu command. -
  • -
  • - SciTE bug fixed with box comment command near start of file setting selection to end of file. -
  • -
  • - SciTE on GTK+, fixed loop that occurred with automatic loading for an unreadable file. -
  • -
  • - SciTE asks whether to save files when Windows shuts down. -
  • -
  • - Save Session on Windows now defaults the extension to "ses". -
  • -
  • - Bug fixed with single character keywords. -
  • -
  • - Fixed infinite loop for SCI_GETCOLUMN for position beyond end of document. -
  • -
  • - Fixed failure to accept typing on Solaris/GTK+ when using default ISO-8859-1 encoding. -
  • -
  • - Fixed warning from Lua in SciTE when creating a new buffer when already have - maximum number of buffers open. -
  • -
  • - Crash fixed with "%%" at end of batch file. -
  • -
-

- Release 1.71 -

-
    -
  • - Released on 21 August 2006. -
  • - -
  • - Double click notification includes line and position. -
  • -
  • - VB lexer bugs fixed for preprocessor directive below a comment or some other states and - to use string not closed style back to the starting quote when there are internal doubled quotes. -
  • -
  • - C++ lexer allows identifiers to contain '$' and non-ASCII characters such as UTF-8. - The '$' character can be disallowed with lexer.cpp.allow.dollars=0. -
  • -
  • - Perl lexer allows UTF-8 identifiers and has some other small improvements. -
  • -
  • - SciTE's $(CurrentWord) uses word.characters.<filepattern> to define the word - rather than a hardcoded list of word characters. -
  • -
  • - SciTE Export as HTML adds encoding information for UTF-8 file and fixes DOCTYPE. -
  • -
  • - SciTE session and .recent files default to the user properties directory rather than global - properties directory. -
  • -
  • - Left and right scroll events handled correctly on GTK+ and horizontal scroll bar has more sensible - distances for page and arrow clicks. -
  • -
  • - SciTE on GTK+ tab bar fixed to work on recent versions of GTK+. -
  • -
  • - On GTK+, if the approximate character set conversion is unavailable, a second attempt is made - without approximations. This may allow keyboard input and paste to work on older systems. -
  • -
  • - SciTE on GTK+ can redefine the Insert key. -
  • -
  • - SciTE scripting interface bug fixed where some string properties could not be changed. -
  • -
-

- Release 1.70 -

-
    -
  • - Released on 20 June 2006. -
  • -
  • - On GTK+, character set conversion is performed using an option that allows approximate conversions rather - than failures when a character can not be converted. This may lead to similar characters being inserted or - when no similar character is available a '?' may be inserted. -
  • -
  • - On GTK+, the internationalised IM (Input Method) feature is used for all typed input for all character sets. -
  • -
  • - Scintilla has new margin types SC_MARGIN_BACK and SC_MARGIN_FORE that use the default - style's background and foreground colours (normally white and black) as the background to the margin. -
  • -
  • - Scintilla/GTK+ allows file drops on Windows when drop is of type DROPFILES_DND - as well as text/uri-list. -
  • -
  • - Code page can only be set to one of the listed valid values. -
  • -
  • - Text wrapping fixed for cases where insertion was not wide enough to trigger - wrapping before being styled but was after styling. -
  • -
  • - SciTE find marks are removed before printing or exporting to avoid producing incorrect styles. -
  • -
-

- Release 1.69 -

-
    -
  • - Released on 29 May 2006. -
  • -
  • - SciTE supports z-order based buffer switching on Ctrl+Tab. -
  • -
  • - Translucent support for selection and whole line markers. -
  • -
  • - SciTE may have per-language abbreviations files. -
  • -
  • - Support for Spice language. -
  • -
  • - On GTK+ autocompletion lists are optimised and use correct selection colours. -
  • -
  • - On GTK+ the URI data type is preferred in drag and drop so that applications - will see files dragged from the shell rather than dragging the text of the file name - into the document. -
  • -
  • - Increased number of margins to 5. -
  • -
  • - Basic lexer allows include directive $include: "file name". -
  • -
  • - SQL lexer no longer bases folding on indentation. -
  • -
  • - Line ends are transformed when copied to clipboard on - Windows/GTK+2 as well as Windows/GTK+ 1. -
  • -
  • - Lexing code masks off the indicator bits on the start style before calling the lexer - to avoid confusing the lexer when an application has used an indicator. -
  • -
  • - SciTE savebefore:yes only saves the file when it has been changed. -
  • -
  • - SciTE adds output.initial.hide setting to allow setting the size of the output pane - without it showing initially. -
  • -
  • - SciTE on Windows Go To dialog allows line number with more digits. -
  • -
  • - Bug in HTML lexer fixed where a segment of PHP could switch scripting language - based on earlier text on that line. -
  • -
  • - Memory bug fixed when freeing regions on GTK+. - Other minor bugs fixed on GTK+. -
  • -
  • - Deprecated GTK+ calls in Scintilla replaced with current calls. -
  • -
  • - Fixed a SciTE bug where closing the final buffer, if read-only, left the text present in an - untitled buffer. -
  • -
  • - Bug fixed in bash lexer that prevented folding. -
  • -
  • - Crash fixed in bash lexer when backslash at end of file. -
  • -
  • - Crash on recent releases of GTK+ 2.x avoided by changing default font from X - core font to Pango font "!Sans". -
  • -
  • - Fix for SciTE properties files where multiline properties continued over completely blank lines. -
  • -
  • - Bug fixed in SciTE/GTK+ director interface where more data available than - buffer size. -
  • -
  • - Minor visual fixes to SciTE splitter on GTK+. -
  • -
-

- Release 1.68 -

-
    -
  • - Released on 9 March 2006. -
  • -
  • - Translucent drawing implemented for caret line and box indicators. -
  • -
  • - Lexer specifically for TCL is much more accurate than reusing C++ lexer. -
  • -
  • - Support for Inno Setup scripts. -
  • -
  • - Support for Opal language. -
  • -
  • - Calltips may use a new style, STYLE_CALLTIP which allows choosing a - different font for calltips. -
  • -
  • - Python lexer styles comments on decorators. -
  • -
  • - HTML lexer refined handling of "?>" and "%>" within server - side scripts. -
  • -
  • - Batch file lexer improved. -
  • -
  • - Eiffel lexer doesn't treat '.' as a name character. -
  • -
  • - Lua lexer handles length operator, #, and hex literals. -
  • -
  • - Properties file lexer has separate style for keys. -
  • -
  • - PL/SQL folding improved. -
  • -
  • - SciTE Replace dialog always searches in forwards direction. -
  • -
  • - SciTE can detect language of file from initial #! line. -
  • -
  • - SciTE on GTK+ supports output.scroll=2 setting. -
  • -
  • - SciTE can perform an import a properties file from the command line. -
  • -
  • - Set of word characters used for regular expression \< and \>. -
  • -
  • - Bug fixed with SCI_COPYTEXT stopping too early. -
  • -
  • - Bug fixed with splitting lines so that all lines are split. -
  • -
  • - SciTE calls OnSwitchFile when closing one buffer causes a switch to another. -
  • -
  • - SciTE bug fixed where properties were being reevaluated without good reason - after running a macro. -
  • -
  • - Crash fixed when clearing document with some lines contracted in word wrap mode. -
  • -
  • - Palette expands as more entries are needed. -
  • -
  • - SCI_POSITIONFROMPOINT returns more reasonable value when close to - last text on a line. -
  • -
  • - On Windows, long pieces of text may be drawn in segments if they fail to draw - as a whole. -
  • -
  • - Bug fixed with bad drawing when some visual changes made inside SCN_UPDATEUI - notification. -
  • -
  • - SciTE bug fixed with groupundo setting. -
  • -
-

- Release 1.67 -

-
    -
  • - Released on 17 December 2005. -
  • -
  • - Scintilla checks the paint region more accurately when seeing if an area is being - repainted. Platform layer implementations may need to change for this to take - effect. This fixes some drawing and styling bugs. Also optimized some parts of - marker code to only redraw the line of the marker rather than whole of the margin. -
  • -
  • - Quoted identifier style for SQL. SQL folding performed more simply. -
  • -
  • - Ruby lexer improved to better handle here documents and non-ASCII - characters. -
  • -
  • - Lua lexer supports long string and block comment syntax from Lua 5.1. -
  • -
  • - Bash lexer handles here documents better. -
  • -
  • - JavaScript lexing recognises regular expressions more accurately and includes flag - characters in the regular expression style. This is both in JavaScript files and when - JavaScript is embedded in HTML. -
  • -
  • - Scintilla API provided to reveal how many style bits are needed for the - current lexer. -
  • -
  • - Selection duplicate added. -
  • -
  • - Scintilla API for adding a set of markers to a line. -
  • -
  • - DBCS encodings work on Windows 9x. -
  • -
  • - Convention defined for property names to be used by lexers and folders - so they can be automatically discovered and forwarded from containers. -
  • -
  • - Default bookmark in SciTE changed to a blue sphere image. -
  • -
  • - SciTE stores the time of last asking for a save separately for each buffer - which fixes bugs with automatic reloading. -
  • -
  • - On Windows, pasted text has line ends converted to current preference. - GTK+ already did this. -
  • -
  • - Kid template language better handled by HTML lexer by finishing ASP Python - mode when a ?> is found. -
  • -
  • - SciTE counts number of characters in a rectangular selection correctly. -
  • -
  • - 64-bit compatibility improved. One change that may affect user code is that - the notification message header changed to include a pointer-sized id field - to match the current Windows definition. -
  • -
  • - Empty ranges can no longer be dragged. -
  • -
  • - Crash fixed when calls made that use layout inside the painted notification. -
  • -
  • - Bug fixed where Scintilla created pixmap buffers that were too large leading - to failures when many instances used. -
  • -
  • - SciTE sets the directory of a new file to the directory of the currently - active file. -
  • -
  • - SciTE allows choosing a code page for the output pane. -
  • -
  • - SciTE HTML exporter no longer honours monospaced font setting. -
  • -
  • - Line layout cache in page mode caches the line of the caret. An assertion is - now used to ensure that the layout reentrancy problem that caused this - is easier to find. -
  • -
  • - Speed optimized for long lines and lines containing many control characters. -
  • -
  • - Bug fixed in brace matching in DBCS files where byte inside character - is same as brace. -
  • -
  • - Indent command does not indent empty lines. -
  • -
  • - SciTE bug fixed for commands that operate on files with empty extensions. -
  • -
  • - SciTE bug fixed where monospaced option was copied for subsequently opened files. -
  • -
  • - SciTE on Windows bug fixed in the display of a non-ASCII search string - which can not be found. -
  • -
  • - Bugs fixed with nested calls displaying a new calltip while one is already - displayed. -
  • -
  • - Bug fixed when styling PHP strings. -
  • -
  • - Bug fixed when styling C++ continued preprocessor lines. -
  • -
  • - SciTE bug fixed where opening file from recently used list reset choice of - language. -
  • -
  • - SciTE bug fixed when compiled with NO_EXTENSIONS and - closing one file closes the application. -
  • -
  • - SciTE crash fixed for error messages that look like Lua messages but aren't - in the same order. -
  • -
  • - Remaining fold box support deprecated. The symbols SC_FOLDLEVELBOXHEADERFLAG, - SC_FOLDLEVELBOXFOOTERFLAG, SC_FOLDLEVELCONTRACTED, - SC_FOLDLEVELUNINDENT, and SC_FOLDFLAG_BOX are deprecated. -
  • -
-

- Release 1.66 -

-
    -
  • - Released on 26 August 2005. -
  • -
  • - New, more ambitious Ruby lexer. -
  • -
  • - SciTE Find in Files dialog has options for matching case and whole words which are - enabled when the internal find command is used. -
  • -
  • - SciTE output pane can display automatic completion after "$(" typed. - An initial ">" on a line is ignored when Enter pressed. -
  • -
  • - C++ lexer recognises keywords within line doc comments. It continues styles over line - end characters more consistently so that eolfilled style can be used for preprocessor lines - and line comments. -
  • -
  • - VB lexer improves handling of file numbers and date literals. -
  • -
  • - Lua folder handles repeat until, nested comments and nested strings. -
  • -
  • - POV lexer improves handling of comment lines. -
  • -
  • - AU3 lexer and folder updated. COMOBJ style added. -
  • -
  • - Bug fixed with text display on GTK+ with Pango 1.8. -
  • -
  • - Caret painting avoided when not focused. -
  • -
  • - SciTE on GTK+ handles file names used to reference properties as case-sensitive. -
  • -
  • - SciTE on GTK+ Save As and Export commands set the file name field. - On GTK+ the Export commands modify the file name in the same way as on Windows. -
  • -
  • - Fixed SciTE problem where confirmation was not displaying when closing a file where all - contents had been deleted. -
  • -
  • - Middle click on SciTE tab now closes correct buffer on Windows when tool bar is visible. -
  • -
  • - SciTE bugs fixed where files contained in directory that includes '.' character. -
  • -
  • - SciTE bug fixed where import in user options was reading file from directory of - global options. -
  • -
  • - SciTE calltip bug fixed where single line calltips had arrow displayed incorrectly. -
  • -
  • - SciTE folding bug fixed where empty lines were shown for no reason. -
  • -
  • - Bug fixed where 2 byte per pixel XPM images caused crash although they are still not - displayed. -
  • -
  • - Autocompletion list size tweaked. -
  • -
-

- Release 1.65 -

-
    -
  • - Released on 1 August 2005. -
  • -
  • - FreeBasic support. -
  • -
  • - SciTE on Windows handles command line arguments - "-" (read standard input into buffer), - "--" (read standard input into output pane) and - "-@" (read file names from standard input and open each). -
  • -
  • - SciTE includes a simple implementation of Find in Files which is used if no find.command is set. -
  • -
  • - SciTE can close tabs with a mouse middle click. -
  • -
  • - SciTE includes a save.all.for.build setting. -
  • -
  • - Folder for MSSQL. -
  • -
  • - Batch file lexer understands more of the syntax and the behaviour of built in commands. -
  • -
  • - Perl lexer handles here docs better; disambiguates barewords, quote-like delimiters, and repetition operators; - handles Pods after __END__; recognises numbers better; and handles some typeglob special variables. -
  • -
  • - Lisp adds more lexical states. -
  • -
  • - PHP allows spaces after <<<. -
  • -
  • - TADS3 has a simpler set of states and recognises identifiers. -
  • -
  • - Avenue elseif folds better. -
  • -
  • - Errorlist lexer treats lines starting with '+++' and '---' as separate - styles from '+' and '-' as they indicate file names in diffs. -
  • -
  • - SciTE error recogniser handles file paths in extra explanatory lines from MSVC - and in '+++' and '---' lines from diff. -
  • -
  • - Bugs fixed in SciTE and Scintilla folding behaviour when text pasted before - folded text caused unnecessary - unfolding and cutting text could lead to text being irretrievably hidden. -
  • -
  • - SciTE on Windows uses correct font for dialogs and better font for tab bar - allowing better localisation -
  • -
  • - When Windows is used with a secondary monitor before the primary - monitor, autocompletion lists are not forced onto the primary monitor. -
  • -
  • - Scintilla calltip bug fixed where down arrow setting wrong value in notification - if not in first line. SciTE bug fixed where second arrow only shown on multiple line - calltip and was therefore misinterpreting the notification value. -
  • -
  • - Lexers will no longer be re-entered recursively during, for example, fold level setting. -
  • -
  • - Undo of typing in overwrite mode undoes one character at a time rather than requiring a removal - and addition step for each character. -
  • -
  • - EM_EXSETSEL(0,-1) fixed. -
  • -
  • - Bug fixed where part of a rectangular selection was not shown as selected. -
  • -
  • - Autocomplete window size fixed. -
  • -
-

- Release 1.64 -

-
    -
  • - Released on 6 June 2005. -
  • -
  • - TADS3 support -
  • -
  • - Smalltalk support. -
  • -
  • - Rebol support. -
  • -
  • - Flagship (Clipper / XBase) support. -
  • -
  • - CSound support. -
  • -
  • - SQL enhanced to support SQL*Plus. -
  • -
  • - SC_MARK_FULLRECT margin marker fills the whole marker margin for marked - lines with a colour. -
  • -
  • - Performance improved for some large undo and redo operations and modification flags - added in notifications. -
  • -
  • - SciTE adds command equivalents for fold margin mouse actions. -
  • -
  • - SciTE adds OnUpdateUI to set of events that can be handled by a Lua script. -
  • -
  • - Properties set in Scintilla can be read. -
  • -
  • - GTK+ SciTE exit confirmation adds Cancel button. -
  • -
  • - More accurate lexing of numbers in PHP and Caml. -
  • -
  • - Perl can fold POD and package sections. POD verbatim section style. - Globbing syntax recognised better. -
  • -
  • - Context menu moved slightly on GTK+ so that it will be under the mouse and will - stay open if just clicked rather than held. -
  • -
  • - Rectangular selection paste works the same whichever direction the selection was dragged in. -
  • -
  • - EncodedFromUTF8 handles -1 length argument as documented. -
  • -
  • - Undo and redo can cause SCN_MODIFYATTEMPTRO notifications. -
  • -
  • - Indicators display correctly when they start at the second character on a line. -
  • -
  • - SciTE Export As HTML uses standards compliant CSS. -
  • -
  • - SciTE automatic indentation handles keywords for indentation better. -
  • -
  • - SciTE fold.comment.python property removed as does not work. -
  • -
  • - Fixed problem with character set conversion when pasting on GTK+. -
  • -
  • - SciTE default character set changed from ANSI_CHARSET to DEFAULT_CHARSET. -
  • -
  • - Fixed crash when creating empty autocompletion list. -
  • -
  • - Autocomplete window size made larger under some conditions to make truncation less common. -
  • -
  • - Bug fixed where changing case of a selection did not affect initial character of lines - in multi-byte encodings. -
  • -
  • - Bug fixed where rectangular selection not displayed after Alt+Shift+Click. -
  • -
-

- Release 1.63 -

-
    -
  • - Released on 4 April 2005. -
  • -
  • - Autocompletion on Windows changed to use pop up window, be faster, - allow choice of maximum width and height, and to highlight only the text of the - selected item rather than both the text and icon if any. -
  • -
  • - Extra items can be added to the context menu in SciTE. -
  • -
  • - Character wrap mode in Scintilla helps East Asian languages. -
  • -
  • - Lexer added for Haskell. -
  • -
  • - Objective Caml support. -
  • -
  • - BlitzBasic and PureBasic support. -
  • -
  • - CSS support updated to handle CSS2. -
  • -
  • - C++ lexer is more selective about document comment keywords. -
  • -
  • - AutoIt 3 lexer improved. -
  • -
  • - Lua lexer styles end of line characters on comment and preprocessor - lines so that the eolfilled style can be applied to them. -
  • -
  • - NSIS support updated for line continuations, box comments, SectionGroup and - PageEx, and with more up-to-date properties. -
  • -
  • - Clarion lexer updated to perform folding and have more styles. -
  • -
  • - SQL lexer gains second set of keywords. -
  • -
  • - Errorlist lexer recognises Borland Delphi error messages. -
  • -
  • - Method added for determining number of visual lines occupied by a document - line due to wrapping. -
  • -
  • - Sticky caret mode does not modify the preferred caret x position when typing - and may be useful for typing columns of text. -
  • -
  • - Dwell end notification sent when scroll occurs. -
  • -
  • - On GTK+, Scintilla requisition height is screen height rather than large fixed value. -
  • -
  • - Case insensitive autocompletion prefers exact case match. -
  • -
  • - SCI_PARADOWN and SCI_PARAUP treat lines containing only white - space as empty and handle text hidden by folding. -
  • -
  • - Scintilla on Windows supports WM_PRINTCLIENT although there are some - limitations. -
  • -
  • - SCN_AUTOCSELECTION notification sent when user selects from autoselection list. -
  • -
  • - SciTE's standard properties file sets buffers to 10, uses Pango fonts on GTK+ and - has dropped several languages to make the menu fit on screen. -
  • -
  • - SciTE's encoding cookie detection loosened so that common XML files will load - in UTF-8 if that is their declared encoding. -
  • -
  • - SciTE on GTK+ changes menus and toolbars to not be detachable unless turned - on with a property. Menus no longer tear off. The toolbar may be set to use the - default theme icons rather than SciTE's set. Changed key for View | End of Line - because of a conflict. Language menu can contain more items. -
  • -
  • - SciTE on GTK+ 2.x allows the height and width of the file open file chooser to - be set, for the show hidden files check box to be set from an option and for it - to be opened in the directory of the current file explicitly. Enter key works in - save chooser. -
  • -
  • - Scintilla lexers should no longer see bits in style bytes that are outside the set - they modify so should be able to correctly lex documents where the container - has used indicators. -
  • -
  • - SciTE no longer asks to save before performing a revert. -
  • -
  • - SciTE director interface adds a reloadproperties command to reload properties - from files. -
  • -
  • - Allow build on CYGWIN platform. -
  • -
  • - Allow use from LccWin compiler. -
  • -
  • - SCI_COLOURISE for SCLEX_CONTAINER causes a - SCN_STYLENEEDED notification. -
  • -
  • - Bugs fixed in lexing of HTML/ASP/JScript. -
  • -
  • - Fix for folding becoming confused. -
  • -
  • - On Windows, fixes for Japanese Input Method Editor and for 8 bit Katakana - characters. -
  • -
  • - Fixed buffer size bug avoided when typing long words by making buffer bigger. -
  • -
  • - Undo after automatic indentation more sensible. -
  • -
  • - SciTE menus on GTK+ uses Shift and Ctrl rather than old style abbreviations. -
  • -
  • - SciTE full screen mode on Windows calculates size more correctly. -
  • -
  • - SciTE on Windows menus work better with skinning applications. -
  • -
  • - Searching bugs fixed. -
  • -
  • - Colours reallocated when changing image using SCI_REGISTERIMAGE. -
  • -
  • - Caret stays visible when Enter held down. -
  • -
  • - Undo of automatic indentation more reasonable. -
  • -
  • - High processor usage fixed in background wrapping under some - circumstances. -
  • -
  • - Crashing bug fixed on AMD64. -
  • -
  • - SciTE crashing bug fixed when position.height or position.width not set. -
  • -
  • - Crashing bug on GTK+ fixed when setting cursor and window is NULL. -
  • -
  • - Crashing bug on GTK+ preedit window fixed. -
  • -
  • - SciTE crashing bug fixed in incremental search on Windows ME. -
  • -
  • - SciTE on Windows has a optional find and replace dialogs that can search through - all buffers and search within a particular style number. -
  • -
-

- Release 1.62 -

-
    -
  • - Released on 31 October 2004. -
  • -
  • - Lexer added for ASN.1. -
  • -
  • - Lexer added for VHDL. -
  • -
  • - On Windows, an invisible system caret is used to allow screen readers to determine - where the caret is. The visible caret is still drawn by the painting code. -
  • -
  • - On GTK+, Scintilla has methods to read the target as UTF-8 and to convert - a string from UTF-8 to the document encoding. This eases integration with - containers that use the UTF-8 encoding which is the API encoding for GTK+ 2. -
  • -
  • - SciTE on GTK+2 and Windows NT/2000/XP allows search and replace of Unicode text. -
  • -
  • - SciTE calltips allow setting the characters used to start and end parameter lists and - to separate parameters. -
  • -
  • - FindColumn method converts a line and column into a position, taking into account - tabs and multi-byte characters. -
  • -
  • - On Windows, when Scintilla copies text to the clipboard as Unicode, it avoids - adding an ANSI copy as the system will automatically convert as required in - a context-sensitive manner. -
  • -
  • - SciTE indent.auto setting automatically determines indent.size and use.tabs from - document contents. -
  • -
  • - SciTE defines a CurrentMessage property that holds the most recently selected - output pane message. -
  • -
  • - SciTE Lua scripting enhanced with -
      -
    • A Lua table called 'buffer' is associated with each buffer and can be used to - maintain buffer-specific state.
    • -
    • A 'scite' object allows interaction with the application such as opening - files from script.
    • -
    • Dynamic properties can be reset by assigning nil to a given key in - the props table.
    • -
    • An 'OnClear' event fires whenever properties and extension scripts are - about to be reloaded.
    • -
    • On Windows, loadlib is enabled and can be used to access Lua - binary modules / DLLs.
    -
  • -
  • - SciTE Find in Files on Windows can be used in a modeless way and gains a '..' - button to move up to the parent directory. It is also wider so that longer paths - can be seen. -
  • -
  • - Close buttons added to dialogs in SciTE on Windows. -
  • -
  • - SciTE on GTK+ 2 has a "hidden files" check box in file open dialog. -
  • -
  • - SciTE use.monospaced setting removed. More information in the - FAQ. -
  • -
  • - APDL lexer updated with more lexical classes -
  • -
  • - AutoIt3 lexer updated. -
  • -
  • - Ada lexer fixed to support non-ASCII text. -
  • -
  • - Cpp lexer now only matches exactly three slashes as starting a doc-comment so that - lines of slashes are seen as a normal comment. - Line ending characters are appear in default style on preprocessor and single line - comment lines. -
  • -
  • - CSS lexer updated to support CSS2 including second set of keywords. -
  • -
  • - Errorlist lexer now understands Java stack trace lines. -
  • -
  • - SciTE's handling of HTML Tidy messages jumps to column as well as line indicated. -
  • -
  • - Lisp lexer allows multiline strings. -
  • -
  • - Lua lexer treats .. as an operator when between identifiers. -
  • -
  • - PHP lexer handles 'e' in numerical literals. -
  • -
  • - PowerBasic lexer updated for macros and optimised. -
  • -
  • - Properties file folder changed to leave lines before a header at the base level - and thus avoid a vertical line when using connected folding symbols. -
  • -
  • - GTK+ on Windows version uses Alt for rectangular selection to be compatible with - platform convention. -
  • -
  • - SciTE abbreviations file moved from system directory to user directory - so each user can have separate abbreviations. -
  • -
  • - SciTE on GTK+ has improved .desktop file and make install support that may - lead to better integration with system shell. -
  • -
  • - Disabling of themed background drawing on GTK+ extended to all cases. -
  • -
  • - SciTE date formatting on Windows performed with the user setting rather than the - system setting. -
  • -
  • - GTK+ 2 redraw while scrolling fixed. -
  • -
  • - Recursive property definitions are safer, avoiding expansion when detected. -
  • -
  • - SciTE thread synchronization for scripts no longer uses HWND_MESSAGE - so is compatible with older versions of Windows. - Other Lua scripting bugs fixed. -
  • -
  • - SciTE on Windows localisation of menu accelerators changed to be compatible - with alternative UI themes. -
  • -
  • - SciTE on Windows full screen mode now fits better when menu different height - to title bar height. -
  • -
  • - SC_MARK_EMPTY marker is now invisible and does not change the background - colour. -
  • -
  • - Bug fixed in HTML lexer to allow use of <?xml in strings in scripts without - triggering xml mode. -
  • -
  • - Bug fixed in SciTE abbreviation expansion that could break indentation or crash. -
  • -
  • - Bug fixed when searching for a whole word string that ends one character before - end of document. -
  • -
  • - Drawing bug fixed when indicators drawn on wrapped lines. -
  • -
  • - Bug fixed when double clicking a hotspot. -
  • -
  • - Bug fixed where autocompletion would remove typed text if no match found. -
  • -
  • - Bug fixed where display does not scroll when inserting in long wrapped line. -
  • -
  • - Bug fixed where SCI_MARKERDELETEALL would only remove one of the markers - on a line that contained multiple markers with the same number. -
  • -
  • - Bug fixed where markers would move when converting line endings. -
  • -
  • - Bug fixed where SCI_LINEENDWRAP would move too far when line ends are visible. -
  • -
  • - Bugs fixed where calltips with unicode or other non-ASCII text would display - incorrectly. -
  • -
  • - Bug fixed in determining if at save point after undoing from save point and then - performing changes. -
  • -
  • - Bug fixed on GTK+ using unsupported code pages where extraneous text could - be drawn. -
  • -
  • - Bug fixed in drag and drop code on Windows where dragging from SciTE to - Firefox could hang both applications. -
  • -
  • - Crashing bug fixed on GTK+ when no font allocation succeeds. -
  • -
  • - Crashing bug fixed when autocompleting word longer than 1000 characters. -
  • -
  • - SciTE crashing bug fixed when both Find and Replace dialogs shown by disallowing - this situation. -
  • -
-

- Release 1.61 -

-
    -
  • - Released on 29 May 2004. -
  • -
  • - Improvements to selection handling on GTK+. -
  • -
  • - SciTE on GTK+ 2.4 uses the improved file chooser which allows - file extension filters, multiple selection, and remembers favourite - directories. -
  • -
  • - SciTE Load Session and Save Session commands available on GTK+. -
  • -
  • - SciTE lists Lua Startup Script in Options menu when loaded. -
  • -
  • - In SciTE, OnUserListSelection can be implemented in Lua. -
  • -
  • - SciTE on Windows has a context menu on the file tabs. -
  • -
  • - SQL lexer allows '#' comments and optionally '\' quoting inside strings. -
  • -
  • - Mssql lexer improved. -
  • -
  • - AutoIt3 lexer updated. -
  • -
  • - Perl lexer recognises regular expression use better. -
  • -
  • - Errorlist lexer understands Lua tracebacks and copes with findstr - output for file names that end with digits. -
  • -
  • - Drawing of lines on GTK+ improved and made more like Windows - without final point. -
  • -
  • - SciTE on GTK+ uses a high resolution window icon. -
  • -
  • - SciTE can be set to warn before loading files larger than a particular size. -
  • -
  • - SciTE Lua scripting bugs fixed included a crashing bug when using - an undefined function name that would go before first actual name. -
  • -
  • - SciTE bug fixed where a modified buffer was not saved if it was - the last buffer and was not current when the New command used. -
  • -
  • - SciTE monofont mode no longer affects line numbers. -
  • -
  • - Crashing bug in SciTE avoided by not allowing both the Find and Replace - dialogs to be visible at one time. -
  • -
  • - Crashing bug in SciTE fixed when Lua scripts were being run - concurrently. -
  • -
  • - Bug fixed that caused incorrect line number width in SciTE. -
  • -
  • - PHP folding bug fixed. -
  • -
  • - Regression fixed when setting word characters to not include - some of the standard word characters. -
  • -
-

- Release 1.60 -

-
    -
  • - Released on 1 May 2004. -
  • -
  • - SciTE can be scripted using the Lua programming language. -
  • -
  • - command.mode is a better way to specify tool command options in SciTE. -
  • -
  • - Continuation markers can be displayed so that you can see which lines are wrapped. -
  • -
  • - Lexer for Gui4Cli language. -
  • -
  • - Lexer for Kix language. -
  • -
  • - Lexer for Specman E language. -
  • -
  • - Lexer for AutoIt3 language. -
  • -
  • - Lexer for APDL language. -
  • -
  • - Lexer for Bash language. Also reasonable for other Unix shells. -
  • -
  • - SciTE can load lexers implemented in external shared libraries. -
  • -
  • - Perl treats "." not as part of an identifier and interprets '/' and '->' - correctly in more circumstances. -
  • -
  • - PHP recognises variables within strings. -
  • -
  • - NSIS has properties "nsis.uservars" and "nsis.ignorecase". -
  • -
  • - MSSQL lexer adds keyword list for operators and stored procedures, - defines '(', ')', and ',' as operators and changes some other details. -
  • -
  • - Input method preedit window on GTK+ 2 may support some Asian languages. -
  • -
  • - Platform interface adds an extra platform-specific flag to Font::Create. - Used on wxWidgets to choose antialiased text display but may be used for - any task that a platform needs. -
  • -
  • - OnBeforeSave method added to Extension interface. -
  • -
  • - Scintilla methods that return strings can be called with a NULL pointer - to find out how long the string should be. -
  • -
  • - Visual Studio .NET project file now in VS .NET 2003 format so can not be used - directly in VS .NET 2002. -
  • -
  • - Scintilla can be built with GTK+ 2 on Windows. -
  • -
  • - Updated RPM spec for SciTE on GTK+. -
  • -
  • - GTK+ makefile for SciTE allows selection of destination directory, creates destination - directories and sets file modes and owners better. -
  • -
  • - Tab indents now go to next tab multiple rather than add tab size. -
  • -
  • - SciTE abbreviations now use the longest possible match rather than the shortest. -
  • -
  • - Autocompletion does not remove prefix when actioned with no choice selected. -
  • -
  • - Autocompletion cancels when moving beyond the start position, not at the start position. -
  • -
  • - SciTE now shows only calltips for functions that match exactly, not - those that match as a prefix. -
  • -
  • - SciTE can repair box comment sections where some lines were added without - the box comment middle line prefix. -
  • -
  • - Alt+ works in user.shortcuts on Windows. -
  • -
  • - SciTE on GTK+ enables replace in selection for rectangular selections. -
  • -
  • - Key bindings for command.shortcut implemented in a way that doesn't break - when the menus are localised. -
  • -
  • - Drawing of background on GTK+ faster as theme drawing disabled. -
  • -
  • - On GTK+, calltips are moved back onto the screen if they extend beyond the screen bounds. -
  • -
  • - On Windows, the Scintilla object is destroyed on WM_NCDESTROY rather than - WM_DESTROY which arrives earlier. This fixes some problems when Scintilla was subclassed. -
  • -
  • - The zorder switching feature removed due to number of crashing bugs. -
  • -
  • - Code for XPM images made more robust. -
  • -
  • - Bug fixed with primary selection on GTK+. -
  • -
  • - On GTK+ 2, copied or cut text can still be pasted after the Scintilla widget is destroyed. -
  • -
  • - Styling change not visible problem fixed when line was cached. -
  • -
  • - Bug in SciTE on Windows fixed where clipboard commands stopped working. -
  • -
  • - Crashing bugs in display fixed in line layout cache. -
  • -
  • - Crashing bug may be fixed on AMD64 processor on GTK+. -
  • -
  • - Rare hanging crash fixed in Python lexer. -
  • -
  • - Display bugs fixed with DBCS characters on GTK+. -
  • -
  • - Autocompletion lists on GTK+ 2 are not sorted by the ListModel as the - contents are sorted correctly by Scintilla. -
  • -
  • - SciTE fixed to not open extra untitled buffers with check.if.already.open. -
  • -
  • - Sizing bug fixed on GTK+ when window resized while unmapped. -
  • -
  • - Text drawing crashing bug fixed on GTK+ with non-Pango fonts and long strings. -
  • -
  • - Fixed some issues if characters are unsigned. -
  • -
  • - Fixes in NSIS support. -
  • -
-

- Release 1.59 -

-
    -
  • - Released on 19 February 2004. -
  • -
  • - SciTE Options and Language menus reduced in length by commenting - out some languages. Languages can be enabled by editing the global - properties file. -
  • -
  • - Verilog language supported. -
  • -
  • - Lexer for Microsoft dialect of SQL. SciTE properties file available from extras page. -
  • -
  • - Perl lexer disambiguates '/' better. -
  • -
  • - NSIS lexer improved with a lexical class for numbers, option for ignoring case - of keywords, and folds only occurring when folding keyword first on line. -
  • -
  • - PowerBasic lexer improved with styles for constants and assembler and - folding improvements. -
  • -
  • - On GTK+, input method support only invoked for Asian languages and not - European languages as the old European keyboard code works better. -
  • -
  • - Scintilla can be requested to allocate a certain amount and so avoid repeated - reallocations and memory inefficiencies. SciTE uses this and so should require - less memory. -
  • -
  • - SciTE's "toggle current fold" works when invoked on child line as well as - fold header. -
  • -
  • - SciTE output pane scrolling can be set to not scroll back to start after - completion of command. -
  • -
  • - SciTE has a $(SessionPath) property. -
  • -
  • - SciTE on Windows can use VK_* codes for keys in user.shortcuts. -
  • -
  • - Stack overwrite bug fixed in SciTE's command to move to the end of a - preprocessor conditional. -
  • -
  • - Bug fixed where vertical selection appeared to select a different set of characters - then would be used by, for example, a copy. -
  • -
  • - SciTE memory leak fixed in fold state remembering. -
  • -
  • - Bug fixed where changing the style of some text outside the - standard StyleNeeded notification would not be visible. -
  • -
  • - On GTK+ 2 g_iconv is used in preference to iconv, as it is provided by GTK+ - so should avoid problems finding the iconv library. -
  • -
  • - On GTK+ fixed a style reference count bug. -
  • -
  • - Memory corruption bug fixed with GetSelText. -
  • -
  • - On Windows Scintilla deletes memory on WM_NCDESTROY rather than - the earlier WM_DESTROY to avoid problems when the window is subclassed. -
  • -
-

- Release 1.58 -

-
    -
  • - Released on 11 January 2004. -
  • -
  • - Method to discover the currently highlighted element in an autocompletion list. -
  • -
  • - On GTK+, the lexers are now included in the scintilla.a library file. This - will require changes to the make files of dependent projects. -
  • -
  • - Octave support added alongside related Matlab language and Matlab support improved. -
  • -
  • - VB lexer gains an unterminated string state and 4 sets of keywords. -
  • -
  • - Ruby lexer handles $' correctly. -
  • -
  • - Error line handling improved for FORTRAN compilers from Absoft and Intel. -
  • -
  • - International input enabled on GTK+ 2 although there is no way to choose an - input method. -
  • -
  • - MultiplexExtension in SciTE allows multiple extensions to be used at once. -
  • -
  • - Regular expression replace interprets backslash expressions \a, \b, \f, \n, \r, \t, - and \v in the replacement value. -
  • -
  • - SciTE Replace dialog displays number of replacements made when Replace All or - Replace in Selection performed. -
  • -
  • - Localisation files may contain a translation.encoding setting which is used - on GTK+ 2 to automatically reencode the translation to UTF-8 so it will be - the localised text will be displayed correctly. -
  • -
  • - SciTE on GTK+ implements check.if.already.open. -
  • -
  • - Make files for Mac OS X made more robust. -
  • -
  • - Performance improved in SciTE when switching buffers when there - is a rectangular selection. -
  • -
  • - Fixed failure to display some text when wrapped. -
  • -
  • - SciTE crashes from Ctrl+Tab buffer cycling fixed. - May still be some rare bugs here. -
  • -
  • - Crash fixed when decoding an error message that appears similar to a - Borland error message. -
  • -
  • - Fix to auto-scrolling allows containers to implement enhanced double click selection. -
  • -
  • - Hang fixed in idle word wrap. -
  • -
  • - Crash fixed in hotspot display code.. -
  • -
  • - SciTE on Windows Incremental Search no longer moves caret back. -
  • -
  • - SciTE hang fixed when performing a replace with a find string that - matched zero length strings such as ".*". -
  • -
  • - SciTE no longer styles the whole file when saving buffer fold state - as that was slow. -
  • -
-

- Release 1.57 -

-
    -
  • - Released on 27 November 2003. -
  • -
  • - SciTE remembers folding of each buffer. -
  • -
  • - Lexer for Erlang language. -
  • -
  • - Scintilla allows setting the set of white space characters. -
  • -
  • - Scintilla has 'stuttered' page movement commands to first move - to top or bottom within current visible lines before scrolling. -
  • -
  • - Scintilla commands for moving to end of words. -
  • -
  • - Incremental line wrap enabled on Windows. -
  • -
  • - SciTE PDF exporter produces output that is more compliant with reader - applications, is smaller and allows more configuration. - HTML exporter optimizes size of output files. -
  • -
  • - SciTE defines properties PLAT_WINNT and PLAT_WIN95 on the - corresponding platforms. -
  • -
  • - SciTE can adjust the line margin width to fit the largest line number. - The line.numbers property is split between line.margin.visible and - line.margin.width. -
  • -
  • - SciTE on GTK+ allows user defined menu accelerators. - Alt can be included in user.shortcuts. -
  • -
  • - SciTE Language menu can have items commented out. -
  • -
  • - SciTE on Windows Go to dialog allows choosing a column number as - well as a line number. -
  • -
  • - SciTE on GTK+ make file uses prefix setting more consistently. -
  • -
  • - Bug fixed that caused word wrapping to fail to display all text. -
  • -
  • - Crashing bug fixed in GTK+ version of Scintilla when using GDK fonts - and opening autocompletion. -
  • -
  • - Bug fixed in Scintilla SCI_GETSELTEXT where an extra NUL - was included at end of returned string -
  • -
  • - Crashing bug fixed in SciTE z-order switching implementation. -
  • -
  • - Hanging bug fixed in Perl lexer. -
  • -
  • - SciTE crashing bug fixed for using 'case' without argument in style definition. -
  • -
-

- Release 1.56 -

-
    -
  • - Released on 25 October 2003. -
  • -
  • - Rectangular selection can be performed using the keyboard. - Greater programmatic control over rectangular selection. - This has caused several changes to key bindings. -
  • -
  • - SciTE Replace In Selection works on rectangular selections. -
  • -
  • - Improved lexer for TeX, new lexer for Metapost and other support for these - languages. -
  • -
  • - Lexer for PowerBasic. -
  • -
  • - Lexer for Forth. -
  • -
  • - YAML lexer improved to include error styling. -
  • -
  • - Perl lexer improved to correctly handle more cases. -
  • -
  • - Assembler lexer updated to support single-quote strings and fix some - problems. -
  • -
  • - SciTE on Windows can switch between buffers in order of use (z-order) rather - than static order. -
  • -
  • - SciTE supports adding an extension for "Open Selected Filename". - The openpath setting works on GTK+. -
  • -
  • - SciTE can Export as XML. -
  • -
  • - SciTE $(SelHeight) variable gives a more natural result for empty and whole line - selections. -
  • -
  • - Fixes to wrapping problems, such as only first display line being visible in some - cases. -
  • -
  • - Fixes to hotspot to only highlight when over the hotspot, only use background - colour when set and option to limit hotspots to a single line. -
  • -
  • - Small fixes to FORTRAN lexing and folding. -
  • -
  • - SQL lexer treats single quote strings as a separate class to double quote strings.. -
  • -
  • - Scintilla made compatible with expectations of container widget in GTK+ 2.3. -
  • -
  • - Fix to strip out pixmap ID when automatically choosing from an autocompletion - list with only one element. -
  • -
  • - SciTE bug fixed where UTF-8 files longer than 128K were gaining more than one - BOM. -
  • -
  • - Crashing bug fixed in SciTE on GTK+ where using "Stop Executing" twice leads - to all applications exiting. -
  • -
  • - Bug fixed in autocompletion scrolling on GTK+ 2 with a case sensitive list. - The ListBox::Sort method is no longer needed or available so platform - maintainers should remove it. -
  • -
  • - SciTE check.if.already.open setting removed from GTK+ version as unmaintained. -
  • -
-

- Release 1.55 -

-
    -
  • - Released on 25 September 2003. -
  • -
  • - Fix a crashing bug in indicator display in Scintilla. -
  • -
  • - GTK+ version now defaults to building for GTK+ 2 rather than 1. -
  • -
  • - Mingw make file detects compiler version and avoids options - that are cause problems for some versions. -
  • -
  • - Large performance improvement on GTK+ 2 for long lines. -
  • -
  • - Incremental line wrap on GTK+. -
  • -
  • - International text entry works much better on GTK+ with particular - improvements for Baltic languages and languages that use 'dead' accents. - NUL key events such as those generated by some function keys, ignored. -
  • -
  • - Unicode clipboard support on GTK+. -
  • -
  • - Indicator type INDIC_BOX draws a rectangle around the text. -
  • -
  • - Clarion language support. -
  • -
  • - YAML language support. -
  • -
  • - MPT LOG language support. -
  • -
  • - On Windows, SciTE can switch buffers based on activation order rather - than buffer number. -
  • -
  • - SciTE save.on.deactivate saves all buffers rather than just the current buffer. -
  • -
  • - Lua lexer handles non-ASCII characters correctly. -
  • -
  • - Error lexer understands Borland errors with pathnames that contain space. -
  • -
  • - On GTK+ 2, autocompletion uses TreeView rather than deprecated CList. -
  • -
  • - SciTE autocompletion removed when expand abbreviation command used. -
  • -
  • - SciTE calltips support overloaded functions. -
  • -
  • - When Save fails in SciTE, choice offered to Save As. -
  • -
  • - SciTE message boxes on Windows may be moved to front when needed. -
  • -
  • - Indicators drawn correctly on wrapped lines. -
  • -
  • - Regular expression search no longer matches characters with high bit - set to characters without high bit set. -
  • -
  • - Hang fixed in backwards search in multi byte character documents. -
  • -
  • - Hang fixed in SciTE Mark All command when wrap around turned off. -
  • -
  • - SciTE Incremental Search no longer uses hot keys on Windows. -
  • -
  • - Calltips draw non-ASCII characters correctly rather than as arrows. -
  • -
  • - SciTE crash fixed when going to an error message with empty file name. -
  • -
  • - Bugs fixed in XPM image handling code. -
  • -
-

- Release 1.54 -

-
    -
  • - Released on 12 August 2003. -
  • -
  • - SciTE on GTK+ 2.x can display a tab bar. -
  • -
  • - SciTE on Windows provides incremental search. -
  • -
  • - Lexer for PostScript. -
  • -
  • - Lexer for the NSIS scripting language. -
  • -
  • - New lexer for POV-Ray Scene Description Language - replaces previous implementation. -
  • -
  • - Lexer for the MMIX Assembler language. -
  • -
  • - Lexer for the Scriptol language. -
  • -
  • - Incompatibility: SQL keywords are specified in lower case rather than upper case. - SQL lexer allows double quoted strings. -
  • -
  • - Pascal lexer: character constants that start with '#' understood, - '@' only allowed within assembler blocks, - '$' can be the start of a number, - initial '.' in 0..constant not treated as part of a number, - and assembler blocks made more distinctive. -
  • -
  • - Lua lexer allows '.' in keywords. - Multi-line strings and comments can be folded. -
  • -
  • - CSS lexer handles multiple psuedoclasses. -
  • -
  • - Properties file folder works for INI file format. -
  • -
  • - Hidden indicator style allows the container to mark text within Scintilla - without there being any visual effect. -
  • -
  • - SciTE does not prompt to save changes when the buffer is empty and untitled. -
  • -
  • - Modification notifications caused by SCI_INSERTSTYLEDSTRING - now include the contents of the insertion. -
  • -
  • - SCI_MARKERDELETEALL deletes all the markers on a line - rather than just the first match. -
  • -
  • - Better handling of 'dead' accents on GTK+ 2 for languages - that use accented characters. -
  • -
  • - SciTE now uses value of output.vertical.size property. -
  • -
  • - Crash fixed in SciTE autocompletion on long lines. -
  • -
  • - Crash fixed in SciTE comment command on long lines. -
  • -
  • - Bug fixed with backwards regular expression search skipping - every second match. -
  • -
  • - Hang fixed with regular expression replace where both target and replacement were empty. -
  • -
-

- Release 1.53 -

-
    -
  • - Released on 16 May 2003. -
  • -
  • - On GTK+ 2, encodings other than ASCII, Latin1, and Unicode are - supported for both display and input using iconv. -
  • -
  • - External lexers supported on GTK+/Linux. - External lexers must now be explicitly loaded with SCI_LOADLEXERLIBRARY - rather than relying upon a naming convention and automatic loading. -
  • -
  • - Support of Lout typesetting language. -
  • -
  • - Support of E-Scripts language used in the POL Ultima Online Emulator. -
  • -
  • - Scrolling and drawing performance on GTK+ enhanced, particularly for GTK+ 2.x - with an extra window for the text area avoiding conflicts with the scroll bars. -
  • -
  • - CopyText and CopyRange methods in Scintilla allow container to - easily copy to the system clipboard. -
  • -
  • - Line Copy command implemented and bound to Ctrl+Shift+T. -
  • -
  • - Scintilla APIs PositionBefore and PositionAfter can be used to iterate through - a document taking into account the encoding and multi-byte characters. -
  • -
  • - C++ folder can fold on the "} else {" line of an if statement by setting - fold.at.else property to 1. -
  • -
  • - C++ lexer allows an extra set of keywords. -
  • -
  • - Property names and thus abbreviations may be non-ASCII. -
  • -
  • - Removed attempt to load a file when setting properties that was - part of an old scripting experiment. -
  • -
  • - SciTE no longer warns about a file not existing when opening - properties files from the Options menu as there is a good chance - the user wants to create one. -
  • -
  • - Bug fixed with brace recognition in multi-byte encoded files where a partial - character matched a brace byte. -
  • -
  • - More protection against infinite loops or recursion with recursive property definitions. -
  • -
  • - On Windows, cursor will no longer disappear over margins in custom builds when - cursor resource not present. The Windows default cursor is displayed instead. -
  • -
  • - load.on.activate fixed in SciTE as was broken in 1.52. -
  • -
-

- Release 1.52 -

-
    -
  • - Released on 17 April 2003. -
  • -
  • - Pango font support on GTK+ 2. - Unicode input improved on GTK+ 2. -
  • -
  • - Hotspot style implemented in Scintilla. -
  • -
  • - Small up and down arrows can be displayed in calltips and the container - is notified when the mouse is clicked on a calltip. - Normal and selected calltip text colours can be set. -
  • -
  • - POSIX compatibility flag in Scintilla regular expression search - interprets bare ( and ) as tagged sections. -
  • -
  • - Error message lexer tightened to yield fewer false matches. - Recognition of Lahey and Intel FORTRAN error formats. -
  • -
  • - Scintilla keyboard commands for moving to start and end of - screen lines rather than document lines, unless already there - where these keys move to the start or end of the document line. -
  • -
  • - Line joining command. -
  • -
  • - Lexer for POV-Ray. -
  • -
  • - Calltips on Windows are no longer clipped by the parent window. -
  • -
  • - Autocompletion lists are cancelled when focus leaves their parent window. -
  • -
  • - Move to next/previous empty line delimited paragraph key commands. -
  • -
  • - SciTE hang fixed with recursive property definitions by placing limit - on number of substitutions performed. -
  • -
  • - SciTE Export as PDF reenabled and works. -
  • -
  • - Added loadsession: command line command to SciTE. -
  • -
  • - SciTE option to quit application when last document closed. -
  • -
  • - SciTE option to ask user if it is OK to reload a file that has been - modified outside SciTE. -
  • -
  • - SciTE option to automatically save before running particular command tools - or to ask user or to not save. -
  • -
  • - SciTE on Windows 9x will write a Ctrl+Z to the process input pipe before - closing the pipe when running tool commands that take input. -
  • -
  • - Added a manifest resource to SciTE on Windows to enable Windows XP - themed UI. -
  • -
  • - SciTE calltips handle nested calls and other situations better. -
  • -
  • - CSS lexer improved. -
  • -
  • - Interface to platform layer changed - Surface initialisation now requires - a WindowID parameter. -
  • -
  • - Bug fixed with drawing or measuring long pieces of text on Windows 9x - by truncating the pieces. -
  • -
  • - Bug fixed with SciTE on GTK+ where a user shortcut for a visible character - inserted the character as well as executing the command. -
  • -
  • - Bug fixed where primary selection on GTK+ was reset by - Scintilla during creation. -
  • -
  • - Bug fixed where SciTE would close immediately on startup - when using save.session. -
  • -
  • - Crash fixed when entering '\' in LaTeX file. -
  • -
  • - Hang fixed when '#' last character in VB file. -
  • -
  • - Crash fixed in error message lexer. -
  • -
  • - Crash fixed when searching for long regular expressions. -
  • -
  • - Pressing return when nothing selected in user list sends notification with - empty text rather than random text. -
  • -
  • - Mouse debouncing disabled on Windows as it interfered with some - mouse utilities. -
  • -
  • - Bug fixed where overstrike mode inserted before rather than replaced last - character in document. -
  • -
  • - Bug fixed with syntax highlighting of Japanese text. -
  • -
  • - Bug fixed in split lines function. -
  • -
  • - Cosmetic fix to SciTE tab bar on Windows when window resized. - Focus sticks to either pane more consistently. -
  • -
-

- Release 1.51 -

-
    -
  • - Released on 16 February 2003. -
  • -
  • - Two phase drawing avoids cutting off text that overlaps runs by drawing - all the backgrounds of a line then drawing all the text transparently. - Single phase drawing is an option. -
  • -
  • - Scintilla method to split lines at a particular width by adding new line - characters. -
  • -
  • - The character used in autocompletion lists to separate the text from the image - number can be changed. -
  • -
  • - The scrollbar range will automatically expand when the caret is moved - beyond the current range. - The scroll bar is updated when SCI_SETXOFFSET is called. -
  • -
  • - Mouse cursors on GTK+ improved to be consistent with other applications - and the Windows version. -
  • -
  • - Horizontal scrollbar on GTK+ now disappears in wrapped mode. -
  • -
  • - Scintilla on GTK+ 2: mouse wheel scrolling, cursor over scrollbars, focus, - and syntax highlighting now work. - gtk_selection_notify avoided for compatibility with GTK+ 2.2. -
  • -
  • - Fold margin colours can now be set. -
  • -
  • - SciTE can be built for GTK+ 2. -
  • -
  • - SciTE can optionally preserve the undo history over an automatic file reload. -
  • -
  • - Tags can optionally be case insensitive in XML and HTML. -
  • -
  • - SciTE on Windows handles input to tool commands in a way that should avoid - deadlock. Output from tools can be used to replace the selection. -
  • -
  • - SciTE on GTK+ automatically substitutes '|' for '/' in menu items as '/' - is used to define the menu hierarchy. -
  • -
  • - Optional buffer number in SciTE title bar. -
  • -
  • - Crash fixed in SciTE brace matching. -
  • -
  • - Bug fixed where automatic scrolling past end of document - flipped back to the beginning. -
  • -
  • - Bug fixed where wrapping caused text to disappear. -
  • -
  • - Bug fixed on Windows where images in autocompletion lists were - shown on the wrong item. -
  • -
  • - Crash fixed due to memory bug in autocompletion lists on Windows. -
  • -
  • - Crash fixed when double clicking some error messages. -
  • -
  • - Bug fixed in word part movement where sometimes no movement would occur. -
  • -
  • - Bug fixed on Windows NT where long text runs were truncated by - treating NT differently to 9x where there is a limitation. -
  • -
  • - Text in not-changeable style works better but there remain some cases where - it is still possible to delete text protected this way. -
  • -
-

- Release 1.50 -

-
    -
  • - Released on 24 January 2003. -
  • -
  • - Autocompletion lists may have a per-item pixmap. -
  • -
  • - Autocompletion lists allow Unicode text on Windows. -
  • -
  • - Scintilla documentation rewritten. -
  • -
  • - Additional DBCS encoding support in Scintilla on GTK+ primarily aimed at - Japanese EUC encoding. -
  • -
  • - CSS (Cascading Style Sheets) lexer added. -
  • -
  • - diff lexer understands some more formats. -
  • -
  • - Fold box feature is an alternative way to show the structure of code. -
  • -
  • - Avenue lexer supports multiple keyword lists. -
  • -
  • - The caret may now be made invisible by setting the caret width to 0. -
  • -
  • - Python folder attaches comments before blocks to the next block rather - than the previous block. -
  • -
  • - SciTE openpath property on Windows searches a path for files that are - the subject of the Open Selected Filename command. -
  • -
  • - The localisation file name can be changed with the locale.properties property. -
  • -
  • - On Windows, SciTE can pipe the result of a string expression into a command line tool. -
  • -
  • - On Windows, SciTE's Find dialog has a Mark All button. -
  • -
  • - On Windows, there is an Insert Abbreviation command that allows a choice from - the defined abbreviations and inserts the selection into the abbreviation at the - position of a '|'. -
  • -
  • - Minor fixes to Fortran lexer. -
  • -
  • - fold.html.preprocessor decides whether to fold <? and ?>. - Minor improvements to PHP folding. -
  • -
  • - Maximum number of keyword lists allowed increased from 6 to 9. -
  • -
  • - Duplicate line command added with default assignment to Ctrl+D. -
  • -
  • - SciTE sets $(Replacements) to the number of replacements made by the - Replace All command. $(CurrentWord) is set to the word before the caret if the caret - is at the end of a word. -
  • -
  • - Opening a SciTE session now loads files in remembered order, sets the current file - as remembered, and moves the caret to the remembered line. -
  • -
  • - Bugs fixed with printing on Windows where line wrapping was causing some text - to not print. -
  • -
  • - Bug fixed with Korean Input Method Editor on Windows. -
  • -
  • - Bugs fixed with line wrap which would sometimes choose different break positions - after switching focus away and back. -
  • -
  • - Bug fixed where wheel scrolling had no effect on GTK+ after opening a fold. -
  • -
  • - Bug fixed with file paths containing non-ASCII characters on Windows. -
  • -
  • - Crash fixed with printing on Windows after defining pixmap marker. -
  • -
  • - Crash fixed in makefile lexer when first character on line was '='. -
  • -
  • - Bug fixed where local properties were not always being applied. -
  • -
  • - Ctrl+Keypad* fold command works on GTK+. -
  • -
  • - Hangs fixed in SciTE's Replace All command when replacing regular expressions '^' - or '$'. -
  • -
  • - SciTE monospace setting behaves more sensibly. -
  • -
-

- Release 1.49 -

-
    -
  • - Released on 1 November 2002. -
  • -
  • - Unicode supported on GTK+. To perform well, this added a font cache to GTK+ - and to make that safe, a mutex is used. The mutex requires the application to link in - the threading library by evaluating `glib-config --libs gthread`. A Unicode locale - should also be set up by a call like setlocale(LC_CTYPE, "en_US.UTF-8"). - scintilla_release_resources function added to release mutex. -
  • -
  • - FORTRAN and assembler lexers added along with other support for these - languages in SciTE. -
  • -
  • - Ada lexer improved handling of based numbers, identifier validity and attributes - distinguished from character literals. -
  • -
  • - Lua lexer handles block comments and a deep level of nesting for literal strings - and block comments. -
  • -
  • - Errorlist lexer recognises PHP error messages. -
  • -
  • - Variant of the C++ lexer with case insensitive keywords - called cppnocase. Whitespace in preprocessor text handled more correctly. -
  • -
  • - Folder added for Perl. -
  • -
  • - Compilation with GCC 3.2 supported. -
  • -
  • - Markers can be pixmaps. -
  • -
  • - Lines are wrapped when printing. - Bug fixed which printed line numbers in different styles. -
  • -
  • - Text can be appended to end with AppendText method. -
  • -
  • - ChooseCaretX method added. -
  • -
  • - Vertical scroll bar can be turned off with SetVScrollBar method. -
  • -
  • - SciTE Save All command saves all buffers. -
  • -
  • - SciTE localisation compares keys case insensitively to make translations more flexible. -
  • -
  • - SciTE detects a utf-8 coding cookie "coding: utf-8" in first two - lines and goes into Unicode mode. -
  • -
  • - SciTE key bindings are definable. -
  • -
  • - SciTE Find in Files dialog can display directory browser to - choose directory to search. -
  • -
  • - SciTE enabling of undo and redo toolbar buttons improved. -
  • -
  • - SciTE on Windows file type filters in open dialog sorted. -
  • -
  • - Fixed crashing bug when using automatic tag closing in XML or HTML. -
  • -
  • - Fixed bug on Windows causing very long (>64K) lines to not display. -
  • -
  • - Fixed bug in backwards regular expression searching. -
  • -
  • - Fixed bug in calltips where wrong argument was highlighted. -
  • -
  • - Fixed bug in tab timmy feature when file has line feed line endings. -
  • -
  • - Fixed bug in compiling without INCLUDE_DEPRECATED_FEATURES - defined. -
  • -
-

- Release 1.48 -

-
    -
  • - Released on 9 September 2002. -
  • -
  • - Improved Pascal lexer with context sensitive keywords - and separate folder which handles //{ and //} folding comments and - {$region} and {$end} folding directives. - The "case" statement now folds correctly. -
  • -
  • - C++ lexer correctly handles comments on preprocessor lines. -
  • -
  • - New commands for moving to beginning and end of display lines when in line - wrap mode. Key bindings added for these commands. -
  • -
  • - New marker symbols that look like ">>>" and "..." which can be used for - interactive shell prompts for Python. -
  • -
  • - The foreground and background colours of visible whitespace can be chosen - independent of the colours chosen for the lexical class of that whitespace. -
  • -
  • - Per line data optimised by using an exponential allocation scheme. -
  • -
  • - SciTE API file loading optimised. -
  • -
  • - SciTE for GTK+ subsystem 2 documented. The exit status of commands - is decoded into more understandable fields. -
  • -
  • - SciTE find dialog remembers previous find string when there is no selection. - Find in Selection button disabled when selection is rectangular as command - did not work. -
  • -
  • - Shift+Enter made equivalent to Enter to avoid users having to let go of - the shift key when typing. Avoids the possibility of entering single carriage - returns in a file that contains CR+LF line ends. -
  • -
  • - Autocompletion does not immediately disappear when the length parameter - to SCI_AUTOCSHOW is 0. -
  • -
  • - SciTE focuses on the editor pane when File | New executed and when the - output pane is closed with F8. Double clicking on a non-highlighted output - pane line selects the word under the cursor rather than seeking the next - highlighted line. -
  • -
  • - SciTE director interface implements an "askproperty" command. -
  • -
  • - SciTE's Export as LaTeX output improved. -
  • -
  • - Better choice of autocompletion displaying above the caret rather then - below when that is more sensible. -
  • -
  • - Bug fixed where context menu would not be completely visible if invoked - when cursor near bottom or left of screen. -
  • -
  • - Crashing bug fixed when displaying long strings on GTK+ caused failure of X server - by displaying long text in segments. -
  • -
  • - Crashing bug fixed on GTK+ when a Scintilla window was removed from its parent - but was still the selection owner. -
  • -
  • - Bug fixed on Windows in Unicode mode where not all characters on a line - were displayed when that line contained some characters not in ASCII. -
  • -
  • - Crashing bug fixed in SciTE on Windows with clearing output while running command. -
  • -
  • - Bug fixed in SciTE for GTK+ with command completion not detected when - no output was produced by the command. -
  • -
  • - Bug fixed in SciTE for Windows where menus were not shown translated. -
  • -
  • - Bug fixed where words failed to display in line wrapping mode with visible - line ends. -
  • -
  • - Bug fixed in SciTE where files opened from a session file were not closed. -
  • -
  • - Cosmetic flicker fixed when using Ctrl+Up and Ctrl+Down with some caret policies. -
  • -
-

- Release 1.47 -

-
    -
  • - Released on 1 August 2002. -
  • -
  • - Support for GTK+ 2 in Scintilla. International input methods not supported - on GTK+2. -
  • -
  • - Line wrapping performance improved greatly. -
  • -
  • - New caret policy implementation that treats horizontal and vertical - positioning equivalently and independently. Old caret policy methods - deprecated and not all options work correctly with old methods. -
  • -
  • - Extra fold points for C, C++, Java, ... for fold comments //{ .. //} and - #if / #ifdef .. #endif and the #region .. #endregion feature of C#. -
  • -
  • - Scintilla method to find the height in pixels of a line. Currently returns the - same result for every line as all lines are same height. -
  • -
  • - Separate make file, scintilla_vc6.mak, for Scintilla to use Visual C++ - version 6 since main makefile now assumes VS .NET. - VS .NET project files available for combined Scintilla and - SciTE in scite/boundscheck. -
  • -
  • - SciTE automatically recognises Unicode files based - on their Byte Order Marks and switches to Unicode mode. - On Windows, where SciTE supports Unicode display, this - allows display of non European characters. - The file is saved back into the same character encoding unless - the user decides to switch using the File | Encoding menu. -
  • -
  • - Handling of character input changed so that a fillup character, typically '(' - displays a calltip when an autocompletion list was being displayed. -
  • -
  • - Multiline strings lexed better for C++ and Lua. -
  • -
  • - Regular expressions in JavaScript within hypertext files are lexed better. -
  • -
  • - On Windows, Scintilla exports a function called Scintilla_DirectFunction - that can be used the same as the function returned by GetDirectFunction. -
  • -
  • - Scintilla converts line endings of text obtained from the clipboard to - the current default line endings. -
  • -
  • - New SciTE property ensure.final.line.end can ensure that saved files - always end with a new line as this is required by some tools. - The ensure.consistent.line.ends property ensures all line ends are the - current default when saving files. - The strip.trailing.spaces property now works on the buffer so the - buffer in memory and the file on disk are the same after a save is performed. -
  • -
  • - The SciTE expand abbreviation command again allows '|' characters - in expansions to be quoted by using '||'. -
  • -
  • - SciTE on Windows can send data to the find tool through standard - input rather than using a command line argument to avoid problems - with quoting command line arguments. -
  • -
  • - The Stop Executing command in SciTE on Windows improved to send - a Ctrl+Z character to the tool. Better messages when stopping a tool. -
  • -
  • - Autocompletion can automatically "fill up" when one of a set of characters is - type with the autocomplete.<lexer>.fillups property. -
  • -
  • - New predefined properties in SciTE, SelectionStartColumn, SelectionStartLine, - SelectionEndColumn, SelectionEndLine can be used to integrate with other - applications. -
  • -
  • - Environment variables are available as properties in SciTE. -
  • -
  • - SciTE on Windows keeps status line more current. -
  • -
  • - Abbreviations work in SciTE on Linux when first opened. -
  • -
  • - File saving fixed in SciTE to ensure files are not closed when they can not be - saved because of file permissions. Also fixed a problem with buffers that - caused files to not be saved. -
  • -
  • - SciTE bug fixed where monospace mode not remembered when saving files. - Some searching options now remembered when switching files. -
  • -
  • - SciTE on Linux now waits on child termination when it shuts a child down - to avoid zombies. -
  • -
  • - SciTE on Linux has a Print menu command that defaults to invoking a2ps. -
  • -
  • - Fixed incorrect highlighting of indentation guides in SciTE for Python. -
  • -
  • - Crash fixed in Scintilla when calling GetText for 0 characters. -
  • -
  • - Exporting as LaTeX improved when processing backslashes and tabs - and setting up font. -
  • -
  • - Crash fixed in SciTE when exporting or copying as RTF. -
  • -
  • - SciTE session loading fixed to handle more than 10 files in session. -
  • -
-

- Release 1.46 -

-
    -
  • - Released on 10 May 2002. -
  • -
  • - Set of lexers compiled into Scintilla can now be changed by adding and - removing lexer source files from scintilla/src and running LexGen.py. -
  • -
  • - SCN_ZOOM notification provided by Scintilla when user changes zoom level. - Method to determine width of strings in pixels so that elements can be sized - relative to text size. - SciTE changed to keep line number column displaying a given - number of characters. -
  • -
  • - The logical width of the document used to determine scroll bar range can be set. -
  • -
  • - Setting to allow vertical scrolling to display last line at top rather than - bottom of window. -
  • -
  • - Read-only mode improved to avoid changing the selection in most cases - when a modification is attempted. Drag and drop cursors display correctly - for read-only in some cases. -
  • -
  • - Visual C++ options in make files changed to suit Visual Studio .NET. -
  • -
  • - Scintilla.iface includes feature types for enumerations and lexers. -
  • -
  • - Lua lexer improves handling of literal strings and copes with nested literal strings. -
  • -
  • - Diff lexer changed to treat lines starting with "***" similarly to "---". - Symbolic names defined for lexical classes. -
  • -
  • - nncrontab lexer improved. -
  • -
  • - Turkish fonts (iso8859-9) supported on GTK+. -
  • -
  • - Automatic close tag feature for XML and HTML in SciTE. -
  • -
  • - Automatic indentation in SciTE improved. -
  • -
  • - Maximum number of buffers available in SciTE increased. May be up to 100 - although other restrictions on menu length limit the real maximum. -
  • -
  • - Save a Copy command added to SciTE. -
  • -
  • - Export as TeX command added to SciTE. -
  • -
  • - Export as HTML command in SciTE respects Use Monospaced Font and - background colour settings. -
  • -
  • - Compilation problem on Solaris fixed. -
  • -
  • - Order of files displayed for SciTE's previous and next menu and key commands - are now consistent. -
  • -
  • - Saving of MRU in recent file changed so files open when SciTE quit - are remembered. -
  • -
  • - More variants of ctags tags handled by Open Selected Filename in SciTE. -
  • -
  • - JavaScript embedded in XML highlighted again. -
  • -
  • - SciTE status bar updated after changing parameters in case they are being - displayed in status bar. -
  • -
  • - Crash fixed when handling some multi-byte languages. -
  • -
  • - Crash fixed when replacing end of line characters. -
  • -
  • - Bug in SciTE fixed in multiple buffer mode where automatic loading - turned on could lead to losing file contents. -
  • -
  • - Bug in SciTE on GTK+ fixed where dismissing dialogs with close box led to - those dialogs never being shown again. -
  • -
  • - Bug in SciTE on Windows fixed where position.tile with default positions - led to SciTE being positioned off-screen. -
  • -
  • - Bug fixed in read-only mode, clearing all deletes contraction state data - leading to it not being synchronized with text. -
  • -
  • - Crash fixed in SciTE on Windows when tab bar displayed. -
  • -
-

- Release 1.45 -

-
    -
  • - Released on 15 March 2002. -
  • -
  • - Line layout cache implemented to improve performance by maintaining - the positioning of characters on lines. Can be set to cache nothing, - the line with the caret, the visible page or the whole document. -
  • -
  • - Support, including a new lexer, added for Matlab programs. -
  • -
  • - Lua folder supports folding {} ranges and compact mode. - Lua lexer styles floating point numbers in number style instead of - setting the '.' in operator style. - Up to 6 sets of keywords. - Better support for [[ although only works well - when all on one line. -
  • -
  • - Python lexer improved to handle floating point numbers that contain negative - exponents and that start with '.'. -
  • -
  • - When performing a rectangular paste, the caret now remains at the - insertion point. -
  • -
  • - On Windows with a wheel mouse, page-at-a-time mode is recognised. -
  • -
  • - Read-only mode added to SciTE with a property to initialise it and another property, - $(ReadOnly) available to show this mode in the status bar. -
  • -
  • - SciTE status bar can show the number of lines in the selection - with the $(SelHeight) property. -
  • -
  • - SciTE's "Export as HTML" command uses the current character set to produce - correct output for non-Western-European character sets, such as Russian. -
  • -
  • - SciTE's "Export as RTF" fixed to produce correct output when file contains '\'. -
  • -
  • - SciTE goto command accepts a column as well as a line. - If given a column, it selects the word at that column. -
  • -
  • - SciTE's Build, Compile and Go commands are now disabled if no - action has been assigned to them. -
  • -
  • - The Refresh button in the status bar has been removed from SciTE on Windows. -
  • -
  • - Bug fixed in line wrap mode where cursor up or down command did not work. -
  • -
  • - Some styling bugs fixed that were due to a compilation problem with - gcc and inline functions with same name but different code. -
  • -
  • - The way that lexers loop over text was changed to avoid accessing beyond the - end or setting beyond the end. May fix some bugs and make the code safer but - may also cause new bugs. -
  • -
  • - Bug fixed in HTML lexer's handling of SGML. -
  • -
  • - Bug fixed on GTK+/X where lines wider than 32767 pixels did not display. -
  • -
  • - SciTE bug fixed with file name generation for standard property files. -
  • -
  • - SciTE bug fixed with Open Selected Filename command when used with - file name and line number combination. -
  • -
  • - In SciTE, indentation and tab settings stored with buffers so maintained correctly - as buffers selected. - The properties used to initialise these settings can now be set separately for different - file patterns. -
  • -
  • - Thread safety improved on Windows with a critical section protecting the font - cache and initialisation of globals performed within Scintilla_RegisterClasses. - New Scintilla_ReleaseResources call provided to allow explicit freeing of resources - when statically bound into another application. Resources automatically freed - in DLL version. The window classes are now unregistered as part of resource - freeing which fixes bugs that occurred in some containers such as Internet Explorer. -
  • -
  • - 'make install' fixed on Solaris. -
  • -
  • - Bug fixed that could lead to a file being opened twice in SciTE. -
  • -
-

- Release 1.44 -

-
    -
  • - Released on 4 February 2002. -
  • -
  • - Crashing bug fixed in Editor::Paint. -
  • -
  • - Lua lexer no longer treats '.' as a word character and - handles 6 keyword sets. -
  • -
  • - WordStartPosition and WordEndPosition take an onlyWordCharacters - argument. -
  • -
  • - SciTE option for simplified automatic indentation which repeats - the indentation of the previous line. -
  • -
  • - Compilation fix on Alpha because of 64 bit. -
  • -
  • - Compilation fix for static linking. -
  • -
  • - Limited maximum line length handled to 8000 characters as previous - value of 16000 was causing stack exhaustion crashes for some. -
  • -
  • - When whole document line selected, only the last display line gets - the extra selected rectangle at the right hand side rather than - every display line. -
  • -
  • - Caret disappearing bug fixed for the case that the caret was not on the - first display line of a document line. -
  • -
  • - SciTE bug fixed where untitled buffer containing text was sometimes - deleted without chance to save. -
  • -
  • - SciTE bug fixed where use.monospaced not working with - multiple buffers. -
  • -
-

- Release 1.43 -

-
    -
  • - Released on 19 January 2002. -
  • -
  • - Line wrapping robustness and performance improved in Scintilla. -
  • -
  • - Line wrapping option added to SciTE for both edit and output panes. -
  • -
  • - Static linking on Windows handles cursor resource better. - Documentation of static linking improved. -
  • -
  • - Autocompletion has an option to delete any word characters after the caret - upon selecting an item. -
  • -
  • - FOX version identified by PLAT_FOX in Platform.h. -
  • -
  • - Calltips in SciTE use the calltip.<lexer>.word.characters setting to - correctly find calltips for functions that include characters like '$' which - is not normally considered a word character. -
  • -
  • - SciTE has a command to show help on itself which gets hooked up to displaying - SciTEDoc.html. -
  • -
  • - SciTE option calltip.<lexer>.end.definition to display help text on a - second line of calltip. -
  • -
  • - Fixed the handling of the Buffers menu on GTK+ to ensure current buffer - indicated and no warnings occur. - Changed some menu items on GTK+ version to be same as Windows version. -
  • -
  • - use.monospaced property for SciTE determines initial state of Use Monospaced Font - setting. -
  • -
  • - The SciTE Complete Symbol command now works when there are no word - characters before the caret, even though it is slow to display the whole set of - symbols. -
  • -
  • - Function names removed from SciTE's list of PHP keywords. The full list of - predefined functions is available from another web site mentioned on the - Extras page. -
  • -
  • - Crashing bug at startup on GTK+ for some configurations fixed. -
  • -
  • - Crashing bug on GTK+ on 64 bit platforms fixed. -
  • -
  • - Compilation problem with some compilers fixed in GTK+. -
  • -
  • - Japanese text entry improved on Windows 9x. -
  • -
  • - SciTE recent files directory problem on Windows when HOME and SciTE_HOME - environment variables not set is now the directory of the executable. -
  • -
  • - Session files no longer include untitled buffers. -
  • -
-

- Release 1.42 -

-
    -
  • - Released on 24 December 2001. -
  • -
  • - Better localisation support including context menus and most messages. - Translations of the SciTE user interface available for Bulgarian, - French, German, Italian, Russian, and Turkish. -
  • -
  • - Can specify a character to use to indicate control characters - rather than having them displayed as mnemonics. -
  • -
  • - Scintilla key command for backspace that will not delete line - end characters. -
  • -
  • - Scintilla method to find start and end of words. -
  • -
  • - SciTE on GTK+ now supports the load.on.activate and save.on.deactivate - properties in an equivalent way to the Windows version. -
  • -
  • - The output pane of SciTE on Windows is now interactive so command line - utilities that prompt for input or confirmation can be used. -
  • -
  • - SciTE on Windows can choose directory for a "Find in Files" - command like the GTK+ version could. -
  • -
  • - SciTE can now load a set of API files rather than just one file. -
  • -
  • - ElapsedTime class added to Platform for accurate measurement of durations. - Used for debugging and for showing the user how long commands take in SciTE. -
  • -
  • - Baan lexer added. -
  • -
  • - In C++ lexer, document comment keywords no longer have to be at the start - of the line. -
  • -
  • - PHP lexer changed to match keywords case insensitively. -
  • -
  • - More shell keywords added. -
  • -
  • - SciTE support for VoiceXML added to xml.properties. -
  • -
  • - In SciTE the selection is not copied to the find field of the Search and Replace - dialogs if it contains end of line characters. -
  • -
  • - SciTE on Windows has a menu item to decide whether to respond to other - instances which are performing their check.if.already.open check. -
  • -
  • - SciTE accelerator key for Box Comment command changed to avoid problems - in non-English locales. -
  • -
  • - SciTE context menu includes Close command for the editor pane and - Hide command for the output pane. -
  • -
  • - output: command added to SciTE director interface to add text to the - output pane. The director interface can execute commands (such as tool - commands with subsystem set to 3) by sending a macro:run message. -
  • -
  • - SciTE on GTK+ will defer to the Window Manager for position if position.left or - position.top not set and for size if position.width or position.height not set. -
  • -
  • - SciTE on Windows has a position.tile property to place a second instance - to the right of the first. -
  • -
  • - Scintilla on Windows again supports EM_GETSEL and EM_SETSEL. -
  • -
  • - Problem fixed in Scintilla on Windows where control ID is no longer cached - as it could be changed by external code. -
  • -
  • - Problems fixed in SciTE on Windows when finding any other open instances at - start up when check.if.already.open is true. -
  • -
  • - Bugs fixed in SciTE where command strings were not always having - variables evaluated. -
  • -
  • - Bugs fixed with displaying partial double-byte and Unicode characters - in rectangular selections and at the edge when edge mode is EDGE_BACKGROUND. - Column numbers reported by GetColumn treat multiple byte characters as one column - rather than counting bytes. -
  • -
  • - Bug fixed with caret movement over folded lines. -
  • -
  • - Another bug fixed with tracking selection in secondary views when performing - modifications. -
  • -
  • - Horizontal scrolling and display of long lines optimised. -
  • -
  • - Cursor setting in Scintilla on GTK+ optimised. -
  • -
  • - Experimental changeable style attribute. - Set to false to make text read-only. - Currently only stops caret from being within not-changeable - text and does not yet stop deleting a range that contains - not-changeable text. - Can be used from SciTE by adding notchangeable to style entries. -
  • -
  • - Experimental line wrapping. - Currently has performance and appearence problems. -
  • -
-

- Release 1.41 -

-
    -
  • - Released on 6 November 2001. -
  • -
  • - Changed Platform.h to not include platform headers. This lessens likelihood and impact of - name clashes from system headers and also speeds up compilation. - Renamed DrawText to DrawTextNoClip to avoid name clash. -
  • -
  • - Changed way word functions work to treat a sequence of punctuation as - a word. This is more sensible and also more compatible with other editors. -
  • -
  • - Cursor changes over the margins and selection on GTK+ platform. -
  • -
  • - SC_MARK_BACKGROUND is a marker that only changes the line's background colour. -
  • -
  • - Enhanced Visual Basic lexer handles character date and octal literals, - and bracketed keywords for VB.NET. There are two VB lexers, vb and vbscript - with type indication characters like ! and $ allowed at the end of identifiers - in vb but not vbscript. Lexer states now separate from those used for C++ and - names start with SCE_B. -
  • -
  • - Lexer added for Bullant language. -
  • -
  • - The horizontal scroll position, xOffset, is now exposed through the API. -
  • -
  • - The SCN_POSCHANGED notification is deprecated as it was causing confusion. - Use SCN_UPDATEUI instead. -
  • -
  • - Compilation problems fixed for some versions of gcc. -
  • -
  • - Support for WM_GETTEXT restored on Windows. -
  • -
  • - Double clicking on an autocompletion list entry works on GTK+. -
  • -
  • - Bug fixed with case insensitive sorts for autocompletion lists. -
  • -
  • - Bug fixed with tracking selection in secondary views when performing modifications. -
  • -
  • - SciTE's abbreviation expansion feature will now indent expansions to the current - indentation level if indent.automatic is on. -
  • -
  • - SciTE allows setting up of parameters to commands from a dialog and can also - show this dialog automatically to prompt for arguments when running a command. -
  • -
  • - SciTE's Language menu (formerly Options | Use Lexer) is now defined by the - menu.language property rather than being hardcoded. -
  • -
  • - The user interface of SciTE can be localised to a particular language by editing - a locale.properties file. -
  • -
  • - On Windows, SciTE will try to move to the front when opening a new file from - the shell and using check.if.already.open. -
  • -
  • - SciTE can display the file name and directory in the title bar in the form - "file @ directory" when title.full.path=2. -
  • -
  • - The SciTE time.commands property reports the time taken by a command as well - as its status when completed. -
  • -
  • - The SciTE find.files property is now a list separated by '|' characters and this list is - added into the Files pull down of the Find in Files dialog. -
  • -
-

- Release 1.40 -

-
    -
  • - Released on 23 September 2001. -
  • -
  • - Removal of emulation of Win32 RichEdit control in core of Scintilla. - This change may be incompatible with existing client code. - Some emulation still done in Windows platform layer. -
  • -
  • - SGML support in the HTML/XML lexer. -
  • -
  • - SciTE's "Stop Executing" command will terminate GUI programs on - Windows NT and Windows 2000. -
  • -
  • - StyleContext class helps construct lexers that are simple and accurate. - Used in the C++, Eiffel, and Python lexers. -
  • -
  • - Clipboard operations in GTK+ version convert between platform '\n' line endings and - currently chosen line endings. -
  • -
  • - Any character in range 0..255 can be used as a marker. - This can be used to support numbered bookmarks, for example. -
  • -
  • - The default scripting language for ASP can be set. -
  • -
  • - New lexer and other support for crontab files used with the nncron scheduler. -
  • -
  • - Folding of Python improved. -
  • -
  • - The ` character is treated as a Python operator. -
  • -
  • - Line continuations ("\" at end of line) handled inside Python strings. -
  • -
  • - More consistent handling of line continuation ('\' at end of line) in - C++ lexer. - This fixes macro definitions that span more than one line. -
  • -
  • - C++ lexer can understand Doxygen keywords in doc comments. -
  • -
  • - SciTE on Windows allows choosing to open the "open" dialog on the directory - of the current file rather than in the default directory. -
  • -
  • - SciTE on Windows handles command line arguments in "check.if.already.open" - correctly when the current directory of the new instance is different to the - already open instance of SciTE. -
  • -
  • - "cwd" command (change working directory) defined for SciTE director interface. -
  • -
  • - SciTE "Export As HTML" produces better, more compliant, and shorter files. -
  • -
  • - SciTE on Windows allows several options for determining default file name - for exported files. -
  • -
  • - Automatic indentation of Python in SciTE fixed. -
  • -
  • - Exported HTML can support folding. -
  • -
  • - Bug fixed in SCI_GETTEXT macro command of director interface. -
  • -
  • - Cursor leak fixed on GTK+. -
  • -
  • - During SciTE shutdown, "identity" messages are no longer sent over the director interface. -
  • -
-

- Release 1.39 -

-
    -
  • - Released on 22 August 2001. -
  • -
  • - Windows version requires msvcrt.dll to be available so will not work - on original Windows 95 version 1. The msvcrt.dll file is installed - by almost everything including Internet Explorer so should be available. -
  • -
  • - Flattened tree control style folding margin. The SciTE fold.plus option is - now fold.symbols and has more values for the new styles. -
  • -
  • - Mouse dwell events are generated when the user holds the mouse steady - over Scintilla. -
  • -
  • - PositionFromPointClose is like PositionFromPoint but returns - INVALID_POSITION when point outside window or after end of line. -
  • -
  • - Input of Hungarian and Russian characters in GTK+ version works by - truncating input to 8 bits if in the range of normal characters. -
  • -
  • - Better choices for font descriptors on GTK+ for most character sets. -
  • -
  • - GTK+ Scintilla is destroyed upon receiving destroy signal rather than - destroy_event signal. -
  • -
  • - Style setting that force upper or lower case text. -
  • -
  • - Case-insensitive autocompletion lists work correctly. -
  • -
  • - Keywords can be prefix based so ^GTK_ will treat all words that start - with GTK_ as keywords. -
  • -
  • - Horizontal scrolling can be jumpy rather than gradual. -
  • -
  • - GetSelText places a '\0' in the buffer if the selection is empty.. -
  • -
  • - EnsureVisible split into two methods EnsureVisible which will not scroll to show - the line and EnsureVisibleEnforcePolicy which may scroll. -
  • -
  • - Python folder has options to fold multi-line comments and triple quoted strings. -
  • -
  • - C++ lexer handles keywords before '.' like "this.x" in Java as keywords. - Compact folding mode option chooses whether blank lines after a structure are - folded with that structure. Second set of keywords with separate style supported. -
  • -
  • - Ruby lexer handles multi-line comments. -
  • -
  • - VB has folder. -
  • -
  • - PHP lexer has an operator style, handles "<?" and "?>" inside strings - and some comments. -
  • -
  • - TCL lexer which is just an alias for the C++ lexer so does not really - understand TCL syntax. -
  • -
  • - Error lines lexer has styles for Lua error messages and .NET stack traces. -
  • -
  • - Makefile lexer has a target style. -
  • -
  • - Lua lexer handles some [[]] string literals. -
  • -
  • - HTML and XML lexer have a SCE_H_SGML state for tags that - start with "<!". -
  • -
  • - Fixed Scintilla bugs with folding. When modifications were performed near - folded regions sometimes no unfolding occurred when it should have. Deleting a - fold causing character sometimes failed to update fold information correctly. -
  • -
  • - Better support for Scintilla on GTK+ for Win32 including separate - PLAT_GTK_WIN32 definition and correct handling of rectangular selection - with clipboard operations. -
  • -
  • - SciTE has a Tools | Switch Pane (Ctrl+F6) command to switch focus between - edit and output panes. -
  • -
  • - SciTE option output.scroll allows automatic scrolling of output pane to - be turned off. -
  • -
  • - Commands can be typed into the SciTE output pane similar to a shell window. -
  • -
  • - SciTE properties magnification and output magnification set initial zoom levels. -
  • -
  • - Option for SciTE comment block command to place comments at start of line. -
  • -
  • - SciTE for Win32 has an option to minimize to the tray rather than the task bar. -
  • -
  • - Close button on SciTE tool bar for Win32. -
  • -
  • - SciTE compiles with GCC 3.0. -
  • -
  • - SciTE's automatic indentation of C++ handles braces without preceding keyword - correctly. -
  • -
  • - Bug fixed with GetLine method writing past the end of where it should. -
  • -
  • - Bug fixed with mouse drag automatic scrolling when some lines were folded. -
  • -
  • - Bug fixed because caret XEven setting was inverted. -
  • -
  • - Bug fixed where caret was initially visible even though window was not focussed. -
  • -
  • - Bug fixed where some file names could end with "\\" which caused slow - downs on Windows 9x. -
  • -
  • - On Win32, SciTE Replace dialog starts with focus on replacement text. -
  • -
  • - SciTE Go to dialog displays correct current line. -
  • -
  • - Fixed bug with SciTE opening multiple files at once. -
  • -
  • - Fixed bug with Unicode key values reported to container truncated. -
  • -
  • - Fixed bug with unnecessary save point notifications. -
  • -
  • - Fixed bugs with indenting and unindenting at start of line. -
  • -
  • - Monospace Font setting behaves more consistently. -
  • -
-

- Release 1.38 -

-
    -
  • - Released on 23 May 2001. -
  • -
  • - Loadable lexer plugins on Windows. -
  • -
  • - Ruby lexer and support. -
  • -
  • - Lisp lexer and support. -
  • -
  • - Eiffel lexer and support. -
  • -
  • - Modes for better handling of Tab and BackSpace keys within - indentation. Mode to avoid autocompletion list cancelling when - there are no viable matches. -
  • -
  • - ReplaceTarget replaced with two calls ReplaceTarget - (which is incompatible with previous ReplaceTarget) and - ReplaceTargetRE. Both of these calls have a count first - parameter which allows using strings containing nulls. - SearchInTarget and SetSearchFlags functions allow - specifying a search in several simple steps which helps - some clients which can not create structs or pointers easily. -
  • -
  • - Asian language input through an Input Method Editor works - on Windows 2000. -
  • -
  • - On Windows, control characters can be entered through use of - the numeric keypad in conjunction with the Alt key. -
  • -
  • - Document memory allocation changed to grow exponentially - which reduced time to load a 30 Megabyte file from - 1000 seconds to 25. Change means more memory may be used. -
  • -
  • - Word part movement keys now handled in Scintilla rather than - SciTE. -
  • -
  • - Regular expression '^' and '$' work more often allowing insertion - of text at start or end of line with a replace command. - Backslash quoted control characters \a, \b, \f, \t, and \v - recognised within sets. -
  • -
  • - Session files for SciTE. -
  • -
  • - Export as PDF command hidden in SciTE as it often failed. - Code still present so can be turned on by those willing to cope. -
  • -
  • - Bug fixed in HTML lexer handling % before > as end ASP - even when no start ASP encountered. - Bug fixed when scripts ended with a quoted string and - end tag was not seen. -
  • -
  • - Bug fixed on Windows where context menu key caused menu to - appear in corner of screen rather than within window. -
  • -
  • - Bug fixed in SciTE's Replace All command not processing - whole file when replace string longer than search string. -
  • -
  • - Bug fixed in SciTE's MRU list repeating entries if Ctrl+Tab - used when all entries filled. -
  • -
  • - ConvertEOLs call documentation fixed. -
  • -
-

- Release 1.37 -

-
    -
  • - Released on 17 April 2001. -
  • -
  • - Bug fixed with scroll bars being invisible on GTK+ 1.2.9. -
  • -
  • - Scintilla and SciTE support find and replace using simple regular - expressions with tagged expressions. SciTE supports C '\' escapes - in the Find and Replace dialogs. - Replace in Selection available in SciTE. -
  • -
  • - Scintilla has a 'target' feature for replacing code rapidly without - causing display updates. -
  • -
  • - Scintilla and SciTE on GTK+ support file dropping from file managers - such as Nautilus and gmc. Files or other URIs dropped on Scintilla - result in a URIDropped notification. -
  • -
  • - Lexers may have separate Lex and Fold functions. -
  • -
  • - Lexer infrastructure improved to allow for plug in lexers and for referring - to lexers by name rather than by ID. -
  • -
  • - Ada lexer and support added. -
  • -
  • - Option in both Scintilla and SciTE to treat both left and right margin - as equally important when repositioning visible area in response to - caret movement. Default is to prefer visible area positioning which - minimises the horizontal scroll position thus favouring the left margin. -
  • -
  • - Caret line highlighting. -
  • -
  • - Commands to delete from the caret to the end of line and - from the caret to the beginning of line. -
  • -
  • - SciTE has commands for inserting and removing block comments and - for inserting stream comments. -
  • -
  • - SciTE Director interface uses C++ '\' escapes to send control characters. -
  • -
  • - SciTE Director interface adds more commands including support for macros. -
  • -
  • - SciTE has menu options for recording and playing macros which are visible - when used with a companion program that supports these features. -
  • -
  • - SciTE has an Expand Abbreviation command. - Abbreviations are stored in a global abbrev.properties file. -
  • -
  • - SciTE has a Full Screen command to switch between a normal window - size and using the full screen. On Windows, the menu bar can be turned - off when in full screen mode. -
  • -
  • - SciTE has a Use monospaced font command to switch between the normal - set of fonts and one size of a particular fixed width font. -
  • -
  • - SciTE's use of tabs can be controlled for particular file names - as well as globally. -
  • -
  • - The contents of SciTE's status bar can be defined by a property and - include variables. On Windows, several status bar definitions can be active - with a click on the status bar cycling through them. -
  • -
  • - Copy as RTF command in SciTE on Windows to allow pasting - styled text into word processors. -
  • -
  • - SciTE can allow the use of non-alphabetic characters in - Complete Symbol lists and can automatically display this autocompletion - list when a trigger character such as '.' is typed. - Complete word can be set to pop up when the user is typing a word and - there is only one matching word in the document. -
  • -
  • - SciTE lists the imported properties files on a menu to allow rapid - access to them. -
  • -
  • - SciTE on GTK+ improvements to handling accelerator keys and focus - in dialogs. Message boxes respond to key presses without the Alt key as - they have no text entries to accept normal keystrokes. -
  • -
  • - SciTE on GTK+ sets the application icon. -
  • -
  • - SciTE allows setting the colours used to indicate the current - error line. -
  • -
  • - Variables within PHP strings have own style. Keyword list updated. -
  • -
  • - Keyword list for Lua updated for Lua 4.0. -
  • -
  • - Bug fixed in rectangular selection where rectangle still appeared - selected after using cursor keys to move caret. -
  • -
  • - Bug fixed in C++ lexer when deleting a '{' controlling a folded range - led to that range becoming permanently invisible. -
  • -
  • - Bug fixed in Batch lexer where comments were not recognised. -
  • -
  • - Bug fixed with undo actions coalescing into steps incorrectly. -
  • -
  • - Bug fixed with Scintilla on GTK+ positioning scroll bars 1 pixel - over the Scintilla window leading to their sides being chopped off. -
  • -
  • - Bugs fixed in SciTE when doing some actions led to the start - or end of the file being displayed rather than the current location. -
  • -
  • - Appearance of calltips fixed to look like document text including - any zoom factor. Positioned to be outside current line even when - multiple fonts and sizes used. -
  • -
  • - Bug fixed in Scintilla macro support where typing Enter caused both a newline - command and newline character insertion to be recorded. -
  • -
  • - Bug fixed in SciTE on GTK+ where focus was moving - between widgets incorrectly. -
  • -
  • - Bug fixed with fold symbols sometimes not updating when - the text changed. -
  • -
  • - Bugs fixed in SciTE's handling of folding commands. -
  • -
  • - Deprecated undo collection enumeration removed from API. -
  • -
-

- Release 1.36 -

-
    -
  • - Released on 1 March 2001. -
  • -
  • - Scintilla supports GTK+ on Win32. -
  • -
  • - Some untested work on making Scintilla and SciTE 64 bit compatible. - For users on GTK+ this requires including Scintilla.h before - ScintillaWidget.h. -
  • -
  • - HTML lexer allows folding HTML. -
  • -
  • - New lexer for Avenue files which are used in the ESRI ArcView GIS. -
  • -
  • - DOS Batch file lexer has states for '@', external commands, variables and - operators. -
  • -
  • - C++ lexer can fold comments of /* .. */ form. -
  • -
  • - Better disabling of pop up menu items in Scintilla when in read-only mode. -
  • -
  • - Starting to move to Doxygen compatible commenting. -
  • -
  • - Director interface on Windows enables another application to control SciTE. -
  • -
  • - Opening SciTE on Windows 9x sped up greatly for some cases. -
  • -
  • - The command.build.directory property allows SciTE to run the build - command in a different directory to the source files. -
  • -
  • - SciTE on Windows allows setting foreground and background colours - for printed headers and footers. -
  • -
  • - Bug fixed in finding calltips in SciTE which led to no calltips for some identifiers. -
  • -
  • - Documentation added for lexers and for the extension and director interfaces. -
  • -
  • - SciTE menus rearranged with new View menu taking over some of the items that - were under the Options menu. Clear All Bookmarks command added. -
  • -
  • - Clear Output command in SciTE. -
  • -
  • - SciTE on Windows gains an Always On Top command. -
  • -
  • - Bug fixed in SciTE with attempts to define properties recursively. -
  • -
  • - Bug fixed in SciTE properties where only one level of substitution was done. -
  • -
  • - Bug fixed in SciTE properties where extensions were not being - matched in a case insensitive manner. -
  • -
  • - Bug fixed in SciTE on Windows where the Go to dialog displays the correct - line number. -
  • -
  • - In SciTE, if fold.on.open set then switching buffers also performs fold. -
  • -
  • - Bug fixed in Scintilla where ensuring a line was visible in the presence of folding - operated on the document line instead of the visible line. -
  • -
  • - SciTE command line processing modified to operate on arguments in order and in - two phases. First any arguments before the first file name are processed, then the - UI is opened, then the remaining arguments are processed. Actions defined for the - Director interface (currently only "open") may also be used on the command line. - For example, "SciTE -open:x.txt" will start SciTE and open x.txt. -
  • -
  • - Numbered menu items SciTE's Buffers menu and the Most Recently Used portion - of the File menu go from 1..0 rather than 0..9. -
  • -
  • - The tab bar in SciTE for Windows has numbers. - The tab.hide.one option hides the tab bar until there is more than one buffer open. -
  • -
-

- Release 1.35 -

-
    -
  • - Released on 29 January 2001. -
  • -
  • - Rewritten and simplified widget code for the GTK+ version to enhance - solidity and make more fully compliant with platform norms. This includes more - normal handling of keystrokes so they are forwarded to containers correctly. -
  • -
  • - User defined lists can be shown. -
  • -
  • - Many fixes to the Perl lexer. -
  • -
  • - Pascal lexer handles comments more correctly. -
  • -
  • - C/C++/Java/JavaScipt lexer has a state for line doc comments. -
  • -
  • - Error output lexer understands Sun CC messages. -
  • -
  • - Make file lexer has variable, preprocessor, and operator states. -
  • -
  • - Wider area given to an italics character that is at the end of a line to prevent it - being cut off. -
  • -
  • - Call to move the caret inside the currently visible area. -
  • -
  • - Paste Rectangular will space fill on the left hand side of the pasted text as - needed to ensure it is kept rectangular. -
  • -
  • - Cut and Paste Rectangular does nothing in read-only mode. -
  • -
  • - Undo batching changed so that a paste followed by typing creates two undo actions.. -
  • -
  • - A "visibility policy" setting for Scintilla determines which range of lines are displayed - when a particular line is moved to. Also exposed as a property in SciTE. -
  • -
  • - SciTE command line allows property settings. -
  • -
  • - SciTE has a View Output command to hide or show the output pane. -
  • -
  • - SciTE's Edit menu has been split in two with searching commands moved to a - new Search menu. Find Previous and Previous Bookmark are in the Search menu. -
  • -
  • - SciTE on Windows has options for setting print margins, headers and footers. -
  • -
  • - SciTE on Windows has tooltips for toolbar. -
  • -
  • - SciTE on GTK+ has properties for setting size of file selector. -
  • -
  • - Visual and audio cues in SciTE on Windows enhanced. -
  • -
  • - Fixed performance problem in SciTE for GTK+ by dropping the extra 3D - effect on the content windows. -
  • -
  • - Fixed problem in SciTE where choosing a specific lexer then meant - that no lexer was chosen when files opened. -
  • -
  • - Default selection colour changed to be visible on low colour displays. -
  • -
  • - Fixed problems with automatically reloading changed documents in SciTE on - Windows. -
  • -
  • - Fixed problem with uppercase file extensions in SciTE. -
  • -
  • - Fixed some problems when using characters >= 128, some of which were being - incorrectly treated as spaces. -
  • -
  • - Fixed handling multiple line tags, non-inline scripts, and XML end tags /> in HTML/XML lexer. -
  • -
  • - Bookmarks in SciTE no longer disappear when switching between buffers. -
  • -
-

- Release 1.34 -

-
    -
  • - Released on 28 November 2000. -
  • -
  • - Pascal lexer. -
  • -
  • - Export as PDF in SciTE. -
  • -
  • - Support for the OpenVMS operating system in SciTE. -
  • -
  • - SciTE for GTK+ can check for another instance of SciTE - editing a file and switch to it rather than open a second instance - on one file. -
  • -
  • - Fixes to quoting and here documents in the Perl lexer. -
  • -
  • - SciTE on Windows can give extra visual and audio cues when a - warning is shown or find restarts from beginning of file. -
  • -
  • - Open Selected Filename command in SciTE. Also understands some - warning message formats. -
  • -
  • - Wider area for line numbers when printing. -
  • -
  • - Better scrolling performance on GTK+. -
  • -
  • - Fixed problem where rectangles with negative coordinates were - invalidated leading to trouble with platforms that use - unsigned coordinates. -
  • -
  • - GTK+ Scintilla uses more compliant signalling code so that keyboard - events should propagate to containers. -
  • -
  • - Bug fixed with opening full or partial paths. -
  • -
  • - Improved handling of paths in error messages in SciTE. -
  • -
  • - Better handling of F6 in SciTE. -
  • -
-

- Release 1.33 -

-
    -
  • - Released on 6 November 2000. -
  • -
  • - XIM support for the GTK+ version of Scintilla ensures that more non-English - characters can be typed. -
  • -
  • - Caret may be 1, 2, or 3 pixels wide. -
  • -
  • - Cursor may be switched to wait image during lengthy processing. -
  • -
  • - Scintilla's internal focus flag is exposed for clients where focus is handled in - complex ways. -
  • -
  • - Error status defined for Scintilla to hold indication that an operation failed and the reason - for that failure. No detection yet implemented but clients may start using the interface - so as to be ready for when it does. -
  • -
  • - Context sensitive help in SciTE. -
  • -
  • - CurrentWord property available in SciTE holding the value of the word the - caret is within or near. -
  • -
  • - Apache CONF file lexer. -
  • -
  • - Changes to Python lexer to allow 'as' as a context sensitive keyword and the - string forms starting with u, r, and ur to be recognised. -
  • -
  • - SCN_POSCHANGED notification now working and SCN_PAINTED notification added. -
  • -
  • - Word part movement commands for cursoring between the parts of reallyLongCamelIdentifiers and - other_ways_of_making_words. -
  • -
  • - When text on only one line is selected, Shift+Tab moves to the previous tab stop. -
  • -
  • - Tab control available for Windows version of SciTE listing all the buffers - and making it easy to switch between them. -
  • -
  • - SciTE can be set to automatically determine the line ending type from the contents of a - file when it is opened. -
  • -
  • - Dialogs in GTK+ version of SciTE made more modal and have accelerator keys. -
  • -
  • - Find in Files command in GTK+ version of SciTE allows choice of directory. -
  • -
  • - On Windows, multiple files can be opened at once. -
  • -
  • - SciTE source broken up into more files. -
  • -
  • - Scintilla headers made safe for C language, not just C++. -
  • -
  • - New printing modes - force background to white and force default background to white. -
  • -
  • - Automatic unfolding not occurring when Enter pressed at end of line bug fixed. -
  • -
  • - Bugs fixed in line selection. -
  • -
  • - Bug fixed with escapes in PHP strings in the HTML lexer. -
  • -
  • - Bug fixed in SciTE for GTK+ opening files when given full paths. -
  • -
  • - Bug fixed in autocompletion where user backspaces into existing text. -
  • -
  • - Bugs fixed in opening files and ensuring they are saved before running. - A case bug also fixed here. -
  • -
-

- Release 1.32 -

-
    -
  • - Released on 8 September 2000. -
  • -
  • - Fixes bugs in complete word and related code. Protection against a bug when - receiving a bad argument. -
  • -
-

- Release 1.31 -

-
    -
  • - Released on 6 September 2000. -
  • -
  • - Scintilla is available as a COM control from the scintillactrl module in CVS. -
  • -
  • - Style setting to underline text. Exposed in SciTE as "underlined". -
  • -
  • - Style setting to make text invisible. -
  • -
  • - SciTE has an extensibility interface that can be used to implement features such as - a scripting language or remote control. An example use of this is the extlua module - available from CVS which allows SciTE to be scripted in Lua. -
  • -
  • - Many minor fixes to all of the lexers. -
  • -
  • - New lexer for diff and patch files. -
  • -
  • - Error message lexer understands Perl error messages. -
  • -
  • - C/C++/Java lexer now supports C#, specifically verbatim strings and - @ quoting of identifiers that are the same as keywords. SciTE has - a set of keywords for C# and a build command set up for C#. -
  • -
  • - Scintilla property to see whether in overtype or insert state. -
  • -
  • - PosChanged notification fired when caret moved. -
  • -
  • - Comboboxes in dialogs in SciTE on Windows can be horizontally scrolled. -
  • -
  • - Autocompletion and calltips can treat the document as case sensitive or - case insensitive. -
  • -
  • - Autocompletion can be set to automatically choose the only - element in a single element list. -
  • -
  • - Set of characters that automatically complete an autocompletion list - can be set. -
  • -
  • - SciTE command to display calltip - useful when dropped because of - editing. -
  • -
  • - SciTE has a Revert command to go back to the last saved version. -
  • -
  • - SciTE has an Export as RTF command. Save as HTML is renamed - to Export as HTML and is located on the Export sub menu. -
  • -
  • - SciTE command "Complete Word" searches document for any - words starting with characters before caret. -
  • -
  • - SciTE options for changing aspects of the formatting of files exported - as HTML or RTF. -
  • -
  • - SciTE "character.set" option for choosing the character - set for all fonts. -
  • -
  • - SciTE has a "Toggle all folds" command. -
  • -
  • - The makefiles have changed. The makefile_vc and - makefile_bor files in scintilla/win32 and scite/win32 have been - merged into scintilla/win32/scintilla.mak and scite/win32/scite.mak. - DEBUG may be defined for all make files and this will turn on - assertions and for some make files will choose other debugging - options. -
  • -
  • - To make debugging easier and allow good use of BoundsChecker - there is a Visual C++ project file in scite/boundscheck that builds - all of Scintilla and SciTE into one executable. -
  • -
  • - The size of the SciTE output window can be set with the - output.horizontal.size and output.vertical.size settings. -
  • -
  • - SciTE status bar indicator for insert or overwrite mode. -
  • -
  • - Performance improvements to autocompletion and calltips. -
  • -
  • - A caret redraw problem when undoing is fixed. -
  • -
  • - Crash with long lines fixed. -
  • -
  • - Bug fixed with merging markers when lines merged. -
  • -
-

- Release 1.30 -

-
    -
  • - Released on 26 July 2000. -
  • -
  • - Much better support for PHP which is now an integral part of the HTML support. -
  • -
  • - Start replacement of Windows-specific APIs with cross platform APIs. - In 1.30, the new APIs are introduced but the old APIs are still available. - For the GTK+ version, may have to include "WinDefs.h" explicitly to - use the old APIs. -
  • -
  • - "if" and "import" statements in SciTE properties files allows modularisation into - language-specific properties files and choices based upon platform. - This means that SciTE is delivered with 9 language-specific properties files - as well as the standard SciTEGlobal.properties file. -
  • -
  • - Much lower resource usage on Windows 9x. -
  • -
  • - "/p" option in SciTE on Windows for printing a file and then exiting. -
  • -
  • - Options for printing with inverted brightness (when the screen is set to use - a dark background) and to force black on white printing. -
  • -
  • - Option for printing magnified or miniaturised from screen settings. -
  • -
  • - In SciTE, Ctrl+F3 and Ctrl+Shift+F3 find the selection in the forwards and backwards - directions respectively. -
  • -
  • - Auto-completion lists may be set to cancel when the cursor goes before - its start position or before the start of string being completed. -
  • -
  • - Auto-completion lists automatically size more sensibly. -
  • -
  • - SCI_CLEARDOCUMENTSTYLE zeroes all style bytes, ensures all - lines are shown and deletes all folding information. -
  • -
  • - On Windows, auto-completion lists are visually outdented rather than indented. -
  • -
  • - Close all command in SciTE. -
  • -
  • - On Windows multiple files can be dragged into SciTE. -
  • -
  • - When saving a file, the SciTE option save.deletes.first deletes it before doing the save. - This allows saving with a different capitalisation on Windows. -
  • -
  • - When use tabs option is off pressing the tab key inserts spaces. -
  • -
  • - Bug in indicators leading to extra line drawn fixed. -
  • -
-

- Release 1.28 -

-
    -
  • - Released on 27 June 2000. -
  • -
  • - Fixes crash in indentation guides when indent size set to 0. -
  • -
  • - Fixes to installation on GTK+/Linux. User properties file on GTK+ has a dot at front of name: - .SciTEUser.properties. Global properties file location configurable at compile time - defaulting to $prefix/share/scite. $prefix determined from Gnome if present else its - /usr/local and can be overridden by installer. Gnome menu integration performed in - make install if Gnome present. -
  • -
-

- Release 1.27 -

-
    -
  • - Released on 23 June 2000. -
  • -
  • - Indentation guides. View whitespace mode may be set to not display whitespace - in indentation. -
  • -
  • - Set methods have corresponding gets for UndoCollection, BufferedDraw, - CodePage, UsePalette, ReadOnly, CaretFore, and ModEventMask. -
  • -
  • - Caret is continuously on rather than blinking while typing or holding down - delete or backspace. And is now always shown if non blinking when focused on GTK+. -
  • -
  • - Bug fixed in SciTE with file extension comparison now done in case insensitive way. -
  • -
  • - Bugs fixed in SciTE's file path handling on Windows. -
  • -
  • - Bug fixed with preprocessor '#' last visible character causing hang. -
  • -
-

- Release 1.26 -

-
    -
  • - Released on 13 June 2000. -
  • -
  • - Support for the Lua language in both Scintilla and SciTE. -
  • -
  • - Multiple buffers may be open in SciTE. -
  • -
  • - Each style may have a character set configured. This may determine - the characters that are displayed by the style. -
  • -
  • - In the C++ lexer, lexing of preprocessor source may either treat it all as being in - the preprocessor class or only the initial # and preprocessor command word as - being in the preprocessor class. -
  • -
  • - Scintilla provides SCI_CREATEDOCUMENT, SCI_ADDREFDOCUMENT, and - SCI_RELEASEDOCUMENT to make it easier for a container to deal with multiple - documents. -
  • -
  • - GTK+ specific definitions in Scintilla.h were removed to ScintillaWidget.h. All GTK+ clients will need to - #include "ScintillaWidget.h". -
  • -
  • - For GTK+, tools can be executed in the background by setting subsystem to 2. -
  • -
  • - Keys in the properties files are now case sensitive. This leads to a performance increase. -
  • -
  • - Menu to choose which lexer to use on a file. -
  • -
  • - Tab size dialog on Windows. -
  • -
  • - File dialogs enlarged on GTK+. -
  • -
  • - Match Brace command bound to Ctrl+E on both platforms with Ctrl+] a synonym on Windows. - Ctrl+Shift+E is select to matching brace. Brace matching tries to match to either the inside or the - outside, depending on whether the cursor is inside or outside the braces initially. - View End of Line bound to Ctrl+Shift+O. -
  • -
  • - The Home key may be bound to move the caret to either the start of the line or the start of the - text on the line. -
  • -
  • - Visual C++ project file for SciTE. -
  • -
  • - Bug fixed with current x location after Tab key. -
  • -
  • - Bug fixed with hiding fold margin by setting fold.margin.width to 0. -
  • -
  • - Bugs fixed with file name confusion on Windows when long and short names used, or different capitalisations, - or relative paths. -
  • -
-

- Release 1.25 -

-
    -
  • - Released on 9 May 2000. -
  • -
  • - Some Unicode support on Windows. Treats buffer and API as UTF-8 and displays - through UCS-2 of Windows. -
  • -
  • - Automatic indentation. Indentation size can be different to tab size. -
  • -
  • - Tool bar. -
  • -
  • - Status bar now on Windows as well as GTK+. -
  • -
  • - Input fields in Find and Replace dialogs now have history on both Windows and - GTK+. -
  • -
  • - Auto completion list items may be separated by a chosen character to allow spaces - in items. The selected item may be changed through the API. -
  • -
  • - Horizontal scrollbar can be turned off. -
  • -
  • - Property to remove trailing spaces when saving file. -
  • -
  • - On Windows, changed font size calculation to be more compatible with - other applications. -
  • -
  • - On GTK+, SciTE's global properties files are looked for in the directory specified in the - SCITE_HOME environment variable if it is set. This allows hiding in a dot directory. -
  • -
  • - Keyword lists in SciTE updated for JavaScript to include those destined to be used in - the future. IDL includes XPIDL keywords as well as MSIDL keywords. -
  • -
  • - Zoom level can be set and queried through API. -
  • -
  • - New notification sent before insertions and deletions. -
  • -
  • - LaTeX lexer. -
  • -
  • - Fixes to folding including when deletions and additions are performed. -
  • -
  • - Fix for crash with very long lines. -
  • -
  • - Fix to affect all of rectangular selections with deletion and case changing. -
  • -
  • - Removed non-working messages that had been included only for Richedit compatibility. -
  • -
-

- Release 1.24 -

-
    -
  • - Released on 29 March 2000. -
  • -
  • - Added lexing of IDL based on C++ lexer with extra UUID lexical class. -
  • -
  • - Functions and associated keys for Line Delete, Line Cut, Line Transpose, - Selection Lower Case and Selection Upper Case. -
  • -
  • - Property setting for SciTE, eol.mode, chooses initial state of line end characters. -
  • -
  • - Fixed bugs in undo history with small almost-contiguous changes being incorrectly coalesced. -
  • -
  • - Fixed bugs with incorrect expansion of ContractionState data structures causing crash. -
  • -
  • - Fixed bugs relating to null fonts. -
  • -
  • - Fixed bugs where recolourisation was not done sometimes when required. -
  • -
  • - Fixed compilation problems with SVector.h. -
  • -
  • - Fixed bad setting of fold points in Python. -
  • -
-

- Release 1.23 -

-
    -
  • - Released on 21 March 2000. -
  • -
  • - Directory structure to separate on basis of product (Scintilla, SciTE, DMApp) - and environment (Cross-platform, Win32, GTK+). -
  • -
  • - Download packaging to allow download of the source or platform dependent executables. -
  • -
  • - Source code now available from CVS at SourceForge. -
  • -
  • - Very simple Windows-only demonstration application DMApp is available from cvs as dmapp. -
  • -
  • - Lexing functionality may optionally be included in Scintilla rather than be provided by - the container. -
  • -
  • - Set of lexers included is determined at link time by defining which of the Lex* object files - are linked in. -
  • -
  • - On Windows, the SciLexer.DLL extends Scintilla.DLL with the standard lexers. -
  • -
  • - Enhanced HTML lexer styles embedded VBScript and Python. - ASP segments are styled and ASP scripts in JavaScript, VBScript and Python are styled. -
  • -
  • - PLSQL and PHP supported. -
  • -
  • - Maximum number of lexical states extended to 128. -
  • -
  • - Lexers may store per line parse state for multiple line features such as ASP script language choice. -
  • -
  • - Lexing API simplified. -
  • -
  • - Project file for Visual C++. -
  • -
  • - Can now cycle through all recent files with Ctrl+Tab in SciTE. -
  • -
  • - Bookmarks in SciTE. -
  • -
  • - Drag and drop copy works when dragging to the edge of the selection. -
  • -
  • - Fixed bug with value sizes in properties file. -
  • -
  • - Fixed bug with last line in properties file not being used. -
  • -
  • - Bug with multiple views of one document fixed. -
  • -
  • - Keypad now works on GTK+. -
  • -
-

- Release 1.22 -

-
    -
  • - Released on 27 February 2000. -
  • -
  • - wxWindows platform defined. - Implementation for wxWindows will be available separately - from main Scintilla distribution. -
  • -
  • - Line folding in Scintilla. -
  • -
  • - SciTE performs syntax directed folding for C/C++/Java/JavaScript and for Python. -
  • -
  • - Optional macro recording support. -
  • -
  • - User properties file (SciTEUser.properties) allows for customisation by the user - that is not overwritten with each installation of SciTE. -
  • -
  • - Python lexer detects and highlights inconsistent indentation. -
  • -
  • - Margin API made more orthogonal. SCI_SETMARGINWIDTH and SCI_SETLINENUMBERWIDTH - are deprecated in favour of this new API. -
  • -
  • - Margins may be made sensitive to forward mouse click events to container. -
  • -
  • - SQL lexer and styles included. -
  • -
  • - Perl lexer handles regular expressions better. -
  • -
  • - Caret policy determines how closely caret is tracked by visible area. -
  • -
  • - New marker shapes: arrow pointing down, plus and minus. -
  • -
  • - Optionally display full path in title rather than just file name. -
  • -
  • - Container is notified when Scintilla gains or loses focus. -
  • -
  • - SciTE handles focus in a more standard way and applies the main - edit commands to the focused pane. -
  • -
  • - Container is notified when Scintilla determines that a line needs to be made visible. -
  • -
  • - Document watchers receive notification when document about to be deleted. -
  • -
  • - Document interface allows access to list of watchers. -
  • -
  • - Line end determined correctly for lines ending with only a '\n'. -
  • -
  • - Search variant that searches form current selection and sets selection. -
  • -
  • - SciTE understands format of diagnostic messages from WScript. -
  • -
  • - SciTE remembers top line of window for each file in MRU list so switching to a recent file - is more likely to show the same text as when the file was previously visible. -
  • -
  • - Document reference count now initialised correctly. -
  • -
  • - Setting a null document pointer creates an empty document. -
  • -
  • - WM_GETTEXT can no longer overrun buffer. -
  • -
  • - Polygon drawing bug fixed on GTK+. -
  • -
  • - Java and JavaScript lexers merged into C++ lexer. -
  • -
  • - C++ lexer indicates unterminated strings by colouring the end of the line - rather than changing the rest of the file to string style. This is less - obtrusive and helps the folding. -
  • -
-

- Release 1.21 -

-
    -
  • - Released on 2 February 2000. -
  • -
  • - Blank margins on left and right side of text. -
  • -
  • - SCN_CHECKBRACE renamed SCN_UPDATEUI and made more efficient. -
  • -
  • - SciTE source code refactored into platform independent and platform specific classes. -
  • -
  • - XML and Perl subset lexers in SciTE. -
  • -
  • - Large improvement to lexing speed. -
  • -
  • - A new subsystem, 2, allows use of ShellExec on Windows. -
  • -
  • - Borland compatible makefile. -
  • -
  • - Status bar showing caret position in GTK+ version of SciTE. -
  • -
  • - Bug fixes to selection drawing when part of selection outside window, mouse release over - scroll bars, and scroll positioning after deletion. -
  • -
-

- Release 1.2 -

-
    -
  • - Released on 21 January 2000. -
  • -
  • - Multiple views of one document. -
  • -
  • - Rectangular selection, cut, copy, paste, drag and drop. -
  • -
  • - Long line indication. -
  • -
  • - Reverse searching -
  • -
  • - Line end conversion. -
  • -
  • - Generic autocompletion and calltips in SciTE. -
  • -
  • - Call tip background colour can be set. -
  • -
  • - SCI_MARKERPREV for moving to a previous marker. -
  • -
  • - Caret kept more within window where possible. -
  • -
-

- Release 1.15 -

-
    -
  • - Released on 15 December 1999. -
  • -
  • - Brace highlighting and badlighting (for mismatched braces). -
  • -
  • - Visible line ends. -
  • -
  • - Multiple line call tips. -
  • -
  • - Printing now works from SciTE on Windows. -
  • -
  • - SciTE has a global "*" lexer style that is used as the basis for all the lexers' styles. -
  • -
  • - Fixes some warnings on GTK+ 1.2.6. -
  • -
  • - Better handling of modal dialogs on GTK+. -
  • -
  • - Resize handle drawn on pane splitter in SciTE on GTK+ so it looks more like a regular GTK+ - *paned widget. -
  • -
  • - SciTE does not place window origin offscreen if no properties file found on GTK+. -
  • -
  • - File open filter remembered in SciTE on Windows. -
  • -
  • - New mechanism using style numbers 32 to 36 standardises the setting of styles for brace - highlighting, brace badlighting, line numbers, control characters and the default style. -
  • -
  • - Old messages SCI_SETFORE .. SCI_SETFONT have been replaced by the default style 32. The old - messages are deprecated and will disappear in a future version. -
  • -
-

- Release 1.14 -

-
    -
  • - Released on 20 November 1999. -
  • -
  • - Fixes a scrolling bug reported on GTK+. -
  • -
-

- Release 1.13 -

-
    -
  • - Released on 18 November 1999. -
  • -
  • - Fixes compilation problems with the mingw32 GCC 2.95.2 on Windows. -
  • -
  • - Control characters are now visible. -
  • -
  • - Performance has improved, particularly for scrolling. -
  • -
  • - Windows RichEdit emulation is more accurate. This may break client code that uses these - messages: EM_GETLINE, EM_GETLINECOUNT, EM_EXGETSEL, EM_EXSETSEL, EM_EXLINEFROMCHAR, - EM_LINELENGTH, EM_LINEINDEX, EM_CHARFROMPOS, EM_POSFROMCHAR, and EM_GETTEXTRANGE. -
  • -
  • - Menus rearranged and accelerator keys set for all static items. -
  • -
  • - Placement of space indicators in view whitespace mode is more accurate with some fonts. -
  • -
-

- Release 1.12 -

-
    -
  • - Released on 9 November 1999. -
  • -
  • - Packaging error in 1.11 meant that the compilation error was not fixed in that release. - Linux/GTK+ should compile with GCC 2.95 this time. -
  • -
-

- Release 1.11 -

-
    -
  • - Released on 7 November 1999. -
  • -
  • - Fixed a compilation bug in ScintillaGTK.cxx. -
  • -
  • - Added a README file to explain how to build. -
  • -
  • - GTK+/Linux downloads now include documentation. -
  • -
  • - Binary only Sc1.EXE one file download for Windows. -
  • -
-

- Release 1.1 -

-
    -
  • - Released on 6 November 1999. -
  • -
  • - Major restructuring for better modularity and platform independence. -
  • -
  • - Inter-application drag and drop. -
  • -
  • - Printing support in Scintilla on Windows. -
  • -
  • - Styles can select colouring to end of line. This can be used when a file contains more than - one language to differentiate between the areas in each language. An example is the HTML + - JavaScript styling in SciTE. -
  • -
  • - Actions can be grouped in the undo stack, so they will be undone together. This grouping is - hierarchical so higher level actions such as replace all can be undone in one go. Call to - discover whether there are any actions to redo. -
  • -
  • - The set of characters that define words can be changed. -
  • -
  • - Markers now have identifiers and can be found and deleted by their identifier. The empty - marker type can be used to make a marker that is invisible and which is only used to trace - where a particular line moves to. -
  • -
  • - Double click notification. -
  • -
  • - HTML styling in SciTE also styles embedded JavaScript. -
  • -
  • - Additional tool commands can be added to SciTE. -
  • -
  • - SciTE option to allow reloading if changed upon application activation and saving on - application deactivation. Not yet working on GTK+ version. -
  • -
  • - Entry fields in search dialogs remember last 10 user entries. Not working in all cases in - Windows version. -
  • -
  • - SciTE can save a styled copy of the current file in HTML format. As SciTE does not yet - support printing, this can be used to print a file by then using a browser to print the - HTML file. -
  • -
-

- Release 1.02 -

-
    -
  • - Released on 1 October 1999. -
  • -
  • - GTK+ version compiles with GCC 2.95. -
  • -
  • - Properly deleting objects when window destroyed under GTK+. -
  • -
  • - If the selection is not empty backspace deletes the selection. -
  • -
  • - Some X style middle mouse button handling for copying the primary selection to and from - Scintilla. Does not work in all cases. -
  • -
  • - HTML styling in SciTE. -
  • -
  • - Stopped dirty flag being set in SciTE when results pane modified. -
  • -
-

- Release 1.01 -

-
    -
  • - Released on 28 September 1999. -
  • -
  • - Better DBCS support on Windows including IME. -
  • -
  • - Wheel mouse support for scrolling and zooming on Windows. Zooming with Ctrl+KeypadPlus and - Ctrl+KeypadMinus. -
  • -
  • - Performance improvements especially on GTK+. -
  • -
  • - Caret blinking and settable colour on both GTK+ and Windows. -
  • -
  • - Drag and drop within a Scintilla window. On Windows, files can be dragged into SciTE. -
  • -
-

- Release 1.0 -

-
    -
  • - Released on 17 May 1999. -
  • -
  • - Changed name of "Tide" to "SciTE" to avoid clash with a TCL based IDE. "SciTE" is a - SCIntilla based Text Editor and is Latin meaning something like "understanding in a neat - way" and is also an Old English version of the word "shit". -
  • -
  • - There is a SCI_AUTOCSTOPS message for defining a string of characters that will stop - autocompletion mode. Autocompletion mode is cancelled when any cursor movement occurs apart - from backspace. -
  • -
  • - GTK+ version now splits horizontally as well as vertically and all dialogs cancel when the - escape key is pressed. -
  • -
-

- Beta release 0.93 -

-
    -
  • - Released on 12 May 1999. -
  • -
  • - A bit more robust than 0.92 and supports SCI_MARKERNEXT message. -
  • -
-

- Beta release 0.92 -

-
    -
  • - Released on 11 May 1999. -
  • -
  • - GTK+ version now contains all features of Windows version with some very small differences. - Executing programs works much better now. -
  • -
  • - New palette code to allow more colours to be displayed in 256 colour screen modes. A line - number column can be displayed to the left of the selection margin. -
  • -
  • - The code that maps from line numbers to text positions and back has been completely - rewritten to be faster, and to allow markers to move with the text. -
  • -
-

- Beta release 0.91 -

-
    -
  • - Released on 30 April 1999, containing fixes to text measuring to make Scintilla work better - with bitmap fonts. Also some small fixes to make compiling work with Visual C++. -
  • -
-

- Beta release 0.90 -

-
    -
  • - Released on 29 April 1999, containing working GTK+/Linux version. -
  • -
  • - The Java, C++ and Python lexers recognise operators as distinct from default allowing them - to be highlighted. -
  • -
-

- Beta release 0.82 -

-
    -
  • - Released on 1 April 1999, to fix a problem with handling the Enter key in PythonWin. Also - fixes some problems with cmd key mapping. -
  • -
-

- Beta release 0.81 -

-
    -
  • - Released on 30th March 1999, containing bug fixes and a few more features. -
  • -
  • - Static linking supported and Tidy.EXE, a statically linked version of Tide.EXE. Changes to - compiler flags in the makefiles to optimise for size. -
  • -
  • - Scintilla supports a 'savepoint' in the undo stack which can be set by the container when - the document is saved. Notifications are sent to the container when the savepoint is - entered or left, allowing the container to to display a dirty indicator and change its - menus. -
  • -
  • - When Scintilla is set to read-only mode, a notification is sent to the container should the - user try to edit the document. This can be used to check the document out of a version - control system. -
  • -
  • - There is an API for setting the appearance of indicators. -
  • -
  • - The keyboard mapping can be redefined or removed so it can be implemented completely by the - container. All of the keyboard commands are now commands which can be sent by the - container. -
  • -
  • - A home command like Visual C++ with one hit going to the start of the text on the line and - the next going to the left margin is available. I do not personally like this but my - fingers have become trained to it by much repetition. -
  • -
  • - SCI_MARKERDELETEALL has an argument in wParam which is the number of the type marker to - delete with -1 performing the old action of removing all marker types. -
  • -
  • - Tide now understands both the file name and line numbers in error messages in most cases. -
  • -
  • - Tide remembers the current lines of files in the recently used list. -
  • -
  • - Tide has a Find in Files command. -
  • -
-

- Beta release 0.80 -

-
    -
  • - This was the first public release on 14th March 1999, containing a mostly working Win32 - Scintilla DLL and Tide EXE. -
  • -
-

- Beta releases of SciTE were called Tide -

- - - + + + + + + + + + Scintilla and SciTE + + + + + + + + + +
+ Scintilla icon + + Scintilla + and SciTE +
+

+ History of Scintilla and SciTE +

+

+ Contributors +

+

+ Thanks to all the people that have contributed patches, bug reports and suggestions. +

+

+ Source code and documentation have been contributed by +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Atsuo IshimotoMark HammondFrancois Le CoguiecDale Nagata
Ralf ReinhardtPhilippe LhosteAndrew McKinlayStephan R. A. Deibel
Hans EckardtVassili BourdoMaksim LinRobin Dunn
John EhresmanSteffen GoeldnerDeepak S.Yann Gaillard
Aubin PaulJason DiamondAhmad BaitalmalPaul Winwood
Maxim BaranovRagnar HøjlandChristian ObrechtAndreas Neukoetter
Adam GatesSteve LhommeFerdinand PrantlJan Dries
Markus GritschTahir KaracaAhmad ZawawiLaurent le Tynevez
Walter BraeuAshley CambrellGarrett SerackHolger Schmidt
ActiveStateJames LarcombeAlexey YutkinJan Hercek
Richard PeclEdward K. ReamValery KondakoffSmári McCarthy
Clemens WyssSimon SteeleSerge A. BaranovXavier Nodet
Willy DevauxDavid ClainBrendon YensonVamsi Potluru
Praveen AmbekarAlan KnowlesKengo JinnoValentin Valchev
Marcos E. WurziusMartin AldersonRobert GustavssonJosé Fonseca
Holger KiemesFrancis IrvingScott KirkwoodBrian Quinlan
UbiMichael R. DuerigDeepak TDon Paul Beletsky
Gerhard KalabOlivier DagenaisJosh WingstromBruce Dodson
Sergey KoshcheyevChuan-jian ShenShane CaraveoAlexander Scripnik
Ryan ChristiansonMartin SteffensenJakub VránaThe Black Horus
Bernd KreussThomas LauerMike LansdaalYukihiro Nakai
Jochen TuchtGreg SmithSteve SchoettlerMauritius Thinnes
Darren SchroederPedro GuerreiroDan PetittBiswapesh Chattopadhyay
Kein-Hong ManPatrizio BekerleNigel HathawayHrishikesh Desai
Sergey PuljajevMathias RauenAngelo MandatoDenis Sureau
Kaspar SchiessChristoph HöslerJoão Paulo F FariasRon Schofield
Stefan WosnikMarius GheorgheNaba KumarSean O'Dell
Stefanos TogoulidisHans HagenJim CapeRoland Walter
Brian MosherNicholas NemtsevRoy WoodPeter-Henry Mander
Robert BoucherChristoph DalitzApril WhiteS. Umar
Trent MickFilip YaghobAvi YegudinVivi Orunitia
Manfred BeckerDimitris KeletsekisYuigaDavide Scola
Jason BoggsReinhold NiesnerJos van der ZandePescuma
Pavol BosikJohannes SchmidBlair McGlashanMikael Hultgren
Florian BalmerHadar RazHerr PfarrerBen Key
Gene BarryNiki SpahievCarsten SperberPhil Reid
Iago RubioRégis VaquetteMassimo CoràElias Pschernig
Chris JonesJosiah ReynoldsRobert Roessler rftp.comSteve Donovan
Jan Martin PettersenSergey PhilippovBorujoaMichael Owens
Franck MarciaMassimo Maria GhisalbertiFrank WunderlichJosepmaria Roca
Tobias EngvallSuzumizaki KimitakaMichael CartmellPascal Hurni
AndreRandy ButlerGeorg RitterMichael Goffioul
Ben HarperAdam StrzeleckiKamen StanevSteve Menard
Oliver YeohEric PromislowJoseph GalbraithJeffrey Ren
Armel AsselinJim PatteeFriedrich VedderSebastian Pipping
Andre ArpinStanislav MaslovskiMartin StoneFabien Proriol
mimirNicola CivranSnowMitchell Foral
Pieter HoltzhausenWaldemar AugustynJason HaslamSebastian Steinlechner
Chris RickardRob McMullenStefan SchwendelerCristian Adam
Nicolas ChachereauIstvan SzollosiXie RenhuiEnrico Tröger
Todd WhitemanYuval PapishinstantonSergio Lucato
VladVRODmitry MaslovchupakabraJuan Carlos Arevalo Baeza
Nick TreleavenStephen StaggJean-Paul IribarrenTim Gerundt
Sam HarwellBorisJason OsterGertjan Kloosterman
alexbodnSergiu DotencoAnders Karlssonozlooper
Marko NjezicEugen BitterChristoph BaumannChristopher Bean
Sergey KishchenkoKai LiuAndreas RumpfJames Moffatt
Yuzhou XinNic JansmaEvan JonesMike Lischke
Eric KiddmaXmoDavid SeverwrightJon Strait
Oliver KiddleEtienne GirondelHaimag RenAndrey Moskalyov
XaviToby InksterEric ForgeotColomban Wendling
NeoJordan RussellFarshid LashkariSam Rawlins
Michael MullinCarlos SSvimMartial Demolins
Tino WeinkaufJérôme LaforgeUdo LechnerMarco Falda
Dariusz KnocińskiBen FisherDon GobinJohn Yeung
AdobeElizabeth A. IrizarryMike SchroederMorten MacFly
Jaime GimenoThomas Linder PulsArtyom ZuikovGerrit
Occam's RazorBen BluemelDavid WolfendaleChris Angelico
Marat DukhanStefan WeilRex ConnRoss McKay
Bruno Barbieri
+

+ Images used in GTK+ version +

+
    +
  • + + Icons Copyright(C) 1998 by Dean S. Jones
    +
  • +
+

+ Release 3.0.3 +

+
    +
  • + Released 28 January 2012. +
  • +
  • + Printing works on GTK+ version 2.x as well as 3.x. +
  • +
  • + Lexer added for the AviSynth language. + Feature #3475611. +
  • +
  • + Lexer added for the Take Command / TCC scripting language. + Feature #3462462. +
  • +
  • + CSS lexer gains support for SCSS. + Feature #3268017. +
  • +
  • + CPP lexer fixes problems in the preprocessor structure caused by continuation lines. + Bug #3458508. +
  • +
  • + Errorlist lexer handles column numbers for GCC format diagnostics. + In SciTE, Next Message goes to column where this can be decoded from GCC format diagnostics. + Feature #3453075. +
  • +
  • + HTML folder fixes spurious folds on some tags. + Bug #3459262. +
  • +
  • + Ruby lexer fixes bug where '=' at start of file caused whole file to appear as a comment. + Bug #3452488. +
  • +
  • + SQL folder folds blocks of single line comments. + Feature #3467425. +
  • +
  • + On Windows using Direct2D, defer invalidation of render target until completion of painting to avoid failures. +
  • +
  • + Further support of fractional positioning. Spaces, tabs, and single character tokens can take fractional space + and wrapped lines are positioned taking fractional positions into account. + Bug #3471998. +
  • +
  • + On Windows using Direct2D, fix extra carets appearing. + Bug #3471998. +
  • +
  • + For autocompletion lists Page Up and Down move by the list height instead of by 5 lines. + Bug #3455493. +
  • +
  • + For SCI_LINESCROLLDOWN/UP don't select into virtual space. + Bug #3451681. +
  • +
  • + Fix fold highlight not being fully drawn. + Bug #3469936. +
  • +
  • + Fix selection margin appearing black when starting in wrap mode. +
  • +
  • + Fix crash when changing end of document after adding an annotation. + Bug #3476637. +
  • +
  • + Fix problems with building to make RPMs. + Bug #3476149. +
  • +
  • + Fix problem with building on GTK+ where recent distributions could not find gmodule. + Bug #3469056. +
  • +
  • + Fix problem with installing SciTE on GTK+ due to icon definition in .desktop file including an extension. + Bug #3476117. +
  • +
  • + Fix SciTE bug where new buffers inherited some properties from previously opened file. + Bug #3457060. +
  • +
  • + Fix focus when closing tab in SciTE with middle click. Focus moves to edit pane instead of staying on tab bar. + Bug #3440142. +
  • +
  • + For SciTE on Windows fix bug where Open Selected Filename for URL would append a file extension. + Feature #3459185. +
  • +
  • + For SciTE on Windows fix key handling of control characters in Parameters dialog so normal editing (Ctrl+C, ...) works. + Bug #3459345. +
  • +
  • + Fix SciTE bug where files became read-only after saving. Drop the "*" dirty marker after save completes. + Bug #3467432. +
  • +
  • + For SciTE handling of diffs with "+++" and "---" lines, also handle case where not followed by tab. + Go to correct line for diff "+++" message. + Bug #3467143. + Bug #3467178. +
  • +
  • + SciTE on GTK+ now performs threaded actions even on GTK+ versions before 2.12. +
  • +
+

+ Release 3.0.2 +

+
    +
  • + Released 9 December 2011. +
  • +
  • + SciTE saves files in the background without blocking the user interface. +
  • +
  • + Printing implemented in SciTE on GTK+ 3.x. +
  • +
  • + ILoader interface for background loading finalised and documented. +
  • +
  • + CoffeeScript lexer added. +
  • +
  • + C++ lexer fixes crash with "#if defined( XXX 1". +
  • +
  • + Crash with Direct2D on Windows fixed. +
  • +
  • + Backspace removing protected range fixed. + Bug #3445911. +
  • +
  • + Cursor setting failure on Windows when screen saver on fixed. + Bug #3438780. +
  • +
  • + SciTE on GTK+ hang fixed with -open:file option. + Bug #3441980. +
  • +
  • + Failure to evaluate shbang fixed in SciTE. + Bug #3441801. +
  • +
  • + SciTE failure to treat files starting with "<?xml" as XML fixed. + Bug #3440718. +
  • +
  • + Made untitled tab saveable when created by closing all files. + Bug #3440244. +
  • +
  • + SciTE crash fixed when using Scintillua. +
  • +
  • + SciTE revert command fixed so that undo works on individual actions instead of undoing to revert point. +
  • +
  • + Focus loss in SciTE when opening a recent file fixed. + Bug #3440142. +
  • +
  • + Fixed SciTE SelLength property to measure characters instead of bytes. + Bug #3283519. +
  • +
+

+ Release 3.0.1 +

+
    +
  • + Released 15 November 2011. +
  • +
  • + SciTE on Windows now runs Lua scripts directly on the main thread instead of starting them on a + secondary thread and then moving back to the main thread. +
  • +
  • + Highlight "else" as a keyword for TCL in the same way as other languages. + Bug #1836954. +
  • +
  • + Fix problems with setting fonts for autocompletion lists on Windows where + font handles were copied and later deleted causing a system default font to be used. +
  • +
  • + Fix font size used on Windows for Asian language input methods which sometimes led to IME not being visible. + Bug #3436753. +
  • +
  • + Fixed polygon drawing on Windows so fold symbols are visible again. + Bug #3433558. +
  • +
  • + Changed background drawing on GTK+ to allow for fractional character positioning as occurs on OS X + as this avoids faint lines at lexeme boundaries. +
  • +
  • + Ensure pixmaps allocated before painting as there was a crash when Scintilla drew without common initialisation calls. + Bug #3432354. +
  • +
  • + Fixed SciTE on Windows bug causing wrong caret position after indenting a selection. + Bug #3433433. +
  • +
  • + Fixed SciTE session saving to store buffer position matching buffer. + Bug #3434372. +
  • +
  • + Fixed leak of document objects in SciTE. +
  • +
  • + Recognize URL characters '?' and '%' for Open Selected command in SciTE. + Bug #3429409. +
  • +
+

+ Release 3.0.0 +

+
    +
  • + Released 1 November 2011. +
  • +
  • + Carbon platform support removed. OS X applications should switch to Cocoa. +
  • +
  • + On Windows Vista or newer, drawing may be performed with Direct2D and DirectWrite instead of GDI. +
  • +
  • + Cairo is now used for all drawing on GTK+. GDK drawing was removed. +
  • +
  • + Paletted display support removed. +
  • +
  • + Fractional font sizes can be specified. +
  • +
  • + Different weights of text supported on some platforms instead of just normal and bold. +
  • +
  • + Sub-pixel character positioning supported. +
  • +
  • + SciTE loads files in the background without blocking the user interface. +
  • +
  • + SciTE can display diagnostic messages interleaved with the text of files immediately after the + line referred to by the diagnostic. +
  • +
  • + New API to see if all lines are visible which can be used to optimize processing fold structure notifications. +
  • +
  • + Scrolling optimized by avoiding invalidation of fold margin when redrawing whole window. +
  • +
  • + Optimized SCI_MARKERNEXT. +
  • +
  • + C++ lexer supports Pike hash quoted strings when turned on with lexer.cpp.hashquoted.strings. +
  • +
  • + Fixed incorrect line height with annotations in wrapped mode when there are multiple views. + Bug #3388159. +
  • +
  • + Calltips may be displayed above the text as well as below. + Bug #3410830. +
  • +
  • + For huge files SciTE only examines the first megabyte for newline discovery. +
  • +
  • + SciTE on GTK+ removes the fileselector.show.hidden property and check box as this was buggy and GTK+ now + supports an equivalent feature. + Bug #3413630. +
  • +
  • + SciTE on GTK+ supports mnemonics in dynamic menus. +
  • +
  • + SciTE on GTK+ displays the user's home directory as '~' in menus to make them shorter. +
  • +
+

+ Release 2.29 +

+
    +
  • + Released 16 September 2011. +
  • +
  • + To automatically discover the encoding of a file when opening it, SciTE can run a program set with command.discover.properties. + Feature #3324341. +
  • +
  • + Cairo always used for drawing on GTK+. +
  • +
  • + The set of properties files imported by SciTE can be controlled with the properties imports.include and imports.exclude. + The import statement has been extended to allow "import *". + The properties files for some languages are no longer automatically loaded by default. The properties files affected are + avenue, baan, escript, lot, metapost, and mmixal. +
  • +
  • + C++ lexer fixed a bug with raw strings being recognised too easily. + Bug #3388122. +
  • +
  • + LaTeX lexer improved with more states and fixes to most outstanding bugs. + Bug #1493111. + Bug #1856356. + Bug #3081692. +
  • +
  • + Lua lexer updates for Lua 5.2 beta with goto labels and "\z" string escape. + Feature #3386330. +
  • +
  • + Perl string styling highlights interpolated variables. + Feature #3394258. + Bug #3076629. +
  • +
  • + Perl lexer updated for Perl 5.14.0 with 0X and 0B numeric literal prefixes, break keyword and "+" supported in subroutine prototypes. + Feature #3388802. +
  • +
  • + Perl bug fixed with CRLF line endings. +
  • +
  • + Markdown lexer fixed to not change state with "_" in middle of word. + Bug #3398184. +
  • +
  • + Cocoa restores compatibility with OS X 10.5. +
  • +
  • + Mouse pointer changes over selection to an arrow near start when scrolled horizontally. + Bug #3389055. +
  • +
  • + Indicators that finish at the end of the document no longer expand when text is appended. + Bug #3378718. +
  • +
  • + SparseState merge fixed to check if other range is empty. + Bug #3387053. +
  • +
  • + On Windows, autocompletion lists will scroll instead of document when mouse wheel spun. + Feature #3403600. +
  • +
  • + SciTE performs more rapid polling for command completion so will return faster and report more accurate times. +
  • +
  • + SciTE resizes panes proportionally when switched between horizontal and vertical layout. + Feature #3376784. +
  • +
  • + SciTE on GTK+ opens multiple files into a single instance more reliably. + Bug #3363754. +
  • +
+

+ Release 2.28 +

+
    +
  • + Released 1 August 2011. +
  • +
  • + GTK+ Cairo support works back to GTK+ version 2.8. Requires changing Scintilla source code to enable before GTK+ 2.22. + Bug #3322351. +
  • +
  • + Translucent images in RGBA format can be used for margin markers and in autocompletion lists. +
  • +
  • + INDIC_DOTBOX added as a translucent dotted rectangular indicator. +
  • +
  • + Asian text input using IME works for GTK+ 3.x and GTK+ 2.x with Cairo. +
  • +
  • + On GTK+, IME works for Ctrl+Shift+U Unicode input in Scintilla. For SciTE, Ctrl+Shift+U is still Make Selection Uppercase. +
  • +
  • + Key bindings for GTK+ on OS X made compatible with Cocoa port and platform conventions. +
  • +
  • + Cocoa port supports different character encodings, improves scrolling performance and drag image appearance. + The control ID is included in WM_COMMAND notifications. Text may be deleted by dragging to the trash. + ScrollToStart and ScrollToEnd key commands added to simplify implementation of standard OS X Home and End + behaviour. +
  • +
  • + SciTE on GTK+ uses a paned widget to contain the edit and output panes instead of custom code. + This allows the divider to be moved easily on GTK+ 3 and its appearance follows GTK+ conventions more closely. +
  • +
  • + SciTE builds and installs on BSD. + Bug #3324644. +
  • +
  • + Cobol supports fixed format comments. + Bug #3014850. +
  • +
  • + Mako template language block syntax extended and ## comments recognised. + Feature #3325178. + Bug #3318818. +
  • +
  • + Folding of Mako template language within HTML fixed. + Bug #3324563. +
  • +
  • + Python lexer has lexer.python.keywords2.no.sub.identifiers option to avoid highlighting second set of + keywords following '.'. + Bug #3325333. +
  • +
  • + Python folder fixes bug where fold would not extend to final line. + Bug #3349157. +
  • +
  • + SciTE treats LPEG lexers the same as script lexers by setting all 8 style bits. +
  • +
  • + For Cocoa, crashes with unsupported font variants and memory leaks for colour objects fixed. +
  • +
  • + Shift-JIS lead byte ranges modified to match Windows. +
  • +
  • + Mouse pointer changes over selection to an arrow more consistently. + Bug #3315756. +
  • +
  • + Bug fixed with annotations beyond end of document. + Bug #3347268. +
  • +
  • + Incorrect drawing fixed for combination of background colour change and translucent selection. + Bug #3377116. +
  • +
  • + Lexers initialized correctly when started at position other than start of line. + Bug #3377148. +
  • +
  • + Fold highlight drawing fixed for some situations. + Bug #3323015. + Bug #3323805. +
  • +
  • + Case insensitive search fixed for cases where folded character uses fewer bytes than base character. + Bug #3362038. +
  • +
  • + SciTE bookmark.alpha setting fixed. + Bug #3373907. +
  • +
+

+ Release 2.27 +

+
    +
  • + Released 20 June 2011. +
  • +
  • + On recent GTK+ 2.x versions when using Cairo, bug fixed where wrong colours were drawn. +
  • +
  • + SciTE on GTK+ slow performance in menu maintenance fixed. + Bug #3315233. +
  • +
  • + Cocoa platform supports 64-bit builds and uses only non-deprecated APIs. + Asian Input Method Editors are supported. + Autocompletion lists and calltips implemented. + Control identifier used in notifications. +
  • +
  • + On Cocoa, rectangular selection now uses Option/Alt key to be compatible with Apple Human + Interface Guidelines and other applications. + The Control key is reported with an SCMOD_META modifier bit. +
  • +
  • + API added for setting and retrieving the identifier number used in notifications. +
  • +
  • + SCI_SETEMPTYSELECTION added to set selection without scrolling or redrawing more than needed. + Feature #3314877. +
  • +
  • + Added new indicators. INDIC_DASH and INDIC_DOTS are variants of underlines. + INDIC_SQUIGGLELOW indicator added as shorter alternative to INDIC_SQUIGGLE for small fonts. + Bug #3314591 +
  • +
  • + Margin line selection can be changed to select display lines instead of document lines. + Bug #3312763. +
  • +
  • + On Windows, SciTE can perform reverse searches by pressing Shift+Enter + in the Find or Replace strips or dialogs. +
  • +
  • + Matlab lexer does not special case '\' in single quoted strings. + Bug #948757 + Bug #1755950 + Bug #1888738 + Bug #3316852. +
  • +
  • + Verilog lexer supports SystemVerilog folding and keywords. +
  • +
  • + Font leak fixed. + Bug #3306156. +
  • +
  • + Automatic scrolling works for long wrapped lines. + Bug #3312763. +
  • +
  • + Multiple typing works for cases where selections collapse together. + Bug #3309906. +
  • +
  • + Fold expanded when needed in word wrap mode. + Bug #3291579. +
  • +
  • + Bug fixed with edge drawn in wrong place on wrapped lines. + Bug #3314807. +
  • +
  • + Bug fixed with unnecessary scrolling for SCI_GOTOLINE. + Bug #3303406. +
  • +
  • + Bug fixed where extra step needed to undo SCI_CLEAR in virtual space. + Bug #3159691. +
  • +
  • + Regular expression search fixed for \$ on last line of search range. + Bug #3313746. +
  • +
  • + SciTE performance improved when switching to a tab with a very large file. + Bug #3311421. +
  • +
  • + On Windows, SciTE advanced search remembers the "Search only in this style" setting. + Bug #3313344. +
  • +
  • + On GTK+, SciTE opens help using "xdg-open" instead of "netscape" as "netscape" no longer commonly installed. + Bug #3314377. +
  • +
  • + SciTE script lexers can use 256 styles. +
  • +
  • + SciTE word highlight works for words containing DBCS characters. + Bug #3315173. +
  • +
  • + Compilation fixed for wxWidgets. + Bug #3306156. +
  • +
+

+ Release 2.26 +

+
    +
  • + Released 25 May 2011. +
  • +
  • + Folding margin symbols can be highlighted for the current folding block. + Feature #3147069. +
  • +
  • + Selected lines can be moved up or down together. + Feature #3304850. +
  • +
  • + SciTE can highlight all occurrences of the current word or selected text. + Feature #3291636. +
  • +
  • + Experimental GTK+ 3.0 support: build with "make GTK3=1". +
  • +
  • + INDIC_STRAIGHTBOX added. Is similar to INDIC_ROUNDBOX but without rounded corners. + Bug #3290435. +
  • +
  • + Can show brace matching and mismatching with indicators instead of text style. + Translucency of outline can be altered for INDIC_ROUNDBOX and INDIC_STRAIGHTBOX. + Feature #3290434. +
  • +
  • + SciTE can automatically indent python by examining previous line for scope-starting ':' with indent.python.colon. +
  • +
  • + Batch file lexer allows braces '(' or ')' inside variable names. +
  • +
  • + The cpp lexer only recognises Vala triple quoted strings when lexer.cpp.triplequoted.strings property is set. + Bug #3239234. +
  • +
  • + Make file lexer treats a variable with a nested variable like $(f$(qx)b) as one variable. + Bug #3298223. +
  • +
  • + Folding bug fixed for JavaScript with nested PHP. + Bug #3193530. +
  • +
  • + HTML lexer styles Django's {# #} comments. + Bug #3013798. +
  • +
  • + HTML lexer styles JavaScript regular expression correctly for /abc/i.test('abc');. + Bug #3209108. +
  • +
  • + Inno Setup Script lexer now works properly when it restarts from middle of [CODE] section. + Bug #3283880. + Bug #3129044. +
  • +
  • + Lua lexer updated for Lua 5.2 with hexadecimal floating-point numbers and '\*' whitespace escaping in strings. + Feature #3243811. +
  • +
  • + Perl folding folds "here doc"s and adds options fold.perl.at.else and fold.perl.comment.explicit. Fold structure for Perl fixed. + Feature #3112671. + Bug #3265401. +
  • +
  • + Python lexer supports cpdef keyword for Cython. + Bug #3279728. +
  • +
  • + SQL folding option lexer.sql.fold.at.else renamed to fold.sql.at.else. + Bug #3271474. +
  • +
  • + SQL lexer no longer treats ';' as terminating a comment. + Bug #3196071. +
  • +
  • + Text drawing and measurement segmented into smaller runs to avoid platform bugs. + Bug #3277449. + Bug #3165743. +
  • +
  • + SciTE on Windows adds temp.files.sync.load property to open dropped temporary files synchronously as they may + be removed before they can be opened asynchronously. + Bug #3072009. +
  • +
  • + Bug fixed with indentation guides ignoring first line in SC_IV_LOOKBOTH mode. + Bug #3291317. +
  • +
  • + Bugs fixed in backward regex search. + Bug #3292659. +
  • +
  • + Bugs with display of folding structure fixed for wrapped lines and where there is a fold header but no body. + Bug #3291579. + Bug #3265401. +
  • +
  • + SciTE on Windows cursor changes to an arrow now when over horizontal splitter near top of window. + Bug #3286620. +
  • +
  • + Fixed default widget size problem on GTK+. + Bug #3267892. +
  • +
  • + Fixed font size when using Cairo on GTK+. + Bug #3272662. +
  • +
  • + Fixed primary selection and cursor issues on GTK+ when unrealized then realized. + Bug #3256153. +
  • +
  • + Right click now cancels selection on GTK+ like on Windows. + Bug #3235190. +
  • +
  • + SciTE on GTK+ implements z-order buffer switching like on Windows. + Bug #3228384. +
  • +
  • + Improve selection position after SciTE Insert Abbreviation command when abbreviation expansion includes '|'. +
  • +
+

+ Release 2.25 +

+
    +
  • + Released 21 March 2011. +
  • +
  • + SparseState class makes it easier to write lexers which have to remember complex state between lines. +
  • +
  • + Visual Studio project (.dsp) files removed. The make files should be used instead as described in the README. +
  • +
  • + Modula 3 lexer added along with SciTE support. + Feature #3173374. +
  • +
  • + Asm, Basic, and D lexers add extra folding properties. +
  • +
  • + Raw string literals for C++0x supported in C++ lexer. +
  • +
  • + Triple-quoted strings used in Vala language supported in C++ lexer. + Feature #3177601. +
  • +
  • + The errorlist lexer used in SciTE's output pane colours lines that start with '<' as diff deletions. + Feature #3172878. +
  • +
  • + The Fortran lexer correctly folds type-bound procedures from Fortran 2003. +
  • +
  • + LPeg lexer support‎ improved in SciTE. +
  • +
  • + SciTE on Windows-64 fixes for menu localisation and Lua scripts. + Bug #3204502. +
  • +
  • + SciTE on Windows avoids locking folders when using the open or save dialogs. + Bug #1795484. +
  • +
  • + Diff lexer fixes problem where diffs of diffs producing lines that start with "----". + Bug #3197952. +
  • +
  • + Bug fixed when searching upwards in Chinese code page 936. + Bug #3176271. +
  • +
  • + On Cocoa, translucent drawing performed as on other platforms instead of 2.5 times less translucent. +
  • +
  • + Performance issue and potential bug fixed on GTK+ with caret line for long lines. +
  • +
+

+ Release 2.24 +

+
    +
  • + Released 3 February 2011. +
  • +
  • + Fixed memory leak in GTK+ Cairo code. + Feature #3157655. +
  • +
  • + Insert Abbreviation dialog added to SciTE on GTK+. +
  • +
  • + SCN_UPDATEUI notifications received when window scrolled. An 'updated' bit mask indicates which + types of update have occurred from SC_UPDATE_SELECTION, SC_UPDATE_CONTENT, SC_UPDATE_H_SCROLL + or SC_UPDATE_V_SCROLL. + Feature #3125977. +
  • +
  • + On Windows, to ensure reverse arrow cursor matches platform default, it is now generated by + reflecting the platform arrow cursor. + Feature #3143968. +
  • +
  • + Can choose mouse cursor used in margins. + Feature #3161326. +
  • +
  • + On GTK+, SciTE sets a mime type of text/plain in its .desktop file so that it will appear in the shell context menu. + Feature #3137126. +
  • +
  • + Bash folder handles here docs. + Feature #3118223. +
  • +
  • + C++ folder adds fold.cpp.syntax.based, fold.cpp.comment.multiline, fold.cpp.explicit.start, fold.cpp.explicit.end, + and fold.cpp.explicit.anywhere properties to allow more control over folding and choice of explicit fold markers. +
  • +
  • + C++ lexer fixed to always handle single quote strings continued past a line end. + Bug #3150522. +
  • +
  • + Ruby folder handles here docs. + Feature #3118224. +
  • +
  • + SQL lexer allows '.' to be part of words. + Feature #3103129. +
  • +
  • + SQL folder handles case statements in more situations. + Feature #3135027. +
  • +
  • + SQL folder adds fold points inside expressions based on bracket structure. + Feature #3165488. +
  • +
  • + SQL folder drops fold.sql.exists property as 'exists' is handled automatically. + Bug #3164194. +
  • +
  • + SciTE only forwards properties to lexers when they have been explicitly set so the defaults set by lexers are used + rather than 0. +
  • +
  • + Mouse double click word selection chooses the word around the character under the mouse rather than + the inter-character position under the mouse. This makes double clicking select what the user is pointing + at and avoids selecting adjacent non-word characters. + Bug #3111174. +
  • +
  • + Fixed mouse double click to always perform word select, not line select. + Bug #3143635. +
  • +
  • + Right click cancels autocompletion. + Bug #3144531. +
  • +
  • + Fixed multiPaste to work when additionalSelectionTyping off. + Bug #3126221. +
  • +
  • + Fixed virtual space problems when text modified at caret. + Bug #3154986. +
  • +
  • + Fixed memory leak in lexer object code. + Bug #3133672. +
  • +
  • + Fixed SciTE on GTK+ search failure when using regular expression. + Bug #3156217. +
  • +
  • + Avoid unnecessary full window redraw for SCI_GOTOPOS. + Feature #3146650. +
  • +
  • + Avoid unnecessary redraw when indicator fill range makes no real change. +
  • +
+

+ Release 2.23 +

+
    +
  • + Released 7 December 2010. +
  • +
  • + On GTK+ version 2.22 and later, drawing is performed with Cairo rather than GDK. + This is in preparation for GTK+ 3.0 which will no longer support GDK drawing. + The appearance of some elements will be different with Cairo as it is anti-aliased and uses sub-pixel positioning. + Cairo may be turned on for GTK+ versions before 2.22 by defining USE_CAIRO although this has not + been extensively tested. +
  • +
  • + New lexer a68k for Motorola 68000 assembler. + Feature #3101598. +
  • +
  • + Borland C++ is no longer supported for building Scintilla or SciTE on Windows. +
  • +
  • + Performance improved when creating large rectangular selections. +
  • +
  • + PHP folder recognizes #region and #endregion comments. + Feature #3101624. +
  • +
  • + SQL lexer has a lexer.sql.numbersign.comment option to turn off use of '#' comments + as these are a non-standard feature only available in some implementations. + Feature #3098071. +
  • +
  • + SQL folder recognizes case statements and understands the fold.at.else property. + Bug #3104091. + Bug #3107362. +
  • +
  • + SQL folder fixes bugs with end statements when fold.sql.only.begin=1. + Bug #3104091. +
  • +
  • + SciTE on Windows bug fixed with multi-line tab bar not adjusting correctly when maximizing and demaximizing. + Bug #3097517. +
  • +
  • + Crash fixed on GTK+ when Scintilla widget destroyed while it still has an outstanding style idle pending. +
  • +
  • + Bug fixed where searching backwards in DBCS text (code page 936 or similar) failed to find occurrences at the start of the line. + Bug #3103936. +
  • +
  • + SciTE on Windows supports Unicode file names when executing help applications with winhelp and htmlhelp subsystems. +
  • +
+

+ Release 2.22 +

+
    +
  • + Released 27 October 2010. +
  • +
  • + SciTE includes support for integrating with Scintillua which allows lexers to be implemented in Lua as a + Parsing Expression Grammar (PEG). +
  • +
  • + Regular expressions allow use of '?' for non-greedy matches or to match 0 or 1 instances of an item. +
  • +
  • + SCI_CONTRACTEDFOLDNEXT added to allow rapid retrieval of folding state. +
  • +
  • + SCN_HOTSPOTRELEASECLICK notification added which is similar to SCN_HOTSPOTCLICK but occurs + when the mouse is released. + Feature #3082409. +
  • +
  • + Command added for centring current line in window. + Feature #3064696. +
  • +
  • + SciTE performance improved by not examining document for line ends when switching buffers and not + storing folds when folding turned off. +
  • +
  • + Bug fixed where scrolling to ensure the caret is visible did not take into account all pixels of the line. + Bug #3081721. +
  • +
  • + Bug fixed for autocompletion list overlapping text when WS_EX_CLIENTEDGE used. + Bug #3079778. +
  • +
  • + After autocompletion, the caret's X is updated. + Bug #3079114. +
  • +
  • + On Windows, default to the system caret blink time. + Feature #3079784. +
  • +
  • + PgUp/PgDn fixed to allow virtual space. + Bug #3077452. +
  • +
  • + Crash fixed when AddMark and AddMarkSet called with negative argument. + Bug #3075074. +
  • +
  • + Dwell notifications fixed so that they do not occur when the mouse is outside Scintilla. + Bug #3073481. +
  • +
  • + Bash lexer bug fixed for here docs starting with <<-. + Bug #3063822. +
  • +
  • + C++ lexer bug fixed for // comments that are continued onto a second line by a \. + Bug #3066031. +
  • +
  • + C++ lexer fixes wrong highlighting for float literals containing +/-. + Bug #3058924. +
  • +
  • + JavaScript lexer recognize regexes following return keyword.‎ + Bug #3062287. +
  • +
  • + Ruby lexer handles % quoting better and treats range dots as operators in 1..2 and 1...2. + Ruby folder handles "if" keyword used as a modifier even when it is separated from the modified statement by an escaped new line. + Bug #2093767. + Bug #3058496. +
  • +
  • + Bug fixed where upwards search failed with DBCS code pages. + Bug #3065912. +
  • +
  • + SciTE has a default Lua startup script name distributed in SciTEGlobal.properties. + No error message is displayed if this file does not exist. +
  • +
  • + SciTE on Windows tab control height is calculated better. + Bug #2635702. +
  • +
  • + SciTE on Windows uses better themed check buttons in find and replace strips. +
  • +
  • + SciTE on Windows fixes bug with Find strip appearing along with Incremental Find strip. +
  • +
  • + SciTE setting find.close.on.find added to allow preventing the Find dialog from closing. +
  • +
  • + SciTE on Windows attempts to rerun commands that fail by prepending them with "cmd.exe /c". + This allows commands built in to the command processor like "dir" to run. +
  • +
+

+ Release 2.21 +

+
    +
  • + Released 1 September 2010. +
  • +
  • + Asian Double Byte Character Set (DBCS) support improved. + Case insensitive search works and other operations are much faster. + Bug #2999125, + Bug #2774616, + Bug #2991942, + Bug #3005688. +
  • +
  • + Scintilla on GTK+ uses only non-deprecated APIs (for GTK+ 2.20) except for GdkFont and GdkFont use can be disabled + with the preprocessor symbol DISABLE_GDK_FONT. +
  • +
  • + IDocument interface used by lexers adds BufferPointer and GetLineIndentation methods. +
  • +
  • + On Windows, clicking sets focus before processing the click or sending notifications. +
  • +
  • + Bug on OS X (macosx platform) fixed where drag/drop overwrote clipboard. + Bug #3039732. +
  • +
  • + GTK+ drawing bug when the view was horizontally scrolled more than 32000 pixels fixed. +
  • +
  • + SciTE bug fixed with invoking Complete Symbol from output pane. + Bug #3050957. +
  • +
  • + Bug fixed where it was not possible to disable folding. + Bug #3040649. +
  • +
  • + Bug fixed with pressing Enter on a folded fold header line not opening the fold. + Bug #3043419. +
  • +
  • + SciTE 'Match case' option in find and replace user interfaces changed to 'Case sensitive' to allow use of 'v' + rather than 'c' as the mnemonic. +
  • +
  • + SciTE displays stack trace for Lua when error occurs.. + Bug #3051397. +
  • +
  • + SciTE on Windows fixes bug where double clicking on error message left focus in output pane. + Bug #1264835. +
  • +
  • + SciTE on Windows uses SetDllDirectory to avoid a security problem. +
  • +
  • + C++ lexer crash fixed with preprocessor expression that looked like division by 0. + Bug #3056825. +
  • +
  • + Haskell lexer improved. + Feature #3039490. +
  • +
  • + HTML lexing fixed around Django {% %} tags. + Bug #3034853. +
  • +
  • + HTML JavaScript lexing fixed when line end escaped. + Bug #3038381. +
  • +
  • + HTML lexer stores line state produced by a line on that line rather than on the next line. +
  • +
  • + Markdown lexer fixes infinite loop. + Bug #3045386. +
  • +
  • + MySQL folding bugs with END statements fixed. + Bug #3031742. +
  • +
  • + PowerShell lexer allows '_' as a word character. + Feature #3042228. +
  • +
  • + SciTE on GTK+ abandons processing of subsequent commands if a command.go.needs command fails. +
  • +
  • + When SciTE is closed, all buffers now receive an OnClose call. + Bug #3033857. +
  • +
+

+ Release 2.20 +

+
    +
  • + Released 30 July 2010. +
  • +
  • + Lexers are implemented as objects so that they may retain extra state. + The interfaces defined for this are tentative and may change before the next release. + Compatibility classes allow current lexers compiled into Scintilla to run with few changes. + The interface to external lexers has changed and existing external lexers will need to have changes + made and be recompiled. + A single lexer object is attached to a document whereas previously lexers were attached to views + which could lead to different lexers being used for split views with confusing results. +
  • +
  • + C++ lexer understands the preprocessor enough to grey-out inactive code due to conditional compilation. +
  • +
  • + SciTE can use strips within the main window for find and replace rather than dialogs. + On Windows SciTE always uses a strip for incremental search. +
  • +
  • + Lexer added for Txt2Tags language. + Feature #3018736. +
  • +
  • + Sticky caret feature enhanced with additional SC_CARETSTICKY_WHITESPACE mode . + Feature #3027559. +
  • +
  • + Bash lexer implements basic parsing of compound commands and constructs. + Feature #3033135. +
  • +
  • + C++ folder allows disabling explicit fold comments. +
  • +
  • + Perl folder works for array blocks, adjacent package statements, nested PODs, and terminates package folding at __DATA__, ^D and ^Z. + Feature #3030887. +
  • +
  • + PowerShell lexer supports multiline <# .. #> comments and adds 2 keyword classes. + Feature #3015176. +
  • +
  • + Lexing performed incrementally when needed by wrapping to make user interface more responsive. +
  • +
  • + SciTE setting replaceselection:yes works on GTK+. +
  • +
  • + SciTE Lua scripts calling io.open or io.popen on Windows have arguments treated as UTF-8 and converted to Unicode + so that non-ASCII file paths will work. Lua files with non-ASCII paths run. + Bug #3016951. +
  • +
  • + Crash fixed when searching for empty string. + Bug #3017572. +
  • +
  • + Bugs fixed with folding and lexing when Enter pressed at start of line. + Bug #3032652. +
  • +
  • + Bug fixed with line selection mode not affecting selection range. + Bug #3021480. +
  • +
  • + Bug fixed where indicator alpha was limited to 100 rather than 255. + Bug #3021473. +
  • +
  • + Bug fixed where changing annotation did not cause automatic redraw. +
  • +
  • + Regular expression bug fixed when a character range included non-ASCII characters. +
  • +
  • + Compilation failure with recent compilers fixed on GTK+. + Bug #3022027. +
  • +
  • + Bug fixed on Windows with multiple monitors where autocomplete pop up would appear off-screen + or straddling monitors. + Bug #3017512. +
  • +
  • + SciTE on Windows bug fixed where changing directory to a Unicode path failed. + Bug #3011987. +
  • +
  • + SciTE on Windows bug fixed where combo boxes were not allowing Unicode characters. + Bug #3012986. +
  • +
  • + SciTE on GTK+ bug fixed when dragging files into SciTE on KDE. + Bug #3026555. +
  • +
  • + SciTE bug fixed where closing untitled file could lose data if attempt to name file same as another buffer. + Bug #3011680. +
  • +
  • + COBOL number masks now correctly highlighted. + Bug #3012164. +
  • +
  • + PHP comments can include <?PHP without triggering state change. + Bug #2854183. +
  • +
  • + VHDL lexer styles unclosed string correctly. + Bug #3029627. +
  • +
  • + Memory leak fixed in list boxes on GTK+. + Bug #3007669. +
  • +
+

+ Release 2.12 +

+
    +
  • + Released 1 June 2010. +
  • +
  • + Drawing optimizations improve speed and fix some visible flashing when scrolling. +
  • +
  • + Copy Path command added to File menu in SciTE. + Feature #2986745. +
  • +
  • + Optional warning displayed by SciTE when saving a file which has been modified by another process. + Feature #2975041. +
  • +
  • + Flagship lexer for xBase languages updated to follow the language much more closely. + Feature #2992689. +
  • +
  • + HTML lexer highlights Django templates in more regions. + Feature #3002874. +
  • +
  • + Dropping files on SciTE on Windows, releases the drag object earlier and opens the files asynchronously, + leading to smoother user experience. + Feature #2986724. +
  • +
  • + SciTE HTML exports take the Use Monospaced Font setting into account. +
  • +
  • + SciTE window title "[n of m]" localised. +
  • +
  • + When new line inserted at start of line, markers are moved down. + Bug #2986727. +
  • +
  • + On Windows, dropped text has its line ends converted, similar to pasting. + Bug #3005328. +
  • +
  • + Fixed bug with middle-click paste in block select mode where text was pasted next to selection rather than at cursor. + Bug #2984460. +
  • +
  • + Fixed SciTE crash where a style had a size parameter without a value. + Bug #3003834. +
  • +
  • + Debug assertions in multiple lexers fixed. + Bug #3000566. +
  • +
  • + CSS lexer fixed bug where @font-face displayed incorrectly + Bug #2994224. +
  • +
  • + CSS lexer fixed bug where open comment caused highlighting error. + Bug #1683672. +
  • +
  • + Shell file lexer fixed highlight glitch with here docs where the first line is a comment. + Bug #2830239. +
  • +
  • + Bug fixed in SciTE openpath property that caused Open Selected File to fail to open the selected file. +
  • +
  • + Bug fixed in SciTE FileExt property when file name with no extension evaluated to whole path. +
  • +
  • + Fixed SciTE on Windows printing bug where the $(CurrentTime), $(CurrentPage) variables were not expanded. + Bug #2994612. +
  • +
  • + SciTE compiles for 64-bit Windows and runs without crashing. + Bug #2986312. +
  • +
  • + Full Screen mode in Windows Vista/7 improved to hide Start button and size borders a little better. + Bug #3002813. +
  • +
+

+ Release 2.11 +

+
    +
  • + Released 9 April 2010. +
  • +
  • + Fixes compatibility of Scintilla.h with the C language. +
  • +
  • + With a rectangular selection SCI_GETSELECTIONSTART and SCI_GETSELECTIONEND return limits of the + rectangular selection rather than the limits of the main selection. +
  • +
  • + When SciTE on Windows is minimized to tray, only takes a single click to restore rather than a double click. + Feature #981917. +
  • +
+

+ Release 2.10 +

+
    +
  • + Released 4 April 2010. +
  • +
  • + Version 1.x of GTK+ is no longer supported. +
  • +
  • + SciTE is no longer supported on Windows 95, 98 or ME. +
  • +
  • + Case-insensitive search works for non-ASCII characters in UTF-8 and 8-bit encodings. + Non-regex search in DBCS encodings is always case-sensitive. +
  • +
  • + Non-ASCII characters may be changed to upper and lower case. +
  • +
  • + SciTE on Windows can access all files including those with names outside the user's preferred character encoding. +
  • +
  • + SciTE may be extended with lexers written in Lua. +
  • +
  • + When there are multiple selections, the paste command can go either to the main selection or to each + selection. This is controlled with SCI_SETMULTIPASTE. +
  • +
  • + More forms of bad UTF-8 are detected including overlong sequences, surrogates, and characters outside + the valid range. Bad UTF-8 bytes are now displayed as 2 hex digits preceded by 'x'. +
  • +
  • + SCI_GETTAG retrieves the value of captured expressions within regular expression searches. +
  • +
  • + Django template highlighting added to the HTML lexer. + Feature #2974889. +
  • +
  • + Verilog line comments can be folded. +
  • +
  • + SciTE on Windows allows specifying a filter for the Save As dialog. + Feature #2943445. +
  • +
  • + Bug fixed when multiple selection disabled where rectangular selections could be expanded into multiple selections. + Bug #2948260. +
  • +
  • + Bug fixed when document horizontally scrolled and up/down-arrow did not return to the same + column after horizontal scroll occurred. + Bug #2950799. +
  • +
  • + Bug fixed to remove hotspot highlight when mouse is moved out of the document. Windows only fix. + Bug #2951353. +
  • +
  • + R lexer now performs case-sensitive check for keywords. + Bug #2956543. +
  • +
  • + Bug fixed on GTK+ where text disappeared when a wrap occurred. + Bug #2958043. +
  • +
  • + Bug fixed where regular expression replace cannot escape the '\' character by using '\\'. + Bug #2959876. +
  • +
  • + Bug fixed on GTK+ when virtual space disabled, middle-click could still paste text beyond end of line. + Bug #2971618. +
  • +
  • + SciTE crash fixed when double clicking on a malformed error message in the output pane. + Bug #2976551. +
  • +
  • + Improved performance on GTK+ when changing parameters associated with scroll bars to the same value. + Bug #2964357. +
  • +
  • + Fixed bug with pressing Shift+Tab with a rectangular selection so that it performs an un-indent + similar to how Tab performs an indent. +
  • +
+

+ Release 2.03 +

+
    +
  • + Released 14 February 2010. +
  • +
  • + Added SCI_SETFIRSTVISIBLELINE to match SCI_GETFIRSTVISIBLELINE. +
  • +
  • + Erlang lexer extended set of numeric bases recognised; separate style for module:function_name; detects + built-in functions, known module attributes, and known preprocessor instructions; recognizes EDoc and EDoc macros; + separates types of comments. + Bug #2942448. +
  • +
  • + Python lexer extended with lexer.python.strings.over.newline option that allows non-triple-quoted strings to extend + past line ends. This allows use of the Ren'Py language. + Feature #2945550. +
  • +
  • + Fixed bugs with cursor movement after deleting a rectangular selection. + Bug #2942131. +
  • +
  • + Fixed bug where calling SCI_SETSEL when there is a rectangular selection left + the additional selections selected. + Bug #2947064. +
  • +
  • + Fixed macro recording bug where not all bytes in multi-byte character insertions were reported through + SCI_REPLACESEL. +
  • +
  • + Fixed SciTE bug where using Ctrl+Enter followed by Ctrl+Space produced an autocompletion list + with only a single line containing all the identifiers. +
  • +
  • + Fixed SciTE on GTK+ bug where running a tool made the user interface completely unresponsive. +
  • +
  • + Fixed SciTE on Windows Copy to RTF bug. + Bug #2108574. +
  • +
+

+ Release 2.02 +

+
    +
  • + Released on 25 January 2010. +
  • +
  • + Markdown lexer added. + Feature #2844081. +
  • +
  • + On GTK+, include code that understands the ranges of lead bytes for code pages 932, 936, and 950 + so that most Chinese and Japanese text can be used on systems that are not set to the corresponding locale. +
  • +
  • + Allow changing the size of dots in visible whitespace using SCI_SETWHITESPACESIZE. + Feature #2839427. +
  • +
  • + Additional carets can be hidden with SCI_SETADDITIONALCARETSVISIBLE. +
  • +
  • + Can choose anti-aliased, non-anti-aliased or lcd-optimized text using SCI_SETFONTQUALITY. +
  • +
  • + Retrieve the current selected text in the autocompletion list with SCI_AUTOCGETCURRENTTEXT. +
  • +
  • + Retrieve the name of the current lexer with SCI_GETLEXERLANGUAGE. +
  • +
  • + Progress 4GL lexer improves handling of comments in preprocessor declaration. + Feature #2902206. +
  • +
  • + HTML lexer extended to handle Mako template language. +
  • +
  • + SQL folder extended for SQL Anywhere "EXISTS" and "ENDIF" keywords. + Feature #2887524. +
  • +
  • + SciTE adds APIPath and AbbrevPath variables. +
  • +
  • + SciTE on GTK+ uses pipes instead of temporary files for running tools. This should be more secure. +
  • +
  • + Fixed crash when calling SCI_STYLEGETFONT for a style which does not have a font set. + Bug #2857425. +
  • +
  • + Fixed crash caused by not having sufficient styles allocated after choosing a lexer. + Bug #2881279. +
  • +
  • + Fixed crash in SciTE using autocomplete word when word characters includes space. + Bug #2840141. +
  • +
  • + Fixed bug with handling upper-case file extensions SciTE on GTK+. +
  • +
  • + Fixed SciTE loading files from sessions with folded folds where it would not + be scrolled to the correct location. + Bug #2882775. +
  • +
  • + Fixed SciTE loading files from sessions when file no longer exists. + Bug #2883437. +
  • +
  • + Fixed SciTE export to HTML using the wrong background colour. +
  • +
  • + Fixed crash when adding an annotation and then adding a new line after the annotation. + Bug #2929708. +
  • +
  • + Fixed crash in SciTE setting a property to nil from Lua. +
  • +
  • + SCI_GETSELTEXT fixed to return correct length. + Bug #2929441. +
  • +
  • + Fixed text positioning problems with selection in some circumstances. +
  • +
  • + Fixed text positioning problems with ligatures on GTK+. +
  • +
  • + Fixed problem pasting into rectangular selection with caret at bottom caused text to go from the caret down + rather than replacing the selection. +
  • +
  • + Fixed problem replacing in a rectangular selection where only the final line was changed. +
  • +
  • + Fixed inability to select a rectangular area using Alt+Shift+Click at both corners. + Bug #2899746. +
  • +
  • + Fixed problem moving to start/end of a rectangular selection with left/right key. + Bug #2871358. +
  • +
  • + Fixed problem with Select All when there's a rectangular selection. + Bug #2930488. +
  • +
  • + Fixed SCI_LINEDUPLICATE on a rectangular selection to not produce multiple discontinuous selections. +
  • +
  • + Virtual space removed when performing delete word left or delete line left. + Virtual space converted to real space for delete word right. + Preserve virtual space when pressing Delete key. + Bug #2882566. +
  • +
  • + Fixed problem where Shift+Alt+Down did not move through wrapped lines. + Bug #2871749. +
  • +
  • + Fixed incorrect background colour when using coloured lines with virtual space. + Bug #2914691. +
  • +
  • + Fixed failure to display wrap symbol for SC_WRAPVISUALFLAGLOC_END_BY_TEXT. + Bug #2936108. +
  • +
  • + Fixed blank background colour with EOLFilled style on last line. + Bug #2890105. +
  • +
  • + Fixed problem in VB lexer with keyword at end of file. + Bug #2901239. +
  • +
  • + Fixed SciTE bug where double clicking on a tab closed the file. +
  • +
  • + Fixed SciTE brace matching commands to only work when the caret is next to the brace, not when + it is in virtual space. + Bug #2885560. +
  • +
  • + Fixed SciTE on Windows Vista to access files in the Program Files directory rather than allow Windows + to virtualize access. + Bug #2916685. +
  • +
  • + Fixed NSIS folder to handle keywords that start with '!'. + Bug #2872157. +
  • +
  • + Changed linkage of Scintilla_LinkLexers to "C" so that it can be used by clients written in C. + Bug #2844718. +
  • +
+

+ Release 2.01 +

+
    +
  • + Released on 19 August 2009. +
  • +
  • + Fix to positioning rectangular paste when viewing line ends. +
  • +
  • + Don't insert new lines and indentation for line ends at end of rectangular paste. +
  • +
  • + When not in additional selection typing mode, cutting a rectangular selection removes all of the selected text. +
  • +
  • + Rectangular selections are copied to the clipboard in document order, not in the order of selection. +
  • +
  • + SCI_SETCURRENTPOS and SCI_SETANCHOR work in rectangular mode. +
  • +
  • + On GTK+, drag and drop to a later position in the document now drops at the position. +
  • +
  • + Fix bug where missing property did not use default value. +
  • +
+

+ Release 2.0 +

+
    +
  • + Released on 11 August 2009. +
  • +
  • + Multiple pieces of text can be selected simultaneously by holding control while dragging the mouse. + Typing, backspace and delete may affect all selections together. +
  • +
  • + Virtual space allows selecting beyond the last character on a line. +
  • +
  • + SciTE on GTK+ path bar is now optional and defaults to off. +
  • +
  • + MagikSF lexer recognises numbers correctly. +
  • +
  • + Folding of Python comments and blank lines improved. Bug #210240. +
  • +
  • + Bug fixed where background colour of last character in document leaked past that character. +
  • +
  • + Crash fixed when adding marker beyond last line in document. Bug #2830307. +
  • +
  • + Resource leak fixed in SciTE for Windows when printing fails. Bug #2816524. +
  • +
  • + Bug fixed on Windows where the system caret was destroyed during destruction when another window + was using the system caret. Bug #2830223. +
  • +
  • + Bug fixed where indentation guides were drawn over text when the indentation used a style with a different + space width to the default style. +
  • +
  • + SciTE bug fixed where box comment added a bare line feed rather than the chosen line end. Bug #2818104. +
  • +
  • + Reverted fix that led to wrapping whole document when displaying the first line of the document. +
  • +
  • + Export to LaTeX in SciTE fixed to work in more cases and not use as much space. Bug #1286548. +
  • +
  • + Bug fixed where EN_CHANGE notification was sent when performing a paste operation in a + read-only document. Bug #2825485. +
  • +
  • + Refactored code so that Scintilla exposes less of its internal implementation and uses the C++ standard + library for some basic collections. Projects that linked to Scintilla's SString or PropSet classes + should copy this code from a previous version of Scintilla or from SciTE. +
  • +
+

+ Release 1.79 +

+
    +
  • + Released on 1 July 2009. +
  • +
  • + Memory exhaustion and other exceptions handled by placing an error value into the + status property rather than crashing. + Scintilla now builds with exception handling enabled and requires exception handling to be enabled.
    + This is a major change and application developers should consider how they will deal with Scintilla exhausting + memory since Scintilla may not be in a stable state. +
  • +
  • + Deprecated APIs removed. The symbols removed are: +
      +
    • SCI_SETCARETPOLICY
    • +
    • CARET_CENTER
    • +
    • CARET_XEVEN
    • +
    • CARET_XJUMPS
    • +
    • SC_FOLDFLAG_BOX
    • +
    • SC_FOLDLEVELBOXHEADERFLAG
    • +
    • SC_FOLDLEVELBOXFOOTERFLAG
    • +
    • SC_FOLDLEVELCONTRACTED
    • +
    • SC_FOLDLEVELUNINDENT
    • +
    • SCN_POSCHANGED
    • +
    • SCN_CHECKBRACE
    • +
    • SCLEX_ASP
    • +
    • SCLEX_PHP
    • +
    +
  • +
  • + Cocoa platform added. +
  • +
  • + Names of struct types in Scintilla.h now start with "Sci_" to avoid possible clashes with platform + definitions. Currently, the old names still work but these will be phased out. +
  • +
  • + When lines are wrapped, subsequent lines may be indented to match the indent of the initial line, + or one more indentation level. Feature #2796119. +
  • +
  • + APIs added for finding the character at a point rather than an inter-character position. Feature #2646738. +
  • +
  • + A new marker SC_MARK_BACKGROUND_UNDERLINE is drawn in the text area as an underline + the full width of the window. +
  • +
  • + Batch file lexer understands variables surrounded by '!'. +
  • +
  • + CAML lexer also supports SML. +
  • +
  • + D lexer handles string and numeric literals more accurately. Feature #2793782. +
  • +
  • + Forth lexer is now case-insensitive and better supports numbers like $hex and %binary. Feature #2804894. +
  • +
  • + Lisp lexer treats '[', ']', '{', and '}' as balanced delimiters which is common usage. Feature #2794989. +
    + It treats keyword argument names as being equivalent to symbols. Feature #2794901. +
  • +
  • + Pascal lexer bug fixed to prevent hang when 'interface' near beginning of file. Bug #2802863. +
  • +
  • + Perl lexer bug fixed where previous lexical states persisted causing "/" special case styling and + subroutine prototype styling to not be correct. Bug #2809168. +
  • +
  • + XML lexer fixes bug where Unicode entities like '&—' were broken into fragments. Bug #2804760. +
  • +
  • + SciTE on GTK+ enables scrolling the tab bar on recent versions of GTK+. Feature #2061821. +
  • +
  • + SciTE on Windows allows tab bar tabs to be reordered by drag and drop. +
  • +
  • + Unit test script for Scintilla on Windows included with source code. +
  • +
  • + User defined menu items are now localised when there is a matching translation. +
  • +
  • + Width of icon column of autocompletion lists on GTK+ made more consistent. +
  • +
  • + Bug with slicing UTF-8 text into character fragments when there is a sequence of 100 or more 3 byte characters. Bug #2780566. +
  • +
  • + Folding bugs introduced in 1.78 fixed. Some of the fix was generic and there was also a specific fix for C++. +
  • +
  • + Bug fixed where a rectangular paste was not padding the line with sufficient spaces to align the pasted text. +
  • +
  • + Bug fixed with showing all text on each line of multi-line annotations when styling the whole annotation using SCI_ANNOTATIONSETSTYLE. Bug #2789430. +
  • +
+

+ Release 1.78 +

+
    +
  • + Released on 28 April 2009. +
  • +
  • + Annotation lines may be added to each line. +
  • +
  • + A text margin may be defined with different text on each line. +
  • +
  • + Application actions may be added to the undo history. +
  • +
  • + Can query the symbol defined for a marker. + An available symbol added for applications to indicate that plugins may allocate a marker. +
  • +
  • + Can increase the amount of font ascent and descent. +
  • +
  • + COBOL lexer added. Feature #2127406. +
  • +
  • + Nimrod lexer added. Feature #2642620. +
  • +
  • + PowerPro lexer added. Feature #2195308. +
  • +
  • + SML lexer added. Feature #2710950. +
  • +
  • + SORCUS Installation file lexer added. Feature #2343375. +
  • +
  • + TACL lexer added. Feature #2127406. +
  • +
  • + TAL lexer added. Feature #2127406. +
  • +
  • + Rewritten Pascal lexer with improved folding and other fixes. Feature #2190650. +
  • +
  • + INDIC_ROUNDBOX translucency level can be modified. Feature #2586290. +
  • +
  • + C++ lexer treats angle brackets in #include directives as quotes when styling.within.preprocessor. Bug #2551033. +
  • +
  • + Inno Setup lexer is sensitive to whether within the [Code] section and handles comments better. Bug #2552973. +
  • +
  • + HTML lexer does not go into script mode when script tag is self-closing. +
  • +
  • + HTML folder fixed where confused by comments when fold.html.preprocessor off. Bug #2532774. +
  • +
  • + Perl lexer fixes problem with string matching caused by line endings. Bug #2648342. +
  • +
  • + Progress lexer fixes problem with "last-event:function" phrase. Bug #2483619. +
  • +
  • + Properties file lexer extended to handle RFC2822 text when lexer.props.allow.initial.spaces on. +
  • +
  • + Python lexer adds options for Python 3 and Cython. +
  • +
  • + Shell lexer fixes heredoc problem caused by line endings. Bug #2635257. +
  • +
  • + TeX lexer handles comment at end of line correctly. Bug #2698766. +
  • +
  • + SciTE retains selection range when performing a replace selection command. Feature #2339160. +
  • +
  • + SciTE definition of word characters fixed to match documentaiton. Bug #2464531. +
  • +
  • + SciTE on GTK+ performing Search or Replace when dialog already shown now brings dialog to foreground. + Bug #2634224. +
  • +
  • + Fixed encoding bug with calltips on GTK+. +
  • +
  • + Block caret drawn in correct place on wrapped lines. Bug #2126144. +
  • +
  • + Compilation for 64 bit Windows works using MinGW. Bug #2515578. +
  • +
  • + Incorrect memory freeing fixed on OS X. + Bug #2354098, + Bug #2671749. +
  • +
  • + SciTE on GTK+ crash fixed on startup when child process exits before initialisation complete. + Bug #2716987. +
  • +
  • + Crash fixed when AutoCompleteGetCurrent called with no active autocompletion. +
  • +
  • + Flickering diminished when pressing Tab. Bug #2723006. +
  • +
  • + Namespace compilation issues with GTK+ on OS X fixed. +
  • +
  • + Increased maximum length of SciTE's Language menu on GTK+ to 100 items. Bug #2528241. +
  • +
  • + Fixed incorrect Python lexing for multi-line continued strings. Bug #2450963. +
  • +
+

+ Release 1.77 +

+
    +
  • + Released on 18 October 2008. +
  • +
  • + Direct temporary access to Scintilla's text buffer to allow simple efficient interfacing + to libraries like regular expression libraries. +
  • +
  • + Scintilla on Windows can interpret keys as Unicode even when a narrow character + window with SCI_SETKEYSUNICODE. +
  • +
  • + Notification sent when autocompletion cancelled. +
  • +
  • + MySQL lexer added. +
  • +
  • + Lexer for gettext .po files added. +
  • +
  • + Abaqus lexer handles program structure more correctly. +
  • +
  • + Assembler lexer works with non-ASCII text. +
  • +
  • + C++ lexer allows mixed case doc comment tags. +
  • +
  • + CSS lexer updated and works with non-ASCII. +
  • +
  • + Diff lexer adds style for changed lines, handles subversion diffs better and + fixes styling and folding for lines containing chunk dividers ("---"). +
  • +
  • + FORTRAN lexer accepts more styles of compiler directive. +
  • +
  • + Haskell lexer allows hexadecimal literals. +
  • +
  • + HTML lexer improves PHP and JavaScript folding. + PHP heredocs, nowdocs, strings and comments processed more accurately. + Internet Explorer's non-standard >comment< tag supported. + Script recognition in XML can be controlled with lexer.xml.allow.scripts property. +
  • +
  • + Lua lexer styles last character correctly. +
  • +
  • + Perl lexer update. +
  • +
  • + Comment folding implemented for Ruby. +
  • +
  • + Better TeX folding. +
  • +
  • + Verilog lexer updated. +
  • +
  • + Windows Batch file lexer handles %~ and %*. +
  • +
  • + YAML lexer allows non-ASCII text. +
  • +
  • + SciTE on GTK+ implements "Replace in Buffers" in advanced mode. +
  • +
  • + The extender OnBeforeSave method can override the default file saving behaviour by retuning true. +
  • +
  • + Window position and recent files list may be saved into the session file. +
  • +
  • + Right button press outside the selection moves the caret. +
  • +
  • + SciTE load.on.activate works when closing a document reveals a changed document. +
  • +
  • + SciTE bug fixed where eol.mode not used for initial buffer. +
  • +
  • + SciTE bug fixed where a file could be saved as the same name as another + buffer leading to confusing behaviour. +
  • +
  • + Fixed display bug for long lines in same style on Windows. +
  • +
  • + Fixed SciTE crash when finding matching preprocessor command used on some files. +
  • +
  • + Drawing performance improved for files with many blank lines. +
  • +
  • + Folding bugs fixed where changing program text produced a decrease in fold level on a fold header line. +
  • +
  • + Clearing document style now clears all indicators. +
  • +
  • + SciTE's embedded Lua updated to 5.1.4. +
  • +
  • + SciTE will compile with versions of GTK+ before 2.8 again. +
  • +
  • + SciTE on GTK+ bug fixed where multiple files not opened. +
  • +
  • + Bug fixed with SCI_VCHOMEWRAP and SCI_VCHOMEWRAPEXTEND on white last line. +
  • +
  • + Regular expression bug fixed where "^[^(]+$" matched empty lines. +
  • +
+

+ Release 1.76 +

+
    +
  • + Released on 16 March 2008. +
  • +
  • + Support for PowerShell. +
  • +
  • + Lexer added for Magik. +
  • +
  • + Director extension working on GTK+. +
  • +
  • + Director extension may set focus to SciTE through "focus:" message on GTK+. +
  • +
  • + C++ folder handles final line better in some cases. +
  • +
  • + SCI_COPYALLOWLINE added which is similar to SCI_COPY except that if the selection is empty then + the line holding the caret is copied. On Windows an extra clipboard format allows pasting this as a whole + line before the current selection. This behaviour is compatible with Visual Studio. +
  • +
  • + On Windows, the horizontal scroll bar can handle wider files. +
  • +
  • + On Windows, a system palette leak was fixed. Should not affect many as palette mode is rarely used. +
  • +
  • + Install command on GTK+ no longer tries to set explicit owner. +
  • +
  • + Perl lexer handles defined-or operator "//". +
  • +
  • + Octave lexer fixes "!=" operator. +
  • +
  • + Optimized selection change drawing to not redraw as much when not needed. +
  • +
  • + SciTE on GTK+ no longer echoes Lua commands so is same as on Windows. +
  • +
  • + Automatic vertical scrolling limited to one line at a time so is not too fast. +
  • +
  • + Crash fixed when line states set beyond end of line states. This occurred when lexers did not + set a line state for each line. +
  • +
  • + Crash in SciTE on Windows fixed when search for 513 character string fails. +
  • +
  • + SciTE disables translucent features on Windows 9x due to crashes reported when using translucency. +
  • +
  • + Bug fixed where whitespace background was not seen on wrapped lines. +
  • +
+

+ Release 1.75 +

+
    +
  • + Released on 22 November 2007. +
  • +
  • + Some WordList and PropSet functionality moved from Scintilla to SciTE. + Projects that link to Scintilla's code for these classes may need to copy + code from SciTE. +
  • +
  • + Borland C++ can no longer build Scintilla. +
  • +
  • + Invalid bytes in UTF-8 mode are displayed as hex blobs. This also prevents crashes due to + passing invalid UTF-8 to platform calls. +
  • +
  • + Indentation guides enhanced to be visible on completely empty lines when possible. +
  • +
  • + The horizontal scroll bar may grow to match the widest line displayed. +
  • +
  • + Allow autocomplete pop ups to appear outside client rectangle in some cases. +
  • +
  • + When line state changed, SC_MOD_CHANGELINESTATE modification notification sent and + margin redrawn. +
  • +
  • + SciTE scripts can access the menu command values IDM_*. +
  • +
  • + SciTE's statement.end property has been implemented again. +
  • +
  • + SciTE shows paths and matches in different styles for Find In Files. +
  • +
  • + Incremental search in SciTE for Windows is modeless to make it easier to exit. +
  • +
  • + Folding performance improved. +
  • +
  • + SciTE for GTK+ now includes a Browse button in the Find In Files dialog. +
  • +
  • + On Windows versions that support Unicode well, Scintilla is a wide character window + which allows input for some less common languages like Armenian, Devanagari, + Tamil, and Georgian. To fully benefit, applications should use wide character calls. +
  • +
  • + Lua function names are exported from SciTE to allow some extension libraries to work. +
  • +
  • + Lexers added for Abaqus, Ansys APDL, Asymptote, and R. +
  • +
  • + SCI_DELWORDRIGHTEND added for closer compatibility with GTK+ entry widget. +
  • +
  • + The styling buffer may now use all 8 bits in each byte for lexical states with 0 bits for indicators. +
  • +
  • + Multiple characters may be set for SciTE's calltip.<lexer>.parameters.start property. +
  • +
  • + Bash lexer handles octal literals. +
  • +
  • + C++/JavaScript lexer recognises regex literals in more situations. +
  • +
  • + Haskell lexer fixed for quoted strings. +
  • +
  • + HTML/XML lexer does not notice XML indicator if there is + non-whitespace between the "<?" and "XML". + ASP problem fixed where </ is used inside a comment. +
  • +
  • + Error messages from Lua 5.1 are recognised. +
  • +
  • + Folding implemented for Metapost. +
  • +
  • + Perl lexer enhanced for handling minus-prefixed barewords, + underscores in numeric literals and vector/version strings, + ^D and ^Z similar to __END__, + subroutine prototypes as a new lexical class, + formats and format blocks as new lexical classes, and + '/' suffixed keywords and barewords. +
  • +
  • + Python lexer styles all of a decorator in the decorator style rather than just the name. +
  • +
  • + YAML lexer styles colons as operators. +
  • +
  • + Fixed SciTE bug where undo would group together multiple separate modifications. +
  • +
  • + Bug fixed where setting background colour of calltip failed. +
  • +
  • + SciTE allows wildcard suffixes for file pattern based properties. +
  • +
  • + SciTE on GTK+ bug fixed where user not prompted to save untitled buffer. +
  • +
  • + SciTE bug fixed where property values from one file were not seen by lower priority files. +
  • +
  • + Bug fixed when showing selection with a foreground colour change which highlighted + an incorrect range in some positions. +
  • +
  • + Cut now invokes SCN_MODIFYATTEMPTRO notification. +
  • +
  • + Bug fixed where caret not shown at beginning of wrapped lines. + Caret made visible in some cases after wrapping and scroll bar updated after wrapping. +
  • +
  • + Modern indicators now work on wrapped lines. +
  • +
  • + Some crashes fixed for 64-bit GTK+. +
  • +
  • + On GTK+ clipboard features improved for VMWare tools copy and paste. + SciTE exports the clipboard more consistently on shut down. +
  • +
+

+ Release 1.74 +

+
    +
  • + Released on 18 June 2007. +
  • +
  • + OS X support. +
  • +
  • + Indicators changed to be a separate data structure allowing more indicators. Storing indicators in high bits + of styling bytes is deprecated and will be removed in the next version. +
  • +
  • + Unicode support extended to all Unicode characters not just the Basic Multilingual Plane. +
  • +
  • + Performance improved on wide lines by breaking long runs in a single style into shorter segments. +
  • +
  • + Performance improved by caching layout of short text segments. +
  • +
  • + SciTE includes Lua 5.1. +
  • +
  • + Caret may be displayed as a block. +
  • +
  • + Lexer added for GAP. +
  • +
  • + Lexer added for PL/M. +
  • +
  • + Lexer added for Progress. +
  • +
  • + SciTE session files have changed format to be like other SciTE .properties files + and now use the extension .session. + Bookmarks and folds may optionally be saved in session files. + Session files created with previous versions of SciTE will not load into this version. +
  • +
  • + SciTE's extension and scripting interfaces add OnKey, OnDwellStart, and OnClose methods. +
  • +
  • + On GTK+, copying to the clipboard does not include the text/urilist type since this caused problems when + pasting into Open Office. +
  • +
  • + On GTK+, Scintilla defaults caret blink rate to platform preference. +
  • +
  • + Dragging does not start until the mouse has been dragged a certain amount. + This stops spurious drags when just clicking inside the selection. +
  • +
  • + Bug fixed where brace highlight not shown when caret line background set. +
  • +
  • + Bug fixed in Ruby lexer where out of bounds access could occur. +
  • +
  • + Bug fixed in XML folding where tags were not being folded because they are singletons in HTML. +
  • +
  • + Bug fixed when many font names used. +
  • +
  • + Layout bug fixed on GTK+ where fonts have ligatures available. +
  • +
  • + Bug fixed with SCI_LINETRANSPOSE on a blank line. +
  • +
  • + SciTE hang fixed when using UNC path with directory properties feature. +
  • +
  • + Bug on Windows fixed by examining dropped text for Unicode even in non-Unicode mode so it + can work when source only provides Unicode or when using an encoding different from the + system default. +
  • +
  • + SciTE bug on GTK+ fixed where Stop Executing did not work when more than a single process started. +
  • +
  • + SciTE bug on GTK+ fixed where mouse wheel was not switching between buffers. +
  • +
  • + Minor line end fix to PostScript lexer. +
  • +
+

+ Release 1.73 +

+
    +
  • + Released on 31 March 2007. +
  • +
  • + SciTE adds a Directory properties file to configure behaviour for files in a directory and its subdirectories. +
  • +
  • + Style changes may be made during text modification events. +
  • +
  • + Regular expressions recognize \d, \D, \s, \S, \w, \W, and \xHH. +
  • +
  • + Support for cmake language added. +
  • +
  • + More Scintilla properties can be queried. +
  • +
  • + Edge line drawn under text. +
  • +
  • + A savesession command added to SciTE director interface. +
  • +
  • + SciTE File | Encoding menu item names changed to be less confusing. +
  • +
  • + SciTE on GTK+ dialog buttons reordered to follow guidelines. +
  • +
  • + SciTE on GTK+ removed GTK+ 1.x compatible file dialog code. +
  • +
  • + SciTE on GTK+ recognises key names KeypadMultiply and KeypadDivide. +
  • +
  • + Background colour of line wrapping visual flag changed to STYLE_DEFAULT. +
  • +
  • + Makefile lexing enhanced for ':=' operator and when lines start with tab. +
  • +
  • + TADS3 lexer and folder improved. +
  • +
  • + SCN_DOUBLECLICK notification may set SCI_SHIFT, SCI_CTRL, and SCI_ALT flags on modifiers field. +
  • +
  • + Slow folding of large constructs in Python fixed. +
  • +
  • + MSSQL folding fixed to be case-insensitive and fold at more keywords. +
  • +
  • + SciTE's brace matching works better for HTML. +
  • +
  • + Determining API list items checks for specified parameters start character before default '('. +
  • +
  • + Hang fixed in HTML lexer. +
  • +
  • + Bug fixed in with LineTranspose command where markers could move to different line. +
  • +
  • + Memory released when buffer completely emptied. +
  • +
  • + If translucency not available on Windows, draw rectangular outline instead. +
  • +
  • + Bash lexer handles "-x" in "--x-includes..." better. +
  • +
  • + AutoIt3 lexer fixes string followed by '+'. +
  • +
  • + LinesJoin fixed where it stopped early due to not adjusting for inserted spaces.. +
  • +
  • + StutteredPageDown fixed when lines wrapped. +
  • +
  • + FormatRange fixed to not double count line number width which could lead to a large space. +
  • +
  • + SciTE Export As PDF and Latex commands fixed to format floating point numbers with '.' even in locales + that use ','. +
  • +
  • + SciTE bug fixed where File | New could produce buffer with contents of previous file when using read-only mode. +
  • +
  • + SciTE retains current scroll position when switching buffers and fold.on.open set. +
  • +
  • + SciTE crash fixed where '*' used to invoke parameters dialog. +
  • +
  • + SciTE bugs when writing large UCS-2 files fixed. +
  • +
  • + Bug fixed when scrolling inside a SCN_PAINTED event by invalidating window + rather than trying to perform synchronous painting. +
  • +
  • + SciTE for GTK+ View | Full Screen works on recent versions of GTK+. +
  • +
  • + SciTE for Windows enables and disables toolbar commands correctly. +
  • +
+

+ Release 1.72 +

+
    +
  • + Released on 15 January 2007. +
  • +
  • + Performance of per-line data improved. +
  • +
  • + SC_STARTACTION flag set on the first modification notification in an undo + transaction to help synchronize the container's undo stack with Scintilla's. +
  • +
  • + On GTK+ drag and drop defaults to move rather than copy. +
  • +
  • + Scintilla supports extending appearance of selection to right hand margin. +
  • +
  • + Incremental search available on GTK+. +
  • +
  • + SciTE Indentation Settings dialog available on GTK+ and adds a "Convert" button. +
  • +
  • + Find in Files can optionally ignore binary files or directories that start with ".". +
  • +
  • + Lexer added for "D" language. +
  • +
  • + Export as HTML shows folding with underline lines and +/- symbols. +
  • +
  • + Ruby lexer interprets interpolated strings as expressions. +
  • +
  • + Lua lexer fixes some cases of numeric literals. +
  • +
  • + C++ folder fixes bug with "@" in doc comments. +
  • +
  • + NSIS folder handles !if and related commands. +
  • +
  • + Inno setup lexer adds styling for single and double quoted strings. +
  • +
  • + Matlab lexer handles backslashes in string literals correctly. +
  • +
  • + HTML lexer fixed to allow "?>" in comments in Basic script. +
  • +
  • + Added key codes for Windows key and Menu key. +
  • +
  • + Lua script method scite.MenuCommand(x) performs a menu command. +
  • +
  • + SciTE bug fixed with box comment command near start of file setting selection to end of file. +
  • +
  • + SciTE on GTK+, fixed loop that occurred with automatic loading for an unreadable file. +
  • +
  • + SciTE asks whether to save files when Windows shuts down. +
  • +
  • + Save Session on Windows now defaults the extension to "ses". +
  • +
  • + Bug fixed with single character keywords. +
  • +
  • + Fixed infinite loop for SCI_GETCOLUMN for position beyond end of document. +
  • +
  • + Fixed failure to accept typing on Solaris/GTK+ when using default ISO-8859-1 encoding. +
  • +
  • + Fixed warning from Lua in SciTE when creating a new buffer when already have + maximum number of buffers open. +
  • +
  • + Crash fixed with "%%" at end of batch file. +
  • +
+

+ Release 1.71 +

+
    +
  • + Released on 21 August 2006. +
  • + +
  • + Double click notification includes line and position. +
  • +
  • + VB lexer bugs fixed for preprocessor directive below a comment or some other states and + to use string not closed style back to the starting quote when there are internal doubled quotes. +
  • +
  • + C++ lexer allows identifiers to contain '$' and non-ASCII characters such as UTF-8. + The '$' character can be disallowed with lexer.cpp.allow.dollars=0. +
  • +
  • + Perl lexer allows UTF-8 identifiers and has some other small improvements. +
  • +
  • + SciTE's $(CurrentWord) uses word.characters.<filepattern> to define the word + rather than a hardcoded list of word characters. +
  • +
  • + SciTE Export as HTML adds encoding information for UTF-8 file and fixes DOCTYPE. +
  • +
  • + SciTE session and .recent files default to the user properties directory rather than global + properties directory. +
  • +
  • + Left and right scroll events handled correctly on GTK+ and horizontal scroll bar has more sensible + distances for page and arrow clicks. +
  • +
  • + SciTE on GTK+ tab bar fixed to work on recent versions of GTK+. +
  • +
  • + On GTK+, if the approximate character set conversion is unavailable, a second attempt is made + without approximations. This may allow keyboard input and paste to work on older systems. +
  • +
  • + SciTE on GTK+ can redefine the Insert key. +
  • +
  • + SciTE scripting interface bug fixed where some string properties could not be changed. +
  • +
+

+ Release 1.70 +

+
    +
  • + Released on 20 June 2006. +
  • +
  • + On GTK+, character set conversion is performed using an option that allows approximate conversions rather + than failures when a character can not be converted. This may lead to similar characters being inserted or + when no similar character is available a '?' may be inserted. +
  • +
  • + On GTK+, the internationalised IM (Input Method) feature is used for all typed input for all character sets. +
  • +
  • + Scintilla has new margin types SC_MARGIN_BACK and SC_MARGIN_FORE that use the default + style's background and foreground colours (normally white and black) as the background to the margin. +
  • +
  • + Scintilla/GTK+ allows file drops on Windows when drop is of type DROPFILES_DND + as well as text/uri-list. +
  • +
  • + Code page can only be set to one of the listed valid values. +
  • +
  • + Text wrapping fixed for cases where insertion was not wide enough to trigger + wrapping before being styled but was after styling. +
  • +
  • + SciTE find marks are removed before printing or exporting to avoid producing incorrect styles. +
  • +
+

+ Release 1.69 +

+
    +
  • + Released on 29 May 2006. +
  • +
  • + SciTE supports z-order based buffer switching on Ctrl+Tab. +
  • +
  • + Translucent support for selection and whole line markers. +
  • +
  • + SciTE may have per-language abbreviations files. +
  • +
  • + Support for Spice language. +
  • +
  • + On GTK+ autocompletion lists are optimised and use correct selection colours. +
  • +
  • + On GTK+ the URI data type is preferred in drag and drop so that applications + will see files dragged from the shell rather than dragging the text of the file name + into the document. +
  • +
  • + Increased number of margins to 5. +
  • +
  • + Basic lexer allows include directive $include: "file name". +
  • +
  • + SQL lexer no longer bases folding on indentation. +
  • +
  • + Line ends are transformed when copied to clipboard on + Windows/GTK+2 as well as Windows/GTK+ 1. +
  • +
  • + Lexing code masks off the indicator bits on the start style before calling the lexer + to avoid confusing the lexer when an application has used an indicator. +
  • +
  • + SciTE savebefore:yes only saves the file when it has been changed. +
  • +
  • + SciTE adds output.initial.hide setting to allow setting the size of the output pane + without it showing initially. +
  • +
  • + SciTE on Windows Go To dialog allows line number with more digits. +
  • +
  • + Bug in HTML lexer fixed where a segment of PHP could switch scripting language + based on earlier text on that line. +
  • +
  • + Memory bug fixed when freeing regions on GTK+. + Other minor bugs fixed on GTK+. +
  • +
  • + Deprecated GTK+ calls in Scintilla replaced with current calls. +
  • +
  • + Fixed a SciTE bug where closing the final buffer, if read-only, left the text present in an + untitled buffer. +
  • +
  • + Bug fixed in bash lexer that prevented folding. +
  • +
  • + Crash fixed in bash lexer when backslash at end of file. +
  • +
  • + Crash on recent releases of GTK+ 2.x avoided by changing default font from X + core font to Pango font "!Sans". +
  • +
  • + Fix for SciTE properties files where multiline properties continued over completely blank lines. +
  • +
  • + Bug fixed in SciTE/GTK+ director interface where more data available than + buffer size. +
  • +
  • + Minor visual fixes to SciTE splitter on GTK+. +
  • +
+

+ Release 1.68 +

+
    +
  • + Released on 9 March 2006. +
  • +
  • + Translucent drawing implemented for caret line and box indicators. +
  • +
  • + Lexer specifically for TCL is much more accurate than reusing C++ lexer. +
  • +
  • + Support for Inno Setup scripts. +
  • +
  • + Support for Opal language. +
  • +
  • + Calltips may use a new style, STYLE_CALLTIP which allows choosing a + different font for calltips. +
  • +
  • + Python lexer styles comments on decorators. +
  • +
  • + HTML lexer refined handling of "?>" and "%>" within server + side scripts. +
  • +
  • + Batch file lexer improved. +
  • +
  • + Eiffel lexer doesn't treat '.' as a name character. +
  • +
  • + Lua lexer handles length operator, #, and hex literals. +
  • +
  • + Properties file lexer has separate style for keys. +
  • +
  • + PL/SQL folding improved. +
  • +
  • + SciTE Replace dialog always searches in forwards direction. +
  • +
  • + SciTE can detect language of file from initial #! line. +
  • +
  • + SciTE on GTK+ supports output.scroll=2 setting. +
  • +
  • + SciTE can perform an import a properties file from the command line. +
  • +
  • + Set of word characters used for regular expression \< and \>. +
  • +
  • + Bug fixed with SCI_COPYTEXT stopping too early. +
  • +
  • + Bug fixed with splitting lines so that all lines are split. +
  • +
  • + SciTE calls OnSwitchFile when closing one buffer causes a switch to another. +
  • +
  • + SciTE bug fixed where properties were being reevaluated without good reason + after running a macro. +
  • +
  • + Crash fixed when clearing document with some lines contracted in word wrap mode. +
  • +
  • + Palette expands as more entries are needed. +
  • +
  • + SCI_POSITIONFROMPOINT returns more reasonable value when close to + last text on a line. +
  • +
  • + On Windows, long pieces of text may be drawn in segments if they fail to draw + as a whole. +
  • +
  • + Bug fixed with bad drawing when some visual changes made inside SCN_UPDATEUI + notification. +
  • +
  • + SciTE bug fixed with groupundo setting. +
  • +
+

+ Release 1.67 +

+
    +
  • + Released on 17 December 2005. +
  • +
  • + Scintilla checks the paint region more accurately when seeing if an area is being + repainted. Platform layer implementations may need to change for this to take + effect. This fixes some drawing and styling bugs. Also optimized some parts of + marker code to only redraw the line of the marker rather than whole of the margin. +
  • +
  • + Quoted identifier style for SQL. SQL folding performed more simply. +
  • +
  • + Ruby lexer improved to better handle here documents and non-ASCII + characters. +
  • +
  • + Lua lexer supports long string and block comment syntax from Lua 5.1. +
  • +
  • + Bash lexer handles here documents better. +
  • +
  • + JavaScript lexing recognises regular expressions more accurately and includes flag + characters in the regular expression style. This is both in JavaScript files and when + JavaScript is embedded in HTML. +
  • +
  • + Scintilla API provided to reveal how many style bits are needed for the + current lexer. +
  • +
  • + Selection duplicate added. +
  • +
  • + Scintilla API for adding a set of markers to a line. +
  • +
  • + DBCS encodings work on Windows 9x. +
  • +
  • + Convention defined for property names to be used by lexers and folders + so they can be automatically discovered and forwarded from containers. +
  • +
  • + Default bookmark in SciTE changed to a blue sphere image. +
  • +
  • + SciTE stores the time of last asking for a save separately for each buffer + which fixes bugs with automatic reloading. +
  • +
  • + On Windows, pasted text has line ends converted to current preference. + GTK+ already did this. +
  • +
  • + Kid template language better handled by HTML lexer by finishing ASP Python + mode when a ?> is found. +
  • +
  • + SciTE counts number of characters in a rectangular selection correctly. +
  • +
  • + 64-bit compatibility improved. One change that may affect user code is that + the notification message header changed to include a pointer-sized id field + to match the current Windows definition. +
  • +
  • + Empty ranges can no longer be dragged. +
  • +
  • + Crash fixed when calls made that use layout inside the painted notification. +
  • +
  • + Bug fixed where Scintilla created pixmap buffers that were too large leading + to failures when many instances used. +
  • +
  • + SciTE sets the directory of a new file to the directory of the currently + active file. +
  • +
  • + SciTE allows choosing a code page for the output pane. +
  • +
  • + SciTE HTML exporter no longer honours monospaced font setting. +
  • +
  • + Line layout cache in page mode caches the line of the caret. An assertion is + now used to ensure that the layout reentrancy problem that caused this + is easier to find. +
  • +
  • + Speed optimized for long lines and lines containing many control characters. +
  • +
  • + Bug fixed in brace matching in DBCS files where byte inside character + is same as brace. +
  • +
  • + Indent command does not indent empty lines. +
  • +
  • + SciTE bug fixed for commands that operate on files with empty extensions. +
  • +
  • + SciTE bug fixed where monospaced option was copied for subsequently opened files. +
  • +
  • + SciTE on Windows bug fixed in the display of a non-ASCII search string + which can not be found. +
  • +
  • + Bugs fixed with nested calls displaying a new calltip while one is already + displayed. +
  • +
  • + Bug fixed when styling PHP strings. +
  • +
  • + Bug fixed when styling C++ continued preprocessor lines. +
  • +
  • + SciTE bug fixed where opening file from recently used list reset choice of + language. +
  • +
  • + SciTE bug fixed when compiled with NO_EXTENSIONS and + closing one file closes the application. +
  • +
  • + SciTE crash fixed for error messages that look like Lua messages but aren't + in the same order. +
  • +
  • + Remaining fold box support deprecated. The symbols SC_FOLDLEVELBOXHEADERFLAG, + SC_FOLDLEVELBOXFOOTERFLAG, SC_FOLDLEVELCONTRACTED, + SC_FOLDLEVELUNINDENT, and SC_FOLDFLAG_BOX are deprecated. +
  • +
+

+ Release 1.66 +

+
    +
  • + Released on 26 August 2005. +
  • +
  • + New, more ambitious Ruby lexer. +
  • +
  • + SciTE Find in Files dialog has options for matching case and whole words which are + enabled when the internal find command is used. +
  • +
  • + SciTE output pane can display automatic completion after "$(" typed. + An initial ">" on a line is ignored when Enter pressed. +
  • +
  • + C++ lexer recognises keywords within line doc comments. It continues styles over line + end characters more consistently so that eolfilled style can be used for preprocessor lines + and line comments. +
  • +
  • + VB lexer improves handling of file numbers and date literals. +
  • +
  • + Lua folder handles repeat until, nested comments and nested strings. +
  • +
  • + POV lexer improves handling of comment lines. +
  • +
  • + AU3 lexer and folder updated. COMOBJ style added. +
  • +
  • + Bug fixed with text display on GTK+ with Pango 1.8. +
  • +
  • + Caret painting avoided when not focused. +
  • +
  • + SciTE on GTK+ handles file names used to reference properties as case-sensitive. +
  • +
  • + SciTE on GTK+ Save As and Export commands set the file name field. + On GTK+ the Export commands modify the file name in the same way as on Windows. +
  • +
  • + Fixed SciTE problem where confirmation was not displaying when closing a file where all + contents had been deleted. +
  • +
  • + Middle click on SciTE tab now closes correct buffer on Windows when tool bar is visible. +
  • +
  • + SciTE bugs fixed where files contained in directory that includes '.' character. +
  • +
  • + SciTE bug fixed where import in user options was reading file from directory of + global options. +
  • +
  • + SciTE calltip bug fixed where single line calltips had arrow displayed incorrectly. +
  • +
  • + SciTE folding bug fixed where empty lines were shown for no reason. +
  • +
  • + Bug fixed where 2 byte per pixel XPM images caused crash although they are still not + displayed. +
  • +
  • + Autocompletion list size tweaked. +
  • +
+

+ Release 1.65 +

+
    +
  • + Released on 1 August 2005. +
  • +
  • + FreeBasic support. +
  • +
  • + SciTE on Windows handles command line arguments + "-" (read standard input into buffer), + "--" (read standard input into output pane) and + "-@" (read file names from standard input and open each). +
  • +
  • + SciTE includes a simple implementation of Find in Files which is used if no find.command is set. +
  • +
  • + SciTE can close tabs with a mouse middle click. +
  • +
  • + SciTE includes a save.all.for.build setting. +
  • +
  • + Folder for MSSQL. +
  • +
  • + Batch file lexer understands more of the syntax and the behaviour of built in commands. +
  • +
  • + Perl lexer handles here docs better; disambiguates barewords, quote-like delimiters, and repetition operators; + handles Pods after __END__; recognises numbers better; and handles some typeglob special variables. +
  • +
  • + Lisp adds more lexical states. +
  • +
  • + PHP allows spaces after <<<. +
  • +
  • + TADS3 has a simpler set of states and recognises identifiers. +
  • +
  • + Avenue elseif folds better. +
  • +
  • + Errorlist lexer treats lines starting with '+++' and '---' as separate + styles from '+' and '-' as they indicate file names in diffs. +
  • +
  • + SciTE error recogniser handles file paths in extra explanatory lines from MSVC + and in '+++' and '---' lines from diff. +
  • +
  • + Bugs fixed in SciTE and Scintilla folding behaviour when text pasted before + folded text caused unnecessary + unfolding and cutting text could lead to text being irretrievably hidden. +
  • +
  • + SciTE on Windows uses correct font for dialogs and better font for tab bar + allowing better localisation +
  • +
  • + When Windows is used with a secondary monitor before the primary + monitor, autocompletion lists are not forced onto the primary monitor. +
  • +
  • + Scintilla calltip bug fixed where down arrow setting wrong value in notification + if not in first line. SciTE bug fixed where second arrow only shown on multiple line + calltip and was therefore misinterpreting the notification value. +
  • +
  • + Lexers will no longer be re-entered recursively during, for example, fold level setting. +
  • +
  • + Undo of typing in overwrite mode undoes one character at a time rather than requiring a removal + and addition step for each character. +
  • +
  • + EM_EXSETSEL(0,-1) fixed. +
  • +
  • + Bug fixed where part of a rectangular selection was not shown as selected. +
  • +
  • + Autocomplete window size fixed. +
  • +
+

+ Release 1.64 +

+
    +
  • + Released on 6 June 2005. +
  • +
  • + TADS3 support +
  • +
  • + Smalltalk support. +
  • +
  • + Rebol support. +
  • +
  • + Flagship (Clipper / XBase) support. +
  • +
  • + CSound support. +
  • +
  • + SQL enhanced to support SQL*Plus. +
  • +
  • + SC_MARK_FULLRECT margin marker fills the whole marker margin for marked + lines with a colour. +
  • +
  • + Performance improved for some large undo and redo operations and modification flags + added in notifications. +
  • +
  • + SciTE adds command equivalents for fold margin mouse actions. +
  • +
  • + SciTE adds OnUpdateUI to set of events that can be handled by a Lua script. +
  • +
  • + Properties set in Scintilla can be read. +
  • +
  • + GTK+ SciTE exit confirmation adds Cancel button. +
  • +
  • + More accurate lexing of numbers in PHP and Caml. +
  • +
  • + Perl can fold POD and package sections. POD verbatim section style. + Globbing syntax recognised better. +
  • +
  • + Context menu moved slightly on GTK+ so that it will be under the mouse and will + stay open if just clicked rather than held. +
  • +
  • + Rectangular selection paste works the same whichever direction the selection was dragged in. +
  • +
  • + EncodedFromUTF8 handles -1 length argument as documented. +
  • +
  • + Undo and redo can cause SCN_MODIFYATTEMPTRO notifications. +
  • +
  • + Indicators display correctly when they start at the second character on a line. +
  • +
  • + SciTE Export As HTML uses standards compliant CSS. +
  • +
  • + SciTE automatic indentation handles keywords for indentation better. +
  • +
  • + SciTE fold.comment.python property removed as does not work. +
  • +
  • + Fixed problem with character set conversion when pasting on GTK+. +
  • +
  • + SciTE default character set changed from ANSI_CHARSET to DEFAULT_CHARSET. +
  • +
  • + Fixed crash when creating empty autocompletion list. +
  • +
  • + Autocomplete window size made larger under some conditions to make truncation less common. +
  • +
  • + Bug fixed where changing case of a selection did not affect initial character of lines + in multi-byte encodings. +
  • +
  • + Bug fixed where rectangular selection not displayed after Alt+Shift+Click. +
  • +
+

+ Release 1.63 +

+
    +
  • + Released on 4 April 2005. +
  • +
  • + Autocompletion on Windows changed to use pop up window, be faster, + allow choice of maximum width and height, and to highlight only the text of the + selected item rather than both the text and icon if any. +
  • +
  • + Extra items can be added to the context menu in SciTE. +
  • +
  • + Character wrap mode in Scintilla helps East Asian languages. +
  • +
  • + Lexer added for Haskell. +
  • +
  • + Objective Caml support. +
  • +
  • + BlitzBasic and PureBasic support. +
  • +
  • + CSS support updated to handle CSS2. +
  • +
  • + C++ lexer is more selective about document comment keywords. +
  • +
  • + AutoIt 3 lexer improved. +
  • +
  • + Lua lexer styles end of line characters on comment and preprocessor + lines so that the eolfilled style can be applied to them. +
  • +
  • + NSIS support updated for line continuations, box comments, SectionGroup and + PageEx, and with more up-to-date properties. +
  • +
  • + Clarion lexer updated to perform folding and have more styles. +
  • +
  • + SQL lexer gains second set of keywords. +
  • +
  • + Errorlist lexer recognises Borland Delphi error messages. +
  • +
  • + Method added for determining number of visual lines occupied by a document + line due to wrapping. +
  • +
  • + Sticky caret mode does not modify the preferred caret x position when typing + and may be useful for typing columns of text. +
  • +
  • + Dwell end notification sent when scroll occurs. +
  • +
  • + On GTK+, Scintilla requisition height is screen height rather than large fixed value. +
  • +
  • + Case insensitive autocompletion prefers exact case match. +
  • +
  • + SCI_PARADOWN and SCI_PARAUP treat lines containing only white + space as empty and handle text hidden by folding. +
  • +
  • + Scintilla on Windows supports WM_PRINTCLIENT although there are some + limitations. +
  • +
  • + SCN_AUTOCSELECTION notification sent when user selects from autoselection list. +
  • +
  • + SciTE's standard properties file sets buffers to 10, uses Pango fonts on GTK+ and + has dropped several languages to make the menu fit on screen. +
  • +
  • + SciTE's encoding cookie detection loosened so that common XML files will load + in UTF-8 if that is their declared encoding. +
  • +
  • + SciTE on GTK+ changes menus and toolbars to not be detachable unless turned + on with a property. Menus no longer tear off. The toolbar may be set to use the + default theme icons rather than SciTE's set. Changed key for View | End of Line + because of a conflict. Language menu can contain more items. +
  • +
  • + SciTE on GTK+ 2.x allows the height and width of the file open file chooser to + be set, for the show hidden files check box to be set from an option and for it + to be opened in the directory of the current file explicitly. Enter key works in + save chooser. +
  • +
  • + Scintilla lexers should no longer see bits in style bytes that are outside the set + they modify so should be able to correctly lex documents where the container + has used indicators. +
  • +
  • + SciTE no longer asks to save before performing a revert. +
  • +
  • + SciTE director interface adds a reloadproperties command to reload properties + from files. +
  • +
  • + Allow build on CYGWIN platform. +
  • +
  • + Allow use from LccWin compiler. +
  • +
  • + SCI_COLOURISE for SCLEX_CONTAINER causes a + SCN_STYLENEEDED notification. +
  • +
  • + Bugs fixed in lexing of HTML/ASP/JScript. +
  • +
  • + Fix for folding becoming confused. +
  • +
  • + On Windows, fixes for Japanese Input Method Editor and for 8 bit Katakana + characters. +
  • +
  • + Fixed buffer size bug avoided when typing long words by making buffer bigger. +
  • +
  • + Undo after automatic indentation more sensible. +
  • +
  • + SciTE menus on GTK+ uses Shift and Ctrl rather than old style abbreviations. +
  • +
  • + SciTE full screen mode on Windows calculates size more correctly. +
  • +
  • + SciTE on Windows menus work better with skinning applications. +
  • +
  • + Searching bugs fixed. +
  • +
  • + Colours reallocated when changing image using SCI_REGISTERIMAGE. +
  • +
  • + Caret stays visible when Enter held down. +
  • +
  • + Undo of automatic indentation more reasonable. +
  • +
  • + High processor usage fixed in background wrapping under some + circumstances. +
  • +
  • + Crashing bug fixed on AMD64. +
  • +
  • + SciTE crashing bug fixed when position.height or position.width not set. +
  • +
  • + Crashing bug on GTK+ fixed when setting cursor and window is NULL. +
  • +
  • + Crashing bug on GTK+ preedit window fixed. +
  • +
  • + SciTE crashing bug fixed in incremental search on Windows ME. +
  • +
  • + SciTE on Windows has a optional find and replace dialogs that can search through + all buffers and search within a particular style number. +
  • +
+

+ Release 1.62 +

+
    +
  • + Released on 31 October 2004. +
  • +
  • + Lexer added for ASN.1. +
  • +
  • + Lexer added for VHDL. +
  • +
  • + On Windows, an invisible system caret is used to allow screen readers to determine + where the caret is. The visible caret is still drawn by the painting code. +
  • +
  • + On GTK+, Scintilla has methods to read the target as UTF-8 and to convert + a string from UTF-8 to the document encoding. This eases integration with + containers that use the UTF-8 encoding which is the API encoding for GTK+ 2. +
  • +
  • + SciTE on GTK+2 and Windows NT/2000/XP allows search and replace of Unicode text. +
  • +
  • + SciTE calltips allow setting the characters used to start and end parameter lists and + to separate parameters. +
  • +
  • + FindColumn method converts a line and column into a position, taking into account + tabs and multi-byte characters. +
  • +
  • + On Windows, when Scintilla copies text to the clipboard as Unicode, it avoids + adding an ANSI copy as the system will automatically convert as required in + a context-sensitive manner. +
  • +
  • + SciTE indent.auto setting automatically determines indent.size and use.tabs from + document contents. +
  • +
  • + SciTE defines a CurrentMessage property that holds the most recently selected + output pane message. +
  • +
  • + SciTE Lua scripting enhanced with +
      +
    • A Lua table called 'buffer' is associated with each buffer and can be used to + maintain buffer-specific state.
    • +
    • A 'scite' object allows interaction with the application such as opening + files from script.
    • +
    • Dynamic properties can be reset by assigning nil to a given key in + the props table.
    • +
    • An 'OnClear' event fires whenever properties and extension scripts are + about to be reloaded.
    • +
    • On Windows, loadlib is enabled and can be used to access Lua + binary modules / DLLs.
    +
  • +
  • + SciTE Find in Files on Windows can be used in a modeless way and gains a '..' + button to move up to the parent directory. It is also wider so that longer paths + can be seen. +
  • +
  • + Close buttons added to dialogs in SciTE on Windows. +
  • +
  • + SciTE on GTK+ 2 has a "hidden files" check box in file open dialog. +
  • +
  • + SciTE use.monospaced setting removed. More information in the + FAQ. +
  • +
  • + APDL lexer updated with more lexical classes +
  • +
  • + AutoIt3 lexer updated. +
  • +
  • + Ada lexer fixed to support non-ASCII text. +
  • +
  • + Cpp lexer now only matches exactly three slashes as starting a doc-comment so that + lines of slashes are seen as a normal comment. + Line ending characters are appear in default style on preprocessor and single line + comment lines. +
  • +
  • + CSS lexer updated to support CSS2 including second set of keywords. +
  • +
  • + Errorlist lexer now understands Java stack trace lines. +
  • +
  • + SciTE's handling of HTML Tidy messages jumps to column as well as line indicated. +
  • +
  • + Lisp lexer allows multiline strings. +
  • +
  • + Lua lexer treats .. as an operator when between identifiers. +
  • +
  • + PHP lexer handles 'e' in numerical literals. +
  • +
  • + PowerBasic lexer updated for macros and optimised. +
  • +
  • + Properties file folder changed to leave lines before a header at the base level + and thus avoid a vertical line when using connected folding symbols. +
  • +
  • + GTK+ on Windows version uses Alt for rectangular selection to be compatible with + platform convention. +
  • +
  • + SciTE abbreviations file moved from system directory to user directory + so each user can have separate abbreviations. +
  • +
  • + SciTE on GTK+ has improved .desktop file and make install support that may + lead to better integration with system shell. +
  • +
  • + Disabling of themed background drawing on GTK+ extended to all cases. +
  • +
  • + SciTE date formatting on Windows performed with the user setting rather than the + system setting. +
  • +
  • + GTK+ 2 redraw while scrolling fixed. +
  • +
  • + Recursive property definitions are safer, avoiding expansion when detected. +
  • +
  • + SciTE thread synchronization for scripts no longer uses HWND_MESSAGE + so is compatible with older versions of Windows. + Other Lua scripting bugs fixed. +
  • +
  • + SciTE on Windows localisation of menu accelerators changed to be compatible + with alternative UI themes. +
  • +
  • + SciTE on Windows full screen mode now fits better when menu different height + to title bar height. +
  • +
  • + SC_MARK_EMPTY marker is now invisible and does not change the background + colour. +
  • +
  • + Bug fixed in HTML lexer to allow use of <?xml in strings in scripts without + triggering xml mode. +
  • +
  • + Bug fixed in SciTE abbreviation expansion that could break indentation or crash. +
  • +
  • + Bug fixed when searching for a whole word string that ends one character before + end of document. +
  • +
  • + Drawing bug fixed when indicators drawn on wrapped lines. +
  • +
  • + Bug fixed when double clicking a hotspot. +
  • +
  • + Bug fixed where autocompletion would remove typed text if no match found. +
  • +
  • + Bug fixed where display does not scroll when inserting in long wrapped line. +
  • +
  • + Bug fixed where SCI_MARKERDELETEALL would only remove one of the markers + on a line that contained multiple markers with the same number. +
  • +
  • + Bug fixed where markers would move when converting line endings. +
  • +
  • + Bug fixed where SCI_LINEENDWRAP would move too far when line ends are visible. +
  • +
  • + Bugs fixed where calltips with unicode or other non-ASCII text would display + incorrectly. +
  • +
  • + Bug fixed in determining if at save point after undoing from save point and then + performing changes. +
  • +
  • + Bug fixed on GTK+ using unsupported code pages where extraneous text could + be drawn. +
  • +
  • + Bug fixed in drag and drop code on Windows where dragging from SciTE to + Firefox could hang both applications. +
  • +
  • + Crashing bug fixed on GTK+ when no font allocation succeeds. +
  • +
  • + Crashing bug fixed when autocompleting word longer than 1000 characters. +
  • +
  • + SciTE crashing bug fixed when both Find and Replace dialogs shown by disallowing + this situation. +
  • +
+

+ Release 1.61 +

+
    +
  • + Released on 29 May 2004. +
  • +
  • + Improvements to selection handling on GTK+. +
  • +
  • + SciTE on GTK+ 2.4 uses the improved file chooser which allows + file extension filters, multiple selection, and remembers favourite + directories. +
  • +
  • + SciTE Load Session and Save Session commands available on GTK+. +
  • +
  • + SciTE lists Lua Startup Script in Options menu when loaded. +
  • +
  • + In SciTE, OnUserListSelection can be implemented in Lua. +
  • +
  • + SciTE on Windows has a context menu on the file tabs. +
  • +
  • + SQL lexer allows '#' comments and optionally '\' quoting inside strings. +
  • +
  • + Mssql lexer improved. +
  • +
  • + AutoIt3 lexer updated. +
  • +
  • + Perl lexer recognises regular expression use better. +
  • +
  • + Errorlist lexer understands Lua tracebacks and copes with findstr + output for file names that end with digits. +
  • +
  • + Drawing of lines on GTK+ improved and made more like Windows + without final point. +
  • +
  • + SciTE on GTK+ uses a high resolution window icon. +
  • +
  • + SciTE can be set to warn before loading files larger than a particular size. +
  • +
  • + SciTE Lua scripting bugs fixed included a crashing bug when using + an undefined function name that would go before first actual name. +
  • +
  • + SciTE bug fixed where a modified buffer was not saved if it was + the last buffer and was not current when the New command used. +
  • +
  • + SciTE monofont mode no longer affects line numbers. +
  • +
  • + Crashing bug in SciTE avoided by not allowing both the Find and Replace + dialogs to be visible at one time. +
  • +
  • + Crashing bug in SciTE fixed when Lua scripts were being run + concurrently. +
  • +
  • + Bug fixed that caused incorrect line number width in SciTE. +
  • +
  • + PHP folding bug fixed. +
  • +
  • + Regression fixed when setting word characters to not include + some of the standard word characters. +
  • +
+

+ Release 1.60 +

+
    +
  • + Released on 1 May 2004. +
  • +
  • + SciTE can be scripted using the Lua programming language. +
  • +
  • + command.mode is a better way to specify tool command options in SciTE. +
  • +
  • + Continuation markers can be displayed so that you can see which lines are wrapped. +
  • +
  • + Lexer for Gui4Cli language. +
  • +
  • + Lexer for Kix language. +
  • +
  • + Lexer for Specman E language. +
  • +
  • + Lexer for AutoIt3 language. +
  • +
  • + Lexer for APDL language. +
  • +
  • + Lexer for Bash language. Also reasonable for other Unix shells. +
  • +
  • + SciTE can load lexers implemented in external shared libraries. +
  • +
  • + Perl treats "." not as part of an identifier and interprets '/' and '->' + correctly in more circumstances. +
  • +
  • + PHP recognises variables within strings. +
  • +
  • + NSIS has properties "nsis.uservars" and "nsis.ignorecase". +
  • +
  • + MSSQL lexer adds keyword list for operators and stored procedures, + defines '(', ')', and ',' as operators and changes some other details. +
  • +
  • + Input method preedit window on GTK+ 2 may support some Asian languages. +
  • +
  • + Platform interface adds an extra platform-specific flag to Font::Create. + Used on wxWidgets to choose antialiased text display but may be used for + any task that a platform needs. +
  • +
  • + OnBeforeSave method added to Extension interface. +
  • +
  • + Scintilla methods that return strings can be called with a NULL pointer + to find out how long the string should be. +
  • +
  • + Visual Studio .NET project file now in VS .NET 2003 format so can not be used + directly in VS .NET 2002. +
  • +
  • + Scintilla can be built with GTK+ 2 on Windows. +
  • +
  • + Updated RPM spec for SciTE on GTK+. +
  • +
  • + GTK+ makefile for SciTE allows selection of destination directory, creates destination + directories and sets file modes and owners better. +
  • +
  • + Tab indents now go to next tab multiple rather than add tab size. +
  • +
  • + SciTE abbreviations now use the longest possible match rather than the shortest. +
  • +
  • + Autocompletion does not remove prefix when actioned with no choice selected. +
  • +
  • + Autocompletion cancels when moving beyond the start position, not at the start position. +
  • +
  • + SciTE now shows only calltips for functions that match exactly, not + those that match as a prefix. +
  • +
  • + SciTE can repair box comment sections where some lines were added without + the box comment middle line prefix. +
  • +
  • + Alt+ works in user.shortcuts on Windows. +
  • +
  • + SciTE on GTK+ enables replace in selection for rectangular selections. +
  • +
  • + Key bindings for command.shortcut implemented in a way that doesn't break + when the menus are localised. +
  • +
  • + Drawing of background on GTK+ faster as theme drawing disabled. +
  • +
  • + On GTK+, calltips are moved back onto the screen if they extend beyond the screen bounds. +
  • +
  • + On Windows, the Scintilla object is destroyed on WM_NCDESTROY rather than + WM_DESTROY which arrives earlier. This fixes some problems when Scintilla was subclassed. +
  • +
  • + The zorder switching feature removed due to number of crashing bugs. +
  • +
  • + Code for XPM images made more robust. +
  • +
  • + Bug fixed with primary selection on GTK+. +
  • +
  • + On GTK+ 2, copied or cut text can still be pasted after the Scintilla widget is destroyed. +
  • +
  • + Styling change not visible problem fixed when line was cached. +
  • +
  • + Bug in SciTE on Windows fixed where clipboard commands stopped working. +
  • +
  • + Crashing bugs in display fixed in line layout cache. +
  • +
  • + Crashing bug may be fixed on AMD64 processor on GTK+. +
  • +
  • + Rare hanging crash fixed in Python lexer. +
  • +
  • + Display bugs fixed with DBCS characters on GTK+. +
  • +
  • + Autocompletion lists on GTK+ 2 are not sorted by the ListModel as the + contents are sorted correctly by Scintilla. +
  • +
  • + SciTE fixed to not open extra untitled buffers with check.if.already.open. +
  • +
  • + Sizing bug fixed on GTK+ when window resized while unmapped. +
  • +
  • + Text drawing crashing bug fixed on GTK+ with non-Pango fonts and long strings. +
  • +
  • + Fixed some issues if characters are unsigned. +
  • +
  • + Fixes in NSIS support. +
  • +
+

+ Release 1.59 +

+
    +
  • + Released on 19 February 2004. +
  • +
  • + SciTE Options and Language menus reduced in length by commenting + out some languages. Languages can be enabled by editing the global + properties file. +
  • +
  • + Verilog language supported. +
  • +
  • + Lexer for Microsoft dialect of SQL. SciTE properties file available from extras page. +
  • +
  • + Perl lexer disambiguates '/' better. +
  • +
  • + NSIS lexer improved with a lexical class for numbers, option for ignoring case + of keywords, and folds only occurring when folding keyword first on line. +
  • +
  • + PowerBasic lexer improved with styles for constants and assembler and + folding improvements. +
  • +
  • + On GTK+, input method support only invoked for Asian languages and not + European languages as the old European keyboard code works better. +
  • +
  • + Scintilla can be requested to allocate a certain amount and so avoid repeated + reallocations and memory inefficiencies. SciTE uses this and so should require + less memory. +
  • +
  • + SciTE's "toggle current fold" works when invoked on child line as well as + fold header. +
  • +
  • + SciTE output pane scrolling can be set to not scroll back to start after + completion of command. +
  • +
  • + SciTE has a $(SessionPath) property. +
  • +
  • + SciTE on Windows can use VK_* codes for keys in user.shortcuts. +
  • +
  • + Stack overwrite bug fixed in SciTE's command to move to the end of a + preprocessor conditional. +
  • +
  • + Bug fixed where vertical selection appeared to select a different set of characters + then would be used by, for example, a copy. +
  • +
  • + SciTE memory leak fixed in fold state remembering. +
  • +
  • + Bug fixed where changing the style of some text outside the + standard StyleNeeded notification would not be visible. +
  • +
  • + On GTK+ 2 g_iconv is used in preference to iconv, as it is provided by GTK+ + so should avoid problems finding the iconv library. +
  • +
  • + On GTK+ fixed a style reference count bug. +
  • +
  • + Memory corruption bug fixed with GetSelText. +
  • +
  • + On Windows Scintilla deletes memory on WM_NCDESTROY rather than + the earlier WM_DESTROY to avoid problems when the window is subclassed. +
  • +
+

+ Release 1.58 +

+
    +
  • + Released on 11 January 2004. +
  • +
  • + Method to discover the currently highlighted element in an autocompletion list. +
  • +
  • + On GTK+, the lexers are now included in the scintilla.a library file. This + will require changes to the make files of dependent projects. +
  • +
  • + Octave support added alongside related Matlab language and Matlab support improved. +
  • +
  • + VB lexer gains an unterminated string state and 4 sets of keywords. +
  • +
  • + Ruby lexer handles $' correctly. +
  • +
  • + Error line handling improved for FORTRAN compilers from Absoft and Intel. +
  • +
  • + International input enabled on GTK+ 2 although there is no way to choose an + input method. +
  • +
  • + MultiplexExtension in SciTE allows multiple extensions to be used at once. +
  • +
  • + Regular expression replace interprets backslash expressions \a, \b, \f, \n, \r, \t, + and \v in the replacement value. +
  • +
  • + SciTE Replace dialog displays number of replacements made when Replace All or + Replace in Selection performed. +
  • +
  • + Localisation files may contain a translation.encoding setting which is used + on GTK+ 2 to automatically reencode the translation to UTF-8 so it will be + the localised text will be displayed correctly. +
  • +
  • + SciTE on GTK+ implements check.if.already.open. +
  • +
  • + Make files for Mac OS X made more robust. +
  • +
  • + Performance improved in SciTE when switching buffers when there + is a rectangular selection. +
  • +
  • + Fixed failure to display some text when wrapped. +
  • +
  • + SciTE crashes from Ctrl+Tab buffer cycling fixed. + May still be some rare bugs here. +
  • +
  • + Crash fixed when decoding an error message that appears similar to a + Borland error message. +
  • +
  • + Fix to auto-scrolling allows containers to implement enhanced double click selection. +
  • +
  • + Hang fixed in idle word wrap. +
  • +
  • + Crash fixed in hotspot display code.. +
  • +
  • + SciTE on Windows Incremental Search no longer moves caret back. +
  • +
  • + SciTE hang fixed when performing a replace with a find string that + matched zero length strings such as ".*". +
  • +
  • + SciTE no longer styles the whole file when saving buffer fold state + as that was slow. +
  • +
+

+ Release 1.57 +

+
    +
  • + Released on 27 November 2003. +
  • +
  • + SciTE remembers folding of each buffer. +
  • +
  • + Lexer for Erlang language. +
  • +
  • + Scintilla allows setting the set of white space characters. +
  • +
  • + Scintilla has 'stuttered' page movement commands to first move + to top or bottom within current visible lines before scrolling. +
  • +
  • + Scintilla commands for moving to end of words. +
  • +
  • + Incremental line wrap enabled on Windows. +
  • +
  • + SciTE PDF exporter produces output that is more compliant with reader + applications, is smaller and allows more configuration. + HTML exporter optimizes size of output files. +
  • +
  • + SciTE defines properties PLAT_WINNT and PLAT_WIN95 on the + corresponding platforms. +
  • +
  • + SciTE can adjust the line margin width to fit the largest line number. + The line.numbers property is split between line.margin.visible and + line.margin.width. +
  • +
  • + SciTE on GTK+ allows user defined menu accelerators. + Alt can be included in user.shortcuts. +
  • +
  • + SciTE Language menu can have items commented out. +
  • +
  • + SciTE on Windows Go to dialog allows choosing a column number as + well as a line number. +
  • +
  • + SciTE on GTK+ make file uses prefix setting more consistently. +
  • +
  • + Bug fixed that caused word wrapping to fail to display all text. +
  • +
  • + Crashing bug fixed in GTK+ version of Scintilla when using GDK fonts + and opening autocompletion. +
  • +
  • + Bug fixed in Scintilla SCI_GETSELTEXT where an extra NUL + was included at end of returned string +
  • +
  • + Crashing bug fixed in SciTE z-order switching implementation. +
  • +
  • + Hanging bug fixed in Perl lexer. +
  • +
  • + SciTE crashing bug fixed for using 'case' without argument in style definition. +
  • +
+

+ Release 1.56 +

+
    +
  • + Released on 25 October 2003. +
  • +
  • + Rectangular selection can be performed using the keyboard. + Greater programmatic control over rectangular selection. + This has caused several changes to key bindings. +
  • +
  • + SciTE Replace In Selection works on rectangular selections. +
  • +
  • + Improved lexer for TeX, new lexer for Metapost and other support for these + languages. +
  • +
  • + Lexer for PowerBasic. +
  • +
  • + Lexer for Forth. +
  • +
  • + YAML lexer improved to include error styling. +
  • +
  • + Perl lexer improved to correctly handle more cases. +
  • +
  • + Assembler lexer updated to support single-quote strings and fix some + problems. +
  • +
  • + SciTE on Windows can switch between buffers in order of use (z-order) rather + than static order. +
  • +
  • + SciTE supports adding an extension for "Open Selected Filename". + The openpath setting works on GTK+. +
  • +
  • + SciTE can Export as XML. +
  • +
  • + SciTE $(SelHeight) variable gives a more natural result for empty and whole line + selections. +
  • +
  • + Fixes to wrapping problems, such as only first display line being visible in some + cases. +
  • +
  • + Fixes to hotspot to only highlight when over the hotspot, only use background + colour when set and option to limit hotspots to a single line. +
  • +
  • + Small fixes to FORTRAN lexing and folding. +
  • +
  • + SQL lexer treats single quote strings as a separate class to double quote strings.. +
  • +
  • + Scintilla made compatible with expectations of container widget in GTK+ 2.3. +
  • +
  • + Fix to strip out pixmap ID when automatically choosing from an autocompletion + list with only one element. +
  • +
  • + SciTE bug fixed where UTF-8 files longer than 128K were gaining more than one + BOM. +
  • +
  • + Crashing bug fixed in SciTE on GTK+ where using "Stop Executing" twice leads + to all applications exiting. +
  • +
  • + Bug fixed in autocompletion scrolling on GTK+ 2 with a case sensitive list. + The ListBox::Sort method is no longer needed or available so platform + maintainers should remove it. +
  • +
  • + SciTE check.if.already.open setting removed from GTK+ version as unmaintained. +
  • +
+

+ Release 1.55 +

+
    +
  • + Released on 25 September 2003. +
  • +
  • + Fix a crashing bug in indicator display in Scintilla. +
  • +
  • + GTK+ version now defaults to building for GTK+ 2 rather than 1. +
  • +
  • + Mingw make file detects compiler version and avoids options + that are cause problems for some versions. +
  • +
  • + Large performance improvement on GTK+ 2 for long lines. +
  • +
  • + Incremental line wrap on GTK+. +
  • +
  • + International text entry works much better on GTK+ with particular + improvements for Baltic languages and languages that use 'dead' accents. + NUL key events such as those generated by some function keys, ignored. +
  • +
  • + Unicode clipboard support on GTK+. +
  • +
  • + Indicator type INDIC_BOX draws a rectangle around the text. +
  • +
  • + Clarion language support. +
  • +
  • + YAML language support. +
  • +
  • + MPT LOG language support. +
  • +
  • + On Windows, SciTE can switch buffers based on activation order rather + than buffer number. +
  • +
  • + SciTE save.on.deactivate saves all buffers rather than just the current buffer. +
  • +
  • + Lua lexer handles non-ASCII characters correctly. +
  • +
  • + Error lexer understands Borland errors with pathnames that contain space. +
  • +
  • + On GTK+ 2, autocompletion uses TreeView rather than deprecated CList. +
  • +
  • + SciTE autocompletion removed when expand abbreviation command used. +
  • +
  • + SciTE calltips support overloaded functions. +
  • +
  • + When Save fails in SciTE, choice offered to Save As. +
  • +
  • + SciTE message boxes on Windows may be moved to front when needed. +
  • +
  • + Indicators drawn correctly on wrapped lines. +
  • +
  • + Regular expression search no longer matches characters with high bit + set to characters without high bit set. +
  • +
  • + Hang fixed in backwards search in multi byte character documents. +
  • +
  • + Hang fixed in SciTE Mark All command when wrap around turned off. +
  • +
  • + SciTE Incremental Search no longer uses hot keys on Windows. +
  • +
  • + Calltips draw non-ASCII characters correctly rather than as arrows. +
  • +
  • + SciTE crash fixed when going to an error message with empty file name. +
  • +
  • + Bugs fixed in XPM image handling code. +
  • +
+

+ Release 1.54 +

+
    +
  • + Released on 12 August 2003. +
  • +
  • + SciTE on GTK+ 2.x can display a tab bar. +
  • +
  • + SciTE on Windows provides incremental search. +
  • +
  • + Lexer for PostScript. +
  • +
  • + Lexer for the NSIS scripting language. +
  • +
  • + New lexer for POV-Ray Scene Description Language + replaces previous implementation. +
  • +
  • + Lexer for the MMIX Assembler language. +
  • +
  • + Lexer for the Scriptol language. +
  • +
  • + Incompatibility: SQL keywords are specified in lower case rather than upper case. + SQL lexer allows double quoted strings. +
  • +
  • + Pascal lexer: character constants that start with '#' understood, + '@' only allowed within assembler blocks, + '$' can be the start of a number, + initial '.' in 0..constant not treated as part of a number, + and assembler blocks made more distinctive. +
  • +
  • + Lua lexer allows '.' in keywords. + Multi-line strings and comments can be folded. +
  • +
  • + CSS lexer handles multiple psuedoclasses. +
  • +
  • + Properties file folder works for INI file format. +
  • +
  • + Hidden indicator style allows the container to mark text within Scintilla + without there being any visual effect. +
  • +
  • + SciTE does not prompt to save changes when the buffer is empty and untitled. +
  • +
  • + Modification notifications caused by SCI_INSERTSTYLEDSTRING + now include the contents of the insertion. +
  • +
  • + SCI_MARKERDELETEALL deletes all the markers on a line + rather than just the first match. +
  • +
  • + Better handling of 'dead' accents on GTK+ 2 for languages + that use accented characters. +
  • +
  • + SciTE now uses value of output.vertical.size property. +
  • +
  • + Crash fixed in SciTE autocompletion on long lines. +
  • +
  • + Crash fixed in SciTE comment command on long lines. +
  • +
  • + Bug fixed with backwards regular expression search skipping + every second match. +
  • +
  • + Hang fixed with regular expression replace where both target and replacement were empty. +
  • +
+

+ Release 1.53 +

+
    +
  • + Released on 16 May 2003. +
  • +
  • + On GTK+ 2, encodings other than ASCII, Latin1, and Unicode are + supported for both display and input using iconv. +
  • +
  • + External lexers supported on GTK+/Linux. + External lexers must now be explicitly loaded with SCI_LOADLEXERLIBRARY + rather than relying upon a naming convention and automatic loading. +
  • +
  • + Support of Lout typesetting language. +
  • +
  • + Support of E-Scripts language used in the POL Ultima Online Emulator. +
  • +
  • + Scrolling and drawing performance on GTK+ enhanced, particularly for GTK+ 2.x + with an extra window for the text area avoiding conflicts with the scroll bars. +
  • +
  • + CopyText and CopyRange methods in Scintilla allow container to + easily copy to the system clipboard. +
  • +
  • + Line Copy command implemented and bound to Ctrl+Shift+T. +
  • +
  • + Scintilla APIs PositionBefore and PositionAfter can be used to iterate through + a document taking into account the encoding and multi-byte characters. +
  • +
  • + C++ folder can fold on the "} else {" line of an if statement by setting + fold.at.else property to 1. +
  • +
  • + C++ lexer allows an extra set of keywords. +
  • +
  • + Property names and thus abbreviations may be non-ASCII. +
  • +
  • + Removed attempt to load a file when setting properties that was + part of an old scripting experiment. +
  • +
  • + SciTE no longer warns about a file not existing when opening + properties files from the Options menu as there is a good chance + the user wants to create one. +
  • +
  • + Bug fixed with brace recognition in multi-byte encoded files where a partial + character matched a brace byte. +
  • +
  • + More protection against infinite loops or recursion with recursive property definitions. +
  • +
  • + On Windows, cursor will no longer disappear over margins in custom builds when + cursor resource not present. The Windows default cursor is displayed instead. +
  • +
  • + load.on.activate fixed in SciTE as was broken in 1.52. +
  • +
+

+ Release 1.52 +

+
    +
  • + Released on 17 April 2003. +
  • +
  • + Pango font support on GTK+ 2. + Unicode input improved on GTK+ 2. +
  • +
  • + Hotspot style implemented in Scintilla. +
  • +
  • + Small up and down arrows can be displayed in calltips and the container + is notified when the mouse is clicked on a calltip. + Normal and selected calltip text colours can be set. +
  • +
  • + POSIX compatibility flag in Scintilla regular expression search + interprets bare ( and ) as tagged sections. +
  • +
  • + Error message lexer tightened to yield fewer false matches. + Recognition of Lahey and Intel FORTRAN error formats. +
  • +
  • + Scintilla keyboard commands for moving to start and end of + screen lines rather than document lines, unless already there + where these keys move to the start or end of the document line. +
  • +
  • + Line joining command. +
  • +
  • + Lexer for POV-Ray. +
  • +
  • + Calltips on Windows are no longer clipped by the parent window. +
  • +
  • + Autocompletion lists are cancelled when focus leaves their parent window. +
  • +
  • + Move to next/previous empty line delimited paragraph key commands. +
  • +
  • + SciTE hang fixed with recursive property definitions by placing limit + on number of substitutions performed. +
  • +
  • + SciTE Export as PDF reenabled and works. +
  • +
  • + Added loadsession: command line command to SciTE. +
  • +
  • + SciTE option to quit application when last document closed. +
  • +
  • + SciTE option to ask user if it is OK to reload a file that has been + modified outside SciTE. +
  • +
  • + SciTE option to automatically save before running particular command tools + or to ask user or to not save. +
  • +
  • + SciTE on Windows 9x will write a Ctrl+Z to the process input pipe before + closing the pipe when running tool commands that take input. +
  • +
  • + Added a manifest resource to SciTE on Windows to enable Windows XP + themed UI. +
  • +
  • + SciTE calltips handle nested calls and other situations better. +
  • +
  • + CSS lexer improved. +
  • +
  • + Interface to platform layer changed - Surface initialisation now requires + a WindowID parameter. +
  • +
  • + Bug fixed with drawing or measuring long pieces of text on Windows 9x + by truncating the pieces. +
  • +
  • + Bug fixed with SciTE on GTK+ where a user shortcut for a visible character + inserted the character as well as executing the command. +
  • +
  • + Bug fixed where primary selection on GTK+ was reset by + Scintilla during creation. +
  • +
  • + Bug fixed where SciTE would close immediately on startup + when using save.session. +
  • +
  • + Crash fixed when entering '\' in LaTeX file. +
  • +
  • + Hang fixed when '#' last character in VB file. +
  • +
  • + Crash fixed in error message lexer. +
  • +
  • + Crash fixed when searching for long regular expressions. +
  • +
  • + Pressing return when nothing selected in user list sends notification with + empty text rather than random text. +
  • +
  • + Mouse debouncing disabled on Windows as it interfered with some + mouse utilities. +
  • +
  • + Bug fixed where overstrike mode inserted before rather than replaced last + character in document. +
  • +
  • + Bug fixed with syntax highlighting of Japanese text. +
  • +
  • + Bug fixed in split lines function. +
  • +
  • + Cosmetic fix to SciTE tab bar on Windows when window resized. + Focus sticks to either pane more consistently. +
  • +
+

+ Release 1.51 +

+
    +
  • + Released on 16 February 2003. +
  • +
  • + Two phase drawing avoids cutting off text that overlaps runs by drawing + all the backgrounds of a line then drawing all the text transparently. + Single phase drawing is an option. +
  • +
  • + Scintilla method to split lines at a particular width by adding new line + characters. +
  • +
  • + The character used in autocompletion lists to separate the text from the image + number can be changed. +
  • +
  • + The scrollbar range will automatically expand when the caret is moved + beyond the current range. + The scroll bar is updated when SCI_SETXOFFSET is called. +
  • +
  • + Mouse cursors on GTK+ improved to be consistent with other applications + and the Windows version. +
  • +
  • + Horizontal scrollbar on GTK+ now disappears in wrapped mode. +
  • +
  • + Scintilla on GTK+ 2: mouse wheel scrolling, cursor over scrollbars, focus, + and syntax highlighting now work. + gtk_selection_notify avoided for compatibility with GTK+ 2.2. +
  • +
  • + Fold margin colours can now be set. +
  • +
  • + SciTE can be built for GTK+ 2. +
  • +
  • + SciTE can optionally preserve the undo history over an automatic file reload. +
  • +
  • + Tags can optionally be case insensitive in XML and HTML. +
  • +
  • + SciTE on Windows handles input to tool commands in a way that should avoid + deadlock. Output from tools can be used to replace the selection. +
  • +
  • + SciTE on GTK+ automatically substitutes '|' for '/' in menu items as '/' + is used to define the menu hierarchy. +
  • +
  • + Optional buffer number in SciTE title bar. +
  • +
  • + Crash fixed in SciTE brace matching. +
  • +
  • + Bug fixed where automatic scrolling past end of document + flipped back to the beginning. +
  • +
  • + Bug fixed where wrapping caused text to disappear. +
  • +
  • + Bug fixed on Windows where images in autocompletion lists were + shown on the wrong item. +
  • +
  • + Crash fixed due to memory bug in autocompletion lists on Windows. +
  • +
  • + Crash fixed when double clicking some error messages. +
  • +
  • + Bug fixed in word part movement where sometimes no movement would occur. +
  • +
  • + Bug fixed on Windows NT where long text runs were truncated by + treating NT differently to 9x where there is a limitation. +
  • +
  • + Text in not-changeable style works better but there remain some cases where + it is still possible to delete text protected this way. +
  • +
+

+ Release 1.50 +

+
    +
  • + Released on 24 January 2003. +
  • +
  • + Autocompletion lists may have a per-item pixmap. +
  • +
  • + Autocompletion lists allow Unicode text on Windows. +
  • +
  • + Scintilla documentation rewritten. +
  • +
  • + Additional DBCS encoding support in Scintilla on GTK+ primarily aimed at + Japanese EUC encoding. +
  • +
  • + CSS (Cascading Style Sheets) lexer added. +
  • +
  • + diff lexer understands some more formats. +
  • +
  • + Fold box feature is an alternative way to show the structure of code. +
  • +
  • + Avenue lexer supports multiple keyword lists. +
  • +
  • + The caret may now be made invisible by setting the caret width to 0. +
  • +
  • + Python folder attaches comments before blocks to the next block rather + than the previous block. +
  • +
  • + SciTE openpath property on Windows searches a path for files that are + the subject of the Open Selected Filename command. +
  • +
  • + The localisation file name can be changed with the locale.properties property. +
  • +
  • + On Windows, SciTE can pipe the result of a string expression into a command line tool. +
  • +
  • + On Windows, SciTE's Find dialog has a Mark All button. +
  • +
  • + On Windows, there is an Insert Abbreviation command that allows a choice from + the defined abbreviations and inserts the selection into the abbreviation at the + position of a '|'. +
  • +
  • + Minor fixes to Fortran lexer. +
  • +
  • + fold.html.preprocessor decides whether to fold <? and ?>. + Minor improvements to PHP folding. +
  • +
  • + Maximum number of keyword lists allowed increased from 6 to 9. +
  • +
  • + Duplicate line command added with default assignment to Ctrl+D. +
  • +
  • + SciTE sets $(Replacements) to the number of replacements made by the + Replace All command. $(CurrentWord) is set to the word before the caret if the caret + is at the end of a word. +
  • +
  • + Opening a SciTE session now loads files in remembered order, sets the current file + as remembered, and moves the caret to the remembered line. +
  • +
  • + Bugs fixed with printing on Windows where line wrapping was causing some text + to not print. +
  • +
  • + Bug fixed with Korean Input Method Editor on Windows. +
  • +
  • + Bugs fixed with line wrap which would sometimes choose different break positions + after switching focus away and back. +
  • +
  • + Bug fixed where wheel scrolling had no effect on GTK+ after opening a fold. +
  • +
  • + Bug fixed with file paths containing non-ASCII characters on Windows. +
  • +
  • + Crash fixed with printing on Windows after defining pixmap marker. +
  • +
  • + Crash fixed in makefile lexer when first character on line was '='. +
  • +
  • + Bug fixed where local properties were not always being applied. +
  • +
  • + Ctrl+Keypad* fold command works on GTK+. +
  • +
  • + Hangs fixed in SciTE's Replace All command when replacing regular expressions '^' + or '$'. +
  • +
  • + SciTE monospace setting behaves more sensibly. +
  • +
+

+ Release 1.49 +

+
    +
  • + Released on 1 November 2002. +
  • +
  • + Unicode supported on GTK+. To perform well, this added a font cache to GTK+ + and to make that safe, a mutex is used. The mutex requires the application to link in + the threading library by evaluating `glib-config --libs gthread`. A Unicode locale + should also be set up by a call like setlocale(LC_CTYPE, "en_US.UTF-8"). + scintilla_release_resources function added to release mutex. +
  • +
  • + FORTRAN and assembler lexers added along with other support for these + languages in SciTE. +
  • +
  • + Ada lexer improved handling of based numbers, identifier validity and attributes + distinguished from character literals. +
  • +
  • + Lua lexer handles block comments and a deep level of nesting for literal strings + and block comments. +
  • +
  • + Errorlist lexer recognises PHP error messages. +
  • +
  • + Variant of the C++ lexer with case insensitive keywords + called cppnocase. Whitespace in preprocessor text handled more correctly. +
  • +
  • + Folder added for Perl. +
  • +
  • + Compilation with GCC 3.2 supported. +
  • +
  • + Markers can be pixmaps. +
  • +
  • + Lines are wrapped when printing. + Bug fixed which printed line numbers in different styles. +
  • +
  • + Text can be appended to end with AppendText method. +
  • +
  • + ChooseCaretX method added. +
  • +
  • + Vertical scroll bar can be turned off with SetVScrollBar method. +
  • +
  • + SciTE Save All command saves all buffers. +
  • +
  • + SciTE localisation compares keys case insensitively to make translations more flexible. +
  • +
  • + SciTE detects a utf-8 coding cookie "coding: utf-8" in first two + lines and goes into Unicode mode. +
  • +
  • + SciTE key bindings are definable. +
  • +
  • + SciTE Find in Files dialog can display directory browser to + choose directory to search. +
  • +
  • + SciTE enabling of undo and redo toolbar buttons improved. +
  • +
  • + SciTE on Windows file type filters in open dialog sorted. +
  • +
  • + Fixed crashing bug when using automatic tag closing in XML or HTML. +
  • +
  • + Fixed bug on Windows causing very long (>64K) lines to not display. +
  • +
  • + Fixed bug in backwards regular expression searching. +
  • +
  • + Fixed bug in calltips where wrong argument was highlighted. +
  • +
  • + Fixed bug in tab timmy feature when file has line feed line endings. +
  • +
  • + Fixed bug in compiling without INCLUDE_DEPRECATED_FEATURES + defined. +
  • +
+

+ Release 1.48 +

+
    +
  • + Released on 9 September 2002. +
  • +
  • + Improved Pascal lexer with context sensitive keywords + and separate folder which handles //{ and //} folding comments and + {$region} and {$end} folding directives. + The "case" statement now folds correctly. +
  • +
  • + C++ lexer correctly handles comments on preprocessor lines. +
  • +
  • + New commands for moving to beginning and end of display lines when in line + wrap mode. Key bindings added for these commands. +
  • +
  • + New marker symbols that look like ">>>" and "..." which can be used for + interactive shell prompts for Python. +
  • +
  • + The foreground and background colours of visible whitespace can be chosen + independent of the colours chosen for the lexical class of that whitespace. +
  • +
  • + Per line data optimised by using an exponential allocation scheme. +
  • +
  • + SciTE API file loading optimised. +
  • +
  • + SciTE for GTK+ subsystem 2 documented. The exit status of commands + is decoded into more understandable fields. +
  • +
  • + SciTE find dialog remembers previous find string when there is no selection. + Find in Selection button disabled when selection is rectangular as command + did not work. +
  • +
  • + Shift+Enter made equivalent to Enter to avoid users having to let go of + the shift key when typing. Avoids the possibility of entering single carriage + returns in a file that contains CR+LF line ends. +
  • +
  • + Autocompletion does not immediately disappear when the length parameter + to SCI_AUTOCSHOW is 0. +
  • +
  • + SciTE focuses on the editor pane when File | New executed and when the + output pane is closed with F8. Double clicking on a non-highlighted output + pane line selects the word under the cursor rather than seeking the next + highlighted line. +
  • +
  • + SciTE director interface implements an "askproperty" command. +
  • +
  • + SciTE's Export as LaTeX output improved. +
  • +
  • + Better choice of autocompletion displaying above the caret rather then + below when that is more sensible. +
  • +
  • + Bug fixed where context menu would not be completely visible if invoked + when cursor near bottom or left of screen. +
  • +
  • + Crashing bug fixed when displaying long strings on GTK+ caused failure of X server + by displaying long text in segments. +
  • +
  • + Crashing bug fixed on GTK+ when a Scintilla window was removed from its parent + but was still the selection owner. +
  • +
  • + Bug fixed on Windows in Unicode mode where not all characters on a line + were displayed when that line contained some characters not in ASCII. +
  • +
  • + Crashing bug fixed in SciTE on Windows with clearing output while running command. +
  • +
  • + Bug fixed in SciTE for GTK+ with command completion not detected when + no output was produced by the command. +
  • +
  • + Bug fixed in SciTE for Windows where menus were not shown translated. +
  • +
  • + Bug fixed where words failed to display in line wrapping mode with visible + line ends. +
  • +
  • + Bug fixed in SciTE where files opened from a session file were not closed. +
  • +
  • + Cosmetic flicker fixed when using Ctrl+Up and Ctrl+Down with some caret policies. +
  • +
+

+ Release 1.47 +

+
    +
  • + Released on 1 August 2002. +
  • +
  • + Support for GTK+ 2 in Scintilla. International input methods not supported + on GTK+2. +
  • +
  • + Line wrapping performance improved greatly. +
  • +
  • + New caret policy implementation that treats horizontal and vertical + positioning equivalently and independently. Old caret policy methods + deprecated and not all options work correctly with old methods. +
  • +
  • + Extra fold points for C, C++, Java, ... for fold comments //{ .. //} and + #if / #ifdef .. #endif and the #region .. #endregion feature of C#. +
  • +
  • + Scintilla method to find the height in pixels of a line. Currently returns the + same result for every line as all lines are same height. +
  • +
  • + Separate make file, scintilla_vc6.mak, for Scintilla to use Visual C++ + version 6 since main makefile now assumes VS .NET. + VS .NET project files available for combined Scintilla and + SciTE in scite/boundscheck. +
  • +
  • + SciTE automatically recognises Unicode files based + on their Byte Order Marks and switches to Unicode mode. + On Windows, where SciTE supports Unicode display, this + allows display of non European characters. + The file is saved back into the same character encoding unless + the user decides to switch using the File | Encoding menu. +
  • +
  • + Handling of character input changed so that a fillup character, typically '(' + displays a calltip when an autocompletion list was being displayed. +
  • +
  • + Multiline strings lexed better for C++ and Lua. +
  • +
  • + Regular expressions in JavaScript within hypertext files are lexed better. +
  • +
  • + On Windows, Scintilla exports a function called Scintilla_DirectFunction + that can be used the same as the function returned by GetDirectFunction. +
  • +
  • + Scintilla converts line endings of text obtained from the clipboard to + the current default line endings. +
  • +
  • + New SciTE property ensure.final.line.end can ensure that saved files + always end with a new line as this is required by some tools. + The ensure.consistent.line.ends property ensures all line ends are the + current default when saving files. + The strip.trailing.spaces property now works on the buffer so the + buffer in memory and the file on disk are the same after a save is performed. +
  • +
  • + The SciTE expand abbreviation command again allows '|' characters + in expansions to be quoted by using '||'. +
  • +
  • + SciTE on Windows can send data to the find tool through standard + input rather than using a command line argument to avoid problems + with quoting command line arguments. +
  • +
  • + The Stop Executing command in SciTE on Windows improved to send + a Ctrl+Z character to the tool. Better messages when stopping a tool. +
  • +
  • + Autocompletion can automatically "fill up" when one of a set of characters is + type with the autocomplete.<lexer>.fillups property. +
  • +
  • + New predefined properties in SciTE, SelectionStartColumn, SelectionStartLine, + SelectionEndColumn, SelectionEndLine can be used to integrate with other + applications. +
  • +
  • + Environment variables are available as properties in SciTE. +
  • +
  • + SciTE on Windows keeps status line more current. +
  • +
  • + Abbreviations work in SciTE on Linux when first opened. +
  • +
  • + File saving fixed in SciTE to ensure files are not closed when they can not be + saved because of file permissions. Also fixed a problem with buffers that + caused files to not be saved. +
  • +
  • + SciTE bug fixed where monospace mode not remembered when saving files. + Some searching options now remembered when switching files. +
  • +
  • + SciTE on Linux now waits on child termination when it shuts a child down + to avoid zombies. +
  • +
  • + SciTE on Linux has a Print menu command that defaults to invoking a2ps. +
  • +
  • + Fixed incorrect highlighting of indentation guides in SciTE for Python. +
  • +
  • + Crash fixed in Scintilla when calling GetText for 0 characters. +
  • +
  • + Exporting as LaTeX improved when processing backslashes and tabs + and setting up font. +
  • +
  • + Crash fixed in SciTE when exporting or copying as RTF. +
  • +
  • + SciTE session loading fixed to handle more than 10 files in session. +
  • +
+

+ Release 1.46 +

+
    +
  • + Released on 10 May 2002. +
  • +
  • + Set of lexers compiled into Scintilla can now be changed by adding and + removing lexer source files from scintilla/src and running LexGen.py. +
  • +
  • + SCN_ZOOM notification provided by Scintilla when user changes zoom level. + Method to determine width of strings in pixels so that elements can be sized + relative to text size. + SciTE changed to keep line number column displaying a given + number of characters. +
  • +
  • + The logical width of the document used to determine scroll bar range can be set. +
  • +
  • + Setting to allow vertical scrolling to display last line at top rather than + bottom of window. +
  • +
  • + Read-only mode improved to avoid changing the selection in most cases + when a modification is attempted. Drag and drop cursors display correctly + for read-only in some cases. +
  • +
  • + Visual C++ options in make files changed to suit Visual Studio .NET. +
  • +
  • + Scintilla.iface includes feature types for enumerations and lexers. +
  • +
  • + Lua lexer improves handling of literal strings and copes with nested literal strings. +
  • +
  • + Diff lexer changed to treat lines starting with "***" similarly to "---". + Symbolic names defined for lexical classes. +
  • +
  • + nncrontab lexer improved. +
  • +
  • + Turkish fonts (iso8859-9) supported on GTK+. +
  • +
  • + Automatic close tag feature for XML and HTML in SciTE. +
  • +
  • + Automatic indentation in SciTE improved. +
  • +
  • + Maximum number of buffers available in SciTE increased. May be up to 100 + although other restrictions on menu length limit the real maximum. +
  • +
  • + Save a Copy command added to SciTE. +
  • +
  • + Export as TeX command added to SciTE. +
  • +
  • + Export as HTML command in SciTE respects Use Monospaced Font and + background colour settings. +
  • +
  • + Compilation problem on Solaris fixed. +
  • +
  • + Order of files displayed for SciTE's previous and next menu and key commands + are now consistent. +
  • +
  • + Saving of MRU in recent file changed so files open when SciTE quit + are remembered. +
  • +
  • + More variants of ctags tags handled by Open Selected Filename in SciTE. +
  • +
  • + JavaScript embedded in XML highlighted again. +
  • +
  • + SciTE status bar updated after changing parameters in case they are being + displayed in status bar. +
  • +
  • + Crash fixed when handling some multi-byte languages. +
  • +
  • + Crash fixed when replacing end of line characters. +
  • +
  • + Bug in SciTE fixed in multiple buffer mode where automatic loading + turned on could lead to losing file contents. +
  • +
  • + Bug in SciTE on GTK+ fixed where dismissing dialogs with close box led to + those dialogs never being shown again. +
  • +
  • + Bug in SciTE on Windows fixed where position.tile with default positions + led to SciTE being positioned off-screen. +
  • +
  • + Bug fixed in read-only mode, clearing all deletes contraction state data + leading to it not being synchronized with text. +
  • +
  • + Crash fixed in SciTE on Windows when tab bar displayed. +
  • +
+

+ Release 1.45 +

+
    +
  • + Released on 15 March 2002. +
  • +
  • + Line layout cache implemented to improve performance by maintaining + the positioning of characters on lines. Can be set to cache nothing, + the line with the caret, the visible page or the whole document. +
  • +
  • + Support, including a new lexer, added for Matlab programs. +
  • +
  • + Lua folder supports folding {} ranges and compact mode. + Lua lexer styles floating point numbers in number style instead of + setting the '.' in operator style. + Up to 6 sets of keywords. + Better support for [[ although only works well + when all on one line. +
  • +
  • + Python lexer improved to handle floating point numbers that contain negative + exponents and that start with '.'. +
  • +
  • + When performing a rectangular paste, the caret now remains at the + insertion point. +
  • +
  • + On Windows with a wheel mouse, page-at-a-time mode is recognised. +
  • +
  • + Read-only mode added to SciTE with a property to initialise it and another property, + $(ReadOnly) available to show this mode in the status bar. +
  • +
  • + SciTE status bar can show the number of lines in the selection + with the $(SelHeight) property. +
  • +
  • + SciTE's "Export as HTML" command uses the current character set to produce + correct output for non-Western-European character sets, such as Russian. +
  • +
  • + SciTE's "Export as RTF" fixed to produce correct output when file contains '\'. +
  • +
  • + SciTE goto command accepts a column as well as a line. + If given a column, it selects the word at that column. +
  • +
  • + SciTE's Build, Compile and Go commands are now disabled if no + action has been assigned to them. +
  • +
  • + The Refresh button in the status bar has been removed from SciTE on Windows. +
  • +
  • + Bug fixed in line wrap mode where cursor up or down command did not work. +
  • +
  • + Some styling bugs fixed that were due to a compilation problem with + gcc and inline functions with same name but different code. +
  • +
  • + The way that lexers loop over text was changed to avoid accessing beyond the + end or setting beyond the end. May fix some bugs and make the code safer but + may also cause new bugs. +
  • +
  • + Bug fixed in HTML lexer's handling of SGML. +
  • +
  • + Bug fixed on GTK+/X where lines wider than 32767 pixels did not display. +
  • +
  • + SciTE bug fixed with file name generation for standard property files. +
  • +
  • + SciTE bug fixed with Open Selected Filename command when used with + file name and line number combination. +
  • +
  • + In SciTE, indentation and tab settings stored with buffers so maintained correctly + as buffers selected. + The properties used to initialise these settings can now be set separately for different + file patterns. +
  • +
  • + Thread safety improved on Windows with a critical section protecting the font + cache and initialisation of globals performed within Scintilla_RegisterClasses. + New Scintilla_ReleaseResources call provided to allow explicit freeing of resources + when statically bound into another application. Resources automatically freed + in DLL version. The window classes are now unregistered as part of resource + freeing which fixes bugs that occurred in some containers such as Internet Explorer. +
  • +
  • + 'make install' fixed on Solaris. +
  • +
  • + Bug fixed that could lead to a file being opened twice in SciTE. +
  • +
+

+ Release 1.44 +

+
    +
  • + Released on 4 February 2002. +
  • +
  • + Crashing bug fixed in Editor::Paint. +
  • +
  • + Lua lexer no longer treats '.' as a word character and + handles 6 keyword sets. +
  • +
  • + WordStartPosition and WordEndPosition take an onlyWordCharacters + argument. +
  • +
  • + SciTE option for simplified automatic indentation which repeats + the indentation of the previous line. +
  • +
  • + Compilation fix on Alpha because of 64 bit. +
  • +
  • + Compilation fix for static linking. +
  • +
  • + Limited maximum line length handled to 8000 characters as previous + value of 16000 was causing stack exhaustion crashes for some. +
  • +
  • + When whole document line selected, only the last display line gets + the extra selected rectangle at the right hand side rather than + every display line. +
  • +
  • + Caret disappearing bug fixed for the case that the caret was not on the + first display line of a document line. +
  • +
  • + SciTE bug fixed where untitled buffer containing text was sometimes + deleted without chance to save. +
  • +
  • + SciTE bug fixed where use.monospaced not working with + multiple buffers. +
  • +
+

+ Release 1.43 +

+
    +
  • + Released on 19 January 2002. +
  • +
  • + Line wrapping robustness and performance improved in Scintilla. +
  • +
  • + Line wrapping option added to SciTE for both edit and output panes. +
  • +
  • + Static linking on Windows handles cursor resource better. + Documentation of static linking improved. +
  • +
  • + Autocompletion has an option to delete any word characters after the caret + upon selecting an item. +
  • +
  • + FOX version identified by PLAT_FOX in Platform.h. +
  • +
  • + Calltips in SciTE use the calltip.<lexer>.word.characters setting to + correctly find calltips for functions that include characters like '$' which + is not normally considered a word character. +
  • +
  • + SciTE has a command to show help on itself which gets hooked up to displaying + SciTEDoc.html. +
  • +
  • + SciTE option calltip.<lexer>.end.definition to display help text on a + second line of calltip. +
  • +
  • + Fixed the handling of the Buffers menu on GTK+ to ensure current buffer + indicated and no warnings occur. + Changed some menu items on GTK+ version to be same as Windows version. +
  • +
  • + use.monospaced property for SciTE determines initial state of Use Monospaced Font + setting. +
  • +
  • + The SciTE Complete Symbol command now works when there are no word + characters before the caret, even though it is slow to display the whole set of + symbols. +
  • +
  • + Function names removed from SciTE's list of PHP keywords. The full list of + predefined functions is available from another web site mentioned on the + Extras page. +
  • +
  • + Crashing bug at startup on GTK+ for some configurations fixed. +
  • +
  • + Crashing bug on GTK+ on 64 bit platforms fixed. +
  • +
  • + Compilation problem with some compilers fixed in GTK+. +
  • +
  • + Japanese text entry improved on Windows 9x. +
  • +
  • + SciTE recent files directory problem on Windows when HOME and SciTE_HOME + environment variables not set is now the directory of the executable. +
  • +
  • + Session files no longer include untitled buffers. +
  • +
+

+ Release 1.42 +

+
    +
  • + Released on 24 December 2001. +
  • +
  • + Better localisation support including context menus and most messages. + Translations of the SciTE user interface available for Bulgarian, + French, German, Italian, Russian, and Turkish. +
  • +
  • + Can specify a character to use to indicate control characters + rather than having them displayed as mnemonics. +
  • +
  • + Scintilla key command for backspace that will not delete line + end characters. +
  • +
  • + Scintilla method to find start and end of words. +
  • +
  • + SciTE on GTK+ now supports the load.on.activate and save.on.deactivate + properties in an equivalent way to the Windows version. +
  • +
  • + The output pane of SciTE on Windows is now interactive so command line + utilities that prompt for input or confirmation can be used. +
  • +
  • + SciTE on Windows can choose directory for a "Find in Files" + command like the GTK+ version could. +
  • +
  • + SciTE can now load a set of API files rather than just one file. +
  • +
  • + ElapsedTime class added to Platform for accurate measurement of durations. + Used for debugging and for showing the user how long commands take in SciTE. +
  • +
  • + Baan lexer added. +
  • +
  • + In C++ lexer, document comment keywords no longer have to be at the start + of the line. +
  • +
  • + PHP lexer changed to match keywords case insensitively. +
  • +
  • + More shell keywords added. +
  • +
  • + SciTE support for VoiceXML added to xml.properties. +
  • +
  • + In SciTE the selection is not copied to the find field of the Search and Replace + dialogs if it contains end of line characters. +
  • +
  • + SciTE on Windows has a menu item to decide whether to respond to other + instances which are performing their check.if.already.open check. +
  • +
  • + SciTE accelerator key for Box Comment command changed to avoid problems + in non-English locales. +
  • +
  • + SciTE context menu includes Close command for the editor pane and + Hide command for the output pane. +
  • +
  • + output: command added to SciTE director interface to add text to the + output pane. The director interface can execute commands (such as tool + commands with subsystem set to 3) by sending a macro:run message. +
  • +
  • + SciTE on GTK+ will defer to the Window Manager for position if position.left or + position.top not set and for size if position.width or position.height not set. +
  • +
  • + SciTE on Windows has a position.tile property to place a second instance + to the right of the first. +
  • +
  • + Scintilla on Windows again supports EM_GETSEL and EM_SETSEL. +
  • +
  • + Problem fixed in Scintilla on Windows where control ID is no longer cached + as it could be changed by external code. +
  • +
  • + Problems fixed in SciTE on Windows when finding any other open instances at + start up when check.if.already.open is true. +
  • +
  • + Bugs fixed in SciTE where command strings were not always having + variables evaluated. +
  • +
  • + Bugs fixed with displaying partial double-byte and Unicode characters + in rectangular selections and at the edge when edge mode is EDGE_BACKGROUND. + Column numbers reported by GetColumn treat multiple byte characters as one column + rather than counting bytes. +
  • +
  • + Bug fixed with caret movement over folded lines. +
  • +
  • + Another bug fixed with tracking selection in secondary views when performing + modifications. +
  • +
  • + Horizontal scrolling and display of long lines optimised. +
  • +
  • + Cursor setting in Scintilla on GTK+ optimised. +
  • +
  • + Experimental changeable style attribute. + Set to false to make text read-only. + Currently only stops caret from being within not-changeable + text and does not yet stop deleting a range that contains + not-changeable text. + Can be used from SciTE by adding notchangeable to style entries. +
  • +
  • + Experimental line wrapping. + Currently has performance and appearence problems. +
  • +
+

+ Release 1.41 +

+
    +
  • + Released on 6 November 2001. +
  • +
  • + Changed Platform.h to not include platform headers. This lessens likelihood and impact of + name clashes from system headers and also speeds up compilation. + Renamed DrawText to DrawTextNoClip to avoid name clash. +
  • +
  • + Changed way word functions work to treat a sequence of punctuation as + a word. This is more sensible and also more compatible with other editors. +
  • +
  • + Cursor changes over the margins and selection on GTK+ platform. +
  • +
  • + SC_MARK_BACKGROUND is a marker that only changes the line's background colour. +
  • +
  • + Enhanced Visual Basic lexer handles character date and octal literals, + and bracketed keywords for VB.NET. There are two VB lexers, vb and vbscript + with type indication characters like ! and $ allowed at the end of identifiers + in vb but not vbscript. Lexer states now separate from those used for C++ and + names start with SCE_B. +
  • +
  • + Lexer added for Bullant language. +
  • +
  • + The horizontal scroll position, xOffset, is now exposed through the API. +
  • +
  • + The SCN_POSCHANGED notification is deprecated as it was causing confusion. + Use SCN_UPDATEUI instead. +
  • +
  • + Compilation problems fixed for some versions of gcc. +
  • +
  • + Support for WM_GETTEXT restored on Windows. +
  • +
  • + Double clicking on an autocompletion list entry works on GTK+. +
  • +
  • + Bug fixed with case insensitive sorts for autocompletion lists. +
  • +
  • + Bug fixed with tracking selection in secondary views when performing modifications. +
  • +
  • + SciTE's abbreviation expansion feature will now indent expansions to the current + indentation level if indent.automatic is on. +
  • +
  • + SciTE allows setting up of parameters to commands from a dialog and can also + show this dialog automatically to prompt for arguments when running a command. +
  • +
  • + SciTE's Language menu (formerly Options | Use Lexer) is now defined by the + menu.language property rather than being hardcoded. +
  • +
  • + The user interface of SciTE can be localised to a particular language by editing + a locale.properties file. +
  • +
  • + On Windows, SciTE will try to move to the front when opening a new file from + the shell and using check.if.already.open. +
  • +
  • + SciTE can display the file name and directory in the title bar in the form + "file @ directory" when title.full.path=2. +
  • +
  • + The SciTE time.commands property reports the time taken by a command as well + as its status when completed. +
  • +
  • + The SciTE find.files property is now a list separated by '|' characters and this list is + added into the Files pull down of the Find in Files dialog. +
  • +
+

+ Release 1.40 +

+
    +
  • + Released on 23 September 2001. +
  • +
  • + Removal of emulation of Win32 RichEdit control in core of Scintilla. + This change may be incompatible with existing client code. + Some emulation still done in Windows platform layer. +
  • +
  • + SGML support in the HTML/XML lexer. +
  • +
  • + SciTE's "Stop Executing" command will terminate GUI programs on + Windows NT and Windows 2000. +
  • +
  • + StyleContext class helps construct lexers that are simple and accurate. + Used in the C++, Eiffel, and Python lexers. +
  • +
  • + Clipboard operations in GTK+ version convert between platform '\n' line endings and + currently chosen line endings. +
  • +
  • + Any character in range 0..255 can be used as a marker. + This can be used to support numbered bookmarks, for example. +
  • +
  • + The default scripting language for ASP can be set. +
  • +
  • + New lexer and other support for crontab files used with the nncron scheduler. +
  • +
  • + Folding of Python improved. +
  • +
  • + The ` character is treated as a Python operator. +
  • +
  • + Line continuations ("\" at end of line) handled inside Python strings. +
  • +
  • + More consistent handling of line continuation ('\' at end of line) in + C++ lexer. + This fixes macro definitions that span more than one line. +
  • +
  • + C++ lexer can understand Doxygen keywords in doc comments. +
  • +
  • + SciTE on Windows allows choosing to open the "open" dialog on the directory + of the current file rather than in the default directory. +
  • +
  • + SciTE on Windows handles command line arguments in "check.if.already.open" + correctly when the current directory of the new instance is different to the + already open instance of SciTE. +
  • +
  • + "cwd" command (change working directory) defined for SciTE director interface. +
  • +
  • + SciTE "Export As HTML" produces better, more compliant, and shorter files. +
  • +
  • + SciTE on Windows allows several options for determining default file name + for exported files. +
  • +
  • + Automatic indentation of Python in SciTE fixed. +
  • +
  • + Exported HTML can support folding. +
  • +
  • + Bug fixed in SCI_GETTEXT macro command of director interface. +
  • +
  • + Cursor leak fixed on GTK+. +
  • +
  • + During SciTE shutdown, "identity" messages are no longer sent over the director interface. +
  • +
+

+ Release 1.39 +

+
    +
  • + Released on 22 August 2001. +
  • +
  • + Windows version requires msvcrt.dll to be available so will not work + on original Windows 95 version 1. The msvcrt.dll file is installed + by almost everything including Internet Explorer so should be available. +
  • +
  • + Flattened tree control style folding margin. The SciTE fold.plus option is + now fold.symbols and has more values for the new styles. +
  • +
  • + Mouse dwell events are generated when the user holds the mouse steady + over Scintilla. +
  • +
  • + PositionFromPointClose is like PositionFromPoint but returns + INVALID_POSITION when point outside window or after end of line. +
  • +
  • + Input of Hungarian and Russian characters in GTK+ version works by + truncating input to 8 bits if in the range of normal characters. +
  • +
  • + Better choices for font descriptors on GTK+ for most character sets. +
  • +
  • + GTK+ Scintilla is destroyed upon receiving destroy signal rather than + destroy_event signal. +
  • +
  • + Style setting that force upper or lower case text. +
  • +
  • + Case-insensitive autocompletion lists work correctly. +
  • +
  • + Keywords can be prefix based so ^GTK_ will treat all words that start + with GTK_ as keywords. +
  • +
  • + Horizontal scrolling can be jumpy rather than gradual. +
  • +
  • + GetSelText places a '\0' in the buffer if the selection is empty.. +
  • +
  • + EnsureVisible split into two methods EnsureVisible which will not scroll to show + the line and EnsureVisibleEnforcePolicy which may scroll. +
  • +
  • + Python folder has options to fold multi-line comments and triple quoted strings. +
  • +
  • + C++ lexer handles keywords before '.' like "this.x" in Java as keywords. + Compact folding mode option chooses whether blank lines after a structure are + folded with that structure. Second set of keywords with separate style supported. +
  • +
  • + Ruby lexer handles multi-line comments. +
  • +
  • + VB has folder. +
  • +
  • + PHP lexer has an operator style, handles "<?" and "?>" inside strings + and some comments. +
  • +
  • + TCL lexer which is just an alias for the C++ lexer so does not really + understand TCL syntax. +
  • +
  • + Error lines lexer has styles for Lua error messages and .NET stack traces. +
  • +
  • + Makefile lexer has a target style. +
  • +
  • + Lua lexer handles some [[]] string literals. +
  • +
  • + HTML and XML lexer have a SCE_H_SGML state for tags that + start with "<!". +
  • +
  • + Fixed Scintilla bugs with folding. When modifications were performed near + folded regions sometimes no unfolding occurred when it should have. Deleting a + fold causing character sometimes failed to update fold information correctly. +
  • +
  • + Better support for Scintilla on GTK+ for Win32 including separate + PLAT_GTK_WIN32 definition and correct handling of rectangular selection + with clipboard operations. +
  • +
  • + SciTE has a Tools | Switch Pane (Ctrl+F6) command to switch focus between + edit and output panes. +
  • +
  • + SciTE option output.scroll allows automatic scrolling of output pane to + be turned off. +
  • +
  • + Commands can be typed into the SciTE output pane similar to a shell window. +
  • +
  • + SciTE properties magnification and output magnification set initial zoom levels. +
  • +
  • + Option for SciTE comment block command to place comments at start of line. +
  • +
  • + SciTE for Win32 has an option to minimize to the tray rather than the task bar. +
  • +
  • + Close button on SciTE tool bar for Win32. +
  • +
  • + SciTE compiles with GCC 3.0. +
  • +
  • + SciTE's automatic indentation of C++ handles braces without preceding keyword + correctly. +
  • +
  • + Bug fixed with GetLine method writing past the end of where it should. +
  • +
  • + Bug fixed with mouse drag automatic scrolling when some lines were folded. +
  • +
  • + Bug fixed because caret XEven setting was inverted. +
  • +
  • + Bug fixed where caret was initially visible even though window was not focussed. +
  • +
  • + Bug fixed where some file names could end with "\\" which caused slow + downs on Windows 9x. +
  • +
  • + On Win32, SciTE Replace dialog starts with focus on replacement text. +
  • +
  • + SciTE Go to dialog displays correct current line. +
  • +
  • + Fixed bug with SciTE opening multiple files at once. +
  • +
  • + Fixed bug with Unicode key values reported to container truncated. +
  • +
  • + Fixed bug with unnecessary save point notifications. +
  • +
  • + Fixed bugs with indenting and unindenting at start of line. +
  • +
  • + Monospace Font setting behaves more consistently. +
  • +
+

+ Release 1.38 +

+
    +
  • + Released on 23 May 2001. +
  • +
  • + Loadable lexer plugins on Windows. +
  • +
  • + Ruby lexer and support. +
  • +
  • + Lisp lexer and support. +
  • +
  • + Eiffel lexer and support. +
  • +
  • + Modes for better handling of Tab and BackSpace keys within + indentation. Mode to avoid autocompletion list cancelling when + there are no viable matches. +
  • +
  • + ReplaceTarget replaced with two calls ReplaceTarget + (which is incompatible with previous ReplaceTarget) and + ReplaceTargetRE. Both of these calls have a count first + parameter which allows using strings containing nulls. + SearchInTarget and SetSearchFlags functions allow + specifying a search in several simple steps which helps + some clients which can not create structs or pointers easily. +
  • +
  • + Asian language input through an Input Method Editor works + on Windows 2000. +
  • +
  • + On Windows, control characters can be entered through use of + the numeric keypad in conjunction with the Alt key. +
  • +
  • + Document memory allocation changed to grow exponentially + which reduced time to load a 30 Megabyte file from + 1000 seconds to 25. Change means more memory may be used. +
  • +
  • + Word part movement keys now handled in Scintilla rather than + SciTE. +
  • +
  • + Regular expression '^' and '$' work more often allowing insertion + of text at start or end of line with a replace command. + Backslash quoted control characters \a, \b, \f, \t, and \v + recognised within sets. +
  • +
  • + Session files for SciTE. +
  • +
  • + Export as PDF command hidden in SciTE as it often failed. + Code still present so can be turned on by those willing to cope. +
  • +
  • + Bug fixed in HTML lexer handling % before > as end ASP + even when no start ASP encountered. + Bug fixed when scripts ended with a quoted string and + end tag was not seen. +
  • +
  • + Bug fixed on Windows where context menu key caused menu to + appear in corner of screen rather than within window. +
  • +
  • + Bug fixed in SciTE's Replace All command not processing + whole file when replace string longer than search string. +
  • +
  • + Bug fixed in SciTE's MRU list repeating entries if Ctrl+Tab + used when all entries filled. +
  • +
  • + ConvertEOLs call documentation fixed. +
  • +
+

+ Release 1.37 +

+
    +
  • + Released on 17 April 2001. +
  • +
  • + Bug fixed with scroll bars being invisible on GTK+ 1.2.9. +
  • +
  • + Scintilla and SciTE support find and replace using simple regular + expressions with tagged expressions. SciTE supports C '\' escapes + in the Find and Replace dialogs. + Replace in Selection available in SciTE. +
  • +
  • + Scintilla has a 'target' feature for replacing code rapidly without + causing display updates. +
  • +
  • + Scintilla and SciTE on GTK+ support file dropping from file managers + such as Nautilus and gmc. Files or other URIs dropped on Scintilla + result in a URIDropped notification. +
  • +
  • + Lexers may have separate Lex and Fold functions. +
  • +
  • + Lexer infrastructure improved to allow for plug in lexers and for referring + to lexers by name rather than by ID. +
  • +
  • + Ada lexer and support added. +
  • +
  • + Option in both Scintilla and SciTE to treat both left and right margin + as equally important when repositioning visible area in response to + caret movement. Default is to prefer visible area positioning which + minimises the horizontal scroll position thus favouring the left margin. +
  • +
  • + Caret line highlighting. +
  • +
  • + Commands to delete from the caret to the end of line and + from the caret to the beginning of line. +
  • +
  • + SciTE has commands for inserting and removing block comments and + for inserting stream comments. +
  • +
  • + SciTE Director interface uses C++ '\' escapes to send control characters. +
  • +
  • + SciTE Director interface adds more commands including support for macros. +
  • +
  • + SciTE has menu options for recording and playing macros which are visible + when used with a companion program that supports these features. +
  • +
  • + SciTE has an Expand Abbreviation command. + Abbreviations are stored in a global abbrev.properties file. +
  • +
  • + SciTE has a Full Screen command to switch between a normal window + size and using the full screen. On Windows, the menu bar can be turned + off when in full screen mode. +
  • +
  • + SciTE has a Use monospaced font command to switch between the normal + set of fonts and one size of a particular fixed width font. +
  • +
  • + SciTE's use of tabs can be controlled for particular file names + as well as globally. +
  • +
  • + The contents of SciTE's status bar can be defined by a property and + include variables. On Windows, several status bar definitions can be active + with a click on the status bar cycling through them. +
  • +
  • + Copy as RTF command in SciTE on Windows to allow pasting + styled text into word processors. +
  • +
  • + SciTE can allow the use of non-alphabetic characters in + Complete Symbol lists and can automatically display this autocompletion + list when a trigger character such as '.' is typed. + Complete word can be set to pop up when the user is typing a word and + there is only one matching word in the document. +
  • +
  • + SciTE lists the imported properties files on a menu to allow rapid + access to them. +
  • +
  • + SciTE on GTK+ improvements to handling accelerator keys and focus + in dialogs. Message boxes respond to key presses without the Alt key as + they have no text entries to accept normal keystrokes. +
  • +
  • + SciTE on GTK+ sets the application icon. +
  • +
  • + SciTE allows setting the colours used to indicate the current + error line. +
  • +
  • + Variables within PHP strings have own style. Keyword list updated. +
  • +
  • + Keyword list for Lua updated for Lua 4.0. +
  • +
  • + Bug fixed in rectangular selection where rectangle still appeared + selected after using cursor keys to move caret. +
  • +
  • + Bug fixed in C++ lexer when deleting a '{' controlling a folded range + led to that range becoming permanently invisible. +
  • +
  • + Bug fixed in Batch lexer where comments were not recognised. +
  • +
  • + Bug fixed with undo actions coalescing into steps incorrectly. +
  • +
  • + Bug fixed with Scintilla on GTK+ positioning scroll bars 1 pixel + over the Scintilla window leading to their sides being chopped off. +
  • +
  • + Bugs fixed in SciTE when doing some actions led to the start + or end of the file being displayed rather than the current location. +
  • +
  • + Appearance of calltips fixed to look like document text including + any zoom factor. Positioned to be outside current line even when + multiple fonts and sizes used. +
  • +
  • + Bug fixed in Scintilla macro support where typing Enter caused both a newline + command and newline character insertion to be recorded. +
  • +
  • + Bug fixed in SciTE on GTK+ where focus was moving + between widgets incorrectly. +
  • +
  • + Bug fixed with fold symbols sometimes not updating when + the text changed. +
  • +
  • + Bugs fixed in SciTE's handling of folding commands. +
  • +
  • + Deprecated undo collection enumeration removed from API. +
  • +
+

+ Release 1.36 +

+
    +
  • + Released on 1 March 2001. +
  • +
  • + Scintilla supports GTK+ on Win32. +
  • +
  • + Some untested work on making Scintilla and SciTE 64 bit compatible. + For users on GTK+ this requires including Scintilla.h before + ScintillaWidget.h. +
  • +
  • + HTML lexer allows folding HTML. +
  • +
  • + New lexer for Avenue files which are used in the ESRI ArcView GIS. +
  • +
  • + DOS Batch file lexer has states for '@', external commands, variables and + operators. +
  • +
  • + C++ lexer can fold comments of /* .. */ form. +
  • +
  • + Better disabling of pop up menu items in Scintilla when in read-only mode. +
  • +
  • + Starting to move to Doxygen compatible commenting. +
  • +
  • + Director interface on Windows enables another application to control SciTE. +
  • +
  • + Opening SciTE on Windows 9x sped up greatly for some cases. +
  • +
  • + The command.build.directory property allows SciTE to run the build + command in a different directory to the source files. +
  • +
  • + SciTE on Windows allows setting foreground and background colours + for printed headers and footers. +
  • +
  • + Bug fixed in finding calltips in SciTE which led to no calltips for some identifiers. +
  • +
  • + Documentation added for lexers and for the extension and director interfaces. +
  • +
  • + SciTE menus rearranged with new View menu taking over some of the items that + were under the Options menu. Clear All Bookmarks command added. +
  • +
  • + Clear Output command in SciTE. +
  • +
  • + SciTE on Windows gains an Always On Top command. +
  • +
  • + Bug fixed in SciTE with attempts to define properties recursively. +
  • +
  • + Bug fixed in SciTE properties where only one level of substitution was done. +
  • +
  • + Bug fixed in SciTE properties where extensions were not being + matched in a case insensitive manner. +
  • +
  • + Bug fixed in SciTE on Windows where the Go to dialog displays the correct + line number. +
  • +
  • + In SciTE, if fold.on.open set then switching buffers also performs fold. +
  • +
  • + Bug fixed in Scintilla where ensuring a line was visible in the presence of folding + operated on the document line instead of the visible line. +
  • +
  • + SciTE command line processing modified to operate on arguments in order and in + two phases. First any arguments before the first file name are processed, then the + UI is opened, then the remaining arguments are processed. Actions defined for the + Director interface (currently only "open") may also be used on the command line. + For example, "SciTE -open:x.txt" will start SciTE and open x.txt. +
  • +
  • + Numbered menu items SciTE's Buffers menu and the Most Recently Used portion + of the File menu go from 1..0 rather than 0..9. +
  • +
  • + The tab bar in SciTE for Windows has numbers. + The tab.hide.one option hides the tab bar until there is more than one buffer open. +
  • +
+

+ Release 1.35 +

+
    +
  • + Released on 29 January 2001. +
  • +
  • + Rewritten and simplified widget code for the GTK+ version to enhance + solidity and make more fully compliant with platform norms. This includes more + normal handling of keystrokes so they are forwarded to containers correctly. +
  • +
  • + User defined lists can be shown. +
  • +
  • + Many fixes to the Perl lexer. +
  • +
  • + Pascal lexer handles comments more correctly. +
  • +
  • + C/C++/Java/JavaScipt lexer has a state for line doc comments. +
  • +
  • + Error output lexer understands Sun CC messages. +
  • +
  • + Make file lexer has variable, preprocessor, and operator states. +
  • +
  • + Wider area given to an italics character that is at the end of a line to prevent it + being cut off. +
  • +
  • + Call to move the caret inside the currently visible area. +
  • +
  • + Paste Rectangular will space fill on the left hand side of the pasted text as + needed to ensure it is kept rectangular. +
  • +
  • + Cut and Paste Rectangular does nothing in read-only mode. +
  • +
  • + Undo batching changed so that a paste followed by typing creates two undo actions.. +
  • +
  • + A "visibility policy" setting for Scintilla determines which range of lines are displayed + when a particular line is moved to. Also exposed as a property in SciTE. +
  • +
  • + SciTE command line allows property settings. +
  • +
  • + SciTE has a View Output command to hide or show the output pane. +
  • +
  • + SciTE's Edit menu has been split in two with searching commands moved to a + new Search menu. Find Previous and Previous Bookmark are in the Search menu. +
  • +
  • + SciTE on Windows has options for setting print margins, headers and footers. +
  • +
  • + SciTE on Windows has tooltips for toolbar. +
  • +
  • + SciTE on GTK+ has properties for setting size of file selector. +
  • +
  • + Visual and audio cues in SciTE on Windows enhanced. +
  • +
  • + Fixed performance problem in SciTE for GTK+ by dropping the extra 3D + effect on the content windows. +
  • +
  • + Fixed problem in SciTE where choosing a specific lexer then meant + that no lexer was chosen when files opened. +
  • +
  • + Default selection colour changed to be visible on low colour displays. +
  • +
  • + Fixed problems with automatically reloading changed documents in SciTE on + Windows. +
  • +
  • + Fixed problem with uppercase file extensions in SciTE. +
  • +
  • + Fixed some problems when using characters >= 128, some of which were being + incorrectly treated as spaces. +
  • +
  • + Fixed handling multiple line tags, non-inline scripts, and XML end tags /> in HTML/XML lexer. +
  • +
  • + Bookmarks in SciTE no longer disappear when switching between buffers. +
  • +
+

+ Release 1.34 +

+
    +
  • + Released on 28 November 2000. +
  • +
  • + Pascal lexer. +
  • +
  • + Export as PDF in SciTE. +
  • +
  • + Support for the OpenVMS operating system in SciTE. +
  • +
  • + SciTE for GTK+ can check for another instance of SciTE + editing a file and switch to it rather than open a second instance + on one file. +
  • +
  • + Fixes to quoting and here documents in the Perl lexer. +
  • +
  • + SciTE on Windows can give extra visual and audio cues when a + warning is shown or find restarts from beginning of file. +
  • +
  • + Open Selected Filename command in SciTE. Also understands some + warning message formats. +
  • +
  • + Wider area for line numbers when printing. +
  • +
  • + Better scrolling performance on GTK+. +
  • +
  • + Fixed problem where rectangles with negative coordinates were + invalidated leading to trouble with platforms that use + unsigned coordinates. +
  • +
  • + GTK+ Scintilla uses more compliant signalling code so that keyboard + events should propagate to containers. +
  • +
  • + Bug fixed with opening full or partial paths. +
  • +
  • + Improved handling of paths in error messages in SciTE. +
  • +
  • + Better handling of F6 in SciTE. +
  • +
+

+ Release 1.33 +

+
    +
  • + Released on 6 November 2000. +
  • +
  • + XIM support for the GTK+ version of Scintilla ensures that more non-English + characters can be typed. +
  • +
  • + Caret may be 1, 2, or 3 pixels wide. +
  • +
  • + Cursor may be switched to wait image during lengthy processing. +
  • +
  • + Scintilla's internal focus flag is exposed for clients where focus is handled in + complex ways. +
  • +
  • + Error status defined for Scintilla to hold indication that an operation failed and the reason + for that failure. No detection yet implemented but clients may start using the interface + so as to be ready for when it does. +
  • +
  • + Context sensitive help in SciTE. +
  • +
  • + CurrentWord property available in SciTE holding the value of the word the + caret is within or near. +
  • +
  • + Apache CONF file lexer. +
  • +
  • + Changes to Python lexer to allow 'as' as a context sensitive keyword and the + string forms starting with u, r, and ur to be recognised. +
  • +
  • + SCN_POSCHANGED notification now working and SCN_PAINTED notification added. +
  • +
  • + Word part movement commands for cursoring between the parts of reallyLongCamelIdentifiers and + other_ways_of_making_words. +
  • +
  • + When text on only one line is selected, Shift+Tab moves to the previous tab stop. +
  • +
  • + Tab control available for Windows version of SciTE listing all the buffers + and making it easy to switch between them. +
  • +
  • + SciTE can be set to automatically determine the line ending type from the contents of a + file when it is opened. +
  • +
  • + Dialogs in GTK+ version of SciTE made more modal and have accelerator keys. +
  • +
  • + Find in Files command in GTK+ version of SciTE allows choice of directory. +
  • +
  • + On Windows, multiple files can be opened at once. +
  • +
  • + SciTE source broken up into more files. +
  • +
  • + Scintilla headers made safe for C language, not just C++. +
  • +
  • + New printing modes - force background to white and force default background to white. +
  • +
  • + Automatic unfolding not occurring when Enter pressed at end of line bug fixed. +
  • +
  • + Bugs fixed in line selection. +
  • +
  • + Bug fixed with escapes in PHP strings in the HTML lexer. +
  • +
  • + Bug fixed in SciTE for GTK+ opening files when given full paths. +
  • +
  • + Bug fixed in autocompletion where user backspaces into existing text. +
  • +
  • + Bugs fixed in opening files and ensuring they are saved before running. + A case bug also fixed here. +
  • +
+

+ Release 1.32 +

+
    +
  • + Released on 8 September 2000. +
  • +
  • + Fixes bugs in complete word and related code. Protection against a bug when + receiving a bad argument. +
  • +
+

+ Release 1.31 +

+
    +
  • + Released on 6 September 2000. +
  • +
  • + Scintilla is available as a COM control from the scintillactrl module in CVS. +
  • +
  • + Style setting to underline text. Exposed in SciTE as "underlined". +
  • +
  • + Style setting to make text invisible. +
  • +
  • + SciTE has an extensibility interface that can be used to implement features such as + a scripting language or remote control. An example use of this is the extlua module + available from CVS which allows SciTE to be scripted in Lua. +
  • +
  • + Many minor fixes to all of the lexers. +
  • +
  • + New lexer for diff and patch files. +
  • +
  • + Error message lexer understands Perl error messages. +
  • +
  • + C/C++/Java lexer now supports C#, specifically verbatim strings and + @ quoting of identifiers that are the same as keywords. SciTE has + a set of keywords for C# and a build command set up for C#. +
  • +
  • + Scintilla property to see whether in overtype or insert state. +
  • +
  • + PosChanged notification fired when caret moved. +
  • +
  • + Comboboxes in dialogs in SciTE on Windows can be horizontally scrolled. +
  • +
  • + Autocompletion and calltips can treat the document as case sensitive or + case insensitive. +
  • +
  • + Autocompletion can be set to automatically choose the only + element in a single element list. +
  • +
  • + Set of characters that automatically complete an autocompletion list + can be set. +
  • +
  • + SciTE command to display calltip - useful when dropped because of + editing. +
  • +
  • + SciTE has a Revert command to go back to the last saved version. +
  • +
  • + SciTE has an Export as RTF command. Save as HTML is renamed + to Export as HTML and is located on the Export sub menu. +
  • +
  • + SciTE command "Complete Word" searches document for any + words starting with characters before caret. +
  • +
  • + SciTE options for changing aspects of the formatting of files exported + as HTML or RTF. +
  • +
  • + SciTE "character.set" option for choosing the character + set for all fonts. +
  • +
  • + SciTE has a "Toggle all folds" command. +
  • +
  • + The makefiles have changed. The makefile_vc and + makefile_bor files in scintilla/win32 and scite/win32 have been + merged into scintilla/win32/scintilla.mak and scite/win32/scite.mak. + DEBUG may be defined for all make files and this will turn on + assertions and for some make files will choose other debugging + options. +
  • +
  • + To make debugging easier and allow good use of BoundsChecker + there is a Visual C++ project file in scite/boundscheck that builds + all of Scintilla and SciTE into one executable. +
  • +
  • + The size of the SciTE output window can be set with the + output.horizontal.size and output.vertical.size settings. +
  • +
  • + SciTE status bar indicator for insert or overwrite mode. +
  • +
  • + Performance improvements to autocompletion and calltips. +
  • +
  • + A caret redraw problem when undoing is fixed. +
  • +
  • + Crash with long lines fixed. +
  • +
  • + Bug fixed with merging markers when lines merged. +
  • +
+

+ Release 1.30 +

+
    +
  • + Released on 26 July 2000. +
  • +
  • + Much better support for PHP which is now an integral part of the HTML support. +
  • +
  • + Start replacement of Windows-specific APIs with cross platform APIs. + In 1.30, the new APIs are introduced but the old APIs are still available. + For the GTK+ version, may have to include "WinDefs.h" explicitly to + use the old APIs. +
  • +
  • + "if" and "import" statements in SciTE properties files allows modularisation into + language-specific properties files and choices based upon platform. + This means that SciTE is delivered with 9 language-specific properties files + as well as the standard SciTEGlobal.properties file. +
  • +
  • + Much lower resource usage on Windows 9x. +
  • +
  • + "/p" option in SciTE on Windows for printing a file and then exiting. +
  • +
  • + Options for printing with inverted brightness (when the screen is set to use + a dark background) and to force black on white printing. +
  • +
  • + Option for printing magnified or miniaturised from screen settings. +
  • +
  • + In SciTE, Ctrl+F3 and Ctrl+Shift+F3 find the selection in the forwards and backwards + directions respectively. +
  • +
  • + Auto-completion lists may be set to cancel when the cursor goes before + its start position or before the start of string being completed. +
  • +
  • + Auto-completion lists automatically size more sensibly. +
  • +
  • + SCI_CLEARDOCUMENTSTYLE zeroes all style bytes, ensures all + lines are shown and deletes all folding information. +
  • +
  • + On Windows, auto-completion lists are visually outdented rather than indented. +
  • +
  • + Close all command in SciTE. +
  • +
  • + On Windows multiple files can be dragged into SciTE. +
  • +
  • + When saving a file, the SciTE option save.deletes.first deletes it before doing the save. + This allows saving with a different capitalisation on Windows. +
  • +
  • + When use tabs option is off pressing the tab key inserts spaces. +
  • +
  • + Bug in indicators leading to extra line drawn fixed. +
  • +
+

+ Release 1.28 +

+
    +
  • + Released on 27 June 2000. +
  • +
  • + Fixes crash in indentation guides when indent size set to 0. +
  • +
  • + Fixes to installation on GTK+/Linux. User properties file on GTK+ has a dot at front of name: + .SciTEUser.properties. Global properties file location configurable at compile time + defaulting to $prefix/share/scite. $prefix determined from Gnome if present else its + /usr/local and can be overridden by installer. Gnome menu integration performed in + make install if Gnome present. +
  • +
+

+ Release 1.27 +

+
    +
  • + Released on 23 June 2000. +
  • +
  • + Indentation guides. View whitespace mode may be set to not display whitespace + in indentation. +
  • +
  • + Set methods have corresponding gets for UndoCollection, BufferedDraw, + CodePage, UsePalette, ReadOnly, CaretFore, and ModEventMask. +
  • +
  • + Caret is continuously on rather than blinking while typing or holding down + delete or backspace. And is now always shown if non blinking when focused on GTK+. +
  • +
  • + Bug fixed in SciTE with file extension comparison now done in case insensitive way. +
  • +
  • + Bugs fixed in SciTE's file path handling on Windows. +
  • +
  • + Bug fixed with preprocessor '#' last visible character causing hang. +
  • +
+

+ Release 1.26 +

+
    +
  • + Released on 13 June 2000. +
  • +
  • + Support for the Lua language in both Scintilla and SciTE. +
  • +
  • + Multiple buffers may be open in SciTE. +
  • +
  • + Each style may have a character set configured. This may determine + the characters that are displayed by the style. +
  • +
  • + In the C++ lexer, lexing of preprocessor source may either treat it all as being in + the preprocessor class or only the initial # and preprocessor command word as + being in the preprocessor class. +
  • +
  • + Scintilla provides SCI_CREATEDOCUMENT, SCI_ADDREFDOCUMENT, and + SCI_RELEASEDOCUMENT to make it easier for a container to deal with multiple + documents. +
  • +
  • + GTK+ specific definitions in Scintilla.h were removed to ScintillaWidget.h. All GTK+ clients will need to + #include "ScintillaWidget.h". +
  • +
  • + For GTK+, tools can be executed in the background by setting subsystem to 2. +
  • +
  • + Keys in the properties files are now case sensitive. This leads to a performance increase. +
  • +
  • + Menu to choose which lexer to use on a file. +
  • +
  • + Tab size dialog on Windows. +
  • +
  • + File dialogs enlarged on GTK+. +
  • +
  • + Match Brace command bound to Ctrl+E on both platforms with Ctrl+] a synonym on Windows. + Ctrl+Shift+E is select to matching brace. Brace matching tries to match to either the inside or the + outside, depending on whether the cursor is inside or outside the braces initially. + View End of Line bound to Ctrl+Shift+O. +
  • +
  • + The Home key may be bound to move the caret to either the start of the line or the start of the + text on the line. +
  • +
  • + Visual C++ project file for SciTE. +
  • +
  • + Bug fixed with current x location after Tab key. +
  • +
  • + Bug fixed with hiding fold margin by setting fold.margin.width to 0. +
  • +
  • + Bugs fixed with file name confusion on Windows when long and short names used, or different capitalisations, + or relative paths. +
  • +
+

+ Release 1.25 +

+
    +
  • + Released on 9 May 2000. +
  • +
  • + Some Unicode support on Windows. Treats buffer and API as UTF-8 and displays + through UCS-2 of Windows. +
  • +
  • + Automatic indentation. Indentation size can be different to tab size. +
  • +
  • + Tool bar. +
  • +
  • + Status bar now on Windows as well as GTK+. +
  • +
  • + Input fields in Find and Replace dialogs now have history on both Windows and + GTK+. +
  • +
  • + Auto completion list items may be separated by a chosen character to allow spaces + in items. The selected item may be changed through the API. +
  • +
  • + Horizontal scrollbar can be turned off. +
  • +
  • + Property to remove trailing spaces when saving file. +
  • +
  • + On Windows, changed font size calculation to be more compatible with + other applications. +
  • +
  • + On GTK+, SciTE's global properties files are looked for in the directory specified in the + SCITE_HOME environment variable if it is set. This allows hiding in a dot directory. +
  • +
  • + Keyword lists in SciTE updated for JavaScript to include those destined to be used in + the future. IDL includes XPIDL keywords as well as MSIDL keywords. +
  • +
  • + Zoom level can be set and queried through API. +
  • +
  • + New notification sent before insertions and deletions. +
  • +
  • + LaTeX lexer. +
  • +
  • + Fixes to folding including when deletions and additions are performed. +
  • +
  • + Fix for crash with very long lines. +
  • +
  • + Fix to affect all of rectangular selections with deletion and case changing. +
  • +
  • + Removed non-working messages that had been included only for Richedit compatibility. +
  • +
+

+ Release 1.24 +

+
    +
  • + Released on 29 March 2000. +
  • +
  • + Added lexing of IDL based on C++ lexer with extra UUID lexical class. +
  • +
  • + Functions and associated keys for Line Delete, Line Cut, Line Transpose, + Selection Lower Case and Selection Upper Case. +
  • +
  • + Property setting for SciTE, eol.mode, chooses initial state of line end characters. +
  • +
  • + Fixed bugs in undo history with small almost-contiguous changes being incorrectly coalesced. +
  • +
  • + Fixed bugs with incorrect expansion of ContractionState data structures causing crash. +
  • +
  • + Fixed bugs relating to null fonts. +
  • +
  • + Fixed bugs where recolourisation was not done sometimes when required. +
  • +
  • + Fixed compilation problems with SVector.h. +
  • +
  • + Fixed bad setting of fold points in Python. +
  • +
+

+ Release 1.23 +

+
    +
  • + Released on 21 March 2000. +
  • +
  • + Directory structure to separate on basis of product (Scintilla, SciTE, DMApp) + and environment (Cross-platform, Win32, GTK+). +
  • +
  • + Download packaging to allow download of the source or platform dependent executables. +
  • +
  • + Source code now available from CVS at SourceForge. +
  • +
  • + Very simple Windows-only demonstration application DMApp is available from cvs as dmapp. +
  • +
  • + Lexing functionality may optionally be included in Scintilla rather than be provided by + the container. +
  • +
  • + Set of lexers included is determined at link time by defining which of the Lex* object files + are linked in. +
  • +
  • + On Windows, the SciLexer.DLL extends Scintilla.DLL with the standard lexers. +
  • +
  • + Enhanced HTML lexer styles embedded VBScript and Python. + ASP segments are styled and ASP scripts in JavaScript, VBScript and Python are styled. +
  • +
  • + PLSQL and PHP supported. +
  • +
  • + Maximum number of lexical states extended to 128. +
  • +
  • + Lexers may store per line parse state for multiple line features such as ASP script language choice. +
  • +
  • + Lexing API simplified. +
  • +
  • + Project file for Visual C++. +
  • +
  • + Can now cycle through all recent files with Ctrl+Tab in SciTE. +
  • +
  • + Bookmarks in SciTE. +
  • +
  • + Drag and drop copy works when dragging to the edge of the selection. +
  • +
  • + Fixed bug with value sizes in properties file. +
  • +
  • + Fixed bug with last line in properties file not being used. +
  • +
  • + Bug with multiple views of one document fixed. +
  • +
  • + Keypad now works on GTK+. +
  • +
+

+ Release 1.22 +

+
    +
  • + Released on 27 February 2000. +
  • +
  • + wxWindows platform defined. + Implementation for wxWindows will be available separately + from main Scintilla distribution. +
  • +
  • + Line folding in Scintilla. +
  • +
  • + SciTE performs syntax directed folding for C/C++/Java/JavaScript and for Python. +
  • +
  • + Optional macro recording support. +
  • +
  • + User properties file (SciTEUser.properties) allows for customisation by the user + that is not overwritten with each installation of SciTE. +
  • +
  • + Python lexer detects and highlights inconsistent indentation. +
  • +
  • + Margin API made more orthogonal. SCI_SETMARGINWIDTH and SCI_SETLINENUMBERWIDTH + are deprecated in favour of this new API. +
  • +
  • + Margins may be made sensitive to forward mouse click events to container. +
  • +
  • + SQL lexer and styles included. +
  • +
  • + Perl lexer handles regular expressions better. +
  • +
  • + Caret policy determines how closely caret is tracked by visible area. +
  • +
  • + New marker shapes: arrow pointing down, plus and minus. +
  • +
  • + Optionally display full path in title rather than just file name. +
  • +
  • + Container is notified when Scintilla gains or loses focus. +
  • +
  • + SciTE handles focus in a more standard way and applies the main + edit commands to the focused pane. +
  • +
  • + Container is notified when Scintilla determines that a line needs to be made visible. +
  • +
  • + Document watchers receive notification when document about to be deleted. +
  • +
  • + Document interface allows access to list of watchers. +
  • +
  • + Line end determined correctly for lines ending with only a '\n'. +
  • +
  • + Search variant that searches form current selection and sets selection. +
  • +
  • + SciTE understands format of diagnostic messages from WScript. +
  • +
  • + SciTE remembers top line of window for each file in MRU list so switching to a recent file + is more likely to show the same text as when the file was previously visible. +
  • +
  • + Document reference count now initialised correctly. +
  • +
  • + Setting a null document pointer creates an empty document. +
  • +
  • + WM_GETTEXT can no longer overrun buffer. +
  • +
  • + Polygon drawing bug fixed on GTK+. +
  • +
  • + Java and JavaScript lexers merged into C++ lexer. +
  • +
  • + C++ lexer indicates unterminated strings by colouring the end of the line + rather than changing the rest of the file to string style. This is less + obtrusive and helps the folding. +
  • +
+

+ Release 1.21 +

+
    +
  • + Released on 2 February 2000. +
  • +
  • + Blank margins on left and right side of text. +
  • +
  • + SCN_CHECKBRACE renamed SCN_UPDATEUI and made more efficient. +
  • +
  • + SciTE source code refactored into platform independent and platform specific classes. +
  • +
  • + XML and Perl subset lexers in SciTE. +
  • +
  • + Large improvement to lexing speed. +
  • +
  • + A new subsystem, 2, allows use of ShellExec on Windows. +
  • +
  • + Borland compatible makefile. +
  • +
  • + Status bar showing caret position in GTK+ version of SciTE. +
  • +
  • + Bug fixes to selection drawing when part of selection outside window, mouse release over + scroll bars, and scroll positioning after deletion. +
  • +
+

+ Release 1.2 +

+
    +
  • + Released on 21 January 2000. +
  • +
  • + Multiple views of one document. +
  • +
  • + Rectangular selection, cut, copy, paste, drag and drop. +
  • +
  • + Long line indication. +
  • +
  • + Reverse searching +
  • +
  • + Line end conversion. +
  • +
  • + Generic autocompletion and calltips in SciTE. +
  • +
  • + Call tip background colour can be set. +
  • +
  • + SCI_MARKERPREV for moving to a previous marker. +
  • +
  • + Caret kept more within window where possible. +
  • +
+

+ Release 1.15 +

+
    +
  • + Released on 15 December 1999. +
  • +
  • + Brace highlighting and badlighting (for mismatched braces). +
  • +
  • + Visible line ends. +
  • +
  • + Multiple line call tips. +
  • +
  • + Printing now works from SciTE on Windows. +
  • +
  • + SciTE has a global "*" lexer style that is used as the basis for all the lexers' styles. +
  • +
  • + Fixes some warnings on GTK+ 1.2.6. +
  • +
  • + Better handling of modal dialogs on GTK+. +
  • +
  • + Resize handle drawn on pane splitter in SciTE on GTK+ so it looks more like a regular GTK+ + *paned widget. +
  • +
  • + SciTE does not place window origin offscreen if no properties file found on GTK+. +
  • +
  • + File open filter remembered in SciTE on Windows. +
  • +
  • + New mechanism using style numbers 32 to 36 standardises the setting of styles for brace + highlighting, brace badlighting, line numbers, control characters and the default style. +
  • +
  • + Old messages SCI_SETFORE .. SCI_SETFONT have been replaced by the default style 32. The old + messages are deprecated and will disappear in a future version. +
  • +
+

+ Release 1.14 +

+
    +
  • + Released on 20 November 1999. +
  • +
  • + Fixes a scrolling bug reported on GTK+. +
  • +
+

+ Release 1.13 +

+
    +
  • + Released on 18 November 1999. +
  • +
  • + Fixes compilation problems with the mingw32 GCC 2.95.2 on Windows. +
  • +
  • + Control characters are now visible. +
  • +
  • + Performance has improved, particularly for scrolling. +
  • +
  • + Windows RichEdit emulation is more accurate. This may break client code that uses these + messages: EM_GETLINE, EM_GETLINECOUNT, EM_EXGETSEL, EM_EXSETSEL, EM_EXLINEFROMCHAR, + EM_LINELENGTH, EM_LINEINDEX, EM_CHARFROMPOS, EM_POSFROMCHAR, and EM_GETTEXTRANGE. +
  • +
  • + Menus rearranged and accelerator keys set for all static items. +
  • +
  • + Placement of space indicators in view whitespace mode is more accurate with some fonts. +
  • +
+

+ Release 1.12 +

+
    +
  • + Released on 9 November 1999. +
  • +
  • + Packaging error in 1.11 meant that the compilation error was not fixed in that release. + Linux/GTK+ should compile with GCC 2.95 this time. +
  • +
+

+ Release 1.11 +

+
    +
  • + Released on 7 November 1999. +
  • +
  • + Fixed a compilation bug in ScintillaGTK.cxx. +
  • +
  • + Added a README file to explain how to build. +
  • +
  • + GTK+/Linux downloads now include documentation. +
  • +
  • + Binary only Sc1.EXE one file download for Windows. +
  • +
+

+ Release 1.1 +

+
    +
  • + Released on 6 November 1999. +
  • +
  • + Major restructuring for better modularity and platform independence. +
  • +
  • + Inter-application drag and drop. +
  • +
  • + Printing support in Scintilla on Windows. +
  • +
  • + Styles can select colouring to end of line. This can be used when a file contains more than + one language to differentiate between the areas in each language. An example is the HTML + + JavaScript styling in SciTE. +
  • +
  • + Actions can be grouped in the undo stack, so they will be undone together. This grouping is + hierarchical so higher level actions such as replace all can be undone in one go. Call to + discover whether there are any actions to redo. +
  • +
  • + The set of characters that define words can be changed. +
  • +
  • + Markers now have identifiers and can be found and deleted by their identifier. The empty + marker type can be used to make a marker that is invisible and which is only used to trace + where a particular line moves to. +
  • +
  • + Double click notification. +
  • +
  • + HTML styling in SciTE also styles embedded JavaScript. +
  • +
  • + Additional tool commands can be added to SciTE. +
  • +
  • + SciTE option to allow reloading if changed upon application activation and saving on + application deactivation. Not yet working on GTK+ version. +
  • +
  • + Entry fields in search dialogs remember last 10 user entries. Not working in all cases in + Windows version. +
  • +
  • + SciTE can save a styled copy of the current file in HTML format. As SciTE does not yet + support printing, this can be used to print a file by then using a browser to print the + HTML file. +
  • +
+

+ Release 1.02 +

+
    +
  • + Released on 1 October 1999. +
  • +
  • + GTK+ version compiles with GCC 2.95. +
  • +
  • + Properly deleting objects when window destroyed under GTK+. +
  • +
  • + If the selection is not empty backspace deletes the selection. +
  • +
  • + Some X style middle mouse button handling for copying the primary selection to and from + Scintilla. Does not work in all cases. +
  • +
  • + HTML styling in SciTE. +
  • +
  • + Stopped dirty flag being set in SciTE when results pane modified. +
  • +
+

+ Release 1.01 +

+
    +
  • + Released on 28 September 1999. +
  • +
  • + Better DBCS support on Windows including IME. +
  • +
  • + Wheel mouse support for scrolling and zooming on Windows. Zooming with Ctrl+KeypadPlus and + Ctrl+KeypadMinus. +
  • +
  • + Performance improvements especially on GTK+. +
  • +
  • + Caret blinking and settable colour on both GTK+ and Windows. +
  • +
  • + Drag and drop within a Scintilla window. On Windows, files can be dragged into SciTE. +
  • +
+

+ Release 1.0 +

+
    +
  • + Released on 17 May 1999. +
  • +
  • + Changed name of "Tide" to "SciTE" to avoid clash with a TCL based IDE. "SciTE" is a + SCIntilla based Text Editor and is Latin meaning something like "understanding in a neat + way" and is also an Old English version of the word "shit". +
  • +
  • + There is a SCI_AUTOCSTOPS message for defining a string of characters that will stop + autocompletion mode. Autocompletion mode is cancelled when any cursor movement occurs apart + from backspace. +
  • +
  • + GTK+ version now splits horizontally as well as vertically and all dialogs cancel when the + escape key is pressed. +
  • +
+

+ Beta release 0.93 +

+
    +
  • + Released on 12 May 1999. +
  • +
  • + A bit more robust than 0.92 and supports SCI_MARKERNEXT message. +
  • +
+

+ Beta release 0.92 +

+
    +
  • + Released on 11 May 1999. +
  • +
  • + GTK+ version now contains all features of Windows version with some very small differences. + Executing programs works much better now. +
  • +
  • + New palette code to allow more colours to be displayed in 256 colour screen modes. A line + number column can be displayed to the left of the selection margin. +
  • +
  • + The code that maps from line numbers to text positions and back has been completely + rewritten to be faster, and to allow markers to move with the text. +
  • +
+

+ Beta release 0.91 +

+
    +
  • + Released on 30 April 1999, containing fixes to text measuring to make Scintilla work better + with bitmap fonts. Also some small fixes to make compiling work with Visual C++. +
  • +
+

+ Beta release 0.90 +

+
    +
  • + Released on 29 April 1999, containing working GTK+/Linux version. +
  • +
  • + The Java, C++ and Python lexers recognise operators as distinct from default allowing them + to be highlighted. +
  • +
+

+ Beta release 0.82 +

+
    +
  • + Released on 1 April 1999, to fix a problem with handling the Enter key in PythonWin. Also + fixes some problems with cmd key mapping. +
  • +
+

+ Beta release 0.81 +

+
    +
  • + Released on 30th March 1999, containing bug fixes and a few more features. +
  • +
  • + Static linking supported and Tidy.EXE, a statically linked version of Tide.EXE. Changes to + compiler flags in the makefiles to optimise for size. +
  • +
  • + Scintilla supports a 'savepoint' in the undo stack which can be set by the container when + the document is saved. Notifications are sent to the container when the savepoint is + entered or left, allowing the container to to display a dirty indicator and change its + menus. +
  • +
  • + When Scintilla is set to read-only mode, a notification is sent to the container should the + user try to edit the document. This can be used to check the document out of a version + control system. +
  • +
  • + There is an API for setting the appearance of indicators. +
  • +
  • + The keyboard mapping can be redefined or removed so it can be implemented completely by the + container. All of the keyboard commands are now commands which can be sent by the + container. +
  • +
  • + A home command like Visual C++ with one hit going to the start of the text on the line and + the next going to the left margin is available. I do not personally like this but my + fingers have become trained to it by much repetition. +
  • +
  • + SCI_MARKERDELETEALL has an argument in wParam which is the number of the type marker to + delete with -1 performing the old action of removing all marker types. +
  • +
  • + Tide now understands both the file name and line numbers in error messages in most cases. +
  • +
  • + Tide remembers the current lines of files in the recently used list. +
  • +
  • + Tide has a Find in Files command. +
  • +
+

+ Beta release 0.80 +

+
    +
  • + This was the first public release on 14th March 1999, containing a mostly working Win32 + Scintilla DLL and Tide EXE. +
  • +
+

+ Beta releases of SciTE were called Tide +

+ + + diff --git a/scintilla/doc/ScintillaRelated.html b/ThirdLibs/scintilla/doc/ScintillaRelated.html similarity index 97% rename from scintilla/doc/ScintillaRelated.html rename to ThirdLibs/scintilla/doc/ScintillaRelated.html index f87f5520..8bed6865 100644 --- a/scintilla/doc/ScintillaRelated.html +++ b/ThirdLibs/scintilla/doc/ScintillaRelated.html @@ -1,510 +1,510 @@ - - - - - - - - - Scintilla and SciTE Related Sites - - - - - - - - -
- Scintilla icon - - Scintilla - and SciTE -
-

- Related Sites -

-

- Ports and Bindings of Scintilla -

-

- Wx::Scintilla - is a Perl Binding for Scintilla on wxWidgets. -

-

- GtkScintilla - is a GTK+ widget which enables easily adding a powerful - source code editor to your applications. Harnessing the abilities - of the Scintilla editing component, GtkScintilla adds a familiar - GTK+/GObject API, making the widget comfortable to use in - these programs, using all the typical GObject conventions. -

-

- Editawy - is an ActiveX Control wrapper that support all Scintilla functions and additional high level functions. -

-

- Jintilla - is a JNI wrapper that allows Scintilla to be used in Java with - both SWT and AWT. -

-

- Delphi Scintilla Interface Components - is a FREE collection of components that makes it easy to use the - Scintilla source code editing control from within Delphi and C++ Builder. -

-

- wxStEdit - is a library and sample program that provides extra features over wxStyledTextControl. -

-

- CScintillaCtrl, CScintillaView & CScintillaDoc - are freeware MFC classes to encapsulate Scintilla. -

-

- ScintillaNet - is an encapsulation of Scintilla for use within the .NET framework. -

-

- QScintilla - is a port of Scintilla to the Qt platform. It has a similar license to Qt: GPL for use in - free software and commercial for use in close-source applications. -

-

- - GWindows is a Win32 RAD GUI Framework for Ada 95 that - includes a binding of Scintilla. -

-

- ScintillaVB - is an ActiveX control written in VB that encapsulates Scintilla. -

-

- FXScintilla - is a port of Scintilla to the FOX platform. FXRuby includes Ruby - bindings for FXScintilla. -

-

- Delphi wrapper for - Scintilla which is also usable from Borland C++ Builder. -

-

- The wxStyledTextCtrl editor component in the - wxWidgets cross platform toolkit is based on Scintilla.
- A Python binding for wxStyledTextCtrl is part of wxPython. -

-

- gtkscintilla - is an alternative GTK class implementation for scintilla. - This implementation acts more like a Gtk+ object, with many methods rather - than just scintilla_send_message() and is available as a shared library. - This implementation works with GTK 1.x. -

-

- gtkscintilla2 - is an alternative GTK class implementation for scintilla - similar to the above, but for GTK 2.x. -

-

- pygtkscintilla - is a Python binding for gtk1.x scintilla that uses - gtkscintilla instead of the default GTK class. -

-

- ScintillaCtrl - is an unmaintained ActiveX control wrapper for Scintilla. -

-

- Projects using Scintilla -

-

- Padre - is a wxWidgets-based Perl IDE. -

-

- CoderStudio - is an IDE for Assembly programming similar to Visual Studio 6.0. -

-

- Enterprise Architect - is a UML 2.1 analysis and design tool. -

-

- The CodeAssistor Editor - is a small and simple MacOSX source code editor. -

-

- PBEditor - is a text editor for PowerBuilder. -

-

- CrypTool - is an application for applying and analyzing cryptographic algorithms. -

-

- FXiTe - is an advanced cross-platform text editor built with the Fox GUI toolkit - and the FXScintilla text widget. -

-

- Jabaco - is a simple programming language with a Visual Basic like syntax. -

-

- LispIDE - is a basic Lisp editor for Windows 2000, XP and Vista. -

-

- FlexEdit - is Free Text/Hex Editor for Windows. -

-

- File Workbench: - a file manager / text editor environment with Squirrel scripting. -

-

- Kephra - is a free, easy and comfortable cross-platform editor written in Perl. -

-

- TOP - is an interface to HP's NonStop servers which run a proprietary OS. -

-

- UniversalIndentGUI - is a cross platform GUI for several code formatters, beautifiers and indenters - like GreatCode, AStyle (Artistic Styler), GNU Indent, BCPP and so on. -

-

- TrackBack - watches and backs up every change made in your source code. -

-

- Elementary Reports - is designed to reduce the time to compose detailed and professional primary school reports. -

-

- Visual Classworks - Visual class modeling and coding in C++ via 'live' - UML style class diagrams. -

-

- Javelin - Visual Class modeling and coding in Java via 'live' UML style - class diagrams. -

-

- The ExtendScript Toolkit - is a development and debugging tool for JavaScript - scripts included with Adobe CS3 Suites. -

-

- TortoiseSVN - is a Windows GUI client for the Subversion source control software. -

-

- Geany - is a small and fast GTK2 based IDE, which has only a few dependencies from other packages. -

-

- ECMerge - is a commercial graphical and batch diff / merge tool for Windows, Linux and Solaris - (aiming to target all major platforms). -

-

- PyPE - is an editor written in Python with the wxPython GUI toolkit. -

-

- Sciboo - is an editor based on ScintillaNET. -

-

- The Scite Config Tool - is a graphical user interface for changing SciTE properties files. -

-

- Scintilla Lister - is a plugin for Total Commander allowing viewing all documents with syntax highlighting - inside Total Commander. -

-

- ChSciTE - is a free IDE for C/C++ interpreter Ch. It runs cross platform. - Ch is for cross-platform scripting, shell - programming, 2D/3D plotting, numerical computing, and embedded - scripting. -

-

- - Code::Blocks is an open source, cross platform free C++ IDE. -

-

- - Notepad++ is a free source code editor under Windows. -

-

- - Gubed is a cross platform program to debug PHP scripts. -

-

- - LSW DotNet-Lab is a development environment for the .NET platform. -

-

- - GLIntercept is an OpenGL function call interceptor that uses SciTE as a - run-time shader editor. -

-

- - wyoEditor is "A nice editor with a well designed and consistent look and feel". -

-

- - Notepad2 is "Yet another Notepad replacement". -

-

- - PyCrash Viewer can examine crash dumps of Python programs. -

-

- - MPT series Wire Analyzers use Scintilla and SciTE. -

-

- MyGeneration - is a .NET based code generator. -

-

- CSSED - is a tiny GTK2 CSS editor. -

-

- - IdePS - is a free Integrated Development Environment for PostScript -

-

- - CUTE - is a user-friendly source code editor easily extended using Python. -

-

- - Venis IX, - the Visual Environment for NSIS (Nullsoft Scriptable Install System). -

-

- Eric3 - is a Python IDE written using PyQt and QScintilla. -

-

- SciTE|Flash - is a free Scintilla-based ActionScript editor for Windows. -

-

- CPPIDE - is part of some commercial high-school oriented programming course software. -

-

- Instant Source - is a commercial tool for looking at the HTML on web sites. -

-

- RAD.On++ - is a free C++ Rapid Application Developer for Win32. -

-

- wxBasic is an open source - Basic interpreter that uses the wxWidgets toolkit. A small IDE is under construction. -

-

- FreeRIDE will be a - cross-platform IDE for the Ruby programming language. -

-

- Visual MinGW is an - IDE for the MinGW compiler system.This runs on Windows with gcc. -

-

- The Wing IDE is a - complete integrated development environment for the Python programming - language. - Available on Intel based Linux and Windows and on MacOS X through XDarwin. -

-

- LuaIDE - is an IDE for Lua on Windows. -

-

- Sphere - is 2D RPG engine with a development environment. -

-

- Practical Ruby - is an IDE for Ruby on Windows. -

-

- GNUe - is a suite of tools and applications for solving the needs of the enterprise. -

-

- SilverCity - is a lexing package that can provide lexical analysis for over 20 programming - and markup languages. -

-

- HAP Python Remote Debugger - is a Python debugger that can run on one Windows machine debugging a Python program running - on either the same or another machine. -

-

- pyeditor and wxEditor - are scriptable editors implemented in Python. pyeditor is based on GTK+ and - the pyscintilla wrapper. wxEditor is based on wxWidgets, wxPython and - wxStyledTextControl. -

-

- PyCrust is an interactive - Python shell based on wxPython. -

-

- Black Adder is a - Qt based development environment for Python and Ruby. -

-

- Komodo - is a cross-platform multi-language development environment built - as an application of Mozilla. -

-

- Filerx - is a project manager for SciTE on Windows. - Open source and includes an implementation of SciTE's Director interface so - will be of interest to others wanting to control SciTE. -

-

- Anjuta - is an open source C/C++ IDE for Linux/GNOME. -

-

- A version of SciTE for Win32 enhanced - with a tab control to allow easy movement between buffers. - Go to the "Goodies" area on this site. -

-

- - Suneido is an integrated application platform currently available for Win32 that includes an - object-oriented language, client-server database, and user interface and reporting frameworks. -

-

- - Agast is an authoring system for adventure games which includes - a customised version of SciTE. -

-

- Boa Constructor is a RAD GUI - Building IDE for the wxWidgets cross platform platform. Written using wxPython with the - wxStyledTextCtrl used as its editor. -

-

- PythonWin, a Win32 IDE for Python, uses - Scintilla for both its editing and interactive windows. -

-

- Editing Components -

-

- GtkSourceView - is a text widget that extends the standard GTK+ 2.x text widget and improves it - by implementing syntax highlighting and other features typical of a source editor. -

-

- AEditor - is a free source code editing component implemented in Ruby. -

-

- SyntaxEditor - is a commercial native .Net source code editing component. -

-

- jEdit is a good Open Source syntax colouring - editor written in and for Java. -

-

- GTK+, the GIMP Toolkit, contains a rich text editing - widget.
- Gedit is an editor for GTK+/GNOME.
- -

-

- CodeGuru has source code for several Win32 MFC based - editors. -

- SynEdit is a Win32 edit control written - in Delphi. -

- SourceView is a commercial editing - component for Win32. -

-

- CodeMax is another commercial component for Win32. -

-

- Documents -

-

- The Craft of Text Editing - describes how EMACS works, Craig A. Finseth -

-

- Data Structures in a Bit-Mapped Text - Editor, Wilfred J. Hanson, Byte January 1987 -

-

- Text Editors: Algorithms and Architectures, Ray Valdés, Dr. Dobbs Journal - April 1993 -

-

- Macintosh User Interface Guidelines and TextEdit chapters of Inside Macintosh -

-

- Development Tools -

-

- Scintilla and SciTE were developed using the - Mingw version of GCC. -

-

- AStyle is a source code formatter for C++ and - Java code. SciTE has an Indent command defined for .cxx files that uses AStyle. -

-

- WinMerge is an interactive diff / merge - for Windows. I prefer code submissions in the form of source files rather than diffs and then run - WinMerge over the files to work out how to merge. -

-

- Python is my favourite programming language. Scintilla - was started after I tried to improve the editor built into PythonWin, but was frustrated by the limitations of - the Windows Richedit control which PythonWin used. -

-

- regex is a public domain - implementation of regular expression pattern matching used in Scintilla. -

-

- Inspirational coding soundscapes by David Bridie. -

- - - + + + + + + + + + Scintilla and SciTE Related Sites + + + + + + + + +
+ Scintilla icon + + Scintilla + and SciTE +
+

+ Related Sites +

+

+ Ports and Bindings of Scintilla +

+

+ Wx::Scintilla + is a Perl Binding for Scintilla on wxWidgets. +

+

+ GtkScintilla + is a GTK+ widget which enables easily adding a powerful + source code editor to your applications. Harnessing the abilities + of the Scintilla editing component, GtkScintilla adds a familiar + GTK+/GObject API, making the widget comfortable to use in + these programs, using all the typical GObject conventions. +

+

+ Editawy + is an ActiveX Control wrapper that support all Scintilla functions and additional high level functions. +

+

+ Jintilla + is a JNI wrapper that allows Scintilla to be used in Java with + both SWT and AWT. +

+

+ Delphi Scintilla Interface Components + is a FREE collection of components that makes it easy to use the + Scintilla source code editing control from within Delphi and C++ Builder. +

+

+ wxStEdit + is a library and sample program that provides extra features over wxStyledTextControl. +

+

+ CScintillaCtrl, CScintillaView & CScintillaDoc + are freeware MFC classes to encapsulate Scintilla. +

+

+ ScintillaNet + is an encapsulation of Scintilla for use within the .NET framework. +

+

+ QScintilla + is a port of Scintilla to the Qt platform. It has a similar license to Qt: GPL for use in + free software and commercial for use in close-source applications. +

+

+ + GWindows is a Win32 RAD GUI Framework for Ada 95 that + includes a binding of Scintilla. +

+

+ ScintillaVB + is an ActiveX control written in VB that encapsulates Scintilla. +

+

+ FXScintilla + is a port of Scintilla to the FOX platform. FXRuby includes Ruby + bindings for FXScintilla. +

+

+ Delphi wrapper for + Scintilla which is also usable from Borland C++ Builder. +

+

+ The wxStyledTextCtrl editor component in the + wxWidgets cross platform toolkit is based on Scintilla.
+ A Python binding for wxStyledTextCtrl is part of wxPython. +

+

+ gtkscintilla + is an alternative GTK class implementation for scintilla. + This implementation acts more like a Gtk+ object, with many methods rather + than just scintilla_send_message() and is available as a shared library. + This implementation works with GTK 1.x. +

+

+ gtkscintilla2 + is an alternative GTK class implementation for scintilla + similar to the above, but for GTK 2.x. +

+

+ pygtkscintilla + is a Python binding for gtk1.x scintilla that uses + gtkscintilla instead of the default GTK class. +

+

+ ScintillaCtrl + is an unmaintained ActiveX control wrapper for Scintilla. +

+

+ Projects using Scintilla +

+

+ Padre + is a wxWidgets-based Perl IDE. +

+

+ CoderStudio + is an IDE for Assembly programming similar to Visual Studio 6.0. +

+

+ Enterprise Architect + is a UML 2.1 analysis and design tool. +

+

+ The CodeAssistor Editor + is a small and simple MacOSX source code editor. +

+

+ PBEditor + is a text editor for PowerBuilder. +

+

+ CrypTool + is an application for applying and analyzing cryptographic algorithms. +

+

+ FXiTe + is an advanced cross-platform text editor built with the Fox GUI toolkit + and the FXScintilla text widget. +

+

+ Jabaco + is a simple programming language with a Visual Basic like syntax. +

+

+ LispIDE + is a basic Lisp editor for Windows 2000, XP and Vista. +

+

+ FlexEdit + is Free Text/Hex Editor for Windows. +

+

+ File Workbench: + a file manager / text editor environment with Squirrel scripting. +

+

+ Kephra + is a free, easy and comfortable cross-platform editor written in Perl. +

+

+ TOP + is an interface to HP's NonStop servers which run a proprietary OS. +

+

+ UniversalIndentGUI + is a cross platform GUI for several code formatters, beautifiers and indenters + like GreatCode, AStyle (Artistic Styler), GNU Indent, BCPP and so on. +

+

+ TrackBack + watches and backs up every change made in your source code. +

+

+ Elementary Reports + is designed to reduce the time to compose detailed and professional primary school reports. +

+

+ Visual Classworks + Visual class modeling and coding in C++ via 'live' + UML style class diagrams. +

+

+ Javelin + Visual Class modeling and coding in Java via 'live' UML style + class diagrams. +

+

+ The ExtendScript Toolkit + is a development and debugging tool for JavaScript + scripts included with Adobe CS3 Suites. +

+

+ TortoiseSVN + is a Windows GUI client for the Subversion source control software. +

+

+ Geany + is a small and fast GTK2 based IDE, which has only a few dependencies from other packages. +

+

+ ECMerge + is a commercial graphical and batch diff / merge tool for Windows, Linux and Solaris + (aiming to target all major platforms). +

+

+ PyPE + is an editor written in Python with the wxPython GUI toolkit. +

+

+ Sciboo + is an editor based on ScintillaNET. +

+

+ The Scite Config Tool + is a graphical user interface for changing SciTE properties files. +

+

+ Scintilla Lister + is a plugin for Total Commander allowing viewing all documents with syntax highlighting + inside Total Commander. +

+

+ ChSciTE + is a free IDE for C/C++ interpreter Ch. It runs cross platform. + Ch is for cross-platform scripting, shell + programming, 2D/3D plotting, numerical computing, and embedded + scripting. +

+

+ + Code::Blocks is an open source, cross platform free C++ IDE. +

+

+ + Notepad++ is a free source code editor under Windows. +

+

+ + Gubed is a cross platform program to debug PHP scripts. +

+

+ + LSW DotNet-Lab is a development environment for the .NET platform. +

+

+ + GLIntercept is an OpenGL function call interceptor that uses SciTE as a + run-time shader editor. +

+

+ + wyoEditor is "A nice editor with a well designed and consistent look and feel". +

+

+ + Notepad2 is "Yet another Notepad replacement". +

+

+ + PyCrash Viewer can examine crash dumps of Python programs. +

+

+ + MPT series Wire Analyzers use Scintilla and SciTE. +

+

+ MyGeneration + is a .NET based code generator. +

+

+ CSSED + is a tiny GTK2 CSS editor. +

+

+ + IdePS + is a free Integrated Development Environment for PostScript +

+

+ + CUTE + is a user-friendly source code editor easily extended using Python. +

+

+ + Venis IX, + the Visual Environment for NSIS (Nullsoft Scriptable Install System). +

+

+ Eric3 + is a Python IDE written using PyQt and QScintilla. +

+

+ SciTE|Flash + is a free Scintilla-based ActionScript editor for Windows. +

+

+ CPPIDE + is part of some commercial high-school oriented programming course software. +

+

+ Instant Source + is a commercial tool for looking at the HTML on web sites. +

+

+ RAD.On++ + is a free C++ Rapid Application Developer for Win32. +

+

+ wxBasic is an open source + Basic interpreter that uses the wxWidgets toolkit. A small IDE is under construction. +

+

+ FreeRIDE will be a + cross-platform IDE for the Ruby programming language. +

+

+ Visual MinGW is an + IDE for the MinGW compiler system.This runs on Windows with gcc. +

+

+ The Wing IDE is a + complete integrated development environment for the Python programming + language. + Available on Intel based Linux and Windows and on MacOS X through XDarwin. +

+

+ LuaIDE + is an IDE for Lua on Windows. +

+

+ Sphere + is 2D RPG engine with a development environment. +

+

+ Practical Ruby + is an IDE for Ruby on Windows. +

+

+ GNUe + is a suite of tools and applications for solving the needs of the enterprise. +

+

+ SilverCity + is a lexing package that can provide lexical analysis for over 20 programming + and markup languages. +

+

+ HAP Python Remote Debugger + is a Python debugger that can run on one Windows machine debugging a Python program running + on either the same or another machine. +

+

+ pyeditor and wxEditor + are scriptable editors implemented in Python. pyeditor is based on GTK+ and + the pyscintilla wrapper. wxEditor is based on wxWidgets, wxPython and + wxStyledTextControl. +

+

+ PyCrust is an interactive + Python shell based on wxPython. +

+

+ Black Adder is a + Qt based development environment for Python and Ruby. +

+

+ Komodo + is a cross-platform multi-language development environment built + as an application of Mozilla. +

+

+ Filerx + is a project manager for SciTE on Windows. + Open source and includes an implementation of SciTE's Director interface so + will be of interest to others wanting to control SciTE. +

+

+ Anjuta + is an open source C/C++ IDE for Linux/GNOME. +

+

+ A version of SciTE for Win32 enhanced + with a tab control to allow easy movement between buffers. + Go to the "Goodies" area on this site. +

+

+ + Suneido is an integrated application platform currently available for Win32 that includes an + object-oriented language, client-server database, and user interface and reporting frameworks. +

+

+ + Agast is an authoring system for adventure games which includes + a customised version of SciTE. +

+

+ Boa Constructor is a RAD GUI + Building IDE for the wxWidgets cross platform platform. Written using wxPython with the + wxStyledTextCtrl used as its editor. +

+

+ PythonWin, a Win32 IDE for Python, uses + Scintilla for both its editing and interactive windows. +

+

+ Editing Components +

+

+ GtkSourceView + is a text widget that extends the standard GTK+ 2.x text widget and improves it + by implementing syntax highlighting and other features typical of a source editor. +

+

+ AEditor + is a free source code editing component implemented in Ruby. +

+

+ SyntaxEditor + is a commercial native .Net source code editing component. +

+

+ jEdit is a good Open Source syntax colouring + editor written in and for Java. +

+

+ GTK+, the GIMP Toolkit, contains a rich text editing + widget.
+ Gedit is an editor for GTK+/GNOME.
+ +

+

+ CodeGuru has source code for several Win32 MFC based + editors. +

+ SynEdit is a Win32 edit control written + in Delphi. +

+ SourceView is a commercial editing + component for Win32. +

+

+ CodeMax is another commercial component for Win32. +

+

+ Documents +

+

+ The Craft of Text Editing + describes how EMACS works, Craig A. Finseth +

+

+ Data Structures in a Bit-Mapped Text + Editor, Wilfred J. Hanson, Byte January 1987 +

+

+ Text Editors: Algorithms and Architectures, Ray Valdés, Dr. Dobbs Journal + April 1993 +

+

+ Macintosh User Interface Guidelines and TextEdit chapters of Inside Macintosh +

+

+ Development Tools +

+

+ Scintilla and SciTE were developed using the + Mingw version of GCC. +

+

+ AStyle is a source code formatter for C++ and + Java code. SciTE has an Indent command defined for .cxx files that uses AStyle. +

+

+ WinMerge is an interactive diff / merge + for Windows. I prefer code submissions in the form of source files rather than diffs and then run + WinMerge over the files to work out how to merge. +

+

+ Python is my favourite programming language. Scintilla + was started after I tried to improve the editor built into PythonWin, but was frustrated by the limitations of + the Windows Richedit control which PythonWin used. +

+

+ regex is a public domain + implementation of regular expression pattern matching used in Scintilla. +

+

+ Inspirational coding soundscapes by David Bridie. +

+ + + diff --git a/scintilla/doc/ScintillaToDo.html b/ThirdLibs/scintilla/doc/ScintillaToDo.html similarity index 96% rename from scintilla/doc/ScintillaToDo.html rename to ThirdLibs/scintilla/doc/ScintillaToDo.html index dffd4219..419a8cc8 100644 --- a/scintilla/doc/ScintillaToDo.html +++ b/ThirdLibs/scintilla/doc/ScintillaToDo.html @@ -1,127 +1,127 @@ - - - - - - - - - Scintilla and SciTE To Do - - - - - - - - -
- Scintilla icon - - Scintilla - and SciTE -
-

- Bugs and To Do List -

-

- Feedback -

-

- Issues can be reported on the Bug Tracker - and features requested on the Feature Request Tracker. -

-

- Scintilla Bugs -

-

- Automatic scrolling when text dragged near edge of window. -

-

- Scintilla To Do -

-

- Folding for languages that don't have it yet and good folding for languages - that inherited poor folding from another languages folding code. -

-

- Simple pattern based styling. -

-

- Different height lines based upon tallest text on the line rather than on the tallest style - possible. -

-

- Composition of lexing for mixed languages (such as ASP+ over COBOL) by - combining lexers. -

-

- Stream folding which could be used to fold up the contents of HTML elements. -

-

- Printing of highlight lines and folding margin. -

-

- Flow diagrams inside editor similar to - GRASP. -

-

- More lexers for other languages. -

-

- SciTE To Do -

-

- Good regular expression support through a plugin. -

-

- Allow file name based selection on all properties rather than just a chosen few. -

-

- Opening from and saving to FTP servers. -

-

- Setting to fold away comments upon opening. -

-

- User defined fold ranges. -

-

- Silent mode that does not display any message boxes. -

-

- Features I am unlikely to do -

-

- These are features I don't like or don't think are important enough to work on. - Implementations are welcome from others though. -

-

- Mouse wheel panning (press the mouse wheel and then move the mouse) on - Windows. -

-

- Adding options to the save dialog to save in a particular encoding or with a - chosen line ending. -

-

- Directions -

-

- The main point of this development is Scintilla, and this is where most effort will - go. SciTE will get new features, but only when they make my life easier - I am - not intending to make it grow up to be a huge full-function IDE like Visual - Cafe. The lines I've currently decided not to step over in SciTE are any sort of - project facility and any configuration dialogs. SciTE for Windows now has a - Director interface for communicating with a separate project manager - application. -

-

- If you are interested in contributing code, do not feel any need to make it cross - platform. - Just code it for your platform and I'll either reimplement for the other platform or - ensure that there is no effect on the other platform. -

- - + + + + + + + + + Scintilla and SciTE To Do + + + + + + + + +
+ Scintilla icon + + Scintilla + and SciTE +
+

+ Bugs and To Do List +

+

+ Feedback +

+

+ Issues can be reported on the Bug Tracker + and features requested on the Feature Request Tracker. +

+

+ Scintilla Bugs +

+

+ Automatic scrolling when text dragged near edge of window. +

+

+ Scintilla To Do +

+

+ Folding for languages that don't have it yet and good folding for languages + that inherited poor folding from another languages folding code. +

+

+ Simple pattern based styling. +

+

+ Different height lines based upon tallest text on the line rather than on the tallest style + possible. +

+

+ Composition of lexing for mixed languages (such as ASP+ over COBOL) by + combining lexers. +

+

+ Stream folding which could be used to fold up the contents of HTML elements. +

+

+ Printing of highlight lines and folding margin. +

+

+ Flow diagrams inside editor similar to + GRASP. +

+

+ More lexers for other languages. +

+

+ SciTE To Do +

+

+ Good regular expression support through a plugin. +

+

+ Allow file name based selection on all properties rather than just a chosen few. +

+

+ Opening from and saving to FTP servers. +

+

+ Setting to fold away comments upon opening. +

+

+ User defined fold ranges. +

+

+ Silent mode that does not display any message boxes. +

+

+ Features I am unlikely to do +

+

+ These are features I don't like or don't think are important enough to work on. + Implementations are welcome from others though. +

+

+ Mouse wheel panning (press the mouse wheel and then move the mouse) on + Windows. +

+

+ Adding options to the save dialog to save in a particular encoding or with a + chosen line ending. +

+

+ Directions +

+

+ The main point of this development is Scintilla, and this is where most effort will + go. SciTE will get new features, but only when they make my life easier - I am + not intending to make it grow up to be a huge full-function IDE like Visual + Cafe. The lines I've currently decided not to step over in SciTE are any sort of + project facility and any configuration dialogs. SciTE for Windows now has a + Director interface for communicating with a separate project manager + application. +

+

+ If you are interested in contributing code, do not feel any need to make it cross + platform. + Just code it for your platform and I'll either reimplement for the other platform or + ensure that there is no effect on the other platform. +

+ + diff --git a/scintilla/doc/ScintillaUsage.html b/ThirdLibs/scintilla/doc/ScintillaUsage.html similarity index 98% rename from scintilla/doc/ScintillaUsage.html rename to ThirdLibs/scintilla/doc/ScintillaUsage.html index c19cbc55..e0ffb0bf 100644 --- a/scintilla/doc/ScintillaUsage.html +++ b/ThirdLibs/scintilla/doc/ScintillaUsage.html @@ -1,375 +1,375 @@ - - - - - - - - - Scintilla Usage Notes - - - - - - - - - -
- Scintilla icon - - Scintilla - Usage Notes -
-

- Implementing Auto-Indent -

-

- The key idea is to use the SCN_CHARADDED notification to add indentation after a newline. -

-

- The lParam on the notification is a pointer to a SCNotification structure whose ch member - specifies the character added. If a newline was added, the previous line can be retrieved and - the same indentation can be added to the new line. -

-

- Here is the relevant portion of code from SciTE: (SciTE.cxx SciTEWindow::CharAdded) -

- if  (ch  ==  '\r'  ||  ch  ==  '\n')  {
-     
char  - linebuf[1000];
-     
int  - curLine  =  GetCurrentLineNumber();
-     
int  - lineLength  - =  SendEditor(SCI_LINELENGTH,  curLine);
-     
- //Platform::DebugPrintf("[CR] %d len = %d\n", curLine, lineLength);
-     
if  (curLine  >  0  &&  - lineLength  - <=  2)  {
-     
int  - prevLineLength  - =  SendEditor(SCI_LINELENGTH,  curLine  -  1);
-     
if  (prevLineLength  <  sizeof(linebuf))  {
-         
WORD  buflen  =  sizeof(linebuf);
-         
memcpy(linebuf,  &buflen,  sizeof(buflen));
-         
- SendEditor(EM_GETLINE,  curLine  -  1,
-                    
- reinterpret_cast<LPARAM>(static_cast<char  *>(linebuf)));
-         
linebuf[prevLineLength]  =  '\0';
-         
for  (int  pos  =  0;  linebuf[pos];  pos++)  {
-             
if  (linebuf[pos]  !=  ' '  &&  - linebuf[pos]  !=  '\t')
-                 
- linebuf[pos]  =  '\0';
-         
}
-         
- SendEditor(EM_REPLACESEL,  0,  - reinterpret_cast<LPARAM>(static_cast<char  *>(linebuf)));
-     
}
-
}
- -

- Of course, fancier handling could be implemented. For example, if the previous line was the - start of a control construct, the next line could be automatically indented one tab further. - (Assuming that is your indenting style.) -

-

- Implementing Syntax Styling -

-

- Syntax styling is handled by the SCN_STYLENEEDED notification. Scintilla keeps track of the - end of the styled text - this is retrieved with SCI_GETENDSTYLED. In response to the - SCN_STYLENEEDED notification, you should apply styles to the text from ENDSTYLED to the - position specified by the notification. -

-

- Here is the relevant portion of code from SciTE: (SciTE.cxx) -

- void  - SciTEWindow::Notify(SCNotification  *notification)  {
-     
switch  - (notification->nmhdr.code)  {
-     
case  - SCN_STYLENEEDED:  {
-             
if  (notification->nmhdr.idFrom  ==  IDM_SRCWIN)  {
-                 
- int  - endStyled  =  SendEditor(SCI_GETENDSTYLED);
-                 
- int  - lineEndStyled  =  SendEditor(EM_LINEFROMCHAR,  - endStyled);
-                 
- endStyled  - =  SendEditor(EM_LINEINDEX,  lineEndStyled);
-                 
- Colourise(endStyled,  notification->position);
- -

- Colourize(start, end) retrieves the specified range of text and then calls ColourizeDoc in - keywords.cxx. It starts the process by calling: -

-     SendMessage(hwnd,  SCI_STARTSTYLING,  - startPos,  31);
- -

- and then for each token of the text, calling: -

-     SendMessage(hwnd,  SCI_SETSTYLING,  length,  style);
- -

- where style is a number from 0 to 31 whose appearance has been defined using the - SCI_STYLESET... messages. -

-

- Implementing Calltips -

-

- Again, the SCN_CHARADDED notification is used to catch when an opening parenthesis is added. - The preceding word can then be retrieved from the current line: -

-     char  linebuf[1000];
-
    int  current  =  SendEditor(SCI_GETCURLINE,  sizeof(linebuf),
-         
- reinterpret_cast<LPARAM>(static_cast<char  *>(linebuf)));
-
    int  pos  =  SendEditor(SCI_GETCURRENTPOS);
-
-
    int  startword  =  current  -  1;
-
    while  - (startword  - >  0  &&  - isalpha(linebuf[startword  -  1]))
-         
- startword--;
-
    linebuf[current  -  1]  =  '\0';
-
    char*  word  =  linebuf  +  startword;
- -

- Then if a calltip is available it can be displayed. The calltip appears immediately below - the position specified. The calltip can be multiple lines separated by newlines (\n). -

-     pos  =  SendMessage(hwnd,  SCI_GETCURRENTPOS,  0,  0);
-
    SendMessageText(hwnd,  SCI_CALLTIPSHOW,  pos  -  wordLen  -  1,  calltip);
- -

- The calltip can be removed when a closing parenthesis is entered: -

-     if  (SendMessage(hwnd,  SCI_CALLTIPACTIVE,  - 0,  0))
-         
- SendMessage(hwnd,  - SCI_CALLTIPCANCEL,  0,  - 0);
- -

- Obviously, it is up the application to look after supplying the appropriate calltip text. -

-

- SciTE goes one step further, counting the commas between arguments and highlighting the - corresponding part of the calltip. This code is in ContinueCallTip. -

-

- Page contributed by Andrew McKinlay. -

- - - + + + + + + + + + Scintilla Usage Notes + + + + + + + + + +
+ Scintilla icon + + Scintilla + Usage Notes +
+

+ Implementing Auto-Indent +

+

+ The key idea is to use the SCN_CHARADDED notification to add indentation after a newline. +

+

+ The lParam on the notification is a pointer to a SCNotification structure whose ch member + specifies the character added. If a newline was added, the previous line can be retrieved and + the same indentation can be added to the new line. +

+

+ Here is the relevant portion of code from SciTE: (SciTE.cxx SciTEWindow::CharAdded) +

+ if  (ch  ==  '\r'  ||  ch  ==  '\n')  {
+     
char  + linebuf[1000];
+     
int  + curLine  =  GetCurrentLineNumber();
+     
int  + lineLength  + =  SendEditor(SCI_LINELENGTH,  curLine);
+     
+ //Platform::DebugPrintf("[CR] %d len = %d\n", curLine, lineLength);
+     
if  (curLine  >  0  &&  + lineLength  + <=  2)  {
+     
int  + prevLineLength  + =  SendEditor(SCI_LINELENGTH,  curLine  -  1);
+     
if  (prevLineLength  <  sizeof(linebuf))  {
+         
WORD  buflen  =  sizeof(linebuf);
+         
memcpy(linebuf,  &buflen,  sizeof(buflen));
+         
+ SendEditor(EM_GETLINE,  curLine  -  1,
+                    
+ reinterpret_cast<LPARAM>(static_cast<char  *>(linebuf)));
+         
linebuf[prevLineLength]  =  '\0';
+         
for  (int  pos  =  0;  linebuf[pos];  pos++)  {
+             
if  (linebuf[pos]  !=  ' '  &&  + linebuf[pos]  !=  '\t')
+                 
+ linebuf[pos]  =  '\0';
+         
}
+         
+ SendEditor(EM_REPLACESEL,  0,  + reinterpret_cast<LPARAM>(static_cast<char  *>(linebuf)));
+     
}
+
}
+ +

+ Of course, fancier handling could be implemented. For example, if the previous line was the + start of a control construct, the next line could be automatically indented one tab further. + (Assuming that is your indenting style.) +

+

+ Implementing Syntax Styling +

+

+ Syntax styling is handled by the SCN_STYLENEEDED notification. Scintilla keeps track of the + end of the styled text - this is retrieved with SCI_GETENDSTYLED. In response to the + SCN_STYLENEEDED notification, you should apply styles to the text from ENDSTYLED to the + position specified by the notification. +

+

+ Here is the relevant portion of code from SciTE: (SciTE.cxx) +

+ void  + SciTEWindow::Notify(SCNotification  *notification)  {
+     
switch  + (notification->nmhdr.code)  {
+     
case  + SCN_STYLENEEDED:  {
+             
if  (notification->nmhdr.idFrom  ==  IDM_SRCWIN)  {
+                 
+ int  + endStyled  =  SendEditor(SCI_GETENDSTYLED);
+                 
+ int  + lineEndStyled  =  SendEditor(EM_LINEFROMCHAR,  + endStyled);
+                 
+ endStyled  + =  SendEditor(EM_LINEINDEX,  lineEndStyled);
+                 
+ Colourise(endStyled,  notification->position);
+ +

+ Colourize(start, end) retrieves the specified range of text and then calls ColourizeDoc in + keywords.cxx. It starts the process by calling: +

+     SendMessage(hwnd,  SCI_STARTSTYLING,  + startPos,  31);
+ +

+ and then for each token of the text, calling: +

+     SendMessage(hwnd,  SCI_SETSTYLING,  length,  style);
+ +

+ where style is a number from 0 to 31 whose appearance has been defined using the + SCI_STYLESET... messages. +

+

+ Implementing Calltips +

+

+ Again, the SCN_CHARADDED notification is used to catch when an opening parenthesis is added. + The preceding word can then be retrieved from the current line: +

+     char  linebuf[1000];
+
    int  current  =  SendEditor(SCI_GETCURLINE,  sizeof(linebuf),
+         
+ reinterpret_cast<LPARAM>(static_cast<char  *>(linebuf)));
+
    int  pos  =  SendEditor(SCI_GETCURRENTPOS);
+
+
    int  startword  =  current  -  1;
+
    while  + (startword  + >  0  &&  + isalpha(linebuf[startword  -  1]))
+         
+ startword--;
+
    linebuf[current  -  1]  =  '\0';
+
    char*  word  =  linebuf  +  startword;
+ +

+ Then if a calltip is available it can be displayed. The calltip appears immediately below + the position specified. The calltip can be multiple lines separated by newlines (\n). +

+     pos  =  SendMessage(hwnd,  SCI_GETCURRENTPOS,  0,  0);
+
    SendMessageText(hwnd,  SCI_CALLTIPSHOW,  pos  -  wordLen  -  1,  calltip);
+ +

+ The calltip can be removed when a closing parenthesis is entered: +

+     if  (SendMessage(hwnd,  SCI_CALLTIPACTIVE,  + 0,  0))
+         
+ SendMessage(hwnd,  + SCI_CALLTIPCANCEL,  0,  + 0);
+ +

+ Obviously, it is up the application to look after supplying the appropriate calltip text. +

+

+ SciTE goes one step further, counting the commas between arguments and highlighting the + corresponding part of the calltip. This code is in ContinueCallTip. +

+

+ Page contributed by Andrew McKinlay. +

+ + + diff --git a/scintilla/doc/Steps.html b/ThirdLibs/scintilla/doc/Steps.html similarity index 97% rename from scintilla/doc/Steps.html rename to ThirdLibs/scintilla/doc/Steps.html index 765268da..ff88e88a 100644 --- a/scintilla/doc/Steps.html +++ b/ThirdLibs/scintilla/doc/Steps.html @@ -1,142 +1,142 @@ - -How to use the Scintilla Edit Control in windows? -

How to use the Scintilla Edit Control in windows?

-

- This should be a little step by step explanation how to use Scintilla in the windows environment. -

-

-

How to create Scintilla Edit Control?

-

- First of all, load the Scintilla DLL with something like: -

-
-
-	hmod = LoadLibrary("SciLexer.DLL");
-		if (hmod==NULL)
-		{
-			MessageBox(hwndParent,
-			"The Scintilla DLL could not be loaded.",
-			"Error loading Scintilla",
-			MB_OK | MB_ICONERROR);
-		}
-		
-

- If the DLL was loaded successfully, then the DLL has registered (yes, by itself) a new - window class. The new class called "Scintilla" is the new scintilla edit control. -

-

- Now you can use this new control just like any other windows control. -

-
-
-	hwndScintilla = CreateWindowEx(0,
-		"Scintilla","", WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPCHILDREN,
-		10,10,500,400,hwndParent,(HMENU)GuiID, hInstance,NULL);
-		
-

- Note the new window class name: "Scintilla". By reaching this point you actually included - a Scintilla Edit Control to your windows program. -

-

-

How to control the Scintilla Edit Control?

-

- You can control Scintilla by sending commands to the Edit Control. - There a 2 ways of doing this. A simple and fast way. -

-

The simple way to control Scintilla

-

- The simple way is just like with any other windows control. You can send messages to the - Scintilla Edit Control and receive notifications from the control. (Note that the notifications - are sent to the parent window of the Scintilla Edit Control.) -

-

- The Scintilla Edit Control knows a special message for each command. - To send commands to the Scintilla Edit Control you can use the SendMessage function. -

-
-
-	SendMessage(hwndScintilla,sci_command,wparam,lparam);
-			
-

- like: -

-
-
-	SendMessage(hwndScintilla,SCI_CREATEDOCUMENT, 0, 0);
-			
-

- Some of the commands will return a value and unused parameters should be set to NULL. -

-

-

The fast way to control Scintilla

-

- The fast way of controlling the Scintilla Edit Control is to call message handling function by yourself. - You can retrieve a pointer to the message handling function of the Scintilla Edit Control and - call it directly to execute a command. This way is much more faster than the SendMessage() way. -

-

- 1st you have to use the SCI_GETDIRECTFUNCTION and SCI_GETDIRECTPOINTER commands to - retrieve the pointer to the function and a pointer which must be the first parameter when calling the retrieved - function pointer. - You have to do this with the SendMessage way :) -

-

- The whole thing has to look like this: -

-
-
-	int (*fn)(void*,int,int,int);
-	void * ptr;
-	int canundo;
-
-	fn = (int (__cdecl *)(void *,int,int,int))SendMessage(
-		hwndScintilla,SCI_GETDIRECTFUNCTION,0,0);
-	ptr = (void *)SendMessage(hwndScintilla,SCI_GETDIRECTPOINTER,0,0);
-
-	canundo = fn(ptr,SCI_CANUNDO,0,0);
-			
-

- with "fn" as the function pointer to the message handling function of the Scintilla Control - and "ptr" as the pointer that must be used as 1st parameter. - The next parameters are the Scintilla Command with its two (optional) parameters. -

- -

-

How will I receive notifications?

-

- Whenever an event occurs where Scintilla wants to inform you about something, the Scintilla Edit Control - will send notification to the parent window. This is done by a WM_NOTITY message. - When receiving that message, you have to look in the xxx struct for the actual message. -

-

- So in Scintillas parent window message handling function you have to include some code like this: -

-
-	NMHDR *lpnmhdr;
-
-	[...]
-
-	case WM_NOTIFY:
-		lpnmhdr = (LPNMHDR) lParam;
-
-		if(lpnmhdr->hwndFrom==hwndScintilla)
-		{
-			switch(lpnmhdr->code)
-			{
-				case SCN_CHARADDED:
-					/* Hey, Scintilla just told me that a new */
-					/* character was added to the Edit Control.*/
-					/* Now i do something cool with that char. */
-				break;
-			}
-		}
-	break;
-			
-

-

- -

- Page contributed by Holger Schmidt. -

- - + +How to use the Scintilla Edit Control in windows? +

How to use the Scintilla Edit Control in windows?

+

+ This should be a little step by step explanation how to use Scintilla in the windows environment. +

+

+

How to create Scintilla Edit Control?

+

+ First of all, load the Scintilla DLL with something like: +

+
+
+	hmod = LoadLibrary("SciLexer.DLL");
+		if (hmod==NULL)
+		{
+			MessageBox(hwndParent,
+			"The Scintilla DLL could not be loaded.",
+			"Error loading Scintilla",
+			MB_OK | MB_ICONERROR);
+		}
+		
+

+ If the DLL was loaded successfully, then the DLL has registered (yes, by itself) a new + window class. The new class called "Scintilla" is the new scintilla edit control. +

+

+ Now you can use this new control just like any other windows control. +

+
+
+	hwndScintilla = CreateWindowEx(0,
+		"Scintilla","", WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPCHILDREN,
+		10,10,500,400,hwndParent,(HMENU)GuiID, hInstance,NULL);
+		
+

+ Note the new window class name: "Scintilla". By reaching this point you actually included + a Scintilla Edit Control to your windows program. +

+

+

How to control the Scintilla Edit Control?

+

+ You can control Scintilla by sending commands to the Edit Control. + There a 2 ways of doing this. A simple and fast way. +

+

The simple way to control Scintilla

+

+ The simple way is just like with any other windows control. You can send messages to the + Scintilla Edit Control and receive notifications from the control. (Note that the notifications + are sent to the parent window of the Scintilla Edit Control.) +

+

+ The Scintilla Edit Control knows a special message for each command. + To send commands to the Scintilla Edit Control you can use the SendMessage function. +

+
+
+	SendMessage(hwndScintilla,sci_command,wparam,lparam);
+			
+

+ like: +

+
+
+	SendMessage(hwndScintilla,SCI_CREATEDOCUMENT, 0, 0);
+			
+

+ Some of the commands will return a value and unused parameters should be set to NULL. +

+

+

The fast way to control Scintilla

+

+ The fast way of controlling the Scintilla Edit Control is to call message handling function by yourself. + You can retrieve a pointer to the message handling function of the Scintilla Edit Control and + call it directly to execute a command. This way is much more faster than the SendMessage() way. +

+

+ 1st you have to use the SCI_GETDIRECTFUNCTION and SCI_GETDIRECTPOINTER commands to + retrieve the pointer to the function and a pointer which must be the first parameter when calling the retrieved + function pointer. + You have to do this with the SendMessage way :) +

+

+ The whole thing has to look like this: +

+
+
+	int (*fn)(void*,int,int,int);
+	void * ptr;
+	int canundo;
+
+	fn = (int (__cdecl *)(void *,int,int,int))SendMessage(
+		hwndScintilla,SCI_GETDIRECTFUNCTION,0,0);
+	ptr = (void *)SendMessage(hwndScintilla,SCI_GETDIRECTPOINTER,0,0);
+
+	canundo = fn(ptr,SCI_CANUNDO,0,0);
+			
+

+ with "fn" as the function pointer to the message handling function of the Scintilla Control + and "ptr" as the pointer that must be used as 1st parameter. + The next parameters are the Scintilla Command with its two (optional) parameters. +

+ +

+

How will I receive notifications?

+

+ Whenever an event occurs where Scintilla wants to inform you about something, the Scintilla Edit Control + will send notification to the parent window. This is done by a WM_NOTITY message. + When receiving that message, you have to look in the xxx struct for the actual message. +

+

+ So in Scintillas parent window message handling function you have to include some code like this: +

+
+	NMHDR *lpnmhdr;
+
+	[...]
+
+	case WM_NOTIFY:
+		lpnmhdr = (LPNMHDR) lParam;
+
+		if(lpnmhdr->hwndFrom==hwndScintilla)
+		{
+			switch(lpnmhdr->code)
+			{
+				case SCN_CHARADDED:
+					/* Hey, Scintilla just told me that a new */
+					/* character was added to the Edit Control.*/
+					/* Now i do something cool with that char. */
+				break;
+			}
+		}
+	break;
+			
+

+

+ +

+ Page contributed by Holger Schmidt. +

+ + diff --git a/scintilla/doc/annotations.png b/ThirdLibs/scintilla/doc/annotations.png similarity index 100% rename from scintilla/doc/annotations.png rename to ThirdLibs/scintilla/doc/annotations.png diff --git a/scintilla/doc/index.html b/ThirdLibs/scintilla/doc/index.html similarity index 97% rename from scintilla/doc/index.html rename to ThirdLibs/scintilla/doc/index.html index d330a7dc..de746ed3 100644 --- a/scintilla/doc/index.html +++ b/ThirdLibs/scintilla/doc/index.html @@ -1,187 +1,187 @@ - - - - - - - - - - - - - - Scintilla and SciTE - - - - - - - - - - -
- Scintilla - - A free source code editing component for Win32 and - GTK+ - - Release version 3.0.3
- Site last modified January 28 2012
-
-   -
- - - - -
-   -
-
    -
  • Version 3.0.3 uses fractional positioning in more situations.
  • -
  • Version 3.0.2 fixes bugs.
  • -
  • Version 3.0.1 fixes bugs, most notably display bugs on Windows.
  • -
  • Version 3.0.0 has changed the platforms supported. - For OS X, Cocoa must be used instead of Carbon. - For recent versions of Windows, Direct2D and DirectWrite can be used. - For GTK+ all drawing is performed with Cairo as GDK drawing removed. - Palette support removed. - Font size and weight can be specified with more precision.
  • -
  • Version 2.28 allows translucent images in RGBA format to be used for margin markers and in autocompletion lists.
  • -
  • Version 2.27 fixes incorrect colours on some versions of GTK+.
  • -
- - -

- Scintilla is a free source code editing component. - It comes with complete source code and a license that - permits use in any free project or commercial product. -

-

- As well as features found in standard text editing components, Scintilla includes features - especially useful when editing and debugging source code. - These include support for syntax styling, error indicators, code completion and call tips. - The selection margin can contain markers like those used in debuggers to indicate - breakpoints and the current line. Styling choices are more open than with many editors, - allowing the use of proportional fonts, bold and italics, multiple foreground and background - colours and multiple fonts. -

-

- SciTE is a SCIntilla based Text Editor. Originally built to - demonstrate Scintilla, it has grown to be a generally useful editor with facilities for - building and running programs. It is best used for jobs with simple configurations - I use it - for building test and demonstration programs as well as SciTE and Scintilla, themselves. -

-

- Development of Scintilla started as an effort to improve the text editor in PythonWin. After - being frustrated by problems in the Richedit control used by PythonWin, it looked like the - best way forward was to write a new edit control. The biggest problem with Richedit and other - similar controls is that they treat styling changes as important persistent changes to the - document so they are saved into the undo stack and set the document's dirty flag. For source - code, styling should not be persisted as it can be mechanically recreated. -

-

- Scintilla and SciTE are currently available for Intel Win32 and Linux compatible operating - systems with GTK+. They have been run on Windows XP, Windows 7, and on Ubuntu 10.10 - with GTK+ 2.20. Here is a screenshot of - SciTE.
-

-

- You can download Scintilla. -

-

- The source code can be downloaded via CVS at the Source Forge - Scintilla project page. -

-

- Related sites. -

-

- Bugs and To Do list. -

-

- History and contribution credits. -

-

- Icons that can be used with Scintilla. -

-

- Questions and comments about Scintilla should be directed to the - scintilla-interest - mailing list, - which is for discussion of Scintilla and related projects, their bugs and future features. - This is a low traffic list, averaging less than 50 messages per week. - To avoid spam, only list members can write to the list. - New versions of Scintilla are announced on scintilla-interest and may also be received by SourceForge - members by clicking on the Monitor column icon for "scintilla" on - the downloads page. - Messages sent to my personal email address that could have been sent to the list - may receive no response. -
-

-There is a Scintilla project page -hosted on - - - - - + + + + + + + + + + + + + + Scintilla and SciTE + + + + + + + + + + +
+ Scintilla + + A free source code editing component for Win32 and + GTK+ + + Release version 3.0.3
+ Site last modified January 28 2012
+
+   +
+ + + + +
+   +
+
    +
  • Version 3.0.3 uses fractional positioning in more situations.
  • +
  • Version 3.0.2 fixes bugs.
  • +
  • Version 3.0.1 fixes bugs, most notably display bugs on Windows.
  • +
  • Version 3.0.0 has changed the platforms supported. + For OS X, Cocoa must be used instead of Carbon. + For recent versions of Windows, Direct2D and DirectWrite can be used. + For GTK+ all drawing is performed with Cairo as GDK drawing removed. + Palette support removed. + Font size and weight can be specified with more precision.
  • +
  • Version 2.28 allows translucent images in RGBA format to be used for margin markers and in autocompletion lists.
  • +
  • Version 2.27 fixes incorrect colours on some versions of GTK+.
  • +
+ + +

+ Scintilla is a free source code editing component. + It comes with complete source code and a license that + permits use in any free project or commercial product. +

+

+ As well as features found in standard text editing components, Scintilla includes features + especially useful when editing and debugging source code. + These include support for syntax styling, error indicators, code completion and call tips. + The selection margin can contain markers like those used in debuggers to indicate + breakpoints and the current line. Styling choices are more open than with many editors, + allowing the use of proportional fonts, bold and italics, multiple foreground and background + colours and multiple fonts. +

+

+ SciTE is a SCIntilla based Text Editor. Originally built to + demonstrate Scintilla, it has grown to be a generally useful editor with facilities for + building and running programs. It is best used for jobs with simple configurations - I use it + for building test and demonstration programs as well as SciTE and Scintilla, themselves. +

+

+ Development of Scintilla started as an effort to improve the text editor in PythonWin. After + being frustrated by problems in the Richedit control used by PythonWin, it looked like the + best way forward was to write a new edit control. The biggest problem with Richedit and other + similar controls is that they treat styling changes as important persistent changes to the + document so they are saved into the undo stack and set the document's dirty flag. For source + code, styling should not be persisted as it can be mechanically recreated. +

+

+ Scintilla and SciTE are currently available for Intel Win32 and Linux compatible operating + systems with GTK+. They have been run on Windows XP, Windows 7, and on Ubuntu 10.10 + with GTK+ 2.20. Here is a screenshot of + SciTE.
+

+

+ You can download Scintilla. +

+

+ The source code can be downloaded via CVS at the Source Forge + Scintilla project page. +

+

+ Related sites. +

+

+ Bugs and To Do list. +

+

+ History and contribution credits. +

+

+ Icons that can be used with Scintilla. +

+

+ Questions and comments about Scintilla should be directed to the + scintilla-interest + mailing list, + which is for discussion of Scintilla and related projects, their bugs and future features. + This is a low traffic list, averaging less than 50 messages per week. + To avoid spam, only list members can write to the list. + New versions of Scintilla are announced on scintilla-interest and may also be received by SourceForge + members by clicking on the Monitor column icon for "scintilla" on + the downloads page. + Messages sent to my personal email address that could have been sent to the list + may receive no response. +
+

+There is a Scintilla project page +hosted on + + + + + diff --git a/scintilla/doc/styledmargin.png b/ThirdLibs/scintilla/doc/styledmargin.png similarity index 100% rename from scintilla/doc/styledmargin.png rename to ThirdLibs/scintilla/doc/styledmargin.png diff --git a/scintilla/gtk/Converter.h b/ThirdLibs/scintilla/gtk/Converter.h similarity index 96% rename from scintilla/gtk/Converter.h rename to ThirdLibs/scintilla/gtk/Converter.h index 9c5123b2..8e7e3e9e 100644 --- a/scintilla/gtk/Converter.h +++ b/ThirdLibs/scintilla/gtk/Converter.h @@ -1,70 +1,70 @@ -// Scintilla source code edit control -// Converter.h - Encapsulation of iconv -// Copyright 2004 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -typedef GIConv ConverterHandle; -const ConverterHandle iconvhBad = (ConverterHandle)(-1); -// Since various versions of iconv can not agree on whether the src argument -// is char ** or const char ** provide a templatised adaptor. -template -size_t iconv_adaptor(size_t(*f_iconv)(ConverterHandle, T, size_t *, char **, size_t *), - ConverterHandle cd, char** src, size_t *srcleft, - char **dst, size_t *dstleft) { - return f_iconv(cd, (T)src, srcleft, dst, dstleft); -} -/** - * Encapsulate iconv safely and avoid iconv_adaptor complexity in client code. - */ -class Converter { - ConverterHandle iconvh; - void OpenHandle(const char *fullDestination, const char *charSetSource) { - iconvh = g_iconv_open(fullDestination, charSetSource); - } - bool Succeeded() const { - return iconvh != iconvhBad; - } -public: - Converter() { - iconvh = iconvhBad; - } - Converter(const char *charSetDestination, const char *charSetSource, bool transliterations) { - iconvh = iconvhBad; - Open(charSetDestination, charSetSource, transliterations); - } - ~Converter() { - Close(); - } - operator bool() const { - return Succeeded(); - } - void Open(const char *charSetDestination, const char *charSetSource, bool transliterations=true) { - Close(); - if (*charSetSource) { - // Try allowing approximate transliterations - if (transliterations) { - char fullDest[200]; - strcpy(fullDest, charSetDestination); - strcat(fullDest, "//TRANSLIT"); - OpenHandle(fullDest, charSetSource); - } - if (!Succeeded()) { - // Transliterations failed so try basic name - OpenHandle(charSetDestination, charSetSource); - } - } - } - void Close() { - if (Succeeded()) { - g_iconv_close(iconvh); - iconvh = iconvhBad; - } - } - size_t Convert(char** src, size_t *srcleft, char **dst, size_t *dstleft) const { - if (!Succeeded()) { - return (size_t)(-1); - } else { - return iconv_adaptor(g_iconv, iconvh, src, srcleft, dst, dstleft); - } - } -}; +// Scintilla source code edit control +// Converter.h - Encapsulation of iconv +// Copyright 2004 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +typedef GIConv ConverterHandle; +const ConverterHandle iconvhBad = (ConverterHandle)(-1); +// Since various versions of iconv can not agree on whether the src argument +// is char ** or const char ** provide a templatised adaptor. +template +size_t iconv_adaptor(size_t(*f_iconv)(ConverterHandle, T, size_t *, char **, size_t *), + ConverterHandle cd, char** src, size_t *srcleft, + char **dst, size_t *dstleft) { + return f_iconv(cd, (T)src, srcleft, dst, dstleft); +} +/** + * Encapsulate iconv safely and avoid iconv_adaptor complexity in client code. + */ +class Converter { + ConverterHandle iconvh; + void OpenHandle(const char *fullDestination, const char *charSetSource) { + iconvh = g_iconv_open(fullDestination, charSetSource); + } + bool Succeeded() const { + return iconvh != iconvhBad; + } +public: + Converter() { + iconvh = iconvhBad; + } + Converter(const char *charSetDestination, const char *charSetSource, bool transliterations) { + iconvh = iconvhBad; + Open(charSetDestination, charSetSource, transliterations); + } + ~Converter() { + Close(); + } + operator bool() const { + return Succeeded(); + } + void Open(const char *charSetDestination, const char *charSetSource, bool transliterations=true) { + Close(); + if (*charSetSource) { + // Try allowing approximate transliterations + if (transliterations) { + char fullDest[200]; + strcpy(fullDest, charSetDestination); + strcat(fullDest, "//TRANSLIT"); + OpenHandle(fullDest, charSetSource); + } + if (!Succeeded()) { + // Transliterations failed so try basic name + OpenHandle(charSetDestination, charSetSource); + } + } + } + void Close() { + if (Succeeded()) { + g_iconv_close(iconvh); + iconvh = iconvhBad; + } + } + size_t Convert(char** src, size_t *srcleft, char **dst, size_t *dstleft) const { + if (!Succeeded()) { + return (size_t)(-1); + } else { + return iconv_adaptor(g_iconv, iconvh, src, srcleft, dst, dstleft); + } + } +}; diff --git a/scintilla/gtk/PlatGTK.cxx b/ThirdLibs/scintilla/gtk/PlatGTK.cxx similarity index 96% rename from scintilla/gtk/PlatGTK.cxx rename to ThirdLibs/scintilla/gtk/PlatGTK.cxx index 51a077e5..b7ce3856 100644 --- a/scintilla/gtk/PlatGTK.cxx +++ b/ThirdLibs/scintilla/gtk/PlatGTK.cxx @@ -1,2144 +1,2144 @@ -// Scintilla source code edit control -// PlatGTK.cxx - implementation of platform facilities on GTK+/Linux -// Copyright 1998-2004 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "Scintilla.h" -#include "ScintillaWidget.h" -#include "UniConversion.h" -#include "XPM.h" - -/* GLIB must be compiled with thread support, otherwise we - will bail on trying to use locks, and that could lead to - problems for someone. `glib-config --libs gthread` needs - to be used to get the glib libraries for linking, otherwise - g_thread_init will fail */ -#define USE_LOCK defined(G_THREADS_ENABLED) && !defined(G_THREADS_IMPL_NONE) - -#include "Converter.h" - -#if GTK_CHECK_VERSION(2,20,0) -#define IS_WIDGET_FOCUSSED(w) (gtk_widget_has_focus(GTK_WIDGET(w))) -#else -#define IS_WIDGET_FOCUSSED(w) (GTK_WIDGET_HAS_FOCUS(w)) -#endif - -// The Pango version guard for pango_units_from_double and pango_units_to_double -// is more complex than simply implementing these here. - -static int pangoUnitsFromDouble(double d) { - return static_cast(d * PANGO_SCALE + 0.5); -} - -static double doubleFromPangoUnits(int pu) { - return static_cast(pu) / PANGO_SCALE; -} - -static cairo_surface_t *CreateSimilarSurface(GdkWindow *window, cairo_content_t content, int width, int height) { -#if GTK_CHECK_VERSION(2,22,0) - return gdk_window_create_similar_surface(window, content, width, height); -#else - cairo_surface_t *window_surface, *surface; - - g_return_val_if_fail(GDK_IS_WINDOW(window), NULL); - - window_surface = GDK_DRAWABLE_GET_CLASS(window)->ref_cairo_surface(window); - - surface = cairo_surface_create_similar(window_surface, content, width, height); - - cairo_surface_destroy(window_surface); - - return surface; -#endif -} - -static GdkWindow *WindowFromWidget(GtkWidget *w) { -#if GTK_CHECK_VERSION(3,0,0) - return gtk_widget_get_window(w); -#else - return w->window; -#endif -} - -#ifdef _MSC_VER -// Ignore unreferenced local functions in GTK+ headers -#pragma warning(disable: 4505) -#endif - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -enum encodingType { singleByte, UTF8, dbcs}; - -struct LOGFONT { - int size; - int weight; - bool italic; - int characterSet; - char faceName[300]; -}; - -#if USE_LOCK -static GMutex *fontMutex = NULL; - -static void InitializeGLIBThreads() { - if (!g_thread_supported()) { - g_thread_init(NULL); - } -} -#endif - -static void FontMutexAllocate() { -#if USE_LOCK - if (!fontMutex) { - InitializeGLIBThreads(); - fontMutex = g_mutex_new(); - } -#endif -} - -static void FontMutexFree() { -#if USE_LOCK - if (fontMutex) { - g_mutex_free(fontMutex); - fontMutex = NULL; - } -#endif -} - -static void FontMutexLock() { -#if USE_LOCK - g_mutex_lock(fontMutex); -#endif -} - -static void FontMutexUnlock() { -#if USE_LOCK - if (fontMutex) { - g_mutex_unlock(fontMutex); - } -#endif -} - -// On GTK+ 1.x holds a GdkFont* but on GTK+ 2.x can hold a GdkFont* or a -// PangoFontDescription*. -class FontHandle { - XYPOSITION width[128]; - encodingType et; -public: - int ascent; - PangoFontDescription *pfd; - int characterSet; - FontHandle() : et(singleByte), ascent(0), pfd(0), characterSet(-1) { - ResetWidths(et); - } - FontHandle(PangoFontDescription *pfd_, int characterSet_) { - et = singleByte; - ascent = 0; - pfd = pfd_; - characterSet = characterSet_; - ResetWidths(et); - } - ~FontHandle() { - if (pfd) - pango_font_description_free(pfd); - pfd = 0; - } - void ResetWidths(encodingType et_) { - et = et_; - for (int i=0; i<=127; i++) { - width[i] = 0; - } - } - XYPOSITION CharWidth(unsigned char ch, encodingType et_) { - XYPOSITION w = 0; - FontMutexLock(); - if ((ch <= 127) && (et == et_)) { - w = width[ch]; - } - FontMutexUnlock(); - return w; - } - void SetCharWidth(unsigned char ch, XYPOSITION w, encodingType et_) { - if (ch <= 127) { - FontMutexLock(); - if (et != et_) { - ResetWidths(et_); - } - width[ch] = w; - FontMutexUnlock(); - } - } -}; - -// X has a 16 bit coordinate space, so stop drawing here to avoid wrapping -static const int maxCoordinate = 32000; - -static FontHandle *PFont(Font &f) { - return reinterpret_cast(f.GetID()); -} - -static GtkWidget *PWidget(WindowID wid) { - return reinterpret_cast(wid); -} - -Point Point::FromLong(long lpoint) { - return Point( - Platform::LowShortFromLong(lpoint), - Platform::HighShortFromLong(lpoint)); -} - -static void SetLogFont(LOGFONT &lf, const char *faceName, int characterSet, float size, int weight, bool italic) { - memset(&lf, 0, sizeof(lf)); - lf.size = size; - lf.weight = weight; - lf.italic = italic; - lf.characterSet = characterSet; - strncpy(lf.faceName, faceName, sizeof(lf.faceName) - 1); -} - -/** - * Create a hash from the parameters for a font to allow easy checking for identity. - * If one font is the same as another, its hash will be the same, but if the hash is the - * same then they may still be different. - */ -static int HashFont(const FontParameters &fp) { - return - static_cast(fp.size+0.5) ^ - (fp.characterSet << 10) ^ - ((fp.weight / 100) << 12) ^ - (fp.italic ? 0x20000000 : 0) ^ - fp.faceName[0]; -} - -class FontCached : Font { - FontCached *next; - int usage; - LOGFONT lf; - int hash; - FontCached(const FontParameters &fp); - ~FontCached() {} - bool SameAs(const FontParameters &fp); - virtual void Release(); - static FontID CreateNewFont(const FontParameters &fp); - static FontCached *first; -public: - static FontID FindOrCreate(const FontParameters &fp); - static void ReleaseId(FontID fid_); -}; - -FontCached *FontCached::first = 0; - -FontCached::FontCached(const FontParameters &fp) : -next(0), usage(0), hash(0) { - ::SetLogFont(lf, fp.faceName, fp.characterSet, fp.size, fp.weight, fp.italic); - hash = HashFont(fp); - fid = CreateNewFont(fp); - usage = 1; -} - -bool FontCached::SameAs(const FontParameters &fp) { - return - lf.size == fp.size && - lf.weight == fp.weight && - lf.italic == fp.italic && - lf.characterSet == fp.characterSet && - 0 == strcmp(lf.faceName, fp.faceName); -} - -void FontCached::Release() { - if (fid) - delete PFont(*this); - fid = 0; -} - -FontID FontCached::FindOrCreate(const FontParameters &fp) { - FontID ret = 0; - FontMutexLock(); - int hashFind = HashFont(fp); - for (FontCached *cur = first; cur; cur = cur->next) { - if ((cur->hash == hashFind) && - cur->SameAs(fp)) { - cur->usage++; - ret = cur->fid; - } - } - if (ret == 0) { - FontCached *fc = new FontCached(fp); - if (fc) { - fc->next = first; - first = fc; - ret = fc->fid; - } - } - FontMutexUnlock(); - return ret; -} - -void FontCached::ReleaseId(FontID fid_) { - FontMutexLock(); - FontCached **pcur = &first; - for (FontCached *cur = first; cur; cur = cur->next) { - if (cur->fid == fid_) { - cur->usage--; - if (cur->usage == 0) { - *pcur = cur->next; - cur->Release(); - cur->next = 0; - delete cur; - } - break; - } - pcur = &cur->next; - } - FontMutexUnlock(); -} - -FontID FontCached::CreateNewFont(const FontParameters &fp) { - PangoFontDescription *pfd = pango_font_description_new(); - if (pfd) { - pango_font_description_set_family(pfd, - (fp.faceName[0] == '!') ? fp.faceName+1 : fp.faceName); - pango_font_description_set_size(pfd, pangoUnitsFromDouble(fp.size)); - pango_font_description_set_weight(pfd, static_cast(fp.weight)); - pango_font_description_set_style(pfd, fp.italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL); - return new FontHandle(pfd, fp.characterSet); - } - - return new FontHandle(); -} - -Font::Font() : fid(0) {} - -Font::~Font() {} - -void Font::Create(const FontParameters &fp) { - Release(); - fid = FontCached::FindOrCreate(fp); -} - -void Font::Release() { - if (fid) - FontCached::ReleaseId(fid); - fid = 0; -} - -// Required on OS X -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -// SurfaceID is a cairo_t* -class SurfaceImpl : public Surface { - encodingType et; - cairo_t *context; - cairo_surface_t *psurf; - int x; - int y; - bool inited; - bool createdGC; - PangoContext *pcontext; - PangoLayout *layout; - Converter conv; - int characterSet; - void SetConverter(int characterSet_); -public: - SurfaceImpl(); - virtual ~SurfaceImpl(); - - void Init(WindowID wid); - void Init(SurfaceID sid, WindowID wid); - void InitPixMap(int width, int height, Surface *surface_, WindowID wid); - - void Release(); - bool Initialised(); - void PenColour(ColourDesired fore); - int LogPixelsY(); - int DeviceHeightFont(int points); - void MoveTo(int x_, int y_); - void LineTo(int x_, int y_); - void Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back); - void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back); - void FillRectangle(PRectangle rc, ColourDesired back); - void FillRectangle(PRectangle rc, Surface &surfacePattern); - void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back); - void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill, - ColourDesired outline, int alphaOutline, int flags); - void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage); - void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back); - void Copy(PRectangle rc, Point from, Surface &surfaceSource); - - void DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore); - void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back); - void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back); - void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore); - void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions); - XYPOSITION WidthText(Font &font_, const char *s, int len); - XYPOSITION WidthChar(Font &font_, char ch); - XYPOSITION Ascent(Font &font_); - XYPOSITION Descent(Font &font_); - XYPOSITION InternalLeading(Font &font_); - XYPOSITION ExternalLeading(Font &font_); - XYPOSITION Height(Font &font_); - XYPOSITION AverageCharWidth(Font &font_); - - void SetClip(PRectangle rc); - void FlushCachedState(); - - void SetUnicodeMode(bool unicodeMode_); - void SetDBCSMode(int codePage); -}; -#ifdef SCI_NAMESPACE -} -#endif - -const char *CharacterSetID(int characterSet) { - switch (characterSet) { - case SC_CHARSET_ANSI: - return ""; - case SC_CHARSET_DEFAULT: - return "ISO-8859-1"; - case SC_CHARSET_BALTIC: - return "ISO-8859-13"; - case SC_CHARSET_CHINESEBIG5: - return "BIG-5"; - case SC_CHARSET_EASTEUROPE: - return "ISO-8859-2"; - case SC_CHARSET_GB2312: - return "CP936"; - case SC_CHARSET_GREEK: - return "ISO-8859-7"; - case SC_CHARSET_HANGUL: - return "CP949"; - case SC_CHARSET_MAC: - return "MACINTOSH"; - case SC_CHARSET_OEM: - return "ASCII"; - case SC_CHARSET_RUSSIAN: - return "KOI8-R"; - case SC_CHARSET_CYRILLIC: - return "CP1251"; - case SC_CHARSET_SHIFTJIS: - return "SHIFT-JIS"; - case SC_CHARSET_SYMBOL: - return ""; - case SC_CHARSET_TURKISH: - return "ISO-8859-9"; - case SC_CHARSET_JOHAB: - return "CP1361"; - case SC_CHARSET_HEBREW: - return "ISO-8859-8"; - case SC_CHARSET_ARABIC: - return "ISO-8859-6"; - case SC_CHARSET_VIETNAMESE: - return ""; - case SC_CHARSET_THAI: - return "ISO-8859-11"; - case SC_CHARSET_8859_15: - return "ISO-8859-15"; - default: - return ""; - } -} - -void SurfaceImpl::SetConverter(int characterSet_) { - if (characterSet != characterSet_) { - characterSet = characterSet_; - conv.Open("UTF-8", CharacterSetID(characterSet), false); - } -} - -SurfaceImpl::SurfaceImpl() : et(singleByte), -context(0), -psurf(0), -x(0), y(0), inited(false), createdGC(false) -, pcontext(0), layout(0), characterSet(-1) { -} - -SurfaceImpl::~SurfaceImpl() { - Release(); -} - -void SurfaceImpl::Release() { - et = singleByte; - if (createdGC) { - createdGC = false; - cairo_destroy(context); - } - context = 0; - if (psurf) - cairo_surface_destroy(psurf); - psurf = 0; - if (layout) - g_object_unref(layout); - layout = 0; - if (pcontext) - g_object_unref(pcontext); - pcontext = 0; - conv.Close(); - characterSet = -1; - x = 0; - y = 0; - inited = false; - createdGC = false; -} - -bool SurfaceImpl::Initialised() { - return inited; -} - -void SurfaceImpl::Init(WindowID wid) { - Release(); - PLATFORM_ASSERT(wid); -#if GTK_CHECK_VERSION(3,0,0) - GdkWindow *drawable_ = gtk_widget_get_window(PWidget(wid)); -#else - GdkDrawable *drawable_ = GDK_DRAWABLE(PWidget(wid)->window); -#endif - if (drawable_) { - context = gdk_cairo_create(drawable_); - PLATFORM_ASSERT(context); - } else { - // Shouldn't happen with valid window but may when calls made before - // window completely allocated and mapped. - psurf = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 1, 1); - context = cairo_create(psurf); - } - createdGC = true; - pcontext = gtk_widget_create_pango_context(PWidget(wid)); - PLATFORM_ASSERT(pcontext); - layout = pango_layout_new(pcontext); - PLATFORM_ASSERT(layout); - inited = true; -} - -void SurfaceImpl::Init(SurfaceID sid, WindowID wid) { - PLATFORM_ASSERT(sid); - Release(); - PLATFORM_ASSERT(wid); - context = cairo_reference(reinterpret_cast(sid)); - pcontext = gtk_widget_create_pango_context(PWidget(wid)); - layout = pango_layout_new(pcontext); - cairo_set_line_width(context, 1); - createdGC = true; - inited = true; -} - -void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID wid) { - PLATFORM_ASSERT(surface_); - Release(); - SurfaceImpl *surfImpl = static_cast(surface_); - PLATFORM_ASSERT(wid); - context = cairo_reference(surfImpl->context); - pcontext = gtk_widget_create_pango_context(PWidget(wid)); - PLATFORM_ASSERT(pcontext); - layout = pango_layout_new(pcontext); - PLATFORM_ASSERT(layout); - if (height > 0 && width > 0) - psurf = CreateSimilarSurface( - WindowFromWidget(PWidget(wid)), - CAIRO_CONTENT_COLOR_ALPHA, width, height); - cairo_destroy(context); - context = cairo_create(psurf); - cairo_rectangle(context, 0, 0, width, height); - cairo_set_source_rgb(context, 1.0, 0, 0); - cairo_fill(context); - // This produces sharp drawing more similar to GDK: - //cairo_set_antialias(context, CAIRO_ANTIALIAS_NONE); - cairo_set_line_width(context, 1); - createdGC = true; - inited = true; -} - -void SurfaceImpl::PenColour(ColourDesired fore) { - if (context) { - ColourDesired cdFore(fore.AsLong()); - cairo_set_source_rgb(context, - cdFore.GetRed() / 255.0, - cdFore.GetGreen() / 255.0, - cdFore.GetBlue() / 255.0); - } -} - -int SurfaceImpl::LogPixelsY() { - return 72; -} - -int SurfaceImpl::DeviceHeightFont(int points) { - int logPix = LogPixelsY(); - return (points * logPix + logPix / 2) / 72; -} - -void SurfaceImpl::MoveTo(int x_, int y_) { - x = x_; - y = y_; -} - -static int Delta(int difference) { - if (difference < 0) - return -1; - else if (difference > 0) - return 1; - else - return 0; -} - -void SurfaceImpl::LineTo(int x_, int y_) { - // cairo_line_to draws the end position, unlike Win32 or GDK with GDK_CAP_NOT_LAST. - // For simple cases, move back one pixel from end. - if (context) { - int xDiff = x_ - x; - int xDelta = Delta(xDiff); - int yDiff = y_ - y; - int yDelta = Delta(yDiff); - if ((xDiff == 0) || (yDiff == 0)) { - // Horizontal or vertical lines can be more precisely drawn as a filled rectangle - int xEnd = x_ - xDelta; - int left = Platform::Minimum(x, xEnd); - int width = abs(x - xEnd) + 1; - int yEnd = y_ - yDelta; - int top = Platform::Minimum(y, yEnd); - int height = abs(y - yEnd) + 1; - cairo_rectangle(context, left, top, width, height); - cairo_fill(context); - } else if ((abs(xDiff) == abs(yDiff))) { - // 45 degree slope - cairo_move_to(context, x + 0.5, y + 0.5); - cairo_line_to(context, x_ + 0.5 - xDelta, y_ + 0.5 - yDelta); - } else { - // Line has a different slope so difficult to avoid last pixel - cairo_move_to(context, x + 0.5, y + 0.5); - cairo_line_to(context, x_ + 0.5, y_ + 0.5); - } - cairo_stroke(context); - } - x = x_; - y = y_; -} - -void SurfaceImpl::Polygon(Point *pts, int npts, ColourDesired fore, - ColourDesired back) { - PenColour(back); - cairo_move_to(context, pts[0].x + 0.5, pts[0].y + 0.5); - for (int i = 1;i < npts;i++) { - cairo_line_to(context, pts[i].x + 0.5, pts[i].y + 0.5); - } - cairo_close_path(context); - cairo_fill_preserve(context); - PenColour(fore); - cairo_stroke(context); -} - -void SurfaceImpl::RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back) { - if (context) { - cairo_rectangle(context, rc.left + 0.5, rc.top + 0.5, - rc.right - rc.left - 1, rc.bottom - rc.top - 1); - PenColour(back); - cairo_fill_preserve(context); - PenColour(fore); - cairo_stroke(context); - } -} - -void SurfaceImpl::FillRectangle(PRectangle rc, ColourDesired back) { - PenColour(back); - if (context && (rc.left < maxCoordinate)) { // Protect against out of range - rc.left = lround(rc.left); - rc.right = lround(rc.right); - cairo_rectangle(context, rc.left, rc.top, - rc.right - rc.left, rc.bottom - rc.top); - cairo_fill(context); - } -} - -void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) { - SurfaceImpl &surfi = static_cast(surfacePattern); - bool canDraw = surfi.psurf; - if (canDraw) { - // Tile pattern over rectangle - // Currently assumes 8x8 pattern - int widthPat = 8; - int heightPat = 8; - for (int xTile = rc.left; xTile < rc.right; xTile += widthPat) { - int widthx = (xTile + widthPat > rc.right) ? rc.right - xTile : widthPat; - for (int yTile = rc.top; yTile < rc.bottom; yTile += heightPat) { - int heighty = (yTile + heightPat > rc.bottom) ? rc.bottom - yTile : heightPat; - cairo_set_source_surface(context, surfi.psurf, xTile, yTile); - cairo_rectangle(context, xTile, yTile, widthx, heighty); - cairo_fill(context); - } - } - } else { - // Something is wrong so try to show anyway - // Shows up black because colour not allocated - FillRectangle(rc, ColourDesired(0)); - } -} - -void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back) { - if (((rc.right - rc.left) > 4) && ((rc.bottom - rc.top) > 4)) { - // Approximate a round rect with some cut off corners - Point pts[] = { - Point(rc.left + 2, rc.top), - Point(rc.right - 2, rc.top), - Point(rc.right, rc.top + 2), - Point(rc.right, rc.bottom - 2), - Point(rc.right - 2, rc.bottom), - Point(rc.left + 2, rc.bottom), - Point(rc.left, rc.bottom - 2), - Point(rc.left, rc.top + 2), - }; - Polygon(pts, sizeof(pts) / sizeof(pts[0]), fore, back); - } else { - RectangleDraw(rc, fore, back); - } -} - -static void PathRoundRectangle(cairo_t *context, double left, double top, double width, double height, int radius) { - double degrees = M_PI / 180.0; - -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 2, 0) - cairo_new_sub_path(context); -#else - // First arc is in the top-right corner and starts from a point on the top line - cairo_move_to(context, left + width - radius, top); -#endif - cairo_arc(context, left + width - radius, top + radius, radius, -90 * degrees, 0 * degrees); - cairo_arc(context, left + width - radius, top + height - radius, radius, 0 * degrees, 90 * degrees); - cairo_arc(context, left + radius, top + height - radius, radius, 90 * degrees, 180 * degrees); - cairo_arc(context, left + radius, top + radius, radius, 180 * degrees, 270 * degrees); - cairo_close_path(context); -} - -void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill, - ColourDesired outline, int alphaOutline, int flags) { - if (context && rc.Width() > 0) { - ColourDesired cdFill(fill.AsLong()); - cairo_set_source_rgba(context, - cdFill.GetRed() / 255.0, - cdFill.GetGreen() / 255.0, - cdFill.GetBlue() / 255.0, - alphaFill / 255.0); - if (cornerSize > 0) - PathRoundRectangle(context, rc.left + 1.0, rc.top + 1.0, rc.right - rc.left - 2.0, rc.bottom - rc.top - 2.0, cornerSize); - else - cairo_rectangle(context, rc.left + 1.0, rc.top + 1.0, rc.right - rc.left - 2.0, rc.bottom - rc.top - 2.0); - cairo_fill(context); - - ColourDesired cdOutline(outline.AsLong()); - cairo_set_source_rgba(context, - cdOutline.GetRed() / 255.0, - cdOutline.GetGreen() / 255.0, - cdOutline.GetBlue() / 255.0, - alphaOutline / 255.0); - if (cornerSize > 0) - PathRoundRectangle(context, rc.left + 0.5, rc.top + 0.5, rc.right - rc.left - 1, rc.bottom - rc.top - 1, cornerSize); - else - cairo_rectangle(context, rc.left + 0.5, rc.top + 0.5, rc.right - rc.left - 1, rc.bottom - rc.top - 1); - cairo_stroke(context); - } -} - -void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) { - if (rc.Width() > width) - rc.left += (rc.Width() - width) / 2; - rc.right = rc.left + width; - if (rc.Height() > height) - rc.top += (rc.Height() - height) / 2; - rc.bottom = rc.top + height; - -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,6,0) - int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); -#else - int stride = width * 4; -#endif - int ucs = stride * height; - std::vector image(ucs); - for (int y=0; y(surfaceSource); - bool canDraw = surfi.psurf; - if (canDraw) { - cairo_set_source_surface(context, surfi.psurf, - rc.left - from.x, rc.top - from.y); - cairo_rectangle(context, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top); - cairo_fill(context); - } -} - -char *UTF8FromLatin1(const char *s, int &len) { - char *utfForm = new char[len*2+1]; - size_t lenU = 0; - for (int i=0;i(s[i]); - if (uch < 0x80) { - utfForm[lenU++] = uch; - } else { - utfForm[lenU++] = static_cast(0xC0 | (uch >> 6)); - utfForm[lenU++] = static_cast(0x80 | (uch & 0x3f)); - } - } - utfForm[lenU] = '\0'; - len = lenU; - return utfForm; -} - -static char *UTF8FromIconv(const Converter &conv, const char *s, int &len) { - if (conv) { - char *utfForm = new char[len*3+1]; - char *pin = const_cast(s); - size_t inLeft = len; - char *pout = utfForm; - size_t outLeft = len*3+1; - size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft); - if (conversions != ((size_t)(-1))) { - *pout = '\0'; - len = pout - utfForm; - return utfForm; - } - delete []utfForm; - } - return 0; -} - -// Work out how many bytes are in a character by trying to convert using iconv, -// returning the first length that succeeds. -static size_t MultiByteLenFromIconv(const Converter &conv, const char *s, size_t len) { - for (size_t lenMB=1; (lenMB<4) && (lenMB <= len); lenMB++) { - char wcForm[2]; - char *pin = const_cast(s); - size_t inLeft = lenMB; - char *pout = wcForm; - size_t outLeft = 2; - size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft); - if (conversions != ((size_t)(-1))) { - return lenMB; - } - } - return 1; -} - -static size_t UTF8CharLength(const char *s) { - const unsigned char *us = reinterpret_cast(s); - unsigned char ch = *us; - if (ch < 0x80) { - return 1; - } else if (ch < 0x80 + 0x40 + 0x20) { - return 2; - } else { - return 3; - } -} - -void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, - ColourDesired fore) { - PenColour(fore); - if (context) { - XYPOSITION xText = rc.left; - if (PFont(font_)->pfd) { - char *utfForm = 0; - if (et == UTF8) { - pango_layout_set_text(layout, s, len); - } else { - if (!utfForm) { - SetConverter(PFont(font_)->characterSet); - utfForm = UTF8FromIconv(conv, s, len); - } - if (!utfForm) { // iconv failed so treat as Latin1 - utfForm = UTF8FromLatin1(s, len); - } - pango_layout_set_text(layout, utfForm, len); - } - pango_layout_set_font_description(layout, PFont(font_)->pfd); - pango_cairo_update_layout(context, layout); -#ifdef PANGO_VERSION - PangoLayoutLine *pll = pango_layout_get_line_readonly(layout,0); -#else - PangoLayoutLine *pll = pango_layout_get_line(layout,0); -#endif - cairo_move_to(context, xText, ybase); - pango_cairo_show_layout_line(context, pll); - delete []utfForm; - } - } -} - -void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, - ColourDesired fore, ColourDesired back) { - FillRectangle(rc, back); - DrawTextBase(rc, font_, ybase, s, len, fore); -} - -// On GTK+, exactly same as DrawTextNoClip -void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, - ColourDesired fore, ColourDesired back) { - FillRectangle(rc, back); - DrawTextBase(rc, font_, ybase, s, len, fore); -} - -void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, - ColourDesired fore) { - // Avoid drawing spaces in transparent mode - for (int i=0;ipfd) { - if (len == 1) { - int width = PFont(font_)->CharWidth(*s, et); - if (width) { - positions[0] = width; - return; - } - } - pango_layout_set_font_description(layout, PFont(font_)->pfd); - if (et == UTF8) { - // Simple and direct as UTF-8 is native Pango encoding - int i = 0; - pango_layout_set_text(layout, s, len); - ClusterIterator iti(layout, lenPositions); - while (!iti.finished) { - iti.Next(); - int places = iti.curIndex - i; - while (i < iti.curIndex) { - // Evenly distribute space among bytes of this cluster. - // Would be better to find number of characters and then - // divide evenly between characters with each byte of a character - // being at the same position. - positions[i] = iti.position - (iti.curIndex - 1 - i) * iti.distance / places; - i++; - } - } - PLATFORM_ASSERT(i == lenPositions); - } else { - int positionsCalculated = 0; - if (et == dbcs) { - SetConverter(PFont(font_)->characterSet); - char *utfForm = UTF8FromIconv(conv, s, len); - if (utfForm) { - // Convert to UTF-8 so can ask Pango for widths, then - // Loop through UTF-8 and DBCS forms, taking account of different - // character byte lengths. - Converter convMeasure("UCS-2", CharacterSetID(characterSet), false); - pango_layout_set_text(layout, utfForm, strlen(utfForm)); - int i = 0; - int clusterStart = 0; - ClusterIterator iti(layout, strlen(utfForm)); - while (!iti.finished) { - iti.Next(); - int clusterEnd = iti.curIndex; - int places = g_utf8_strlen(utfForm + clusterStart, clusterEnd - clusterStart); - int place = 1; - while (clusterStart < clusterEnd) { - size_t lenChar = MultiByteLenFromIconv(convMeasure, s+i, len-i); - while (lenChar--) { - positions[i++] = iti.position - (places - place) * iti.distance / places; - positionsCalculated++; - } - clusterStart += UTF8CharLength(utfForm+clusterStart); - place++; - } - } - delete []utfForm; - PLATFORM_ASSERT(i == lenPositions); - } - } - if (positionsCalculated < 1 ) { - // Either Latin1 or DBCS conversion failed so treat as Latin1. - SetConverter(PFont(font_)->characterSet); - char *utfForm = UTF8FromIconv(conv, s, len); - if (!utfForm) { - utfForm = UTF8FromLatin1(s, len); - } - pango_layout_set_text(layout, utfForm, len); - int i = 0; - int clusterStart = 0; - // Each Latin1 input character may take 1 or 2 bytes in UTF-8 - // and groups of up to 3 may be represented as ligatures. - ClusterIterator iti(layout, strlen(utfForm)); - while (!iti.finished) { - iti.Next(); - int clusterEnd = iti.curIndex; - int ligatureLength = g_utf8_strlen(utfForm + clusterStart, clusterEnd - clusterStart); - PLATFORM_ASSERT(ligatureLength > 0 && ligatureLength <= 3); - for (int charInLig=0; charInLigSetCharWidth(*s, positions[0], et); - } - return; - } - } else { - // No font so return an ascending range of values - for (int i = 0; i < len; i++) { - positions[i] = i + 1; - } - } -} - -XYPOSITION SurfaceImpl::WidthText(Font &font_, const char *s, int len) { - if (font_.GetID()) { - if (PFont(font_)->pfd) { - char *utfForm = 0; - pango_layout_set_font_description(layout, PFont(font_)->pfd); - PangoRectangle pos; - if (et == UTF8) { - pango_layout_set_text(layout, s, len); - } else { - if (!utfForm) { // use iconv - SetConverter(PFont(font_)->characterSet); - utfForm = UTF8FromIconv(conv, s, len); - } - if (!utfForm) { // iconv failed so treat as Latin1 - utfForm = UTF8FromLatin1(s, len); - } - pango_layout_set_text(layout, utfForm, len); - } -#ifdef PANGO_VERSION - PangoLayoutLine *pangoLine = pango_layout_get_line_readonly(layout,0); -#else - PangoLayoutLine *pangoLine = pango_layout_get_line(layout,0); -#endif - pango_layout_line_get_extents(pangoLine, NULL, &pos); - delete []utfForm; - return doubleFromPangoUnits(pos.width); - } - return 1; - } else { - return 1; - } -} - -XYPOSITION SurfaceImpl::WidthChar(Font &font_, char ch) { - if (font_.GetID()) { - if (PFont(font_)->pfd) { - return WidthText(font_, &ch, 1); - } - return 1; - } else { - return 1; - } -} - -// Ascent and descent determined by Pango font metrics. - -XYPOSITION SurfaceImpl::Ascent(Font &font_) { - if (!(font_.GetID())) - return 1; - FontMutexLock(); - int ascent = PFont(font_)->ascent; - if ((ascent == 0) && (PFont(font_)->pfd)) { - PangoFontMetrics *metrics = pango_context_get_metrics(pcontext, - PFont(font_)->pfd, pango_context_get_language(pcontext)); - PFont(font_)->ascent = - doubleFromPangoUnits(pango_font_metrics_get_ascent(metrics)); - pango_font_metrics_unref(metrics); - ascent = PFont(font_)->ascent; - } - if (ascent == 0) { - ascent = 1; - } - FontMutexUnlock(); - return ascent; -} - -XYPOSITION SurfaceImpl::Descent(Font &font_) { - if (!(font_.GetID())) - return 1; - if (PFont(font_)->pfd) { - PangoFontMetrics *metrics = pango_context_get_metrics(pcontext, - PFont(font_)->pfd, pango_context_get_language(pcontext)); - int descent = doubleFromPangoUnits(pango_font_metrics_get_descent(metrics)); - pango_font_metrics_unref(metrics); - return descent; - } - return 0; -} - -XYPOSITION SurfaceImpl::InternalLeading(Font &) { - return 0; -} - -XYPOSITION SurfaceImpl::ExternalLeading(Font &) { - return 0; -} - -XYPOSITION SurfaceImpl::Height(Font &font_) { - return Ascent(font_) + Descent(font_); -} - -XYPOSITION SurfaceImpl::AverageCharWidth(Font &font_) { - return WidthChar(font_, 'n'); -} - -void SurfaceImpl::SetClip(PRectangle rc) { - cairo_rectangle(context, rc.left, rc.top, rc.right, rc.bottom); - cairo_clip(context); -} - -void SurfaceImpl::FlushCachedState() {} - -void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) { - if (unicodeMode_) - et = UTF8; -} - -void SurfaceImpl::SetDBCSMode(int codePage) { - if (codePage && (codePage != SC_CP_UTF8)) - et = dbcs; -} - -Surface *Surface::Allocate(int) { - return new SurfaceImpl(); -} - -Window::~Window() {} - -void Window::Destroy() { - if (wid) - gtk_widget_destroy(GTK_WIDGET(wid)); - wid = 0; -} - -bool Window::HasFocus() { - return IS_WIDGET_FOCUSSED(wid); -} - -PRectangle Window::GetPosition() { - // Before any size allocated pretend its 1000 wide so not scrolled - PRectangle rc(0, 0, 1000, 1000); - if (wid) { - GtkAllocation allocation; -#if GTK_CHECK_VERSION(3,0,0) - gtk_widget_get_allocation(PWidget(wid), &allocation); -#else - allocation = PWidget(wid)->allocation; -#endif - rc.left = allocation.x; - rc.top = allocation.y; - if (allocation.width > 20) { - rc.right = rc.left + allocation.width; - rc.bottom = rc.top + allocation.height; - } - } - return rc; -} - -void Window::SetPosition(PRectangle rc) { - GtkAllocation alloc; - alloc.x = rc.left; - alloc.y = rc.top; - alloc.width = rc.Width(); - alloc.height = rc.Height(); - gtk_widget_size_allocate(PWidget(wid), &alloc); -} - -void Window::SetPositionRelative(PRectangle rc, Window relativeTo) { - int ox = 0; - int oy = 0; - gdk_window_get_origin(WindowFromWidget(PWidget(relativeTo.wid)), &ox, &oy); - ox += rc.left; - if (ox < 0) - ox = 0; - oy += rc.top; - if (oy < 0) - oy = 0; - - /* do some corrections to fit into screen */ - int sizex = rc.right - rc.left; - int sizey = rc.bottom - rc.top; - int screenWidth = gdk_screen_width(); - int screenHeight = gdk_screen_height(); - if (sizex > screenWidth) - ox = 0; /* the best we can do */ - else if (ox + sizex > screenWidth) - ox = screenWidth - sizex; - if (oy + sizey > screenHeight) - oy = screenHeight - sizey; - - gtk_window_move(GTK_WINDOW(PWidget(wid)), ox, oy); - - gtk_widget_set_size_request(PWidget(wid), sizex, sizey); -} - -PRectangle Window::GetClientPosition() { - // On GTK+, the client position is the window position - return GetPosition(); -} - -void Window::Show(bool show) { - if (show) - gtk_widget_show(PWidget(wid)); -} - -void Window::InvalidateAll() { - if (wid) { - gtk_widget_queue_draw(PWidget(wid)); - } -} - -void Window::InvalidateRectangle(PRectangle rc) { - if (wid) { - gtk_widget_queue_draw_area(PWidget(wid), - rc.left, rc.top, - rc.right - rc.left, rc.bottom - rc.top); - } -} - -void Window::SetFont(Font &) { - // Can not be done generically but only needed for ListBox -} - -void Window::SetCursor(Cursor curs) { - // We don't set the cursor to same value numerous times under gtk because - // it stores the cursor in the window once it's set - if (curs == cursorLast) - return; - - cursorLast = curs; - GdkCursor *gdkCurs; - switch (curs) { - case cursorText: - gdkCurs = gdk_cursor_new(GDK_XTERM); - break; - case cursorArrow: - gdkCurs = gdk_cursor_new(GDK_LEFT_PTR); - break; - case cursorUp: - gdkCurs = gdk_cursor_new(GDK_CENTER_PTR); - break; - case cursorWait: - gdkCurs = gdk_cursor_new(GDK_WATCH); - break; - case cursorHand: - gdkCurs = gdk_cursor_new(GDK_HAND2); - break; - case cursorReverseArrow: - gdkCurs = gdk_cursor_new(GDK_RIGHT_PTR); - break; - default: - gdkCurs = gdk_cursor_new(GDK_LEFT_PTR); - cursorLast = cursorArrow; - break; - } - - if (WindowFromWidget(PWidget(wid))) - gdk_window_set_cursor(WindowFromWidget(PWidget(wid)), gdkCurs); -#if GTK_CHECK_VERSION(3,0,0) - g_object_unref(gdkCurs); -#else - gdk_cursor_unref(gdkCurs); -#endif -} - -void Window::SetTitle(const char *s) { - gtk_window_set_title(GTK_WINDOW(wid), s); -} - -/* Returns rectangle of monitor pt is on, both rect and pt are in Window's - gdk window coordinates */ -PRectangle Window::GetMonitorRect(Point pt) { - gint x_offset, y_offset; - - gdk_window_get_origin(WindowFromWidget(PWidget(wid)), &x_offset, &y_offset); - - GdkScreen* screen; - gint monitor_num; - GdkRectangle rect; - - screen = gtk_widget_get_screen(PWidget(wid)); - monitor_num = gdk_screen_get_monitor_at_point(screen, pt.x + x_offset, pt.y + y_offset); - gdk_screen_get_monitor_geometry(screen, monitor_num, &rect); - rect.x -= x_offset; - rect.y -= y_offset; - return PRectangle(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height); -} - -typedef std::map ImageMap; - -struct ListImage { - const RGBAImage *rgba_data; - GdkPixbuf *pixbuf; -}; - -static void list_image_free(gpointer, gpointer value, gpointer) { - ListImage *list_image = (ListImage *) value; - if (list_image->pixbuf) - g_object_unref(list_image->pixbuf); - g_free(list_image); -} - -ListBox::ListBox() { -} - -ListBox::~ListBox() { -} - -enum { - PIXBUF_COLUMN, - TEXT_COLUMN, - N_COLUMNS -}; - -class ListBoxX : public ListBox { - WindowID list; - WindowID scroller; - void *pixhash; - GtkCellRenderer* pixbuf_renderer; - RGBAImageSet images; - int desiredVisibleRows; - unsigned int maxItemCharacters; - unsigned int aveCharWidth; -public: - CallBackAction doubleClickAction; - void *doubleClickActionData; - - ListBoxX() : list(0), scroller(0), pixhash(NULL), pixbuf_renderer(0), - desiredVisibleRows(5), maxItemCharacters(0), - aveCharWidth(1), doubleClickAction(NULL), doubleClickActionData(NULL) { - } - virtual ~ListBoxX() { - if (pixhash) { - g_hash_table_foreach((GHashTable *) pixhash, list_image_free, NULL); - g_hash_table_destroy((GHashTable *) pixhash); - } - } - virtual void SetFont(Font &font); - virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_, int technology_); - virtual void SetAverageCharWidth(int width); - virtual void SetVisibleRows(int rows); - virtual int GetVisibleRows() const; - virtual PRectangle GetDesiredRect(); - virtual int CaretFromEdge(); - virtual void Clear(); - virtual void Append(char *s, int type = -1); - virtual int Length(); - virtual void Select(int n); - virtual int GetSelection(); - virtual int Find(const char *prefix); - virtual void GetValue(int n, char *value, int len); - void RegisterRGBA(int type, RGBAImage *image); - virtual void RegisterImage(int type, const char *xpm_data); - virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage); - virtual void ClearRegisteredImages(); - virtual void SetDoubleClickAction(CallBackAction action, void *data) { - doubleClickAction = action; - doubleClickActionData = data; - } - virtual void SetList(const char *listText, char separator, char typesep); -}; - -ListBox *ListBox::Allocate() { - ListBoxX *lb = new ListBoxX(); - return lb; -} - -static gboolean ButtonPress(GtkWidget *, GdkEventButton* ev, gpointer p) { - try { - ListBoxX* lb = reinterpret_cast(p); - if (ev->type == GDK_2BUTTON_PRESS && lb->doubleClickAction != NULL) { - lb->doubleClickAction(lb->doubleClickActionData); - return TRUE; - } - - } catch (...) { - // No pointer back to Scintilla to save status - } - return FALSE; -} - -/* Change the active color to the selected color so the listbox uses the color -scheme that it would use if it had the focus. */ -static void StyleSet(GtkWidget *w, GtkStyle*, void*) { - - g_return_if_fail(w != NULL); - - /* Copy the selected color to active. Note that the modify calls will cause - recursive calls to this function after the value is updated and w->style to - be set to a new object */ - -#if GTK_CHECK_VERSION(3,0,0) - GtkStyleContext *styleContext = gtk_widget_get_style_context(w); - if (styleContext == NULL) - return; - - GdkRGBA colourForeSelected; - gtk_style_context_get_color(styleContext, GTK_STATE_FLAG_SELECTED, &colourForeSelected); - GdkRGBA colourForeActive; - gtk_style_context_get_color(styleContext, GTK_STATE_FLAG_ACTIVE, &colourForeActive); - if (!gdk_rgba_equal(&colourForeSelected, &colourForeActive)) - gtk_widget_override_color(w, GTK_STATE_FLAG_ACTIVE, &colourForeSelected); - - styleContext = gtk_widget_get_style_context(w); - if (styleContext == NULL) - return; - - GdkRGBA colourBaseSelected; - gtk_style_context_get_background_color(styleContext, GTK_STATE_FLAG_SELECTED, &colourBaseSelected); - GdkRGBA colourBaseActive; - gtk_style_context_get_background_color(styleContext, GTK_STATE_FLAG_ACTIVE, &colourBaseActive); - if (!gdk_rgba_equal(&colourBaseSelected, &colourBaseActive)) - gtk_widget_override_background_color(w, GTK_STATE_FLAG_ACTIVE, &colourBaseSelected); -#else - GtkStyle *style = gtk_widget_get_style(w); - if (style == NULL) - return; - if (!gdk_color_equal(&style->base[GTK_STATE_SELECTED], &style->base[GTK_STATE_ACTIVE])) - gtk_widget_modify_base(w, GTK_STATE_ACTIVE, &style->base[GTK_STATE_SELECTED]); - style = gtk_widget_get_style(w); - if (style == NULL) - return; - if (!gdk_color_equal(&style->text[GTK_STATE_SELECTED], &style->text[GTK_STATE_ACTIVE])) - gtk_widget_modify_text(w, GTK_STATE_ACTIVE, &style->text[GTK_STATE_SELECTED]); -#endif -} - -void ListBoxX::Create(Window &, int, Point, int, bool, int) { - wid = gtk_window_new(GTK_WINDOW_POPUP); - - GtkWidget *frame = gtk_frame_new(NULL); - gtk_widget_show(frame); - gtk_container_add(GTK_CONTAINER(GetID()), frame); - gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); - gtk_container_set_border_width(GTK_CONTAINER(frame), 0); - - scroller = gtk_scrolled_window_new(NULL, NULL); - gtk_container_set_border_width(GTK_CONTAINER(scroller), 0); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroller), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_container_add(GTK_CONTAINER(frame), PWidget(scroller)); - gtk_widget_show(PWidget(scroller)); - - /* Tree and its model */ - GtkListStore *store = - gtk_list_store_new(N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING); - - list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); - g_signal_connect(G_OBJECT(list), "style-set", G_CALLBACK(StyleSet), NULL); - - GtkTreeSelection *selection = - gtk_tree_view_get_selection(GTK_TREE_VIEW(list)); - gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE); - gtk_tree_view_set_reorderable(GTK_TREE_VIEW(list), FALSE); - - /* Columns */ - GtkTreeViewColumn *column = gtk_tree_view_column_new(); - gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_title(column, "Autocomplete"); - - pixbuf_renderer = gtk_cell_renderer_pixbuf_new(); - gtk_cell_renderer_set_fixed_size(pixbuf_renderer, 0, -1); - gtk_tree_view_column_pack_start(column, pixbuf_renderer, FALSE); - gtk_tree_view_column_add_attribute(column, pixbuf_renderer, - "pixbuf", PIXBUF_COLUMN); - - GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); - gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT(renderer), 1); - gtk_tree_view_column_pack_start(column, renderer, TRUE); - gtk_tree_view_column_add_attribute(column, renderer, - "text", TEXT_COLUMN); - - gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); - if (g_object_class_find_property(G_OBJECT_GET_CLASS(list), "fixed-height-mode")) - g_object_set(G_OBJECT(list), "fixed-height-mode", TRUE, NULL); - - GtkWidget *wid = PWidget(list); // No code inside the G_OBJECT macro - gtk_container_add(GTK_CONTAINER(PWidget(scroller)), wid); - gtk_widget_show(wid); - g_signal_connect(G_OBJECT(wid), "button_press_event", - G_CALLBACK(ButtonPress), this); - gtk_widget_realize(PWidget(wid)); -} - -void ListBoxX::SetFont(Font &scint_font) { - // Only do for Pango font as there have been crashes for GDK fonts - if (Created() && PFont(scint_font)->pfd) { - // Current font is Pango font -#if GTK_CHECK_VERSION(3,0,0) - gtk_widget_override_font(PWidget(list), PFont(scint_font)->pfd); -#else - gtk_widget_modify_font(PWidget(list), PFont(scint_font)->pfd); -#endif - } -} - -void ListBoxX::SetAverageCharWidth(int width) { - aveCharWidth = width; -} - -void ListBoxX::SetVisibleRows(int rows) { - desiredVisibleRows = rows; -} - -int ListBoxX::GetVisibleRows() const { - return desiredVisibleRows; -} - -PRectangle ListBoxX::GetDesiredRect() { - // Before any size allocated pretend its 100 wide so not scrolled - PRectangle rc(0, 0, 100, 100); - if (wid) { - int rows = Length(); - if ((rows == 0) || (rows > desiredVisibleRows)) - rows = desiredVisibleRows; - - GtkRequisition req; - int height; - - // First calculate height of the clist for our desired visible - // row count otherwise it tries to expand to the total # of rows - // Get cell height - int row_width=0; - int row_height=0; - GtkTreeViewColumn * column = - gtk_tree_view_get_column(GTK_TREE_VIEW(list), 0); - gtk_tree_view_column_cell_get_size(column, NULL, - NULL, NULL, &row_width, &row_height); -#if GTK_CHECK_VERSION(3,0,0) - GtkStyleContext *styleContextList = gtk_widget_get_style_context(PWidget(list)); - GtkBorder padding; - gtk_style_context_get_padding(styleContextList, GTK_STATE_FLAG_NORMAL, &padding); - height = (rows * row_height - + padding.top + padding.bottom - + 2 * (gtk_container_get_border_width(GTK_CONTAINER(PWidget(list))) + 1)); -#else - int ythickness = PWidget(list)->style->ythickness; - height = (rows * row_height - + 2 * (ythickness - + GTK_CONTAINER(PWidget(list))->border_width + 1)); -#endif - gtk_widget_set_size_request(GTK_WIDGET(PWidget(list)), -1, height); - - // Get the size of the scroller because we set usize on the window -#if GTK_CHECK_VERSION(3,0,0) - gtk_widget_get_preferred_size(GTK_WIDGET(scroller), NULL, &req); -#else - gtk_widget_size_request(GTK_WIDGET(scroller), &req); -#endif - rc.right = req.width; - rc.bottom = req.height; - - gtk_widget_set_size_request(GTK_WIDGET(list), -1, -1); - int width = maxItemCharacters; - if (width < 12) - width = 12; - rc.right = width * (aveCharWidth + aveCharWidth / 3); - if (Length() > rows) - rc.right = rc.right + 16; - } - return rc; -} - -int ListBoxX::CaretFromEdge() { - gint renderer_width, renderer_height; - gtk_cell_renderer_get_fixed_size(pixbuf_renderer, &renderer_width, - &renderer_height); - return 4 + renderer_width; -} - -void ListBoxX::Clear() { - GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list)); - gtk_list_store_clear(GTK_LIST_STORE(model)); - maxItemCharacters = 0; -} - -static void init_pixmap(ListImage *list_image) { - if (list_image->rgba_data) { - // Drop any existing pixmap/bitmap as data may have changed - if (list_image->pixbuf) - g_object_unref(list_image->pixbuf); - list_image->pixbuf = - gdk_pixbuf_new_from_data(list_image->rgba_data->Pixels(), - GDK_COLORSPACE_RGB, - TRUE, - 8, - list_image->rgba_data->GetWidth(), - list_image->rgba_data->GetHeight(), - list_image->rgba_data->GetWidth() * 4, - NULL, - NULL); - } -} - -#define SPACING 5 - -void ListBoxX::Append(char *s, int type) { - ListImage *list_image = NULL; - if ((type >= 0) && pixhash) { - list_image = (ListImage *) g_hash_table_lookup((GHashTable *) pixhash - , (gconstpointer) GINT_TO_POINTER(type)); - } - GtkTreeIter iter; - GtkListStore *store = - GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list))); - gtk_list_store_append(GTK_LIST_STORE(store), &iter); - if (list_image) { - if (NULL == list_image->pixbuf) - init_pixmap(list_image); - if (list_image->pixbuf) { - gtk_list_store_set(GTK_LIST_STORE(store), &iter, - PIXBUF_COLUMN, list_image->pixbuf, - TEXT_COLUMN, s, -1); - - gint pixbuf_width = gdk_pixbuf_get_width(list_image->pixbuf); - gint renderer_height, renderer_width; - gtk_cell_renderer_get_fixed_size(pixbuf_renderer, - &renderer_width, &renderer_height); - if (pixbuf_width > renderer_width) - gtk_cell_renderer_set_fixed_size(pixbuf_renderer, - pixbuf_width, -1); - } else { - gtk_list_store_set(GTK_LIST_STORE(store), &iter, - TEXT_COLUMN, s, -1); - } - } else { - gtk_list_store_set(GTK_LIST_STORE(store), &iter, - TEXT_COLUMN, s, -1); - } - size_t len = strlen(s); - if (maxItemCharacters < len) - maxItemCharacters = len; -} - -int ListBoxX::Length() { - if (wid) - return gtk_tree_model_iter_n_children(gtk_tree_view_get_model - (GTK_TREE_VIEW(list)), NULL); - return 0; -} - -void ListBoxX::Select(int n) { - GtkTreeIter iter; - GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list)); - GtkTreeSelection *selection = - gtk_tree_view_get_selection(GTK_TREE_VIEW(list)); - - if (n < 0) { - gtk_tree_selection_unselect_all(selection); - return; - } - - bool valid = gtk_tree_model_iter_nth_child(model, &iter, NULL, n) != FALSE; - if (valid) { - gtk_tree_selection_select_iter(selection, &iter); - - // Move the scrollbar to show the selection. - int total = Length(); -#if GTK_CHECK_VERSION(3,0,0) - GtkAdjustment *adj = - gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(list)); - gfloat value = ((gfloat)n / total) * (gtk_adjustment_get_upper(adj) - gtk_adjustment_get_lower(adj)) - + gtk_adjustment_get_lower(adj) - gtk_adjustment_get_page_size(adj) / 2; -#else - GtkAdjustment *adj = - gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(list)); - gfloat value = ((gfloat)n / total) * (adj->upper - adj->lower) - + adj->lower - adj->page_size / 2; -#endif - // Get cell height - int row_width; - int row_height; - GtkTreeViewColumn * column = - gtk_tree_view_get_column(GTK_TREE_VIEW(list), 0); - gtk_tree_view_column_cell_get_size(column, NULL, NULL, - NULL, &row_width, &row_height); - - int rows = Length(); - if ((rows == 0) || (rows > desiredVisibleRows)) - rows = desiredVisibleRows; - if (rows & 0x1) { - // Odd rows to display -- We are now in the middle. - // Align it so that we don't chop off rows. - value += (gfloat)row_height / 2.0; - } - // Clamp it. - value = (value < 0)? 0 : value; -#if GTK_CHECK_VERSION(3,0,0) - value = (value > (gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj)))? - (gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj)) : value; -#else - value = (value > (adj->upper - adj->page_size))? - (adj->upper - adj->page_size) : value; -#endif - - // Set it. - gtk_adjustment_set_value(adj, value); - } else { - gtk_tree_selection_unselect_all(selection); - } -} - -int ListBoxX::GetSelection() { - GtkTreeIter iter; - GtkTreeModel *model; - GtkTreeSelection *selection; - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list)); - if (gtk_tree_selection_get_selected(selection, &model, &iter)) { - GtkTreePath *path = gtk_tree_model_get_path(model, &iter); - int *indices = gtk_tree_path_get_indices(path); - // Don't free indices. - if (indices) - return indices[0]; - } - return -1; -} - -int ListBoxX::Find(const char *prefix) { - GtkTreeIter iter; - GtkTreeModel *model = - gtk_tree_view_get_model(GTK_TREE_VIEW(list)); - bool valid = gtk_tree_model_get_iter_first(model, &iter) != FALSE; - int i = 0; - while(valid) { - gchar *s; - gtk_tree_model_get(model, &iter, TEXT_COLUMN, &s, -1); - if (s && (0 == strncmp(prefix, s, strlen(prefix)))) { - g_free(s); - return i; - } - g_free(s); - valid = gtk_tree_model_iter_next(model, &iter) != FALSE; - i++; - } - return -1; -} - -void ListBoxX::GetValue(int n, char *value, int len) { - char *text = NULL; - GtkTreeIter iter; - GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list)); - bool valid = gtk_tree_model_iter_nth_child(model, &iter, NULL, n) != FALSE; - if (valid) { - gtk_tree_model_get(model, &iter, TEXT_COLUMN, &text, -1); - } - if (text && len > 0) { - strncpy(value, text, len); - value[len - 1] = '\0'; - } else { - value[0] = '\0'; - } - g_free(text); -} - -// g_return_if_fail causes unnecessary compiler warning in release compile. -#ifdef _MSC_VER -#pragma warning(disable: 4127) -#endif - -void ListBoxX::RegisterRGBA(int type, RGBAImage *image) { - images.Add(type, image); - - if (!pixhash) { - pixhash = g_hash_table_new(g_direct_hash, g_direct_equal); - } - ListImage *list_image = (ListImage *) g_hash_table_lookup((GHashTable *) pixhash, - (gconstpointer) GINT_TO_POINTER(type)); - if (list_image) { - // Drop icon already registered - if (list_image->pixbuf) - g_object_unref(list_image->pixbuf); - list_image->pixbuf = NULL; - list_image->rgba_data = image; - } else { - list_image = g_new0(ListImage, 1); - list_image->rgba_data = image; - g_hash_table_insert((GHashTable *) pixhash, GINT_TO_POINTER(type), - (gpointer) list_image); - } -} - -void ListBoxX::RegisterImage(int type, const char *xpm_data) { - g_return_if_fail(xpm_data); - XPM xpmImage(xpm_data); - RegisterRGBA(type, new RGBAImage(xpmImage)); -} - -void ListBoxX::RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) { - RegisterRGBA(type, new RGBAImage(width, height, pixelsImage)); -} - -void ListBoxX::ClearRegisteredImages() { - images.Clear(); -} - -void ListBoxX::SetList(const char *listText, char separator, char typesep) { - Clear(); - int count = strlen(listText) + 1; - char *words = new char[count]; - if (words) { - memcpy(words, listText, count); - char *startword = words; - char *numword = NULL; - int i = 0; - for (; words[i]; i++) { - if (words[i] == separator) { - words[i] = '\0'; - if (numword) - *numword = '\0'; - Append(startword, numword?atoi(numword + 1):-1); - startword = words + i + 1; - numword = NULL; - } else if (words[i] == typesep) { - numword = words + i; - } - } - if (startword) { - if (numword) - *numword = '\0'; - Append(startword, numword?atoi(numword + 1):-1); - } - delete []words; - } -} - -Menu::Menu() : mid(0) {} - -void Menu::CreatePopUp() { - Destroy(); - mid = gtk_menu_new(); -#if GLIB_CHECK_VERSION(2,10,0) - g_object_ref_sink(G_OBJECT(mid)); -#else - g_object_ref(G_OBJECT(mid)); - gtk_object_sink(GTK_OBJECT(G_OBJECT(mid))); -#endif -} - -void Menu::Destroy() { - if (mid) - g_object_unref(G_OBJECT(mid)); - mid = 0; -} - -static void MenuPositionFunc(GtkMenu *, gint *x, gint *y, gboolean *, gpointer userData) { - sptr_t intFromPointer = reinterpret_cast(userData); - *x = intFromPointer & 0xffff; - *y = intFromPointer >> 16; -} - -void Menu::Show(Point pt, Window &) { - int screenHeight = gdk_screen_height(); - int screenWidth = gdk_screen_width(); - GtkMenu *widget = reinterpret_cast(mid); - gtk_widget_show_all(GTK_WIDGET(widget)); - GtkRequisition requisition; -#if GTK_CHECK_VERSION(3,0,0) - gtk_widget_get_preferred_size(GTK_WIDGET(widget), NULL, &requisition); -#else - gtk_widget_size_request(GTK_WIDGET(widget), &requisition); -#endif - if ((pt.x + requisition.width) > screenWidth) { - pt.x = screenWidth - requisition.width; - } - if ((pt.y + requisition.height) > screenHeight) { - pt.y = screenHeight - requisition.height; - } - gtk_menu_popup(widget, NULL, NULL, MenuPositionFunc, - reinterpret_cast((static_cast(pt.y) << 16) | static_cast(pt.x)), 0, - gtk_get_current_event_time()); -} - -ElapsedTime::ElapsedTime() { - GTimeVal curTime; - g_get_current_time(&curTime); - bigBit = curTime.tv_sec; - littleBit = curTime.tv_usec; -} - -class DynamicLibraryImpl : public DynamicLibrary { -protected: - GModule* m; -public: - DynamicLibraryImpl(const char *modulePath) { - m = g_module_open(modulePath, G_MODULE_BIND_LAZY); - } - - virtual ~DynamicLibraryImpl() { - if (m != NULL) - g_module_close(m); - } - - // Use g_module_symbol to get a pointer to the relevant function. - virtual Function FindFunction(const char *name) { - if (m != NULL) { - gpointer fn_address = NULL; - gboolean status = g_module_symbol(m, name, &fn_address); - if (status) - return static_cast(fn_address); - else - return NULL; - } else - return NULL; - } - - virtual bool IsValid() { - return m != NULL; - } -}; - -DynamicLibrary *DynamicLibrary::Load(const char *modulePath) { - return static_cast( new DynamicLibraryImpl(modulePath) ); -} - -double ElapsedTime::Duration(bool reset) { - GTimeVal curTime; - g_get_current_time(&curTime); - long endBigBit = curTime.tv_sec; - long endLittleBit = curTime.tv_usec; - double result = 1000000.0 * (endBigBit - bigBit); - result += endLittleBit - littleBit; - result /= 1000000.0; - if (reset) { - bigBit = endBigBit; - littleBit = endLittleBit; - } - return result; -} - -ColourDesired Platform::Chrome() { - return ColourDesired(0xe0, 0xe0, 0xe0); -} - -ColourDesired Platform::ChromeHighlight() { - return ColourDesired(0xff, 0xff, 0xff); -} - -const char *Platform::DefaultFont() { -#ifdef G_OS_WIN32 - return "Lucida Console"; -#else - return "!Sans"; -#endif -} - -int Platform::DefaultFontSize() { -#ifdef G_OS_WIN32 - return 10; -#else - return 12; -#endif -} - -unsigned int Platform::DoubleClickTime() { - return 500; // Half a second -} - -bool Platform::MouseButtonBounce() { - return true; -} - -void Platform::DebugDisplay(const char *s) { - fprintf(stderr, "%s", s); -} - -bool Platform::IsKeyDown(int) { - // TODO: discover state of keys in GTK+/X - return false; -} - -long Platform::SendScintilla( - WindowID w, unsigned int msg, unsigned long wParam, long lParam) { - return scintilla_send_message(SCINTILLA(w), msg, wParam, lParam); -} - -long Platform::SendScintillaPointer( - WindowID w, unsigned int msg, unsigned long wParam, void *lParam) { - return scintilla_send_message(SCINTILLA(w), msg, wParam, - reinterpret_cast(lParam)); -} - -bool Platform::IsDBCSLeadByte(int codePage, char ch) { - // Byte ranges found in Wikipedia articles with relevant search strings in each case - unsigned char uch = static_cast(ch); - switch (codePage) { - case 932: - // Shift_jis - return ((uch >= 0x81) && (uch <= 0x9F)) || - ((uch >= 0xE0) && (uch <= 0xFC)); - // Lead bytes F0 to FC may be a Microsoft addition. - case 936: - // GBK - return (uch >= 0x81) && (uch <= 0xFE); - case 950: - // Big5 - return (uch >= 0x81) && (uch <= 0xFE); - // Korean EUC-KR may be code page 949. - } - return false; -} - -int Platform::DBCSCharLength(int codePage, const char *s) { - if (codePage == 932 || codePage == 936 || codePage == 950) { - return IsDBCSLeadByte(codePage, s[0]) ? 2 : 1; - } else { - int bytes = mblen(s, MB_CUR_MAX); - if (bytes >= 1) - return bytes; - else - return 1; - } -} - -int Platform::DBCSCharMaxLength() { - return MB_CUR_MAX; - //return 2; -} - -// These are utility functions not really tied to a platform - -int Platform::Minimum(int a, int b) { - if (a < b) - return a; - else - return b; -} - -int Platform::Maximum(int a, int b) { - if (a > b) - return a; - else - return b; -} - -//#define TRACE - -#ifdef TRACE -void Platform::DebugPrintf(const char *format, ...) { - char buffer[2000]; - va_list pArguments; - va_start(pArguments, format); - vsprintf(buffer, format, pArguments); - va_end(pArguments); - Platform::DebugDisplay(buffer); -} -#else -void Platform::DebugPrintf(const char *, ...) {} - -#endif - -// Not supported for GTK+ -static bool assertionPopUps = true; - -bool Platform::ShowAssertionPopUps(bool assertionPopUps_) { - bool ret = assertionPopUps; - assertionPopUps = assertionPopUps_; - return ret; -} - -void Platform::Assert(const char *c, const char *file, int line) { - char buffer[2000]; - sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line); - strcat(buffer, "\r\n"); - Platform::DebugDisplay(buffer); - abort(); -} - -int Platform::Clamp(int val, int minVal, int maxVal) { - if (val > maxVal) - val = maxVal; - if (val < minVal) - val = minVal; - return val; -} - -void Platform_Initialise() { - FontMutexAllocate(); -} - -void Platform_Finalise() { - FontMutexFree(); -} +// Scintilla source code edit control +// PlatGTK.cxx - implementation of platform facilities on GTK+/Linux +// Copyright 1998-2004 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "Scintilla.h" +#include "ScintillaWidget.h" +#include "UniConversion.h" +#include "XPM.h" + +/* GLIB must be compiled with thread support, otherwise we + will bail on trying to use locks, and that could lead to + problems for someone. `glib-config --libs gthread` needs + to be used to get the glib libraries for linking, otherwise + g_thread_init will fail */ +#define USE_LOCK defined(G_THREADS_ENABLED) && !defined(G_THREADS_IMPL_NONE) + +#include "Converter.h" + +#if GTK_CHECK_VERSION(2,20,0) +#define IS_WIDGET_FOCUSSED(w) (gtk_widget_has_focus(GTK_WIDGET(w))) +#else +#define IS_WIDGET_FOCUSSED(w) (GTK_WIDGET_HAS_FOCUS(w)) +#endif + +// The Pango version guard for pango_units_from_double and pango_units_to_double +// is more complex than simply implementing these here. + +static int pangoUnitsFromDouble(double d) { + return static_cast(d * PANGO_SCALE + 0.5); +} + +static double doubleFromPangoUnits(int pu) { + return static_cast(pu) / PANGO_SCALE; +} + +static cairo_surface_t *CreateSimilarSurface(GdkWindow *window, cairo_content_t content, int width, int height) { +#if GTK_CHECK_VERSION(2,22,0) + return gdk_window_create_similar_surface(window, content, width, height); +#else + cairo_surface_t *window_surface, *surface; + + g_return_val_if_fail(GDK_IS_WINDOW(window), NULL); + + window_surface = GDK_DRAWABLE_GET_CLASS(window)->ref_cairo_surface(window); + + surface = cairo_surface_create_similar(window_surface, content, width, height); + + cairo_surface_destroy(window_surface); + + return surface; +#endif +} + +static GdkWindow *WindowFromWidget(GtkWidget *w) { +#if GTK_CHECK_VERSION(3,0,0) + return gtk_widget_get_window(w); +#else + return w->window; +#endif +} + +#ifdef _MSC_VER +// Ignore unreferenced local functions in GTK+ headers +#pragma warning(disable: 4505) +#endif + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +enum encodingType { singleByte, UTF8, dbcs}; + +struct LOGFONT { + int size; + int weight; + bool italic; + int characterSet; + char faceName[300]; +}; + +#if USE_LOCK +static GMutex *fontMutex = NULL; + +static void InitializeGLIBThreads() { + if (!g_thread_supported()) { + g_thread_init(NULL); + } +} +#endif + +static void FontMutexAllocate() { +#if USE_LOCK + if (!fontMutex) { + InitializeGLIBThreads(); + fontMutex = g_mutex_new(); + } +#endif +} + +static void FontMutexFree() { +#if USE_LOCK + if (fontMutex) { + g_mutex_free(fontMutex); + fontMutex = NULL; + } +#endif +} + +static void FontMutexLock() { +#if USE_LOCK + g_mutex_lock(fontMutex); +#endif +} + +static void FontMutexUnlock() { +#if USE_LOCK + if (fontMutex) { + g_mutex_unlock(fontMutex); + } +#endif +} + +// On GTK+ 1.x holds a GdkFont* but on GTK+ 2.x can hold a GdkFont* or a +// PangoFontDescription*. +class FontHandle { + XYPOSITION width[128]; + encodingType et; +public: + int ascent; + PangoFontDescription *pfd; + int characterSet; + FontHandle() : et(singleByte), ascent(0), pfd(0), characterSet(-1) { + ResetWidths(et); + } + FontHandle(PangoFontDescription *pfd_, int characterSet_) { + et = singleByte; + ascent = 0; + pfd = pfd_; + characterSet = characterSet_; + ResetWidths(et); + } + ~FontHandle() { + if (pfd) + pango_font_description_free(pfd); + pfd = 0; + } + void ResetWidths(encodingType et_) { + et = et_; + for (int i=0; i<=127; i++) { + width[i] = 0; + } + } + XYPOSITION CharWidth(unsigned char ch, encodingType et_) { + XYPOSITION w = 0; + FontMutexLock(); + if ((ch <= 127) && (et == et_)) { + w = width[ch]; + } + FontMutexUnlock(); + return w; + } + void SetCharWidth(unsigned char ch, XYPOSITION w, encodingType et_) { + if (ch <= 127) { + FontMutexLock(); + if (et != et_) { + ResetWidths(et_); + } + width[ch] = w; + FontMutexUnlock(); + } + } +}; + +// X has a 16 bit coordinate space, so stop drawing here to avoid wrapping +static const int maxCoordinate = 32000; + +static FontHandle *PFont(Font &f) { + return reinterpret_cast(f.GetID()); +} + +static GtkWidget *PWidget(WindowID wid) { + return reinterpret_cast(wid); +} + +Point Point::FromLong(long lpoint) { + return Point( + Platform::LowShortFromLong(lpoint), + Platform::HighShortFromLong(lpoint)); +} + +static void SetLogFont(LOGFONT &lf, const char *faceName, int characterSet, float size, int weight, bool italic) { + memset(&lf, 0, sizeof(lf)); + lf.size = size; + lf.weight = weight; + lf.italic = italic; + lf.characterSet = characterSet; + strncpy(lf.faceName, faceName, sizeof(lf.faceName) - 1); +} + +/** + * Create a hash from the parameters for a font to allow easy checking for identity. + * If one font is the same as another, its hash will be the same, but if the hash is the + * same then they may still be different. + */ +static int HashFont(const FontParameters &fp) { + return + static_cast(fp.size+0.5) ^ + (fp.characterSet << 10) ^ + ((fp.weight / 100) << 12) ^ + (fp.italic ? 0x20000000 : 0) ^ + fp.faceName[0]; +} + +class FontCached : Font { + FontCached *next; + int usage; + LOGFONT lf; + int hash; + FontCached(const FontParameters &fp); + ~FontCached() {} + bool SameAs(const FontParameters &fp); + virtual void Release(); + static FontID CreateNewFont(const FontParameters &fp); + static FontCached *first; +public: + static FontID FindOrCreate(const FontParameters &fp); + static void ReleaseId(FontID fid_); +}; + +FontCached *FontCached::first = 0; + +FontCached::FontCached(const FontParameters &fp) : +next(0), usage(0), hash(0) { + ::SetLogFont(lf, fp.faceName, fp.characterSet, fp.size, fp.weight, fp.italic); + hash = HashFont(fp); + fid = CreateNewFont(fp); + usage = 1; +} + +bool FontCached::SameAs(const FontParameters &fp) { + return + lf.size == fp.size && + lf.weight == fp.weight && + lf.italic == fp.italic && + lf.characterSet == fp.characterSet && + 0 == strcmp(lf.faceName, fp.faceName); +} + +void FontCached::Release() { + if (fid) + delete PFont(*this); + fid = 0; +} + +FontID FontCached::FindOrCreate(const FontParameters &fp) { + FontID ret = 0; + FontMutexLock(); + int hashFind = HashFont(fp); + for (FontCached *cur = first; cur; cur = cur->next) { + if ((cur->hash == hashFind) && + cur->SameAs(fp)) { + cur->usage++; + ret = cur->fid; + } + } + if (ret == 0) { + FontCached *fc = new FontCached(fp); + if (fc) { + fc->next = first; + first = fc; + ret = fc->fid; + } + } + FontMutexUnlock(); + return ret; +} + +void FontCached::ReleaseId(FontID fid_) { + FontMutexLock(); + FontCached **pcur = &first; + for (FontCached *cur = first; cur; cur = cur->next) { + if (cur->fid == fid_) { + cur->usage--; + if (cur->usage == 0) { + *pcur = cur->next; + cur->Release(); + cur->next = 0; + delete cur; + } + break; + } + pcur = &cur->next; + } + FontMutexUnlock(); +} + +FontID FontCached::CreateNewFont(const FontParameters &fp) { + PangoFontDescription *pfd = pango_font_description_new(); + if (pfd) { + pango_font_description_set_family(pfd, + (fp.faceName[0] == '!') ? fp.faceName+1 : fp.faceName); + pango_font_description_set_size(pfd, pangoUnitsFromDouble(fp.size)); + pango_font_description_set_weight(pfd, static_cast(fp.weight)); + pango_font_description_set_style(pfd, fp.italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL); + return new FontHandle(pfd, fp.characterSet); + } + + return new FontHandle(); +} + +Font::Font() : fid(0) {} + +Font::~Font() {} + +void Font::Create(const FontParameters &fp) { + Release(); + fid = FontCached::FindOrCreate(fp); +} + +void Font::Release() { + if (fid) + FontCached::ReleaseId(fid); + fid = 0; +} + +// Required on OS X +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +// SurfaceID is a cairo_t* +class SurfaceImpl : public Surface { + encodingType et; + cairo_t *context; + cairo_surface_t *psurf; + int x; + int y; + bool inited; + bool createdGC; + PangoContext *pcontext; + PangoLayout *layout; + Converter conv; + int characterSet; + void SetConverter(int characterSet_); +public: + SurfaceImpl(); + virtual ~SurfaceImpl(); + + void Init(WindowID wid); + void Init(SurfaceID sid, WindowID wid); + void InitPixMap(int width, int height, Surface *surface_, WindowID wid); + + void Release(); + bool Initialised(); + void PenColour(ColourDesired fore); + int LogPixelsY(); + int DeviceHeightFont(int points); + void MoveTo(int x_, int y_); + void LineTo(int x_, int y_); + void Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back); + void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back); + void FillRectangle(PRectangle rc, ColourDesired back); + void FillRectangle(PRectangle rc, Surface &surfacePattern); + void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back); + void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill, + ColourDesired outline, int alphaOutline, int flags); + void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage); + void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back); + void Copy(PRectangle rc, Point from, Surface &surfaceSource); + + void DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore); + void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back); + void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back); + void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore); + void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions); + XYPOSITION WidthText(Font &font_, const char *s, int len); + XYPOSITION WidthChar(Font &font_, char ch); + XYPOSITION Ascent(Font &font_); + XYPOSITION Descent(Font &font_); + XYPOSITION InternalLeading(Font &font_); + XYPOSITION ExternalLeading(Font &font_); + XYPOSITION Height(Font &font_); + XYPOSITION AverageCharWidth(Font &font_); + + void SetClip(PRectangle rc); + void FlushCachedState(); + + void SetUnicodeMode(bool unicodeMode_); + void SetDBCSMode(int codePage); +}; +#ifdef SCI_NAMESPACE +} +#endif + +const char *CharacterSetID(int characterSet) { + switch (characterSet) { + case SC_CHARSET_ANSI: + return ""; + case SC_CHARSET_DEFAULT: + return "ISO-8859-1"; + case SC_CHARSET_BALTIC: + return "ISO-8859-13"; + case SC_CHARSET_CHINESEBIG5: + return "BIG-5"; + case SC_CHARSET_EASTEUROPE: + return "ISO-8859-2"; + case SC_CHARSET_GB2312: + return "CP936"; + case SC_CHARSET_GREEK: + return "ISO-8859-7"; + case SC_CHARSET_HANGUL: + return "CP949"; + case SC_CHARSET_MAC: + return "MACINTOSH"; + case SC_CHARSET_OEM: + return "ASCII"; + case SC_CHARSET_RUSSIAN: + return "KOI8-R"; + case SC_CHARSET_CYRILLIC: + return "CP1251"; + case SC_CHARSET_SHIFTJIS: + return "SHIFT-JIS"; + case SC_CHARSET_SYMBOL: + return ""; + case SC_CHARSET_TURKISH: + return "ISO-8859-9"; + case SC_CHARSET_JOHAB: + return "CP1361"; + case SC_CHARSET_HEBREW: + return "ISO-8859-8"; + case SC_CHARSET_ARABIC: + return "ISO-8859-6"; + case SC_CHARSET_VIETNAMESE: + return ""; + case SC_CHARSET_THAI: + return "ISO-8859-11"; + case SC_CHARSET_8859_15: + return "ISO-8859-15"; + default: + return ""; + } +} + +void SurfaceImpl::SetConverter(int characterSet_) { + if (characterSet != characterSet_) { + characterSet = characterSet_; + conv.Open("UTF-8", CharacterSetID(characterSet), false); + } +} + +SurfaceImpl::SurfaceImpl() : et(singleByte), +context(0), +psurf(0), +x(0), y(0), inited(false), createdGC(false) +, pcontext(0), layout(0), characterSet(-1) { +} + +SurfaceImpl::~SurfaceImpl() { + Release(); +} + +void SurfaceImpl::Release() { + et = singleByte; + if (createdGC) { + createdGC = false; + cairo_destroy(context); + } + context = 0; + if (psurf) + cairo_surface_destroy(psurf); + psurf = 0; + if (layout) + g_object_unref(layout); + layout = 0; + if (pcontext) + g_object_unref(pcontext); + pcontext = 0; + conv.Close(); + characterSet = -1; + x = 0; + y = 0; + inited = false; + createdGC = false; +} + +bool SurfaceImpl::Initialised() { + return inited; +} + +void SurfaceImpl::Init(WindowID wid) { + Release(); + PLATFORM_ASSERT(wid); +#if GTK_CHECK_VERSION(3,0,0) + GdkWindow *drawable_ = gtk_widget_get_window(PWidget(wid)); +#else + GdkDrawable *drawable_ = GDK_DRAWABLE(PWidget(wid)->window); +#endif + if (drawable_) { + context = gdk_cairo_create(drawable_); + PLATFORM_ASSERT(context); + } else { + // Shouldn't happen with valid window but may when calls made before + // window completely allocated and mapped. + psurf = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 1, 1); + context = cairo_create(psurf); + } + createdGC = true; + pcontext = gtk_widget_create_pango_context(PWidget(wid)); + PLATFORM_ASSERT(pcontext); + layout = pango_layout_new(pcontext); + PLATFORM_ASSERT(layout); + inited = true; +} + +void SurfaceImpl::Init(SurfaceID sid, WindowID wid) { + PLATFORM_ASSERT(sid); + Release(); + PLATFORM_ASSERT(wid); + context = cairo_reference(reinterpret_cast(sid)); + pcontext = gtk_widget_create_pango_context(PWidget(wid)); + layout = pango_layout_new(pcontext); + cairo_set_line_width(context, 1); + createdGC = true; + inited = true; +} + +void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID wid) { + PLATFORM_ASSERT(surface_); + Release(); + SurfaceImpl *surfImpl = static_cast(surface_); + PLATFORM_ASSERT(wid); + context = cairo_reference(surfImpl->context); + pcontext = gtk_widget_create_pango_context(PWidget(wid)); + PLATFORM_ASSERT(pcontext); + layout = pango_layout_new(pcontext); + PLATFORM_ASSERT(layout); + if (height > 0 && width > 0) + psurf = CreateSimilarSurface( + WindowFromWidget(PWidget(wid)), + CAIRO_CONTENT_COLOR_ALPHA, width, height); + cairo_destroy(context); + context = cairo_create(psurf); + cairo_rectangle(context, 0, 0, width, height); + cairo_set_source_rgb(context, 1.0, 0, 0); + cairo_fill(context); + // This produces sharp drawing more similar to GDK: + //cairo_set_antialias(context, CAIRO_ANTIALIAS_NONE); + cairo_set_line_width(context, 1); + createdGC = true; + inited = true; +} + +void SurfaceImpl::PenColour(ColourDesired fore) { + if (context) { + ColourDesired cdFore(fore.AsLong()); + cairo_set_source_rgb(context, + cdFore.GetRed() / 255.0, + cdFore.GetGreen() / 255.0, + cdFore.GetBlue() / 255.0); + } +} + +int SurfaceImpl::LogPixelsY() { + return 72; +} + +int SurfaceImpl::DeviceHeightFont(int points) { + int logPix = LogPixelsY(); + return (points * logPix + logPix / 2) / 72; +} + +void SurfaceImpl::MoveTo(int x_, int y_) { + x = x_; + y = y_; +} + +static int Delta(int difference) { + if (difference < 0) + return -1; + else if (difference > 0) + return 1; + else + return 0; +} + +void SurfaceImpl::LineTo(int x_, int y_) { + // cairo_line_to draws the end position, unlike Win32 or GDK with GDK_CAP_NOT_LAST. + // For simple cases, move back one pixel from end. + if (context) { + int xDiff = x_ - x; + int xDelta = Delta(xDiff); + int yDiff = y_ - y; + int yDelta = Delta(yDiff); + if ((xDiff == 0) || (yDiff == 0)) { + // Horizontal or vertical lines can be more precisely drawn as a filled rectangle + int xEnd = x_ - xDelta; + int left = Platform::Minimum(x, xEnd); + int width = abs(x - xEnd) + 1; + int yEnd = y_ - yDelta; + int top = Platform::Minimum(y, yEnd); + int height = abs(y - yEnd) + 1; + cairo_rectangle(context, left, top, width, height); + cairo_fill(context); + } else if ((abs(xDiff) == abs(yDiff))) { + // 45 degree slope + cairo_move_to(context, x + 0.5, y + 0.5); + cairo_line_to(context, x_ + 0.5 - xDelta, y_ + 0.5 - yDelta); + } else { + // Line has a different slope so difficult to avoid last pixel + cairo_move_to(context, x + 0.5, y + 0.5); + cairo_line_to(context, x_ + 0.5, y_ + 0.5); + } + cairo_stroke(context); + } + x = x_; + y = y_; +} + +void SurfaceImpl::Polygon(Point *pts, int npts, ColourDesired fore, + ColourDesired back) { + PenColour(back); + cairo_move_to(context, pts[0].x + 0.5, pts[0].y + 0.5); + for (int i = 1;i < npts;i++) { + cairo_line_to(context, pts[i].x + 0.5, pts[i].y + 0.5); + } + cairo_close_path(context); + cairo_fill_preserve(context); + PenColour(fore); + cairo_stroke(context); +} + +void SurfaceImpl::RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back) { + if (context) { + cairo_rectangle(context, rc.left + 0.5, rc.top + 0.5, + rc.right - rc.left - 1, rc.bottom - rc.top - 1); + PenColour(back); + cairo_fill_preserve(context); + PenColour(fore); + cairo_stroke(context); + } +} + +void SurfaceImpl::FillRectangle(PRectangle rc, ColourDesired back) { + PenColour(back); + if (context && (rc.left < maxCoordinate)) { // Protect against out of range + rc.left = lround(rc.left); + rc.right = lround(rc.right); + cairo_rectangle(context, rc.left, rc.top, + rc.right - rc.left, rc.bottom - rc.top); + cairo_fill(context); + } +} + +void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) { + SurfaceImpl &surfi = static_cast(surfacePattern); + bool canDraw = surfi.psurf; + if (canDraw) { + // Tile pattern over rectangle + // Currently assumes 8x8 pattern + int widthPat = 8; + int heightPat = 8; + for (int xTile = rc.left; xTile < rc.right; xTile += widthPat) { + int widthx = (xTile + widthPat > rc.right) ? rc.right - xTile : widthPat; + for (int yTile = rc.top; yTile < rc.bottom; yTile += heightPat) { + int heighty = (yTile + heightPat > rc.bottom) ? rc.bottom - yTile : heightPat; + cairo_set_source_surface(context, surfi.psurf, xTile, yTile); + cairo_rectangle(context, xTile, yTile, widthx, heighty); + cairo_fill(context); + } + } + } else { + // Something is wrong so try to show anyway + // Shows up black because colour not allocated + FillRectangle(rc, ColourDesired(0)); + } +} + +void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back) { + if (((rc.right - rc.left) > 4) && ((rc.bottom - rc.top) > 4)) { + // Approximate a round rect with some cut off corners + Point pts[] = { + Point(rc.left + 2, rc.top), + Point(rc.right - 2, rc.top), + Point(rc.right, rc.top + 2), + Point(rc.right, rc.bottom - 2), + Point(rc.right - 2, rc.bottom), + Point(rc.left + 2, rc.bottom), + Point(rc.left, rc.bottom - 2), + Point(rc.left, rc.top + 2), + }; + Polygon(pts, sizeof(pts) / sizeof(pts[0]), fore, back); + } else { + RectangleDraw(rc, fore, back); + } +} + +static void PathRoundRectangle(cairo_t *context, double left, double top, double width, double height, int radius) { + double degrees = M_PI / 180.0; + +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 2, 0) + cairo_new_sub_path(context); +#else + // First arc is in the top-right corner and starts from a point on the top line + cairo_move_to(context, left + width - radius, top); +#endif + cairo_arc(context, left + width - radius, top + radius, radius, -90 * degrees, 0 * degrees); + cairo_arc(context, left + width - radius, top + height - radius, radius, 0 * degrees, 90 * degrees); + cairo_arc(context, left + radius, top + height - radius, radius, 90 * degrees, 180 * degrees); + cairo_arc(context, left + radius, top + radius, radius, 180 * degrees, 270 * degrees); + cairo_close_path(context); +} + +void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill, + ColourDesired outline, int alphaOutline, int flags) { + if (context && rc.Width() > 0) { + ColourDesired cdFill(fill.AsLong()); + cairo_set_source_rgba(context, + cdFill.GetRed() / 255.0, + cdFill.GetGreen() / 255.0, + cdFill.GetBlue() / 255.0, + alphaFill / 255.0); + if (cornerSize > 0) + PathRoundRectangle(context, rc.left + 1.0, rc.top + 1.0, rc.right - rc.left - 2.0, rc.bottom - rc.top - 2.0, cornerSize); + else + cairo_rectangle(context, rc.left + 1.0, rc.top + 1.0, rc.right - rc.left - 2.0, rc.bottom - rc.top - 2.0); + cairo_fill(context); + + ColourDesired cdOutline(outline.AsLong()); + cairo_set_source_rgba(context, + cdOutline.GetRed() / 255.0, + cdOutline.GetGreen() / 255.0, + cdOutline.GetBlue() / 255.0, + alphaOutline / 255.0); + if (cornerSize > 0) + PathRoundRectangle(context, rc.left + 0.5, rc.top + 0.5, rc.right - rc.left - 1, rc.bottom - rc.top - 1, cornerSize); + else + cairo_rectangle(context, rc.left + 0.5, rc.top + 0.5, rc.right - rc.left - 1, rc.bottom - rc.top - 1); + cairo_stroke(context); + } +} + +void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) { + if (rc.Width() > width) + rc.left += (rc.Width() - width) / 2; + rc.right = rc.left + width; + if (rc.Height() > height) + rc.top += (rc.Height() - height) / 2; + rc.bottom = rc.top + height; + +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,6,0) + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); +#else + int stride = width * 4; +#endif + int ucs = stride * height; + std::vector image(ucs); + for (int y=0; y(surfaceSource); + bool canDraw = surfi.psurf; + if (canDraw) { + cairo_set_source_surface(context, surfi.psurf, + rc.left - from.x, rc.top - from.y); + cairo_rectangle(context, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top); + cairo_fill(context); + } +} + +char *UTF8FromLatin1(const char *s, int &len) { + char *utfForm = new char[len*2+1]; + size_t lenU = 0; + for (int i=0;i(s[i]); + if (uch < 0x80) { + utfForm[lenU++] = uch; + } else { + utfForm[lenU++] = static_cast(0xC0 | (uch >> 6)); + utfForm[lenU++] = static_cast(0x80 | (uch & 0x3f)); + } + } + utfForm[lenU] = '\0'; + len = lenU; + return utfForm; +} + +static char *UTF8FromIconv(const Converter &conv, const char *s, int &len) { + if (conv) { + char *utfForm = new char[len*3+1]; + char *pin = const_cast(s); + size_t inLeft = len; + char *pout = utfForm; + size_t outLeft = len*3+1; + size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft); + if (conversions != ((size_t)(-1))) { + *pout = '\0'; + len = pout - utfForm; + return utfForm; + } + delete []utfForm; + } + return 0; +} + +// Work out how many bytes are in a character by trying to convert using iconv, +// returning the first length that succeeds. +static size_t MultiByteLenFromIconv(const Converter &conv, const char *s, size_t len) { + for (size_t lenMB=1; (lenMB<4) && (lenMB <= len); lenMB++) { + char wcForm[2]; + char *pin = const_cast(s); + size_t inLeft = lenMB; + char *pout = wcForm; + size_t outLeft = 2; + size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft); + if (conversions != ((size_t)(-1))) { + return lenMB; + } + } + return 1; +} + +static size_t UTF8CharLength(const char *s) { + const unsigned char *us = reinterpret_cast(s); + unsigned char ch = *us; + if (ch < 0x80) { + return 1; + } else if (ch < 0x80 + 0x40 + 0x20) { + return 2; + } else { + return 3; + } +} + +void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, + ColourDesired fore) { + PenColour(fore); + if (context) { + XYPOSITION xText = rc.left; + if (PFont(font_)->pfd) { + char *utfForm = 0; + if (et == UTF8) { + pango_layout_set_text(layout, s, len); + } else { + if (!utfForm) { + SetConverter(PFont(font_)->characterSet); + utfForm = UTF8FromIconv(conv, s, len); + } + if (!utfForm) { // iconv failed so treat as Latin1 + utfForm = UTF8FromLatin1(s, len); + } + pango_layout_set_text(layout, utfForm, len); + } + pango_layout_set_font_description(layout, PFont(font_)->pfd); + pango_cairo_update_layout(context, layout); +#ifdef PANGO_VERSION + PangoLayoutLine *pll = pango_layout_get_line_readonly(layout,0); +#else + PangoLayoutLine *pll = pango_layout_get_line(layout,0); +#endif + cairo_move_to(context, xText, ybase); + pango_cairo_show_layout_line(context, pll); + delete []utfForm; + } + } +} + +void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, + ColourDesired fore, ColourDesired back) { + FillRectangle(rc, back); + DrawTextBase(rc, font_, ybase, s, len, fore); +} + +// On GTK+, exactly same as DrawTextNoClip +void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, + ColourDesired fore, ColourDesired back) { + FillRectangle(rc, back); + DrawTextBase(rc, font_, ybase, s, len, fore); +} + +void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, + ColourDesired fore) { + // Avoid drawing spaces in transparent mode + for (int i=0;ipfd) { + if (len == 1) { + int width = PFont(font_)->CharWidth(*s, et); + if (width) { + positions[0] = width; + return; + } + } + pango_layout_set_font_description(layout, PFont(font_)->pfd); + if (et == UTF8) { + // Simple and direct as UTF-8 is native Pango encoding + int i = 0; + pango_layout_set_text(layout, s, len); + ClusterIterator iti(layout, lenPositions); + while (!iti.finished) { + iti.Next(); + int places = iti.curIndex - i; + while (i < iti.curIndex) { + // Evenly distribute space among bytes of this cluster. + // Would be better to find number of characters and then + // divide evenly between characters with each byte of a character + // being at the same position. + positions[i] = iti.position - (iti.curIndex - 1 - i) * iti.distance / places; + i++; + } + } + PLATFORM_ASSERT(i == lenPositions); + } else { + int positionsCalculated = 0; + if (et == dbcs) { + SetConverter(PFont(font_)->characterSet); + char *utfForm = UTF8FromIconv(conv, s, len); + if (utfForm) { + // Convert to UTF-8 so can ask Pango for widths, then + // Loop through UTF-8 and DBCS forms, taking account of different + // character byte lengths. + Converter convMeasure("UCS-2", CharacterSetID(characterSet), false); + pango_layout_set_text(layout, utfForm, strlen(utfForm)); + int i = 0; + int clusterStart = 0; + ClusterIterator iti(layout, strlen(utfForm)); + while (!iti.finished) { + iti.Next(); + int clusterEnd = iti.curIndex; + int places = g_utf8_strlen(utfForm + clusterStart, clusterEnd - clusterStart); + int place = 1; + while (clusterStart < clusterEnd) { + size_t lenChar = MultiByteLenFromIconv(convMeasure, s+i, len-i); + while (lenChar--) { + positions[i++] = iti.position - (places - place) * iti.distance / places; + positionsCalculated++; + } + clusterStart += UTF8CharLength(utfForm+clusterStart); + place++; + } + } + delete []utfForm; + PLATFORM_ASSERT(i == lenPositions); + } + } + if (positionsCalculated < 1 ) { + // Either Latin1 or DBCS conversion failed so treat as Latin1. + SetConverter(PFont(font_)->characterSet); + char *utfForm = UTF8FromIconv(conv, s, len); + if (!utfForm) { + utfForm = UTF8FromLatin1(s, len); + } + pango_layout_set_text(layout, utfForm, len); + int i = 0; + int clusterStart = 0; + // Each Latin1 input character may take 1 or 2 bytes in UTF-8 + // and groups of up to 3 may be represented as ligatures. + ClusterIterator iti(layout, strlen(utfForm)); + while (!iti.finished) { + iti.Next(); + int clusterEnd = iti.curIndex; + int ligatureLength = g_utf8_strlen(utfForm + clusterStart, clusterEnd - clusterStart); + PLATFORM_ASSERT(ligatureLength > 0 && ligatureLength <= 3); + for (int charInLig=0; charInLigSetCharWidth(*s, positions[0], et); + } + return; + } + } else { + // No font so return an ascending range of values + for (int i = 0; i < len; i++) { + positions[i] = i + 1; + } + } +} + +XYPOSITION SurfaceImpl::WidthText(Font &font_, const char *s, int len) { + if (font_.GetID()) { + if (PFont(font_)->pfd) { + char *utfForm = 0; + pango_layout_set_font_description(layout, PFont(font_)->pfd); + PangoRectangle pos; + if (et == UTF8) { + pango_layout_set_text(layout, s, len); + } else { + if (!utfForm) { // use iconv + SetConverter(PFont(font_)->characterSet); + utfForm = UTF8FromIconv(conv, s, len); + } + if (!utfForm) { // iconv failed so treat as Latin1 + utfForm = UTF8FromLatin1(s, len); + } + pango_layout_set_text(layout, utfForm, len); + } +#ifdef PANGO_VERSION + PangoLayoutLine *pangoLine = pango_layout_get_line_readonly(layout,0); +#else + PangoLayoutLine *pangoLine = pango_layout_get_line(layout,0); +#endif + pango_layout_line_get_extents(pangoLine, NULL, &pos); + delete []utfForm; + return doubleFromPangoUnits(pos.width); + } + return 1; + } else { + return 1; + } +} + +XYPOSITION SurfaceImpl::WidthChar(Font &font_, char ch) { + if (font_.GetID()) { + if (PFont(font_)->pfd) { + return WidthText(font_, &ch, 1); + } + return 1; + } else { + return 1; + } +} + +// Ascent and descent determined by Pango font metrics. + +XYPOSITION SurfaceImpl::Ascent(Font &font_) { + if (!(font_.GetID())) + return 1; + FontMutexLock(); + int ascent = PFont(font_)->ascent; + if ((ascent == 0) && (PFont(font_)->pfd)) { + PangoFontMetrics *metrics = pango_context_get_metrics(pcontext, + PFont(font_)->pfd, pango_context_get_language(pcontext)); + PFont(font_)->ascent = + doubleFromPangoUnits(pango_font_metrics_get_ascent(metrics)); + pango_font_metrics_unref(metrics); + ascent = PFont(font_)->ascent; + } + if (ascent == 0) { + ascent = 1; + } + FontMutexUnlock(); + return ascent; +} + +XYPOSITION SurfaceImpl::Descent(Font &font_) { + if (!(font_.GetID())) + return 1; + if (PFont(font_)->pfd) { + PangoFontMetrics *metrics = pango_context_get_metrics(pcontext, + PFont(font_)->pfd, pango_context_get_language(pcontext)); + int descent = doubleFromPangoUnits(pango_font_metrics_get_descent(metrics)); + pango_font_metrics_unref(metrics); + return descent; + } + return 0; +} + +XYPOSITION SurfaceImpl::InternalLeading(Font &) { + return 0; +} + +XYPOSITION SurfaceImpl::ExternalLeading(Font &) { + return 0; +} + +XYPOSITION SurfaceImpl::Height(Font &font_) { + return Ascent(font_) + Descent(font_); +} + +XYPOSITION SurfaceImpl::AverageCharWidth(Font &font_) { + return WidthChar(font_, 'n'); +} + +void SurfaceImpl::SetClip(PRectangle rc) { + cairo_rectangle(context, rc.left, rc.top, rc.right, rc.bottom); + cairo_clip(context); +} + +void SurfaceImpl::FlushCachedState() {} + +void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) { + if (unicodeMode_) + et = UTF8; +} + +void SurfaceImpl::SetDBCSMode(int codePage) { + if (codePage && (codePage != SC_CP_UTF8)) + et = dbcs; +} + +Surface *Surface::Allocate(int) { + return new SurfaceImpl(); +} + +Window::~Window() {} + +void Window::Destroy() { + if (wid) + gtk_widget_destroy(GTK_WIDGET(wid)); + wid = 0; +} + +bool Window::HasFocus() { + return IS_WIDGET_FOCUSSED(wid); +} + +PRectangle Window::GetPosition() { + // Before any size allocated pretend its 1000 wide so not scrolled + PRectangle rc(0, 0, 1000, 1000); + if (wid) { + GtkAllocation allocation; +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_get_allocation(PWidget(wid), &allocation); +#else + allocation = PWidget(wid)->allocation; +#endif + rc.left = allocation.x; + rc.top = allocation.y; + if (allocation.width > 20) { + rc.right = rc.left + allocation.width; + rc.bottom = rc.top + allocation.height; + } + } + return rc; +} + +void Window::SetPosition(PRectangle rc) { + GtkAllocation alloc; + alloc.x = rc.left; + alloc.y = rc.top; + alloc.width = rc.Width(); + alloc.height = rc.Height(); + gtk_widget_size_allocate(PWidget(wid), &alloc); +} + +void Window::SetPositionRelative(PRectangle rc, Window relativeTo) { + int ox = 0; + int oy = 0; + gdk_window_get_origin(WindowFromWidget(PWidget(relativeTo.wid)), &ox, &oy); + ox += rc.left; + if (ox < 0) + ox = 0; + oy += rc.top; + if (oy < 0) + oy = 0; + + /* do some corrections to fit into screen */ + int sizex = rc.right - rc.left; + int sizey = rc.bottom - rc.top; + int screenWidth = gdk_screen_width(); + int screenHeight = gdk_screen_height(); + if (sizex > screenWidth) + ox = 0; /* the best we can do */ + else if (ox + sizex > screenWidth) + ox = screenWidth - sizex; + if (oy + sizey > screenHeight) + oy = screenHeight - sizey; + + gtk_window_move(GTK_WINDOW(PWidget(wid)), ox, oy); + + gtk_widget_set_size_request(PWidget(wid), sizex, sizey); +} + +PRectangle Window::GetClientPosition() { + // On GTK+, the client position is the window position + return GetPosition(); +} + +void Window::Show(bool show) { + if (show) + gtk_widget_show(PWidget(wid)); +} + +void Window::InvalidateAll() { + if (wid) { + gtk_widget_queue_draw(PWidget(wid)); + } +} + +void Window::InvalidateRectangle(PRectangle rc) { + if (wid) { + gtk_widget_queue_draw_area(PWidget(wid), + rc.left, rc.top, + rc.right - rc.left, rc.bottom - rc.top); + } +} + +void Window::SetFont(Font &) { + // Can not be done generically but only needed for ListBox +} + +void Window::SetCursor(Cursor curs) { + // We don't set the cursor to same value numerous times under gtk because + // it stores the cursor in the window once it's set + if (curs == cursorLast) + return; + + cursorLast = curs; + GdkCursor *gdkCurs; + switch (curs) { + case cursorText: + gdkCurs = gdk_cursor_new(GDK_XTERM); + break; + case cursorArrow: + gdkCurs = gdk_cursor_new(GDK_LEFT_PTR); + break; + case cursorUp: + gdkCurs = gdk_cursor_new(GDK_CENTER_PTR); + break; + case cursorWait: + gdkCurs = gdk_cursor_new(GDK_WATCH); + break; + case cursorHand: + gdkCurs = gdk_cursor_new(GDK_HAND2); + break; + case cursorReverseArrow: + gdkCurs = gdk_cursor_new(GDK_RIGHT_PTR); + break; + default: + gdkCurs = gdk_cursor_new(GDK_LEFT_PTR); + cursorLast = cursorArrow; + break; + } + + if (WindowFromWidget(PWidget(wid))) + gdk_window_set_cursor(WindowFromWidget(PWidget(wid)), gdkCurs); +#if GTK_CHECK_VERSION(3,0,0) + g_object_unref(gdkCurs); +#else + gdk_cursor_unref(gdkCurs); +#endif +} + +void Window::SetTitle(const char *s) { + gtk_window_set_title(GTK_WINDOW(wid), s); +} + +/* Returns rectangle of monitor pt is on, both rect and pt are in Window's + gdk window coordinates */ +PRectangle Window::GetMonitorRect(Point pt) { + gint x_offset, y_offset; + + gdk_window_get_origin(WindowFromWidget(PWidget(wid)), &x_offset, &y_offset); + + GdkScreen* screen; + gint monitor_num; + GdkRectangle rect; + + screen = gtk_widget_get_screen(PWidget(wid)); + monitor_num = gdk_screen_get_monitor_at_point(screen, pt.x + x_offset, pt.y + y_offset); + gdk_screen_get_monitor_geometry(screen, monitor_num, &rect); + rect.x -= x_offset; + rect.y -= y_offset; + return PRectangle(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height); +} + +typedef std::map ImageMap; + +struct ListImage { + const RGBAImage *rgba_data; + GdkPixbuf *pixbuf; +}; + +static void list_image_free(gpointer, gpointer value, gpointer) { + ListImage *list_image = (ListImage *) value; + if (list_image->pixbuf) + g_object_unref(list_image->pixbuf); + g_free(list_image); +} + +ListBox::ListBox() { +} + +ListBox::~ListBox() { +} + +enum { + PIXBUF_COLUMN, + TEXT_COLUMN, + N_COLUMNS +}; + +class ListBoxX : public ListBox { + WindowID list; + WindowID scroller; + void *pixhash; + GtkCellRenderer* pixbuf_renderer; + RGBAImageSet images; + int desiredVisibleRows; + unsigned int maxItemCharacters; + unsigned int aveCharWidth; +public: + CallBackAction doubleClickAction; + void *doubleClickActionData; + + ListBoxX() : list(0), scroller(0), pixhash(NULL), pixbuf_renderer(0), + desiredVisibleRows(5), maxItemCharacters(0), + aveCharWidth(1), doubleClickAction(NULL), doubleClickActionData(NULL) { + } + virtual ~ListBoxX() { + if (pixhash) { + g_hash_table_foreach((GHashTable *) pixhash, list_image_free, NULL); + g_hash_table_destroy((GHashTable *) pixhash); + } + } + virtual void SetFont(Font &font); + virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_, int technology_); + virtual void SetAverageCharWidth(int width); + virtual void SetVisibleRows(int rows); + virtual int GetVisibleRows() const; + virtual PRectangle GetDesiredRect(); + virtual int CaretFromEdge(); + virtual void Clear(); + virtual void Append(char *s, int type = -1); + virtual int Length(); + virtual void Select(int n); + virtual int GetSelection(); + virtual int Find(const char *prefix); + virtual void GetValue(int n, char *value, int len); + void RegisterRGBA(int type, RGBAImage *image); + virtual void RegisterImage(int type, const char *xpm_data); + virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage); + virtual void ClearRegisteredImages(); + virtual void SetDoubleClickAction(CallBackAction action, void *data) { + doubleClickAction = action; + doubleClickActionData = data; + } + virtual void SetList(const char *listText, char separator, char typesep); +}; + +ListBox *ListBox::Allocate() { + ListBoxX *lb = new ListBoxX(); + return lb; +} + +static gboolean ButtonPress(GtkWidget *, GdkEventButton* ev, gpointer p) { + try { + ListBoxX* lb = reinterpret_cast(p); + if (ev->type == GDK_2BUTTON_PRESS && lb->doubleClickAction != NULL) { + lb->doubleClickAction(lb->doubleClickActionData); + return TRUE; + } + + } catch (...) { + // No pointer back to Scintilla to save status + } + return FALSE; +} + +/* Change the active color to the selected color so the listbox uses the color +scheme that it would use if it had the focus. */ +static void StyleSet(GtkWidget *w, GtkStyle*, void*) { + + g_return_if_fail(w != NULL); + + /* Copy the selected color to active. Note that the modify calls will cause + recursive calls to this function after the value is updated and w->style to + be set to a new object */ + +#if GTK_CHECK_VERSION(3,0,0) + GtkStyleContext *styleContext = gtk_widget_get_style_context(w); + if (styleContext == NULL) + return; + + GdkRGBA colourForeSelected; + gtk_style_context_get_color(styleContext, GTK_STATE_FLAG_SELECTED, &colourForeSelected); + GdkRGBA colourForeActive; + gtk_style_context_get_color(styleContext, GTK_STATE_FLAG_ACTIVE, &colourForeActive); + if (!gdk_rgba_equal(&colourForeSelected, &colourForeActive)) + gtk_widget_override_color(w, GTK_STATE_FLAG_ACTIVE, &colourForeSelected); + + styleContext = gtk_widget_get_style_context(w); + if (styleContext == NULL) + return; + + GdkRGBA colourBaseSelected; + gtk_style_context_get_background_color(styleContext, GTK_STATE_FLAG_SELECTED, &colourBaseSelected); + GdkRGBA colourBaseActive; + gtk_style_context_get_background_color(styleContext, GTK_STATE_FLAG_ACTIVE, &colourBaseActive); + if (!gdk_rgba_equal(&colourBaseSelected, &colourBaseActive)) + gtk_widget_override_background_color(w, GTK_STATE_FLAG_ACTIVE, &colourBaseSelected); +#else + GtkStyle *style = gtk_widget_get_style(w); + if (style == NULL) + return; + if (!gdk_color_equal(&style->base[GTK_STATE_SELECTED], &style->base[GTK_STATE_ACTIVE])) + gtk_widget_modify_base(w, GTK_STATE_ACTIVE, &style->base[GTK_STATE_SELECTED]); + style = gtk_widget_get_style(w); + if (style == NULL) + return; + if (!gdk_color_equal(&style->text[GTK_STATE_SELECTED], &style->text[GTK_STATE_ACTIVE])) + gtk_widget_modify_text(w, GTK_STATE_ACTIVE, &style->text[GTK_STATE_SELECTED]); +#endif +} + +void ListBoxX::Create(Window &, int, Point, int, bool, int) { + wid = gtk_window_new(GTK_WINDOW_POPUP); + + GtkWidget *frame = gtk_frame_new(NULL); + gtk_widget_show(frame); + gtk_container_add(GTK_CONTAINER(GetID()), frame); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); + gtk_container_set_border_width(GTK_CONTAINER(frame), 0); + + scroller = gtk_scrolled_window_new(NULL, NULL); + gtk_container_set_border_width(GTK_CONTAINER(scroller), 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroller), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + gtk_container_add(GTK_CONTAINER(frame), PWidget(scroller)); + gtk_widget_show(PWidget(scroller)); + + /* Tree and its model */ + GtkListStore *store = + gtk_list_store_new(N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING); + + list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); + g_signal_connect(G_OBJECT(list), "style-set", G_CALLBACK(StyleSet), NULL); + + GtkTreeSelection *selection = + gtk_tree_view_get_selection(GTK_TREE_VIEW(list)); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE); + gtk_tree_view_set_reorderable(GTK_TREE_VIEW(list), FALSE); + + /* Columns */ + GtkTreeViewColumn *column = gtk_tree_view_column_new(); + gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); + gtk_tree_view_column_set_title(column, "Autocomplete"); + + pixbuf_renderer = gtk_cell_renderer_pixbuf_new(); + gtk_cell_renderer_set_fixed_size(pixbuf_renderer, 0, -1); + gtk_tree_view_column_pack_start(column, pixbuf_renderer, FALSE); + gtk_tree_view_column_add_attribute(column, pixbuf_renderer, + "pixbuf", PIXBUF_COLUMN); + + GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); + gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT(renderer), 1); + gtk_tree_view_column_pack_start(column, renderer, TRUE); + gtk_tree_view_column_add_attribute(column, renderer, + "text", TEXT_COLUMN); + + gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); + if (g_object_class_find_property(G_OBJECT_GET_CLASS(list), "fixed-height-mode")) + g_object_set(G_OBJECT(list), "fixed-height-mode", TRUE, NULL); + + GtkWidget *wid = PWidget(list); // No code inside the G_OBJECT macro + gtk_container_add(GTK_CONTAINER(PWidget(scroller)), wid); + gtk_widget_show(wid); + g_signal_connect(G_OBJECT(wid), "button_press_event", + G_CALLBACK(ButtonPress), this); + gtk_widget_realize(PWidget(wid)); +} + +void ListBoxX::SetFont(Font &scint_font) { + // Only do for Pango font as there have been crashes for GDK fonts + if (Created() && PFont(scint_font)->pfd) { + // Current font is Pango font +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_override_font(PWidget(list), PFont(scint_font)->pfd); +#else + gtk_widget_modify_font(PWidget(list), PFont(scint_font)->pfd); +#endif + } +} + +void ListBoxX::SetAverageCharWidth(int width) { + aveCharWidth = width; +} + +void ListBoxX::SetVisibleRows(int rows) { + desiredVisibleRows = rows; +} + +int ListBoxX::GetVisibleRows() const { + return desiredVisibleRows; +} + +PRectangle ListBoxX::GetDesiredRect() { + // Before any size allocated pretend its 100 wide so not scrolled + PRectangle rc(0, 0, 100, 100); + if (wid) { + int rows = Length(); + if ((rows == 0) || (rows > desiredVisibleRows)) + rows = desiredVisibleRows; + + GtkRequisition req; + int height; + + // First calculate height of the clist for our desired visible + // row count otherwise it tries to expand to the total # of rows + // Get cell height + int row_width=0; + int row_height=0; + GtkTreeViewColumn * column = + gtk_tree_view_get_column(GTK_TREE_VIEW(list), 0); + gtk_tree_view_column_cell_get_size(column, NULL, + NULL, NULL, &row_width, &row_height); +#if GTK_CHECK_VERSION(3,0,0) + GtkStyleContext *styleContextList = gtk_widget_get_style_context(PWidget(list)); + GtkBorder padding; + gtk_style_context_get_padding(styleContextList, GTK_STATE_FLAG_NORMAL, &padding); + height = (rows * row_height + + padding.top + padding.bottom + + 2 * (gtk_container_get_border_width(GTK_CONTAINER(PWidget(list))) + 1)); +#else + int ythickness = PWidget(list)->style->ythickness; + height = (rows * row_height + + 2 * (ythickness + + GTK_CONTAINER(PWidget(list))->border_width + 1)); +#endif + gtk_widget_set_size_request(GTK_WIDGET(PWidget(list)), -1, height); + + // Get the size of the scroller because we set usize on the window +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_get_preferred_size(GTK_WIDGET(scroller), NULL, &req); +#else + gtk_widget_size_request(GTK_WIDGET(scroller), &req); +#endif + rc.right = req.width; + rc.bottom = req.height; + + gtk_widget_set_size_request(GTK_WIDGET(list), -1, -1); + int width = maxItemCharacters; + if (width < 12) + width = 12; + rc.right = width * (aveCharWidth + aveCharWidth / 3); + if (Length() > rows) + rc.right = rc.right + 16; + } + return rc; +} + +int ListBoxX::CaretFromEdge() { + gint renderer_width, renderer_height; + gtk_cell_renderer_get_fixed_size(pixbuf_renderer, &renderer_width, + &renderer_height); + return 4 + renderer_width; +} + +void ListBoxX::Clear() { + GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list)); + gtk_list_store_clear(GTK_LIST_STORE(model)); + maxItemCharacters = 0; +} + +static void init_pixmap(ListImage *list_image) { + if (list_image->rgba_data) { + // Drop any existing pixmap/bitmap as data may have changed + if (list_image->pixbuf) + g_object_unref(list_image->pixbuf); + list_image->pixbuf = + gdk_pixbuf_new_from_data(list_image->rgba_data->Pixels(), + GDK_COLORSPACE_RGB, + TRUE, + 8, + list_image->rgba_data->GetWidth(), + list_image->rgba_data->GetHeight(), + list_image->rgba_data->GetWidth() * 4, + NULL, + NULL); + } +} + +#define SPACING 5 + +void ListBoxX::Append(char *s, int type) { + ListImage *list_image = NULL; + if ((type >= 0) && pixhash) { + list_image = (ListImage *) g_hash_table_lookup((GHashTable *) pixhash + , (gconstpointer) GINT_TO_POINTER(type)); + } + GtkTreeIter iter; + GtkListStore *store = + GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list))); + gtk_list_store_append(GTK_LIST_STORE(store), &iter); + if (list_image) { + if (NULL == list_image->pixbuf) + init_pixmap(list_image); + if (list_image->pixbuf) { + gtk_list_store_set(GTK_LIST_STORE(store), &iter, + PIXBUF_COLUMN, list_image->pixbuf, + TEXT_COLUMN, s, -1); + + gint pixbuf_width = gdk_pixbuf_get_width(list_image->pixbuf); + gint renderer_height, renderer_width; + gtk_cell_renderer_get_fixed_size(pixbuf_renderer, + &renderer_width, &renderer_height); + if (pixbuf_width > renderer_width) + gtk_cell_renderer_set_fixed_size(pixbuf_renderer, + pixbuf_width, -1); + } else { + gtk_list_store_set(GTK_LIST_STORE(store), &iter, + TEXT_COLUMN, s, -1); + } + } else { + gtk_list_store_set(GTK_LIST_STORE(store), &iter, + TEXT_COLUMN, s, -1); + } + size_t len = strlen(s); + if (maxItemCharacters < len) + maxItemCharacters = len; +} + +int ListBoxX::Length() { + if (wid) + return gtk_tree_model_iter_n_children(gtk_tree_view_get_model + (GTK_TREE_VIEW(list)), NULL); + return 0; +} + +void ListBoxX::Select(int n) { + GtkTreeIter iter; + GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list)); + GtkTreeSelection *selection = + gtk_tree_view_get_selection(GTK_TREE_VIEW(list)); + + if (n < 0) { + gtk_tree_selection_unselect_all(selection); + return; + } + + bool valid = gtk_tree_model_iter_nth_child(model, &iter, NULL, n) != FALSE; + if (valid) { + gtk_tree_selection_select_iter(selection, &iter); + + // Move the scrollbar to show the selection. + int total = Length(); +#if GTK_CHECK_VERSION(3,0,0) + GtkAdjustment *adj = + gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(list)); + gfloat value = ((gfloat)n / total) * (gtk_adjustment_get_upper(adj) - gtk_adjustment_get_lower(adj)) + + gtk_adjustment_get_lower(adj) - gtk_adjustment_get_page_size(adj) / 2; +#else + GtkAdjustment *adj = + gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(list)); + gfloat value = ((gfloat)n / total) * (adj->upper - adj->lower) + + adj->lower - adj->page_size / 2; +#endif + // Get cell height + int row_width; + int row_height; + GtkTreeViewColumn * column = + gtk_tree_view_get_column(GTK_TREE_VIEW(list), 0); + gtk_tree_view_column_cell_get_size(column, NULL, NULL, + NULL, &row_width, &row_height); + + int rows = Length(); + if ((rows == 0) || (rows > desiredVisibleRows)) + rows = desiredVisibleRows; + if (rows & 0x1) { + // Odd rows to display -- We are now in the middle. + // Align it so that we don't chop off rows. + value += (gfloat)row_height / 2.0; + } + // Clamp it. + value = (value < 0)? 0 : value; +#if GTK_CHECK_VERSION(3,0,0) + value = (value > (gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj)))? + (gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj)) : value; +#else + value = (value > (adj->upper - adj->page_size))? + (adj->upper - adj->page_size) : value; +#endif + + // Set it. + gtk_adjustment_set_value(adj, value); + } else { + gtk_tree_selection_unselect_all(selection); + } +} + +int ListBoxX::GetSelection() { + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreeSelection *selection; + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list)); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) { + GtkTreePath *path = gtk_tree_model_get_path(model, &iter); + int *indices = gtk_tree_path_get_indices(path); + // Don't free indices. + if (indices) + return indices[0]; + } + return -1; +} + +int ListBoxX::Find(const char *prefix) { + GtkTreeIter iter; + GtkTreeModel *model = + gtk_tree_view_get_model(GTK_TREE_VIEW(list)); + bool valid = gtk_tree_model_get_iter_first(model, &iter) != FALSE; + int i = 0; + while(valid) { + gchar *s; + gtk_tree_model_get(model, &iter, TEXT_COLUMN, &s, -1); + if (s && (0 == strncmp(prefix, s, strlen(prefix)))) { + g_free(s); + return i; + } + g_free(s); + valid = gtk_tree_model_iter_next(model, &iter) != FALSE; + i++; + } + return -1; +} + +void ListBoxX::GetValue(int n, char *value, int len) { + char *text = NULL; + GtkTreeIter iter; + GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list)); + bool valid = gtk_tree_model_iter_nth_child(model, &iter, NULL, n) != FALSE; + if (valid) { + gtk_tree_model_get(model, &iter, TEXT_COLUMN, &text, -1); + } + if (text && len > 0) { + strncpy(value, text, len); + value[len - 1] = '\0'; + } else { + value[0] = '\0'; + } + g_free(text); +} + +// g_return_if_fail causes unnecessary compiler warning in release compile. +#ifdef _MSC_VER +#pragma warning(disable: 4127) +#endif + +void ListBoxX::RegisterRGBA(int type, RGBAImage *image) { + images.Add(type, image); + + if (!pixhash) { + pixhash = g_hash_table_new(g_direct_hash, g_direct_equal); + } + ListImage *list_image = (ListImage *) g_hash_table_lookup((GHashTable *) pixhash, + (gconstpointer) GINT_TO_POINTER(type)); + if (list_image) { + // Drop icon already registered + if (list_image->pixbuf) + g_object_unref(list_image->pixbuf); + list_image->pixbuf = NULL; + list_image->rgba_data = image; + } else { + list_image = g_new0(ListImage, 1); + list_image->rgba_data = image; + g_hash_table_insert((GHashTable *) pixhash, GINT_TO_POINTER(type), + (gpointer) list_image); + } +} + +void ListBoxX::RegisterImage(int type, const char *xpm_data) { + g_return_if_fail(xpm_data); + XPM xpmImage(xpm_data); + RegisterRGBA(type, new RGBAImage(xpmImage)); +} + +void ListBoxX::RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) { + RegisterRGBA(type, new RGBAImage(width, height, pixelsImage)); +} + +void ListBoxX::ClearRegisteredImages() { + images.Clear(); +} + +void ListBoxX::SetList(const char *listText, char separator, char typesep) { + Clear(); + int count = strlen(listText) + 1; + char *words = new char[count]; + if (words) { + memcpy(words, listText, count); + char *startword = words; + char *numword = NULL; + int i = 0; + for (; words[i]; i++) { + if (words[i] == separator) { + words[i] = '\0'; + if (numword) + *numword = '\0'; + Append(startword, numword?atoi(numword + 1):-1); + startword = words + i + 1; + numword = NULL; + } else if (words[i] == typesep) { + numword = words + i; + } + } + if (startword) { + if (numword) + *numword = '\0'; + Append(startword, numword?atoi(numword + 1):-1); + } + delete []words; + } +} + +Menu::Menu() : mid(0) {} + +void Menu::CreatePopUp() { + Destroy(); + mid = gtk_menu_new(); +#if GLIB_CHECK_VERSION(2,10,0) + g_object_ref_sink(G_OBJECT(mid)); +#else + g_object_ref(G_OBJECT(mid)); + gtk_object_sink(GTK_OBJECT(G_OBJECT(mid))); +#endif +} + +void Menu::Destroy() { + if (mid) + g_object_unref(G_OBJECT(mid)); + mid = 0; +} + +static void MenuPositionFunc(GtkMenu *, gint *x, gint *y, gboolean *, gpointer userData) { + sptr_t intFromPointer = reinterpret_cast(userData); + *x = intFromPointer & 0xffff; + *y = intFromPointer >> 16; +} + +void Menu::Show(Point pt, Window &) { + int screenHeight = gdk_screen_height(); + int screenWidth = gdk_screen_width(); + GtkMenu *widget = reinterpret_cast(mid); + gtk_widget_show_all(GTK_WIDGET(widget)); + GtkRequisition requisition; +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_get_preferred_size(GTK_WIDGET(widget), NULL, &requisition); +#else + gtk_widget_size_request(GTK_WIDGET(widget), &requisition); +#endif + if ((pt.x + requisition.width) > screenWidth) { + pt.x = screenWidth - requisition.width; + } + if ((pt.y + requisition.height) > screenHeight) { + pt.y = screenHeight - requisition.height; + } + gtk_menu_popup(widget, NULL, NULL, MenuPositionFunc, + reinterpret_cast((static_cast(pt.y) << 16) | static_cast(pt.x)), 0, + gtk_get_current_event_time()); +} + +ElapsedTime::ElapsedTime() { + GTimeVal curTime; + g_get_current_time(&curTime); + bigBit = curTime.tv_sec; + littleBit = curTime.tv_usec; +} + +class DynamicLibraryImpl : public DynamicLibrary { +protected: + GModule* m; +public: + DynamicLibraryImpl(const char *modulePath) { + m = g_module_open(modulePath, G_MODULE_BIND_LAZY); + } + + virtual ~DynamicLibraryImpl() { + if (m != NULL) + g_module_close(m); + } + + // Use g_module_symbol to get a pointer to the relevant function. + virtual Function FindFunction(const char *name) { + if (m != NULL) { + gpointer fn_address = NULL; + gboolean status = g_module_symbol(m, name, &fn_address); + if (status) + return static_cast(fn_address); + else + return NULL; + } else + return NULL; + } + + virtual bool IsValid() { + return m != NULL; + } +}; + +DynamicLibrary *DynamicLibrary::Load(const char *modulePath) { + return static_cast( new DynamicLibraryImpl(modulePath) ); +} + +double ElapsedTime::Duration(bool reset) { + GTimeVal curTime; + g_get_current_time(&curTime); + long endBigBit = curTime.tv_sec; + long endLittleBit = curTime.tv_usec; + double result = 1000000.0 * (endBigBit - bigBit); + result += endLittleBit - littleBit; + result /= 1000000.0; + if (reset) { + bigBit = endBigBit; + littleBit = endLittleBit; + } + return result; +} + +ColourDesired Platform::Chrome() { + return ColourDesired(0xe0, 0xe0, 0xe0); +} + +ColourDesired Platform::ChromeHighlight() { + return ColourDesired(0xff, 0xff, 0xff); +} + +const char *Platform::DefaultFont() { +#ifdef G_OS_WIN32 + return "Lucida Console"; +#else + return "!Sans"; +#endif +} + +int Platform::DefaultFontSize() { +#ifdef G_OS_WIN32 + return 10; +#else + return 12; +#endif +} + +unsigned int Platform::DoubleClickTime() { + return 500; // Half a second +} + +bool Platform::MouseButtonBounce() { + return true; +} + +void Platform::DebugDisplay(const char *s) { + fprintf(stderr, "%s", s); +} + +bool Platform::IsKeyDown(int) { + // TODO: discover state of keys in GTK+/X + return false; +} + +long Platform::SendScintilla( + WindowID w, unsigned int msg, unsigned long wParam, long lParam) { + return scintilla_send_message(SCINTILLA(w), msg, wParam, lParam); +} + +long Platform::SendScintillaPointer( + WindowID w, unsigned int msg, unsigned long wParam, void *lParam) { + return scintilla_send_message(SCINTILLA(w), msg, wParam, + reinterpret_cast(lParam)); +} + +bool Platform::IsDBCSLeadByte(int codePage, char ch) { + // Byte ranges found in Wikipedia articles with relevant search strings in each case + unsigned char uch = static_cast(ch); + switch (codePage) { + case 932: + // Shift_jis + return ((uch >= 0x81) && (uch <= 0x9F)) || + ((uch >= 0xE0) && (uch <= 0xFC)); + // Lead bytes F0 to FC may be a Microsoft addition. + case 936: + // GBK + return (uch >= 0x81) && (uch <= 0xFE); + case 950: + // Big5 + return (uch >= 0x81) && (uch <= 0xFE); + // Korean EUC-KR may be code page 949. + } + return false; +} + +int Platform::DBCSCharLength(int codePage, const char *s) { + if (codePage == 932 || codePage == 936 || codePage == 950) { + return IsDBCSLeadByte(codePage, s[0]) ? 2 : 1; + } else { + int bytes = mblen(s, MB_CUR_MAX); + if (bytes >= 1) + return bytes; + else + return 1; + } +} + +int Platform::DBCSCharMaxLength() { + return MB_CUR_MAX; + //return 2; +} + +// These are utility functions not really tied to a platform + +int Platform::Minimum(int a, int b) { + if (a < b) + return a; + else + return b; +} + +int Platform::Maximum(int a, int b) { + if (a > b) + return a; + else + return b; +} + +//#define TRACE + +#ifdef TRACE +void Platform::DebugPrintf(const char *format, ...) { + char buffer[2000]; + va_list pArguments; + va_start(pArguments, format); + vsprintf(buffer, format, pArguments); + va_end(pArguments); + Platform::DebugDisplay(buffer); +} +#else +void Platform::DebugPrintf(const char *, ...) {} + +#endif + +// Not supported for GTK+ +static bool assertionPopUps = true; + +bool Platform::ShowAssertionPopUps(bool assertionPopUps_) { + bool ret = assertionPopUps; + assertionPopUps = assertionPopUps_; + return ret; +} + +void Platform::Assert(const char *c, const char *file, int line) { + char buffer[2000]; + sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line); + strcat(buffer, "\r\n"); + Platform::DebugDisplay(buffer); + abort(); +} + +int Platform::Clamp(int val, int minVal, int maxVal) { + if (val > maxVal) + val = maxVal; + if (val < minVal) + val = minVal; + return val; +} + +void Platform_Initialise() { + FontMutexAllocate(); +} + +void Platform_Finalise() { + FontMutexFree(); +} diff --git a/scintilla/gtk/ScintillaGTK.cxx b/ThirdLibs/scintilla/gtk/ScintillaGTK.cxx similarity index 96% rename from scintilla/gtk/ScintillaGTK.cxx rename to ThirdLibs/scintilla/gtk/ScintillaGTK.cxx index 82abe953..b7d3fd22 100644 --- a/scintilla/gtk/ScintillaGTK.cxx +++ b/ThirdLibs/scintilla/gtk/ScintillaGTK.cxx @@ -1,2994 +1,2994 @@ -// Scintilla source code edit control -// ScintillaGTK.cxx - GTK+ specific subclass of ScintillaBase -// Copyright 1998-2004 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include "Platform.h" - -#if PLAT_GTK_WIN32 -#include -#endif - -#include "ILexer.h" -#include "Scintilla.h" -#include "ScintillaWidget.h" -#ifdef SCI_LEXER -#include "SciLexer.h" -#endif -#include "SVector.h" -#include "SplitVector.h" -#include "Partitioning.h" -#include "RunStyles.h" -#include "ContractionState.h" -#include "CellBuffer.h" -#include "CallTip.h" -#include "KeyMap.h" -#include "Indicator.h" -#include "XPM.h" -#include "LineMarker.h" -#include "Style.h" -#include "AutoComplete.h" -#include "ViewStyle.h" -#include "Decoration.h" -#include "CharClassify.h" -#include "Document.h" -#include "Selection.h" -#include "PositionCache.h" -#include "Editor.h" -#include "ScintillaBase.h" -#include "UniConversion.h" - -#include "scintilla-marshal.h" - -#ifdef SCI_LEXER -#include -#include -#include "LexerModule.h" -#include "ExternalLexer.h" -#endif - -#include "Converter.h" - -#if GTK_CHECK_VERSION(2,20,0) -#define IS_WIDGET_REALIZED(w) (gtk_widget_get_realized(GTK_WIDGET(w))) -#define IS_WIDGET_MAPPED(w) (gtk_widget_get_mapped(GTK_WIDGET(w))) -#define IS_WIDGET_VISIBLE(w) (gtk_widget_get_visible(GTK_WIDGET(w))) -#else -#define IS_WIDGET_REALIZED(w) (GTK_WIDGET_REALIZED(w)) -#define IS_WIDGET_MAPPED(w) (GTK_WIDGET_MAPPED(w)) -#define IS_WIDGET_VISIBLE(w) (GTK_WIDGET_VISIBLE(w)) -#endif - -static GdkWindow *WindowFromWidget(GtkWidget *w) { -#if GTK_CHECK_VERSION(3,0,0) - return gtk_widget_get_window(w); -#else - return w->window; -#endif -} - -static GdkWindow *PWindow(const Window &w) { - GtkWidget *widget = reinterpret_cast(w.GetID()); -#if GTK_CHECK_VERSION(3,0,0) - return gtk_widget_get_window(widget); -#else - return widget->window; -#endif -} - -#ifdef _MSC_VER -// Constant conditional expressions are because of GTK+ headers -#pragma warning(disable: 4127) -// Ignore unreferenced local functions in GTK+ headers -#pragma warning(disable: 4505) -#endif - -#define OBJECT_CLASS GObjectClass - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -extern char *UTF8FromLatin1(const char *s, int &len); - -class ScintillaGTK : public ScintillaBase { - _ScintillaObject *sci; - Window wText; - Window scrollbarv; - Window scrollbarh; - GtkAdjustment *adjustmentv; - GtkAdjustment *adjustmenth; - int scrollBarWidth; - int scrollBarHeight; - - SelectionText primary; - - GdkEventButton evbtn; - bool capturedMouse; - bool dragWasDropped; - int lastKey; - int rectangularSelectionModifier; - - GtkWidgetClass *parentClass; - - static GdkAtom atomClipboard; - static GdkAtom atomUTF8; - static GdkAtom atomString; - static GdkAtom atomUriList; - static GdkAtom atomDROPFILES_DND; - GdkAtom atomSought; - -#if PLAT_GTK_WIN32 - CLIPFORMAT cfColumnSelect; -#endif - - Window wPreedit; - Window wPreeditDraw; - GtkIMContext *im_context; - - // Wheel mouse support - unsigned int linesPerScroll; - GTimeVal lastWheelMouseTime; - gint lastWheelMouseDirection; - gint wheelMouseIntensity; - -#if GTK_CHECK_VERSION(3,0,0) - cairo_rectangle_list_t *rgnUpdate; -#else - GdkRegion *rgnUpdate; -#endif - - // Private so ScintillaGTK objects can not be copied - ScintillaGTK(const ScintillaGTK &); - ScintillaGTK &operator=(const ScintillaGTK &); - -public: - ScintillaGTK(_ScintillaObject *sci_); - virtual ~ScintillaGTK(); - static void ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class); -private: - virtual void Initialise(); - virtual void Finalise(); - virtual void DisplayCursor(Window::Cursor c); - virtual bool DragThreshold(Point ptStart, Point ptNow); - virtual void StartDrag(); - int TargetAsUTF8(char *text); - int EncodedFromUTF8(char *utf8, char *encoded); - virtual bool ValidCodePage(int codePage) const; -public: // Public for scintilla_send_message - virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); -private: - virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); - virtual void SetTicking(bool on); - virtual bool SetIdle(bool on); - virtual void SetMouseCapture(bool on); - virtual bool HaveMouseCapture(); - virtual bool PaintContains(PRectangle rc); - void FullPaint(); - virtual PRectangle GetClientRectangle(); - void SyncPaint(PRectangle rc); - virtual void ScrollText(int linesToMove); - virtual void SetVerticalScrollPos(); - virtual void SetHorizontalScrollPos(); - virtual bool ModifyScrollBars(int nMax, int nPage); - void ReconfigureScrollBars(); - virtual void NotifyChange(); - virtual void NotifyFocus(bool focus); - virtual void NotifyParent(SCNotification scn); - void NotifyKey(int key, int modifiers); - void NotifyURIDropped(const char *list); - const char *CharacterSetID() const; - virtual CaseFolder *CaseFolderForEncoding(); - virtual std::string CaseMapString(const std::string &s, int caseMapping); - virtual int KeyDefault(int key, int modifiers); - virtual void CopyToClipboard(const SelectionText &selectedText); - virtual void Copy(); - virtual void Paste(); - virtual void CreateCallTipWindow(PRectangle rc); - virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true); - bool OwnPrimarySelection(); - virtual void ClaimSelection(); - void GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText); - void ReceivedSelection(GtkSelectionData *selection_data); - void ReceivedDrop(GtkSelectionData *selection_data); - static void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected); - void StoreOnClipboard(SelectionText *clipText); - static void ClipboardGetSelection(GtkClipboard* clip, GtkSelectionData *selection_data, guint info, void *data); - static void ClipboardClearSelection(GtkClipboard* clip, void *data); - - void UnclaimSelection(GdkEventSelection *selection_event); - void Resize(int width, int height); - - // Callback functions - void RealizeThis(GtkWidget *widget); - static void Realize(GtkWidget *widget); - void UnRealizeThis(GtkWidget *widget); - static void UnRealize(GtkWidget *widget); - void MapThis(); - static void Map(GtkWidget *widget); - void UnMapThis(); - static void UnMap(GtkWidget *widget); - gint FocusInThis(GtkWidget *widget); - static gint FocusIn(GtkWidget *widget, GdkEventFocus *event); - gint FocusOutThis(GtkWidget *widget); - static gint FocusOut(GtkWidget *widget, GdkEventFocus *event); - static void SizeRequest(GtkWidget *widget, GtkRequisition *requisition); - static void GetPreferredWidth(GtkWidget *widget, gint *minimalWidth, gint *naturalWidth); - static void GetPreferredHeight(GtkWidget *widget, gint *minimalHeight, gint *naturalHeight); - static void SizeAllocate(GtkWidget *widget, GtkAllocation *allocation); -#if GTK_CHECK_VERSION(3,0,0) - gboolean DrawTextThis(cairo_t *cr); - static gboolean DrawText(GtkWidget *widget, cairo_t *cr, ScintillaGTK *sciThis); - gboolean DrawThis(cairo_t *cr); - static gboolean DrawMain(GtkWidget *widget, cairo_t *cr); -#else - gboolean ExposeTextThis(GtkWidget *widget, GdkEventExpose *ose); - static gboolean ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis); - gboolean Expose(GtkWidget *widget, GdkEventExpose *ose); - static gboolean ExposeMain(GtkWidget *widget, GdkEventExpose *ose); -#endif - static void Draw(GtkWidget *widget, GdkRectangle *area); - void ForAll(GtkCallback callback, gpointer callback_data); - static void MainForAll(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); - - static void ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis); - static void ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis); - gint PressThis(GdkEventButton *event); - static gint Press(GtkWidget *widget, GdkEventButton *event); - static gint MouseRelease(GtkWidget *widget, GdkEventButton *event); - static gint ScrollEvent(GtkWidget *widget, GdkEventScroll *event); - static gint Motion(GtkWidget *widget, GdkEventMotion *event); - gboolean KeyThis(GdkEventKey *event); - static gboolean KeyPress(GtkWidget *widget, GdkEventKey *event); - static gboolean KeyRelease(GtkWidget *widget, GdkEventKey *event); -#if GTK_CHECK_VERSION(3,0,0) - gboolean DrawPreeditThis(GtkWidget *widget, cairo_t *cr); - static gboolean DrawPreedit(GtkWidget *widget, cairo_t *cr, ScintillaGTK *sciThis); -#else - gboolean ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose); - static gboolean ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis); -#endif - void CommitThis(char *str); - static void Commit(GtkIMContext *context, char *str, ScintillaGTK *sciThis); - void PreeditChangedThis(); - static void PreeditChanged(GtkIMContext *context, ScintillaGTK *sciThis); - static void StyleSetText(GtkWidget *widget, GtkStyle *previous, void*); - static void RealizeText(GtkWidget *widget, void*); - static void Destroy(GObject *object); - static void SelectionReceived(GtkWidget *widget, GtkSelectionData *selection_data, - guint time); - static void SelectionGet(GtkWidget *widget, GtkSelectionData *selection_data, - guint info, guint time); - static gint SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event); - static void DragBegin(GtkWidget *widget, GdkDragContext *context); - gboolean DragMotionThis(GdkDragContext *context, gint x, gint y, guint dragtime); - static gboolean DragMotion(GtkWidget *widget, GdkDragContext *context, - gint x, gint y, guint dragtime); - static void DragLeave(GtkWidget *widget, GdkDragContext *context, - guint time); - static void DragEnd(GtkWidget *widget, GdkDragContext *context); - static gboolean Drop(GtkWidget *widget, GdkDragContext *context, - gint x, gint y, guint time); - static void DragDataReceived(GtkWidget *widget, GdkDragContext *context, - gint x, gint y, GtkSelectionData *selection_data, guint info, guint time); - static void DragDataGet(GtkWidget *widget, GdkDragContext *context, - GtkSelectionData *selection_data, guint info, guint time); - static gboolean TimeOut(ScintillaGTK *sciThis); - static gboolean IdleCallback(ScintillaGTK *sciThis); - static gboolean StyleIdle(ScintillaGTK *sciThis); - virtual void QueueStyling(int upTo); - static void PopUpCB(GtkMenuItem *menuItem, ScintillaGTK *sciThis); - -#if GTK_CHECK_VERSION(3,0,0) - static gboolean DrawCT(GtkWidget *widget, cairo_t *cr, CallTip *ctip); -#else - static gboolean ExposeCT(GtkWidget *widget, GdkEventExpose *ose, CallTip *ct); -#endif - static gboolean PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis); - - static sptr_t DirectFunction(ScintillaGTK *sciThis, - unsigned int iMessage, uptr_t wParam, sptr_t lParam); -}; - -enum { - COMMAND_SIGNAL, - NOTIFY_SIGNAL, - LAST_SIGNAL -}; - -static gint scintilla_signals[LAST_SIGNAL] = { 0 }; - -enum { - TARGET_STRING, - TARGET_TEXT, - TARGET_COMPOUND_TEXT, - TARGET_UTF8_STRING, - TARGET_URI -}; - -GdkAtom ScintillaGTK::atomClipboard = 0; -GdkAtom ScintillaGTK::atomUTF8 = 0; -GdkAtom ScintillaGTK::atomString = 0; -GdkAtom ScintillaGTK::atomUriList = 0; -GdkAtom ScintillaGTK::atomDROPFILES_DND = 0; - -static const GtkTargetEntry clipboardCopyTargets[] = { - { (gchar *) "UTF8_STRING", 0, TARGET_UTF8_STRING }, - { (gchar *) "STRING", 0, TARGET_STRING }, -}; -static const gint nClipboardCopyTargets = sizeof(clipboardCopyTargets) / sizeof(clipboardCopyTargets[0]); - -static const GtkTargetEntry clipboardPasteTargets[] = { - { (gchar *) "text/uri-list", 0, TARGET_URI }, - { (gchar *) "UTF8_STRING", 0, TARGET_UTF8_STRING }, - { (gchar *) "STRING", 0, TARGET_STRING }, -}; -static const gint nClipboardPasteTargets = sizeof(clipboardPasteTargets) / sizeof(clipboardPasteTargets[0]); - -static GtkWidget *PWidget(Window &w) { - return reinterpret_cast(w.GetID()); -} - -static ScintillaGTK *ScintillaFromWidget(GtkWidget *widget) { - ScintillaObject *scio = reinterpret_cast(widget); - return reinterpret_cast(scio->pscin); -} - -ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) : - adjustmentv(0), adjustmenth(0), - scrollBarWidth(30), scrollBarHeight(30), - capturedMouse(false), dragWasDropped(false), - lastKey(0), rectangularSelectionModifier(SCMOD_CTRL), parentClass(0), - im_context(NULL), - lastWheelMouseDirection(0), - wheelMouseIntensity(0), - rgnUpdate(0) { - sci = sci_; - wMain = GTK_WIDGET(sci); - -#if PLAT_GTK_WIN32 - rectangularSelectionModifier = SCMOD_ALT; -#else - rectangularSelectionModifier = SCMOD_CTRL; -#endif - -#if PLAT_GTK_WIN32 - // There does not seem to be a real standard for indicating that the clipboard - // contains a rectangular selection, so copy Developer Studio. - cfColumnSelect = static_cast( - ::RegisterClipboardFormat("MSDEVColumnSelect")); - - // Get intellimouse parameters when running on win32; otherwise use - // reasonable default -#ifndef SPI_GETWHEELSCROLLLINES -#define SPI_GETWHEELSCROLLLINES 104 -#endif - ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0); -#else - linesPerScroll = 4; -#endif - lastWheelMouseTime.tv_sec = 0; - lastWheelMouseTime.tv_usec = 0; - - Initialise(); -} - -ScintillaGTK::~ScintillaGTK() { - g_idle_remove_by_data(this); -} - -static void UnRefCursor(GdkCursor *cursor) { -#if GTK_CHECK_VERSION(3,0,0) - g_object_unref(cursor); -#else - gdk_cursor_unref(cursor); -#endif -} - -void ScintillaGTK::RealizeThis(GtkWidget *widget) { - //Platform::DebugPrintf("ScintillaGTK::realize this\n"); -#if GTK_CHECK_VERSION(2,20,0) - gtk_widget_set_realized(widget, TRUE); -#else - GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); -#endif - GdkWindowAttr attrs; - attrs.window_type = GDK_WINDOW_CHILD; - GtkAllocation allocation; -#if GTK_CHECK_VERSION(3,0,0) - gtk_widget_get_allocation(widget, &allocation); -#else - allocation = widget->allocation; -#endif - attrs.x = allocation.x; - attrs.y = allocation.y; - attrs.width = allocation.width; - attrs.height = allocation.height; - attrs.wclass = GDK_INPUT_OUTPUT; - attrs.visual = gtk_widget_get_visual(widget); -#if !GTK_CHECK_VERSION(3,0,0) - attrs.colormap = gtk_widget_get_colormap(widget); -#endif - attrs.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK; - GdkCursor *cursor = gdk_cursor_new(GDK_XTERM); - attrs.cursor = cursor; -#if GTK_CHECK_VERSION(3,0,0) - gtk_widget_set_window(widget, gdk_window_new(gtk_widget_get_parent_window(widget), &attrs, - GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_CURSOR)); - gdk_window_set_user_data(gtk_widget_get_window(widget), widget); - GtkStyleContext *styleContext = gtk_widget_get_style_context(widget); - if (styleContext) { - GdkRGBA colourBackWidget; - gtk_style_context_get_background_color(styleContext, GTK_STATE_FLAG_NORMAL, &colourBackWidget); - gdk_window_set_background_rgba(gtk_widget_get_window(widget), &colourBackWidget); - } - gdk_window_show(gtk_widget_get_window(widget)); - UnRefCursor(cursor); -#else - widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), &attrs, - GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_CURSOR); - gdk_window_set_user_data(widget->window, widget); - widget->style = gtk_style_attach(widget->style, widget->window); - gdk_window_set_background(widget->window, &widget->style->bg[GTK_STATE_NORMAL]); - gdk_window_show(widget->window); - UnRefCursor(cursor); -#endif - wPreedit = gtk_window_new(GTK_WINDOW_POPUP); - wPreeditDraw = gtk_drawing_area_new(); - GtkWidget *predrw = PWidget(wPreeditDraw); // No code inside the G_OBJECT macro -#if GTK_CHECK_VERSION(3,0,0) - g_signal_connect(G_OBJECT(predrw), "draw", - G_CALLBACK(DrawPreedit), this); -#else - g_signal_connect(G_OBJECT(predrw), "expose_event", - G_CALLBACK(ExposePreedit), this); -#endif - gtk_container_add(GTK_CONTAINER(PWidget(wPreedit)), predrw); - gtk_widget_realize(PWidget(wPreedit)); - gtk_widget_realize(predrw); - gtk_widget_show(predrw); - - im_context = gtk_im_multicontext_new(); - g_signal_connect(G_OBJECT(im_context), "commit", - G_CALLBACK(Commit), this); - g_signal_connect(G_OBJECT(im_context), "preedit_changed", - G_CALLBACK(PreeditChanged), this); - gtk_im_context_set_client_window(im_context, WindowFromWidget(widget)); - GtkWidget *widtxt = PWidget(wText); // // No code inside the G_OBJECT macro - g_signal_connect_after(G_OBJECT(widtxt), "style_set", - G_CALLBACK(ScintillaGTK::StyleSetText), NULL); - g_signal_connect_after(G_OBJECT(widtxt), "realize", - G_CALLBACK(ScintillaGTK::RealizeText), NULL); - gtk_widget_realize(widtxt); - gtk_widget_realize(PWidget(scrollbarv)); - gtk_widget_realize(PWidget(scrollbarh)); - - cursor = gdk_cursor_new(GDK_XTERM); - gdk_window_set_cursor(PWindow(wText), cursor); - UnRefCursor(cursor); - - cursor = gdk_cursor_new(GDK_LEFT_PTR); - gdk_window_set_cursor(PWindow(scrollbarv), cursor); - UnRefCursor(cursor); - - cursor = gdk_cursor_new(GDK_LEFT_PTR); - gdk_window_set_cursor(PWindow(scrollbarh), cursor); - UnRefCursor(cursor); - - gtk_selection_add_targets(widget, GDK_SELECTION_PRIMARY, - clipboardCopyTargets, nClipboardCopyTargets); -} - -void ScintillaGTK::Realize(GtkWidget *widget) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - sciThis->RealizeThis(widget); -} - -void ScintillaGTK::UnRealizeThis(GtkWidget *widget) { - try { - gtk_selection_clear_targets(widget, GDK_SELECTION_PRIMARY); - - if (IS_WIDGET_MAPPED(widget)) { - gtk_widget_unmap(widget); - } -#if GTK_CHECK_VERSION(2,20,0) - gtk_widget_set_realized(widget, FALSE); -#else - GTK_WIDGET_UNSET_FLAGS(widget, GTK_REALIZED); -#endif - gtk_widget_unrealize(PWidget(wText)); - gtk_widget_unrealize(PWidget(scrollbarv)); - gtk_widget_unrealize(PWidget(scrollbarh)); - gtk_widget_unrealize(PWidget(wPreedit)); - gtk_widget_unrealize(PWidget(wPreeditDraw)); - g_object_unref(im_context); - im_context = NULL; - if (GTK_WIDGET_CLASS(parentClass)->unrealize) - GTK_WIDGET_CLASS(parentClass)->unrealize(widget); - - Finalise(); - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } -} - -void ScintillaGTK::UnRealize(GtkWidget *widget) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - sciThis->UnRealizeThis(widget); -} - -static void MapWidget(GtkWidget *widget) { - if (widget && - IS_WIDGET_VISIBLE(widget) && - !IS_WIDGET_MAPPED(widget)) { - gtk_widget_map(widget); - } -} - -void ScintillaGTK::MapThis() { - try { - //Platform::DebugPrintf("ScintillaGTK::map this\n"); -#if GTK_CHECK_VERSION(2,20,0) - gtk_widget_set_mapped(PWidget(wMain), TRUE); -#else - GTK_WIDGET_SET_FLAGS(PWidget(wMain), GTK_MAPPED); -#endif - MapWidget(PWidget(wText)); - MapWidget(PWidget(scrollbarh)); - MapWidget(PWidget(scrollbarv)); - wMain.SetCursor(Window::cursorArrow); - scrollbarv.SetCursor(Window::cursorArrow); - scrollbarh.SetCursor(Window::cursorArrow); - ChangeSize(); - gdk_window_show(PWindow(wMain)); - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } -} - -void ScintillaGTK::Map(GtkWidget *widget) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - sciThis->MapThis(); -} - -void ScintillaGTK::UnMapThis() { - try { - //Platform::DebugPrintf("ScintillaGTK::unmap this\n"); -#if GTK_CHECK_VERSION(2,20,0) - gtk_widget_set_mapped(PWidget(wMain), FALSE); -#else - GTK_WIDGET_UNSET_FLAGS(PWidget(wMain), GTK_MAPPED); -#endif - DropGraphics(false); - gdk_window_hide(PWindow(wMain)); - gtk_widget_unmap(PWidget(wText)); - gtk_widget_unmap(PWidget(scrollbarh)); - gtk_widget_unmap(PWidget(scrollbarv)); - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } -} - -void ScintillaGTK::UnMap(GtkWidget *widget) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - sciThis->UnMapThis(); -} - -void ScintillaGTK::ForAll(GtkCallback callback, gpointer callback_data) { - try { - (*callback) (PWidget(wText), callback_data); - (*callback) (PWidget(scrollbarv), callback_data); - (*callback) (PWidget(scrollbarh), callback_data); - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } -} - -void ScintillaGTK::MainForAll(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data) { - ScintillaGTK *sciThis = ScintillaFromWidget((GtkWidget *)container); - - if (callback != NULL && include_internals) { - sciThis->ForAll(callback, callback_data); - } -} - -gint ScintillaGTK::FocusInThis(GtkWidget *widget) { - try { - SetFocusState(true); - if (im_context != NULL) { - gchar *str = NULL; - gint cursor_pos; - - gtk_im_context_get_preedit_string(im_context, &str, NULL, &cursor_pos); - if (PWidget(wPreedit) != NULL) { - if (strlen(str) > 0) { - gtk_widget_show(PWidget(wPreedit)); - } else { - gtk_widget_hide(PWidget(wPreedit)); - } - } - g_free(str); - gtk_im_context_focus_in(im_context); - } - - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } - return FALSE; -} - -gint ScintillaGTK::FocusIn(GtkWidget *widget, GdkEventFocus * /*event*/) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - return sciThis->FocusInThis(widget); -} - -gint ScintillaGTK::FocusOutThis(GtkWidget *widget) { - try { - SetFocusState(false); - - if (PWidget(wPreedit) != NULL) - gtk_widget_hide(PWidget(wPreedit)); - if (im_context != NULL) - gtk_im_context_focus_out(im_context); - - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } - return FALSE; -} - -gint ScintillaGTK::FocusOut(GtkWidget *widget, GdkEventFocus * /*event*/) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - return sciThis->FocusOutThis(widget); -} - -void ScintillaGTK::SizeRequest(GtkWidget *widget, GtkRequisition *requisition) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - requisition->width = 1; - requisition->height = 1; - GtkRequisition child_requisition; -#if GTK_CHECK_VERSION(3,0,0) - gtk_widget_get_preferred_size(PWidget(sciThis->scrollbarh), NULL, &child_requisition); - gtk_widget_get_preferred_size(PWidget(sciThis->scrollbarv), NULL, &child_requisition); -#else - gtk_widget_size_request(PWidget(sciThis->scrollbarh), &child_requisition); - gtk_widget_size_request(PWidget(sciThis->scrollbarv), &child_requisition); -#endif -} - -void ScintillaGTK::GetPreferredWidth(GtkWidget *widget, gint *minimalWidth, gint *naturalWidth) { - GtkRequisition requisition; - SizeRequest(widget, &requisition); - *minimalWidth = *naturalWidth = requisition.width; -} - -void ScintillaGTK::GetPreferredHeight(GtkWidget *widget, gint *minimalHeight, gint *naturalHeight) { - GtkRequisition requisition; - SizeRequest(widget, &requisition); - *minimalHeight = *naturalHeight = requisition.height; -} - -void ScintillaGTK::SizeAllocate(GtkWidget *widget, GtkAllocation *allocation) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - try { -#if GTK_CHECK_VERSION(2,20,0) - gtk_widget_set_allocation(widget, allocation); -#else - widget->allocation = *allocation; -#endif - if (IS_WIDGET_REALIZED(widget)) - gdk_window_move_resize(WindowFromWidget(widget), - allocation->x, - allocation->y, - allocation->width, - allocation->height); - - sciThis->Resize(allocation->width, allocation->height); - - } catch (...) { - sciThis->errorStatus = SC_STATUS_FAILURE; - } -} - -void ScintillaGTK::Initialise() { - //Platform::DebugPrintf("ScintillaGTK::Initialise\n"); - parentClass = reinterpret_cast( - g_type_class_ref(gtk_container_get_type())); - -#if GTK_CHECK_VERSION(2,20,0) - gtk_widget_set_can_focus(PWidget(wMain), TRUE); - gtk_widget_set_sensitive(PWidget(wMain), TRUE); -#else - GTK_WIDGET_SET_FLAGS(PWidget(wMain), GTK_CAN_FOCUS); - GTK_WIDGET_SET_FLAGS(GTK_WIDGET(PWidget(wMain)), GTK_SENSITIVE); -#endif - gtk_widget_set_events(PWidget(wMain), - GDK_EXPOSURE_MASK - | GDK_STRUCTURE_MASK - | GDK_KEY_PRESS_MASK - | GDK_KEY_RELEASE_MASK - | GDK_FOCUS_CHANGE_MASK - | GDK_LEAVE_NOTIFY_MASK - | GDK_BUTTON_PRESS_MASK - | GDK_BUTTON_RELEASE_MASK - | GDK_POINTER_MOTION_MASK - | GDK_POINTER_MOTION_HINT_MASK); - - wText = gtk_drawing_area_new(); - gtk_widget_set_parent(PWidget(wText), PWidget(wMain)); - GtkWidget *widtxt = PWidget(wText); // No code inside the G_OBJECT macro - gtk_widget_show(widtxt); -#if GTK_CHECK_VERSION(3,0,0) - g_signal_connect(G_OBJECT(widtxt), "draw", - G_CALLBACK(ScintillaGTK::DrawText), this); -#else - g_signal_connect(G_OBJECT(widtxt), "expose_event", - G_CALLBACK(ScintillaGTK::ExposeText), this); -#endif - gtk_widget_set_events(widtxt, GDK_EXPOSURE_MASK); - // Avoid background drawing flash - gtk_widget_set_double_buffered(widtxt, FALSE); - gtk_widget_set_size_request(widtxt, 100, 100); - adjustmentv = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 201.0, 1.0, 20.0, 20.0)); -#if GTK_CHECK_VERSION(3,0,0) - scrollbarv = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT(adjustmentv)); -#else - scrollbarv = gtk_vscrollbar_new(GTK_ADJUSTMENT(adjustmentv)); -#endif -#if GTK_CHECK_VERSION(2,20,0) - gtk_widget_set_can_focus(PWidget(scrollbarv), FALSE); -#else - GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarv), GTK_CAN_FOCUS); -#endif - g_signal_connect(G_OBJECT(adjustmentv), "value_changed", - G_CALLBACK(ScrollSignal), this); - gtk_widget_set_parent(PWidget(scrollbarv), PWidget(wMain)); - gtk_widget_show(PWidget(scrollbarv)); - - adjustmenth = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 101.0, 1.0, 20.0, 20.0)); -#if GTK_CHECK_VERSION(3,0,0) - scrollbarh = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT(adjustmenth)); -#else - scrollbarh = gtk_hscrollbar_new(GTK_ADJUSTMENT(adjustmenth)); -#endif -#if GTK_CHECK_VERSION(2,20,0) - gtk_widget_set_can_focus(PWidget(scrollbarh), FALSE); -#else - GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarh), GTK_CAN_FOCUS); -#endif - g_signal_connect(G_OBJECT(adjustmenth), "value_changed", - G_CALLBACK(ScrollHSignal), this); - gtk_widget_set_parent(PWidget(scrollbarh), PWidget(wMain)); - gtk_widget_show(PWidget(scrollbarh)); - - gtk_widget_grab_focus(PWidget(wMain)); - - gtk_drag_dest_set(GTK_WIDGET(PWidget(wMain)), - GTK_DEST_DEFAULT_ALL, clipboardPasteTargets, nClipboardPasteTargets, - static_cast(GDK_ACTION_COPY | GDK_ACTION_MOVE)); - - // Set caret period based on GTK settings - gboolean blinkOn = false; - if (g_object_class_find_property(G_OBJECT_GET_CLASS( - G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink")) { - g_object_get(G_OBJECT( - gtk_settings_get_default()), "gtk-cursor-blink", &blinkOn, NULL); - } - if (blinkOn && - g_object_class_find_property(G_OBJECT_GET_CLASS( - G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink-time")) { - gint value; - g_object_get(G_OBJECT( - gtk_settings_get_default()), "gtk-cursor-blink-time", &value, NULL); - caret.period = gint(value / 1.75); - } else { - caret.period = 0; - } - - SetTicking(true); -} - -void ScintillaGTK::Finalise() { - SetTicking(false); - ScintillaBase::Finalise(); -} - -void ScintillaGTK::DisplayCursor(Window::Cursor c) { - if (cursorMode == SC_CURSORNORMAL) - wText.SetCursor(c); - else - wText.SetCursor(static_cast(cursorMode)); -} - -bool ScintillaGTK::DragThreshold(Point ptStart, Point ptNow) { - return gtk_drag_check_threshold(GTK_WIDGET(PWidget(wMain)), - ptStart.x, ptStart.y, ptNow.x, ptNow.y); -} - -void ScintillaGTK::StartDrag() { - dragWasDropped = false; - inDragDrop = ddDragging; - GtkTargetList *tl = gtk_target_list_new(clipboardCopyTargets, nClipboardCopyTargets); - gtk_drag_begin(GTK_WIDGET(PWidget(wMain)), - tl, - static_cast(GDK_ACTION_COPY | GDK_ACTION_MOVE), - evbtn.button, - reinterpret_cast(&evbtn)); -} - -static char *ConvertText(int *lenResult, char *s, size_t len, const char *charSetDest, - const char *charSetSource, bool transliterations, bool silent=false) { - // s is not const because of different versions of iconv disagreeing about const - *lenResult = 0; - char *destForm = 0; - Converter conv(charSetDest, charSetSource, transliterations); - if (conv) { - destForm = new char[len*3+1]; - char *pin = s; - size_t inLeft = len; - char *pout = destForm; - size_t outLeft = len*3+1; - size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft); - if (conversions == ((size_t)(-1))) { - if (!silent) - fprintf(stderr, "iconv %s->%s failed for %s\n", - charSetSource, charSetDest, static_cast(s)); - delete []destForm; - destForm = 0; - } else { -//fprintf(stderr, "iconv OK %s %d\n", destForm, pout - destForm); - *pout = '\0'; - *lenResult = pout - destForm; - } - } else { -fprintf(stderr, "Can not iconv %s %s\n", charSetDest, charSetSource); - } - if (!destForm) { - destForm = new char[1]; - destForm[0] = '\0'; - *lenResult = 0; - } - return destForm; -} - -// Returns the target converted to UTF8. -// Return the length in bytes. -int ScintillaGTK::TargetAsUTF8(char *text) { - int targetLength = targetEnd - targetStart; - if (IsUnicodeMode()) { - if (text) { - pdoc->GetCharRange(text, targetStart, targetLength); - } - } else { - // Need to convert - const char *charSetBuffer = CharacterSetID(); - if (*charSetBuffer) { -//~ fprintf(stderr, "AsUTF8 %s %d %0d-%0d\n", charSetBuffer, targetLength, targetStart, targetEnd); - char *s = new char[targetLength]; - if (s) { - pdoc->GetCharRange(s, targetStart, targetLength); -//~ fprintf(stderr, " \"%s\"\n", s); - if (text) { - char *tmputf = ConvertText(&targetLength, s, targetLength, "UTF-8", charSetBuffer, false); - memcpy(text, tmputf, targetLength); - delete []tmputf; -//~ fprintf(stderr, " \"%s\"\n", text); - } - delete []s; - } - } else { - if (text) { - pdoc->GetCharRange(text, targetStart, targetLength); - } - } - } -//~ fprintf(stderr, "Length = %d bytes\n", targetLength); - return targetLength; -} - -// Translates a nul terminated UTF8 string into the document encoding. -// Return the length of the result in bytes. -int ScintillaGTK::EncodedFromUTF8(char *utf8, char *encoded) { - int inputLength = (lengthForEncode >= 0) ? lengthForEncode : strlen(utf8); - if (IsUnicodeMode()) { - if (encoded) { - memcpy(encoded, utf8, inputLength); - } - return inputLength; - } else { - // Need to convert - const char *charSetBuffer = CharacterSetID(); - if (*charSetBuffer) { - int outLength = 0; - char *tmpEncoded = ConvertText(&outLength, utf8, inputLength, charSetBuffer, "UTF-8", true); - if (tmpEncoded) { - if (encoded) { - memcpy(encoded, tmpEncoded, outLength); - } - delete []tmpEncoded; - } - return outLength; - } else { - if (encoded) { - memcpy(encoded, utf8, inputLength); - } - return inputLength; - } - } - // Fail - return 0; -} - -bool ScintillaGTK::ValidCodePage(int codePage) const { - return codePage == 0 - || codePage == SC_CP_UTF8 - || codePage == 932 - || codePage == 936 - || codePage == 949 - || codePage == 950 - || codePage == 1361; -} - -sptr_t ScintillaGTK::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { - try { - switch (iMessage) { - - case SCI_GRABFOCUS: - gtk_widget_grab_focus(PWidget(wMain)); - break; - - case SCI_GETDIRECTFUNCTION: - return reinterpret_cast(DirectFunction); - - case SCI_GETDIRECTPOINTER: - return reinterpret_cast(this); - -#ifdef SCI_LEXER - case SCI_LOADLEXERLIBRARY: - LexerManager::GetInstance()->Load(reinterpret_cast(lParam)); - break; -#endif - case SCI_TARGETASUTF8: - return TargetAsUTF8(reinterpret_cast(lParam)); - - case SCI_ENCODEDFROMUTF8: - return EncodedFromUTF8(reinterpret_cast(wParam), - reinterpret_cast(lParam)); - - case SCI_SETRECTANGULARSELECTIONMODIFIER: - rectangularSelectionModifier = wParam; - break; - - case SCI_GETRECTANGULARSELECTIONMODIFIER: - return rectangularSelectionModifier; - - default: - return ScintillaBase::WndProc(iMessage, wParam, lParam); - } - } catch (std::bad_alloc&) { - errorStatus = SC_STATUS_BADALLOC; - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } - return 0l; -} - -sptr_t ScintillaGTK::DefWndProc(unsigned int, uptr_t, sptr_t) { - return 0; -} - -void ScintillaGTK::SetTicking(bool on) { - if (timer.ticking != on) { - timer.ticking = on; - if (timer.ticking) { - timer.tickerID = reinterpret_cast(g_timeout_add(timer.tickSize, - reinterpret_cast(TimeOut), this)); - } else { - g_source_remove(GPOINTER_TO_UINT(timer.tickerID)); - } - } - timer.ticksToWait = caret.period; -} - -bool ScintillaGTK::SetIdle(bool on) { - if (on) { - // Start idler, if it's not running. - if (!idler.state) { - idler.state = true; - idler.idlerID = reinterpret_cast( - g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, - reinterpret_cast(IdleCallback), this, NULL)); - } - } else { - // Stop idler, if it's running - if (idler.state) { - idler.state = false; - g_source_remove(GPOINTER_TO_UINT(idler.idlerID)); - } - } - return true; -} - -void ScintillaGTK::SetMouseCapture(bool on) { - if (mouseDownCaptures) { - if (on) { - gtk_grab_add(GTK_WIDGET(PWidget(wMain))); - } else { - gtk_grab_remove(GTK_WIDGET(PWidget(wMain))); - } - } - capturedMouse = on; -} - -bool ScintillaGTK::HaveMouseCapture() { - return capturedMouse; -} - -#if GTK_CHECK_VERSION(3,0,0) - -// Is crcTest completely in crcContainer? -static bool CRectContains(const cairo_rectangle_t &crcContainer, const cairo_rectangle_t &crcTest) { - return - (crcTest.x >= crcContainer.x) && ((crcTest.x + crcTest.width) <= (crcContainer.x + crcContainer.width)) && - (crcTest.y >= crcContainer.y) && ((crcTest.y + crcTest.height) <= (crcContainer.y + crcContainer.height)); -} - -// Is crcTest completely in crcListContainer? -// May incorrectly return false if complex shape -static bool CRectListContains(const cairo_rectangle_list_t *crcListContainer, const cairo_rectangle_t &crcTest) { - for (int r=0; rnum_rectangles; r++) { - if (CRectContains(crcListContainer->rectangles[r], crcTest)) - return true; - } - return false; -} - -#endif - -bool ScintillaGTK::PaintContains(PRectangle rc) { - // This allows optimization when a rectangle is completely in the update region. - // It is OK to return false when too difficult to determine as that just performs extra drawing - bool contains = true; - if (paintState == painting) { - if (!rcPaint.Contains(rc)) { - contains = false; - } else if (rgnUpdate) { -#if GTK_CHECK_VERSION(3,0,0) - cairo_rectangle_t grc = {rc.left, rc.top, - rc.right - rc.left, rc.bottom - rc.top}; - contains = CRectListContains(rgnUpdate, grc); -#else - GdkRectangle grc = {rc.left, rc.top, - rc.right - rc.left, rc.bottom - rc.top}; - if (gdk_region_rect_in(rgnUpdate, &grc) != GDK_OVERLAP_RECTANGLE_IN) { - contains = false; - } -#endif - } - } - return contains; -} - -// Redraw all of text area. This paint will not be abandoned. -void ScintillaGTK::FullPaint() { - wText.InvalidateAll(); -} - -PRectangle ScintillaGTK::GetClientRectangle() { - PRectangle rc = wMain.GetClientPosition(); - if (verticalScrollBarVisible) - rc.right -= scrollBarWidth; - if (horizontalScrollBarVisible && (wrapState == eWrapNone)) - rc.bottom -= scrollBarHeight; - // Move to origin - rc.right -= rc.left; - rc.bottom -= rc.top; - rc.left = 0; - rc.top = 0; - return rc; -} - -// Synchronously paint a rectangle of the window. -void ScintillaGTK::SyncPaint(PRectangle rc) { - paintState = painting; - rcPaint = rc; - PRectangle rcClient = GetClientRectangle(); - paintingAllText = rcPaint.Contains(rcClient); - if (PWindow(wText)) { - Surface *sw = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); - if (sw) { - cairo_t *cr = gdk_cairo_create(PWindow(wText)); - sw->Init(cr, PWidget(wText)); - Paint(sw, rc); - sw->Release(); - delete sw; - cairo_destroy(cr); - } - } - if (paintState == paintAbandoned) { - // Painting area was insufficient to cover new styling or brace highlight positions - FullPaint(); - } - paintState = notPainting; -} - -void ScintillaGTK::ScrollText(int linesToMove) { - int diff = vs.lineHeight * -linesToMove; - //Platform::DebugPrintf("ScintillaGTK::ScrollText %d %d %0d,%0d %0d,%0d\n", linesToMove, diff, - // rc.left, rc.top, rc.right, rc.bottom); - GtkWidget *wi = PWidget(wText); - - gdk_window_scroll(WindowFromWidget(wi), 0, -diff); - gdk_window_process_updates(WindowFromWidget(wi), FALSE); -} - -void ScintillaGTK::SetVerticalScrollPos() { - DwellEnd(true); - gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmentv), topLine); -} - -void ScintillaGTK::SetHorizontalScrollPos() { - DwellEnd(true); - gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmenth), xOffset / 2); -} - -bool ScintillaGTK::ModifyScrollBars(int nMax, int nPage) { - bool modified = false; - int pageScroll = LinesToScroll(); - -#if GTK_CHECK_VERSION(3,0,0) - if (gtk_adjustment_get_upper(adjustmentv) != (nMax + 1) || - gtk_adjustment_get_page_size(adjustmentv) != nPage || - gtk_adjustment_get_page_increment(adjustmentv) != pageScroll) { - gtk_adjustment_set_upper(adjustmentv, nMax + 1); - gtk_adjustment_set_page_size(adjustmentv, nPage); - gtk_adjustment_set_page_increment(adjustmentv, pageScroll); - gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmentv)); - modified = true; - } -#else - if (GTK_ADJUSTMENT(adjustmentv)->upper != (nMax + 1) || - GTK_ADJUSTMENT(adjustmentv)->page_size != nPage || - GTK_ADJUSTMENT(adjustmentv)->page_increment != pageScroll) { - GTK_ADJUSTMENT(adjustmentv)->upper = nMax + 1; - GTK_ADJUSTMENT(adjustmentv)->page_size = nPage; - GTK_ADJUSTMENT(adjustmentv)->page_increment = pageScroll; - gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmentv)); - modified = true; - } -#endif - - PRectangle rcText = GetTextRectangle(); - int horizEndPreferred = scrollWidth; - if (horizEndPreferred < 0) - horizEndPreferred = 0; - unsigned int pageWidth = rcText.Width(); - unsigned int pageIncrement = pageWidth / 3; - unsigned int charWidth = vs.styles[STYLE_DEFAULT].aveCharWidth; -#if GTK_CHECK_VERSION(3,0,0) - if (gtk_adjustment_get_upper(adjustmenth) != horizEndPreferred || - gtk_adjustment_get_page_size(adjustmenth) != pageWidth || - gtk_adjustment_get_page_increment(adjustmenth) != pageIncrement || - gtk_adjustment_get_step_increment(adjustmenth) != charWidth) { - gtk_adjustment_set_upper(adjustmenth, horizEndPreferred); - gtk_adjustment_set_page_size(adjustmenth, pageWidth); - gtk_adjustment_set_page_increment(adjustmenth, pageIncrement); - gtk_adjustment_set_step_increment(adjustmenth, charWidth); - gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmenth)); - modified = true; - } -#else - if (GTK_ADJUSTMENT(adjustmenth)->upper != horizEndPreferred || - GTK_ADJUSTMENT(adjustmenth)->page_size != pageWidth || - GTK_ADJUSTMENT(adjustmenth)->page_increment != pageIncrement || - GTK_ADJUSTMENT(adjustmenth)->step_increment != charWidth) { - GTK_ADJUSTMENT(adjustmenth)->upper = horizEndPreferred; - GTK_ADJUSTMENT(adjustmenth)->step_increment = charWidth; - GTK_ADJUSTMENT(adjustmenth)->page_size = pageWidth; - GTK_ADJUSTMENT(adjustmenth)->page_increment = pageIncrement; - gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmenth)); - modified = true; - } -#endif - return modified; -} - -void ScintillaGTK::ReconfigureScrollBars() { - PRectangle rc = wMain.GetClientPosition(); - Resize(rc.Width(), rc.Height()); -} - -void ScintillaGTK::NotifyChange() { - g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0, - Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE), PWidget(wMain)); -} - -void ScintillaGTK::NotifyFocus(bool focus) { - g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0, - Platform::LongFromTwoShorts - (GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS), PWidget(wMain)); -} - -void ScintillaGTK::NotifyParent(SCNotification scn) { - scn.nmhdr.hwndFrom = PWidget(wMain); - scn.nmhdr.idFrom = GetCtrlID(); - g_signal_emit(G_OBJECT(sci), scintilla_signals[NOTIFY_SIGNAL], 0, - GetCtrlID(), &scn); -} - -void ScintillaGTK::NotifyKey(int key, int modifiers) { - SCNotification scn = {0}; - scn.nmhdr.code = SCN_KEY; - scn.ch = key; - scn.modifiers = modifiers; - - NotifyParent(scn); -} - -void ScintillaGTK::NotifyURIDropped(const char *list) { - SCNotification scn = {0}; - scn.nmhdr.code = SCN_URIDROPPED; - scn.text = list; - - NotifyParent(scn); -} - -const char *CharacterSetID(int characterSet); - -const char *ScintillaGTK::CharacterSetID() const { - return ::CharacterSetID(vs.styles[STYLE_DEFAULT].characterSet); -} - -class CaseFolderUTF8 : public CaseFolderTable { -public: - CaseFolderUTF8() { - StandardASCII(); - } - virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) { - if ((lenMixed == 1) && (sizeFolded > 0)) { - folded[0] = mapping[static_cast(mixed[0])]; - return 1; - } else { - gchar *mapped = g_utf8_casefold(mixed, lenMixed); - size_t lenMapped = strlen(mapped); - if (lenMapped < sizeFolded) { - memcpy(folded, mapped, lenMapped); - } else { - lenMapped = 0; - } - g_free(mapped); - return lenMapped; - } - } -}; - -class CaseFolderDBCS : public CaseFolderTable { - const char *charSet; -public: - CaseFolderDBCS(const char *charSet_) : charSet(charSet_) { - StandardASCII(); - } - virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) { - if ((lenMixed == 1) && (sizeFolded > 0)) { - folded[0] = mapping[static_cast(mixed[0])]; - return 1; - } else if (*charSet) { - int convertedLength = lenMixed; - char *sUTF8 = ConvertText(&convertedLength, const_cast(mixed), lenMixed, - "UTF-8", charSet, false); - if (sUTF8) { - gchar *mapped = g_utf8_casefold(sUTF8, strlen(sUTF8)); - size_t lenMapped = strlen(mapped); - if (lenMapped < sizeFolded) { - memcpy(folded, mapped, lenMapped); - } else { - folded[0] = '\0'; - lenMapped = 1; - } - g_free(mapped); - delete []sUTF8; - return lenMapped; - } - } - // Something failed so return a single NUL byte - folded[0] = '\0'; - return 1; - } -}; - -CaseFolder *ScintillaGTK::CaseFolderForEncoding() { - if (pdoc->dbcsCodePage == SC_CP_UTF8) { - return new CaseFolderUTF8(); - } else { - const char *charSetBuffer = CharacterSetID(); - if (charSetBuffer) { - if (pdoc->dbcsCodePage == 0) { - CaseFolderTable *pcf = new CaseFolderTable(); - pcf->StandardASCII(); - // Only for single byte encodings - for (int i=0x80; i<0x100; i++) { - char sCharacter[2] = "A"; - sCharacter[0] = i; - int convertedLength = 1; - const char *sUTF8 = ConvertText(&convertedLength, sCharacter, 1, - "UTF-8", charSetBuffer, false); - if (sUTF8) { - gchar *mapped = g_utf8_casefold(sUTF8, strlen(sUTF8)); - if (mapped) { - int mappedLength = strlen(mapped); - const char *mappedBack = ConvertText(&mappedLength, mapped, - mappedLength, charSetBuffer, "UTF-8", false, true); - if (mappedBack && (strlen(mappedBack) == 1) && (mappedBack[0] != sCharacter[0])) { - pcf->SetTranslation(sCharacter[0], mappedBack[0]); - } - delete []mappedBack; - g_free(mapped); - } - } - delete []sUTF8; - } - return pcf; - } else { - return new CaseFolderDBCS(charSetBuffer); - } - } - return 0; - } -} - -std::string ScintillaGTK::CaseMapString(const std::string &s, int caseMapping) { - if (s.size() == 0) - return std::string(); - - if (caseMapping == cmSame) - return s; - - const char *needsFree1 = 0; // Must be freed with delete [] - const char *charSetBuffer = CharacterSetID(); - const char *sUTF8 = s.c_str(); - int rangeBytes = s.size(); - - int convertedLength = rangeBytes; - // Change text to UTF-8 - if (!IsUnicodeMode()) { - // Need to convert - if (*charSetBuffer) { - sUTF8 = ConvertText(&convertedLength, const_cast(s.c_str()), rangeBytes, - "UTF-8", charSetBuffer, false); - needsFree1 = sUTF8; - } - } - gchar *mapped; // Must be freed with g_free - if (caseMapping == cmUpper) { - mapped = g_utf8_strup(sUTF8, convertedLength); - } else { - mapped = g_utf8_strdown(sUTF8, convertedLength); - } - int mappedLength = strlen(mapped); - char *mappedBack = mapped; - - char *needsFree2 = 0; // Must be freed with delete [] - if (!IsUnicodeMode()) { - if (*charSetBuffer) { - mappedBack = ConvertText(&mappedLength, mapped, mappedLength, charSetBuffer, "UTF-8", false); - needsFree2 = mappedBack; - } - } - - std::string ret(mappedBack, mappedLength); - g_free(mapped); - delete []needsFree1; - delete []needsFree2; - return ret; -} - -int ScintillaGTK::KeyDefault(int key, int modifiers) { - if (!(modifiers & SCI_CTRL) && !(modifiers & SCI_ALT)) { - if (key < 256) { - NotifyKey(key, modifiers); - return 0; - } else { - // Pass up to container in case it is an accelerator - NotifyKey(key, modifiers); - return 0; - } - } else { - // Pass up to container in case it is an accelerator - NotifyKey(key, modifiers); - return 0; - } - //Platform::DebugPrintf("SK-key: %d %x %x\n",key, modifiers); -} - -void ScintillaGTK::CopyToClipboard(const SelectionText &selectedText) { - SelectionText *clipText = new SelectionText(); - clipText->Copy(selectedText); - StoreOnClipboard(clipText); -} - -void ScintillaGTK::Copy() { - if (!sel.Empty()) { - SelectionText *clipText = new SelectionText(); - CopySelectionRange(clipText); - StoreOnClipboard(clipText); -#if PLAT_GTK_WIN32 - if (sel.IsRectangular()) { - ::OpenClipboard(NULL); - ::SetClipboardData(cfColumnSelect, 0); - ::CloseClipboard(); - } -#endif - } -} - -void ScintillaGTK::Paste() { - atomSought = atomUTF8; - gtk_selection_convert(GTK_WIDGET(PWidget(wMain)), - atomClipboard, atomSought, GDK_CURRENT_TIME); -} - -void ScintillaGTK::CreateCallTipWindow(PRectangle rc) { - if (!ct.wCallTip.Created()) { - ct.wCallTip = gtk_window_new(GTK_WINDOW_POPUP); - ct.wDraw = gtk_drawing_area_new(); - GtkWidget *widcdrw = PWidget(ct.wDraw); // // No code inside the G_OBJECT macro - gtk_container_add(GTK_CONTAINER(PWidget(ct.wCallTip)), widcdrw); -#if GTK_CHECK_VERSION(3,0,0) - g_signal_connect(G_OBJECT(widcdrw), "draw", - G_CALLBACK(ScintillaGTK::DrawCT), &ct); -#else - g_signal_connect(G_OBJECT(widcdrw), "expose_event", - G_CALLBACK(ScintillaGTK::ExposeCT), &ct); -#endif - g_signal_connect(G_OBJECT(widcdrw), "button_press_event", - G_CALLBACK(ScintillaGTK::PressCT), static_cast(this)); - gtk_widget_set_events(widcdrw, - GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK); - } - gtk_widget_set_size_request(PWidget(ct.wDraw), rc.Width(), rc.Height()); - ct.wDraw.Show(); - if (PWindow(ct.wCallTip)) { - gdk_window_resize(PWindow(ct.wCallTip), rc.Width(), rc.Height()); - } -} - -void ScintillaGTK::AddToPopUp(const char *label, int cmd, bool enabled) { - GtkWidget *menuItem; - if (label[0]) - menuItem = gtk_menu_item_new_with_label(label); - else - menuItem = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(popup.GetID()), menuItem); - g_object_set_data(G_OBJECT(menuItem), "CmdNum", reinterpret_cast(cmd)); - g_signal_connect(G_OBJECT(menuItem),"activate", G_CALLBACK(PopUpCB), this); - - if (cmd) { - if (menuItem) - gtk_widget_set_sensitive(menuItem, enabled); - } -} - -bool ScintillaGTK::OwnPrimarySelection() { - return ((gdk_selection_owner_get(GDK_SELECTION_PRIMARY) - == PWindow(wMain)) && - (PWindow(wMain) != NULL)); -} - -void ScintillaGTK::ClaimSelection() { - // X Windows has a 'primary selection' as well as the clipboard. - // Whenever the user selects some text, we become the primary selection - if (!sel.Empty() && IS_WIDGET_REALIZED(GTK_WIDGET(PWidget(wMain)))) { - primarySelection = true; - gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)), - GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); - primary.Free(); - } else if (OwnPrimarySelection()) { - primarySelection = true; - if (primary.s == NULL) - gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); - } else { - primarySelection = false; - primary.Free(); - } -} - -#if GTK_CHECK_VERSION(3,0,0) -static const guchar *DataOfGSD(GtkSelectionData *sd) { return gtk_selection_data_get_data(sd); } -static gint LengthOfGSD(GtkSelectionData *sd) { return gtk_selection_data_get_length(sd); } -static GdkAtom TypeOfGSD(GtkSelectionData *sd) { return gtk_selection_data_get_data_type(sd); } -static GdkAtom SelectionOfGSD(GtkSelectionData *sd) { return gtk_selection_data_get_selection(sd); } -#else -static const guchar *DataOfGSD(GtkSelectionData *sd) { return sd->data; } -static gint LengthOfGSD(GtkSelectionData *sd) { return sd->length; } -static GdkAtom TypeOfGSD(GtkSelectionData *sd) { return sd->type; } -static GdkAtom SelectionOfGSD(GtkSelectionData *sd) { return sd->selection; } -#endif - -// Detect rectangular text, convert line ends to current mode, convert from or to UTF-8 -void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText) { - const char *data = reinterpret_cast(DataOfGSD(selectionData)); - int len = LengthOfGSD(selectionData); - GdkAtom selectionTypeData = TypeOfGSD(selectionData); - - // Return empty string if selection is not a string - if ((selectionTypeData != GDK_TARGET_STRING) && (selectionTypeData != atomUTF8)) { - char *empty = new char[1]; - empty[0] = '\0'; - selText.Set(empty, 0, SC_CP_UTF8, 0, false, false); - return; - } - - // Check for "\n\0" ending to string indicating that selection is rectangular - bool isRectangular; -#if PLAT_GTK_WIN32 - isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0; -#else - isRectangular = ((len > 2) && (data[len - 1] == 0 && data[len - 2] == '\n')); - if (isRectangular) - len--; // Forget the extra '\0' -#endif - - char *dest; - if (selectionTypeData == GDK_TARGET_STRING) { - dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode); - if (IsUnicodeMode()) { - // Unknown encoding so assume in Latin1 - char *destPrevious = dest; - dest = UTF8FromLatin1(dest, len); - selText.Set(dest, len, SC_CP_UTF8, 0, selText.rectangular, false); - delete []destPrevious; - } else { - // Assume buffer is in same encoding as selection - selText.Set(dest, len, pdoc->dbcsCodePage, - vs.styles[STYLE_DEFAULT].characterSet, isRectangular, false); - } - } else { // UTF-8 - dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode); - selText.Set(dest, len, SC_CP_UTF8, 0, isRectangular, false); - const char *charSetBuffer = CharacterSetID(); - if (!IsUnicodeMode() && *charSetBuffer) { - // Convert to locale - dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8", true); - selText.Set(dest, len, pdoc->dbcsCodePage, - vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular, false); - } - } -} - -void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) { - try { - if ((SelectionOfGSD(selection_data) == atomClipboard) || - (SelectionOfGSD(selection_data) == GDK_SELECTION_PRIMARY)) { - if ((atomSought == atomUTF8) && (LengthOfGSD(selection_data) <= 0)) { - atomSought = atomString; - gtk_selection_convert(GTK_WIDGET(PWidget(wMain)), - SelectionOfGSD(selection_data), atomSought, GDK_CURRENT_TIME); - } else if ((LengthOfGSD(selection_data) > 0) && - ((TypeOfGSD(selection_data) == GDK_TARGET_STRING) || (TypeOfGSD(selection_data) == atomUTF8))) { - SelectionText selText; - GetGtkSelectionText(selection_data, selText); - - UndoGroup ug(pdoc); - if (SelectionOfGSD(selection_data) != GDK_SELECTION_PRIMARY) { - ClearSelection(multiPasteMode == SC_MULTIPASTE_EACH); - } - SelectionPosition selStart = sel.IsRectangular() ? - sel.Rectangular().Start() : - sel.Range(sel.Main()).Start(); - - if (selText.rectangular) { - PasteRectangular(selStart, selText.s, selText.len); - } else { - InsertPaste(selStart, selText.s, selText.len); - } - EnsureCaretVisible(); - } - } -// else fprintf(stderr, "Target non string %d %d\n", (int)(selection_data->type), -// (int)(atomUTF8)); - Redraw(); - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } -} - -void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) { - dragWasDropped = true; - if (TypeOfGSD(selection_data) == atomUriList || TypeOfGSD(selection_data) == atomDROPFILES_DND) { - char *ptr = new char[LengthOfGSD(selection_data) + 1]; - ptr[LengthOfGSD(selection_data)] = '\0'; - memcpy(ptr, DataOfGSD(selection_data), LengthOfGSD(selection_data)); - NotifyURIDropped(ptr); - delete []ptr; - } else if ((TypeOfGSD(selection_data) == GDK_TARGET_STRING) || (TypeOfGSD(selection_data) == atomUTF8)) { - if (TypeOfGSD(selection_data) > 0) { - SelectionText selText; - GetGtkSelectionText(selection_data, selText); - DropAt(posDrop, selText.s, false, selText.rectangular); - } - } else if (LengthOfGSD(selection_data) > 0) { - //~ fprintf(stderr, "ReceivedDrop other %p\n", static_cast(selection_data->type)); - } - Redraw(); -} - - - -void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *text) { -#if PLAT_GTK_WIN32 - // GDK on Win32 expands any \n into \r\n, so make a copy of - // the clip text now with newlines converted to \n. Use { } to hide symbols - // from code below - SelectionText *newline_normalized = NULL; - { - int tmpstr_len; - char *tmpstr = Document::TransformLineEnds(&tmpstr_len, text->s, text->len, SC_EOL_LF); - newline_normalized = new SelectionText(); - newline_normalized->Set(tmpstr, tmpstr_len, SC_CP_UTF8, 0, text->rectangular, false); - text = newline_normalized; - } -#endif - - // Convert text to utf8 if it isn't already - SelectionText *converted = 0; - if ((text->codePage != SC_CP_UTF8) && (info == TARGET_UTF8_STRING)) { - const char *charSet = ::CharacterSetID(text->characterSet); - if (*charSet) { - int new_len; - char* tmputf = ConvertText(&new_len, text->s, text->len, "UTF-8", charSet, false); - converted = new SelectionText(); - converted->Set(tmputf, new_len, SC_CP_UTF8, 0, text->rectangular, false); - text = converted; - } - } - - // Here is a somewhat evil kludge. - // As I can not work out how to store data on the clipboard in multiple formats - // and need some way to mark the clipping as being stream or rectangular, - // the terminating \0 is included in the length for rectangular clippings. - // All other tested aplications behave benignly by ignoring the \0. - // The #if is here because on Windows cfColumnSelect clip entry is used - // instead as standard indicator of rectangularness (so no need to kludge) - const char *textData = text->s ? text->s : ""; - int len = strlen(textData); -#if PLAT_GTK_WIN32 == 0 - if (text->rectangular) - len++; -#endif - - if (info == TARGET_UTF8_STRING) { - gtk_selection_data_set_text(selection_data, textData, len); - } else { - gtk_selection_data_set(selection_data, - static_cast(GDK_SELECTION_TYPE_STRING), - 8, reinterpret_cast(textData), len); - } - delete converted; - -#if PLAT_GTK_WIN32 - delete newline_normalized; -#endif -} - -void ScintillaGTK::StoreOnClipboard(SelectionText *clipText) { - GtkClipboard *clipBoard = - gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard); - if (clipBoard == NULL) // Occurs if widget isn't in a toplevel - return; - - if (gtk_clipboard_set_with_data(clipBoard, clipboardCopyTargets, nClipboardCopyTargets, - ClipboardGetSelection, ClipboardClearSelection, clipText)) { - gtk_clipboard_set_can_store(clipBoard, clipboardCopyTargets, nClipboardCopyTargets); - } -} - -void ScintillaGTK::ClipboardGetSelection(GtkClipboard *, GtkSelectionData *selection_data, guint info, void *data) { - GetSelection(selection_data, info, static_cast(data)); -} - -void ScintillaGTK::ClipboardClearSelection(GtkClipboard *, void *data) { - SelectionText *obj = static_cast(data); - delete obj; -} - -void ScintillaGTK::UnclaimSelection(GdkEventSelection *selection_event) { - try { - //Platform::DebugPrintf("UnclaimSelection\n"); - if (selection_event->selection == GDK_SELECTION_PRIMARY) { - //Platform::DebugPrintf("UnclaimPrimarySelection\n"); - if (!OwnPrimarySelection()) { - primary.Free(); - primarySelection = false; - FullPaint(); - } - } - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } -} - -void ScintillaGTK::Resize(int width, int height) { - //Platform::DebugPrintf("Resize %d %d\n", width, height); - //printf("Resize %d %d\n", width, height); - - // Not always needed, but some themes can have different sizes of scrollbars -#if GTK_CHECK_VERSION(3,0,0) - GtkRequisition requisition; - gtk_widget_get_requisition(PWidget(scrollbarv), &requisition); - scrollBarWidth = requisition.width; - gtk_widget_get_requisition(PWidget(scrollbarh), &requisition); - scrollBarHeight = requisition.height; -#else - scrollBarWidth = GTK_WIDGET(PWidget(scrollbarv))->requisition.width; - scrollBarHeight = GTK_WIDGET(PWidget(scrollbarh))->requisition.height; -#endif - - // These allocations should never produce negative sizes as they would wrap around to huge - // unsigned numbers inside GTK+ causing warnings. - bool showSBHorizontal = horizontalScrollBarVisible && (wrapState == eWrapNone); - int horizontalScrollBarHeight = scrollBarHeight; - if (!showSBHorizontal) - horizontalScrollBarHeight = 0; - - GtkAllocation alloc; - if (showSBHorizontal) { - gtk_widget_show(GTK_WIDGET(PWidget(scrollbarh))); - alloc.x = 0; - alloc.y = height - scrollBarHeight; - alloc.width = Platform::Maximum(1, width - scrollBarWidth); - alloc.height = horizontalScrollBarHeight; - gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarh)), &alloc); - } else { - gtk_widget_hide(GTK_WIDGET(PWidget(scrollbarh))); - } - - if (verticalScrollBarVisible) { - gtk_widget_show(GTK_WIDGET(PWidget(scrollbarv))); - alloc.x = width - scrollBarWidth; - alloc.y = 0; - alloc.width = scrollBarWidth; - alloc.height = Platform::Maximum(1, height - scrollBarHeight); - if (!showSBHorizontal) - alloc.height += scrollBarWidth-1; - gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarv)), &alloc); - } else { - gtk_widget_hide(GTK_WIDGET(PWidget(scrollbarv))); - } - if (IS_WIDGET_MAPPED(PWidget(wMain))) { - ChangeSize(); - } - - alloc.x = 0; - alloc.y = 0; - alloc.width = Platform::Maximum(1, width - scrollBarWidth); - alloc.height = Platform::Maximum(1, height - scrollBarHeight); - if (!showSBHorizontal) - alloc.height += scrollBarHeight; - if (!verticalScrollBarVisible) - alloc.width += scrollBarWidth; - gtk_widget_size_allocate(GTK_WIDGET(PWidget(wText)), &alloc); -} - -static void SetAdjustmentValue(GtkAdjustment *object, int value) { - GtkAdjustment *adjustment = GTK_ADJUSTMENT(object); -#if GTK_CHECK_VERSION(3,0,0) - int maxValue = static_cast( - gtk_adjustment_get_upper(adjustment) - gtk_adjustment_get_page_size(adjustment)); -#else - int maxValue = static_cast( - adjustment->upper - adjustment->page_size); -#endif - - if (value > maxValue) - value = maxValue; - if (value < 0) - value = 0; - gtk_adjustment_set_value(adjustment, value); -} - -static int modifierTranslated(int sciModifier) { - switch (sciModifier) { - case SCMOD_SHIFT: - return GDK_SHIFT_MASK; - case SCMOD_CTRL: - return GDK_CONTROL_MASK; - case SCMOD_ALT: - return GDK_MOD1_MASK; - case SCMOD_SUPER: - return GDK_MOD4_MASK; - default: - return 0; - } -} - -gint ScintillaGTK::PressThis(GdkEventButton *event) { - try { - //Platform::DebugPrintf("Press %x time=%d state = %x button = %x\n",this,event->time, event->state, event->button); - // Do not use GTK+ double click events as Scintilla has its own double click detection - if (event->type != GDK_BUTTON_PRESS) - return FALSE; - - evbtn = *event; - Point pt; - pt.x = int(event->x); - pt.y = int(event->y); - PRectangle rcClient = GetClientRectangle(); - //Platform::DebugPrintf("Press %0d,%0d in %0d,%0d %0d,%0d\n", - // pt.x, pt.y, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); - if ((pt.x > rcClient.right) || (pt.y > rcClient.bottom)) { - Platform::DebugPrintf("Bad location\n"); - return FALSE; - } - - bool ctrl = (event->state & GDK_CONTROL_MASK) != 0; - - gtk_widget_grab_focus(PWidget(wMain)); - if (event->button == 1) { - // On X, instead of sending literal modifiers use the user specified - // modifier, defaulting to control instead of alt. - // This is because most X window managers grab alt + click for moving - ButtonDown(pt, event->time, - (event->state & GDK_SHIFT_MASK) != 0, - (event->state & GDK_CONTROL_MASK) != 0, - (event->state & modifierTranslated(rectangularSelectionModifier)) != 0); - } else if (event->button == 2) { - // Grab the primary selection if it exists - SelectionPosition pos = SPositionFromLocation(pt, false, false, UserVirtualSpace()); - if (OwnPrimarySelection() && primary.s == NULL) - CopySelectionRange(&primary); - - sel.Clear(); - SetSelection(pos, pos); - atomSought = atomUTF8; - gtk_selection_convert(GTK_WIDGET(PWidget(wMain)), GDK_SELECTION_PRIMARY, - atomSought, event->time); - } else if (event->button == 3) { - if (!PointInSelection(pt)) - SetEmptySelection(PositionFromLocation(pt)); - if (displayPopupMenu) { - // PopUp menu - // Convert to screen - int ox = 0; - int oy = 0; - gdk_window_get_origin(PWindow(wMain), &ox, &oy); - ContextMenu(Point(pt.x + ox, pt.y + oy)); - } else { - return FALSE; - } - } else if (event->button == 4) { - // Wheel scrolling up (only GTK 1.x does it this way) - if (ctrl) - SetAdjustmentValue(adjustmenth, (xOffset / 2) - 6); - else - SetAdjustmentValue(adjustmentv, topLine - 3); - } else if (event->button == 5) { - // Wheel scrolling down (only GTK 1.x does it this way) - if (ctrl) - SetAdjustmentValue(adjustmenth, (xOffset / 2) + 6); - else - SetAdjustmentValue(adjustmentv, topLine + 3); - } - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } - return TRUE; -} - -gint ScintillaGTK::Press(GtkWidget *widget, GdkEventButton *event) { - if (event->window != WindowFromWidget(widget)) - return FALSE; - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - return sciThis->PressThis(event); -} - -gint ScintillaGTK::MouseRelease(GtkWidget *widget, GdkEventButton *event) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - try { - //Platform::DebugPrintf("Release %x %d %d\n",sciThis,event->time,event->state); - if (!sciThis->HaveMouseCapture()) - return FALSE; - if (event->button == 1) { - Point pt; - pt.x = int(event->x); - pt.y = int(event->y); - //Platform::DebugPrintf("Up %x %x %d %d %d\n", - // sciThis,event->window,event->time, pt.x, pt.y); - if (event->window != PWindow(sciThis->wMain)) - // If mouse released on scroll bar then the position is relative to the - // scrollbar, not the drawing window so just repeat the most recent point. - pt = sciThis->ptMouseLast; - sciThis->ButtonUp(pt, event->time, (event->state & 4) != 0); - } - } catch (...) { - sciThis->errorStatus = SC_STATUS_FAILURE; - } - return FALSE; -} - -// win32gtk and GTK >= 2 use SCROLL_* events instead of passing the -// button4/5/6/7 events to the GTK app -gint ScintillaGTK::ScrollEvent(GtkWidget *widget, - GdkEventScroll *event) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - try { - - if (widget == NULL || event == NULL) - return FALSE; - - // Compute amount and direction to scroll (even tho on win32 there is - // intensity of scrolling info in the native message, gtk doesn't - // support this so we simulate similarly adaptive scrolling) - // Note that this is disabled on OS X (Darwin) where the X11 server already has - // and adaptive scrolling algorithm that fights with this one - int cLineScroll; -#if defined(__MWERKS__) || defined(__APPLE_CPP__) || defined(__APPLE_CC__) - cLineScroll = sciThis->linesPerScroll; - if (cLineScroll == 0) - cLineScroll = 4; - sciThis->wheelMouseIntensity = cLineScroll; -#else - int timeDelta = 1000000; - GTimeVal curTime; - g_get_current_time(&curTime); - if (curTime.tv_sec == sciThis->lastWheelMouseTime.tv_sec) - timeDelta = curTime.tv_usec - sciThis->lastWheelMouseTime.tv_usec; - else if (curTime.tv_sec == sciThis->lastWheelMouseTime.tv_sec + 1) - timeDelta = 1000000 + (curTime.tv_usec - sciThis->lastWheelMouseTime.tv_usec); - if ((event->direction == sciThis->lastWheelMouseDirection) && (timeDelta < 250000)) { - if (sciThis->wheelMouseIntensity < 12) - sciThis->wheelMouseIntensity++; - cLineScroll = sciThis->wheelMouseIntensity; - } else { - cLineScroll = sciThis->linesPerScroll; - if (cLineScroll == 0) - cLineScroll = 4; - sciThis->wheelMouseIntensity = cLineScroll; - } -#endif - if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_LEFT) { - cLineScroll *= -1; - } - g_get_current_time(&sciThis->lastWheelMouseTime); - sciThis->lastWheelMouseDirection = event->direction; - - // Note: Unpatched versions of win32gtk don't set the 'state' value so - // only regular scrolling is supported there. Also, unpatched win32gtk - // issues spurious button 2 mouse events during wheeling, which can cause - // problems (a patch for both was submitted by archaeopteryx.com on 13Jun2001) - - // Data zoom not supported - if (event->state & GDK_SHIFT_MASK) { - return FALSE; - } - - // Horizontal scrolling - if (event->direction == GDK_SCROLL_LEFT || event->direction == GDK_SCROLL_RIGHT) { - sciThis->HorizontalScrollTo(sciThis->xOffset + cLineScroll); - - // Text font size zoom - } else if (event->state & GDK_CONTROL_MASK) { - if (cLineScroll < 0) { - sciThis->KeyCommand(SCI_ZOOMIN); - } else { - sciThis->KeyCommand(SCI_ZOOMOUT); - } - - // Regular scrolling - } else { - sciThis->ScrollTo(sciThis->topLine + cLineScroll); - } - return TRUE; - } catch (...) { - sciThis->errorStatus = SC_STATUS_FAILURE; - } - return FALSE; -} - -gint ScintillaGTK::Motion(GtkWidget *widget, GdkEventMotion *event) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - try { - //Platform::DebugPrintf("Motion %x %d\n",sciThis,event->time); - if (event->window != WindowFromWidget(widget)) - return FALSE; - int x = 0; - int y = 0; - GdkModifierType state; - if (event->is_hint) { - gdk_window_get_pointer(event->window, &x, &y, &state); - } else { - x = static_cast(event->x); - y = static_cast(event->y); - state = static_cast(event->state); - } - //Platform::DebugPrintf("Move %x %x %d %c %d %d\n", - // sciThis,event->window,event->time,event->is_hint? 'h' :'.', x, y); - Point pt(x, y); - sciThis->ButtonMove(pt); - } catch (...) { - sciThis->errorStatus = SC_STATUS_FAILURE; - } - return FALSE; -} - -// Map the keypad keys to their equivalent functions -static int KeyTranslate(int keyIn) { - switch (keyIn) { -#if GTK_CHECK_VERSION(3,0,0) - case GDK_KEY_ISO_Left_Tab: - return SCK_TAB; - case GDK_KEY_KP_Down: - return SCK_DOWN; - case GDK_KEY_KP_Up: - return SCK_UP; - case GDK_KEY_KP_Left: - return SCK_LEFT; - case GDK_KEY_KP_Right: - return SCK_RIGHT; - case GDK_KEY_KP_Home: - return SCK_HOME; - case GDK_KEY_KP_End: - return SCK_END; - case GDK_KEY_KP_Page_Up: - return SCK_PRIOR; - case GDK_KEY_KP_Page_Down: - return SCK_NEXT; - case GDK_KEY_KP_Delete: - return SCK_DELETE; - case GDK_KEY_KP_Insert: - return SCK_INSERT; - case GDK_KEY_KP_Enter: - return SCK_RETURN; - - case GDK_KEY_Down: - return SCK_DOWN; - case GDK_KEY_Up: - return SCK_UP; - case GDK_KEY_Left: - return SCK_LEFT; - case GDK_KEY_Right: - return SCK_RIGHT; - case GDK_KEY_Home: - return SCK_HOME; - case GDK_KEY_End: - return SCK_END; - case GDK_KEY_Page_Up: - return SCK_PRIOR; - case GDK_KEY_Page_Down: - return SCK_NEXT; - case GDK_KEY_Delete: - return SCK_DELETE; - case GDK_KEY_Insert: - return SCK_INSERT; - case GDK_KEY_Escape: - return SCK_ESCAPE; - case GDK_KEY_BackSpace: - return SCK_BACK; - case GDK_KEY_Tab: - return SCK_TAB; - case GDK_KEY_Return: - return SCK_RETURN; - case GDK_KEY_KP_Add: - return SCK_ADD; - case GDK_KEY_KP_Subtract: - return SCK_SUBTRACT; - case GDK_KEY_KP_Divide: - return SCK_DIVIDE; - case GDK_KEY_Super_L: - return SCK_WIN; - case GDK_KEY_Super_R: - return SCK_RWIN; - case GDK_KEY_Menu: - return SCK_MENU; - -#else - - case GDK_ISO_Left_Tab: - return SCK_TAB; - case GDK_KP_Down: - return SCK_DOWN; - case GDK_KP_Up: - return SCK_UP; - case GDK_KP_Left: - return SCK_LEFT; - case GDK_KP_Right: - return SCK_RIGHT; - case GDK_KP_Home: - return SCK_HOME; - case GDK_KP_End: - return SCK_END; - case GDK_KP_Page_Up: - return SCK_PRIOR; - case GDK_KP_Page_Down: - return SCK_NEXT; - case GDK_KP_Delete: - return SCK_DELETE; - case GDK_KP_Insert: - return SCK_INSERT; - case GDK_KP_Enter: - return SCK_RETURN; - - case GDK_Down: - return SCK_DOWN; - case GDK_Up: - return SCK_UP; - case GDK_Left: - return SCK_LEFT; - case GDK_Right: - return SCK_RIGHT; - case GDK_Home: - return SCK_HOME; - case GDK_End: - return SCK_END; - case GDK_Page_Up: - return SCK_PRIOR; - case GDK_Page_Down: - return SCK_NEXT; - case GDK_Delete: - return SCK_DELETE; - case GDK_Insert: - return SCK_INSERT; - case GDK_Escape: - return SCK_ESCAPE; - case GDK_BackSpace: - return SCK_BACK; - case GDK_Tab: - return SCK_TAB; - case GDK_Return: - return SCK_RETURN; - case GDK_KP_Add: - return SCK_ADD; - case GDK_KP_Subtract: - return SCK_SUBTRACT; - case GDK_KP_Divide: - return SCK_DIVIDE; - case GDK_Super_L: - return SCK_WIN; - case GDK_Super_R: - return SCK_RWIN; - case GDK_Menu: - return SCK_MENU; -#endif - default: - return keyIn; - } -} - -gboolean ScintillaGTK::KeyThis(GdkEventKey *event) { - try { - //fprintf(stderr, "SC-key: %d %x [%s]\n", - // event->keyval, event->state, (event->length > 0) ? event->string : "empty"); - if (gtk_im_context_filter_keypress(im_context, event)) { - return 1; - } - if (!event->keyval) { - return true; - } - - bool shift = (event->state & GDK_SHIFT_MASK) != 0; - bool ctrl = (event->state & GDK_CONTROL_MASK) != 0; - bool alt = (event->state & GDK_MOD1_MASK) != 0; - guint key = event->keyval; - if ((ctrl || alt) && (key < 128)) - key = toupper(key); -#if GTK_CHECK_VERSION(3,0,0) - else if (!ctrl && (key >= GDK_KEY_KP_Multiply && key <= GDK_KEY_KP_9)) -#else - else if (!ctrl && (key >= GDK_KP_Multiply && key <= GDK_KP_9)) -#endif - key &= 0x7F; - // Hack for keys over 256 and below command keys but makes Hungarian work. - // This will have to change for Unicode - else if (key >= 0xFE00) - key = KeyTranslate(key); - - bool consumed = false; -#if !(PLAT_GTK_MACOSX) - bool added = KeyDown(key, shift, ctrl, alt, &consumed) != 0; -#else - bool meta = ctrl; - ctrl = alt; - alt = (event->state & GDK_MOD5_MASK) != 0; - bool added = KeyDownWithModifiers(key, (shift ? SCI_SHIFT : 0) | - (ctrl ? SCI_CTRL : 0) | - (alt ? SCI_ALT : 0) | - (meta ? SCI_META : 0), &consumed) != 0; -#endif - if (!consumed) - consumed = added; - //fprintf(stderr, "SK-key: %d %x %x\n",event->keyval, event->state, consumed); - if (event->keyval == 0xffffff && event->length > 0) { - ClearSelection(); - if (pdoc->InsertCString(CurrentPosition(), event->string)) { - MovePositionTo(CurrentPosition() + event->length); - } - } - return consumed; - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } - return FALSE; -} - -gboolean ScintillaGTK::KeyPress(GtkWidget *widget, GdkEventKey *event) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - return sciThis->KeyThis(event); -} - -gboolean ScintillaGTK::KeyRelease(GtkWidget *widget, GdkEventKey *event) { - //Platform::DebugPrintf("SC-keyrel: %d %x %3s\n",event->keyval, event->state, event->string); - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - if (gtk_im_context_filter_keypress(sciThis->im_context, event)) { - return TRUE; - } - return FALSE; -} - -#if GTK_CHECK_VERSION(3,0,0) - -gboolean ScintillaGTK::DrawPreeditThis(GtkWidget *widget, cairo_t *cr) { - try { - gchar *str; - gint cursor_pos; - PangoAttrList *attrs; - - gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos); - PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str); - pango_layout_set_attributes(layout, attrs); - - cairo_move_to(cr, 0, 0); - pango_cairo_show_layout(cr, layout); - - g_free(str); - pango_attr_list_unref(attrs); - g_object_unref(layout); - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } - return TRUE; -} - -gboolean ScintillaGTK::DrawPreedit(GtkWidget *widget, cairo_t *cr, ScintillaGTK *sciThis) { - return sciThis->DrawPreeditThis(widget, cr); -} - -#else - -gboolean ScintillaGTK::ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose) { - try { - gchar *str; - gint cursor_pos; - PangoAttrList *attrs; - - gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos); - PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str); - pango_layout_set_attributes(layout, attrs); - - cairo_t *context = gdk_cairo_create(reinterpret_cast(WindowFromWidget(widget))); - cairo_move_to(context, 0, 0); - pango_cairo_show_layout(context, layout); - cairo_destroy(context); - g_free(str); - pango_attr_list_unref(attrs); - g_object_unref(layout); - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } - return TRUE; -} - -gboolean ScintillaGTK::ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis) { - return sciThis->ExposePreeditThis(widget, ose); -} - -#endif - -void ScintillaGTK::CommitThis(char *utfVal) { - try { - //~ fprintf(stderr, "Commit '%s'\n", utfVal); - if (IsUnicodeMode()) { - AddCharUTF(utfVal, strlen(utfVal)); - } else { - const char *source = CharacterSetID(); - if (*source) { - Converter conv(source, "UTF-8", true); - if (conv) { - char localeVal[4] = "\0\0\0"; - char *pin = utfVal; - size_t inLeft = strlen(utfVal); - char *pout = localeVal; - size_t outLeft = sizeof(localeVal); - size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft); - if (conversions != ((size_t)(-1))) { - *pout = '\0'; - for (int i = 0; localeVal[i]; i++) { - AddChar(localeVal[i]); - } - } else { - fprintf(stderr, "Conversion failed '%s'\n", utfVal); - } - } - } - } - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } -} - -void ScintillaGTK::Commit(GtkIMContext *, char *str, ScintillaGTK *sciThis) { - sciThis->CommitThis(str); -} - -void ScintillaGTK::PreeditChangedThis() { - try { - gchar *str; - PangoAttrList *attrs; - gint cursor_pos; - gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos); - if (strlen(str) > 0) { - PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str); - pango_layout_set_attributes(layout, attrs); - - gint w, h; - pango_layout_get_pixel_size(layout, &w, &h); - g_object_unref(layout); - - gint x, y; - gdk_window_get_origin(PWindow(wText), &x, &y); - - Point pt = PointMainCaret(); - if (pt.x < 0) - pt.x = 0; - if (pt.y < 0) - pt.y = 0; - - gtk_window_move(GTK_WINDOW(PWidget(wPreedit)), x + pt.x, y + pt.y); - gtk_window_resize(GTK_WINDOW(PWidget(wPreedit)), w, h); - gtk_widget_show(PWidget(wPreedit)); - gtk_widget_queue_draw_area(PWidget(wPreeditDraw), 0, 0, w, h); - } else { - gtk_widget_hide(PWidget(wPreedit)); - } - g_free(str); - pango_attr_list_unref(attrs); - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } -} - -void ScintillaGTK::PreeditChanged(GtkIMContext *, ScintillaGTK *sciThis) { - sciThis->PreeditChangedThis(); -} - -void ScintillaGTK::StyleSetText(GtkWidget *widget, GtkStyle *, void*) { - RealizeText(widget, NULL); -} - -void ScintillaGTK::RealizeText(GtkWidget *widget, void*) { - // Set NULL background to avoid automatic clearing so Scintilla responsible for all drawing - if (WindowFromWidget(widget)) { -#if GTK_CHECK_VERSION(3,0,0) - gdk_window_set_background_pattern(WindowFromWidget(widget), NULL); -#else - gdk_window_set_back_pixmap(WindowFromWidget(widget), NULL, FALSE); -#endif - } -} - -void ScintillaGTK::Destroy(GObject *object) { - try { - ScintillaObject *scio = reinterpret_cast(object); - // This avoids a double destruction - if (!scio->pscin) - return; - ScintillaGTK *sciThis = reinterpret_cast(scio->pscin); - //Platform::DebugPrintf("Destroying %x %x\n", sciThis, object); - sciThis->Finalise(); - - delete sciThis; - scio->pscin = 0; - } catch (...) { - // Its dead so nowhere to save the status - } -} - -#if GTK_CHECK_VERSION(3,0,0) - -gboolean ScintillaGTK::DrawTextThis(cairo_t *cr) { - try { - paintState = painting; - - rcPaint = GetClientRectangle(); - - PLATFORM_ASSERT(rgnUpdate == NULL); - rgnUpdate = cairo_copy_clip_rectangle_list(cr); - if (rgnUpdate && rgnUpdate->status != CAIRO_STATUS_SUCCESS) { - // If not successful then ignore - fprintf(stderr, "DrawTextThis failed to copy update region %d [%d]\n", rgnUpdate->status, rgnUpdate->num_rectangles); - cairo_rectangle_list_destroy(rgnUpdate); - rgnUpdate = 0; - } - - double x1, y1, x2, y2; - cairo_clip_extents(cr, &x1, &y1, &x2, &y2); - rcPaint.left = x1; - rcPaint.top = y1; - rcPaint.right = x2; - rcPaint.bottom = y2; - PRectangle rcClient = GetClientRectangle(); - paintingAllText = rcPaint.Contains(rcClient); - Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); - if (surfaceWindow) { - surfaceWindow->Init(cr, PWidget(wText)); - Paint(surfaceWindow, rcPaint); - surfaceWindow->Release(); - delete surfaceWindow; - } - if (paintState == paintAbandoned) { - // Painting area was insufficient to cover new styling or brace highlight positions - FullPaint(); - } - paintState = notPainting; - - if (rgnUpdate) { - cairo_rectangle_list_destroy(rgnUpdate); - } - rgnUpdate = 0; - paintState = notPainting; - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } - - return FALSE; -} - -gboolean ScintillaGTK::DrawText(GtkWidget *, cairo_t *cr, ScintillaGTK *sciThis) { - return sciThis->DrawTextThis(cr); -} - -gboolean ScintillaGTK::DrawThis(cairo_t *cr) { - try { - gtk_container_propagate_draw( - GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarh), cr); - gtk_container_propagate_draw( - GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarv), cr); - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } - return FALSE; -} - -gboolean ScintillaGTK::DrawMain(GtkWidget *widget, cairo_t *cr) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - return sciThis->DrawThis(cr); -} - -#else - -gboolean ScintillaGTK::ExposeTextThis(GtkWidget * /*widget*/, GdkEventExpose *ose) { - try { - paintState = painting; - - rcPaint.left = ose->area.x; - rcPaint.top = ose->area.y; - rcPaint.right = ose->area.x + ose->area.width; - rcPaint.bottom = ose->area.y + ose->area.height; - - PLATFORM_ASSERT(rgnUpdate == NULL); - rgnUpdate = gdk_region_copy(ose->region); - PRectangle rcClient = GetClientRectangle(); - paintingAllText = rcPaint.Contains(rcClient); - Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); - if (surfaceWindow) { - cairo_t *cr = gdk_cairo_create(PWindow(wText)); - surfaceWindow->Init(cr, PWidget(wText)); - Paint(surfaceWindow, rcPaint); - surfaceWindow->Release(); - delete surfaceWindow; - cairo_destroy(cr); - } - if (paintState == paintAbandoned) { - // Painting area was insufficient to cover new styling or brace highlight positions - FullPaint(); - } - paintState = notPainting; - - if (rgnUpdate) { - gdk_region_destroy(rgnUpdate); - } - rgnUpdate = 0; - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } - - return FALSE; -} - -gboolean ScintillaGTK::ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis) { - return sciThis->ExposeTextThis(widget, ose); -} - -gboolean ScintillaGTK::ExposeMain(GtkWidget *widget, GdkEventExpose *ose) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - //Platform::DebugPrintf("Expose Main %0d,%0d %0d,%0d\n", - //ose->area.x, ose->area.y, ose->area.width, ose->area.height); - return sciThis->Expose(widget, ose); -} - -gboolean ScintillaGTK::Expose(GtkWidget *, GdkEventExpose *ose) { - try { - //fprintf(stderr, "Expose %0d,%0d %0d,%0d\n", - //ose->area.x, ose->area.y, ose->area.width, ose->area.height); - - // The text is painted in ExposeText - gtk_container_propagate_expose( - GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarh), ose); - gtk_container_propagate_expose( - GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarv), ose); - - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } - return FALSE; -} - -#endif - -void ScintillaGTK::ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis) { - try { -#if GTK_CHECK_VERSION(3,0,0) - sciThis->ScrollTo(static_cast(gtk_adjustment_get_value(adj)), false); -#else - sciThis->ScrollTo(static_cast(adj->value), false); -#endif - } catch (...) { - sciThis->errorStatus = SC_STATUS_FAILURE; - } -} - -void ScintillaGTK::ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis) { - try { -#if GTK_CHECK_VERSION(3,0,0) - sciThis->HorizontalScrollTo(static_cast(gtk_adjustment_get_value(adj) * 2)); -#else - sciThis->HorizontalScrollTo(static_cast(adj->value * 2)); -#endif - } catch (...) { - sciThis->errorStatus = SC_STATUS_FAILURE; - } -} - -void ScintillaGTK::SelectionReceived(GtkWidget *widget, - GtkSelectionData *selection_data, guint) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - //Platform::DebugPrintf("Selection received\n"); - sciThis->ReceivedSelection(selection_data); -} - -void ScintillaGTK::SelectionGet(GtkWidget *widget, - GtkSelectionData *selection_data, guint info, guint) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - try { - //Platform::DebugPrintf("Selection get\n"); - if (SelectionOfGSD(selection_data) == GDK_SELECTION_PRIMARY) { - if (sciThis->primary.s == NULL) { - sciThis->CopySelectionRange(&sciThis->primary); - } - sciThis->GetSelection(selection_data, info, &sciThis->primary); - } - } catch (...) { - sciThis->errorStatus = SC_STATUS_FAILURE; - } -} - -gint ScintillaGTK::SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - //Platform::DebugPrintf("Selection clear\n"); - sciThis->UnclaimSelection(selection_event); - if (GTK_WIDGET_CLASS(sciThis->parentClass)->selection_clear_event) { - return GTK_WIDGET_CLASS(sciThis->parentClass)->selection_clear_event(widget, selection_event); - } - return TRUE; -} - -void ScintillaGTK::DragBegin(GtkWidget *, GdkDragContext *) { - //Platform::DebugPrintf("DragBegin\n"); -} - -gboolean ScintillaGTK::DragMotionThis(GdkDragContext *context, - gint x, gint y, guint dragtime) { - try { - Point npt(x, y); - SetDragPosition(SPositionFromLocation(npt, false, false, UserVirtualSpace())); -#if GTK_CHECK_VERSION(3,0,0) - GdkDragAction preferredAction = gdk_drag_context_get_suggested_action(context); - GdkDragAction actions = gdk_drag_context_get_actions(context); -#else - GdkDragAction preferredAction = context->suggested_action; - GdkDragAction actions = context->actions; -#endif - SelectionPosition pos = SPositionFromLocation(npt); - if ((inDragDrop == ddDragging) && (PositionInSelection(pos.Position()))) { - // Avoid dragging selection onto itself as that produces a move - // with no real effect but which creates undo actions. - preferredAction = static_cast(0); - } else if (actions == static_cast - (GDK_ACTION_COPY | GDK_ACTION_MOVE)) { - preferredAction = GDK_ACTION_MOVE; - } - gdk_drag_status(context, preferredAction, dragtime); - } catch (...) { - errorStatus = SC_STATUS_FAILURE; - } - return FALSE; -} - -gboolean ScintillaGTK::DragMotion(GtkWidget *widget, GdkDragContext *context, - gint x, gint y, guint dragtime) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - return sciThis->DragMotionThis(context, x, y, dragtime); -} - -void ScintillaGTK::DragLeave(GtkWidget *widget, GdkDragContext * /*context*/, guint) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - try { - sciThis->SetDragPosition(SelectionPosition(invalidPosition)); - //Platform::DebugPrintf("DragLeave %x\n", sciThis); - } catch (...) { - sciThis->errorStatus = SC_STATUS_FAILURE; - } -} - -void ScintillaGTK::DragEnd(GtkWidget *widget, GdkDragContext * /*context*/) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - try { - // If drag did not result in drop here or elsewhere - if (!sciThis->dragWasDropped) - sciThis->SetEmptySelection(sciThis->posDrag); - sciThis->SetDragPosition(SelectionPosition(invalidPosition)); - //Platform::DebugPrintf("DragEnd %x %d\n", sciThis, sciThis->dragWasDropped); - sciThis->inDragDrop = ddNone; - } catch (...) { - sciThis->errorStatus = SC_STATUS_FAILURE; - } -} - -gboolean ScintillaGTK::Drop(GtkWidget *widget, GdkDragContext * /*context*/, - gint, gint, guint) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - try { - //Platform::DebugPrintf("Drop %x\n", sciThis); - sciThis->SetDragPosition(SelectionPosition(invalidPosition)); - } catch (...) { - sciThis->errorStatus = SC_STATUS_FAILURE; - } - return FALSE; -} - -void ScintillaGTK::DragDataReceived(GtkWidget *widget, GdkDragContext * /*context*/, - gint, gint, GtkSelectionData *selection_data, guint /*info*/, guint) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - try { - sciThis->ReceivedDrop(selection_data); - sciThis->SetDragPosition(SelectionPosition(invalidPosition)); - } catch (...) { - sciThis->errorStatus = SC_STATUS_FAILURE; - } -} - -void ScintillaGTK::DragDataGet(GtkWidget *widget, GdkDragContext *context, - GtkSelectionData *selection_data, guint info, guint) { - ScintillaGTK *sciThis = ScintillaFromWidget(widget); - try { - sciThis->dragWasDropped = true; - if (!sciThis->sel.Empty()) { - sciThis->GetSelection(selection_data, info, &sciThis->drag); - } -#if GTK_CHECK_VERSION(3,0,0) - GdkDragAction action = gdk_drag_context_get_selected_action(context); -#else - GdkDragAction action = context->action; -#endif - if (action == GDK_ACTION_MOVE) { - for (size_t r=0; rsel.Count(); r++) { - if (sciThis->posDrop >= sciThis->sel.Range(r).Start()) { - if (sciThis->posDrop > sciThis->sel.Range(r).End()) { - sciThis->posDrop.Add(-sciThis->sel.Range(r).Length()); - } else { - sciThis->posDrop.Add(-SelectionRange(sciThis->posDrop, sciThis->sel.Range(r).Start()).Length()); - } - } - } - sciThis->ClearSelection(); - } - sciThis->SetDragPosition(SelectionPosition(invalidPosition)); - } catch (...) { - sciThis->errorStatus = SC_STATUS_FAILURE; - } -} - -int ScintillaGTK::TimeOut(ScintillaGTK *sciThis) { - sciThis->Tick(); - return 1; -} - -gboolean ScintillaGTK::IdleCallback(ScintillaGTK *sciThis) { - // Idler will be automatically stopped, if there is nothing - // to do while idle. - gdk_threads_enter(); - bool ret = sciThis->Idle(); - if (ret == false) { - // FIXME: This will remove the idler from GTK, we don't want to - // remove it as it is removed automatically when this function - // returns false (although, it should be harmless). - sciThis->SetIdle(false); - } - gdk_threads_leave(); - return ret; -} - -gboolean ScintillaGTK::StyleIdle(ScintillaGTK *sciThis) { - gdk_threads_enter(); - sciThis->IdleStyling(); - gdk_threads_leave(); - // Idler will be automatically stopped - return FALSE; -} - -void ScintillaGTK::QueueStyling(int upTo) { - Editor::QueueStyling(upTo); - if (!styleNeeded.active) { - // Only allow one style needed to be queued - styleNeeded.active = true; - g_idle_add_full(G_PRIORITY_HIGH_IDLE, - reinterpret_cast(StyleIdle), this, NULL); - } -} - -void ScintillaGTK::PopUpCB(GtkMenuItem *menuItem, ScintillaGTK *sciThis) { - guint action = (sptr_t)(g_object_get_data(G_OBJECT(menuItem), "CmdNum")); - if (action) { - sciThis->Command(action); - } -} - -gboolean ScintillaGTK::PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis) { - try { - if (event->window != WindowFromWidget(widget)) - return FALSE; - if (event->type != GDK_BUTTON_PRESS) - return FALSE; - Point pt; - pt.x = int(event->x); - pt.y = int(event->y); - sciThis->ct.MouseClick(pt); - sciThis->CallTipClick(); - } catch (...) { - } - return TRUE; -} - -#if GTK_CHECK_VERSION(3,0,0) - -gboolean ScintillaGTK::DrawCT(GtkWidget *widget, cairo_t *cr, CallTip *ctip) { - try { - Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); - if (surfaceWindow) { - surfaceWindow->Init(cr, widget); - surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ctip->codePage); - surfaceWindow->SetDBCSMode(ctip->codePage); - ctip->PaintCT(surfaceWindow); - surfaceWindow->Release(); - delete surfaceWindow; - } - } catch (...) { - // No pointer back to Scintilla to save status - } - return TRUE; -} - -#else - -gboolean ScintillaGTK::ExposeCT(GtkWidget *widget, GdkEventExpose * /*ose*/, CallTip *ctip) { - try { - Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); - if (surfaceWindow) { - cairo_t *cr = gdk_cairo_create(WindowFromWidget(widget)); - surfaceWindow->Init(cr, widget); - surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ctip->codePage); - surfaceWindow->SetDBCSMode(ctip->codePage); - ctip->PaintCT(surfaceWindow); - surfaceWindow->Release(); - delete surfaceWindow; - cairo_destroy(cr); - } - } catch (...) { - // No pointer back to Scintilla to save status - } - return TRUE; -} - -#endif - -sptr_t ScintillaGTK::DirectFunction( - ScintillaGTK *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam) { - return sciThis->WndProc(iMessage, wParam, lParam); -} - -sptr_t scintilla_send_message(ScintillaObject *sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam) { - ScintillaGTK *psci = reinterpret_cast(sci->pscin); - return psci->WndProc(iMessage, wParam, lParam); -} - -static void scintilla_class_init(ScintillaClass *klass); -static void scintilla_init(ScintillaObject *sci); - -extern void Platform_Initialise(); -extern void Platform_Finalise(); - -GType scintilla_get_type() { - static GType scintilla_type = 0; - try { - - if (!scintilla_type) { - scintilla_type = g_type_from_name("Scintilla"); - if (!scintilla_type) { - static GTypeInfo scintilla_info = { - (guint16) sizeof (ScintillaClass), - NULL, //(GBaseInitFunc) - NULL, //(GBaseFinalizeFunc) - (GClassInitFunc) scintilla_class_init, - NULL, //(GClassFinalizeFunc) - NULL, //gconstpointer data - (guint16) sizeof (ScintillaObject), - 0, //n_preallocs - (GInstanceInitFunc) scintilla_init, - NULL //(GTypeValueTable*) - }; - - scintilla_type = g_type_register_static( - GTK_TYPE_CONTAINER, "Scintilla", &scintilla_info, (GTypeFlags) 0); - } - } - - } catch (...) { - } - return scintilla_type; -} - -void ScintillaGTK::ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class) { - Platform_Initialise(); -#ifdef SCI_LEXER - Scintilla_LinkLexers(); -#endif - atomClipboard = gdk_atom_intern("CLIPBOARD", FALSE); - atomUTF8 = gdk_atom_intern("UTF8_STRING", FALSE); - atomString = GDK_SELECTION_TYPE_STRING; - atomUriList = gdk_atom_intern("text/uri-list", FALSE); - atomDROPFILES_DND = gdk_atom_intern("DROPFILES_DND", FALSE); - - // Define default signal handlers for the class: Could move more - // of the signal handlers here (those that currently attached to wDraw - // in Initialise() may require coordinate translation?) - - object_class->finalize = Destroy; -#if GTK_CHECK_VERSION(3,0,0) - widget_class->get_preferred_width = GetPreferredWidth; - widget_class->get_preferred_height = GetPreferredHeight; -#else - widget_class->size_request = SizeRequest; -#endif - widget_class->size_allocate = SizeAllocate; -#if GTK_CHECK_VERSION(3,0,0) - widget_class->draw = DrawMain; -#else - widget_class->expose_event = ExposeMain; -#endif - widget_class->motion_notify_event = Motion; - widget_class->button_press_event = Press; - widget_class->button_release_event = MouseRelease; - widget_class->scroll_event = ScrollEvent; - widget_class->key_press_event = KeyPress; - widget_class->key_release_event = KeyRelease; - widget_class->focus_in_event = FocusIn; - widget_class->focus_out_event = FocusOut; - widget_class->selection_received = SelectionReceived; - widget_class->selection_get = SelectionGet; - widget_class->selection_clear_event = SelectionClear; - - widget_class->drag_data_received = DragDataReceived; - widget_class->drag_motion = DragMotion; - widget_class->drag_leave = DragLeave; - widget_class->drag_end = DragEnd; - widget_class->drag_drop = Drop; - widget_class->drag_data_get = DragDataGet; - - widget_class->realize = Realize; - widget_class->unrealize = UnRealize; - widget_class->map = Map; - widget_class->unmap = UnMap; - - container_class->forall = MainForAll; -} - -#define SIG_MARSHAL scintilla_marshal_NONE__INT_POINTER -#define MARSHAL_ARGUMENTS G_TYPE_INT, G_TYPE_POINTER - -static void scintilla_class_init(ScintillaClass *klass) { - try { - OBJECT_CLASS *object_class = (OBJECT_CLASS*) klass; - GtkWidgetClass *widget_class = (GtkWidgetClass*) klass; - GtkContainerClass *container_class = (GtkContainerClass*) klass; - - GSignalFlags sigflags = GSignalFlags(G_SIGNAL_ACTION | G_SIGNAL_RUN_LAST); - scintilla_signals[COMMAND_SIGNAL] = g_signal_new( - "command", - G_TYPE_FROM_CLASS(object_class), - sigflags, - G_STRUCT_OFFSET(ScintillaClass, command), - NULL, //(GSignalAccumulator) - NULL, //(gpointer) - SIG_MARSHAL, - G_TYPE_NONE, - 2, MARSHAL_ARGUMENTS); - - scintilla_signals[NOTIFY_SIGNAL] = g_signal_new( - SCINTILLA_NOTIFY, - G_TYPE_FROM_CLASS(object_class), - sigflags, - G_STRUCT_OFFSET(ScintillaClass, notify), - NULL, - NULL, - SIG_MARSHAL, - G_TYPE_NONE, - 2, MARSHAL_ARGUMENTS); - - klass->command = NULL; - klass->notify = NULL; - - ScintillaGTK::ClassInit(object_class, widget_class, container_class); - } catch (...) { - } -} - -static void scintilla_init(ScintillaObject *sci) { - try { -#if GTK_CHECK_VERSION(2,20,0) - gtk_widget_set_can_focus(GTK_WIDGET(sci), TRUE); -#else - GTK_WIDGET_SET_FLAGS(sci, GTK_CAN_FOCUS); -#endif - sci->pscin = new ScintillaGTK(sci); - } catch (...) { - } -} - -GtkWidget* scintilla_new() { - return GTK_WIDGET(g_object_new(scintilla_get_type(), NULL)); -} - -void scintilla_set_id(ScintillaObject *sci, uptr_t id) { - ScintillaGTK *psci = reinterpret_cast(sci->pscin); - psci->ctrlID = id; -} - -void scintilla_release_resources(void) { - try { - Platform_Finalise(); - } catch (...) { - } -} +// Scintilla source code edit control +// ScintillaGTK.cxx - GTK+ specific subclass of ScintillaBase +// Copyright 1998-2004 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "Platform.h" + +#if PLAT_GTK_WIN32 +#include +#endif + +#include "ILexer.h" +#include "Scintilla.h" +#include "ScintillaWidget.h" +#ifdef SCI_LEXER +#include "SciLexer.h" +#endif +#include "SVector.h" +#include "SplitVector.h" +#include "Partitioning.h" +#include "RunStyles.h" +#include "ContractionState.h" +#include "CellBuffer.h" +#include "CallTip.h" +#include "KeyMap.h" +#include "Indicator.h" +#include "XPM.h" +#include "LineMarker.h" +#include "Style.h" +#include "AutoComplete.h" +#include "ViewStyle.h" +#include "Decoration.h" +#include "CharClassify.h" +#include "Document.h" +#include "Selection.h" +#include "PositionCache.h" +#include "Editor.h" +#include "ScintillaBase.h" +#include "UniConversion.h" + +#include "scintilla-marshal.h" + +#ifdef SCI_LEXER +#include +#include +#include "LexerModule.h" +#include "ExternalLexer.h" +#endif + +#include "Converter.h" + +#if GTK_CHECK_VERSION(2,20,0) +#define IS_WIDGET_REALIZED(w) (gtk_widget_get_realized(GTK_WIDGET(w))) +#define IS_WIDGET_MAPPED(w) (gtk_widget_get_mapped(GTK_WIDGET(w))) +#define IS_WIDGET_VISIBLE(w) (gtk_widget_get_visible(GTK_WIDGET(w))) +#else +#define IS_WIDGET_REALIZED(w) (GTK_WIDGET_REALIZED(w)) +#define IS_WIDGET_MAPPED(w) (GTK_WIDGET_MAPPED(w)) +#define IS_WIDGET_VISIBLE(w) (GTK_WIDGET_VISIBLE(w)) +#endif + +static GdkWindow *WindowFromWidget(GtkWidget *w) { +#if GTK_CHECK_VERSION(3,0,0) + return gtk_widget_get_window(w); +#else + return w->window; +#endif +} + +static GdkWindow *PWindow(const Window &w) { + GtkWidget *widget = reinterpret_cast(w.GetID()); +#if GTK_CHECK_VERSION(3,0,0) + return gtk_widget_get_window(widget); +#else + return widget->window; +#endif +} + +#ifdef _MSC_VER +// Constant conditional expressions are because of GTK+ headers +#pragma warning(disable: 4127) +// Ignore unreferenced local functions in GTK+ headers +#pragma warning(disable: 4505) +#endif + +#define OBJECT_CLASS GObjectClass + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +extern char *UTF8FromLatin1(const char *s, int &len); + +class ScintillaGTK : public ScintillaBase { + _ScintillaObject *sci; + Window wText; + Window scrollbarv; + Window scrollbarh; + GtkAdjustment *adjustmentv; + GtkAdjustment *adjustmenth; + int scrollBarWidth; + int scrollBarHeight; + + SelectionText primary; + + GdkEventButton evbtn; + bool capturedMouse; + bool dragWasDropped; + int lastKey; + int rectangularSelectionModifier; + + GtkWidgetClass *parentClass; + + static GdkAtom atomClipboard; + static GdkAtom atomUTF8; + static GdkAtom atomString; + static GdkAtom atomUriList; + static GdkAtom atomDROPFILES_DND; + GdkAtom atomSought; + +#if PLAT_GTK_WIN32 + CLIPFORMAT cfColumnSelect; +#endif + + Window wPreedit; + Window wPreeditDraw; + GtkIMContext *im_context; + + // Wheel mouse support + unsigned int linesPerScroll; + GTimeVal lastWheelMouseTime; + gint lastWheelMouseDirection; + gint wheelMouseIntensity; + +#if GTK_CHECK_VERSION(3,0,0) + cairo_rectangle_list_t *rgnUpdate; +#else + GdkRegion *rgnUpdate; +#endif + + // Private so ScintillaGTK objects can not be copied + ScintillaGTK(const ScintillaGTK &); + ScintillaGTK &operator=(const ScintillaGTK &); + +public: + ScintillaGTK(_ScintillaObject *sci_); + virtual ~ScintillaGTK(); + static void ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class); +private: + virtual void Initialise(); + virtual void Finalise(); + virtual void DisplayCursor(Window::Cursor c); + virtual bool DragThreshold(Point ptStart, Point ptNow); + virtual void StartDrag(); + int TargetAsUTF8(char *text); + int EncodedFromUTF8(char *utf8, char *encoded); + virtual bool ValidCodePage(int codePage) const; +public: // Public for scintilla_send_message + virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); +private: + virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + virtual void SetTicking(bool on); + virtual bool SetIdle(bool on); + virtual void SetMouseCapture(bool on); + virtual bool HaveMouseCapture(); + virtual bool PaintContains(PRectangle rc); + void FullPaint(); + virtual PRectangle GetClientRectangle(); + void SyncPaint(PRectangle rc); + virtual void ScrollText(int linesToMove); + virtual void SetVerticalScrollPos(); + virtual void SetHorizontalScrollPos(); + virtual bool ModifyScrollBars(int nMax, int nPage); + void ReconfigureScrollBars(); + virtual void NotifyChange(); + virtual void NotifyFocus(bool focus); + virtual void NotifyParent(SCNotification scn); + void NotifyKey(int key, int modifiers); + void NotifyURIDropped(const char *list); + const char *CharacterSetID() const; + virtual CaseFolder *CaseFolderForEncoding(); + virtual std::string CaseMapString(const std::string &s, int caseMapping); + virtual int KeyDefault(int key, int modifiers); + virtual void CopyToClipboard(const SelectionText &selectedText); + virtual void Copy(); + virtual void Paste(); + virtual void CreateCallTipWindow(PRectangle rc); + virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true); + bool OwnPrimarySelection(); + virtual void ClaimSelection(); + void GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText); + void ReceivedSelection(GtkSelectionData *selection_data); + void ReceivedDrop(GtkSelectionData *selection_data); + static void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected); + void StoreOnClipboard(SelectionText *clipText); + static void ClipboardGetSelection(GtkClipboard* clip, GtkSelectionData *selection_data, guint info, void *data); + static void ClipboardClearSelection(GtkClipboard* clip, void *data); + + void UnclaimSelection(GdkEventSelection *selection_event); + void Resize(int width, int height); + + // Callback functions + void RealizeThis(GtkWidget *widget); + static void Realize(GtkWidget *widget); + void UnRealizeThis(GtkWidget *widget); + static void UnRealize(GtkWidget *widget); + void MapThis(); + static void Map(GtkWidget *widget); + void UnMapThis(); + static void UnMap(GtkWidget *widget); + gint FocusInThis(GtkWidget *widget); + static gint FocusIn(GtkWidget *widget, GdkEventFocus *event); + gint FocusOutThis(GtkWidget *widget); + static gint FocusOut(GtkWidget *widget, GdkEventFocus *event); + static void SizeRequest(GtkWidget *widget, GtkRequisition *requisition); + static void GetPreferredWidth(GtkWidget *widget, gint *minimalWidth, gint *naturalWidth); + static void GetPreferredHeight(GtkWidget *widget, gint *minimalHeight, gint *naturalHeight); + static void SizeAllocate(GtkWidget *widget, GtkAllocation *allocation); +#if GTK_CHECK_VERSION(3,0,0) + gboolean DrawTextThis(cairo_t *cr); + static gboolean DrawText(GtkWidget *widget, cairo_t *cr, ScintillaGTK *sciThis); + gboolean DrawThis(cairo_t *cr); + static gboolean DrawMain(GtkWidget *widget, cairo_t *cr); +#else + gboolean ExposeTextThis(GtkWidget *widget, GdkEventExpose *ose); + static gboolean ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis); + gboolean Expose(GtkWidget *widget, GdkEventExpose *ose); + static gboolean ExposeMain(GtkWidget *widget, GdkEventExpose *ose); +#endif + static void Draw(GtkWidget *widget, GdkRectangle *area); + void ForAll(GtkCallback callback, gpointer callback_data); + static void MainForAll(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); + + static void ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis); + static void ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis); + gint PressThis(GdkEventButton *event); + static gint Press(GtkWidget *widget, GdkEventButton *event); + static gint MouseRelease(GtkWidget *widget, GdkEventButton *event); + static gint ScrollEvent(GtkWidget *widget, GdkEventScroll *event); + static gint Motion(GtkWidget *widget, GdkEventMotion *event); + gboolean KeyThis(GdkEventKey *event); + static gboolean KeyPress(GtkWidget *widget, GdkEventKey *event); + static gboolean KeyRelease(GtkWidget *widget, GdkEventKey *event); +#if GTK_CHECK_VERSION(3,0,0) + gboolean DrawPreeditThis(GtkWidget *widget, cairo_t *cr); + static gboolean DrawPreedit(GtkWidget *widget, cairo_t *cr, ScintillaGTK *sciThis); +#else + gboolean ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose); + static gboolean ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis); +#endif + void CommitThis(char *str); + static void Commit(GtkIMContext *context, char *str, ScintillaGTK *sciThis); + void PreeditChangedThis(); + static void PreeditChanged(GtkIMContext *context, ScintillaGTK *sciThis); + static void StyleSetText(GtkWidget *widget, GtkStyle *previous, void*); + static void RealizeText(GtkWidget *widget, void*); + static void Destroy(GObject *object); + static void SelectionReceived(GtkWidget *widget, GtkSelectionData *selection_data, + guint time); + static void SelectionGet(GtkWidget *widget, GtkSelectionData *selection_data, + guint info, guint time); + static gint SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event); + static void DragBegin(GtkWidget *widget, GdkDragContext *context); + gboolean DragMotionThis(GdkDragContext *context, gint x, gint y, guint dragtime); + static gboolean DragMotion(GtkWidget *widget, GdkDragContext *context, + gint x, gint y, guint dragtime); + static void DragLeave(GtkWidget *widget, GdkDragContext *context, + guint time); + static void DragEnd(GtkWidget *widget, GdkDragContext *context); + static gboolean Drop(GtkWidget *widget, GdkDragContext *context, + gint x, gint y, guint time); + static void DragDataReceived(GtkWidget *widget, GdkDragContext *context, + gint x, gint y, GtkSelectionData *selection_data, guint info, guint time); + static void DragDataGet(GtkWidget *widget, GdkDragContext *context, + GtkSelectionData *selection_data, guint info, guint time); + static gboolean TimeOut(ScintillaGTK *sciThis); + static gboolean IdleCallback(ScintillaGTK *sciThis); + static gboolean StyleIdle(ScintillaGTK *sciThis); + virtual void QueueStyling(int upTo); + static void PopUpCB(GtkMenuItem *menuItem, ScintillaGTK *sciThis); + +#if GTK_CHECK_VERSION(3,0,0) + static gboolean DrawCT(GtkWidget *widget, cairo_t *cr, CallTip *ctip); +#else + static gboolean ExposeCT(GtkWidget *widget, GdkEventExpose *ose, CallTip *ct); +#endif + static gboolean PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis); + + static sptr_t DirectFunction(ScintillaGTK *sciThis, + unsigned int iMessage, uptr_t wParam, sptr_t lParam); +}; + +enum { + COMMAND_SIGNAL, + NOTIFY_SIGNAL, + LAST_SIGNAL +}; + +static gint scintilla_signals[LAST_SIGNAL] = { 0 }; + +enum { + TARGET_STRING, + TARGET_TEXT, + TARGET_COMPOUND_TEXT, + TARGET_UTF8_STRING, + TARGET_URI +}; + +GdkAtom ScintillaGTK::atomClipboard = 0; +GdkAtom ScintillaGTK::atomUTF8 = 0; +GdkAtom ScintillaGTK::atomString = 0; +GdkAtom ScintillaGTK::atomUriList = 0; +GdkAtom ScintillaGTK::atomDROPFILES_DND = 0; + +static const GtkTargetEntry clipboardCopyTargets[] = { + { (gchar *) "UTF8_STRING", 0, TARGET_UTF8_STRING }, + { (gchar *) "STRING", 0, TARGET_STRING }, +}; +static const gint nClipboardCopyTargets = sizeof(clipboardCopyTargets) / sizeof(clipboardCopyTargets[0]); + +static const GtkTargetEntry clipboardPasteTargets[] = { + { (gchar *) "text/uri-list", 0, TARGET_URI }, + { (gchar *) "UTF8_STRING", 0, TARGET_UTF8_STRING }, + { (gchar *) "STRING", 0, TARGET_STRING }, +}; +static const gint nClipboardPasteTargets = sizeof(clipboardPasteTargets) / sizeof(clipboardPasteTargets[0]); + +static GtkWidget *PWidget(Window &w) { + return reinterpret_cast(w.GetID()); +} + +static ScintillaGTK *ScintillaFromWidget(GtkWidget *widget) { + ScintillaObject *scio = reinterpret_cast(widget); + return reinterpret_cast(scio->pscin); +} + +ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) : + adjustmentv(0), adjustmenth(0), + scrollBarWidth(30), scrollBarHeight(30), + capturedMouse(false), dragWasDropped(false), + lastKey(0), rectangularSelectionModifier(SCMOD_CTRL), parentClass(0), + im_context(NULL), + lastWheelMouseDirection(0), + wheelMouseIntensity(0), + rgnUpdate(0) { + sci = sci_; + wMain = GTK_WIDGET(sci); + +#if PLAT_GTK_WIN32 + rectangularSelectionModifier = SCMOD_ALT; +#else + rectangularSelectionModifier = SCMOD_CTRL; +#endif + +#if PLAT_GTK_WIN32 + // There does not seem to be a real standard for indicating that the clipboard + // contains a rectangular selection, so copy Developer Studio. + cfColumnSelect = static_cast( + ::RegisterClipboardFormat("MSDEVColumnSelect")); + + // Get intellimouse parameters when running on win32; otherwise use + // reasonable default +#ifndef SPI_GETWHEELSCROLLLINES +#define SPI_GETWHEELSCROLLLINES 104 +#endif + ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0); +#else + linesPerScroll = 4; +#endif + lastWheelMouseTime.tv_sec = 0; + lastWheelMouseTime.tv_usec = 0; + + Initialise(); +} + +ScintillaGTK::~ScintillaGTK() { + g_idle_remove_by_data(this); +} + +static void UnRefCursor(GdkCursor *cursor) { +#if GTK_CHECK_VERSION(3,0,0) + g_object_unref(cursor); +#else + gdk_cursor_unref(cursor); +#endif +} + +void ScintillaGTK::RealizeThis(GtkWidget *widget) { + //Platform::DebugPrintf("ScintillaGTK::realize this\n"); +#if GTK_CHECK_VERSION(2,20,0) + gtk_widget_set_realized(widget, TRUE); +#else + GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); +#endif + GdkWindowAttr attrs; + attrs.window_type = GDK_WINDOW_CHILD; + GtkAllocation allocation; +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_get_allocation(widget, &allocation); +#else + allocation = widget->allocation; +#endif + attrs.x = allocation.x; + attrs.y = allocation.y; + attrs.width = allocation.width; + attrs.height = allocation.height; + attrs.wclass = GDK_INPUT_OUTPUT; + attrs.visual = gtk_widget_get_visual(widget); +#if !GTK_CHECK_VERSION(3,0,0) + attrs.colormap = gtk_widget_get_colormap(widget); +#endif + attrs.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK; + GdkCursor *cursor = gdk_cursor_new(GDK_XTERM); + attrs.cursor = cursor; +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_window(widget, gdk_window_new(gtk_widget_get_parent_window(widget), &attrs, + GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_CURSOR)); + gdk_window_set_user_data(gtk_widget_get_window(widget), widget); + GtkStyleContext *styleContext = gtk_widget_get_style_context(widget); + if (styleContext) { + GdkRGBA colourBackWidget; + gtk_style_context_get_background_color(styleContext, GTK_STATE_FLAG_NORMAL, &colourBackWidget); + gdk_window_set_background_rgba(gtk_widget_get_window(widget), &colourBackWidget); + } + gdk_window_show(gtk_widget_get_window(widget)); + UnRefCursor(cursor); +#else + widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), &attrs, + GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_CURSOR); + gdk_window_set_user_data(widget->window, widget); + widget->style = gtk_style_attach(widget->style, widget->window); + gdk_window_set_background(widget->window, &widget->style->bg[GTK_STATE_NORMAL]); + gdk_window_show(widget->window); + UnRefCursor(cursor); +#endif + wPreedit = gtk_window_new(GTK_WINDOW_POPUP); + wPreeditDraw = gtk_drawing_area_new(); + GtkWidget *predrw = PWidget(wPreeditDraw); // No code inside the G_OBJECT macro +#if GTK_CHECK_VERSION(3,0,0) + g_signal_connect(G_OBJECT(predrw), "draw", + G_CALLBACK(DrawPreedit), this); +#else + g_signal_connect(G_OBJECT(predrw), "expose_event", + G_CALLBACK(ExposePreedit), this); +#endif + gtk_container_add(GTK_CONTAINER(PWidget(wPreedit)), predrw); + gtk_widget_realize(PWidget(wPreedit)); + gtk_widget_realize(predrw); + gtk_widget_show(predrw); + + im_context = gtk_im_multicontext_new(); + g_signal_connect(G_OBJECT(im_context), "commit", + G_CALLBACK(Commit), this); + g_signal_connect(G_OBJECT(im_context), "preedit_changed", + G_CALLBACK(PreeditChanged), this); + gtk_im_context_set_client_window(im_context, WindowFromWidget(widget)); + GtkWidget *widtxt = PWidget(wText); // // No code inside the G_OBJECT macro + g_signal_connect_after(G_OBJECT(widtxt), "style_set", + G_CALLBACK(ScintillaGTK::StyleSetText), NULL); + g_signal_connect_after(G_OBJECT(widtxt), "realize", + G_CALLBACK(ScintillaGTK::RealizeText), NULL); + gtk_widget_realize(widtxt); + gtk_widget_realize(PWidget(scrollbarv)); + gtk_widget_realize(PWidget(scrollbarh)); + + cursor = gdk_cursor_new(GDK_XTERM); + gdk_window_set_cursor(PWindow(wText), cursor); + UnRefCursor(cursor); + + cursor = gdk_cursor_new(GDK_LEFT_PTR); + gdk_window_set_cursor(PWindow(scrollbarv), cursor); + UnRefCursor(cursor); + + cursor = gdk_cursor_new(GDK_LEFT_PTR); + gdk_window_set_cursor(PWindow(scrollbarh), cursor); + UnRefCursor(cursor); + + gtk_selection_add_targets(widget, GDK_SELECTION_PRIMARY, + clipboardCopyTargets, nClipboardCopyTargets); +} + +void ScintillaGTK::Realize(GtkWidget *widget) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + sciThis->RealizeThis(widget); +} + +void ScintillaGTK::UnRealizeThis(GtkWidget *widget) { + try { + gtk_selection_clear_targets(widget, GDK_SELECTION_PRIMARY); + + if (IS_WIDGET_MAPPED(widget)) { + gtk_widget_unmap(widget); + } +#if GTK_CHECK_VERSION(2,20,0) + gtk_widget_set_realized(widget, FALSE); +#else + GTK_WIDGET_UNSET_FLAGS(widget, GTK_REALIZED); +#endif + gtk_widget_unrealize(PWidget(wText)); + gtk_widget_unrealize(PWidget(scrollbarv)); + gtk_widget_unrealize(PWidget(scrollbarh)); + gtk_widget_unrealize(PWidget(wPreedit)); + gtk_widget_unrealize(PWidget(wPreeditDraw)); + g_object_unref(im_context); + im_context = NULL; + if (GTK_WIDGET_CLASS(parentClass)->unrealize) + GTK_WIDGET_CLASS(parentClass)->unrealize(widget); + + Finalise(); + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::UnRealize(GtkWidget *widget) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + sciThis->UnRealizeThis(widget); +} + +static void MapWidget(GtkWidget *widget) { + if (widget && + IS_WIDGET_VISIBLE(widget) && + !IS_WIDGET_MAPPED(widget)) { + gtk_widget_map(widget); + } +} + +void ScintillaGTK::MapThis() { + try { + //Platform::DebugPrintf("ScintillaGTK::map this\n"); +#if GTK_CHECK_VERSION(2,20,0) + gtk_widget_set_mapped(PWidget(wMain), TRUE); +#else + GTK_WIDGET_SET_FLAGS(PWidget(wMain), GTK_MAPPED); +#endif + MapWidget(PWidget(wText)); + MapWidget(PWidget(scrollbarh)); + MapWidget(PWidget(scrollbarv)); + wMain.SetCursor(Window::cursorArrow); + scrollbarv.SetCursor(Window::cursorArrow); + scrollbarh.SetCursor(Window::cursorArrow); + ChangeSize(); + gdk_window_show(PWindow(wMain)); + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::Map(GtkWidget *widget) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + sciThis->MapThis(); +} + +void ScintillaGTK::UnMapThis() { + try { + //Platform::DebugPrintf("ScintillaGTK::unmap this\n"); +#if GTK_CHECK_VERSION(2,20,0) + gtk_widget_set_mapped(PWidget(wMain), FALSE); +#else + GTK_WIDGET_UNSET_FLAGS(PWidget(wMain), GTK_MAPPED); +#endif + DropGraphics(false); + gdk_window_hide(PWindow(wMain)); + gtk_widget_unmap(PWidget(wText)); + gtk_widget_unmap(PWidget(scrollbarh)); + gtk_widget_unmap(PWidget(scrollbarv)); + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::UnMap(GtkWidget *widget) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + sciThis->UnMapThis(); +} + +void ScintillaGTK::ForAll(GtkCallback callback, gpointer callback_data) { + try { + (*callback) (PWidget(wText), callback_data); + (*callback) (PWidget(scrollbarv), callback_data); + (*callback) (PWidget(scrollbarh), callback_data); + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::MainForAll(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data) { + ScintillaGTK *sciThis = ScintillaFromWidget((GtkWidget *)container); + + if (callback != NULL && include_internals) { + sciThis->ForAll(callback, callback_data); + } +} + +gint ScintillaGTK::FocusInThis(GtkWidget *widget) { + try { + SetFocusState(true); + if (im_context != NULL) { + gchar *str = NULL; + gint cursor_pos; + + gtk_im_context_get_preedit_string(im_context, &str, NULL, &cursor_pos); + if (PWidget(wPreedit) != NULL) { + if (strlen(str) > 0) { + gtk_widget_show(PWidget(wPreedit)); + } else { + gtk_widget_hide(PWidget(wPreedit)); + } + } + g_free(str); + gtk_im_context_focus_in(im_context); + } + + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + return FALSE; +} + +gint ScintillaGTK::FocusIn(GtkWidget *widget, GdkEventFocus * /*event*/) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + return sciThis->FocusInThis(widget); +} + +gint ScintillaGTK::FocusOutThis(GtkWidget *widget) { + try { + SetFocusState(false); + + if (PWidget(wPreedit) != NULL) + gtk_widget_hide(PWidget(wPreedit)); + if (im_context != NULL) + gtk_im_context_focus_out(im_context); + + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + return FALSE; +} + +gint ScintillaGTK::FocusOut(GtkWidget *widget, GdkEventFocus * /*event*/) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + return sciThis->FocusOutThis(widget); +} + +void ScintillaGTK::SizeRequest(GtkWidget *widget, GtkRequisition *requisition) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + requisition->width = 1; + requisition->height = 1; + GtkRequisition child_requisition; +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_get_preferred_size(PWidget(sciThis->scrollbarh), NULL, &child_requisition); + gtk_widget_get_preferred_size(PWidget(sciThis->scrollbarv), NULL, &child_requisition); +#else + gtk_widget_size_request(PWidget(sciThis->scrollbarh), &child_requisition); + gtk_widget_size_request(PWidget(sciThis->scrollbarv), &child_requisition); +#endif +} + +void ScintillaGTK::GetPreferredWidth(GtkWidget *widget, gint *minimalWidth, gint *naturalWidth) { + GtkRequisition requisition; + SizeRequest(widget, &requisition); + *minimalWidth = *naturalWidth = requisition.width; +} + +void ScintillaGTK::GetPreferredHeight(GtkWidget *widget, gint *minimalHeight, gint *naturalHeight) { + GtkRequisition requisition; + SizeRequest(widget, &requisition); + *minimalHeight = *naturalHeight = requisition.height; +} + +void ScintillaGTK::SizeAllocate(GtkWidget *widget, GtkAllocation *allocation) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + try { +#if GTK_CHECK_VERSION(2,20,0) + gtk_widget_set_allocation(widget, allocation); +#else + widget->allocation = *allocation; +#endif + if (IS_WIDGET_REALIZED(widget)) + gdk_window_move_resize(WindowFromWidget(widget), + allocation->x, + allocation->y, + allocation->width, + allocation->height); + + sciThis->Resize(allocation->width, allocation->height); + + } catch (...) { + sciThis->errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::Initialise() { + //Platform::DebugPrintf("ScintillaGTK::Initialise\n"); + parentClass = reinterpret_cast( + g_type_class_ref(gtk_container_get_type())); + +#if GTK_CHECK_VERSION(2,20,0) + gtk_widget_set_can_focus(PWidget(wMain), TRUE); + gtk_widget_set_sensitive(PWidget(wMain), TRUE); +#else + GTK_WIDGET_SET_FLAGS(PWidget(wMain), GTK_CAN_FOCUS); + GTK_WIDGET_SET_FLAGS(GTK_WIDGET(PWidget(wMain)), GTK_SENSITIVE); +#endif + gtk_widget_set_events(PWidget(wMain), + GDK_EXPOSURE_MASK + | GDK_STRUCTURE_MASK + | GDK_KEY_PRESS_MASK + | GDK_KEY_RELEASE_MASK + | GDK_FOCUS_CHANGE_MASK + | GDK_LEAVE_NOTIFY_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_HINT_MASK); + + wText = gtk_drawing_area_new(); + gtk_widget_set_parent(PWidget(wText), PWidget(wMain)); + GtkWidget *widtxt = PWidget(wText); // No code inside the G_OBJECT macro + gtk_widget_show(widtxt); +#if GTK_CHECK_VERSION(3,0,0) + g_signal_connect(G_OBJECT(widtxt), "draw", + G_CALLBACK(ScintillaGTK::DrawText), this); +#else + g_signal_connect(G_OBJECT(widtxt), "expose_event", + G_CALLBACK(ScintillaGTK::ExposeText), this); +#endif + gtk_widget_set_events(widtxt, GDK_EXPOSURE_MASK); + // Avoid background drawing flash + gtk_widget_set_double_buffered(widtxt, FALSE); + gtk_widget_set_size_request(widtxt, 100, 100); + adjustmentv = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 201.0, 1.0, 20.0, 20.0)); +#if GTK_CHECK_VERSION(3,0,0) + scrollbarv = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT(adjustmentv)); +#else + scrollbarv = gtk_vscrollbar_new(GTK_ADJUSTMENT(adjustmentv)); +#endif +#if GTK_CHECK_VERSION(2,20,0) + gtk_widget_set_can_focus(PWidget(scrollbarv), FALSE); +#else + GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarv), GTK_CAN_FOCUS); +#endif + g_signal_connect(G_OBJECT(adjustmentv), "value_changed", + G_CALLBACK(ScrollSignal), this); + gtk_widget_set_parent(PWidget(scrollbarv), PWidget(wMain)); + gtk_widget_show(PWidget(scrollbarv)); + + adjustmenth = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 101.0, 1.0, 20.0, 20.0)); +#if GTK_CHECK_VERSION(3,0,0) + scrollbarh = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT(adjustmenth)); +#else + scrollbarh = gtk_hscrollbar_new(GTK_ADJUSTMENT(adjustmenth)); +#endif +#if GTK_CHECK_VERSION(2,20,0) + gtk_widget_set_can_focus(PWidget(scrollbarh), FALSE); +#else + GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarh), GTK_CAN_FOCUS); +#endif + g_signal_connect(G_OBJECT(adjustmenth), "value_changed", + G_CALLBACK(ScrollHSignal), this); + gtk_widget_set_parent(PWidget(scrollbarh), PWidget(wMain)); + gtk_widget_show(PWidget(scrollbarh)); + + gtk_widget_grab_focus(PWidget(wMain)); + + gtk_drag_dest_set(GTK_WIDGET(PWidget(wMain)), + GTK_DEST_DEFAULT_ALL, clipboardPasteTargets, nClipboardPasteTargets, + static_cast(GDK_ACTION_COPY | GDK_ACTION_MOVE)); + + // Set caret period based on GTK settings + gboolean blinkOn = false; + if (g_object_class_find_property(G_OBJECT_GET_CLASS( + G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink")) { + g_object_get(G_OBJECT( + gtk_settings_get_default()), "gtk-cursor-blink", &blinkOn, NULL); + } + if (blinkOn && + g_object_class_find_property(G_OBJECT_GET_CLASS( + G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink-time")) { + gint value; + g_object_get(G_OBJECT( + gtk_settings_get_default()), "gtk-cursor-blink-time", &value, NULL); + caret.period = gint(value / 1.75); + } else { + caret.period = 0; + } + + SetTicking(true); +} + +void ScintillaGTK::Finalise() { + SetTicking(false); + ScintillaBase::Finalise(); +} + +void ScintillaGTK::DisplayCursor(Window::Cursor c) { + if (cursorMode == SC_CURSORNORMAL) + wText.SetCursor(c); + else + wText.SetCursor(static_cast(cursorMode)); +} + +bool ScintillaGTK::DragThreshold(Point ptStart, Point ptNow) { + return gtk_drag_check_threshold(GTK_WIDGET(PWidget(wMain)), + ptStart.x, ptStart.y, ptNow.x, ptNow.y); +} + +void ScintillaGTK::StartDrag() { + dragWasDropped = false; + inDragDrop = ddDragging; + GtkTargetList *tl = gtk_target_list_new(clipboardCopyTargets, nClipboardCopyTargets); + gtk_drag_begin(GTK_WIDGET(PWidget(wMain)), + tl, + static_cast(GDK_ACTION_COPY | GDK_ACTION_MOVE), + evbtn.button, + reinterpret_cast(&evbtn)); +} + +static char *ConvertText(int *lenResult, char *s, size_t len, const char *charSetDest, + const char *charSetSource, bool transliterations, bool silent=false) { + // s is not const because of different versions of iconv disagreeing about const + *lenResult = 0; + char *destForm = 0; + Converter conv(charSetDest, charSetSource, transliterations); + if (conv) { + destForm = new char[len*3+1]; + char *pin = s; + size_t inLeft = len; + char *pout = destForm; + size_t outLeft = len*3+1; + size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft); + if (conversions == ((size_t)(-1))) { + if (!silent) + fprintf(stderr, "iconv %s->%s failed for %s\n", + charSetSource, charSetDest, static_cast(s)); + delete []destForm; + destForm = 0; + } else { +//fprintf(stderr, "iconv OK %s %d\n", destForm, pout - destForm); + *pout = '\0'; + *lenResult = pout - destForm; + } + } else { +fprintf(stderr, "Can not iconv %s %s\n", charSetDest, charSetSource); + } + if (!destForm) { + destForm = new char[1]; + destForm[0] = '\0'; + *lenResult = 0; + } + return destForm; +} + +// Returns the target converted to UTF8. +// Return the length in bytes. +int ScintillaGTK::TargetAsUTF8(char *text) { + int targetLength = targetEnd - targetStart; + if (IsUnicodeMode()) { + if (text) { + pdoc->GetCharRange(text, targetStart, targetLength); + } + } else { + // Need to convert + const char *charSetBuffer = CharacterSetID(); + if (*charSetBuffer) { +//~ fprintf(stderr, "AsUTF8 %s %d %0d-%0d\n", charSetBuffer, targetLength, targetStart, targetEnd); + char *s = new char[targetLength]; + if (s) { + pdoc->GetCharRange(s, targetStart, targetLength); +//~ fprintf(stderr, " \"%s\"\n", s); + if (text) { + char *tmputf = ConvertText(&targetLength, s, targetLength, "UTF-8", charSetBuffer, false); + memcpy(text, tmputf, targetLength); + delete []tmputf; +//~ fprintf(stderr, " \"%s\"\n", text); + } + delete []s; + } + } else { + if (text) { + pdoc->GetCharRange(text, targetStart, targetLength); + } + } + } +//~ fprintf(stderr, "Length = %d bytes\n", targetLength); + return targetLength; +} + +// Translates a nul terminated UTF8 string into the document encoding. +// Return the length of the result in bytes. +int ScintillaGTK::EncodedFromUTF8(char *utf8, char *encoded) { + int inputLength = (lengthForEncode >= 0) ? lengthForEncode : strlen(utf8); + if (IsUnicodeMode()) { + if (encoded) { + memcpy(encoded, utf8, inputLength); + } + return inputLength; + } else { + // Need to convert + const char *charSetBuffer = CharacterSetID(); + if (*charSetBuffer) { + int outLength = 0; + char *tmpEncoded = ConvertText(&outLength, utf8, inputLength, charSetBuffer, "UTF-8", true); + if (tmpEncoded) { + if (encoded) { + memcpy(encoded, tmpEncoded, outLength); + } + delete []tmpEncoded; + } + return outLength; + } else { + if (encoded) { + memcpy(encoded, utf8, inputLength); + } + return inputLength; + } + } + // Fail + return 0; +} + +bool ScintillaGTK::ValidCodePage(int codePage) const { + return codePage == 0 + || codePage == SC_CP_UTF8 + || codePage == 932 + || codePage == 936 + || codePage == 949 + || codePage == 950 + || codePage == 1361; +} + +sptr_t ScintillaGTK::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { + try { + switch (iMessage) { + + case SCI_GRABFOCUS: + gtk_widget_grab_focus(PWidget(wMain)); + break; + + case SCI_GETDIRECTFUNCTION: + return reinterpret_cast(DirectFunction); + + case SCI_GETDIRECTPOINTER: + return reinterpret_cast(this); + +#ifdef SCI_LEXER + case SCI_LOADLEXERLIBRARY: + LexerManager::GetInstance()->Load(reinterpret_cast(lParam)); + break; +#endif + case SCI_TARGETASUTF8: + return TargetAsUTF8(reinterpret_cast(lParam)); + + case SCI_ENCODEDFROMUTF8: + return EncodedFromUTF8(reinterpret_cast(wParam), + reinterpret_cast(lParam)); + + case SCI_SETRECTANGULARSELECTIONMODIFIER: + rectangularSelectionModifier = wParam; + break; + + case SCI_GETRECTANGULARSELECTIONMODIFIER: + return rectangularSelectionModifier; + + default: + return ScintillaBase::WndProc(iMessage, wParam, lParam); + } + } catch (std::bad_alloc&) { + errorStatus = SC_STATUS_BADALLOC; + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + return 0l; +} + +sptr_t ScintillaGTK::DefWndProc(unsigned int, uptr_t, sptr_t) { + return 0; +} + +void ScintillaGTK::SetTicking(bool on) { + if (timer.ticking != on) { + timer.ticking = on; + if (timer.ticking) { + timer.tickerID = reinterpret_cast(g_timeout_add(timer.tickSize, + reinterpret_cast(TimeOut), this)); + } else { + g_source_remove(GPOINTER_TO_UINT(timer.tickerID)); + } + } + timer.ticksToWait = caret.period; +} + +bool ScintillaGTK::SetIdle(bool on) { + if (on) { + // Start idler, if it's not running. + if (!idler.state) { + idler.state = true; + idler.idlerID = reinterpret_cast( + g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, + reinterpret_cast(IdleCallback), this, NULL)); + } + } else { + // Stop idler, if it's running + if (idler.state) { + idler.state = false; + g_source_remove(GPOINTER_TO_UINT(idler.idlerID)); + } + } + return true; +} + +void ScintillaGTK::SetMouseCapture(bool on) { + if (mouseDownCaptures) { + if (on) { + gtk_grab_add(GTK_WIDGET(PWidget(wMain))); + } else { + gtk_grab_remove(GTK_WIDGET(PWidget(wMain))); + } + } + capturedMouse = on; +} + +bool ScintillaGTK::HaveMouseCapture() { + return capturedMouse; +} + +#if GTK_CHECK_VERSION(3,0,0) + +// Is crcTest completely in crcContainer? +static bool CRectContains(const cairo_rectangle_t &crcContainer, const cairo_rectangle_t &crcTest) { + return + (crcTest.x >= crcContainer.x) && ((crcTest.x + crcTest.width) <= (crcContainer.x + crcContainer.width)) && + (crcTest.y >= crcContainer.y) && ((crcTest.y + crcTest.height) <= (crcContainer.y + crcContainer.height)); +} + +// Is crcTest completely in crcListContainer? +// May incorrectly return false if complex shape +static bool CRectListContains(const cairo_rectangle_list_t *crcListContainer, const cairo_rectangle_t &crcTest) { + for (int r=0; rnum_rectangles; r++) { + if (CRectContains(crcListContainer->rectangles[r], crcTest)) + return true; + } + return false; +} + +#endif + +bool ScintillaGTK::PaintContains(PRectangle rc) { + // This allows optimization when a rectangle is completely in the update region. + // It is OK to return false when too difficult to determine as that just performs extra drawing + bool contains = true; + if (paintState == painting) { + if (!rcPaint.Contains(rc)) { + contains = false; + } else if (rgnUpdate) { +#if GTK_CHECK_VERSION(3,0,0) + cairo_rectangle_t grc = {rc.left, rc.top, + rc.right - rc.left, rc.bottom - rc.top}; + contains = CRectListContains(rgnUpdate, grc); +#else + GdkRectangle grc = {rc.left, rc.top, + rc.right - rc.left, rc.bottom - rc.top}; + if (gdk_region_rect_in(rgnUpdate, &grc) != GDK_OVERLAP_RECTANGLE_IN) { + contains = false; + } +#endif + } + } + return contains; +} + +// Redraw all of text area. This paint will not be abandoned. +void ScintillaGTK::FullPaint() { + wText.InvalidateAll(); +} + +PRectangle ScintillaGTK::GetClientRectangle() { + PRectangle rc = wMain.GetClientPosition(); + if (verticalScrollBarVisible) + rc.right -= scrollBarWidth; + if (horizontalScrollBarVisible && (wrapState == eWrapNone)) + rc.bottom -= scrollBarHeight; + // Move to origin + rc.right -= rc.left; + rc.bottom -= rc.top; + rc.left = 0; + rc.top = 0; + return rc; +} + +// Synchronously paint a rectangle of the window. +void ScintillaGTK::SyncPaint(PRectangle rc) { + paintState = painting; + rcPaint = rc; + PRectangle rcClient = GetClientRectangle(); + paintingAllText = rcPaint.Contains(rcClient); + if (PWindow(wText)) { + Surface *sw = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); + if (sw) { + cairo_t *cr = gdk_cairo_create(PWindow(wText)); + sw->Init(cr, PWidget(wText)); + Paint(sw, rc); + sw->Release(); + delete sw; + cairo_destroy(cr); + } + } + if (paintState == paintAbandoned) { + // Painting area was insufficient to cover new styling or brace highlight positions + FullPaint(); + } + paintState = notPainting; +} + +void ScintillaGTK::ScrollText(int linesToMove) { + int diff = vs.lineHeight * -linesToMove; + //Platform::DebugPrintf("ScintillaGTK::ScrollText %d %d %0d,%0d %0d,%0d\n", linesToMove, diff, + // rc.left, rc.top, rc.right, rc.bottom); + GtkWidget *wi = PWidget(wText); + + gdk_window_scroll(WindowFromWidget(wi), 0, -diff); + gdk_window_process_updates(WindowFromWidget(wi), FALSE); +} + +void ScintillaGTK::SetVerticalScrollPos() { + DwellEnd(true); + gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmentv), topLine); +} + +void ScintillaGTK::SetHorizontalScrollPos() { + DwellEnd(true); + gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmenth), xOffset / 2); +} + +bool ScintillaGTK::ModifyScrollBars(int nMax, int nPage) { + bool modified = false; + int pageScroll = LinesToScroll(); + +#if GTK_CHECK_VERSION(3,0,0) + if (gtk_adjustment_get_upper(adjustmentv) != (nMax + 1) || + gtk_adjustment_get_page_size(adjustmentv) != nPage || + gtk_adjustment_get_page_increment(adjustmentv) != pageScroll) { + gtk_adjustment_set_upper(adjustmentv, nMax + 1); + gtk_adjustment_set_page_size(adjustmentv, nPage); + gtk_adjustment_set_page_increment(adjustmentv, pageScroll); + gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmentv)); + modified = true; + } +#else + if (GTK_ADJUSTMENT(adjustmentv)->upper != (nMax + 1) || + GTK_ADJUSTMENT(adjustmentv)->page_size != nPage || + GTK_ADJUSTMENT(adjustmentv)->page_increment != pageScroll) { + GTK_ADJUSTMENT(adjustmentv)->upper = nMax + 1; + GTK_ADJUSTMENT(adjustmentv)->page_size = nPage; + GTK_ADJUSTMENT(adjustmentv)->page_increment = pageScroll; + gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmentv)); + modified = true; + } +#endif + + PRectangle rcText = GetTextRectangle(); + int horizEndPreferred = scrollWidth; + if (horizEndPreferred < 0) + horizEndPreferred = 0; + unsigned int pageWidth = rcText.Width(); + unsigned int pageIncrement = pageWidth / 3; + unsigned int charWidth = vs.styles[STYLE_DEFAULT].aveCharWidth; +#if GTK_CHECK_VERSION(3,0,0) + if (gtk_adjustment_get_upper(adjustmenth) != horizEndPreferred || + gtk_adjustment_get_page_size(adjustmenth) != pageWidth || + gtk_adjustment_get_page_increment(adjustmenth) != pageIncrement || + gtk_adjustment_get_step_increment(adjustmenth) != charWidth) { + gtk_adjustment_set_upper(adjustmenth, horizEndPreferred); + gtk_adjustment_set_page_size(adjustmenth, pageWidth); + gtk_adjustment_set_page_increment(adjustmenth, pageIncrement); + gtk_adjustment_set_step_increment(adjustmenth, charWidth); + gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmenth)); + modified = true; + } +#else + if (GTK_ADJUSTMENT(adjustmenth)->upper != horizEndPreferred || + GTK_ADJUSTMENT(adjustmenth)->page_size != pageWidth || + GTK_ADJUSTMENT(adjustmenth)->page_increment != pageIncrement || + GTK_ADJUSTMENT(adjustmenth)->step_increment != charWidth) { + GTK_ADJUSTMENT(adjustmenth)->upper = horizEndPreferred; + GTK_ADJUSTMENT(adjustmenth)->step_increment = charWidth; + GTK_ADJUSTMENT(adjustmenth)->page_size = pageWidth; + GTK_ADJUSTMENT(adjustmenth)->page_increment = pageIncrement; + gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmenth)); + modified = true; + } +#endif + return modified; +} + +void ScintillaGTK::ReconfigureScrollBars() { + PRectangle rc = wMain.GetClientPosition(); + Resize(rc.Width(), rc.Height()); +} + +void ScintillaGTK::NotifyChange() { + g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0, + Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE), PWidget(wMain)); +} + +void ScintillaGTK::NotifyFocus(bool focus) { + g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0, + Platform::LongFromTwoShorts + (GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS), PWidget(wMain)); +} + +void ScintillaGTK::NotifyParent(SCNotification scn) { + scn.nmhdr.hwndFrom = PWidget(wMain); + scn.nmhdr.idFrom = GetCtrlID(); + g_signal_emit(G_OBJECT(sci), scintilla_signals[NOTIFY_SIGNAL], 0, + GetCtrlID(), &scn); +} + +void ScintillaGTK::NotifyKey(int key, int modifiers) { + SCNotification scn = {0}; + scn.nmhdr.code = SCN_KEY; + scn.ch = key; + scn.modifiers = modifiers; + + NotifyParent(scn); +} + +void ScintillaGTK::NotifyURIDropped(const char *list) { + SCNotification scn = {0}; + scn.nmhdr.code = SCN_URIDROPPED; + scn.text = list; + + NotifyParent(scn); +} + +const char *CharacterSetID(int characterSet); + +const char *ScintillaGTK::CharacterSetID() const { + return ::CharacterSetID(vs.styles[STYLE_DEFAULT].characterSet); +} + +class CaseFolderUTF8 : public CaseFolderTable { +public: + CaseFolderUTF8() { + StandardASCII(); + } + virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) { + if ((lenMixed == 1) && (sizeFolded > 0)) { + folded[0] = mapping[static_cast(mixed[0])]; + return 1; + } else { + gchar *mapped = g_utf8_casefold(mixed, lenMixed); + size_t lenMapped = strlen(mapped); + if (lenMapped < sizeFolded) { + memcpy(folded, mapped, lenMapped); + } else { + lenMapped = 0; + } + g_free(mapped); + return lenMapped; + } + } +}; + +class CaseFolderDBCS : public CaseFolderTable { + const char *charSet; +public: + CaseFolderDBCS(const char *charSet_) : charSet(charSet_) { + StandardASCII(); + } + virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) { + if ((lenMixed == 1) && (sizeFolded > 0)) { + folded[0] = mapping[static_cast(mixed[0])]; + return 1; + } else if (*charSet) { + int convertedLength = lenMixed; + char *sUTF8 = ConvertText(&convertedLength, const_cast(mixed), lenMixed, + "UTF-8", charSet, false); + if (sUTF8) { + gchar *mapped = g_utf8_casefold(sUTF8, strlen(sUTF8)); + size_t lenMapped = strlen(mapped); + if (lenMapped < sizeFolded) { + memcpy(folded, mapped, lenMapped); + } else { + folded[0] = '\0'; + lenMapped = 1; + } + g_free(mapped); + delete []sUTF8; + return lenMapped; + } + } + // Something failed so return a single NUL byte + folded[0] = '\0'; + return 1; + } +}; + +CaseFolder *ScintillaGTK::CaseFolderForEncoding() { + if (pdoc->dbcsCodePage == SC_CP_UTF8) { + return new CaseFolderUTF8(); + } else { + const char *charSetBuffer = CharacterSetID(); + if (charSetBuffer) { + if (pdoc->dbcsCodePage == 0) { + CaseFolderTable *pcf = new CaseFolderTable(); + pcf->StandardASCII(); + // Only for single byte encodings + for (int i=0x80; i<0x100; i++) { + char sCharacter[2] = "A"; + sCharacter[0] = i; + int convertedLength = 1; + const char *sUTF8 = ConvertText(&convertedLength, sCharacter, 1, + "UTF-8", charSetBuffer, false); + if (sUTF8) { + gchar *mapped = g_utf8_casefold(sUTF8, strlen(sUTF8)); + if (mapped) { + int mappedLength = strlen(mapped); + const char *mappedBack = ConvertText(&mappedLength, mapped, + mappedLength, charSetBuffer, "UTF-8", false, true); + if (mappedBack && (strlen(mappedBack) == 1) && (mappedBack[0] != sCharacter[0])) { + pcf->SetTranslation(sCharacter[0], mappedBack[0]); + } + delete []mappedBack; + g_free(mapped); + } + } + delete []sUTF8; + } + return pcf; + } else { + return new CaseFolderDBCS(charSetBuffer); + } + } + return 0; + } +} + +std::string ScintillaGTK::CaseMapString(const std::string &s, int caseMapping) { + if (s.size() == 0) + return std::string(); + + if (caseMapping == cmSame) + return s; + + const char *needsFree1 = 0; // Must be freed with delete [] + const char *charSetBuffer = CharacterSetID(); + const char *sUTF8 = s.c_str(); + int rangeBytes = s.size(); + + int convertedLength = rangeBytes; + // Change text to UTF-8 + if (!IsUnicodeMode()) { + // Need to convert + if (*charSetBuffer) { + sUTF8 = ConvertText(&convertedLength, const_cast(s.c_str()), rangeBytes, + "UTF-8", charSetBuffer, false); + needsFree1 = sUTF8; + } + } + gchar *mapped; // Must be freed with g_free + if (caseMapping == cmUpper) { + mapped = g_utf8_strup(sUTF8, convertedLength); + } else { + mapped = g_utf8_strdown(sUTF8, convertedLength); + } + int mappedLength = strlen(mapped); + char *mappedBack = mapped; + + char *needsFree2 = 0; // Must be freed with delete [] + if (!IsUnicodeMode()) { + if (*charSetBuffer) { + mappedBack = ConvertText(&mappedLength, mapped, mappedLength, charSetBuffer, "UTF-8", false); + needsFree2 = mappedBack; + } + } + + std::string ret(mappedBack, mappedLength); + g_free(mapped); + delete []needsFree1; + delete []needsFree2; + return ret; +} + +int ScintillaGTK::KeyDefault(int key, int modifiers) { + if (!(modifiers & SCI_CTRL) && !(modifiers & SCI_ALT)) { + if (key < 256) { + NotifyKey(key, modifiers); + return 0; + } else { + // Pass up to container in case it is an accelerator + NotifyKey(key, modifiers); + return 0; + } + } else { + // Pass up to container in case it is an accelerator + NotifyKey(key, modifiers); + return 0; + } + //Platform::DebugPrintf("SK-key: %d %x %x\n",key, modifiers); +} + +void ScintillaGTK::CopyToClipboard(const SelectionText &selectedText) { + SelectionText *clipText = new SelectionText(); + clipText->Copy(selectedText); + StoreOnClipboard(clipText); +} + +void ScintillaGTK::Copy() { + if (!sel.Empty()) { + SelectionText *clipText = new SelectionText(); + CopySelectionRange(clipText); + StoreOnClipboard(clipText); +#if PLAT_GTK_WIN32 + if (sel.IsRectangular()) { + ::OpenClipboard(NULL); + ::SetClipboardData(cfColumnSelect, 0); + ::CloseClipboard(); + } +#endif + } +} + +void ScintillaGTK::Paste() { + atomSought = atomUTF8; + gtk_selection_convert(GTK_WIDGET(PWidget(wMain)), + atomClipboard, atomSought, GDK_CURRENT_TIME); +} + +void ScintillaGTK::CreateCallTipWindow(PRectangle rc) { + if (!ct.wCallTip.Created()) { + ct.wCallTip = gtk_window_new(GTK_WINDOW_POPUP); + ct.wDraw = gtk_drawing_area_new(); + GtkWidget *widcdrw = PWidget(ct.wDraw); // // No code inside the G_OBJECT macro + gtk_container_add(GTK_CONTAINER(PWidget(ct.wCallTip)), widcdrw); +#if GTK_CHECK_VERSION(3,0,0) + g_signal_connect(G_OBJECT(widcdrw), "draw", + G_CALLBACK(ScintillaGTK::DrawCT), &ct); +#else + g_signal_connect(G_OBJECT(widcdrw), "expose_event", + G_CALLBACK(ScintillaGTK::ExposeCT), &ct); +#endif + g_signal_connect(G_OBJECT(widcdrw), "button_press_event", + G_CALLBACK(ScintillaGTK::PressCT), static_cast(this)); + gtk_widget_set_events(widcdrw, + GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK); + } + gtk_widget_set_size_request(PWidget(ct.wDraw), rc.Width(), rc.Height()); + ct.wDraw.Show(); + if (PWindow(ct.wCallTip)) { + gdk_window_resize(PWindow(ct.wCallTip), rc.Width(), rc.Height()); + } +} + +void ScintillaGTK::AddToPopUp(const char *label, int cmd, bool enabled) { + GtkWidget *menuItem; + if (label[0]) + menuItem = gtk_menu_item_new_with_label(label); + else + menuItem = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(popup.GetID()), menuItem); + g_object_set_data(G_OBJECT(menuItem), "CmdNum", reinterpret_cast(cmd)); + g_signal_connect(G_OBJECT(menuItem),"activate", G_CALLBACK(PopUpCB), this); + + if (cmd) { + if (menuItem) + gtk_widget_set_sensitive(menuItem, enabled); + } +} + +bool ScintillaGTK::OwnPrimarySelection() { + return ((gdk_selection_owner_get(GDK_SELECTION_PRIMARY) + == PWindow(wMain)) && + (PWindow(wMain) != NULL)); +} + +void ScintillaGTK::ClaimSelection() { + // X Windows has a 'primary selection' as well as the clipboard. + // Whenever the user selects some text, we become the primary selection + if (!sel.Empty() && IS_WIDGET_REALIZED(GTK_WIDGET(PWidget(wMain)))) { + primarySelection = true; + gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)), + GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); + primary.Free(); + } else if (OwnPrimarySelection()) { + primarySelection = true; + if (primary.s == NULL) + gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); + } else { + primarySelection = false; + primary.Free(); + } +} + +#if GTK_CHECK_VERSION(3,0,0) +static const guchar *DataOfGSD(GtkSelectionData *sd) { return gtk_selection_data_get_data(sd); } +static gint LengthOfGSD(GtkSelectionData *sd) { return gtk_selection_data_get_length(sd); } +static GdkAtom TypeOfGSD(GtkSelectionData *sd) { return gtk_selection_data_get_data_type(sd); } +static GdkAtom SelectionOfGSD(GtkSelectionData *sd) { return gtk_selection_data_get_selection(sd); } +#else +static const guchar *DataOfGSD(GtkSelectionData *sd) { return sd->data; } +static gint LengthOfGSD(GtkSelectionData *sd) { return sd->length; } +static GdkAtom TypeOfGSD(GtkSelectionData *sd) { return sd->type; } +static GdkAtom SelectionOfGSD(GtkSelectionData *sd) { return sd->selection; } +#endif + +// Detect rectangular text, convert line ends to current mode, convert from or to UTF-8 +void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText) { + const char *data = reinterpret_cast(DataOfGSD(selectionData)); + int len = LengthOfGSD(selectionData); + GdkAtom selectionTypeData = TypeOfGSD(selectionData); + + // Return empty string if selection is not a string + if ((selectionTypeData != GDK_TARGET_STRING) && (selectionTypeData != atomUTF8)) { + char *empty = new char[1]; + empty[0] = '\0'; + selText.Set(empty, 0, SC_CP_UTF8, 0, false, false); + return; + } + + // Check for "\n\0" ending to string indicating that selection is rectangular + bool isRectangular; +#if PLAT_GTK_WIN32 + isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0; +#else + isRectangular = ((len > 2) && (data[len - 1] == 0 && data[len - 2] == '\n')); + if (isRectangular) + len--; // Forget the extra '\0' +#endif + + char *dest; + if (selectionTypeData == GDK_TARGET_STRING) { + dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode); + if (IsUnicodeMode()) { + // Unknown encoding so assume in Latin1 + char *destPrevious = dest; + dest = UTF8FromLatin1(dest, len); + selText.Set(dest, len, SC_CP_UTF8, 0, selText.rectangular, false); + delete []destPrevious; + } else { + // Assume buffer is in same encoding as selection + selText.Set(dest, len, pdoc->dbcsCodePage, + vs.styles[STYLE_DEFAULT].characterSet, isRectangular, false); + } + } else { // UTF-8 + dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode); + selText.Set(dest, len, SC_CP_UTF8, 0, isRectangular, false); + const char *charSetBuffer = CharacterSetID(); + if (!IsUnicodeMode() && *charSetBuffer) { + // Convert to locale + dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8", true); + selText.Set(dest, len, pdoc->dbcsCodePage, + vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular, false); + } + } +} + +void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) { + try { + if ((SelectionOfGSD(selection_data) == atomClipboard) || + (SelectionOfGSD(selection_data) == GDK_SELECTION_PRIMARY)) { + if ((atomSought == atomUTF8) && (LengthOfGSD(selection_data) <= 0)) { + atomSought = atomString; + gtk_selection_convert(GTK_WIDGET(PWidget(wMain)), + SelectionOfGSD(selection_data), atomSought, GDK_CURRENT_TIME); + } else if ((LengthOfGSD(selection_data) > 0) && + ((TypeOfGSD(selection_data) == GDK_TARGET_STRING) || (TypeOfGSD(selection_data) == atomUTF8))) { + SelectionText selText; + GetGtkSelectionText(selection_data, selText); + + UndoGroup ug(pdoc); + if (SelectionOfGSD(selection_data) != GDK_SELECTION_PRIMARY) { + ClearSelection(multiPasteMode == SC_MULTIPASTE_EACH); + } + SelectionPosition selStart = sel.IsRectangular() ? + sel.Rectangular().Start() : + sel.Range(sel.Main()).Start(); + + if (selText.rectangular) { + PasteRectangular(selStart, selText.s, selText.len); + } else { + InsertPaste(selStart, selText.s, selText.len); + } + EnsureCaretVisible(); + } + } +// else fprintf(stderr, "Target non string %d %d\n", (int)(selection_data->type), +// (int)(atomUTF8)); + Redraw(); + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) { + dragWasDropped = true; + if (TypeOfGSD(selection_data) == atomUriList || TypeOfGSD(selection_data) == atomDROPFILES_DND) { + char *ptr = new char[LengthOfGSD(selection_data) + 1]; + ptr[LengthOfGSD(selection_data)] = '\0'; + memcpy(ptr, DataOfGSD(selection_data), LengthOfGSD(selection_data)); + NotifyURIDropped(ptr); + delete []ptr; + } else if ((TypeOfGSD(selection_data) == GDK_TARGET_STRING) || (TypeOfGSD(selection_data) == atomUTF8)) { + if (TypeOfGSD(selection_data) > 0) { + SelectionText selText; + GetGtkSelectionText(selection_data, selText); + DropAt(posDrop, selText.s, false, selText.rectangular); + } + } else if (LengthOfGSD(selection_data) > 0) { + //~ fprintf(stderr, "ReceivedDrop other %p\n", static_cast(selection_data->type)); + } + Redraw(); +} + + + +void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *text) { +#if PLAT_GTK_WIN32 + // GDK on Win32 expands any \n into \r\n, so make a copy of + // the clip text now with newlines converted to \n. Use { } to hide symbols + // from code below + SelectionText *newline_normalized = NULL; + { + int tmpstr_len; + char *tmpstr = Document::TransformLineEnds(&tmpstr_len, text->s, text->len, SC_EOL_LF); + newline_normalized = new SelectionText(); + newline_normalized->Set(tmpstr, tmpstr_len, SC_CP_UTF8, 0, text->rectangular, false); + text = newline_normalized; + } +#endif + + // Convert text to utf8 if it isn't already + SelectionText *converted = 0; + if ((text->codePage != SC_CP_UTF8) && (info == TARGET_UTF8_STRING)) { + const char *charSet = ::CharacterSetID(text->characterSet); + if (*charSet) { + int new_len; + char* tmputf = ConvertText(&new_len, text->s, text->len, "UTF-8", charSet, false); + converted = new SelectionText(); + converted->Set(tmputf, new_len, SC_CP_UTF8, 0, text->rectangular, false); + text = converted; + } + } + + // Here is a somewhat evil kludge. + // As I can not work out how to store data on the clipboard in multiple formats + // and need some way to mark the clipping as being stream or rectangular, + // the terminating \0 is included in the length for rectangular clippings. + // All other tested aplications behave benignly by ignoring the \0. + // The #if is here because on Windows cfColumnSelect clip entry is used + // instead as standard indicator of rectangularness (so no need to kludge) + const char *textData = text->s ? text->s : ""; + int len = strlen(textData); +#if PLAT_GTK_WIN32 == 0 + if (text->rectangular) + len++; +#endif + + if (info == TARGET_UTF8_STRING) { + gtk_selection_data_set_text(selection_data, textData, len); + } else { + gtk_selection_data_set(selection_data, + static_cast(GDK_SELECTION_TYPE_STRING), + 8, reinterpret_cast(textData), len); + } + delete converted; + +#if PLAT_GTK_WIN32 + delete newline_normalized; +#endif +} + +void ScintillaGTK::StoreOnClipboard(SelectionText *clipText) { + GtkClipboard *clipBoard = + gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard); + if (clipBoard == NULL) // Occurs if widget isn't in a toplevel + return; + + if (gtk_clipboard_set_with_data(clipBoard, clipboardCopyTargets, nClipboardCopyTargets, + ClipboardGetSelection, ClipboardClearSelection, clipText)) { + gtk_clipboard_set_can_store(clipBoard, clipboardCopyTargets, nClipboardCopyTargets); + } +} + +void ScintillaGTK::ClipboardGetSelection(GtkClipboard *, GtkSelectionData *selection_data, guint info, void *data) { + GetSelection(selection_data, info, static_cast(data)); +} + +void ScintillaGTK::ClipboardClearSelection(GtkClipboard *, void *data) { + SelectionText *obj = static_cast(data); + delete obj; +} + +void ScintillaGTK::UnclaimSelection(GdkEventSelection *selection_event) { + try { + //Platform::DebugPrintf("UnclaimSelection\n"); + if (selection_event->selection == GDK_SELECTION_PRIMARY) { + //Platform::DebugPrintf("UnclaimPrimarySelection\n"); + if (!OwnPrimarySelection()) { + primary.Free(); + primarySelection = false; + FullPaint(); + } + } + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::Resize(int width, int height) { + //Platform::DebugPrintf("Resize %d %d\n", width, height); + //printf("Resize %d %d\n", width, height); + + // Not always needed, but some themes can have different sizes of scrollbars +#if GTK_CHECK_VERSION(3,0,0) + GtkRequisition requisition; + gtk_widget_get_requisition(PWidget(scrollbarv), &requisition); + scrollBarWidth = requisition.width; + gtk_widget_get_requisition(PWidget(scrollbarh), &requisition); + scrollBarHeight = requisition.height; +#else + scrollBarWidth = GTK_WIDGET(PWidget(scrollbarv))->requisition.width; + scrollBarHeight = GTK_WIDGET(PWidget(scrollbarh))->requisition.height; +#endif + + // These allocations should never produce negative sizes as they would wrap around to huge + // unsigned numbers inside GTK+ causing warnings. + bool showSBHorizontal = horizontalScrollBarVisible && (wrapState == eWrapNone); + int horizontalScrollBarHeight = scrollBarHeight; + if (!showSBHorizontal) + horizontalScrollBarHeight = 0; + + GtkAllocation alloc; + if (showSBHorizontal) { + gtk_widget_show(GTK_WIDGET(PWidget(scrollbarh))); + alloc.x = 0; + alloc.y = height - scrollBarHeight; + alloc.width = Platform::Maximum(1, width - scrollBarWidth); + alloc.height = horizontalScrollBarHeight; + gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarh)), &alloc); + } else { + gtk_widget_hide(GTK_WIDGET(PWidget(scrollbarh))); + } + + if (verticalScrollBarVisible) { + gtk_widget_show(GTK_WIDGET(PWidget(scrollbarv))); + alloc.x = width - scrollBarWidth; + alloc.y = 0; + alloc.width = scrollBarWidth; + alloc.height = Platform::Maximum(1, height - scrollBarHeight); + if (!showSBHorizontal) + alloc.height += scrollBarWidth-1; + gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarv)), &alloc); + } else { + gtk_widget_hide(GTK_WIDGET(PWidget(scrollbarv))); + } + if (IS_WIDGET_MAPPED(PWidget(wMain))) { + ChangeSize(); + } + + alloc.x = 0; + alloc.y = 0; + alloc.width = Platform::Maximum(1, width - scrollBarWidth); + alloc.height = Platform::Maximum(1, height - scrollBarHeight); + if (!showSBHorizontal) + alloc.height += scrollBarHeight; + if (!verticalScrollBarVisible) + alloc.width += scrollBarWidth; + gtk_widget_size_allocate(GTK_WIDGET(PWidget(wText)), &alloc); +} + +static void SetAdjustmentValue(GtkAdjustment *object, int value) { + GtkAdjustment *adjustment = GTK_ADJUSTMENT(object); +#if GTK_CHECK_VERSION(3,0,0) + int maxValue = static_cast( + gtk_adjustment_get_upper(adjustment) - gtk_adjustment_get_page_size(adjustment)); +#else + int maxValue = static_cast( + adjustment->upper - adjustment->page_size); +#endif + + if (value > maxValue) + value = maxValue; + if (value < 0) + value = 0; + gtk_adjustment_set_value(adjustment, value); +} + +static int modifierTranslated(int sciModifier) { + switch (sciModifier) { + case SCMOD_SHIFT: + return GDK_SHIFT_MASK; + case SCMOD_CTRL: + return GDK_CONTROL_MASK; + case SCMOD_ALT: + return GDK_MOD1_MASK; + case SCMOD_SUPER: + return GDK_MOD4_MASK; + default: + return 0; + } +} + +gint ScintillaGTK::PressThis(GdkEventButton *event) { + try { + //Platform::DebugPrintf("Press %x time=%d state = %x button = %x\n",this,event->time, event->state, event->button); + // Do not use GTK+ double click events as Scintilla has its own double click detection + if (event->type != GDK_BUTTON_PRESS) + return FALSE; + + evbtn = *event; + Point pt; + pt.x = int(event->x); + pt.y = int(event->y); + PRectangle rcClient = GetClientRectangle(); + //Platform::DebugPrintf("Press %0d,%0d in %0d,%0d %0d,%0d\n", + // pt.x, pt.y, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); + if ((pt.x > rcClient.right) || (pt.y > rcClient.bottom)) { + Platform::DebugPrintf("Bad location\n"); + return FALSE; + } + + bool ctrl = (event->state & GDK_CONTROL_MASK) != 0; + + gtk_widget_grab_focus(PWidget(wMain)); + if (event->button == 1) { + // On X, instead of sending literal modifiers use the user specified + // modifier, defaulting to control instead of alt. + // This is because most X window managers grab alt + click for moving + ButtonDown(pt, event->time, + (event->state & GDK_SHIFT_MASK) != 0, + (event->state & GDK_CONTROL_MASK) != 0, + (event->state & modifierTranslated(rectangularSelectionModifier)) != 0); + } else if (event->button == 2) { + // Grab the primary selection if it exists + SelectionPosition pos = SPositionFromLocation(pt, false, false, UserVirtualSpace()); + if (OwnPrimarySelection() && primary.s == NULL) + CopySelectionRange(&primary); + + sel.Clear(); + SetSelection(pos, pos); + atomSought = atomUTF8; + gtk_selection_convert(GTK_WIDGET(PWidget(wMain)), GDK_SELECTION_PRIMARY, + atomSought, event->time); + } else if (event->button == 3) { + if (!PointInSelection(pt)) + SetEmptySelection(PositionFromLocation(pt)); + if (displayPopupMenu) { + // PopUp menu + // Convert to screen + int ox = 0; + int oy = 0; + gdk_window_get_origin(PWindow(wMain), &ox, &oy); + ContextMenu(Point(pt.x + ox, pt.y + oy)); + } else { + return FALSE; + } + } else if (event->button == 4) { + // Wheel scrolling up (only GTK 1.x does it this way) + if (ctrl) + SetAdjustmentValue(adjustmenth, (xOffset / 2) - 6); + else + SetAdjustmentValue(adjustmentv, topLine - 3); + } else if (event->button == 5) { + // Wheel scrolling down (only GTK 1.x does it this way) + if (ctrl) + SetAdjustmentValue(adjustmenth, (xOffset / 2) + 6); + else + SetAdjustmentValue(adjustmentv, topLine + 3); + } + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + return TRUE; +} + +gint ScintillaGTK::Press(GtkWidget *widget, GdkEventButton *event) { + if (event->window != WindowFromWidget(widget)) + return FALSE; + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + return sciThis->PressThis(event); +} + +gint ScintillaGTK::MouseRelease(GtkWidget *widget, GdkEventButton *event) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + try { + //Platform::DebugPrintf("Release %x %d %d\n",sciThis,event->time,event->state); + if (!sciThis->HaveMouseCapture()) + return FALSE; + if (event->button == 1) { + Point pt; + pt.x = int(event->x); + pt.y = int(event->y); + //Platform::DebugPrintf("Up %x %x %d %d %d\n", + // sciThis,event->window,event->time, pt.x, pt.y); + if (event->window != PWindow(sciThis->wMain)) + // If mouse released on scroll bar then the position is relative to the + // scrollbar, not the drawing window so just repeat the most recent point. + pt = sciThis->ptMouseLast; + sciThis->ButtonUp(pt, event->time, (event->state & 4) != 0); + } + } catch (...) { + sciThis->errorStatus = SC_STATUS_FAILURE; + } + return FALSE; +} + +// win32gtk and GTK >= 2 use SCROLL_* events instead of passing the +// button4/5/6/7 events to the GTK app +gint ScintillaGTK::ScrollEvent(GtkWidget *widget, + GdkEventScroll *event) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + try { + + if (widget == NULL || event == NULL) + return FALSE; + + // Compute amount and direction to scroll (even tho on win32 there is + // intensity of scrolling info in the native message, gtk doesn't + // support this so we simulate similarly adaptive scrolling) + // Note that this is disabled on OS X (Darwin) where the X11 server already has + // and adaptive scrolling algorithm that fights with this one + int cLineScroll; +#if defined(__MWERKS__) || defined(__APPLE_CPP__) || defined(__APPLE_CC__) + cLineScroll = sciThis->linesPerScroll; + if (cLineScroll == 0) + cLineScroll = 4; + sciThis->wheelMouseIntensity = cLineScroll; +#else + int timeDelta = 1000000; + GTimeVal curTime; + g_get_current_time(&curTime); + if (curTime.tv_sec == sciThis->lastWheelMouseTime.tv_sec) + timeDelta = curTime.tv_usec - sciThis->lastWheelMouseTime.tv_usec; + else if (curTime.tv_sec == sciThis->lastWheelMouseTime.tv_sec + 1) + timeDelta = 1000000 + (curTime.tv_usec - sciThis->lastWheelMouseTime.tv_usec); + if ((event->direction == sciThis->lastWheelMouseDirection) && (timeDelta < 250000)) { + if (sciThis->wheelMouseIntensity < 12) + sciThis->wheelMouseIntensity++; + cLineScroll = sciThis->wheelMouseIntensity; + } else { + cLineScroll = sciThis->linesPerScroll; + if (cLineScroll == 0) + cLineScroll = 4; + sciThis->wheelMouseIntensity = cLineScroll; + } +#endif + if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_LEFT) { + cLineScroll *= -1; + } + g_get_current_time(&sciThis->lastWheelMouseTime); + sciThis->lastWheelMouseDirection = event->direction; + + // Note: Unpatched versions of win32gtk don't set the 'state' value so + // only regular scrolling is supported there. Also, unpatched win32gtk + // issues spurious button 2 mouse events during wheeling, which can cause + // problems (a patch for both was submitted by archaeopteryx.com on 13Jun2001) + + // Data zoom not supported + if (event->state & GDK_SHIFT_MASK) { + return FALSE; + } + + // Horizontal scrolling + if (event->direction == GDK_SCROLL_LEFT || event->direction == GDK_SCROLL_RIGHT) { + sciThis->HorizontalScrollTo(sciThis->xOffset + cLineScroll); + + // Text font size zoom + } else if (event->state & GDK_CONTROL_MASK) { + if (cLineScroll < 0) { + sciThis->KeyCommand(SCI_ZOOMIN); + } else { + sciThis->KeyCommand(SCI_ZOOMOUT); + } + + // Regular scrolling + } else { + sciThis->ScrollTo(sciThis->topLine + cLineScroll); + } + return TRUE; + } catch (...) { + sciThis->errorStatus = SC_STATUS_FAILURE; + } + return FALSE; +} + +gint ScintillaGTK::Motion(GtkWidget *widget, GdkEventMotion *event) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + try { + //Platform::DebugPrintf("Motion %x %d\n",sciThis,event->time); + if (event->window != WindowFromWidget(widget)) + return FALSE; + int x = 0; + int y = 0; + GdkModifierType state; + if (event->is_hint) { + gdk_window_get_pointer(event->window, &x, &y, &state); + } else { + x = static_cast(event->x); + y = static_cast(event->y); + state = static_cast(event->state); + } + //Platform::DebugPrintf("Move %x %x %d %c %d %d\n", + // sciThis,event->window,event->time,event->is_hint? 'h' :'.', x, y); + Point pt(x, y); + sciThis->ButtonMove(pt); + } catch (...) { + sciThis->errorStatus = SC_STATUS_FAILURE; + } + return FALSE; +} + +// Map the keypad keys to their equivalent functions +static int KeyTranslate(int keyIn) { + switch (keyIn) { +#if GTK_CHECK_VERSION(3,0,0) + case GDK_KEY_ISO_Left_Tab: + return SCK_TAB; + case GDK_KEY_KP_Down: + return SCK_DOWN; + case GDK_KEY_KP_Up: + return SCK_UP; + case GDK_KEY_KP_Left: + return SCK_LEFT; + case GDK_KEY_KP_Right: + return SCK_RIGHT; + case GDK_KEY_KP_Home: + return SCK_HOME; + case GDK_KEY_KP_End: + return SCK_END; + case GDK_KEY_KP_Page_Up: + return SCK_PRIOR; + case GDK_KEY_KP_Page_Down: + return SCK_NEXT; + case GDK_KEY_KP_Delete: + return SCK_DELETE; + case GDK_KEY_KP_Insert: + return SCK_INSERT; + case GDK_KEY_KP_Enter: + return SCK_RETURN; + + case GDK_KEY_Down: + return SCK_DOWN; + case GDK_KEY_Up: + return SCK_UP; + case GDK_KEY_Left: + return SCK_LEFT; + case GDK_KEY_Right: + return SCK_RIGHT; + case GDK_KEY_Home: + return SCK_HOME; + case GDK_KEY_End: + return SCK_END; + case GDK_KEY_Page_Up: + return SCK_PRIOR; + case GDK_KEY_Page_Down: + return SCK_NEXT; + case GDK_KEY_Delete: + return SCK_DELETE; + case GDK_KEY_Insert: + return SCK_INSERT; + case GDK_KEY_Escape: + return SCK_ESCAPE; + case GDK_KEY_BackSpace: + return SCK_BACK; + case GDK_KEY_Tab: + return SCK_TAB; + case GDK_KEY_Return: + return SCK_RETURN; + case GDK_KEY_KP_Add: + return SCK_ADD; + case GDK_KEY_KP_Subtract: + return SCK_SUBTRACT; + case GDK_KEY_KP_Divide: + return SCK_DIVIDE; + case GDK_KEY_Super_L: + return SCK_WIN; + case GDK_KEY_Super_R: + return SCK_RWIN; + case GDK_KEY_Menu: + return SCK_MENU; + +#else + + case GDK_ISO_Left_Tab: + return SCK_TAB; + case GDK_KP_Down: + return SCK_DOWN; + case GDK_KP_Up: + return SCK_UP; + case GDK_KP_Left: + return SCK_LEFT; + case GDK_KP_Right: + return SCK_RIGHT; + case GDK_KP_Home: + return SCK_HOME; + case GDK_KP_End: + return SCK_END; + case GDK_KP_Page_Up: + return SCK_PRIOR; + case GDK_KP_Page_Down: + return SCK_NEXT; + case GDK_KP_Delete: + return SCK_DELETE; + case GDK_KP_Insert: + return SCK_INSERT; + case GDK_KP_Enter: + return SCK_RETURN; + + case GDK_Down: + return SCK_DOWN; + case GDK_Up: + return SCK_UP; + case GDK_Left: + return SCK_LEFT; + case GDK_Right: + return SCK_RIGHT; + case GDK_Home: + return SCK_HOME; + case GDK_End: + return SCK_END; + case GDK_Page_Up: + return SCK_PRIOR; + case GDK_Page_Down: + return SCK_NEXT; + case GDK_Delete: + return SCK_DELETE; + case GDK_Insert: + return SCK_INSERT; + case GDK_Escape: + return SCK_ESCAPE; + case GDK_BackSpace: + return SCK_BACK; + case GDK_Tab: + return SCK_TAB; + case GDK_Return: + return SCK_RETURN; + case GDK_KP_Add: + return SCK_ADD; + case GDK_KP_Subtract: + return SCK_SUBTRACT; + case GDK_KP_Divide: + return SCK_DIVIDE; + case GDK_Super_L: + return SCK_WIN; + case GDK_Super_R: + return SCK_RWIN; + case GDK_Menu: + return SCK_MENU; +#endif + default: + return keyIn; + } +} + +gboolean ScintillaGTK::KeyThis(GdkEventKey *event) { + try { + //fprintf(stderr, "SC-key: %d %x [%s]\n", + // event->keyval, event->state, (event->length > 0) ? event->string : "empty"); + if (gtk_im_context_filter_keypress(im_context, event)) { + return 1; + } + if (!event->keyval) { + return true; + } + + bool shift = (event->state & GDK_SHIFT_MASK) != 0; + bool ctrl = (event->state & GDK_CONTROL_MASK) != 0; + bool alt = (event->state & GDK_MOD1_MASK) != 0; + guint key = event->keyval; + if ((ctrl || alt) && (key < 128)) + key = toupper(key); +#if GTK_CHECK_VERSION(3,0,0) + else if (!ctrl && (key >= GDK_KEY_KP_Multiply && key <= GDK_KEY_KP_9)) +#else + else if (!ctrl && (key >= GDK_KP_Multiply && key <= GDK_KP_9)) +#endif + key &= 0x7F; + // Hack for keys over 256 and below command keys but makes Hungarian work. + // This will have to change for Unicode + else if (key >= 0xFE00) + key = KeyTranslate(key); + + bool consumed = false; +#if !(PLAT_GTK_MACOSX) + bool added = KeyDown(key, shift, ctrl, alt, &consumed) != 0; +#else + bool meta = ctrl; + ctrl = alt; + alt = (event->state & GDK_MOD5_MASK) != 0; + bool added = KeyDownWithModifiers(key, (shift ? SCI_SHIFT : 0) | + (ctrl ? SCI_CTRL : 0) | + (alt ? SCI_ALT : 0) | + (meta ? SCI_META : 0), &consumed) != 0; +#endif + if (!consumed) + consumed = added; + //fprintf(stderr, "SK-key: %d %x %x\n",event->keyval, event->state, consumed); + if (event->keyval == 0xffffff && event->length > 0) { + ClearSelection(); + if (pdoc->InsertCString(CurrentPosition(), event->string)) { + MovePositionTo(CurrentPosition() + event->length); + } + } + return consumed; + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + return FALSE; +} + +gboolean ScintillaGTK::KeyPress(GtkWidget *widget, GdkEventKey *event) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + return sciThis->KeyThis(event); +} + +gboolean ScintillaGTK::KeyRelease(GtkWidget *widget, GdkEventKey *event) { + //Platform::DebugPrintf("SC-keyrel: %d %x %3s\n",event->keyval, event->state, event->string); + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + if (gtk_im_context_filter_keypress(sciThis->im_context, event)) { + return TRUE; + } + return FALSE; +} + +#if GTK_CHECK_VERSION(3,0,0) + +gboolean ScintillaGTK::DrawPreeditThis(GtkWidget *widget, cairo_t *cr) { + try { + gchar *str; + gint cursor_pos; + PangoAttrList *attrs; + + gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos); + PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str); + pango_layout_set_attributes(layout, attrs); + + cairo_move_to(cr, 0, 0); + pango_cairo_show_layout(cr, layout); + + g_free(str); + pango_attr_list_unref(attrs); + g_object_unref(layout); + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + return TRUE; +} + +gboolean ScintillaGTK::DrawPreedit(GtkWidget *widget, cairo_t *cr, ScintillaGTK *sciThis) { + return sciThis->DrawPreeditThis(widget, cr); +} + +#else + +gboolean ScintillaGTK::ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose) { + try { + gchar *str; + gint cursor_pos; + PangoAttrList *attrs; + + gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos); + PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str); + pango_layout_set_attributes(layout, attrs); + + cairo_t *context = gdk_cairo_create(reinterpret_cast(WindowFromWidget(widget))); + cairo_move_to(context, 0, 0); + pango_cairo_show_layout(context, layout); + cairo_destroy(context); + g_free(str); + pango_attr_list_unref(attrs); + g_object_unref(layout); + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + return TRUE; +} + +gboolean ScintillaGTK::ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis) { + return sciThis->ExposePreeditThis(widget, ose); +} + +#endif + +void ScintillaGTK::CommitThis(char *utfVal) { + try { + //~ fprintf(stderr, "Commit '%s'\n", utfVal); + if (IsUnicodeMode()) { + AddCharUTF(utfVal, strlen(utfVal)); + } else { + const char *source = CharacterSetID(); + if (*source) { + Converter conv(source, "UTF-8", true); + if (conv) { + char localeVal[4] = "\0\0\0"; + char *pin = utfVal; + size_t inLeft = strlen(utfVal); + char *pout = localeVal; + size_t outLeft = sizeof(localeVal); + size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft); + if (conversions != ((size_t)(-1))) { + *pout = '\0'; + for (int i = 0; localeVal[i]; i++) { + AddChar(localeVal[i]); + } + } else { + fprintf(stderr, "Conversion failed '%s'\n", utfVal); + } + } + } + } + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::Commit(GtkIMContext *, char *str, ScintillaGTK *sciThis) { + sciThis->CommitThis(str); +} + +void ScintillaGTK::PreeditChangedThis() { + try { + gchar *str; + PangoAttrList *attrs; + gint cursor_pos; + gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos); + if (strlen(str) > 0) { + PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str); + pango_layout_set_attributes(layout, attrs); + + gint w, h; + pango_layout_get_pixel_size(layout, &w, &h); + g_object_unref(layout); + + gint x, y; + gdk_window_get_origin(PWindow(wText), &x, &y); + + Point pt = PointMainCaret(); + if (pt.x < 0) + pt.x = 0; + if (pt.y < 0) + pt.y = 0; + + gtk_window_move(GTK_WINDOW(PWidget(wPreedit)), x + pt.x, y + pt.y); + gtk_window_resize(GTK_WINDOW(PWidget(wPreedit)), w, h); + gtk_widget_show(PWidget(wPreedit)); + gtk_widget_queue_draw_area(PWidget(wPreeditDraw), 0, 0, w, h); + } else { + gtk_widget_hide(PWidget(wPreedit)); + } + g_free(str); + pango_attr_list_unref(attrs); + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::PreeditChanged(GtkIMContext *, ScintillaGTK *sciThis) { + sciThis->PreeditChangedThis(); +} + +void ScintillaGTK::StyleSetText(GtkWidget *widget, GtkStyle *, void*) { + RealizeText(widget, NULL); +} + +void ScintillaGTK::RealizeText(GtkWidget *widget, void*) { + // Set NULL background to avoid automatic clearing so Scintilla responsible for all drawing + if (WindowFromWidget(widget)) { +#if GTK_CHECK_VERSION(3,0,0) + gdk_window_set_background_pattern(WindowFromWidget(widget), NULL); +#else + gdk_window_set_back_pixmap(WindowFromWidget(widget), NULL, FALSE); +#endif + } +} + +void ScintillaGTK::Destroy(GObject *object) { + try { + ScintillaObject *scio = reinterpret_cast(object); + // This avoids a double destruction + if (!scio->pscin) + return; + ScintillaGTK *sciThis = reinterpret_cast(scio->pscin); + //Platform::DebugPrintf("Destroying %x %x\n", sciThis, object); + sciThis->Finalise(); + + delete sciThis; + scio->pscin = 0; + } catch (...) { + // Its dead so nowhere to save the status + } +} + +#if GTK_CHECK_VERSION(3,0,0) + +gboolean ScintillaGTK::DrawTextThis(cairo_t *cr) { + try { + paintState = painting; + + rcPaint = GetClientRectangle(); + + PLATFORM_ASSERT(rgnUpdate == NULL); + rgnUpdate = cairo_copy_clip_rectangle_list(cr); + if (rgnUpdate && rgnUpdate->status != CAIRO_STATUS_SUCCESS) { + // If not successful then ignore + fprintf(stderr, "DrawTextThis failed to copy update region %d [%d]\n", rgnUpdate->status, rgnUpdate->num_rectangles); + cairo_rectangle_list_destroy(rgnUpdate); + rgnUpdate = 0; + } + + double x1, y1, x2, y2; + cairo_clip_extents(cr, &x1, &y1, &x2, &y2); + rcPaint.left = x1; + rcPaint.top = y1; + rcPaint.right = x2; + rcPaint.bottom = y2; + PRectangle rcClient = GetClientRectangle(); + paintingAllText = rcPaint.Contains(rcClient); + Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); + if (surfaceWindow) { + surfaceWindow->Init(cr, PWidget(wText)); + Paint(surfaceWindow, rcPaint); + surfaceWindow->Release(); + delete surfaceWindow; + } + if (paintState == paintAbandoned) { + // Painting area was insufficient to cover new styling or brace highlight positions + FullPaint(); + } + paintState = notPainting; + + if (rgnUpdate) { + cairo_rectangle_list_destroy(rgnUpdate); + } + rgnUpdate = 0; + paintState = notPainting; + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + + return FALSE; +} + +gboolean ScintillaGTK::DrawText(GtkWidget *, cairo_t *cr, ScintillaGTK *sciThis) { + return sciThis->DrawTextThis(cr); +} + +gboolean ScintillaGTK::DrawThis(cairo_t *cr) { + try { + gtk_container_propagate_draw( + GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarh), cr); + gtk_container_propagate_draw( + GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarv), cr); + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + return FALSE; +} + +gboolean ScintillaGTK::DrawMain(GtkWidget *widget, cairo_t *cr) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + return sciThis->DrawThis(cr); +} + +#else + +gboolean ScintillaGTK::ExposeTextThis(GtkWidget * /*widget*/, GdkEventExpose *ose) { + try { + paintState = painting; + + rcPaint.left = ose->area.x; + rcPaint.top = ose->area.y; + rcPaint.right = ose->area.x + ose->area.width; + rcPaint.bottom = ose->area.y + ose->area.height; + + PLATFORM_ASSERT(rgnUpdate == NULL); + rgnUpdate = gdk_region_copy(ose->region); + PRectangle rcClient = GetClientRectangle(); + paintingAllText = rcPaint.Contains(rcClient); + Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); + if (surfaceWindow) { + cairo_t *cr = gdk_cairo_create(PWindow(wText)); + surfaceWindow->Init(cr, PWidget(wText)); + Paint(surfaceWindow, rcPaint); + surfaceWindow->Release(); + delete surfaceWindow; + cairo_destroy(cr); + } + if (paintState == paintAbandoned) { + // Painting area was insufficient to cover new styling or brace highlight positions + FullPaint(); + } + paintState = notPainting; + + if (rgnUpdate) { + gdk_region_destroy(rgnUpdate); + } + rgnUpdate = 0; + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + + return FALSE; +} + +gboolean ScintillaGTK::ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis) { + return sciThis->ExposeTextThis(widget, ose); +} + +gboolean ScintillaGTK::ExposeMain(GtkWidget *widget, GdkEventExpose *ose) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + //Platform::DebugPrintf("Expose Main %0d,%0d %0d,%0d\n", + //ose->area.x, ose->area.y, ose->area.width, ose->area.height); + return sciThis->Expose(widget, ose); +} + +gboolean ScintillaGTK::Expose(GtkWidget *, GdkEventExpose *ose) { + try { + //fprintf(stderr, "Expose %0d,%0d %0d,%0d\n", + //ose->area.x, ose->area.y, ose->area.width, ose->area.height); + + // The text is painted in ExposeText + gtk_container_propagate_expose( + GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarh), ose); + gtk_container_propagate_expose( + GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarv), ose); + + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + return FALSE; +} + +#endif + +void ScintillaGTK::ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis) { + try { +#if GTK_CHECK_VERSION(3,0,0) + sciThis->ScrollTo(static_cast(gtk_adjustment_get_value(adj)), false); +#else + sciThis->ScrollTo(static_cast(adj->value), false); +#endif + } catch (...) { + sciThis->errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis) { + try { +#if GTK_CHECK_VERSION(3,0,0) + sciThis->HorizontalScrollTo(static_cast(gtk_adjustment_get_value(adj) * 2)); +#else + sciThis->HorizontalScrollTo(static_cast(adj->value * 2)); +#endif + } catch (...) { + sciThis->errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::SelectionReceived(GtkWidget *widget, + GtkSelectionData *selection_data, guint) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + //Platform::DebugPrintf("Selection received\n"); + sciThis->ReceivedSelection(selection_data); +} + +void ScintillaGTK::SelectionGet(GtkWidget *widget, + GtkSelectionData *selection_data, guint info, guint) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + try { + //Platform::DebugPrintf("Selection get\n"); + if (SelectionOfGSD(selection_data) == GDK_SELECTION_PRIMARY) { + if (sciThis->primary.s == NULL) { + sciThis->CopySelectionRange(&sciThis->primary); + } + sciThis->GetSelection(selection_data, info, &sciThis->primary); + } + } catch (...) { + sciThis->errorStatus = SC_STATUS_FAILURE; + } +} + +gint ScintillaGTK::SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + //Platform::DebugPrintf("Selection clear\n"); + sciThis->UnclaimSelection(selection_event); + if (GTK_WIDGET_CLASS(sciThis->parentClass)->selection_clear_event) { + return GTK_WIDGET_CLASS(sciThis->parentClass)->selection_clear_event(widget, selection_event); + } + return TRUE; +} + +void ScintillaGTK::DragBegin(GtkWidget *, GdkDragContext *) { + //Platform::DebugPrintf("DragBegin\n"); +} + +gboolean ScintillaGTK::DragMotionThis(GdkDragContext *context, + gint x, gint y, guint dragtime) { + try { + Point npt(x, y); + SetDragPosition(SPositionFromLocation(npt, false, false, UserVirtualSpace())); +#if GTK_CHECK_VERSION(3,0,0) + GdkDragAction preferredAction = gdk_drag_context_get_suggested_action(context); + GdkDragAction actions = gdk_drag_context_get_actions(context); +#else + GdkDragAction preferredAction = context->suggested_action; + GdkDragAction actions = context->actions; +#endif + SelectionPosition pos = SPositionFromLocation(npt); + if ((inDragDrop == ddDragging) && (PositionInSelection(pos.Position()))) { + // Avoid dragging selection onto itself as that produces a move + // with no real effect but which creates undo actions. + preferredAction = static_cast(0); + } else if (actions == static_cast + (GDK_ACTION_COPY | GDK_ACTION_MOVE)) { + preferredAction = GDK_ACTION_MOVE; + } + gdk_drag_status(context, preferredAction, dragtime); + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + return FALSE; +} + +gboolean ScintillaGTK::DragMotion(GtkWidget *widget, GdkDragContext *context, + gint x, gint y, guint dragtime) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + return sciThis->DragMotionThis(context, x, y, dragtime); +} + +void ScintillaGTK::DragLeave(GtkWidget *widget, GdkDragContext * /*context*/, guint) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + try { + sciThis->SetDragPosition(SelectionPosition(invalidPosition)); + //Platform::DebugPrintf("DragLeave %x\n", sciThis); + } catch (...) { + sciThis->errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::DragEnd(GtkWidget *widget, GdkDragContext * /*context*/) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + try { + // If drag did not result in drop here or elsewhere + if (!sciThis->dragWasDropped) + sciThis->SetEmptySelection(sciThis->posDrag); + sciThis->SetDragPosition(SelectionPosition(invalidPosition)); + //Platform::DebugPrintf("DragEnd %x %d\n", sciThis, sciThis->dragWasDropped); + sciThis->inDragDrop = ddNone; + } catch (...) { + sciThis->errorStatus = SC_STATUS_FAILURE; + } +} + +gboolean ScintillaGTK::Drop(GtkWidget *widget, GdkDragContext * /*context*/, + gint, gint, guint) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + try { + //Platform::DebugPrintf("Drop %x\n", sciThis); + sciThis->SetDragPosition(SelectionPosition(invalidPosition)); + } catch (...) { + sciThis->errorStatus = SC_STATUS_FAILURE; + } + return FALSE; +} + +void ScintillaGTK::DragDataReceived(GtkWidget *widget, GdkDragContext * /*context*/, + gint, gint, GtkSelectionData *selection_data, guint /*info*/, guint) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + try { + sciThis->ReceivedDrop(selection_data); + sciThis->SetDragPosition(SelectionPosition(invalidPosition)); + } catch (...) { + sciThis->errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::DragDataGet(GtkWidget *widget, GdkDragContext *context, + GtkSelectionData *selection_data, guint info, guint) { + ScintillaGTK *sciThis = ScintillaFromWidget(widget); + try { + sciThis->dragWasDropped = true; + if (!sciThis->sel.Empty()) { + sciThis->GetSelection(selection_data, info, &sciThis->drag); + } +#if GTK_CHECK_VERSION(3,0,0) + GdkDragAction action = gdk_drag_context_get_selected_action(context); +#else + GdkDragAction action = context->action; +#endif + if (action == GDK_ACTION_MOVE) { + for (size_t r=0; rsel.Count(); r++) { + if (sciThis->posDrop >= sciThis->sel.Range(r).Start()) { + if (sciThis->posDrop > sciThis->sel.Range(r).End()) { + sciThis->posDrop.Add(-sciThis->sel.Range(r).Length()); + } else { + sciThis->posDrop.Add(-SelectionRange(sciThis->posDrop, sciThis->sel.Range(r).Start()).Length()); + } + } + } + sciThis->ClearSelection(); + } + sciThis->SetDragPosition(SelectionPosition(invalidPosition)); + } catch (...) { + sciThis->errorStatus = SC_STATUS_FAILURE; + } +} + +int ScintillaGTK::TimeOut(ScintillaGTK *sciThis) { + sciThis->Tick(); + return 1; +} + +gboolean ScintillaGTK::IdleCallback(ScintillaGTK *sciThis) { + // Idler will be automatically stopped, if there is nothing + // to do while idle. + gdk_threads_enter(); + bool ret = sciThis->Idle(); + if (ret == false) { + // FIXME: This will remove the idler from GTK, we don't want to + // remove it as it is removed automatically when this function + // returns false (although, it should be harmless). + sciThis->SetIdle(false); + } + gdk_threads_leave(); + return ret; +} + +gboolean ScintillaGTK::StyleIdle(ScintillaGTK *sciThis) { + gdk_threads_enter(); + sciThis->IdleStyling(); + gdk_threads_leave(); + // Idler will be automatically stopped + return FALSE; +} + +void ScintillaGTK::QueueStyling(int upTo) { + Editor::QueueStyling(upTo); + if (!styleNeeded.active) { + // Only allow one style needed to be queued + styleNeeded.active = true; + g_idle_add_full(G_PRIORITY_HIGH_IDLE, + reinterpret_cast(StyleIdle), this, NULL); + } +} + +void ScintillaGTK::PopUpCB(GtkMenuItem *menuItem, ScintillaGTK *sciThis) { + guint action = (sptr_t)(g_object_get_data(G_OBJECT(menuItem), "CmdNum")); + if (action) { + sciThis->Command(action); + } +} + +gboolean ScintillaGTK::PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis) { + try { + if (event->window != WindowFromWidget(widget)) + return FALSE; + if (event->type != GDK_BUTTON_PRESS) + return FALSE; + Point pt; + pt.x = int(event->x); + pt.y = int(event->y); + sciThis->ct.MouseClick(pt); + sciThis->CallTipClick(); + } catch (...) { + } + return TRUE; +} + +#if GTK_CHECK_VERSION(3,0,0) + +gboolean ScintillaGTK::DrawCT(GtkWidget *widget, cairo_t *cr, CallTip *ctip) { + try { + Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); + if (surfaceWindow) { + surfaceWindow->Init(cr, widget); + surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ctip->codePage); + surfaceWindow->SetDBCSMode(ctip->codePage); + ctip->PaintCT(surfaceWindow); + surfaceWindow->Release(); + delete surfaceWindow; + } + } catch (...) { + // No pointer back to Scintilla to save status + } + return TRUE; +} + +#else + +gboolean ScintillaGTK::ExposeCT(GtkWidget *widget, GdkEventExpose * /*ose*/, CallTip *ctip) { + try { + Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); + if (surfaceWindow) { + cairo_t *cr = gdk_cairo_create(WindowFromWidget(widget)); + surfaceWindow->Init(cr, widget); + surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ctip->codePage); + surfaceWindow->SetDBCSMode(ctip->codePage); + ctip->PaintCT(surfaceWindow); + surfaceWindow->Release(); + delete surfaceWindow; + cairo_destroy(cr); + } + } catch (...) { + // No pointer back to Scintilla to save status + } + return TRUE; +} + +#endif + +sptr_t ScintillaGTK::DirectFunction( + ScintillaGTK *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam) { + return sciThis->WndProc(iMessage, wParam, lParam); +} + +sptr_t scintilla_send_message(ScintillaObject *sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam) { + ScintillaGTK *psci = reinterpret_cast(sci->pscin); + return psci->WndProc(iMessage, wParam, lParam); +} + +static void scintilla_class_init(ScintillaClass *klass); +static void scintilla_init(ScintillaObject *sci); + +extern void Platform_Initialise(); +extern void Platform_Finalise(); + +GType scintilla_get_type() { + static GType scintilla_type = 0; + try { + + if (!scintilla_type) { + scintilla_type = g_type_from_name("Scintilla"); + if (!scintilla_type) { + static GTypeInfo scintilla_info = { + (guint16) sizeof (ScintillaClass), + NULL, //(GBaseInitFunc) + NULL, //(GBaseFinalizeFunc) + (GClassInitFunc) scintilla_class_init, + NULL, //(GClassFinalizeFunc) + NULL, //gconstpointer data + (guint16) sizeof (ScintillaObject), + 0, //n_preallocs + (GInstanceInitFunc) scintilla_init, + NULL //(GTypeValueTable*) + }; + + scintilla_type = g_type_register_static( + GTK_TYPE_CONTAINER, "Scintilla", &scintilla_info, (GTypeFlags) 0); + } + } + + } catch (...) { + } + return scintilla_type; +} + +void ScintillaGTK::ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class) { + Platform_Initialise(); +#ifdef SCI_LEXER + Scintilla_LinkLexers(); +#endif + atomClipboard = gdk_atom_intern("CLIPBOARD", FALSE); + atomUTF8 = gdk_atom_intern("UTF8_STRING", FALSE); + atomString = GDK_SELECTION_TYPE_STRING; + atomUriList = gdk_atom_intern("text/uri-list", FALSE); + atomDROPFILES_DND = gdk_atom_intern("DROPFILES_DND", FALSE); + + // Define default signal handlers for the class: Could move more + // of the signal handlers here (those that currently attached to wDraw + // in Initialise() may require coordinate translation?) + + object_class->finalize = Destroy; +#if GTK_CHECK_VERSION(3,0,0) + widget_class->get_preferred_width = GetPreferredWidth; + widget_class->get_preferred_height = GetPreferredHeight; +#else + widget_class->size_request = SizeRequest; +#endif + widget_class->size_allocate = SizeAllocate; +#if GTK_CHECK_VERSION(3,0,0) + widget_class->draw = DrawMain; +#else + widget_class->expose_event = ExposeMain; +#endif + widget_class->motion_notify_event = Motion; + widget_class->button_press_event = Press; + widget_class->button_release_event = MouseRelease; + widget_class->scroll_event = ScrollEvent; + widget_class->key_press_event = KeyPress; + widget_class->key_release_event = KeyRelease; + widget_class->focus_in_event = FocusIn; + widget_class->focus_out_event = FocusOut; + widget_class->selection_received = SelectionReceived; + widget_class->selection_get = SelectionGet; + widget_class->selection_clear_event = SelectionClear; + + widget_class->drag_data_received = DragDataReceived; + widget_class->drag_motion = DragMotion; + widget_class->drag_leave = DragLeave; + widget_class->drag_end = DragEnd; + widget_class->drag_drop = Drop; + widget_class->drag_data_get = DragDataGet; + + widget_class->realize = Realize; + widget_class->unrealize = UnRealize; + widget_class->map = Map; + widget_class->unmap = UnMap; + + container_class->forall = MainForAll; +} + +#define SIG_MARSHAL scintilla_marshal_NONE__INT_POINTER +#define MARSHAL_ARGUMENTS G_TYPE_INT, G_TYPE_POINTER + +static void scintilla_class_init(ScintillaClass *klass) { + try { + OBJECT_CLASS *object_class = (OBJECT_CLASS*) klass; + GtkWidgetClass *widget_class = (GtkWidgetClass*) klass; + GtkContainerClass *container_class = (GtkContainerClass*) klass; + + GSignalFlags sigflags = GSignalFlags(G_SIGNAL_ACTION | G_SIGNAL_RUN_LAST); + scintilla_signals[COMMAND_SIGNAL] = g_signal_new( + "command", + G_TYPE_FROM_CLASS(object_class), + sigflags, + G_STRUCT_OFFSET(ScintillaClass, command), + NULL, //(GSignalAccumulator) + NULL, //(gpointer) + SIG_MARSHAL, + G_TYPE_NONE, + 2, MARSHAL_ARGUMENTS); + + scintilla_signals[NOTIFY_SIGNAL] = g_signal_new( + SCINTILLA_NOTIFY, + G_TYPE_FROM_CLASS(object_class), + sigflags, + G_STRUCT_OFFSET(ScintillaClass, notify), + NULL, + NULL, + SIG_MARSHAL, + G_TYPE_NONE, + 2, MARSHAL_ARGUMENTS); + + klass->command = NULL; + klass->notify = NULL; + + ScintillaGTK::ClassInit(object_class, widget_class, container_class); + } catch (...) { + } +} + +static void scintilla_init(ScintillaObject *sci) { + try { +#if GTK_CHECK_VERSION(2,20,0) + gtk_widget_set_can_focus(GTK_WIDGET(sci), TRUE); +#else + GTK_WIDGET_SET_FLAGS(sci, GTK_CAN_FOCUS); +#endif + sci->pscin = new ScintillaGTK(sci); + } catch (...) { + } +} + +GtkWidget* scintilla_new() { + return GTK_WIDGET(g_object_new(scintilla_get_type(), NULL)); +} + +void scintilla_set_id(ScintillaObject *sci, uptr_t id) { + ScintillaGTK *psci = reinterpret_cast(sci->pscin); + psci->ctrlID = id; +} + +void scintilla_release_resources(void) { + try { + Platform_Finalise(); + } catch (...) { + } +} diff --git a/scintilla/gtk/deps.mak b/ThirdLibs/scintilla/gtk/deps.mak similarity index 98% rename from scintilla/gtk/deps.mak rename to ThirdLibs/scintilla/gtk/deps.mak index 285a9c81..c645e0bd 100644 --- a/scintilla/gtk/deps.mak +++ b/ThirdLibs/scintilla/gtk/deps.mak @@ -1,86 +1,86 @@ -PlatGTK.o: PlatGTK.cxx \ - ../include/Scintilla.h ../include/ScintillaWidget.h \ - ../src/UniConversion.h ../src/XPM.h Converter.h -ScintillaGTK.o: ScintillaGTK.cxx \ - ../include/ILexer.h ../include/Scintilla.h ../include/ScintillaWidget.h \ - ../include/SciLexer.h ../src/SVector.h ../src/SplitVector.h \ - ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \ - ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \ - ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \ - ../src/ViewStyle.h ../src/Decoration.h ../src/CharClassify.h \ - ../src/Document.h ../src/Selection.h ../src/PositionCache.h \ - ../src/Editor.h ../src/ScintillaBase.h ../src/UniConversion.h \ - scintilla-marshal.h ../lexlib/LexerModule.h ../src/ExternalLexer.h \ - Converter.h -AutoComplete.o: ../src/AutoComplete.cxx ../include/Platform.h \ - ../lexlib/CharacterSet.h ../src/AutoComplete.h -CallTip.o: ../src/CallTip.cxx ../include/Platform.h \ - ../include/Scintilla.h ../src/CallTip.h -Catalogue.o: ../src/Catalogue.cxx ../include/ILexer.h \ - ../include/Scintilla.h ../include/SciLexer.h ../lexlib/LexerModule.h \ - ../src/Catalogue.h -CellBuffer.o: ../src/CellBuffer.cxx ../include/Platform.h \ - ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ - ../src/CellBuffer.h -CharClassify.o: ../src/CharClassify.cxx ../src/CharClassify.h -ContractionState.o: ../src/ContractionState.cxx ../include/Platform.h \ - ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \ - ../src/ContractionState.h -Decoration.o: ../src/Decoration.cxx ../include/Platform.h \ - ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ - ../src/RunStyles.h ../src/Decoration.h -Document.o: ../src/Document.cxx ../include/Platform.h ../include/ILexer.h \ - ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ - ../src/RunStyles.h ../src/CellBuffer.h ../src/PerLine.h \ - ../src/CharClassify.h ../lexlib/CharacterSet.h ../src/Decoration.h \ - ../src/Document.h ../src/RESearch.h ../src/UniConversion.h -Editor.o: ../src/Editor.cxx ../include/Platform.h ../include/ILexer.h \ - ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ - ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \ - ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ - ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \ - ../src/Decoration.h ../src/Document.h ../src/Selection.h \ - ../src/PositionCache.h ../src/Editor.h -ExternalLexer.o: ../src/ExternalLexer.cxx ../include/Platform.h \ - ../include/ILexer.h ../include/Scintilla.h ../include/SciLexer.h \ - ../lexlib/LexerModule.h ../src/Catalogue.h ../src/ExternalLexer.h -Indicator.o: ../src/Indicator.cxx ../include/Platform.h \ - ../include/Scintilla.h ../src/Indicator.h -KeyMap.o: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \ - ../src/KeyMap.h -LineMarker.o: ../src/LineMarker.cxx ../include/Platform.h \ - ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h -PerLine.o: ../src/PerLine.cxx ../include/Platform.h \ - ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ - ../src/CellBuffer.h ../src/PerLine.h -PositionCache.o: ../src/PositionCache.cxx ../include/Platform.h \ - ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ - ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \ - ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ - ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \ - ../src/Decoration.h ../include/ILexer.h ../src/Document.h \ - ../src/Selection.h ../src/PositionCache.h -RESearch.o: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h -RunStyles.o: ../src/RunStyles.cxx ../include/Platform.h \ - ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ - ../src/RunStyles.h -ScintillaBase.o: ../src/ScintillaBase.cxx ../include/Platform.h \ - ../include/ILexer.h ../include/Scintilla.h ../lexlib/PropSetSimple.h \ - ../include/SciLexer.h ../lexlib/LexerModule.h ../src/Catalogue.h \ - ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \ - ../src/ContractionState.h ../src/CellBuffer.h ../src/CallTip.h \ - ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ - ../src/Style.h ../src/ViewStyle.h ../src/AutoComplete.h \ - ../src/CharClassify.h ../src/Decoration.h ../src/Document.h \ - ../src/Selection.h ../src/PositionCache.h ../src/Editor.h \ - ../src/ScintillaBase.h -Selection.o: ../src/Selection.cxx ../include/Platform.h \ - ../include/Scintilla.h ../src/Selection.h -Style.o: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \ - ../src/Style.h -UniConversion.o: ../src/UniConversion.cxx ../src/UniConversion.h -ViewStyle.o: ../src/ViewStyle.cxx ../include/Platform.h \ - ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ - ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ - ../src/Style.h ../src/ViewStyle.h -XPM.o: ../src/XPM.cxx ../include/Platform.h ../src/XPM.h +PlatGTK.o: PlatGTK.cxx \ + ../include/Scintilla.h ../include/ScintillaWidget.h \ + ../src/UniConversion.h ../src/XPM.h Converter.h +ScintillaGTK.o: ScintillaGTK.cxx \ + ../include/ILexer.h ../include/Scintilla.h ../include/ScintillaWidget.h \ + ../include/SciLexer.h ../src/SVector.h ../src/SplitVector.h \ + ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \ + ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \ + ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \ + ../src/ViewStyle.h ../src/Decoration.h ../src/CharClassify.h \ + ../src/Document.h ../src/Selection.h ../src/PositionCache.h \ + ../src/Editor.h ../src/ScintillaBase.h ../src/UniConversion.h \ + scintilla-marshal.h ../lexlib/LexerModule.h ../src/ExternalLexer.h \ + Converter.h +AutoComplete.o: ../src/AutoComplete.cxx ../include/Platform.h \ + ../lexlib/CharacterSet.h ../src/AutoComplete.h +CallTip.o: ../src/CallTip.cxx ../include/Platform.h \ + ../include/Scintilla.h ../src/CallTip.h +Catalogue.o: ../src/Catalogue.cxx ../include/ILexer.h \ + ../include/Scintilla.h ../include/SciLexer.h ../lexlib/LexerModule.h \ + ../src/Catalogue.h +CellBuffer.o: ../src/CellBuffer.cxx ../include/Platform.h \ + ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ + ../src/CellBuffer.h +CharClassify.o: ../src/CharClassify.cxx ../src/CharClassify.h +ContractionState.o: ../src/ContractionState.cxx ../include/Platform.h \ + ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \ + ../src/ContractionState.h +Decoration.o: ../src/Decoration.cxx ../include/Platform.h \ + ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ + ../src/RunStyles.h ../src/Decoration.h +Document.o: ../src/Document.cxx ../include/Platform.h ../include/ILexer.h \ + ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ + ../src/RunStyles.h ../src/CellBuffer.h ../src/PerLine.h \ + ../src/CharClassify.h ../lexlib/CharacterSet.h ../src/Decoration.h \ + ../src/Document.h ../src/RESearch.h ../src/UniConversion.h +Editor.o: ../src/Editor.cxx ../include/Platform.h ../include/ILexer.h \ + ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ + ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \ + ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ + ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \ + ../src/Decoration.h ../src/Document.h ../src/Selection.h \ + ../src/PositionCache.h ../src/Editor.h +ExternalLexer.o: ../src/ExternalLexer.cxx ../include/Platform.h \ + ../include/ILexer.h ../include/Scintilla.h ../include/SciLexer.h \ + ../lexlib/LexerModule.h ../src/Catalogue.h ../src/ExternalLexer.h +Indicator.o: ../src/Indicator.cxx ../include/Platform.h \ + ../include/Scintilla.h ../src/Indicator.h +KeyMap.o: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \ + ../src/KeyMap.h +LineMarker.o: ../src/LineMarker.cxx ../include/Platform.h \ + ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h +PerLine.o: ../src/PerLine.cxx ../include/Platform.h \ + ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ + ../src/CellBuffer.h ../src/PerLine.h +PositionCache.o: ../src/PositionCache.cxx ../include/Platform.h \ + ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ + ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \ + ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ + ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \ + ../src/Decoration.h ../include/ILexer.h ../src/Document.h \ + ../src/Selection.h ../src/PositionCache.h +RESearch.o: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h +RunStyles.o: ../src/RunStyles.cxx ../include/Platform.h \ + ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ + ../src/RunStyles.h +ScintillaBase.o: ../src/ScintillaBase.cxx ../include/Platform.h \ + ../include/ILexer.h ../include/Scintilla.h ../lexlib/PropSetSimple.h \ + ../include/SciLexer.h ../lexlib/LexerModule.h ../src/Catalogue.h \ + ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \ + ../src/ContractionState.h ../src/CellBuffer.h ../src/CallTip.h \ + ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ + ../src/Style.h ../src/ViewStyle.h ../src/AutoComplete.h \ + ../src/CharClassify.h ../src/Decoration.h ../src/Document.h \ + ../src/Selection.h ../src/PositionCache.h ../src/Editor.h \ + ../src/ScintillaBase.h +Selection.o: ../src/Selection.cxx ../include/Platform.h \ + ../include/Scintilla.h ../src/Selection.h +Style.o: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \ + ../src/Style.h +UniConversion.o: ../src/UniConversion.cxx ../src/UniConversion.h +ViewStyle.o: ../src/ViewStyle.cxx ../include/Platform.h \ + ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ + ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ + ../src/Style.h ../src/ViewStyle.h +XPM.o: ../src/XPM.cxx ../include/Platform.h ../src/XPM.h diff --git a/scintilla/gtk/makefile b/ThirdLibs/scintilla/gtk/makefile similarity index 96% rename from scintilla/gtk/makefile rename to ThirdLibs/scintilla/gtk/makefile index 72d4978a..4483205c 100644 --- a/scintilla/gtk/makefile +++ b/ThirdLibs/scintilla/gtk/makefile @@ -1,93 +1,93 @@ -# Make file for Scintilla on Linux or compatible OS -# Copyright 1998-2010 by Neil Hodgson -# The License.txt file describes the conditions under which this software may be distributed. -# This makefile assumes GCC 4.3 is used and changes will be needed to use other compilers. -# GNU make does not like \r\n line endings so should be saved to CVS in binary form. -# Builds for GTK+ 2 and no longer supports GTK+ 1. -# Also works with ming32-make on Windows. - -.SUFFIXES: .cxx .c .o .h .a -ifdef CLANG -CC = clang -CCOMP = clang -else -CC = g++ -CCOMP = gcc -endif -AR = ar -RANLIB = touch - -ifdef GTK3 -GTKVERSION=gtk+-3.0 -else -GTKVERSION=gtk+-2.0 -endif - -# Environment variable windir always defined on Win32 - -ifndef windir -ifeq ($(shell uname),Darwin) -RANLIB = ranlib -endif -endif - -ifdef windir -DEL = del /q -COMPLIB=..\bin\scintilla.a -else -DEL = rm -f -COMPLIB=../bin/scintilla.a -endif - -vpath %.h ../src ../include ../lexlib -vpath %.cxx ../src ../lexlib ../lexers - -INCLUDEDIRS=-I ../include -I ../src -I ../lexlib -ifdef CHECK_DEPRECATED -DEPRECATED=-DGDK_PIXBUF_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DDISABLE_GDK_FONT -endif -CXXBASEFLAGS=-Wall -Wno-missing-braces -Wno-char-subscripts -Wno-long-long -pedantic -DGTK -DSCI_LEXER $(INCLUDEDIRS) $(DEPRECATED) - -ifdef NOTHREADS -THREADFLAGS=-DG_THREADS_IMPL_NONE -else -THREADFLAGS= -endif - -ifdef DEBUG -CXXTFLAGS=-DDEBUG -g $(CXXFLAGS) $(CXXBASEFLAGS) $(THREADFLAGS) -else -CXXTFLAGS=-DNDEBUG -Os $(CXXFLAGS) $(CXXBASEFLAGS) $(THREADFLAGS) -endif - -CFLAGS:=$(CXXTFLAGS) - -CONFIGFLAGS:=$(shell pkg-config --cflags $(GTKVERSION)) -MARSHALLER=scintilla-marshal.o - -.cxx.o: - $(CC) $(CONFIGFLAGS) $(CXXTFLAGS) -c $< -.c.o: - $(CCOMP) $(CONFIGFLAGS) $(CFLAGS) -w -c $< - -LEXOBJS:=$(addsuffix .o,$(basename $(notdir $(wildcard ../lexers/Lex*.cxx)))) - -all: $(COMPLIB) - -clean: - $(DEL) *.o $(COMPLIB) - -deps: - $(CC) -MM $(CONFIGFLAGS) $(CXXTFLAGS) *.cxx ../src/*.cxx | sed -e 's/\/usr.* //' | grep [a-zA-Z] >deps.mak - -$(COMPLIB): Accessor.o CharacterSet.o LexerBase.o LexerModule.o LexerSimple.o StyleContext.o WordList.o \ - CharClassify.o Decoration.o Document.o PerLine.o Catalogue.o CallTip.o \ - ScintillaBase.o ContractionState.o Editor.o ExternalLexer.o PropSetSimple.o PlatGTK.o \ - KeyMap.o LineMarker.o PositionCache.o ScintillaGTK.o CellBuffer.o ViewStyle.o \ - RESearch.o RunStyles.o Selection.o Style.o Indicator.o AutoComplete.o UniConversion.o XPM.o \ - $(MARSHALLER) $(LEXOBJS) - $(AR) rc $@ $^ - $(RANLIB) $@ - -# Automatically generate header dependencies with "make deps" -include deps.mak +# Make file for Scintilla on Linux or compatible OS +# Copyright 1998-2010 by Neil Hodgson +# The License.txt file describes the conditions under which this software may be distributed. +# This makefile assumes GCC 4.3 is used and changes will be needed to use other compilers. +# GNU make does not like \r\n line endings so should be saved to CVS in binary form. +# Builds for GTK+ 2 and no longer supports GTK+ 1. +# Also works with ming32-make on Windows. + +.SUFFIXES: .cxx .c .o .h .a +ifdef CLANG +CC = clang +CCOMP = clang +else +CC = g++ +CCOMP = gcc +endif +AR = ar +RANLIB = touch + +ifdef GTK3 +GTKVERSION=gtk+-3.0 +else +GTKVERSION=gtk+-2.0 +endif + +# Environment variable windir always defined on Win32 + +ifndef windir +ifeq ($(shell uname),Darwin) +RANLIB = ranlib +endif +endif + +ifdef windir +DEL = del /q +COMPLIB=..\bin\scintilla.a +else +DEL = rm -f +COMPLIB=../bin/scintilla.a +endif + +vpath %.h ../src ../include ../lexlib +vpath %.cxx ../src ../lexlib ../lexers + +INCLUDEDIRS=-I ../include -I ../src -I ../lexlib +ifdef CHECK_DEPRECATED +DEPRECATED=-DGDK_PIXBUF_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DDISABLE_GDK_FONT +endif +CXXBASEFLAGS=-Wall -Wno-missing-braces -Wno-char-subscripts -Wno-long-long -pedantic -DGTK -DSCI_LEXER $(INCLUDEDIRS) $(DEPRECATED) + +ifdef NOTHREADS +THREADFLAGS=-DG_THREADS_IMPL_NONE +else +THREADFLAGS= +endif + +ifdef DEBUG +CXXTFLAGS=-DDEBUG -g $(CXXFLAGS) $(CXXBASEFLAGS) $(THREADFLAGS) +else +CXXTFLAGS=-DNDEBUG -Os $(CXXFLAGS) $(CXXBASEFLAGS) $(THREADFLAGS) +endif + +CFLAGS:=$(CXXTFLAGS) + +CONFIGFLAGS:=$(shell pkg-config --cflags $(GTKVERSION)) +MARSHALLER=scintilla-marshal.o + +.cxx.o: + $(CC) $(CONFIGFLAGS) $(CXXTFLAGS) -c $< +.c.o: + $(CCOMP) $(CONFIGFLAGS) $(CFLAGS) -w -c $< + +LEXOBJS:=$(addsuffix .o,$(basename $(notdir $(wildcard ../lexers/Lex*.cxx)))) + +all: $(COMPLIB) + +clean: + $(DEL) *.o $(COMPLIB) + +deps: + $(CC) -MM $(CONFIGFLAGS) $(CXXTFLAGS) *.cxx ../src/*.cxx | sed -e 's/\/usr.* //' | grep [a-zA-Z] >deps.mak + +$(COMPLIB): Accessor.o CharacterSet.o LexerBase.o LexerModule.o LexerSimple.o StyleContext.o WordList.o \ + CharClassify.o Decoration.o Document.o PerLine.o Catalogue.o CallTip.o \ + ScintillaBase.o ContractionState.o Editor.o ExternalLexer.o PropSetSimple.o PlatGTK.o \ + KeyMap.o LineMarker.o PositionCache.o ScintillaGTK.o CellBuffer.o ViewStyle.o \ + RESearch.o RunStyles.o Selection.o Style.o Indicator.o AutoComplete.o UniConversion.o XPM.o \ + $(MARSHALLER) $(LEXOBJS) + $(AR) rc $@ $^ + $(RANLIB) $@ + +# Automatically generate header dependencies with "make deps" +include deps.mak diff --git a/scintilla/gtk/scintilla-marshal.c b/ThirdLibs/scintilla/gtk/scintilla-marshal.c similarity index 97% rename from scintilla/gtk/scintilla-marshal.c rename to ThirdLibs/scintilla/gtk/scintilla-marshal.c index 02da1843..be57b7c2 100644 --- a/scintilla/gtk/scintilla-marshal.c +++ b/ThirdLibs/scintilla/gtk/scintilla-marshal.c @@ -1,86 +1,86 @@ - -#include - - -#ifdef G_ENABLE_DEBUG -#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) -#define g_marshal_value_peek_char(v) g_value_get_char (v) -#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) -#define g_marshal_value_peek_int(v) g_value_get_int (v) -#define g_marshal_value_peek_uint(v) g_value_get_uint (v) -#define g_marshal_value_peek_long(v) g_value_get_long (v) -#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) -#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) -#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) -#define g_marshal_value_peek_enum(v) g_value_get_enum (v) -#define g_marshal_value_peek_flags(v) g_value_get_flags (v) -#define g_marshal_value_peek_float(v) g_value_get_float (v) -#define g_marshal_value_peek_double(v) g_value_get_double (v) -#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) -#define g_marshal_value_peek_param(v) g_value_get_param (v) -#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) -#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) -#define g_marshal_value_peek_object(v) g_value_get_object (v) -#else /* !G_ENABLE_DEBUG */ -/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. - * Do not access GValues directly in your code. Instead, use the - * g_value_get_*() functions - */ -#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int -#define g_marshal_value_peek_char(v) (v)->data[0].v_int -#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint -#define g_marshal_value_peek_int(v) (v)->data[0].v_int -#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint -#define g_marshal_value_peek_long(v) (v)->data[0].v_long -#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 -#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 -#define g_marshal_value_peek_enum(v) (v)->data[0].v_int -#define g_marshal_value_peek_flags(v) (v)->data[0].v_uint -#define g_marshal_value_peek_float(v) (v)->data[0].v_float -#define g_marshal_value_peek_double(v) (v)->data[0].v_double -#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer -#endif /* !G_ENABLE_DEBUG */ - - -/* NONE:INT,POINTER (scintilla-marshal.list:1) */ -void -scintilla_marshal_VOID__INT_POINTER (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__INT_POINTER) (gpointer data1, - gint arg_1, - gpointer arg_2, - gpointer data2); - register GMarshalFunc_VOID__INT_POINTER callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__INT_POINTER) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_int (param_values + 1), - g_marshal_value_peek_pointer (param_values + 2), - data2); -} - + +#include + + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_char (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_int +#define g_marshal_value_peek_flags(v) (v)->data[0].v_uint +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* NONE:INT,POINTER (scintilla-marshal.list:1) */ +void +scintilla_marshal_VOID__INT_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__INT_POINTER) (gpointer data1, + gint arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__INT_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__INT_POINTER) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_int (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); +} + diff --git a/scintilla/gtk/scintilla-marshal.h b/ThirdLibs/scintilla/gtk/scintilla-marshal.h similarity index 97% rename from scintilla/gtk/scintilla-marshal.h rename to ThirdLibs/scintilla/gtk/scintilla-marshal.h index 28e94ccc..9116a56c 100644 --- a/scintilla/gtk/scintilla-marshal.h +++ b/ThirdLibs/scintilla/gtk/scintilla-marshal.h @@ -1,21 +1,21 @@ - -#ifndef __scintilla_marshal_MARSHAL_H__ -#define __scintilla_marshal_MARSHAL_H__ - -#include - -G_BEGIN_DECLS - -/* NONE:INT,POINTER (scintilla-marshal.list:1) */ -extern void scintilla_marshal_VOID__INT_POINTER (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); -#define scintilla_marshal_NONE__INT_POINTER scintilla_marshal_VOID__INT_POINTER - -G_END_DECLS - -#endif /* __scintilla_marshal_MARSHAL_H__ */ - + +#ifndef __scintilla_marshal_MARSHAL_H__ +#define __scintilla_marshal_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +/* NONE:INT,POINTER (scintilla-marshal.list:1) */ +extern void scintilla_marshal_VOID__INT_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +#define scintilla_marshal_NONE__INT_POINTER scintilla_marshal_VOID__INT_POINTER + +G_END_DECLS + +#endif /* __scintilla_marshal_MARSHAL_H__ */ + diff --git a/scintilla/gtk/scintilla-marshal.list b/ThirdLibs/scintilla/gtk/scintilla-marshal.list similarity index 100% rename from scintilla/gtk/scintilla-marshal.list rename to ThirdLibs/scintilla/gtk/scintilla-marshal.list diff --git a/scintilla/include/Face.py b/ThirdLibs/scintilla/include/Face.py similarity index 96% rename from scintilla/include/Face.py rename to ThirdLibs/scintilla/include/Face.py index 642b9577..97b700dc 100644 --- a/scintilla/include/Face.py +++ b/ThirdLibs/scintilla/include/Face.py @@ -1,110 +1,110 @@ -# Module for reading and parsing Scintilla.iface file - -def sanitiseLine(line): - if line[-1:] == '\n': line = line[:-1] - if line.find("##") != -1: - line = line[:line.find("##")] - line = line.strip() - return line - -def decodeFunction(featureVal): - retType, rest = featureVal.split(" ", 1) - nameIdent, params = rest.split("(") - name, value = nameIdent.split("=") - params, rest = params.split(")") - param1, param2 = params.split(",")[0:2] - return retType, name, value, param1, param2 - -def decodeEvent(featureVal): - retType, rest = featureVal.split(" ", 1) - nameIdent, params = rest.split("(") - name, value = nameIdent.split("=") - return retType, name, value - -def decodeParam(p): - param = p.strip() - type = "" - name = "" - value = "" - if " " in param: - type, nv = param.split(" ") - if "=" in nv: - name, value = nv.split("=") - else: - name = nv - return type, name, value - -class Face: - - def __init__(self): - self.order = [] - self.features = {} - self.values = {} - self.events = {} - - def ReadFromFile(self, name): - currentCategory = "" - currentComment = [] - currentCommentFinished = 0 - file = open(name) - for line in file.readlines(): - line = sanitiseLine(line) - if line: - if line[0] == "#": - if line[1] == " ": - if currentCommentFinished: - currentComment = [] - currentCommentFinished = 0 - currentComment.append(line[2:]) - else: - currentCommentFinished = 1 - featureType, featureVal = line.split(" ", 1) - if featureType in ["fun", "get", "set"]: - retType, name, value, param1, param2 = decodeFunction(featureVal) - p1 = decodeParam(param1) - p2 = decodeParam(param2) - self.features[name] = { - "FeatureType": featureType, - "ReturnType": retType, - "Value": value, - "Param1Type": p1[0], "Param1Name": p1[1], "Param1Value": p1[2], - "Param2Type": p2[0], "Param2Name": p2[1], "Param2Value": p2[2], - "Category": currentCategory, "Comment": currentComment - } - if value in self.values: - raise Exception("Duplicate value " + value + " " + name) - self.values[value] = 1 - self.order.append(name) - elif featureType == "evt": - retType, name, value = decodeEvent(featureVal) - self.features[name] = { - "FeatureType": featureType, - "ReturnType": retType, - "Value": value, - "Category": currentCategory, "Comment": currentComment - } - if value in self.events: - raise Exception("Duplicate event " + value + " " + name) - self.events[value] = 1 - self.order.append(name) - elif featureType == "cat": - currentCategory = featureVal - elif featureType == "val": - try: - name, value = featureVal.split("=", 1) - except ValueError: - print("Failure %s" % featureVal) - raise Exception() - self.features[name] = { - "FeatureType": featureType, - "Category": currentCategory, - "Value": value } - self.order.append(name) - elif featureType == "enu" or featureType == "lex": - name, value = featureVal.split("=", 1) - self.features[name] = { - "FeatureType": featureType, - "Category": currentCategory, - "Value": value } - self.order.append(name) - +# Module for reading and parsing Scintilla.iface file + +def sanitiseLine(line): + if line[-1:] == '\n': line = line[:-1] + if line.find("##") != -1: + line = line[:line.find("##")] + line = line.strip() + return line + +def decodeFunction(featureVal): + retType, rest = featureVal.split(" ", 1) + nameIdent, params = rest.split("(") + name, value = nameIdent.split("=") + params, rest = params.split(")") + param1, param2 = params.split(",")[0:2] + return retType, name, value, param1, param2 + +def decodeEvent(featureVal): + retType, rest = featureVal.split(" ", 1) + nameIdent, params = rest.split("(") + name, value = nameIdent.split("=") + return retType, name, value + +def decodeParam(p): + param = p.strip() + type = "" + name = "" + value = "" + if " " in param: + type, nv = param.split(" ") + if "=" in nv: + name, value = nv.split("=") + else: + name = nv + return type, name, value + +class Face: + + def __init__(self): + self.order = [] + self.features = {} + self.values = {} + self.events = {} + + def ReadFromFile(self, name): + currentCategory = "" + currentComment = [] + currentCommentFinished = 0 + file = open(name) + for line in file.readlines(): + line = sanitiseLine(line) + if line: + if line[0] == "#": + if line[1] == " ": + if currentCommentFinished: + currentComment = [] + currentCommentFinished = 0 + currentComment.append(line[2:]) + else: + currentCommentFinished = 1 + featureType, featureVal = line.split(" ", 1) + if featureType in ["fun", "get", "set"]: + retType, name, value, param1, param2 = decodeFunction(featureVal) + p1 = decodeParam(param1) + p2 = decodeParam(param2) + self.features[name] = { + "FeatureType": featureType, + "ReturnType": retType, + "Value": value, + "Param1Type": p1[0], "Param1Name": p1[1], "Param1Value": p1[2], + "Param2Type": p2[0], "Param2Name": p2[1], "Param2Value": p2[2], + "Category": currentCategory, "Comment": currentComment + } + if value in self.values: + raise Exception("Duplicate value " + value + " " + name) + self.values[value] = 1 + self.order.append(name) + elif featureType == "evt": + retType, name, value = decodeEvent(featureVal) + self.features[name] = { + "FeatureType": featureType, + "ReturnType": retType, + "Value": value, + "Category": currentCategory, "Comment": currentComment + } + if value in self.events: + raise Exception("Duplicate event " + value + " " + name) + self.events[value] = 1 + self.order.append(name) + elif featureType == "cat": + currentCategory = featureVal + elif featureType == "val": + try: + name, value = featureVal.split("=", 1) + except ValueError: + print("Failure %s" % featureVal) + raise Exception() + self.features[name] = { + "FeatureType": featureType, + "Category": currentCategory, + "Value": value } + self.order.append(name) + elif featureType == "enu" or featureType == "lex": + name, value = featureVal.split("=", 1) + self.features[name] = { + "FeatureType": featureType, + "Category": currentCategory, + "Value": value } + self.order.append(name) + diff --git a/scintilla/include/HFacer.py b/ThirdLibs/scintilla/include/HFacer.py similarity index 96% rename from scintilla/include/HFacer.py rename to ThirdLibs/scintilla/include/HFacer.py index 1dc25bed..074ce96b 100644 --- a/scintilla/include/HFacer.py +++ b/ThirdLibs/scintilla/include/HFacer.py @@ -1,76 +1,76 @@ -#!/usr/bin/env python -# HFacer.py - regenerate the Scintilla.h and SciLexer.h files from the Scintilla.iface interface -# definition file. -# The header files are copied to a temporary file apart from the section between a /* ++Autogenerated*/ -# comment and a /* --Autogenerated*/ comment which is generated by the printHFile and printLexHFile -# functions. After the temporary file is created, it is copied back to the original file name. - -import sys -import os -import Face - -def Contains(s,sub): - return s.find(sub) != -1 - -def printLexHFile(f,out): - for name in f.order: - v = f.features[name] - if v["FeatureType"] in ["val"]: - if Contains(name, "SCE_") or Contains(name, "SCLEX_"): - out.write("#define " + name + " " + v["Value"] + "\n") - -def printHFile(f,out): - for name in f.order: - v = f.features[name] - if v["Category"] != "Deprecated": - if v["FeatureType"] in ["fun", "get", "set"]: - featureDefineName = "SCI_" + name.upper() - out.write("#define " + featureDefineName + " " + v["Value"] + "\n") - elif v["FeatureType"] in ["evt"]: - featureDefineName = "SCN_" + name.upper() - out.write("#define " + featureDefineName + " " + v["Value"] + "\n") - elif v["FeatureType"] in ["val"]: - if not (Contains(name, "SCE_") or Contains(name, "SCLEX_")): - out.write("#define " + name + " " + v["Value"] + "\n") - -def CopyWithInsertion(input, output, genfn, definition): - copying = 1 - for line in input.readlines(): - if copying: - output.write(line) - if Contains(line, "/* ++Autogenerated"): - copying = 0 - genfn(definition, output) - if Contains(line, "/* --Autogenerated"): - copying = 1 - output.write(line) - -def contents(filename): - f = open(filename) - t = f.read() - f.close() - return t - -def Regenerate(filename, genfn, definition): - inText = contents(filename) - tempname = "HFacer.tmp" - out = open(tempname,"w") - hfile = open(filename) - CopyWithInsertion(hfile, out, genfn, definition) - out.close() - hfile.close() - outText = contents(tempname) - if inText == outText: - os.unlink(tempname) - else: - os.unlink(filename) - os.rename(tempname, filename) - -f = Face.Face() -try: - f.ReadFromFile("Scintilla.iface") - Regenerate("Scintilla.h", printHFile, f) - Regenerate("SciLexer.h", printLexHFile, f) - print("Maximum ID is %s" % max([x for x in f.values if int(x) < 3000])) -except: - raise +#!/usr/bin/env python +# HFacer.py - regenerate the Scintilla.h and SciLexer.h files from the Scintilla.iface interface +# definition file. +# The header files are copied to a temporary file apart from the section between a /* ++Autogenerated*/ +# comment and a /* --Autogenerated*/ comment which is generated by the printHFile and printLexHFile +# functions. After the temporary file is created, it is copied back to the original file name. + +import sys +import os +import Face + +def Contains(s,sub): + return s.find(sub) != -1 + +def printLexHFile(f,out): + for name in f.order: + v = f.features[name] + if v["FeatureType"] in ["val"]: + if Contains(name, "SCE_") or Contains(name, "SCLEX_"): + out.write("#define " + name + " " + v["Value"] + "\n") + +def printHFile(f,out): + for name in f.order: + v = f.features[name] + if v["Category"] != "Deprecated": + if v["FeatureType"] in ["fun", "get", "set"]: + featureDefineName = "SCI_" + name.upper() + out.write("#define " + featureDefineName + " " + v["Value"] + "\n") + elif v["FeatureType"] in ["evt"]: + featureDefineName = "SCN_" + name.upper() + out.write("#define " + featureDefineName + " " + v["Value"] + "\n") + elif v["FeatureType"] in ["val"]: + if not (Contains(name, "SCE_") or Contains(name, "SCLEX_")): + out.write("#define " + name + " " + v["Value"] + "\n") + +def CopyWithInsertion(input, output, genfn, definition): + copying = 1 + for line in input.readlines(): + if copying: + output.write(line) + if Contains(line, "/* ++Autogenerated"): + copying = 0 + genfn(definition, output) + if Contains(line, "/* --Autogenerated"): + copying = 1 + output.write(line) + +def contents(filename): + f = open(filename) + t = f.read() + f.close() + return t + +def Regenerate(filename, genfn, definition): + inText = contents(filename) + tempname = "HFacer.tmp" + out = open(tempname,"w") + hfile = open(filename) + CopyWithInsertion(hfile, out, genfn, definition) + out.close() + hfile.close() + outText = contents(tempname) + if inText == outText: + os.unlink(tempname) + else: + os.unlink(filename) + os.rename(tempname, filename) + +f = Face.Face() +try: + f.ReadFromFile("Scintilla.iface") + Regenerate("Scintilla.h", printHFile, f) + Regenerate("SciLexer.h", printLexHFile, f) + print("Maximum ID is %s" % max([x for x in f.values if int(x) < 3000])) +except: + raise diff --git a/scintilla/include/ILexer.h b/ThirdLibs/scintilla/include/ILexer.h similarity index 97% rename from scintilla/include/ILexer.h rename to ThirdLibs/scintilla/include/ILexer.h index 723e8cde..e08b8701 100644 --- a/scintilla/include/ILexer.h +++ b/ThirdLibs/scintilla/include/ILexer.h @@ -1,77 +1,77 @@ -// Scintilla source code edit control -/** @file ILexer.h - ** Interface between Scintilla and lexers. - **/ -// Copyright 1998-2010 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef ILEXER_H -#define ILEXER_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -#ifdef _WIN32 - #define SCI_METHOD __stdcall -#else - #define SCI_METHOD -#endif - -enum { dvOriginal=0 }; - -class IDocument { -public: - virtual int SCI_METHOD Version() const = 0; - virtual void SCI_METHOD SetErrorStatus(int status) = 0; - virtual int SCI_METHOD Length() const = 0; - virtual void SCI_METHOD GetCharRange(char *buffer, int position, int lengthRetrieve) const = 0; - virtual char SCI_METHOD StyleAt(int position) const = 0; - virtual int SCI_METHOD LineFromPosition(int position) const = 0; - virtual int SCI_METHOD LineStart(int line) const = 0; - virtual int SCI_METHOD GetLevel(int line) const = 0; - virtual int SCI_METHOD SetLevel(int line, int level) = 0; - virtual int SCI_METHOD GetLineState(int line) const = 0; - virtual int SCI_METHOD SetLineState(int line, int state) = 0; - virtual void SCI_METHOD StartStyling(int position, char mask) = 0; - virtual bool SCI_METHOD SetStyleFor(int length, char style) = 0; - virtual bool SCI_METHOD SetStyles(int length, const char *styles) = 0; - virtual void SCI_METHOD DecorationSetCurrentIndicator(int indicator) = 0; - virtual void SCI_METHOD DecorationFillRange(int position, int value, int fillLength) = 0; - virtual void SCI_METHOD ChangeLexerState(int start, int end) = 0; - virtual int SCI_METHOD CodePage() const = 0; - virtual bool SCI_METHOD IsDBCSLeadByte(char ch) const = 0; - virtual const char * SCI_METHOD BufferPointer() = 0; - virtual int SCI_METHOD GetLineIndentation(int line) = 0; -}; - -enum { lvOriginal=0 }; - -class ILexer { -public: - virtual int SCI_METHOD Version() const = 0; - virtual void SCI_METHOD Release() = 0; - virtual const char * SCI_METHOD PropertyNames() = 0; - virtual int SCI_METHOD PropertyType(const char *name) = 0; - virtual const char * SCI_METHOD DescribeProperty(const char *name) = 0; - virtual int SCI_METHOD PropertySet(const char *key, const char *val) = 0; - virtual const char * SCI_METHOD DescribeWordListSets() = 0; - virtual int SCI_METHOD WordListSet(int n, const char *wl) = 0; - virtual void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0; - virtual void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0; - virtual void * SCI_METHOD PrivateCall(int operation, void *pointer) = 0; -}; - -class ILoader { -public: - virtual int SCI_METHOD Release() = 0; - // Returns a status code from SC_STATUS_* - virtual int SCI_METHOD AddData(char *data, int length) = 0; - virtual void * SCI_METHOD ConvertToDocument() = 0; -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif +// Scintilla source code edit control +/** @file ILexer.h + ** Interface between Scintilla and lexers. + **/ +// Copyright 1998-2010 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef ILEXER_H +#define ILEXER_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +#ifdef _WIN32 + #define SCI_METHOD __stdcall +#else + #define SCI_METHOD +#endif + +enum { dvOriginal=0 }; + +class IDocument { +public: + virtual int SCI_METHOD Version() const = 0; + virtual void SCI_METHOD SetErrorStatus(int status) = 0; + virtual int SCI_METHOD Length() const = 0; + virtual void SCI_METHOD GetCharRange(char *buffer, int position, int lengthRetrieve) const = 0; + virtual char SCI_METHOD StyleAt(int position) const = 0; + virtual int SCI_METHOD LineFromPosition(int position) const = 0; + virtual int SCI_METHOD LineStart(int line) const = 0; + virtual int SCI_METHOD GetLevel(int line) const = 0; + virtual int SCI_METHOD SetLevel(int line, int level) = 0; + virtual int SCI_METHOD GetLineState(int line) const = 0; + virtual int SCI_METHOD SetLineState(int line, int state) = 0; + virtual void SCI_METHOD StartStyling(int position, char mask) = 0; + virtual bool SCI_METHOD SetStyleFor(int length, char style) = 0; + virtual bool SCI_METHOD SetStyles(int length, const char *styles) = 0; + virtual void SCI_METHOD DecorationSetCurrentIndicator(int indicator) = 0; + virtual void SCI_METHOD DecorationFillRange(int position, int value, int fillLength) = 0; + virtual void SCI_METHOD ChangeLexerState(int start, int end) = 0; + virtual int SCI_METHOD CodePage() const = 0; + virtual bool SCI_METHOD IsDBCSLeadByte(char ch) const = 0; + virtual const char * SCI_METHOD BufferPointer() = 0; + virtual int SCI_METHOD GetLineIndentation(int line) = 0; +}; + +enum { lvOriginal=0 }; + +class ILexer { +public: + virtual int SCI_METHOD Version() const = 0; + virtual void SCI_METHOD Release() = 0; + virtual const char * SCI_METHOD PropertyNames() = 0; + virtual int SCI_METHOD PropertyType(const char *name) = 0; + virtual const char * SCI_METHOD DescribeProperty(const char *name) = 0; + virtual int SCI_METHOD PropertySet(const char *key, const char *val) = 0; + virtual const char * SCI_METHOD DescribeWordListSets() = 0; + virtual int SCI_METHOD WordListSet(int n, const char *wl) = 0; + virtual void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0; + virtual void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0; + virtual void * SCI_METHOD PrivateCall(int operation, void *pointer) = 0; +}; + +class ILoader { +public: + virtual int SCI_METHOD Release() = 0; + // Returns a status code from SC_STATUS_* + virtual int SCI_METHOD AddData(char *data, int length) = 0; + virtual void * SCI_METHOD ConvertToDocument() = 0; +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/scintilla/include/Platform.h b/ThirdLibs/scintilla/include/Platform.h similarity index 96% rename from scintilla/include/Platform.h rename to ThirdLibs/scintilla/include/Platform.h index 46c36428..654c4870 100644 --- a/scintilla/include/Platform.h +++ b/ThirdLibs/scintilla/include/Platform.h @@ -1,514 +1,514 @@ -// Scintilla source code edit control -/** @file Platform.h - ** Interface to platform facilities. Also includes some basic utilities. - ** Implemented in PlatGTK.cxx for GTK+/Linux, PlatWin.cxx for Windows, and PlatWX.cxx for wxWindows. - **/ -// Copyright 1998-2009 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef PLATFORM_H -#define PLATFORM_H - -// PLAT_GTK = GTK+ on Linux or Win32 -// PLAT_GTK_WIN32 is defined additionally when running PLAT_GTK under Win32 -// PLAT_WIN = Win32 API on Win32 OS -// PLAT_WX is wxWindows on any supported platform - -#define PLAT_GTK 0 -#define PLAT_GTK_WIN32 0 -#define PLAT_GTK_MACOSX 0 -#define PLAT_MACOSX 0 -#define PLAT_WIN 0 -#define PLAT_WX 0 -#define PLAT_FOX 0 - -#if defined(FOX) -#undef PLAT_FOX -#define PLAT_FOX 1 - -#elif defined(__WX__) -#undef PLAT_WX -#define PLAT_WX 1 - -#elif defined(GTK) -#undef PLAT_GTK -#define PLAT_GTK 1 - -#if defined(__WIN32__) || defined(_MSC_VER) -#undef PLAT_GTK_WIN32 -#define PLAT_GTK_WIN32 1 -#endif - -#if defined(__APPLE__) -#undef PLAT_GTK_MACOSX -#define PLAT_GTK_MACOSX 1 -#endif - -#elif defined(__APPLE__) - -#undef PLAT_MACOSX -#define PLAT_MACOSX 1 - -#else -#undef PLAT_WIN -#define PLAT_WIN 1 - -#endif - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -typedef float XYPOSITION; -typedef double XYACCUMULATOR; -//#define XYPOSITION int - -// Underlying the implementation of the platform classes are platform specific types. -// Sometimes these need to be passed around by client code so they are defined here - -typedef void *FontID; -typedef void *SurfaceID; -typedef void *WindowID; -typedef void *MenuID; -typedef void *TickerID; -typedef void *Function; -typedef void *IdlerID; - -/** - * A geometric point class. - * Point is exactly the same as the Win32 POINT and GTK+ GdkPoint so can be used interchangeably. - */ -class Point { -public: - XYPOSITION x; - XYPOSITION y; - - explicit Point(XYPOSITION x_=0, XYPOSITION y_=0) : x(x_), y(y_) { - } - - // Other automatically defined methods (assignment, copy constructor, destructor) are fine - - static Point FromLong(long lpoint); -}; - -/** - * A geometric rectangle class. - * PRectangle is exactly the same as the Win32 RECT so can be used interchangeably. - * PRectangles contain their top and left sides, but not their right and bottom sides. - */ -class PRectangle { -public: - XYPOSITION left; - XYPOSITION top; - XYPOSITION right; - XYPOSITION bottom; - - PRectangle(XYPOSITION left_=0, XYPOSITION top_=0, XYPOSITION right_=0, XYPOSITION bottom_ = 0) : - left(left_), top(top_), right(right_), bottom(bottom_) { - } - - // Other automatically defined methods (assignment, copy constructor, destructor) are fine - - bool operator==(PRectangle &rc) { - return (rc.left == left) && (rc.right == right) && - (rc.top == top) && (rc.bottom == bottom); - } - bool Contains(Point pt) { - return (pt.x >= left) && (pt.x <= right) && - (pt.y >= top) && (pt.y <= bottom); - } - bool Contains(PRectangle rc) { - return (rc.left >= left) && (rc.right <= right) && - (rc.top >= top) && (rc.bottom <= bottom); - } - bool Intersects(PRectangle other) { - return (right > other.left) && (left < other.right) && - (bottom > other.top) && (top < other.bottom); - } - void Move(XYPOSITION xDelta, XYPOSITION yDelta) { - left += xDelta; - top += yDelta; - right += xDelta; - bottom += yDelta; - } - XYPOSITION Width() { return right - left; } - XYPOSITION Height() { return bottom - top; } - bool Empty() { - return (Height() <= 0) || (Width() <= 0); - } -}; - -/** - * Holds a desired RGB colour. - */ -class ColourDesired { - long co; -public: - ColourDesired(long lcol=0) { - co = lcol; - } - - ColourDesired(unsigned int red, unsigned int green, unsigned int blue) { - Set(red, green, blue); - } - - bool operator==(const ColourDesired &other) const { - return co == other.co; - } - - void Set(long lcol) { - co = lcol; - } - - void Set(unsigned int red, unsigned int green, unsigned int blue) { - co = red | (green << 8) | (blue << 16); - } - - static inline unsigned int ValueOfHex(const char ch) { - if (ch >= '0' && ch <= '9') - return ch - '0'; - else if (ch >= 'A' && ch <= 'F') - return ch - 'A' + 10; - else if (ch >= 'a' && ch <= 'f') - return ch - 'a' + 10; - else - return 0; - } - - void Set(const char *val) { - if (*val == '#') { - val++; - } - unsigned int r = ValueOfHex(val[0]) * 16 + ValueOfHex(val[1]); - unsigned int g = ValueOfHex(val[2]) * 16 + ValueOfHex(val[3]); - unsigned int b = ValueOfHex(val[4]) * 16 + ValueOfHex(val[5]); - Set(r, g, b); - } - - long AsLong() const { - return co; - } - - unsigned int GetRed() { - return co & 0xff; - } - - unsigned int GetGreen() { - return (co >> 8) & 0xff; - } - - unsigned int GetBlue() { - return (co >> 16) & 0xff; - } -}; - -/** - * Font management. - */ - -struct FontParameters { - const char *faceName; - float size; - int weight; - bool italic; - int extraFontFlag; - int technology; - int characterSet; - - FontParameters( - const char *faceName_, - float size_=10, - int weight_=400, - bool italic_=false, - int extraFontFlag_=0, - int technology_=0, - int characterSet_=0) : - - faceName(faceName_), - size(size_), - weight(weight_), - italic(italic_), - extraFontFlag(extraFontFlag_), - technology(technology_), - characterSet(characterSet_) - { - } - -}; - -class Font { -protected: - FontID fid; -#if PLAT_WX - int ascent; -#endif - // Private so Font objects can not be copied - Font(const Font &); - Font &operator=(const Font &); -public: - Font(); - virtual ~Font(); - - virtual void Create(const FontParameters &fp); - virtual void Release(); - - FontID GetID() { return fid; } - // Alias another font - caller guarantees not to Release - void SetID(FontID fid_) { fid = fid_; } -#if PLAT_WX - void SetAscent(int ascent_) { ascent = ascent_; } -#endif - friend class Surface; - friend class SurfaceImpl; -}; - -/** - * A surface abstracts a place to draw. - */ -class Surface { -private: - // Private so Surface objects can not be copied - Surface(const Surface &) {} - Surface &operator=(const Surface &) { return *this; } -public: - Surface() {} - virtual ~Surface() {} - static Surface *Allocate(int technology); - - virtual void Init(WindowID wid)=0; - virtual void Init(SurfaceID sid, WindowID wid)=0; - virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid)=0; - - virtual void Release()=0; - virtual bool Initialised()=0; - virtual void PenColour(ColourDesired fore)=0; - virtual int LogPixelsY()=0; - virtual int DeviceHeightFont(int points)=0; - virtual void MoveTo(int x_, int y_)=0; - virtual void LineTo(int x_, int y_)=0; - virtual void Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back)=0; - virtual void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back)=0; - virtual void FillRectangle(PRectangle rc, ColourDesired back)=0; - virtual void FillRectangle(PRectangle rc, Surface &surfacePattern)=0; - virtual void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back)=0; - virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill, - ColourDesired outline, int alphaOutline, int flags)=0; - virtual void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) = 0; - virtual void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back)=0; - virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource)=0; - - virtual void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back)=0; - virtual void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back)=0; - virtual void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore)=0; - virtual void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions)=0; - virtual XYPOSITION WidthText(Font &font_, const char *s, int len)=0; - virtual XYPOSITION WidthChar(Font &font_, char ch)=0; - virtual XYPOSITION Ascent(Font &font_)=0; - virtual XYPOSITION Descent(Font &font_)=0; - virtual XYPOSITION InternalLeading(Font &font_)=0; - virtual XYPOSITION ExternalLeading(Font &font_)=0; - virtual XYPOSITION Height(Font &font_)=0; - virtual XYPOSITION AverageCharWidth(Font &font_)=0; - - virtual void SetClip(PRectangle rc)=0; - virtual void FlushCachedState()=0; - - virtual void SetUnicodeMode(bool unicodeMode_)=0; - virtual void SetDBCSMode(int codePage)=0; -}; - -/** - * A simple callback action passing one piece of untyped user data. - */ -typedef void (*CallBackAction)(void*); - -/** - * Class to hide the details of window manipulation. - * Does not own the window which will normally have a longer life than this object. - */ -class Window { -protected: - WindowID wid; -#if PLAT_MACOSX - void *windowRef; - void *control; -#endif -public: - Window() : wid(0), cursorLast(cursorInvalid) { -#if PLAT_MACOSX - windowRef = 0; - control = 0; -#endif - } - Window(const Window &source) : wid(source.wid), cursorLast(cursorInvalid) { -#if PLAT_MACOSX - windowRef = 0; - control = 0; -#endif - } - virtual ~Window(); - Window &operator=(WindowID wid_) { - wid = wid_; - return *this; - } - WindowID GetID() const { return wid; } - bool Created() const { return wid != 0; } - void Destroy(); - bool HasFocus(); - PRectangle GetPosition(); - void SetPosition(PRectangle rc); - void SetPositionRelative(PRectangle rc, Window relativeTo); - PRectangle GetClientPosition(); - void Show(bool show=true); - void InvalidateAll(); - void InvalidateRectangle(PRectangle rc); - virtual void SetFont(Font &font); - enum Cursor { cursorInvalid, cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow, cursorHand }; - void SetCursor(Cursor curs); - void SetTitle(const char *s); - PRectangle GetMonitorRect(Point pt); -#if PLAT_MACOSX - void SetWindow(void *ref) { windowRef = ref; } - void SetControl(void *_control) { control = _control; } -#endif -private: - Cursor cursorLast; -}; - -/** - * Listbox management. - */ - -class ListBox : public Window { -public: - ListBox(); - virtual ~ListBox(); - static ListBox *Allocate(); - - virtual void SetFont(Font &font)=0; - virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_, int technology_)=0; - virtual void SetAverageCharWidth(int width)=0; - virtual void SetVisibleRows(int rows)=0; - virtual int GetVisibleRows() const=0; - virtual PRectangle GetDesiredRect()=0; - virtual int CaretFromEdge()=0; - virtual void Clear()=0; - virtual void Append(char *s, int type = -1)=0; - virtual int Length()=0; - virtual void Select(int n)=0; - virtual int GetSelection()=0; - virtual int Find(const char *prefix)=0; - virtual void GetValue(int n, char *value, int len)=0; - virtual void RegisterImage(int type, const char *xpm_data)=0; - virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) = 0; - virtual void ClearRegisteredImages()=0; - virtual void SetDoubleClickAction(CallBackAction, void *)=0; - virtual void SetList(const char* list, char separator, char typesep)=0; -}; - -/** - * Menu management. - */ -class Menu { - MenuID mid; -public: - Menu(); - MenuID GetID() { return mid; } - void CreatePopUp(); - void Destroy(); - void Show(Point pt, Window &w); -}; - -class ElapsedTime { - long bigBit; - long littleBit; -public: - ElapsedTime(); - double Duration(bool reset=false); -}; - -/** - * Dynamic Library (DLL/SO/...) loading - */ -class DynamicLibrary { -public: - virtual ~DynamicLibrary() {} - - /// @return Pointer to function "name", or NULL on failure. - virtual Function FindFunction(const char *name) = 0; - - /// @return true if the library was loaded successfully. - virtual bool IsValid() = 0; - - /// @return An instance of a DynamicLibrary subclass with "modulePath" loaded. - static DynamicLibrary *Load(const char *modulePath); -}; - -/** - * Platform class used to retrieve system wide parameters such as double click speed - * and chrome colour. Not a creatable object, more of a module with several functions. - */ -class Platform { - // Private so Platform objects can not be copied - Platform(const Platform &) {} - Platform &operator=(const Platform &) { return *this; } -public: - // Should be private because no new Platforms are ever created - // but gcc warns about this - Platform() {} - ~Platform() {} - static ColourDesired Chrome(); - static ColourDesired ChromeHighlight(); - static const char *DefaultFont(); - static int DefaultFontSize(); - static unsigned int DoubleClickTime(); - static bool MouseButtonBounce(); - static void DebugDisplay(const char *s); - static bool IsKeyDown(int key); - static long SendScintilla( - WindowID w, unsigned int msg, unsigned long wParam=0, long lParam=0); - static long SendScintillaPointer( - WindowID w, unsigned int msg, unsigned long wParam=0, void *lParam=0); - static bool IsDBCSLeadByte(int codePage, char ch); - static int DBCSCharLength(int codePage, const char *s); - static int DBCSCharMaxLength(); - - // These are utility functions not really tied to a platform - static int Minimum(int a, int b); - static int Maximum(int a, int b); - // Next three assume 16 bit shorts and 32 bit longs - static long LongFromTwoShorts(short a,short b) { - return (a) | ((b) << 16); - } - static short HighShortFromLong(long x) { - return static_cast(x >> 16); - } - static short LowShortFromLong(long x) { - return static_cast(x & 0xffff); - } - static void DebugPrintf(const char *format, ...); - static bool ShowAssertionPopUps(bool assertionPopUps_); - static void Assert(const char *c, const char *file, int line); - static int Clamp(int val, int minVal, int maxVal); -}; - -#ifdef NDEBUG -#define PLATFORM_ASSERT(c) ((void)0) -#else -#ifdef SCI_NAMESPACE -#define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Scintilla::Platform::Assert(#c, __FILE__, __LINE__)) -#else -#define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Platform::Assert(#c, __FILE__, __LINE__)) -#endif -#endif - -#ifdef SCI_NAMESPACE -} -#endif - -// Shut up annoying Visual C++ warnings: -#ifdef _MSC_VER -#pragma warning(disable: 4244 4309 4514 4710) -#endif - -#endif +// Scintilla source code edit control +/** @file Platform.h + ** Interface to platform facilities. Also includes some basic utilities. + ** Implemented in PlatGTK.cxx for GTK+/Linux, PlatWin.cxx for Windows, and PlatWX.cxx for wxWindows. + **/ +// Copyright 1998-2009 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef PLATFORM_H +#define PLATFORM_H + +// PLAT_GTK = GTK+ on Linux or Win32 +// PLAT_GTK_WIN32 is defined additionally when running PLAT_GTK under Win32 +// PLAT_WIN = Win32 API on Win32 OS +// PLAT_WX is wxWindows on any supported platform + +#define PLAT_GTK 0 +#define PLAT_GTK_WIN32 0 +#define PLAT_GTK_MACOSX 0 +#define PLAT_MACOSX 0 +#define PLAT_WIN 0 +#define PLAT_WX 0 +#define PLAT_FOX 0 + +#if defined(FOX) +#undef PLAT_FOX +#define PLAT_FOX 1 + +#elif defined(__WX__) +#undef PLAT_WX +#define PLAT_WX 1 + +#elif defined(GTK) +#undef PLAT_GTK +#define PLAT_GTK 1 + +#if defined(__WIN32__) || defined(_MSC_VER) +#undef PLAT_GTK_WIN32 +#define PLAT_GTK_WIN32 1 +#endif + +#if defined(__APPLE__) +#undef PLAT_GTK_MACOSX +#define PLAT_GTK_MACOSX 1 +#endif + +#elif defined(__APPLE__) + +#undef PLAT_MACOSX +#define PLAT_MACOSX 1 + +#else +#undef PLAT_WIN +#define PLAT_WIN 1 + +#endif + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +typedef float XYPOSITION; +typedef double XYACCUMULATOR; +//#define XYPOSITION int + +// Underlying the implementation of the platform classes are platform specific types. +// Sometimes these need to be passed around by client code so they are defined here + +typedef void *FontID; +typedef void *SurfaceID; +typedef void *WindowID; +typedef void *MenuID; +typedef void *TickerID; +typedef void *Function; +typedef void *IdlerID; + +/** + * A geometric point class. + * Point is exactly the same as the Win32 POINT and GTK+ GdkPoint so can be used interchangeably. + */ +class Point { +public: + XYPOSITION x; + XYPOSITION y; + + explicit Point(XYPOSITION x_=0, XYPOSITION y_=0) : x(x_), y(y_) { + } + + // Other automatically defined methods (assignment, copy constructor, destructor) are fine + + static Point FromLong(long lpoint); +}; + +/** + * A geometric rectangle class. + * PRectangle is exactly the same as the Win32 RECT so can be used interchangeably. + * PRectangles contain their top and left sides, but not their right and bottom sides. + */ +class PRectangle { +public: + XYPOSITION left; + XYPOSITION top; + XYPOSITION right; + XYPOSITION bottom; + + PRectangle(XYPOSITION left_=0, XYPOSITION top_=0, XYPOSITION right_=0, XYPOSITION bottom_ = 0) : + left(left_), top(top_), right(right_), bottom(bottom_) { + } + + // Other automatically defined methods (assignment, copy constructor, destructor) are fine + + bool operator==(PRectangle &rc) { + return (rc.left == left) && (rc.right == right) && + (rc.top == top) && (rc.bottom == bottom); + } + bool Contains(Point pt) { + return (pt.x >= left) && (pt.x <= right) && + (pt.y >= top) && (pt.y <= bottom); + } + bool Contains(PRectangle rc) { + return (rc.left >= left) && (rc.right <= right) && + (rc.top >= top) && (rc.bottom <= bottom); + } + bool Intersects(PRectangle other) { + return (right > other.left) && (left < other.right) && + (bottom > other.top) && (top < other.bottom); + } + void Move(XYPOSITION xDelta, XYPOSITION yDelta) { + left += xDelta; + top += yDelta; + right += xDelta; + bottom += yDelta; + } + XYPOSITION Width() { return right - left; } + XYPOSITION Height() { return bottom - top; } + bool Empty() { + return (Height() <= 0) || (Width() <= 0); + } +}; + +/** + * Holds a desired RGB colour. + */ +class ColourDesired { + long co; +public: + ColourDesired(long lcol=0) { + co = lcol; + } + + ColourDesired(unsigned int red, unsigned int green, unsigned int blue) { + Set(red, green, blue); + } + + bool operator==(const ColourDesired &other) const { + return co == other.co; + } + + void Set(long lcol) { + co = lcol; + } + + void Set(unsigned int red, unsigned int green, unsigned int blue) { + co = red | (green << 8) | (blue << 16); + } + + static inline unsigned int ValueOfHex(const char ch) { + if (ch >= '0' && ch <= '9') + return ch - '0'; + else if (ch >= 'A' && ch <= 'F') + return ch - 'A' + 10; + else if (ch >= 'a' && ch <= 'f') + return ch - 'a' + 10; + else + return 0; + } + + void Set(const char *val) { + if (*val == '#') { + val++; + } + unsigned int r = ValueOfHex(val[0]) * 16 + ValueOfHex(val[1]); + unsigned int g = ValueOfHex(val[2]) * 16 + ValueOfHex(val[3]); + unsigned int b = ValueOfHex(val[4]) * 16 + ValueOfHex(val[5]); + Set(r, g, b); + } + + long AsLong() const { + return co; + } + + unsigned int GetRed() { + return co & 0xff; + } + + unsigned int GetGreen() { + return (co >> 8) & 0xff; + } + + unsigned int GetBlue() { + return (co >> 16) & 0xff; + } +}; + +/** + * Font management. + */ + +struct FontParameters { + const char *faceName; + float size; + int weight; + bool italic; + int extraFontFlag; + int technology; + int characterSet; + + FontParameters( + const char *faceName_, + float size_=10, + int weight_=400, + bool italic_=false, + int extraFontFlag_=0, + int technology_=0, + int characterSet_=0) : + + faceName(faceName_), + size(size_), + weight(weight_), + italic(italic_), + extraFontFlag(extraFontFlag_), + technology(technology_), + characterSet(characterSet_) + { + } + +}; + +class Font { +protected: + FontID fid; +#if PLAT_WX + int ascent; +#endif + // Private so Font objects can not be copied + Font(const Font &); + Font &operator=(const Font &); +public: + Font(); + virtual ~Font(); + + virtual void Create(const FontParameters &fp); + virtual void Release(); + + FontID GetID() { return fid; } + // Alias another font - caller guarantees not to Release + void SetID(FontID fid_) { fid = fid_; } +#if PLAT_WX + void SetAscent(int ascent_) { ascent = ascent_; } +#endif + friend class Surface; + friend class SurfaceImpl; +}; + +/** + * A surface abstracts a place to draw. + */ +class Surface { +private: + // Private so Surface objects can not be copied + Surface(const Surface &) {} + Surface &operator=(const Surface &) { return *this; } +public: + Surface() {} + virtual ~Surface() {} + static Surface *Allocate(int technology); + + virtual void Init(WindowID wid)=0; + virtual void Init(SurfaceID sid, WindowID wid)=0; + virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid)=0; + + virtual void Release()=0; + virtual bool Initialised()=0; + virtual void PenColour(ColourDesired fore)=0; + virtual int LogPixelsY()=0; + virtual int DeviceHeightFont(int points)=0; + virtual void MoveTo(int x_, int y_)=0; + virtual void LineTo(int x_, int y_)=0; + virtual void Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back)=0; + virtual void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back)=0; + virtual void FillRectangle(PRectangle rc, ColourDesired back)=0; + virtual void FillRectangle(PRectangle rc, Surface &surfacePattern)=0; + virtual void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back)=0; + virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill, + ColourDesired outline, int alphaOutline, int flags)=0; + virtual void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) = 0; + virtual void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back)=0; + virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource)=0; + + virtual void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back)=0; + virtual void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back)=0; + virtual void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore)=0; + virtual void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions)=0; + virtual XYPOSITION WidthText(Font &font_, const char *s, int len)=0; + virtual XYPOSITION WidthChar(Font &font_, char ch)=0; + virtual XYPOSITION Ascent(Font &font_)=0; + virtual XYPOSITION Descent(Font &font_)=0; + virtual XYPOSITION InternalLeading(Font &font_)=0; + virtual XYPOSITION ExternalLeading(Font &font_)=0; + virtual XYPOSITION Height(Font &font_)=0; + virtual XYPOSITION AverageCharWidth(Font &font_)=0; + + virtual void SetClip(PRectangle rc)=0; + virtual void FlushCachedState()=0; + + virtual void SetUnicodeMode(bool unicodeMode_)=0; + virtual void SetDBCSMode(int codePage)=0; +}; + +/** + * A simple callback action passing one piece of untyped user data. + */ +typedef void (*CallBackAction)(void*); + +/** + * Class to hide the details of window manipulation. + * Does not own the window which will normally have a longer life than this object. + */ +class Window { +protected: + WindowID wid; +#if PLAT_MACOSX + void *windowRef; + void *control; +#endif +public: + Window() : wid(0), cursorLast(cursorInvalid) { +#if PLAT_MACOSX + windowRef = 0; + control = 0; +#endif + } + Window(const Window &source) : wid(source.wid), cursorLast(cursorInvalid) { +#if PLAT_MACOSX + windowRef = 0; + control = 0; +#endif + } + virtual ~Window(); + Window &operator=(WindowID wid_) { + wid = wid_; + return *this; + } + WindowID GetID() const { return wid; } + bool Created() const { return wid != 0; } + void Destroy(); + bool HasFocus(); + PRectangle GetPosition(); + void SetPosition(PRectangle rc); + void SetPositionRelative(PRectangle rc, Window relativeTo); + PRectangle GetClientPosition(); + void Show(bool show=true); + void InvalidateAll(); + void InvalidateRectangle(PRectangle rc); + virtual void SetFont(Font &font); + enum Cursor { cursorInvalid, cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow, cursorHand }; + void SetCursor(Cursor curs); + void SetTitle(const char *s); + PRectangle GetMonitorRect(Point pt); +#if PLAT_MACOSX + void SetWindow(void *ref) { windowRef = ref; } + void SetControl(void *_control) { control = _control; } +#endif +private: + Cursor cursorLast; +}; + +/** + * Listbox management. + */ + +class ListBox : public Window { +public: + ListBox(); + virtual ~ListBox(); + static ListBox *Allocate(); + + virtual void SetFont(Font &font)=0; + virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_, int technology_)=0; + virtual void SetAverageCharWidth(int width)=0; + virtual void SetVisibleRows(int rows)=0; + virtual int GetVisibleRows() const=0; + virtual PRectangle GetDesiredRect()=0; + virtual int CaretFromEdge()=0; + virtual void Clear()=0; + virtual void Append(char *s, int type = -1)=0; + virtual int Length()=0; + virtual void Select(int n)=0; + virtual int GetSelection()=0; + virtual int Find(const char *prefix)=0; + virtual void GetValue(int n, char *value, int len)=0; + virtual void RegisterImage(int type, const char *xpm_data)=0; + virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) = 0; + virtual void ClearRegisteredImages()=0; + virtual void SetDoubleClickAction(CallBackAction, void *)=0; + virtual void SetList(const char* list, char separator, char typesep)=0; +}; + +/** + * Menu management. + */ +class Menu { + MenuID mid; +public: + Menu(); + MenuID GetID() { return mid; } + void CreatePopUp(); + void Destroy(); + void Show(Point pt, Window &w); +}; + +class ElapsedTime { + long bigBit; + long littleBit; +public: + ElapsedTime(); + double Duration(bool reset=false); +}; + +/** + * Dynamic Library (DLL/SO/...) loading + */ +class DynamicLibrary { +public: + virtual ~DynamicLibrary() {} + + /// @return Pointer to function "name", or NULL on failure. + virtual Function FindFunction(const char *name) = 0; + + /// @return true if the library was loaded successfully. + virtual bool IsValid() = 0; + + /// @return An instance of a DynamicLibrary subclass with "modulePath" loaded. + static DynamicLibrary *Load(const char *modulePath); +}; + +/** + * Platform class used to retrieve system wide parameters such as double click speed + * and chrome colour. Not a creatable object, more of a module with several functions. + */ +class Platform { + // Private so Platform objects can not be copied + Platform(const Platform &) {} + Platform &operator=(const Platform &) { return *this; } +public: + // Should be private because no new Platforms are ever created + // but gcc warns about this + Platform() {} + ~Platform() {} + static ColourDesired Chrome(); + static ColourDesired ChromeHighlight(); + static const char *DefaultFont(); + static int DefaultFontSize(); + static unsigned int DoubleClickTime(); + static bool MouseButtonBounce(); + static void DebugDisplay(const char *s); + static bool IsKeyDown(int key); + static long SendScintilla( + WindowID w, unsigned int msg, unsigned long wParam=0, long lParam=0); + static long SendScintillaPointer( + WindowID w, unsigned int msg, unsigned long wParam=0, void *lParam=0); + static bool IsDBCSLeadByte(int codePage, char ch); + static int DBCSCharLength(int codePage, const char *s); + static int DBCSCharMaxLength(); + + // These are utility functions not really tied to a platform + static int Minimum(int a, int b); + static int Maximum(int a, int b); + // Next three assume 16 bit shorts and 32 bit longs + static long LongFromTwoShorts(short a,short b) { + return (a) | ((b) << 16); + } + static short HighShortFromLong(long x) { + return static_cast(x >> 16); + } + static short LowShortFromLong(long x) { + return static_cast(x & 0xffff); + } + static void DebugPrintf(const char *format, ...); + static bool ShowAssertionPopUps(bool assertionPopUps_); + static void Assert(const char *c, const char *file, int line); + static int Clamp(int val, int minVal, int maxVal); +}; + +#ifdef NDEBUG +#define PLATFORM_ASSERT(c) ((void)0) +#else +#ifdef SCI_NAMESPACE +#define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Scintilla::Platform::Assert(#c, __FILE__, __LINE__)) +#else +#define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Platform::Assert(#c, __FILE__, __LINE__)) +#endif +#endif + +#ifdef SCI_NAMESPACE +} +#endif + +// Shut up annoying Visual C++ warnings: +#ifdef _MSC_VER +#pragma warning(disable: 4244 4309 4514 4710) +#endif + +#endif diff --git a/scintilla/include/SciLexer.h b/ThirdLibs/scintilla/include/SciLexer.h similarity index 96% rename from scintilla/include/SciLexer.h rename to ThirdLibs/scintilla/include/SciLexer.h index 8e74ef59..2758b92b 100644 --- a/scintilla/include/SciLexer.h +++ b/ThirdLibs/scintilla/include/SciLexer.h @@ -1,1538 +1,1538 @@ -/* Scintilla source code edit control */ -/** @file SciLexer.h - ** Interface to the added lexer functions in the SciLexer version of the edit control. - **/ -/* Copyright 1998-2002 by Neil Hodgson - * The License.txt file describes the conditions under which this software may be distributed. */ - -/* Most of this file is automatically generated from the Scintilla.iface interface definition - * file which contains any comments about the definitions. HFacer.py does the generation. */ - -#ifndef SCILEXER_H -#define SCILEXER_H - -/* SciLexer features - not in standard Scintilla */ - -/* ++Autogenerated -- start of section automatically generated from Scintilla.iface */ -#define SCLEX_CONTAINER 0 -#define SCLEX_NULL 1 -#define SCLEX_PYTHON 2 -#define SCLEX_CPP 3 -#define SCLEX_HTML 4 -#define SCLEX_XML 5 -#define SCLEX_PERL 6 -#define SCLEX_SQL 7 -#define SCLEX_VB 8 -#define SCLEX_PROPERTIES 9 -#define SCLEX_ERRORLIST 10 -#define SCLEX_MAKEFILE 11 -#define SCLEX_BATCH 12 -#define SCLEX_XCODE 13 -#define SCLEX_LATEX 14 -#define SCLEX_LUA 15 -#define SCLEX_DIFF 16 -#define SCLEX_CONF 17 -#define SCLEX_PASCAL 18 -#define SCLEX_AVE 19 -#define SCLEX_ADA 20 -#define SCLEX_LISP 21 -#define SCLEX_RUBY 22 -#define SCLEX_EIFFEL 23 -#define SCLEX_EIFFELKW 24 -#define SCLEX_TCL 25 -#define SCLEX_NNCRONTAB 26 -#define SCLEX_BULLANT 27 -#define SCLEX_VBSCRIPT 28 -#define SCLEX_BAAN 31 -#define SCLEX_MATLAB 32 -#define SCLEX_SCRIPTOL 33 -#define SCLEX_ASM 34 -#define SCLEX_CPPNOCASE 35 -#define SCLEX_FORTRAN 36 -#define SCLEX_F77 37 -#define SCLEX_CSS 38 -#define SCLEX_POV 39 -#define SCLEX_LOUT 40 -#define SCLEX_ESCRIPT 41 -#define SCLEX_PS 42 -#define SCLEX_NSIS 43 -#define SCLEX_MMIXAL 44 -#define SCLEX_CLW 45 -#define SCLEX_CLWNOCASE 46 -#define SCLEX_LOT 47 -#define SCLEX_YAML 48 -#define SCLEX_TEX 49 -#define SCLEX_METAPOST 50 -#define SCLEX_POWERBASIC 51 -#define SCLEX_FORTH 52 -#define SCLEX_ERLANG 53 -#define SCLEX_OCTAVE 54 -#define SCLEX_MSSQL 55 -#define SCLEX_VERILOG 56 -#define SCLEX_KIX 57 -#define SCLEX_GUI4CLI 58 -#define SCLEX_SPECMAN 59 -#define SCLEX_AU3 60 -#define SCLEX_APDL 61 -#define SCLEX_BASH 62 -#define SCLEX_ASN1 63 -#define SCLEX_VHDL 64 -#define SCLEX_CAML 65 -#define SCLEX_BLITZBASIC 66 -#define SCLEX_PUREBASIC 67 -#define SCLEX_HASKELL 68 -#define SCLEX_PHPSCRIPT 69 -#define SCLEX_TADS3 70 -#define SCLEX_REBOL 71 -#define SCLEX_SMALLTALK 72 -#define SCLEX_FLAGSHIP 73 -#define SCLEX_CSOUND 74 -#define SCLEX_FREEBASIC 75 -#define SCLEX_INNOSETUP 76 -#define SCLEX_OPAL 77 -#define SCLEX_SPICE 78 -#define SCLEX_D 79 -#define SCLEX_CMAKE 80 -#define SCLEX_GAP 81 -#define SCLEX_PLM 82 -#define SCLEX_PROGRESS 83 -#define SCLEX_ABAQUS 84 -#define SCLEX_ASYMPTOTE 85 -#define SCLEX_R 86 -#define SCLEX_MAGIK 87 -#define SCLEX_POWERSHELL 88 -#define SCLEX_MYSQL 89 -#define SCLEX_PO 90 -#define SCLEX_TAL 91 -#define SCLEX_COBOL 92 -#define SCLEX_TACL 93 -#define SCLEX_SORCUS 94 -#define SCLEX_POWERPRO 95 -#define SCLEX_NIMROD 96 -#define SCLEX_SML 97 -#define SCLEX_MARKDOWN 98 -#define SCLEX_TXT2TAGS 99 -#define SCLEX_A68K 100 -#define SCLEX_MODULA 101 -#define SCLEX_COFFEESCRIPT 102 -#define SCLEX_TCMD 103 -#define SCLEX_AVS 104 -#define SCLEX_AUTOMATIC 1000 -#define SCE_P_DEFAULT 0 -#define SCE_P_COMMENTLINE 1 -#define SCE_P_NUMBER 2 -#define SCE_P_STRING 3 -#define SCE_P_CHARACTER 4 -#define SCE_P_WORD 5 -#define SCE_P_TRIPLE 6 -#define SCE_P_TRIPLEDOUBLE 7 -#define SCE_P_CLASSNAME 8 -#define SCE_P_DEFNAME 9 -#define SCE_P_OPERATOR 10 -#define SCE_P_IDENTIFIER 11 -#define SCE_P_COMMENTBLOCK 12 -#define SCE_P_STRINGEOL 13 -#define SCE_P_WORD2 14 -#define SCE_P_DECORATOR 15 -#define SCE_C_DEFAULT 0 -#define SCE_C_COMMENT 1 -#define SCE_C_COMMENTLINE 2 -#define SCE_C_COMMENTDOC 3 -#define SCE_C_NUMBER 4 -#define SCE_C_WORD 5 -#define SCE_C_STRING 6 -#define SCE_C_CHARACTER 7 -#define SCE_C_UUID 8 -#define SCE_C_PREPROCESSOR 9 -#define SCE_C_OPERATOR 10 -#define SCE_C_IDENTIFIER 11 -#define SCE_C_STRINGEOL 12 -#define SCE_C_VERBATIM 13 -#define SCE_C_REGEX 14 -#define SCE_C_COMMENTLINEDOC 15 -#define SCE_C_WORD2 16 -#define SCE_C_COMMENTDOCKEYWORD 17 -#define SCE_C_COMMENTDOCKEYWORDERROR 18 -#define SCE_C_GLOBALCLASS 19 -#define SCE_C_STRINGRAW 20 -#define SCE_C_TRIPLEVERBATIM 21 -#define SCE_C_HASHQUOTEDSTRING 22 -#define SCE_D_DEFAULT 0 -#define SCE_D_COMMENT 1 -#define SCE_D_COMMENTLINE 2 -#define SCE_D_COMMENTDOC 3 -#define SCE_D_COMMENTNESTED 4 -#define SCE_D_NUMBER 5 -#define SCE_D_WORD 6 -#define SCE_D_WORD2 7 -#define SCE_D_WORD3 8 -#define SCE_D_TYPEDEF 9 -#define SCE_D_STRING 10 -#define SCE_D_STRINGEOL 11 -#define SCE_D_CHARACTER 12 -#define SCE_D_OPERATOR 13 -#define SCE_D_IDENTIFIER 14 -#define SCE_D_COMMENTLINEDOC 15 -#define SCE_D_COMMENTDOCKEYWORD 16 -#define SCE_D_COMMENTDOCKEYWORDERROR 17 -#define SCE_D_STRINGB 18 -#define SCE_D_STRINGR 19 -#define SCE_D_WORD5 20 -#define SCE_D_WORD6 21 -#define SCE_D_WORD7 22 -#define SCE_TCL_DEFAULT 0 -#define SCE_TCL_COMMENT 1 -#define SCE_TCL_COMMENTLINE 2 -#define SCE_TCL_NUMBER 3 -#define SCE_TCL_WORD_IN_QUOTE 4 -#define SCE_TCL_IN_QUOTE 5 -#define SCE_TCL_OPERATOR 6 -#define SCE_TCL_IDENTIFIER 7 -#define SCE_TCL_SUBSTITUTION 8 -#define SCE_TCL_SUB_BRACE 9 -#define SCE_TCL_MODIFIER 10 -#define SCE_TCL_EXPAND 11 -#define SCE_TCL_WORD 12 -#define SCE_TCL_WORD2 13 -#define SCE_TCL_WORD3 14 -#define SCE_TCL_WORD4 15 -#define SCE_TCL_WORD5 16 -#define SCE_TCL_WORD6 17 -#define SCE_TCL_WORD7 18 -#define SCE_TCL_WORD8 19 -#define SCE_TCL_COMMENT_BOX 20 -#define SCE_TCL_BLOCK_COMMENT 21 -#define SCE_H_DEFAULT 0 -#define SCE_H_TAG 1 -#define SCE_H_TAGUNKNOWN 2 -#define SCE_H_ATTRIBUTE 3 -#define SCE_H_ATTRIBUTEUNKNOWN 4 -#define SCE_H_NUMBER 5 -#define SCE_H_DOUBLESTRING 6 -#define SCE_H_SINGLESTRING 7 -#define SCE_H_OTHER 8 -#define SCE_H_COMMENT 9 -#define SCE_H_ENTITY 10 -#define SCE_H_TAGEND 11 -#define SCE_H_XMLSTART 12 -#define SCE_H_XMLEND 13 -#define SCE_H_SCRIPT 14 -#define SCE_H_ASP 15 -#define SCE_H_ASPAT 16 -#define SCE_H_CDATA 17 -#define SCE_H_QUESTION 18 -#define SCE_H_VALUE 19 -#define SCE_H_XCCOMMENT 20 -#define SCE_H_SGML_DEFAULT 21 -#define SCE_H_SGML_COMMAND 22 -#define SCE_H_SGML_1ST_PARAM 23 -#define SCE_H_SGML_DOUBLESTRING 24 -#define SCE_H_SGML_SIMPLESTRING 25 -#define SCE_H_SGML_ERROR 26 -#define SCE_H_SGML_SPECIAL 27 -#define SCE_H_SGML_ENTITY 28 -#define SCE_H_SGML_COMMENT 29 -#define SCE_H_SGML_1ST_PARAM_COMMENT 30 -#define SCE_H_SGML_BLOCK_DEFAULT 31 -#define SCE_HJ_START 40 -#define SCE_HJ_DEFAULT 41 -#define SCE_HJ_COMMENT 42 -#define SCE_HJ_COMMENTLINE 43 -#define SCE_HJ_COMMENTDOC 44 -#define SCE_HJ_NUMBER 45 -#define SCE_HJ_WORD 46 -#define SCE_HJ_KEYWORD 47 -#define SCE_HJ_DOUBLESTRING 48 -#define SCE_HJ_SINGLESTRING 49 -#define SCE_HJ_SYMBOLS 50 -#define SCE_HJ_STRINGEOL 51 -#define SCE_HJ_REGEX 52 -#define SCE_HJA_START 55 -#define SCE_HJA_DEFAULT 56 -#define SCE_HJA_COMMENT 57 -#define SCE_HJA_COMMENTLINE 58 -#define SCE_HJA_COMMENTDOC 59 -#define SCE_HJA_NUMBER 60 -#define SCE_HJA_WORD 61 -#define SCE_HJA_KEYWORD 62 -#define SCE_HJA_DOUBLESTRING 63 -#define SCE_HJA_SINGLESTRING 64 -#define SCE_HJA_SYMBOLS 65 -#define SCE_HJA_STRINGEOL 66 -#define SCE_HJA_REGEX 67 -#define SCE_HB_START 70 -#define SCE_HB_DEFAULT 71 -#define SCE_HB_COMMENTLINE 72 -#define SCE_HB_NUMBER 73 -#define SCE_HB_WORD 74 -#define SCE_HB_STRING 75 -#define SCE_HB_IDENTIFIER 76 -#define SCE_HB_STRINGEOL 77 -#define SCE_HBA_START 80 -#define SCE_HBA_DEFAULT 81 -#define SCE_HBA_COMMENTLINE 82 -#define SCE_HBA_NUMBER 83 -#define SCE_HBA_WORD 84 -#define SCE_HBA_STRING 85 -#define SCE_HBA_IDENTIFIER 86 -#define SCE_HBA_STRINGEOL 87 -#define SCE_HP_START 90 -#define SCE_HP_DEFAULT 91 -#define SCE_HP_COMMENTLINE 92 -#define SCE_HP_NUMBER 93 -#define SCE_HP_STRING 94 -#define SCE_HP_CHARACTER 95 -#define SCE_HP_WORD 96 -#define SCE_HP_TRIPLE 97 -#define SCE_HP_TRIPLEDOUBLE 98 -#define SCE_HP_CLASSNAME 99 -#define SCE_HP_DEFNAME 100 -#define SCE_HP_OPERATOR 101 -#define SCE_HP_IDENTIFIER 102 -#define SCE_HPHP_COMPLEX_VARIABLE 104 -#define SCE_HPA_START 105 -#define SCE_HPA_DEFAULT 106 -#define SCE_HPA_COMMENTLINE 107 -#define SCE_HPA_NUMBER 108 -#define SCE_HPA_STRING 109 -#define SCE_HPA_CHARACTER 110 -#define SCE_HPA_WORD 111 -#define SCE_HPA_TRIPLE 112 -#define SCE_HPA_TRIPLEDOUBLE 113 -#define SCE_HPA_CLASSNAME 114 -#define SCE_HPA_DEFNAME 115 -#define SCE_HPA_OPERATOR 116 -#define SCE_HPA_IDENTIFIER 117 -#define SCE_HPHP_DEFAULT 118 -#define SCE_HPHP_HSTRING 119 -#define SCE_HPHP_SIMPLESTRING 120 -#define SCE_HPHP_WORD 121 -#define SCE_HPHP_NUMBER 122 -#define SCE_HPHP_VARIABLE 123 -#define SCE_HPHP_COMMENT 124 -#define SCE_HPHP_COMMENTLINE 125 -#define SCE_HPHP_HSTRING_VARIABLE 126 -#define SCE_HPHP_OPERATOR 127 -#define SCE_PL_DEFAULT 0 -#define SCE_PL_ERROR 1 -#define SCE_PL_COMMENTLINE 2 -#define SCE_PL_POD 3 -#define SCE_PL_NUMBER 4 -#define SCE_PL_WORD 5 -#define SCE_PL_STRING 6 -#define SCE_PL_CHARACTER 7 -#define SCE_PL_PUNCTUATION 8 -#define SCE_PL_PREPROCESSOR 9 -#define SCE_PL_OPERATOR 10 -#define SCE_PL_IDENTIFIER 11 -#define SCE_PL_SCALAR 12 -#define SCE_PL_ARRAY 13 -#define SCE_PL_HASH 14 -#define SCE_PL_SYMBOLTABLE 15 -#define SCE_PL_VARIABLE_INDEXER 16 -#define SCE_PL_REGEX 17 -#define SCE_PL_REGSUBST 18 -#define SCE_PL_LONGQUOTE 19 -#define SCE_PL_BACKTICKS 20 -#define SCE_PL_DATASECTION 21 -#define SCE_PL_HERE_DELIM 22 -#define SCE_PL_HERE_Q 23 -#define SCE_PL_HERE_QQ 24 -#define SCE_PL_HERE_QX 25 -#define SCE_PL_STRING_Q 26 -#define SCE_PL_STRING_QQ 27 -#define SCE_PL_STRING_QX 28 -#define SCE_PL_STRING_QR 29 -#define SCE_PL_STRING_QW 30 -#define SCE_PL_POD_VERB 31 -#define SCE_PL_SUB_PROTOTYPE 40 -#define SCE_PL_FORMAT_IDENT 41 -#define SCE_PL_FORMAT 42 -#define SCE_PL_STRING_VAR 43 -#define SCE_PL_XLAT 44 -#define SCE_PL_REGEX_VAR 54 -#define SCE_PL_REGSUBST_VAR 55 -#define SCE_PL_BACKTICKS_VAR 57 -#define SCE_PL_HERE_QQ_VAR 61 -#define SCE_PL_HERE_QX_VAR 62 -#define SCE_PL_STRING_QQ_VAR 64 -#define SCE_PL_STRING_QX_VAR 65 -#define SCE_PL_STRING_QR_VAR 66 -#define SCE_RB_DEFAULT 0 -#define SCE_RB_ERROR 1 -#define SCE_RB_COMMENTLINE 2 -#define SCE_RB_POD 3 -#define SCE_RB_NUMBER 4 -#define SCE_RB_WORD 5 -#define SCE_RB_STRING 6 -#define SCE_RB_CHARACTER 7 -#define SCE_RB_CLASSNAME 8 -#define SCE_RB_DEFNAME 9 -#define SCE_RB_OPERATOR 10 -#define SCE_RB_IDENTIFIER 11 -#define SCE_RB_REGEX 12 -#define SCE_RB_GLOBAL 13 -#define SCE_RB_SYMBOL 14 -#define SCE_RB_MODULE_NAME 15 -#define SCE_RB_INSTANCE_VAR 16 -#define SCE_RB_CLASS_VAR 17 -#define SCE_RB_BACKTICKS 18 -#define SCE_RB_DATASECTION 19 -#define SCE_RB_HERE_DELIM 20 -#define SCE_RB_HERE_Q 21 -#define SCE_RB_HERE_QQ 22 -#define SCE_RB_HERE_QX 23 -#define SCE_RB_STRING_Q 24 -#define SCE_RB_STRING_QQ 25 -#define SCE_RB_STRING_QX 26 -#define SCE_RB_STRING_QR 27 -#define SCE_RB_STRING_QW 28 -#define SCE_RB_WORD_DEMOTED 29 -#define SCE_RB_STDIN 30 -#define SCE_RB_STDOUT 31 -#define SCE_RB_STDERR 40 -#define SCE_RB_UPPER_BOUND 41 -#define SCE_B_DEFAULT 0 -#define SCE_B_COMMENT 1 -#define SCE_B_NUMBER 2 -#define SCE_B_KEYWORD 3 -#define SCE_B_STRING 4 -#define SCE_B_PREPROCESSOR 5 -#define SCE_B_OPERATOR 6 -#define SCE_B_IDENTIFIER 7 -#define SCE_B_DATE 8 -#define SCE_B_STRINGEOL 9 -#define SCE_B_KEYWORD2 10 -#define SCE_B_KEYWORD3 11 -#define SCE_B_KEYWORD4 12 -#define SCE_B_CONSTANT 13 -#define SCE_B_ASM 14 -#define SCE_B_LABEL 15 -#define SCE_B_ERROR 16 -#define SCE_B_HEXNUMBER 17 -#define SCE_B_BINNUMBER 18 -#define SCE_PROPS_DEFAULT 0 -#define SCE_PROPS_COMMENT 1 -#define SCE_PROPS_SECTION 2 -#define SCE_PROPS_ASSIGNMENT 3 -#define SCE_PROPS_DEFVAL 4 -#define SCE_PROPS_KEY 5 -#define SCE_L_DEFAULT 0 -#define SCE_L_COMMAND 1 -#define SCE_L_TAG 2 -#define SCE_L_MATH 3 -#define SCE_L_COMMENT 4 -#define SCE_L_TAG2 5 -#define SCE_L_MATH2 6 -#define SCE_L_COMMENT2 7 -#define SCE_L_VERBATIM 8 -#define SCE_L_SHORTCMD 9 -#define SCE_L_SPECIAL 10 -#define SCE_L_CMDOPT 11 -#define SCE_L_ERROR 12 -#define SCE_LUA_DEFAULT 0 -#define SCE_LUA_COMMENT 1 -#define SCE_LUA_COMMENTLINE 2 -#define SCE_LUA_COMMENTDOC 3 -#define SCE_LUA_NUMBER 4 -#define SCE_LUA_WORD 5 -#define SCE_LUA_STRING 6 -#define SCE_LUA_CHARACTER 7 -#define SCE_LUA_LITERALSTRING 8 -#define SCE_LUA_PREPROCESSOR 9 -#define SCE_LUA_OPERATOR 10 -#define SCE_LUA_IDENTIFIER 11 -#define SCE_LUA_STRINGEOL 12 -#define SCE_LUA_WORD2 13 -#define SCE_LUA_WORD3 14 -#define SCE_LUA_WORD4 15 -#define SCE_LUA_WORD5 16 -#define SCE_LUA_WORD6 17 -#define SCE_LUA_WORD7 18 -#define SCE_LUA_WORD8 19 -#define SCE_LUA_LABEL 20 -#define SCE_ERR_DEFAULT 0 -#define SCE_ERR_PYTHON 1 -#define SCE_ERR_GCC 2 -#define SCE_ERR_MS 3 -#define SCE_ERR_CMD 4 -#define SCE_ERR_BORLAND 5 -#define SCE_ERR_PERL 6 -#define SCE_ERR_NET 7 -#define SCE_ERR_LUA 8 -#define SCE_ERR_CTAG 9 -#define SCE_ERR_DIFF_CHANGED 10 -#define SCE_ERR_DIFF_ADDITION 11 -#define SCE_ERR_DIFF_DELETION 12 -#define SCE_ERR_DIFF_MESSAGE 13 -#define SCE_ERR_PHP 14 -#define SCE_ERR_ELF 15 -#define SCE_ERR_IFC 16 -#define SCE_ERR_IFORT 17 -#define SCE_ERR_ABSF 18 -#define SCE_ERR_TIDY 19 -#define SCE_ERR_JAVA_STACK 20 -#define SCE_ERR_VALUE 21 -#define SCE_BAT_DEFAULT 0 -#define SCE_BAT_COMMENT 1 -#define SCE_BAT_WORD 2 -#define SCE_BAT_LABEL 3 -#define SCE_BAT_HIDE 4 -#define SCE_BAT_COMMAND 5 -#define SCE_BAT_IDENTIFIER 6 -#define SCE_BAT_OPERATOR 7 -#define SCE_TCMD_DEFAULT 0 -#define SCE_TCMD_COMMENT 1 -#define SCE_TCMD_WORD 2 -#define SCE_TCMD_LABEL 3 -#define SCE_TCMD_HIDE 4 -#define SCE_TCMD_COMMAND 5 -#define SCE_TCMD_IDENTIFIER 6 -#define SCE_TCMD_OPERATOR 7 -#define SCE_TCMD_ENVIRONMENT 8 -#define SCE_TCMD_EXPANSION 9 -#define SCE_TCMD_CLABEL 10 -#define SCE_MAKE_DEFAULT 0 -#define SCE_MAKE_COMMENT 1 -#define SCE_MAKE_PREPROCESSOR 2 -#define SCE_MAKE_IDENTIFIER 3 -#define SCE_MAKE_OPERATOR 4 -#define SCE_MAKE_TARGET 5 -#define SCE_MAKE_IDEOL 9 -#define SCE_DIFF_DEFAULT 0 -#define SCE_DIFF_COMMENT 1 -#define SCE_DIFF_COMMAND 2 -#define SCE_DIFF_HEADER 3 -#define SCE_DIFF_POSITION 4 -#define SCE_DIFF_DELETED 5 -#define SCE_DIFF_ADDED 6 -#define SCE_DIFF_CHANGED 7 -#define SCE_CONF_DEFAULT 0 -#define SCE_CONF_COMMENT 1 -#define SCE_CONF_NUMBER 2 -#define SCE_CONF_IDENTIFIER 3 -#define SCE_CONF_EXTENSION 4 -#define SCE_CONF_PARAMETER 5 -#define SCE_CONF_STRING 6 -#define SCE_CONF_OPERATOR 7 -#define SCE_CONF_IP 8 -#define SCE_CONF_DIRECTIVE 9 -#define SCE_AVE_DEFAULT 0 -#define SCE_AVE_COMMENT 1 -#define SCE_AVE_NUMBER 2 -#define SCE_AVE_WORD 3 -#define SCE_AVE_STRING 6 -#define SCE_AVE_ENUM 7 -#define SCE_AVE_STRINGEOL 8 -#define SCE_AVE_IDENTIFIER 9 -#define SCE_AVE_OPERATOR 10 -#define SCE_AVE_WORD1 11 -#define SCE_AVE_WORD2 12 -#define SCE_AVE_WORD3 13 -#define SCE_AVE_WORD4 14 -#define SCE_AVE_WORD5 15 -#define SCE_AVE_WORD6 16 -#define SCE_ADA_DEFAULT 0 -#define SCE_ADA_WORD 1 -#define SCE_ADA_IDENTIFIER 2 -#define SCE_ADA_NUMBER 3 -#define SCE_ADA_DELIMITER 4 -#define SCE_ADA_CHARACTER 5 -#define SCE_ADA_CHARACTEREOL 6 -#define SCE_ADA_STRING 7 -#define SCE_ADA_STRINGEOL 8 -#define SCE_ADA_LABEL 9 -#define SCE_ADA_COMMENTLINE 10 -#define SCE_ADA_ILLEGAL 11 -#define SCE_BAAN_DEFAULT 0 -#define SCE_BAAN_COMMENT 1 -#define SCE_BAAN_COMMENTDOC 2 -#define SCE_BAAN_NUMBER 3 -#define SCE_BAAN_WORD 4 -#define SCE_BAAN_STRING 5 -#define SCE_BAAN_PREPROCESSOR 6 -#define SCE_BAAN_OPERATOR 7 -#define SCE_BAAN_IDENTIFIER 8 -#define SCE_BAAN_STRINGEOL 9 -#define SCE_BAAN_WORD2 10 -#define SCE_LISP_DEFAULT 0 -#define SCE_LISP_COMMENT 1 -#define SCE_LISP_NUMBER 2 -#define SCE_LISP_KEYWORD 3 -#define SCE_LISP_KEYWORD_KW 4 -#define SCE_LISP_SYMBOL 5 -#define SCE_LISP_STRING 6 -#define SCE_LISP_STRINGEOL 8 -#define SCE_LISP_IDENTIFIER 9 -#define SCE_LISP_OPERATOR 10 -#define SCE_LISP_SPECIAL 11 -#define SCE_LISP_MULTI_COMMENT 12 -#define SCE_EIFFEL_DEFAULT 0 -#define SCE_EIFFEL_COMMENTLINE 1 -#define SCE_EIFFEL_NUMBER 2 -#define SCE_EIFFEL_WORD 3 -#define SCE_EIFFEL_STRING 4 -#define SCE_EIFFEL_CHARACTER 5 -#define SCE_EIFFEL_OPERATOR 6 -#define SCE_EIFFEL_IDENTIFIER 7 -#define SCE_EIFFEL_STRINGEOL 8 -#define SCE_NNCRONTAB_DEFAULT 0 -#define SCE_NNCRONTAB_COMMENT 1 -#define SCE_NNCRONTAB_TASK 2 -#define SCE_NNCRONTAB_SECTION 3 -#define SCE_NNCRONTAB_KEYWORD 4 -#define SCE_NNCRONTAB_MODIFIER 5 -#define SCE_NNCRONTAB_ASTERISK 6 -#define SCE_NNCRONTAB_NUMBER 7 -#define SCE_NNCRONTAB_STRING 8 -#define SCE_NNCRONTAB_ENVIRONMENT 9 -#define SCE_NNCRONTAB_IDENTIFIER 10 -#define SCE_FORTH_DEFAULT 0 -#define SCE_FORTH_COMMENT 1 -#define SCE_FORTH_COMMENT_ML 2 -#define SCE_FORTH_IDENTIFIER 3 -#define SCE_FORTH_CONTROL 4 -#define SCE_FORTH_KEYWORD 5 -#define SCE_FORTH_DEFWORD 6 -#define SCE_FORTH_PREWORD1 7 -#define SCE_FORTH_PREWORD2 8 -#define SCE_FORTH_NUMBER 9 -#define SCE_FORTH_STRING 10 -#define SCE_FORTH_LOCALE 11 -#define SCE_MATLAB_DEFAULT 0 -#define SCE_MATLAB_COMMENT 1 -#define SCE_MATLAB_COMMAND 2 -#define SCE_MATLAB_NUMBER 3 -#define SCE_MATLAB_KEYWORD 4 -#define SCE_MATLAB_STRING 5 -#define SCE_MATLAB_OPERATOR 6 -#define SCE_MATLAB_IDENTIFIER 7 -#define SCE_MATLAB_DOUBLEQUOTESTRING 8 -#define SCE_SCRIPTOL_DEFAULT 0 -#define SCE_SCRIPTOL_WHITE 1 -#define SCE_SCRIPTOL_COMMENTLINE 2 -#define SCE_SCRIPTOL_PERSISTENT 3 -#define SCE_SCRIPTOL_CSTYLE 4 -#define SCE_SCRIPTOL_COMMENTBLOCK 5 -#define SCE_SCRIPTOL_NUMBER 6 -#define SCE_SCRIPTOL_STRING 7 -#define SCE_SCRIPTOL_CHARACTER 8 -#define SCE_SCRIPTOL_STRINGEOL 9 -#define SCE_SCRIPTOL_KEYWORD 10 -#define SCE_SCRIPTOL_OPERATOR 11 -#define SCE_SCRIPTOL_IDENTIFIER 12 -#define SCE_SCRIPTOL_TRIPLE 13 -#define SCE_SCRIPTOL_CLASSNAME 14 -#define SCE_SCRIPTOL_PREPROCESSOR 15 -#define SCE_ASM_DEFAULT 0 -#define SCE_ASM_COMMENT 1 -#define SCE_ASM_NUMBER 2 -#define SCE_ASM_STRING 3 -#define SCE_ASM_OPERATOR 4 -#define SCE_ASM_IDENTIFIER 5 -#define SCE_ASM_CPUINSTRUCTION 6 -#define SCE_ASM_MATHINSTRUCTION 7 -#define SCE_ASM_REGISTER 8 -#define SCE_ASM_DIRECTIVE 9 -#define SCE_ASM_DIRECTIVEOPERAND 10 -#define SCE_ASM_COMMENTBLOCK 11 -#define SCE_ASM_CHARACTER 12 -#define SCE_ASM_STRINGEOL 13 -#define SCE_ASM_EXTINSTRUCTION 14 -#define SCE_ASM_COMMENTDIRECTIVE 15 -#define SCE_F_DEFAULT 0 -#define SCE_F_COMMENT 1 -#define SCE_F_NUMBER 2 -#define SCE_F_STRING1 3 -#define SCE_F_STRING2 4 -#define SCE_F_STRINGEOL 5 -#define SCE_F_OPERATOR 6 -#define SCE_F_IDENTIFIER 7 -#define SCE_F_WORD 8 -#define SCE_F_WORD2 9 -#define SCE_F_WORD3 10 -#define SCE_F_PREPROCESSOR 11 -#define SCE_F_OPERATOR2 12 -#define SCE_F_LABEL 13 -#define SCE_F_CONTINUATION 14 -#define SCE_CSS_DEFAULT 0 -#define SCE_CSS_TAG 1 -#define SCE_CSS_CLASS 2 -#define SCE_CSS_PSEUDOCLASS 3 -#define SCE_CSS_UNKNOWN_PSEUDOCLASS 4 -#define SCE_CSS_OPERATOR 5 -#define SCE_CSS_IDENTIFIER 6 -#define SCE_CSS_UNKNOWN_IDENTIFIER 7 -#define SCE_CSS_VALUE 8 -#define SCE_CSS_COMMENT 9 -#define SCE_CSS_ID 10 -#define SCE_CSS_IMPORTANT 11 -#define SCE_CSS_DIRECTIVE 12 -#define SCE_CSS_DOUBLESTRING 13 -#define SCE_CSS_SINGLESTRING 14 -#define SCE_CSS_IDENTIFIER2 15 -#define SCE_CSS_ATTRIBUTE 16 -#define SCE_CSS_IDENTIFIER3 17 -#define SCE_CSS_PSEUDOELEMENT 18 -#define SCE_CSS_EXTENDED_IDENTIFIER 19 -#define SCE_CSS_EXTENDED_PSEUDOCLASS 20 -#define SCE_CSS_EXTENDED_PSEUDOELEMENT 21 -#define SCE_CSS_MEDIA 22 -#define SCE_CSS_VARIABLE 23 -#define SCE_POV_DEFAULT 0 -#define SCE_POV_COMMENT 1 -#define SCE_POV_COMMENTLINE 2 -#define SCE_POV_NUMBER 3 -#define SCE_POV_OPERATOR 4 -#define SCE_POV_IDENTIFIER 5 -#define SCE_POV_STRING 6 -#define SCE_POV_STRINGEOL 7 -#define SCE_POV_DIRECTIVE 8 -#define SCE_POV_BADDIRECTIVE 9 -#define SCE_POV_WORD2 10 -#define SCE_POV_WORD3 11 -#define SCE_POV_WORD4 12 -#define SCE_POV_WORD5 13 -#define SCE_POV_WORD6 14 -#define SCE_POV_WORD7 15 -#define SCE_POV_WORD8 16 -#define SCE_LOUT_DEFAULT 0 -#define SCE_LOUT_COMMENT 1 -#define SCE_LOUT_NUMBER 2 -#define SCE_LOUT_WORD 3 -#define SCE_LOUT_WORD2 4 -#define SCE_LOUT_WORD3 5 -#define SCE_LOUT_WORD4 6 -#define SCE_LOUT_STRING 7 -#define SCE_LOUT_OPERATOR 8 -#define SCE_LOUT_IDENTIFIER 9 -#define SCE_LOUT_STRINGEOL 10 -#define SCE_ESCRIPT_DEFAULT 0 -#define SCE_ESCRIPT_COMMENT 1 -#define SCE_ESCRIPT_COMMENTLINE 2 -#define SCE_ESCRIPT_COMMENTDOC 3 -#define SCE_ESCRIPT_NUMBER 4 -#define SCE_ESCRIPT_WORD 5 -#define SCE_ESCRIPT_STRING 6 -#define SCE_ESCRIPT_OPERATOR 7 -#define SCE_ESCRIPT_IDENTIFIER 8 -#define SCE_ESCRIPT_BRACE 9 -#define SCE_ESCRIPT_WORD2 10 -#define SCE_ESCRIPT_WORD3 11 -#define SCE_PS_DEFAULT 0 -#define SCE_PS_COMMENT 1 -#define SCE_PS_DSC_COMMENT 2 -#define SCE_PS_DSC_VALUE 3 -#define SCE_PS_NUMBER 4 -#define SCE_PS_NAME 5 -#define SCE_PS_KEYWORD 6 -#define SCE_PS_LITERAL 7 -#define SCE_PS_IMMEVAL 8 -#define SCE_PS_PAREN_ARRAY 9 -#define SCE_PS_PAREN_DICT 10 -#define SCE_PS_PAREN_PROC 11 -#define SCE_PS_TEXT 12 -#define SCE_PS_HEXSTRING 13 -#define SCE_PS_BASE85STRING 14 -#define SCE_PS_BADSTRINGCHAR 15 -#define SCE_NSIS_DEFAULT 0 -#define SCE_NSIS_COMMENT 1 -#define SCE_NSIS_STRINGDQ 2 -#define SCE_NSIS_STRINGLQ 3 -#define SCE_NSIS_STRINGRQ 4 -#define SCE_NSIS_FUNCTION 5 -#define SCE_NSIS_VARIABLE 6 -#define SCE_NSIS_LABEL 7 -#define SCE_NSIS_USERDEFINED 8 -#define SCE_NSIS_SECTIONDEF 9 -#define SCE_NSIS_SUBSECTIONDEF 10 -#define SCE_NSIS_IFDEFINEDEF 11 -#define SCE_NSIS_MACRODEF 12 -#define SCE_NSIS_STRINGVAR 13 -#define SCE_NSIS_NUMBER 14 -#define SCE_NSIS_SECTIONGROUP 15 -#define SCE_NSIS_PAGEEX 16 -#define SCE_NSIS_FUNCTIONDEF 17 -#define SCE_NSIS_COMMENTBOX 18 -#define SCE_MMIXAL_LEADWS 0 -#define SCE_MMIXAL_COMMENT 1 -#define SCE_MMIXAL_LABEL 2 -#define SCE_MMIXAL_OPCODE 3 -#define SCE_MMIXAL_OPCODE_PRE 4 -#define SCE_MMIXAL_OPCODE_VALID 5 -#define SCE_MMIXAL_OPCODE_UNKNOWN 6 -#define SCE_MMIXAL_OPCODE_POST 7 -#define SCE_MMIXAL_OPERANDS 8 -#define SCE_MMIXAL_NUMBER 9 -#define SCE_MMIXAL_REF 10 -#define SCE_MMIXAL_CHAR 11 -#define SCE_MMIXAL_STRING 12 -#define SCE_MMIXAL_REGISTER 13 -#define SCE_MMIXAL_HEX 14 -#define SCE_MMIXAL_OPERATOR 15 -#define SCE_MMIXAL_SYMBOL 16 -#define SCE_MMIXAL_INCLUDE 17 -#define SCE_CLW_DEFAULT 0 -#define SCE_CLW_LABEL 1 -#define SCE_CLW_COMMENT 2 -#define SCE_CLW_STRING 3 -#define SCE_CLW_USER_IDENTIFIER 4 -#define SCE_CLW_INTEGER_CONSTANT 5 -#define SCE_CLW_REAL_CONSTANT 6 -#define SCE_CLW_PICTURE_STRING 7 -#define SCE_CLW_KEYWORD 8 -#define SCE_CLW_COMPILER_DIRECTIVE 9 -#define SCE_CLW_RUNTIME_EXPRESSIONS 10 -#define SCE_CLW_BUILTIN_PROCEDURES_FUNCTION 11 -#define SCE_CLW_STRUCTURE_DATA_TYPE 12 -#define SCE_CLW_ATTRIBUTE 13 -#define SCE_CLW_STANDARD_EQUATE 14 -#define SCE_CLW_ERROR 15 -#define SCE_CLW_DEPRECATED 16 -#define SCE_LOT_DEFAULT 0 -#define SCE_LOT_HEADER 1 -#define SCE_LOT_BREAK 2 -#define SCE_LOT_SET 3 -#define SCE_LOT_PASS 4 -#define SCE_LOT_FAIL 5 -#define SCE_LOT_ABORT 6 -#define SCE_YAML_DEFAULT 0 -#define SCE_YAML_COMMENT 1 -#define SCE_YAML_IDENTIFIER 2 -#define SCE_YAML_KEYWORD 3 -#define SCE_YAML_NUMBER 4 -#define SCE_YAML_REFERENCE 5 -#define SCE_YAML_DOCUMENT 6 -#define SCE_YAML_TEXT 7 -#define SCE_YAML_ERROR 8 -#define SCE_YAML_OPERATOR 9 -#define SCE_TEX_DEFAULT 0 -#define SCE_TEX_SPECIAL 1 -#define SCE_TEX_GROUP 2 -#define SCE_TEX_SYMBOL 3 -#define SCE_TEX_COMMAND 4 -#define SCE_TEX_TEXT 5 -#define SCE_METAPOST_DEFAULT 0 -#define SCE_METAPOST_SPECIAL 1 -#define SCE_METAPOST_GROUP 2 -#define SCE_METAPOST_SYMBOL 3 -#define SCE_METAPOST_COMMAND 4 -#define SCE_METAPOST_TEXT 5 -#define SCE_METAPOST_EXTRA 6 -#define SCE_ERLANG_DEFAULT 0 -#define SCE_ERLANG_COMMENT 1 -#define SCE_ERLANG_VARIABLE 2 -#define SCE_ERLANG_NUMBER 3 -#define SCE_ERLANG_KEYWORD 4 -#define SCE_ERLANG_STRING 5 -#define SCE_ERLANG_OPERATOR 6 -#define SCE_ERLANG_ATOM 7 -#define SCE_ERLANG_FUNCTION_NAME 8 -#define SCE_ERLANG_CHARACTER 9 -#define SCE_ERLANG_MACRO 10 -#define SCE_ERLANG_RECORD 11 -#define SCE_ERLANG_PREPROC 12 -#define SCE_ERLANG_NODE_NAME 13 -#define SCE_ERLANG_COMMENT_FUNCTION 14 -#define SCE_ERLANG_COMMENT_MODULE 15 -#define SCE_ERLANG_COMMENT_DOC 16 -#define SCE_ERLANG_COMMENT_DOC_MACRO 17 -#define SCE_ERLANG_ATOM_QUOTED 18 -#define SCE_ERLANG_MACRO_QUOTED 19 -#define SCE_ERLANG_RECORD_QUOTED 20 -#define SCE_ERLANG_NODE_NAME_QUOTED 21 -#define SCE_ERLANG_BIFS 22 -#define SCE_ERLANG_MODULES 23 -#define SCE_ERLANG_MODULES_ATT 24 -#define SCE_ERLANG_UNKNOWN 31 -#define SCE_MSSQL_DEFAULT 0 -#define SCE_MSSQL_COMMENT 1 -#define SCE_MSSQL_LINE_COMMENT 2 -#define SCE_MSSQL_NUMBER 3 -#define SCE_MSSQL_STRING 4 -#define SCE_MSSQL_OPERATOR 5 -#define SCE_MSSQL_IDENTIFIER 6 -#define SCE_MSSQL_VARIABLE 7 -#define SCE_MSSQL_COLUMN_NAME 8 -#define SCE_MSSQL_STATEMENT 9 -#define SCE_MSSQL_DATATYPE 10 -#define SCE_MSSQL_SYSTABLE 11 -#define SCE_MSSQL_GLOBAL_VARIABLE 12 -#define SCE_MSSQL_FUNCTION 13 -#define SCE_MSSQL_STORED_PROCEDURE 14 -#define SCE_MSSQL_DEFAULT_PREF_DATATYPE 15 -#define SCE_MSSQL_COLUMN_NAME_2 16 -#define SCE_V_DEFAULT 0 -#define SCE_V_COMMENT 1 -#define SCE_V_COMMENTLINE 2 -#define SCE_V_COMMENTLINEBANG 3 -#define SCE_V_NUMBER 4 -#define SCE_V_WORD 5 -#define SCE_V_STRING 6 -#define SCE_V_WORD2 7 -#define SCE_V_WORD3 8 -#define SCE_V_PREPROCESSOR 9 -#define SCE_V_OPERATOR 10 -#define SCE_V_IDENTIFIER 11 -#define SCE_V_STRINGEOL 12 -#define SCE_V_USER 19 -#define SCE_KIX_DEFAULT 0 -#define SCE_KIX_COMMENT 1 -#define SCE_KIX_STRING1 2 -#define SCE_KIX_STRING2 3 -#define SCE_KIX_NUMBER 4 -#define SCE_KIX_VAR 5 -#define SCE_KIX_MACRO 6 -#define SCE_KIX_KEYWORD 7 -#define SCE_KIX_FUNCTIONS 8 -#define SCE_KIX_OPERATOR 9 -#define SCE_KIX_IDENTIFIER 31 -#define SCE_GC_DEFAULT 0 -#define SCE_GC_COMMENTLINE 1 -#define SCE_GC_COMMENTBLOCK 2 -#define SCE_GC_GLOBAL 3 -#define SCE_GC_EVENT 4 -#define SCE_GC_ATTRIBUTE 5 -#define SCE_GC_CONTROL 6 -#define SCE_GC_COMMAND 7 -#define SCE_GC_STRING 8 -#define SCE_GC_OPERATOR 9 -#define SCE_SN_DEFAULT 0 -#define SCE_SN_CODE 1 -#define SCE_SN_COMMENTLINE 2 -#define SCE_SN_COMMENTLINEBANG 3 -#define SCE_SN_NUMBER 4 -#define SCE_SN_WORD 5 -#define SCE_SN_STRING 6 -#define SCE_SN_WORD2 7 -#define SCE_SN_WORD3 8 -#define SCE_SN_PREPROCESSOR 9 -#define SCE_SN_OPERATOR 10 -#define SCE_SN_IDENTIFIER 11 -#define SCE_SN_STRINGEOL 12 -#define SCE_SN_REGEXTAG 13 -#define SCE_SN_SIGNAL 14 -#define SCE_SN_USER 19 -#define SCE_AU3_DEFAULT 0 -#define SCE_AU3_COMMENT 1 -#define SCE_AU3_COMMENTBLOCK 2 -#define SCE_AU3_NUMBER 3 -#define SCE_AU3_FUNCTION 4 -#define SCE_AU3_KEYWORD 5 -#define SCE_AU3_MACRO 6 -#define SCE_AU3_STRING 7 -#define SCE_AU3_OPERATOR 8 -#define SCE_AU3_VARIABLE 9 -#define SCE_AU3_SENT 10 -#define SCE_AU3_PREPROCESSOR 11 -#define SCE_AU3_SPECIAL 12 -#define SCE_AU3_EXPAND 13 -#define SCE_AU3_COMOBJ 14 -#define SCE_AU3_UDF 15 -#define SCE_APDL_DEFAULT 0 -#define SCE_APDL_COMMENT 1 -#define SCE_APDL_COMMENTBLOCK 2 -#define SCE_APDL_NUMBER 3 -#define SCE_APDL_STRING 4 -#define SCE_APDL_OPERATOR 5 -#define SCE_APDL_WORD 6 -#define SCE_APDL_PROCESSOR 7 -#define SCE_APDL_COMMAND 8 -#define SCE_APDL_SLASHCOMMAND 9 -#define SCE_APDL_STARCOMMAND 10 -#define SCE_APDL_ARGUMENT 11 -#define SCE_APDL_FUNCTION 12 -#define SCE_SH_DEFAULT 0 -#define SCE_SH_ERROR 1 -#define SCE_SH_COMMENTLINE 2 -#define SCE_SH_NUMBER 3 -#define SCE_SH_WORD 4 -#define SCE_SH_STRING 5 -#define SCE_SH_CHARACTER 6 -#define SCE_SH_OPERATOR 7 -#define SCE_SH_IDENTIFIER 8 -#define SCE_SH_SCALAR 9 -#define SCE_SH_PARAM 10 -#define SCE_SH_BACKTICKS 11 -#define SCE_SH_HERE_DELIM 12 -#define SCE_SH_HERE_Q 13 -#define SCE_ASN1_DEFAULT 0 -#define SCE_ASN1_COMMENT 1 -#define SCE_ASN1_IDENTIFIER 2 -#define SCE_ASN1_STRING 3 -#define SCE_ASN1_OID 4 -#define SCE_ASN1_SCALAR 5 -#define SCE_ASN1_KEYWORD 6 -#define SCE_ASN1_ATTRIBUTE 7 -#define SCE_ASN1_DESCRIPTOR 8 -#define SCE_ASN1_TYPE 9 -#define SCE_ASN1_OPERATOR 10 -#define SCE_VHDL_DEFAULT 0 -#define SCE_VHDL_COMMENT 1 -#define SCE_VHDL_COMMENTLINEBANG 2 -#define SCE_VHDL_NUMBER 3 -#define SCE_VHDL_STRING 4 -#define SCE_VHDL_OPERATOR 5 -#define SCE_VHDL_IDENTIFIER 6 -#define SCE_VHDL_STRINGEOL 7 -#define SCE_VHDL_KEYWORD 8 -#define SCE_VHDL_STDOPERATOR 9 -#define SCE_VHDL_ATTRIBUTE 10 -#define SCE_VHDL_STDFUNCTION 11 -#define SCE_VHDL_STDPACKAGE 12 -#define SCE_VHDL_STDTYPE 13 -#define SCE_VHDL_USERWORD 14 -#define SCE_CAML_DEFAULT 0 -#define SCE_CAML_IDENTIFIER 1 -#define SCE_CAML_TAGNAME 2 -#define SCE_CAML_KEYWORD 3 -#define SCE_CAML_KEYWORD2 4 -#define SCE_CAML_KEYWORD3 5 -#define SCE_CAML_LINENUM 6 -#define SCE_CAML_OPERATOR 7 -#define SCE_CAML_NUMBER 8 -#define SCE_CAML_CHAR 9 -#define SCE_CAML_WHITE 10 -#define SCE_CAML_STRING 11 -#define SCE_CAML_COMMENT 12 -#define SCE_CAML_COMMENT1 13 -#define SCE_CAML_COMMENT2 14 -#define SCE_CAML_COMMENT3 15 -#define SCE_HA_DEFAULT 0 -#define SCE_HA_IDENTIFIER 1 -#define SCE_HA_KEYWORD 2 -#define SCE_HA_NUMBER 3 -#define SCE_HA_STRING 4 -#define SCE_HA_CHARACTER 5 -#define SCE_HA_CLASS 6 -#define SCE_HA_MODULE 7 -#define SCE_HA_CAPITAL 8 -#define SCE_HA_DATA 9 -#define SCE_HA_IMPORT 10 -#define SCE_HA_OPERATOR 11 -#define SCE_HA_INSTANCE 12 -#define SCE_HA_COMMENTLINE 13 -#define SCE_HA_COMMENTBLOCK 14 -#define SCE_HA_COMMENTBLOCK2 15 -#define SCE_HA_COMMENTBLOCK3 16 -#define SCE_T3_DEFAULT 0 -#define SCE_T3_X_DEFAULT 1 -#define SCE_T3_PREPROCESSOR 2 -#define SCE_T3_BLOCK_COMMENT 3 -#define SCE_T3_LINE_COMMENT 4 -#define SCE_T3_OPERATOR 5 -#define SCE_T3_KEYWORD 6 -#define SCE_T3_NUMBER 7 -#define SCE_T3_IDENTIFIER 8 -#define SCE_T3_S_STRING 9 -#define SCE_T3_D_STRING 10 -#define SCE_T3_X_STRING 11 -#define SCE_T3_LIB_DIRECTIVE 12 -#define SCE_T3_MSG_PARAM 13 -#define SCE_T3_HTML_TAG 14 -#define SCE_T3_HTML_DEFAULT 15 -#define SCE_T3_HTML_STRING 16 -#define SCE_T3_USER1 17 -#define SCE_T3_USER2 18 -#define SCE_T3_USER3 19 -#define SCE_T3_BRACE 20 -#define SCE_REBOL_DEFAULT 0 -#define SCE_REBOL_COMMENTLINE 1 -#define SCE_REBOL_COMMENTBLOCK 2 -#define SCE_REBOL_PREFACE 3 -#define SCE_REBOL_OPERATOR 4 -#define SCE_REBOL_CHARACTER 5 -#define SCE_REBOL_QUOTEDSTRING 6 -#define SCE_REBOL_BRACEDSTRING 7 -#define SCE_REBOL_NUMBER 8 -#define SCE_REBOL_PAIR 9 -#define SCE_REBOL_TUPLE 10 -#define SCE_REBOL_BINARY 11 -#define SCE_REBOL_MONEY 12 -#define SCE_REBOL_ISSUE 13 -#define SCE_REBOL_TAG 14 -#define SCE_REBOL_FILE 15 -#define SCE_REBOL_EMAIL 16 -#define SCE_REBOL_URL 17 -#define SCE_REBOL_DATE 18 -#define SCE_REBOL_TIME 19 -#define SCE_REBOL_IDENTIFIER 20 -#define SCE_REBOL_WORD 21 -#define SCE_REBOL_WORD2 22 -#define SCE_REBOL_WORD3 23 -#define SCE_REBOL_WORD4 24 -#define SCE_REBOL_WORD5 25 -#define SCE_REBOL_WORD6 26 -#define SCE_REBOL_WORD7 27 -#define SCE_REBOL_WORD8 28 -#define SCE_SQL_DEFAULT 0 -#define SCE_SQL_COMMENT 1 -#define SCE_SQL_COMMENTLINE 2 -#define SCE_SQL_COMMENTDOC 3 -#define SCE_SQL_NUMBER 4 -#define SCE_SQL_WORD 5 -#define SCE_SQL_STRING 6 -#define SCE_SQL_CHARACTER 7 -#define SCE_SQL_SQLPLUS 8 -#define SCE_SQL_SQLPLUS_PROMPT 9 -#define SCE_SQL_OPERATOR 10 -#define SCE_SQL_IDENTIFIER 11 -#define SCE_SQL_SQLPLUS_COMMENT 13 -#define SCE_SQL_COMMENTLINEDOC 15 -#define SCE_SQL_WORD2 16 -#define SCE_SQL_COMMENTDOCKEYWORD 17 -#define SCE_SQL_COMMENTDOCKEYWORDERROR 18 -#define SCE_SQL_USER1 19 -#define SCE_SQL_USER2 20 -#define SCE_SQL_USER3 21 -#define SCE_SQL_USER4 22 -#define SCE_SQL_QUOTEDIDENTIFIER 23 -#define SCE_ST_DEFAULT 0 -#define SCE_ST_STRING 1 -#define SCE_ST_NUMBER 2 -#define SCE_ST_COMMENT 3 -#define SCE_ST_SYMBOL 4 -#define SCE_ST_BINARY 5 -#define SCE_ST_BOOL 6 -#define SCE_ST_SELF 7 -#define SCE_ST_SUPER 8 -#define SCE_ST_NIL 9 -#define SCE_ST_GLOBAL 10 -#define SCE_ST_RETURN 11 -#define SCE_ST_SPECIAL 12 -#define SCE_ST_KWSEND 13 -#define SCE_ST_ASSIGN 14 -#define SCE_ST_CHARACTER 15 -#define SCE_ST_SPEC_SEL 16 -#define SCE_FS_DEFAULT 0 -#define SCE_FS_COMMENT 1 -#define SCE_FS_COMMENTLINE 2 -#define SCE_FS_COMMENTDOC 3 -#define SCE_FS_COMMENTLINEDOC 4 -#define SCE_FS_COMMENTDOCKEYWORD 5 -#define SCE_FS_COMMENTDOCKEYWORDERROR 6 -#define SCE_FS_KEYWORD 7 -#define SCE_FS_KEYWORD2 8 -#define SCE_FS_KEYWORD3 9 -#define SCE_FS_KEYWORD4 10 -#define SCE_FS_NUMBER 11 -#define SCE_FS_STRING 12 -#define SCE_FS_PREPROCESSOR 13 -#define SCE_FS_OPERATOR 14 -#define SCE_FS_IDENTIFIER 15 -#define SCE_FS_DATE 16 -#define SCE_FS_STRINGEOL 17 -#define SCE_FS_CONSTANT 18 -#define SCE_FS_WORDOPERATOR 19 -#define SCE_FS_DISABLEDCODE 20 -#define SCE_FS_DEFAULT_C 21 -#define SCE_FS_COMMENTDOC_C 22 -#define SCE_FS_COMMENTLINEDOC_C 23 -#define SCE_FS_KEYWORD_C 24 -#define SCE_FS_KEYWORD2_C 25 -#define SCE_FS_NUMBER_C 26 -#define SCE_FS_STRING_C 27 -#define SCE_FS_PREPROCESSOR_C 28 -#define SCE_FS_OPERATOR_C 29 -#define SCE_FS_IDENTIFIER_C 30 -#define SCE_FS_STRINGEOL_C 31 -#define SCE_CSOUND_DEFAULT 0 -#define SCE_CSOUND_COMMENT 1 -#define SCE_CSOUND_NUMBER 2 -#define SCE_CSOUND_OPERATOR 3 -#define SCE_CSOUND_INSTR 4 -#define SCE_CSOUND_IDENTIFIER 5 -#define SCE_CSOUND_OPCODE 6 -#define SCE_CSOUND_HEADERSTMT 7 -#define SCE_CSOUND_USERKEYWORD 8 -#define SCE_CSOUND_COMMENTBLOCK 9 -#define SCE_CSOUND_PARAM 10 -#define SCE_CSOUND_ARATE_VAR 11 -#define SCE_CSOUND_KRATE_VAR 12 -#define SCE_CSOUND_IRATE_VAR 13 -#define SCE_CSOUND_GLOBAL_VAR 14 -#define SCE_CSOUND_STRINGEOL 15 -#define SCE_INNO_DEFAULT 0 -#define SCE_INNO_COMMENT 1 -#define SCE_INNO_KEYWORD 2 -#define SCE_INNO_PARAMETER 3 -#define SCE_INNO_SECTION 4 -#define SCE_INNO_PREPROC 5 -#define SCE_INNO_INLINE_EXPANSION 6 -#define SCE_INNO_COMMENT_PASCAL 7 -#define SCE_INNO_KEYWORD_PASCAL 8 -#define SCE_INNO_KEYWORD_USER 9 -#define SCE_INNO_STRING_DOUBLE 10 -#define SCE_INNO_STRING_SINGLE 11 -#define SCE_INNO_IDENTIFIER 12 -#define SCE_OPAL_SPACE 0 -#define SCE_OPAL_COMMENT_BLOCK 1 -#define SCE_OPAL_COMMENT_LINE 2 -#define SCE_OPAL_INTEGER 3 -#define SCE_OPAL_KEYWORD 4 -#define SCE_OPAL_SORT 5 -#define SCE_OPAL_STRING 6 -#define SCE_OPAL_PAR 7 -#define SCE_OPAL_BOOL_CONST 8 -#define SCE_OPAL_DEFAULT 32 -#define SCE_SPICE_DEFAULT 0 -#define SCE_SPICE_IDENTIFIER 1 -#define SCE_SPICE_KEYWORD 2 -#define SCE_SPICE_KEYWORD2 3 -#define SCE_SPICE_KEYWORD3 4 -#define SCE_SPICE_NUMBER 5 -#define SCE_SPICE_DELIMITER 6 -#define SCE_SPICE_VALUE 7 -#define SCE_SPICE_COMMENTLINE 8 -#define SCE_CMAKE_DEFAULT 0 -#define SCE_CMAKE_COMMENT 1 -#define SCE_CMAKE_STRINGDQ 2 -#define SCE_CMAKE_STRINGLQ 3 -#define SCE_CMAKE_STRINGRQ 4 -#define SCE_CMAKE_COMMANDS 5 -#define SCE_CMAKE_PARAMETERS 6 -#define SCE_CMAKE_VARIABLE 7 -#define SCE_CMAKE_USERDEFINED 8 -#define SCE_CMAKE_WHILEDEF 9 -#define SCE_CMAKE_FOREACHDEF 10 -#define SCE_CMAKE_IFDEFINEDEF 11 -#define SCE_CMAKE_MACRODEF 12 -#define SCE_CMAKE_STRINGVAR 13 -#define SCE_CMAKE_NUMBER 14 -#define SCE_GAP_DEFAULT 0 -#define SCE_GAP_IDENTIFIER 1 -#define SCE_GAP_KEYWORD 2 -#define SCE_GAP_KEYWORD2 3 -#define SCE_GAP_KEYWORD3 4 -#define SCE_GAP_KEYWORD4 5 -#define SCE_GAP_STRING 6 -#define SCE_GAP_CHAR 7 -#define SCE_GAP_OPERATOR 8 -#define SCE_GAP_COMMENT 9 -#define SCE_GAP_NUMBER 10 -#define SCE_GAP_STRINGEOL 11 -#define SCE_PLM_DEFAULT 0 -#define SCE_PLM_COMMENT 1 -#define SCE_PLM_STRING 2 -#define SCE_PLM_NUMBER 3 -#define SCE_PLM_IDENTIFIER 4 -#define SCE_PLM_OPERATOR 5 -#define SCE_PLM_CONTROL 6 -#define SCE_PLM_KEYWORD 7 -#define SCE_4GL_DEFAULT 0 -#define SCE_4GL_NUMBER 1 -#define SCE_4GL_WORD 2 -#define SCE_4GL_STRING 3 -#define SCE_4GL_CHARACTER 4 -#define SCE_4GL_PREPROCESSOR 5 -#define SCE_4GL_OPERATOR 6 -#define SCE_4GL_IDENTIFIER 7 -#define SCE_4GL_BLOCK 8 -#define SCE_4GL_END 9 -#define SCE_4GL_COMMENT1 10 -#define SCE_4GL_COMMENT2 11 -#define SCE_4GL_COMMENT3 12 -#define SCE_4GL_COMMENT4 13 -#define SCE_4GL_COMMENT5 14 -#define SCE_4GL_COMMENT6 15 -#define SCE_4GL_DEFAULT_ 16 -#define SCE_4GL_NUMBER_ 17 -#define SCE_4GL_WORD_ 18 -#define SCE_4GL_STRING_ 19 -#define SCE_4GL_CHARACTER_ 20 -#define SCE_4GL_PREPROCESSOR_ 21 -#define SCE_4GL_OPERATOR_ 22 -#define SCE_4GL_IDENTIFIER_ 23 -#define SCE_4GL_BLOCK_ 24 -#define SCE_4GL_END_ 25 -#define SCE_4GL_COMMENT1_ 26 -#define SCE_4GL_COMMENT2_ 27 -#define SCE_4GL_COMMENT3_ 28 -#define SCE_4GL_COMMENT4_ 29 -#define SCE_4GL_COMMENT5_ 30 -#define SCE_4GL_COMMENT6_ 31 -#define SCE_ABAQUS_DEFAULT 0 -#define SCE_ABAQUS_COMMENT 1 -#define SCE_ABAQUS_COMMENTBLOCK 2 -#define SCE_ABAQUS_NUMBER 3 -#define SCE_ABAQUS_STRING 4 -#define SCE_ABAQUS_OPERATOR 5 -#define SCE_ABAQUS_WORD 6 -#define SCE_ABAQUS_PROCESSOR 7 -#define SCE_ABAQUS_COMMAND 8 -#define SCE_ABAQUS_SLASHCOMMAND 9 -#define SCE_ABAQUS_STARCOMMAND 10 -#define SCE_ABAQUS_ARGUMENT 11 -#define SCE_ABAQUS_FUNCTION 12 -#define SCE_ASY_DEFAULT 0 -#define SCE_ASY_COMMENT 1 -#define SCE_ASY_COMMENTLINE 2 -#define SCE_ASY_NUMBER 3 -#define SCE_ASY_WORD 4 -#define SCE_ASY_STRING 5 -#define SCE_ASY_CHARACTER 6 -#define SCE_ASY_OPERATOR 7 -#define SCE_ASY_IDENTIFIER 8 -#define SCE_ASY_STRINGEOL 9 -#define SCE_ASY_COMMENTLINEDOC 10 -#define SCE_ASY_WORD2 11 -#define SCE_R_DEFAULT 0 -#define SCE_R_COMMENT 1 -#define SCE_R_KWORD 2 -#define SCE_R_BASEKWORD 3 -#define SCE_R_OTHERKWORD 4 -#define SCE_R_NUMBER 5 -#define SCE_R_STRING 6 -#define SCE_R_STRING2 7 -#define SCE_R_OPERATOR 8 -#define SCE_R_IDENTIFIER 9 -#define SCE_R_INFIX 10 -#define SCE_R_INFIXEOL 11 -#define SCE_MAGIK_DEFAULT 0 -#define SCE_MAGIK_COMMENT 1 -#define SCE_MAGIK_HYPER_COMMENT 16 -#define SCE_MAGIK_STRING 2 -#define SCE_MAGIK_CHARACTER 3 -#define SCE_MAGIK_NUMBER 4 -#define SCE_MAGIK_IDENTIFIER 5 -#define SCE_MAGIK_OPERATOR 6 -#define SCE_MAGIK_FLOW 7 -#define SCE_MAGIK_CONTAINER 8 -#define SCE_MAGIK_BRACKET_BLOCK 9 -#define SCE_MAGIK_BRACE_BLOCK 10 -#define SCE_MAGIK_SQBRACKET_BLOCK 11 -#define SCE_MAGIK_UNKNOWN_KEYWORD 12 -#define SCE_MAGIK_KEYWORD 13 -#define SCE_MAGIK_PRAGMA 14 -#define SCE_MAGIK_SYMBOL 15 -#define SCE_POWERSHELL_DEFAULT 0 -#define SCE_POWERSHELL_COMMENT 1 -#define SCE_POWERSHELL_STRING 2 -#define SCE_POWERSHELL_CHARACTER 3 -#define SCE_POWERSHELL_NUMBER 4 -#define SCE_POWERSHELL_VARIABLE 5 -#define SCE_POWERSHELL_OPERATOR 6 -#define SCE_POWERSHELL_IDENTIFIER 7 -#define SCE_POWERSHELL_KEYWORD 8 -#define SCE_POWERSHELL_CMDLET 9 -#define SCE_POWERSHELL_ALIAS 10 -#define SCE_POWERSHELL_FUNCTION 11 -#define SCE_POWERSHELL_USER1 12 -#define SCE_POWERSHELL_COMMENTSTREAM 13 -#define SCE_MYSQL_DEFAULT 0 -#define SCE_MYSQL_COMMENT 1 -#define SCE_MYSQL_COMMENTLINE 2 -#define SCE_MYSQL_VARIABLE 3 -#define SCE_MYSQL_SYSTEMVARIABLE 4 -#define SCE_MYSQL_KNOWNSYSTEMVARIABLE 5 -#define SCE_MYSQL_NUMBER 6 -#define SCE_MYSQL_MAJORKEYWORD 7 -#define SCE_MYSQL_KEYWORD 8 -#define SCE_MYSQL_DATABASEOBJECT 9 -#define SCE_MYSQL_PROCEDUREKEYWORD 10 -#define SCE_MYSQL_STRING 11 -#define SCE_MYSQL_SQSTRING 12 -#define SCE_MYSQL_DQSTRING 13 -#define SCE_MYSQL_OPERATOR 14 -#define SCE_MYSQL_FUNCTION 15 -#define SCE_MYSQL_IDENTIFIER 16 -#define SCE_MYSQL_QUOTEDIDENTIFIER 17 -#define SCE_MYSQL_USER1 18 -#define SCE_MYSQL_USER2 19 -#define SCE_MYSQL_USER3 20 -#define SCE_MYSQL_HIDDENCOMMAND 21 -#define SCE_PO_DEFAULT 0 -#define SCE_PO_COMMENT 1 -#define SCE_PO_MSGID 2 -#define SCE_PO_MSGID_TEXT 3 -#define SCE_PO_MSGSTR 4 -#define SCE_PO_MSGSTR_TEXT 5 -#define SCE_PO_MSGCTXT 6 -#define SCE_PO_MSGCTXT_TEXT 7 -#define SCE_PO_FUZZY 8 -#define SCE_PAS_DEFAULT 0 -#define SCE_PAS_IDENTIFIER 1 -#define SCE_PAS_COMMENT 2 -#define SCE_PAS_COMMENT2 3 -#define SCE_PAS_COMMENTLINE 4 -#define SCE_PAS_PREPROCESSOR 5 -#define SCE_PAS_PREPROCESSOR2 6 -#define SCE_PAS_NUMBER 7 -#define SCE_PAS_HEXNUMBER 8 -#define SCE_PAS_WORD 9 -#define SCE_PAS_STRING 10 -#define SCE_PAS_STRINGEOL 11 -#define SCE_PAS_CHARACTER 12 -#define SCE_PAS_OPERATOR 13 -#define SCE_PAS_ASM 14 -#define SCE_SORCUS_DEFAULT 0 -#define SCE_SORCUS_COMMAND 1 -#define SCE_SORCUS_PARAMETER 2 -#define SCE_SORCUS_COMMENTLINE 3 -#define SCE_SORCUS_STRING 4 -#define SCE_SORCUS_STRINGEOL 5 -#define SCE_SORCUS_IDENTIFIER 6 -#define SCE_SORCUS_OPERATOR 7 -#define SCE_SORCUS_NUMBER 8 -#define SCE_SORCUS_CONSTANT 9 -#define SCE_POWERPRO_DEFAULT 0 -#define SCE_POWERPRO_COMMENTBLOCK 1 -#define SCE_POWERPRO_COMMENTLINE 2 -#define SCE_POWERPRO_NUMBER 3 -#define SCE_POWERPRO_WORD 4 -#define SCE_POWERPRO_WORD2 5 -#define SCE_POWERPRO_WORD3 6 -#define SCE_POWERPRO_WORD4 7 -#define SCE_POWERPRO_DOUBLEQUOTEDSTRING 8 -#define SCE_POWERPRO_SINGLEQUOTEDSTRING 9 -#define SCE_POWERPRO_LINECONTINUE 10 -#define SCE_POWERPRO_OPERATOR 11 -#define SCE_POWERPRO_IDENTIFIER 12 -#define SCE_POWERPRO_STRINGEOL 13 -#define SCE_POWERPRO_VERBATIM 14 -#define SCE_POWERPRO_ALTQUOTE 15 -#define SCE_POWERPRO_FUNCTION 16 -#define SCE_SML_DEFAULT 0 -#define SCE_SML_IDENTIFIER 1 -#define SCE_SML_TAGNAME 2 -#define SCE_SML_KEYWORD 3 -#define SCE_SML_KEYWORD2 4 -#define SCE_SML_KEYWORD3 5 -#define SCE_SML_LINENUM 6 -#define SCE_SML_OPERATOR 7 -#define SCE_SML_NUMBER 8 -#define SCE_SML_CHAR 9 -#define SCE_SML_STRING 11 -#define SCE_SML_COMMENT 12 -#define SCE_SML_COMMENT1 13 -#define SCE_SML_COMMENT2 14 -#define SCE_SML_COMMENT3 15 -#define SCE_MARKDOWN_DEFAULT 0 -#define SCE_MARKDOWN_LINE_BEGIN 1 -#define SCE_MARKDOWN_STRONG1 2 -#define SCE_MARKDOWN_STRONG2 3 -#define SCE_MARKDOWN_EM1 4 -#define SCE_MARKDOWN_EM2 5 -#define SCE_MARKDOWN_HEADER1 6 -#define SCE_MARKDOWN_HEADER2 7 -#define SCE_MARKDOWN_HEADER3 8 -#define SCE_MARKDOWN_HEADER4 9 -#define SCE_MARKDOWN_HEADER5 10 -#define SCE_MARKDOWN_HEADER6 11 -#define SCE_MARKDOWN_PRECHAR 12 -#define SCE_MARKDOWN_ULIST_ITEM 13 -#define SCE_MARKDOWN_OLIST_ITEM 14 -#define SCE_MARKDOWN_BLOCKQUOTE 15 -#define SCE_MARKDOWN_STRIKEOUT 16 -#define SCE_MARKDOWN_HRULE 17 -#define SCE_MARKDOWN_LINK 18 -#define SCE_MARKDOWN_CODE 19 -#define SCE_MARKDOWN_CODE2 20 -#define SCE_MARKDOWN_CODEBK 21 -#define SCE_TXT2TAGS_DEFAULT 0 -#define SCE_TXT2TAGS_LINE_BEGIN 1 -#define SCE_TXT2TAGS_STRONG1 2 -#define SCE_TXT2TAGS_STRONG2 3 -#define SCE_TXT2TAGS_EM1 4 -#define SCE_TXT2TAGS_EM2 5 -#define SCE_TXT2TAGS_HEADER1 6 -#define SCE_TXT2TAGS_HEADER2 7 -#define SCE_TXT2TAGS_HEADER3 8 -#define SCE_TXT2TAGS_HEADER4 9 -#define SCE_TXT2TAGS_HEADER5 10 -#define SCE_TXT2TAGS_HEADER6 11 -#define SCE_TXT2TAGS_PRECHAR 12 -#define SCE_TXT2TAGS_ULIST_ITEM 13 -#define SCE_TXT2TAGS_OLIST_ITEM 14 -#define SCE_TXT2TAGS_BLOCKQUOTE 15 -#define SCE_TXT2TAGS_STRIKEOUT 16 -#define SCE_TXT2TAGS_HRULE 17 -#define SCE_TXT2TAGS_LINK 18 -#define SCE_TXT2TAGS_CODE 19 -#define SCE_TXT2TAGS_CODE2 20 -#define SCE_TXT2TAGS_CODEBK 21 -#define SCE_TXT2TAGS_COMMENT 22 -#define SCE_TXT2TAGS_OPTION 23 -#define SCE_TXT2TAGS_PREPROC 24 -#define SCE_TXT2TAGS_POSTPROC 25 -#define SCE_A68K_DEFAULT 0 -#define SCE_A68K_COMMENT 1 -#define SCE_A68K_NUMBER_DEC 2 -#define SCE_A68K_NUMBER_BIN 3 -#define SCE_A68K_NUMBER_HEX 4 -#define SCE_A68K_STRING1 5 -#define SCE_A68K_OPERATOR 6 -#define SCE_A68K_CPUINSTRUCTION 7 -#define SCE_A68K_EXTINSTRUCTION 8 -#define SCE_A68K_REGISTER 9 -#define SCE_A68K_DIRECTIVE 10 -#define SCE_A68K_MACRO_ARG 11 -#define SCE_A68K_LABEL 12 -#define SCE_A68K_STRING2 13 -#define SCE_A68K_IDENTIFIER 14 -#define SCE_A68K_MACRO_DECLARATION 15 -#define SCE_A68K_COMMENT_WORD 16 -#define SCE_A68K_COMMENT_SPECIAL 17 -#define SCE_A68K_COMMENT_DOXYGEN 18 -#define SCE_MODULA_DEFAULT 0 -#define SCE_MODULA_COMMENT 1 -#define SCE_MODULA_DOXYCOMM 2 -#define SCE_MODULA_DOXYKEY 3 -#define SCE_MODULA_KEYWORD 4 -#define SCE_MODULA_RESERVED 5 -#define SCE_MODULA_NUMBER 6 -#define SCE_MODULA_BASENUM 7 -#define SCE_MODULA_FLOAT 8 -#define SCE_MODULA_STRING 9 -#define SCE_MODULA_STRSPEC 10 -#define SCE_MODULA_CHAR 11 -#define SCE_MODULA_CHARSPEC 12 -#define SCE_MODULA_PROC 13 -#define SCE_MODULA_PRAGMA 14 -#define SCE_MODULA_PRGKEY 15 -#define SCE_MODULA_OPERATOR 16 -#define SCE_MODULA_BADSTR 17 -#define SCE_COFFEESCRIPT_DEFAULT 0 -#define SCE_COFFEESCRIPT_COMMENT 1 -#define SCE_COFFEESCRIPT_COMMENTLINE 2 -#define SCE_COFFEESCRIPT_COMMENTDOC 3 -#define SCE_COFFEESCRIPT_NUMBER 4 -#define SCE_COFFEESCRIPT_WORD 5 -#define SCE_COFFEESCRIPT_STRING 6 -#define SCE_COFFEESCRIPT_CHARACTER 7 -#define SCE_COFFEESCRIPT_UUID 8 -#define SCE_COFFEESCRIPT_PREPROCESSOR 9 -#define SCE_COFFEESCRIPT_OPERATOR 10 -#define SCE_COFFEESCRIPT_IDENTIFIER 11 -#define SCE_COFFEESCRIPT_STRINGEOL 12 -#define SCE_COFFEESCRIPT_VERBATIM 13 -#define SCE_COFFEESCRIPT_REGEX 14 -#define SCE_COFFEESCRIPT_COMMENTLINEDOC 15 -#define SCE_COFFEESCRIPT_WORD2 16 -#define SCE_COFFEESCRIPT_COMMENTDOCKEYWORD 17 -#define SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR 18 -#define SCE_COFFEESCRIPT_GLOBALCLASS 19 -#define SCE_COFFEESCRIPT_STRINGRAW 20 -#define SCE_COFFEESCRIPT_TRIPLEVERBATIM 21 -#define SCE_COFFEESCRIPT_HASHQUOTEDSTRING 22 -#define SCE_COFFEESCRIPT_COMMENTBLOCK 22 -#define SCE_COFFEESCRIPT_VERBOSE_REGEX 23 -#define SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT 24 -#define SCE_AVS_DEFAULT 0 -#define SCE_AVS_COMMENTBLOCK 1 -#define SCE_AVS_COMMENTBLOCKN 2 -#define SCE_AVS_COMMENTLINE 3 -#define SCE_AVS_NUMBER 4 -#define SCE_AVS_OPERATOR 5 -#define SCE_AVS_IDENTIFIER 6 -#define SCE_AVS_STRING 7 -#define SCE_AVS_TRIPLESTRING 8 -#define SCE_AVS_KEYWORD 9 -#define SCE_AVS_FILTER 10 -#define SCE_AVS_PLUGIN 11 -#define SCE_AVS_FUNCTION 12 -#define SCE_AVS_CLIPPROP 13 -#define SCE_AVS_USERDFN 14 -/* --Autogenerated -- end of section automatically generated from Scintilla.iface */ - -#endif +/* Scintilla source code edit control */ +/** @file SciLexer.h + ** Interface to the added lexer functions in the SciLexer version of the edit control. + **/ +/* Copyright 1998-2002 by Neil Hodgson + * The License.txt file describes the conditions under which this software may be distributed. */ + +/* Most of this file is automatically generated from the Scintilla.iface interface definition + * file which contains any comments about the definitions. HFacer.py does the generation. */ + +#ifndef SCILEXER_H +#define SCILEXER_H + +/* SciLexer features - not in standard Scintilla */ + +/* ++Autogenerated -- start of section automatically generated from Scintilla.iface */ +#define SCLEX_CONTAINER 0 +#define SCLEX_NULL 1 +#define SCLEX_PYTHON 2 +#define SCLEX_CPP 3 +#define SCLEX_HTML 4 +#define SCLEX_XML 5 +#define SCLEX_PERL 6 +#define SCLEX_SQL 7 +#define SCLEX_VB 8 +#define SCLEX_PROPERTIES 9 +#define SCLEX_ERRORLIST 10 +#define SCLEX_MAKEFILE 11 +#define SCLEX_BATCH 12 +#define SCLEX_XCODE 13 +#define SCLEX_LATEX 14 +#define SCLEX_LUA 15 +#define SCLEX_DIFF 16 +#define SCLEX_CONF 17 +#define SCLEX_PASCAL 18 +#define SCLEX_AVE 19 +#define SCLEX_ADA 20 +#define SCLEX_LISP 21 +#define SCLEX_RUBY 22 +#define SCLEX_EIFFEL 23 +#define SCLEX_EIFFELKW 24 +#define SCLEX_TCL 25 +#define SCLEX_NNCRONTAB 26 +#define SCLEX_BULLANT 27 +#define SCLEX_VBSCRIPT 28 +#define SCLEX_BAAN 31 +#define SCLEX_MATLAB 32 +#define SCLEX_SCRIPTOL 33 +#define SCLEX_ASM 34 +#define SCLEX_CPPNOCASE 35 +#define SCLEX_FORTRAN 36 +#define SCLEX_F77 37 +#define SCLEX_CSS 38 +#define SCLEX_POV 39 +#define SCLEX_LOUT 40 +#define SCLEX_ESCRIPT 41 +#define SCLEX_PS 42 +#define SCLEX_NSIS 43 +#define SCLEX_MMIXAL 44 +#define SCLEX_CLW 45 +#define SCLEX_CLWNOCASE 46 +#define SCLEX_LOT 47 +#define SCLEX_YAML 48 +#define SCLEX_TEX 49 +#define SCLEX_METAPOST 50 +#define SCLEX_POWERBASIC 51 +#define SCLEX_FORTH 52 +#define SCLEX_ERLANG 53 +#define SCLEX_OCTAVE 54 +#define SCLEX_MSSQL 55 +#define SCLEX_VERILOG 56 +#define SCLEX_KIX 57 +#define SCLEX_GUI4CLI 58 +#define SCLEX_SPECMAN 59 +#define SCLEX_AU3 60 +#define SCLEX_APDL 61 +#define SCLEX_BASH 62 +#define SCLEX_ASN1 63 +#define SCLEX_VHDL 64 +#define SCLEX_CAML 65 +#define SCLEX_BLITZBASIC 66 +#define SCLEX_PUREBASIC 67 +#define SCLEX_HASKELL 68 +#define SCLEX_PHPSCRIPT 69 +#define SCLEX_TADS3 70 +#define SCLEX_REBOL 71 +#define SCLEX_SMALLTALK 72 +#define SCLEX_FLAGSHIP 73 +#define SCLEX_CSOUND 74 +#define SCLEX_FREEBASIC 75 +#define SCLEX_INNOSETUP 76 +#define SCLEX_OPAL 77 +#define SCLEX_SPICE 78 +#define SCLEX_D 79 +#define SCLEX_CMAKE 80 +#define SCLEX_GAP 81 +#define SCLEX_PLM 82 +#define SCLEX_PROGRESS 83 +#define SCLEX_ABAQUS 84 +#define SCLEX_ASYMPTOTE 85 +#define SCLEX_R 86 +#define SCLEX_MAGIK 87 +#define SCLEX_POWERSHELL 88 +#define SCLEX_MYSQL 89 +#define SCLEX_PO 90 +#define SCLEX_TAL 91 +#define SCLEX_COBOL 92 +#define SCLEX_TACL 93 +#define SCLEX_SORCUS 94 +#define SCLEX_POWERPRO 95 +#define SCLEX_NIMROD 96 +#define SCLEX_SML 97 +#define SCLEX_MARKDOWN 98 +#define SCLEX_TXT2TAGS 99 +#define SCLEX_A68K 100 +#define SCLEX_MODULA 101 +#define SCLEX_COFFEESCRIPT 102 +#define SCLEX_TCMD 103 +#define SCLEX_AVS 104 +#define SCLEX_AUTOMATIC 1000 +#define SCE_P_DEFAULT 0 +#define SCE_P_COMMENTLINE 1 +#define SCE_P_NUMBER 2 +#define SCE_P_STRING 3 +#define SCE_P_CHARACTER 4 +#define SCE_P_WORD 5 +#define SCE_P_TRIPLE 6 +#define SCE_P_TRIPLEDOUBLE 7 +#define SCE_P_CLASSNAME 8 +#define SCE_P_DEFNAME 9 +#define SCE_P_OPERATOR 10 +#define SCE_P_IDENTIFIER 11 +#define SCE_P_COMMENTBLOCK 12 +#define SCE_P_STRINGEOL 13 +#define SCE_P_WORD2 14 +#define SCE_P_DECORATOR 15 +#define SCE_C_DEFAULT 0 +#define SCE_C_COMMENT 1 +#define SCE_C_COMMENTLINE 2 +#define SCE_C_COMMENTDOC 3 +#define SCE_C_NUMBER 4 +#define SCE_C_WORD 5 +#define SCE_C_STRING 6 +#define SCE_C_CHARACTER 7 +#define SCE_C_UUID 8 +#define SCE_C_PREPROCESSOR 9 +#define SCE_C_OPERATOR 10 +#define SCE_C_IDENTIFIER 11 +#define SCE_C_STRINGEOL 12 +#define SCE_C_VERBATIM 13 +#define SCE_C_REGEX 14 +#define SCE_C_COMMENTLINEDOC 15 +#define SCE_C_WORD2 16 +#define SCE_C_COMMENTDOCKEYWORD 17 +#define SCE_C_COMMENTDOCKEYWORDERROR 18 +#define SCE_C_GLOBALCLASS 19 +#define SCE_C_STRINGRAW 20 +#define SCE_C_TRIPLEVERBATIM 21 +#define SCE_C_HASHQUOTEDSTRING 22 +#define SCE_D_DEFAULT 0 +#define SCE_D_COMMENT 1 +#define SCE_D_COMMENTLINE 2 +#define SCE_D_COMMENTDOC 3 +#define SCE_D_COMMENTNESTED 4 +#define SCE_D_NUMBER 5 +#define SCE_D_WORD 6 +#define SCE_D_WORD2 7 +#define SCE_D_WORD3 8 +#define SCE_D_TYPEDEF 9 +#define SCE_D_STRING 10 +#define SCE_D_STRINGEOL 11 +#define SCE_D_CHARACTER 12 +#define SCE_D_OPERATOR 13 +#define SCE_D_IDENTIFIER 14 +#define SCE_D_COMMENTLINEDOC 15 +#define SCE_D_COMMENTDOCKEYWORD 16 +#define SCE_D_COMMENTDOCKEYWORDERROR 17 +#define SCE_D_STRINGB 18 +#define SCE_D_STRINGR 19 +#define SCE_D_WORD5 20 +#define SCE_D_WORD6 21 +#define SCE_D_WORD7 22 +#define SCE_TCL_DEFAULT 0 +#define SCE_TCL_COMMENT 1 +#define SCE_TCL_COMMENTLINE 2 +#define SCE_TCL_NUMBER 3 +#define SCE_TCL_WORD_IN_QUOTE 4 +#define SCE_TCL_IN_QUOTE 5 +#define SCE_TCL_OPERATOR 6 +#define SCE_TCL_IDENTIFIER 7 +#define SCE_TCL_SUBSTITUTION 8 +#define SCE_TCL_SUB_BRACE 9 +#define SCE_TCL_MODIFIER 10 +#define SCE_TCL_EXPAND 11 +#define SCE_TCL_WORD 12 +#define SCE_TCL_WORD2 13 +#define SCE_TCL_WORD3 14 +#define SCE_TCL_WORD4 15 +#define SCE_TCL_WORD5 16 +#define SCE_TCL_WORD6 17 +#define SCE_TCL_WORD7 18 +#define SCE_TCL_WORD8 19 +#define SCE_TCL_COMMENT_BOX 20 +#define SCE_TCL_BLOCK_COMMENT 21 +#define SCE_H_DEFAULT 0 +#define SCE_H_TAG 1 +#define SCE_H_TAGUNKNOWN 2 +#define SCE_H_ATTRIBUTE 3 +#define SCE_H_ATTRIBUTEUNKNOWN 4 +#define SCE_H_NUMBER 5 +#define SCE_H_DOUBLESTRING 6 +#define SCE_H_SINGLESTRING 7 +#define SCE_H_OTHER 8 +#define SCE_H_COMMENT 9 +#define SCE_H_ENTITY 10 +#define SCE_H_TAGEND 11 +#define SCE_H_XMLSTART 12 +#define SCE_H_XMLEND 13 +#define SCE_H_SCRIPT 14 +#define SCE_H_ASP 15 +#define SCE_H_ASPAT 16 +#define SCE_H_CDATA 17 +#define SCE_H_QUESTION 18 +#define SCE_H_VALUE 19 +#define SCE_H_XCCOMMENT 20 +#define SCE_H_SGML_DEFAULT 21 +#define SCE_H_SGML_COMMAND 22 +#define SCE_H_SGML_1ST_PARAM 23 +#define SCE_H_SGML_DOUBLESTRING 24 +#define SCE_H_SGML_SIMPLESTRING 25 +#define SCE_H_SGML_ERROR 26 +#define SCE_H_SGML_SPECIAL 27 +#define SCE_H_SGML_ENTITY 28 +#define SCE_H_SGML_COMMENT 29 +#define SCE_H_SGML_1ST_PARAM_COMMENT 30 +#define SCE_H_SGML_BLOCK_DEFAULT 31 +#define SCE_HJ_START 40 +#define SCE_HJ_DEFAULT 41 +#define SCE_HJ_COMMENT 42 +#define SCE_HJ_COMMENTLINE 43 +#define SCE_HJ_COMMENTDOC 44 +#define SCE_HJ_NUMBER 45 +#define SCE_HJ_WORD 46 +#define SCE_HJ_KEYWORD 47 +#define SCE_HJ_DOUBLESTRING 48 +#define SCE_HJ_SINGLESTRING 49 +#define SCE_HJ_SYMBOLS 50 +#define SCE_HJ_STRINGEOL 51 +#define SCE_HJ_REGEX 52 +#define SCE_HJA_START 55 +#define SCE_HJA_DEFAULT 56 +#define SCE_HJA_COMMENT 57 +#define SCE_HJA_COMMENTLINE 58 +#define SCE_HJA_COMMENTDOC 59 +#define SCE_HJA_NUMBER 60 +#define SCE_HJA_WORD 61 +#define SCE_HJA_KEYWORD 62 +#define SCE_HJA_DOUBLESTRING 63 +#define SCE_HJA_SINGLESTRING 64 +#define SCE_HJA_SYMBOLS 65 +#define SCE_HJA_STRINGEOL 66 +#define SCE_HJA_REGEX 67 +#define SCE_HB_START 70 +#define SCE_HB_DEFAULT 71 +#define SCE_HB_COMMENTLINE 72 +#define SCE_HB_NUMBER 73 +#define SCE_HB_WORD 74 +#define SCE_HB_STRING 75 +#define SCE_HB_IDENTIFIER 76 +#define SCE_HB_STRINGEOL 77 +#define SCE_HBA_START 80 +#define SCE_HBA_DEFAULT 81 +#define SCE_HBA_COMMENTLINE 82 +#define SCE_HBA_NUMBER 83 +#define SCE_HBA_WORD 84 +#define SCE_HBA_STRING 85 +#define SCE_HBA_IDENTIFIER 86 +#define SCE_HBA_STRINGEOL 87 +#define SCE_HP_START 90 +#define SCE_HP_DEFAULT 91 +#define SCE_HP_COMMENTLINE 92 +#define SCE_HP_NUMBER 93 +#define SCE_HP_STRING 94 +#define SCE_HP_CHARACTER 95 +#define SCE_HP_WORD 96 +#define SCE_HP_TRIPLE 97 +#define SCE_HP_TRIPLEDOUBLE 98 +#define SCE_HP_CLASSNAME 99 +#define SCE_HP_DEFNAME 100 +#define SCE_HP_OPERATOR 101 +#define SCE_HP_IDENTIFIER 102 +#define SCE_HPHP_COMPLEX_VARIABLE 104 +#define SCE_HPA_START 105 +#define SCE_HPA_DEFAULT 106 +#define SCE_HPA_COMMENTLINE 107 +#define SCE_HPA_NUMBER 108 +#define SCE_HPA_STRING 109 +#define SCE_HPA_CHARACTER 110 +#define SCE_HPA_WORD 111 +#define SCE_HPA_TRIPLE 112 +#define SCE_HPA_TRIPLEDOUBLE 113 +#define SCE_HPA_CLASSNAME 114 +#define SCE_HPA_DEFNAME 115 +#define SCE_HPA_OPERATOR 116 +#define SCE_HPA_IDENTIFIER 117 +#define SCE_HPHP_DEFAULT 118 +#define SCE_HPHP_HSTRING 119 +#define SCE_HPHP_SIMPLESTRING 120 +#define SCE_HPHP_WORD 121 +#define SCE_HPHP_NUMBER 122 +#define SCE_HPHP_VARIABLE 123 +#define SCE_HPHP_COMMENT 124 +#define SCE_HPHP_COMMENTLINE 125 +#define SCE_HPHP_HSTRING_VARIABLE 126 +#define SCE_HPHP_OPERATOR 127 +#define SCE_PL_DEFAULT 0 +#define SCE_PL_ERROR 1 +#define SCE_PL_COMMENTLINE 2 +#define SCE_PL_POD 3 +#define SCE_PL_NUMBER 4 +#define SCE_PL_WORD 5 +#define SCE_PL_STRING 6 +#define SCE_PL_CHARACTER 7 +#define SCE_PL_PUNCTUATION 8 +#define SCE_PL_PREPROCESSOR 9 +#define SCE_PL_OPERATOR 10 +#define SCE_PL_IDENTIFIER 11 +#define SCE_PL_SCALAR 12 +#define SCE_PL_ARRAY 13 +#define SCE_PL_HASH 14 +#define SCE_PL_SYMBOLTABLE 15 +#define SCE_PL_VARIABLE_INDEXER 16 +#define SCE_PL_REGEX 17 +#define SCE_PL_REGSUBST 18 +#define SCE_PL_LONGQUOTE 19 +#define SCE_PL_BACKTICKS 20 +#define SCE_PL_DATASECTION 21 +#define SCE_PL_HERE_DELIM 22 +#define SCE_PL_HERE_Q 23 +#define SCE_PL_HERE_QQ 24 +#define SCE_PL_HERE_QX 25 +#define SCE_PL_STRING_Q 26 +#define SCE_PL_STRING_QQ 27 +#define SCE_PL_STRING_QX 28 +#define SCE_PL_STRING_QR 29 +#define SCE_PL_STRING_QW 30 +#define SCE_PL_POD_VERB 31 +#define SCE_PL_SUB_PROTOTYPE 40 +#define SCE_PL_FORMAT_IDENT 41 +#define SCE_PL_FORMAT 42 +#define SCE_PL_STRING_VAR 43 +#define SCE_PL_XLAT 44 +#define SCE_PL_REGEX_VAR 54 +#define SCE_PL_REGSUBST_VAR 55 +#define SCE_PL_BACKTICKS_VAR 57 +#define SCE_PL_HERE_QQ_VAR 61 +#define SCE_PL_HERE_QX_VAR 62 +#define SCE_PL_STRING_QQ_VAR 64 +#define SCE_PL_STRING_QX_VAR 65 +#define SCE_PL_STRING_QR_VAR 66 +#define SCE_RB_DEFAULT 0 +#define SCE_RB_ERROR 1 +#define SCE_RB_COMMENTLINE 2 +#define SCE_RB_POD 3 +#define SCE_RB_NUMBER 4 +#define SCE_RB_WORD 5 +#define SCE_RB_STRING 6 +#define SCE_RB_CHARACTER 7 +#define SCE_RB_CLASSNAME 8 +#define SCE_RB_DEFNAME 9 +#define SCE_RB_OPERATOR 10 +#define SCE_RB_IDENTIFIER 11 +#define SCE_RB_REGEX 12 +#define SCE_RB_GLOBAL 13 +#define SCE_RB_SYMBOL 14 +#define SCE_RB_MODULE_NAME 15 +#define SCE_RB_INSTANCE_VAR 16 +#define SCE_RB_CLASS_VAR 17 +#define SCE_RB_BACKTICKS 18 +#define SCE_RB_DATASECTION 19 +#define SCE_RB_HERE_DELIM 20 +#define SCE_RB_HERE_Q 21 +#define SCE_RB_HERE_QQ 22 +#define SCE_RB_HERE_QX 23 +#define SCE_RB_STRING_Q 24 +#define SCE_RB_STRING_QQ 25 +#define SCE_RB_STRING_QX 26 +#define SCE_RB_STRING_QR 27 +#define SCE_RB_STRING_QW 28 +#define SCE_RB_WORD_DEMOTED 29 +#define SCE_RB_STDIN 30 +#define SCE_RB_STDOUT 31 +#define SCE_RB_STDERR 40 +#define SCE_RB_UPPER_BOUND 41 +#define SCE_B_DEFAULT 0 +#define SCE_B_COMMENT 1 +#define SCE_B_NUMBER 2 +#define SCE_B_KEYWORD 3 +#define SCE_B_STRING 4 +#define SCE_B_PREPROCESSOR 5 +#define SCE_B_OPERATOR 6 +#define SCE_B_IDENTIFIER 7 +#define SCE_B_DATE 8 +#define SCE_B_STRINGEOL 9 +#define SCE_B_KEYWORD2 10 +#define SCE_B_KEYWORD3 11 +#define SCE_B_KEYWORD4 12 +#define SCE_B_CONSTANT 13 +#define SCE_B_ASM 14 +#define SCE_B_LABEL 15 +#define SCE_B_ERROR 16 +#define SCE_B_HEXNUMBER 17 +#define SCE_B_BINNUMBER 18 +#define SCE_PROPS_DEFAULT 0 +#define SCE_PROPS_COMMENT 1 +#define SCE_PROPS_SECTION 2 +#define SCE_PROPS_ASSIGNMENT 3 +#define SCE_PROPS_DEFVAL 4 +#define SCE_PROPS_KEY 5 +#define SCE_L_DEFAULT 0 +#define SCE_L_COMMAND 1 +#define SCE_L_TAG 2 +#define SCE_L_MATH 3 +#define SCE_L_COMMENT 4 +#define SCE_L_TAG2 5 +#define SCE_L_MATH2 6 +#define SCE_L_COMMENT2 7 +#define SCE_L_VERBATIM 8 +#define SCE_L_SHORTCMD 9 +#define SCE_L_SPECIAL 10 +#define SCE_L_CMDOPT 11 +#define SCE_L_ERROR 12 +#define SCE_LUA_DEFAULT 0 +#define SCE_LUA_COMMENT 1 +#define SCE_LUA_COMMENTLINE 2 +#define SCE_LUA_COMMENTDOC 3 +#define SCE_LUA_NUMBER 4 +#define SCE_LUA_WORD 5 +#define SCE_LUA_STRING 6 +#define SCE_LUA_CHARACTER 7 +#define SCE_LUA_LITERALSTRING 8 +#define SCE_LUA_PREPROCESSOR 9 +#define SCE_LUA_OPERATOR 10 +#define SCE_LUA_IDENTIFIER 11 +#define SCE_LUA_STRINGEOL 12 +#define SCE_LUA_WORD2 13 +#define SCE_LUA_WORD3 14 +#define SCE_LUA_WORD4 15 +#define SCE_LUA_WORD5 16 +#define SCE_LUA_WORD6 17 +#define SCE_LUA_WORD7 18 +#define SCE_LUA_WORD8 19 +#define SCE_LUA_LABEL 20 +#define SCE_ERR_DEFAULT 0 +#define SCE_ERR_PYTHON 1 +#define SCE_ERR_GCC 2 +#define SCE_ERR_MS 3 +#define SCE_ERR_CMD 4 +#define SCE_ERR_BORLAND 5 +#define SCE_ERR_PERL 6 +#define SCE_ERR_NET 7 +#define SCE_ERR_LUA 8 +#define SCE_ERR_CTAG 9 +#define SCE_ERR_DIFF_CHANGED 10 +#define SCE_ERR_DIFF_ADDITION 11 +#define SCE_ERR_DIFF_DELETION 12 +#define SCE_ERR_DIFF_MESSAGE 13 +#define SCE_ERR_PHP 14 +#define SCE_ERR_ELF 15 +#define SCE_ERR_IFC 16 +#define SCE_ERR_IFORT 17 +#define SCE_ERR_ABSF 18 +#define SCE_ERR_TIDY 19 +#define SCE_ERR_JAVA_STACK 20 +#define SCE_ERR_VALUE 21 +#define SCE_BAT_DEFAULT 0 +#define SCE_BAT_COMMENT 1 +#define SCE_BAT_WORD 2 +#define SCE_BAT_LABEL 3 +#define SCE_BAT_HIDE 4 +#define SCE_BAT_COMMAND 5 +#define SCE_BAT_IDENTIFIER 6 +#define SCE_BAT_OPERATOR 7 +#define SCE_TCMD_DEFAULT 0 +#define SCE_TCMD_COMMENT 1 +#define SCE_TCMD_WORD 2 +#define SCE_TCMD_LABEL 3 +#define SCE_TCMD_HIDE 4 +#define SCE_TCMD_COMMAND 5 +#define SCE_TCMD_IDENTIFIER 6 +#define SCE_TCMD_OPERATOR 7 +#define SCE_TCMD_ENVIRONMENT 8 +#define SCE_TCMD_EXPANSION 9 +#define SCE_TCMD_CLABEL 10 +#define SCE_MAKE_DEFAULT 0 +#define SCE_MAKE_COMMENT 1 +#define SCE_MAKE_PREPROCESSOR 2 +#define SCE_MAKE_IDENTIFIER 3 +#define SCE_MAKE_OPERATOR 4 +#define SCE_MAKE_TARGET 5 +#define SCE_MAKE_IDEOL 9 +#define SCE_DIFF_DEFAULT 0 +#define SCE_DIFF_COMMENT 1 +#define SCE_DIFF_COMMAND 2 +#define SCE_DIFF_HEADER 3 +#define SCE_DIFF_POSITION 4 +#define SCE_DIFF_DELETED 5 +#define SCE_DIFF_ADDED 6 +#define SCE_DIFF_CHANGED 7 +#define SCE_CONF_DEFAULT 0 +#define SCE_CONF_COMMENT 1 +#define SCE_CONF_NUMBER 2 +#define SCE_CONF_IDENTIFIER 3 +#define SCE_CONF_EXTENSION 4 +#define SCE_CONF_PARAMETER 5 +#define SCE_CONF_STRING 6 +#define SCE_CONF_OPERATOR 7 +#define SCE_CONF_IP 8 +#define SCE_CONF_DIRECTIVE 9 +#define SCE_AVE_DEFAULT 0 +#define SCE_AVE_COMMENT 1 +#define SCE_AVE_NUMBER 2 +#define SCE_AVE_WORD 3 +#define SCE_AVE_STRING 6 +#define SCE_AVE_ENUM 7 +#define SCE_AVE_STRINGEOL 8 +#define SCE_AVE_IDENTIFIER 9 +#define SCE_AVE_OPERATOR 10 +#define SCE_AVE_WORD1 11 +#define SCE_AVE_WORD2 12 +#define SCE_AVE_WORD3 13 +#define SCE_AVE_WORD4 14 +#define SCE_AVE_WORD5 15 +#define SCE_AVE_WORD6 16 +#define SCE_ADA_DEFAULT 0 +#define SCE_ADA_WORD 1 +#define SCE_ADA_IDENTIFIER 2 +#define SCE_ADA_NUMBER 3 +#define SCE_ADA_DELIMITER 4 +#define SCE_ADA_CHARACTER 5 +#define SCE_ADA_CHARACTEREOL 6 +#define SCE_ADA_STRING 7 +#define SCE_ADA_STRINGEOL 8 +#define SCE_ADA_LABEL 9 +#define SCE_ADA_COMMENTLINE 10 +#define SCE_ADA_ILLEGAL 11 +#define SCE_BAAN_DEFAULT 0 +#define SCE_BAAN_COMMENT 1 +#define SCE_BAAN_COMMENTDOC 2 +#define SCE_BAAN_NUMBER 3 +#define SCE_BAAN_WORD 4 +#define SCE_BAAN_STRING 5 +#define SCE_BAAN_PREPROCESSOR 6 +#define SCE_BAAN_OPERATOR 7 +#define SCE_BAAN_IDENTIFIER 8 +#define SCE_BAAN_STRINGEOL 9 +#define SCE_BAAN_WORD2 10 +#define SCE_LISP_DEFAULT 0 +#define SCE_LISP_COMMENT 1 +#define SCE_LISP_NUMBER 2 +#define SCE_LISP_KEYWORD 3 +#define SCE_LISP_KEYWORD_KW 4 +#define SCE_LISP_SYMBOL 5 +#define SCE_LISP_STRING 6 +#define SCE_LISP_STRINGEOL 8 +#define SCE_LISP_IDENTIFIER 9 +#define SCE_LISP_OPERATOR 10 +#define SCE_LISP_SPECIAL 11 +#define SCE_LISP_MULTI_COMMENT 12 +#define SCE_EIFFEL_DEFAULT 0 +#define SCE_EIFFEL_COMMENTLINE 1 +#define SCE_EIFFEL_NUMBER 2 +#define SCE_EIFFEL_WORD 3 +#define SCE_EIFFEL_STRING 4 +#define SCE_EIFFEL_CHARACTER 5 +#define SCE_EIFFEL_OPERATOR 6 +#define SCE_EIFFEL_IDENTIFIER 7 +#define SCE_EIFFEL_STRINGEOL 8 +#define SCE_NNCRONTAB_DEFAULT 0 +#define SCE_NNCRONTAB_COMMENT 1 +#define SCE_NNCRONTAB_TASK 2 +#define SCE_NNCRONTAB_SECTION 3 +#define SCE_NNCRONTAB_KEYWORD 4 +#define SCE_NNCRONTAB_MODIFIER 5 +#define SCE_NNCRONTAB_ASTERISK 6 +#define SCE_NNCRONTAB_NUMBER 7 +#define SCE_NNCRONTAB_STRING 8 +#define SCE_NNCRONTAB_ENVIRONMENT 9 +#define SCE_NNCRONTAB_IDENTIFIER 10 +#define SCE_FORTH_DEFAULT 0 +#define SCE_FORTH_COMMENT 1 +#define SCE_FORTH_COMMENT_ML 2 +#define SCE_FORTH_IDENTIFIER 3 +#define SCE_FORTH_CONTROL 4 +#define SCE_FORTH_KEYWORD 5 +#define SCE_FORTH_DEFWORD 6 +#define SCE_FORTH_PREWORD1 7 +#define SCE_FORTH_PREWORD2 8 +#define SCE_FORTH_NUMBER 9 +#define SCE_FORTH_STRING 10 +#define SCE_FORTH_LOCALE 11 +#define SCE_MATLAB_DEFAULT 0 +#define SCE_MATLAB_COMMENT 1 +#define SCE_MATLAB_COMMAND 2 +#define SCE_MATLAB_NUMBER 3 +#define SCE_MATLAB_KEYWORD 4 +#define SCE_MATLAB_STRING 5 +#define SCE_MATLAB_OPERATOR 6 +#define SCE_MATLAB_IDENTIFIER 7 +#define SCE_MATLAB_DOUBLEQUOTESTRING 8 +#define SCE_SCRIPTOL_DEFAULT 0 +#define SCE_SCRIPTOL_WHITE 1 +#define SCE_SCRIPTOL_COMMENTLINE 2 +#define SCE_SCRIPTOL_PERSISTENT 3 +#define SCE_SCRIPTOL_CSTYLE 4 +#define SCE_SCRIPTOL_COMMENTBLOCK 5 +#define SCE_SCRIPTOL_NUMBER 6 +#define SCE_SCRIPTOL_STRING 7 +#define SCE_SCRIPTOL_CHARACTER 8 +#define SCE_SCRIPTOL_STRINGEOL 9 +#define SCE_SCRIPTOL_KEYWORD 10 +#define SCE_SCRIPTOL_OPERATOR 11 +#define SCE_SCRIPTOL_IDENTIFIER 12 +#define SCE_SCRIPTOL_TRIPLE 13 +#define SCE_SCRIPTOL_CLASSNAME 14 +#define SCE_SCRIPTOL_PREPROCESSOR 15 +#define SCE_ASM_DEFAULT 0 +#define SCE_ASM_COMMENT 1 +#define SCE_ASM_NUMBER 2 +#define SCE_ASM_STRING 3 +#define SCE_ASM_OPERATOR 4 +#define SCE_ASM_IDENTIFIER 5 +#define SCE_ASM_CPUINSTRUCTION 6 +#define SCE_ASM_MATHINSTRUCTION 7 +#define SCE_ASM_REGISTER 8 +#define SCE_ASM_DIRECTIVE 9 +#define SCE_ASM_DIRECTIVEOPERAND 10 +#define SCE_ASM_COMMENTBLOCK 11 +#define SCE_ASM_CHARACTER 12 +#define SCE_ASM_STRINGEOL 13 +#define SCE_ASM_EXTINSTRUCTION 14 +#define SCE_ASM_COMMENTDIRECTIVE 15 +#define SCE_F_DEFAULT 0 +#define SCE_F_COMMENT 1 +#define SCE_F_NUMBER 2 +#define SCE_F_STRING1 3 +#define SCE_F_STRING2 4 +#define SCE_F_STRINGEOL 5 +#define SCE_F_OPERATOR 6 +#define SCE_F_IDENTIFIER 7 +#define SCE_F_WORD 8 +#define SCE_F_WORD2 9 +#define SCE_F_WORD3 10 +#define SCE_F_PREPROCESSOR 11 +#define SCE_F_OPERATOR2 12 +#define SCE_F_LABEL 13 +#define SCE_F_CONTINUATION 14 +#define SCE_CSS_DEFAULT 0 +#define SCE_CSS_TAG 1 +#define SCE_CSS_CLASS 2 +#define SCE_CSS_PSEUDOCLASS 3 +#define SCE_CSS_UNKNOWN_PSEUDOCLASS 4 +#define SCE_CSS_OPERATOR 5 +#define SCE_CSS_IDENTIFIER 6 +#define SCE_CSS_UNKNOWN_IDENTIFIER 7 +#define SCE_CSS_VALUE 8 +#define SCE_CSS_COMMENT 9 +#define SCE_CSS_ID 10 +#define SCE_CSS_IMPORTANT 11 +#define SCE_CSS_DIRECTIVE 12 +#define SCE_CSS_DOUBLESTRING 13 +#define SCE_CSS_SINGLESTRING 14 +#define SCE_CSS_IDENTIFIER2 15 +#define SCE_CSS_ATTRIBUTE 16 +#define SCE_CSS_IDENTIFIER3 17 +#define SCE_CSS_PSEUDOELEMENT 18 +#define SCE_CSS_EXTENDED_IDENTIFIER 19 +#define SCE_CSS_EXTENDED_PSEUDOCLASS 20 +#define SCE_CSS_EXTENDED_PSEUDOELEMENT 21 +#define SCE_CSS_MEDIA 22 +#define SCE_CSS_VARIABLE 23 +#define SCE_POV_DEFAULT 0 +#define SCE_POV_COMMENT 1 +#define SCE_POV_COMMENTLINE 2 +#define SCE_POV_NUMBER 3 +#define SCE_POV_OPERATOR 4 +#define SCE_POV_IDENTIFIER 5 +#define SCE_POV_STRING 6 +#define SCE_POV_STRINGEOL 7 +#define SCE_POV_DIRECTIVE 8 +#define SCE_POV_BADDIRECTIVE 9 +#define SCE_POV_WORD2 10 +#define SCE_POV_WORD3 11 +#define SCE_POV_WORD4 12 +#define SCE_POV_WORD5 13 +#define SCE_POV_WORD6 14 +#define SCE_POV_WORD7 15 +#define SCE_POV_WORD8 16 +#define SCE_LOUT_DEFAULT 0 +#define SCE_LOUT_COMMENT 1 +#define SCE_LOUT_NUMBER 2 +#define SCE_LOUT_WORD 3 +#define SCE_LOUT_WORD2 4 +#define SCE_LOUT_WORD3 5 +#define SCE_LOUT_WORD4 6 +#define SCE_LOUT_STRING 7 +#define SCE_LOUT_OPERATOR 8 +#define SCE_LOUT_IDENTIFIER 9 +#define SCE_LOUT_STRINGEOL 10 +#define SCE_ESCRIPT_DEFAULT 0 +#define SCE_ESCRIPT_COMMENT 1 +#define SCE_ESCRIPT_COMMENTLINE 2 +#define SCE_ESCRIPT_COMMENTDOC 3 +#define SCE_ESCRIPT_NUMBER 4 +#define SCE_ESCRIPT_WORD 5 +#define SCE_ESCRIPT_STRING 6 +#define SCE_ESCRIPT_OPERATOR 7 +#define SCE_ESCRIPT_IDENTIFIER 8 +#define SCE_ESCRIPT_BRACE 9 +#define SCE_ESCRIPT_WORD2 10 +#define SCE_ESCRIPT_WORD3 11 +#define SCE_PS_DEFAULT 0 +#define SCE_PS_COMMENT 1 +#define SCE_PS_DSC_COMMENT 2 +#define SCE_PS_DSC_VALUE 3 +#define SCE_PS_NUMBER 4 +#define SCE_PS_NAME 5 +#define SCE_PS_KEYWORD 6 +#define SCE_PS_LITERAL 7 +#define SCE_PS_IMMEVAL 8 +#define SCE_PS_PAREN_ARRAY 9 +#define SCE_PS_PAREN_DICT 10 +#define SCE_PS_PAREN_PROC 11 +#define SCE_PS_TEXT 12 +#define SCE_PS_HEXSTRING 13 +#define SCE_PS_BASE85STRING 14 +#define SCE_PS_BADSTRINGCHAR 15 +#define SCE_NSIS_DEFAULT 0 +#define SCE_NSIS_COMMENT 1 +#define SCE_NSIS_STRINGDQ 2 +#define SCE_NSIS_STRINGLQ 3 +#define SCE_NSIS_STRINGRQ 4 +#define SCE_NSIS_FUNCTION 5 +#define SCE_NSIS_VARIABLE 6 +#define SCE_NSIS_LABEL 7 +#define SCE_NSIS_USERDEFINED 8 +#define SCE_NSIS_SECTIONDEF 9 +#define SCE_NSIS_SUBSECTIONDEF 10 +#define SCE_NSIS_IFDEFINEDEF 11 +#define SCE_NSIS_MACRODEF 12 +#define SCE_NSIS_STRINGVAR 13 +#define SCE_NSIS_NUMBER 14 +#define SCE_NSIS_SECTIONGROUP 15 +#define SCE_NSIS_PAGEEX 16 +#define SCE_NSIS_FUNCTIONDEF 17 +#define SCE_NSIS_COMMENTBOX 18 +#define SCE_MMIXAL_LEADWS 0 +#define SCE_MMIXAL_COMMENT 1 +#define SCE_MMIXAL_LABEL 2 +#define SCE_MMIXAL_OPCODE 3 +#define SCE_MMIXAL_OPCODE_PRE 4 +#define SCE_MMIXAL_OPCODE_VALID 5 +#define SCE_MMIXAL_OPCODE_UNKNOWN 6 +#define SCE_MMIXAL_OPCODE_POST 7 +#define SCE_MMIXAL_OPERANDS 8 +#define SCE_MMIXAL_NUMBER 9 +#define SCE_MMIXAL_REF 10 +#define SCE_MMIXAL_CHAR 11 +#define SCE_MMIXAL_STRING 12 +#define SCE_MMIXAL_REGISTER 13 +#define SCE_MMIXAL_HEX 14 +#define SCE_MMIXAL_OPERATOR 15 +#define SCE_MMIXAL_SYMBOL 16 +#define SCE_MMIXAL_INCLUDE 17 +#define SCE_CLW_DEFAULT 0 +#define SCE_CLW_LABEL 1 +#define SCE_CLW_COMMENT 2 +#define SCE_CLW_STRING 3 +#define SCE_CLW_USER_IDENTIFIER 4 +#define SCE_CLW_INTEGER_CONSTANT 5 +#define SCE_CLW_REAL_CONSTANT 6 +#define SCE_CLW_PICTURE_STRING 7 +#define SCE_CLW_KEYWORD 8 +#define SCE_CLW_COMPILER_DIRECTIVE 9 +#define SCE_CLW_RUNTIME_EXPRESSIONS 10 +#define SCE_CLW_BUILTIN_PROCEDURES_FUNCTION 11 +#define SCE_CLW_STRUCTURE_DATA_TYPE 12 +#define SCE_CLW_ATTRIBUTE 13 +#define SCE_CLW_STANDARD_EQUATE 14 +#define SCE_CLW_ERROR 15 +#define SCE_CLW_DEPRECATED 16 +#define SCE_LOT_DEFAULT 0 +#define SCE_LOT_HEADER 1 +#define SCE_LOT_BREAK 2 +#define SCE_LOT_SET 3 +#define SCE_LOT_PASS 4 +#define SCE_LOT_FAIL 5 +#define SCE_LOT_ABORT 6 +#define SCE_YAML_DEFAULT 0 +#define SCE_YAML_COMMENT 1 +#define SCE_YAML_IDENTIFIER 2 +#define SCE_YAML_KEYWORD 3 +#define SCE_YAML_NUMBER 4 +#define SCE_YAML_REFERENCE 5 +#define SCE_YAML_DOCUMENT 6 +#define SCE_YAML_TEXT 7 +#define SCE_YAML_ERROR 8 +#define SCE_YAML_OPERATOR 9 +#define SCE_TEX_DEFAULT 0 +#define SCE_TEX_SPECIAL 1 +#define SCE_TEX_GROUP 2 +#define SCE_TEX_SYMBOL 3 +#define SCE_TEX_COMMAND 4 +#define SCE_TEX_TEXT 5 +#define SCE_METAPOST_DEFAULT 0 +#define SCE_METAPOST_SPECIAL 1 +#define SCE_METAPOST_GROUP 2 +#define SCE_METAPOST_SYMBOL 3 +#define SCE_METAPOST_COMMAND 4 +#define SCE_METAPOST_TEXT 5 +#define SCE_METAPOST_EXTRA 6 +#define SCE_ERLANG_DEFAULT 0 +#define SCE_ERLANG_COMMENT 1 +#define SCE_ERLANG_VARIABLE 2 +#define SCE_ERLANG_NUMBER 3 +#define SCE_ERLANG_KEYWORD 4 +#define SCE_ERLANG_STRING 5 +#define SCE_ERLANG_OPERATOR 6 +#define SCE_ERLANG_ATOM 7 +#define SCE_ERLANG_FUNCTION_NAME 8 +#define SCE_ERLANG_CHARACTER 9 +#define SCE_ERLANG_MACRO 10 +#define SCE_ERLANG_RECORD 11 +#define SCE_ERLANG_PREPROC 12 +#define SCE_ERLANG_NODE_NAME 13 +#define SCE_ERLANG_COMMENT_FUNCTION 14 +#define SCE_ERLANG_COMMENT_MODULE 15 +#define SCE_ERLANG_COMMENT_DOC 16 +#define SCE_ERLANG_COMMENT_DOC_MACRO 17 +#define SCE_ERLANG_ATOM_QUOTED 18 +#define SCE_ERLANG_MACRO_QUOTED 19 +#define SCE_ERLANG_RECORD_QUOTED 20 +#define SCE_ERLANG_NODE_NAME_QUOTED 21 +#define SCE_ERLANG_BIFS 22 +#define SCE_ERLANG_MODULES 23 +#define SCE_ERLANG_MODULES_ATT 24 +#define SCE_ERLANG_UNKNOWN 31 +#define SCE_MSSQL_DEFAULT 0 +#define SCE_MSSQL_COMMENT 1 +#define SCE_MSSQL_LINE_COMMENT 2 +#define SCE_MSSQL_NUMBER 3 +#define SCE_MSSQL_STRING 4 +#define SCE_MSSQL_OPERATOR 5 +#define SCE_MSSQL_IDENTIFIER 6 +#define SCE_MSSQL_VARIABLE 7 +#define SCE_MSSQL_COLUMN_NAME 8 +#define SCE_MSSQL_STATEMENT 9 +#define SCE_MSSQL_DATATYPE 10 +#define SCE_MSSQL_SYSTABLE 11 +#define SCE_MSSQL_GLOBAL_VARIABLE 12 +#define SCE_MSSQL_FUNCTION 13 +#define SCE_MSSQL_STORED_PROCEDURE 14 +#define SCE_MSSQL_DEFAULT_PREF_DATATYPE 15 +#define SCE_MSSQL_COLUMN_NAME_2 16 +#define SCE_V_DEFAULT 0 +#define SCE_V_COMMENT 1 +#define SCE_V_COMMENTLINE 2 +#define SCE_V_COMMENTLINEBANG 3 +#define SCE_V_NUMBER 4 +#define SCE_V_WORD 5 +#define SCE_V_STRING 6 +#define SCE_V_WORD2 7 +#define SCE_V_WORD3 8 +#define SCE_V_PREPROCESSOR 9 +#define SCE_V_OPERATOR 10 +#define SCE_V_IDENTIFIER 11 +#define SCE_V_STRINGEOL 12 +#define SCE_V_USER 19 +#define SCE_KIX_DEFAULT 0 +#define SCE_KIX_COMMENT 1 +#define SCE_KIX_STRING1 2 +#define SCE_KIX_STRING2 3 +#define SCE_KIX_NUMBER 4 +#define SCE_KIX_VAR 5 +#define SCE_KIX_MACRO 6 +#define SCE_KIX_KEYWORD 7 +#define SCE_KIX_FUNCTIONS 8 +#define SCE_KIX_OPERATOR 9 +#define SCE_KIX_IDENTIFIER 31 +#define SCE_GC_DEFAULT 0 +#define SCE_GC_COMMENTLINE 1 +#define SCE_GC_COMMENTBLOCK 2 +#define SCE_GC_GLOBAL 3 +#define SCE_GC_EVENT 4 +#define SCE_GC_ATTRIBUTE 5 +#define SCE_GC_CONTROL 6 +#define SCE_GC_COMMAND 7 +#define SCE_GC_STRING 8 +#define SCE_GC_OPERATOR 9 +#define SCE_SN_DEFAULT 0 +#define SCE_SN_CODE 1 +#define SCE_SN_COMMENTLINE 2 +#define SCE_SN_COMMENTLINEBANG 3 +#define SCE_SN_NUMBER 4 +#define SCE_SN_WORD 5 +#define SCE_SN_STRING 6 +#define SCE_SN_WORD2 7 +#define SCE_SN_WORD3 8 +#define SCE_SN_PREPROCESSOR 9 +#define SCE_SN_OPERATOR 10 +#define SCE_SN_IDENTIFIER 11 +#define SCE_SN_STRINGEOL 12 +#define SCE_SN_REGEXTAG 13 +#define SCE_SN_SIGNAL 14 +#define SCE_SN_USER 19 +#define SCE_AU3_DEFAULT 0 +#define SCE_AU3_COMMENT 1 +#define SCE_AU3_COMMENTBLOCK 2 +#define SCE_AU3_NUMBER 3 +#define SCE_AU3_FUNCTION 4 +#define SCE_AU3_KEYWORD 5 +#define SCE_AU3_MACRO 6 +#define SCE_AU3_STRING 7 +#define SCE_AU3_OPERATOR 8 +#define SCE_AU3_VARIABLE 9 +#define SCE_AU3_SENT 10 +#define SCE_AU3_PREPROCESSOR 11 +#define SCE_AU3_SPECIAL 12 +#define SCE_AU3_EXPAND 13 +#define SCE_AU3_COMOBJ 14 +#define SCE_AU3_UDF 15 +#define SCE_APDL_DEFAULT 0 +#define SCE_APDL_COMMENT 1 +#define SCE_APDL_COMMENTBLOCK 2 +#define SCE_APDL_NUMBER 3 +#define SCE_APDL_STRING 4 +#define SCE_APDL_OPERATOR 5 +#define SCE_APDL_WORD 6 +#define SCE_APDL_PROCESSOR 7 +#define SCE_APDL_COMMAND 8 +#define SCE_APDL_SLASHCOMMAND 9 +#define SCE_APDL_STARCOMMAND 10 +#define SCE_APDL_ARGUMENT 11 +#define SCE_APDL_FUNCTION 12 +#define SCE_SH_DEFAULT 0 +#define SCE_SH_ERROR 1 +#define SCE_SH_COMMENTLINE 2 +#define SCE_SH_NUMBER 3 +#define SCE_SH_WORD 4 +#define SCE_SH_STRING 5 +#define SCE_SH_CHARACTER 6 +#define SCE_SH_OPERATOR 7 +#define SCE_SH_IDENTIFIER 8 +#define SCE_SH_SCALAR 9 +#define SCE_SH_PARAM 10 +#define SCE_SH_BACKTICKS 11 +#define SCE_SH_HERE_DELIM 12 +#define SCE_SH_HERE_Q 13 +#define SCE_ASN1_DEFAULT 0 +#define SCE_ASN1_COMMENT 1 +#define SCE_ASN1_IDENTIFIER 2 +#define SCE_ASN1_STRING 3 +#define SCE_ASN1_OID 4 +#define SCE_ASN1_SCALAR 5 +#define SCE_ASN1_KEYWORD 6 +#define SCE_ASN1_ATTRIBUTE 7 +#define SCE_ASN1_DESCRIPTOR 8 +#define SCE_ASN1_TYPE 9 +#define SCE_ASN1_OPERATOR 10 +#define SCE_VHDL_DEFAULT 0 +#define SCE_VHDL_COMMENT 1 +#define SCE_VHDL_COMMENTLINEBANG 2 +#define SCE_VHDL_NUMBER 3 +#define SCE_VHDL_STRING 4 +#define SCE_VHDL_OPERATOR 5 +#define SCE_VHDL_IDENTIFIER 6 +#define SCE_VHDL_STRINGEOL 7 +#define SCE_VHDL_KEYWORD 8 +#define SCE_VHDL_STDOPERATOR 9 +#define SCE_VHDL_ATTRIBUTE 10 +#define SCE_VHDL_STDFUNCTION 11 +#define SCE_VHDL_STDPACKAGE 12 +#define SCE_VHDL_STDTYPE 13 +#define SCE_VHDL_USERWORD 14 +#define SCE_CAML_DEFAULT 0 +#define SCE_CAML_IDENTIFIER 1 +#define SCE_CAML_TAGNAME 2 +#define SCE_CAML_KEYWORD 3 +#define SCE_CAML_KEYWORD2 4 +#define SCE_CAML_KEYWORD3 5 +#define SCE_CAML_LINENUM 6 +#define SCE_CAML_OPERATOR 7 +#define SCE_CAML_NUMBER 8 +#define SCE_CAML_CHAR 9 +#define SCE_CAML_WHITE 10 +#define SCE_CAML_STRING 11 +#define SCE_CAML_COMMENT 12 +#define SCE_CAML_COMMENT1 13 +#define SCE_CAML_COMMENT2 14 +#define SCE_CAML_COMMENT3 15 +#define SCE_HA_DEFAULT 0 +#define SCE_HA_IDENTIFIER 1 +#define SCE_HA_KEYWORD 2 +#define SCE_HA_NUMBER 3 +#define SCE_HA_STRING 4 +#define SCE_HA_CHARACTER 5 +#define SCE_HA_CLASS 6 +#define SCE_HA_MODULE 7 +#define SCE_HA_CAPITAL 8 +#define SCE_HA_DATA 9 +#define SCE_HA_IMPORT 10 +#define SCE_HA_OPERATOR 11 +#define SCE_HA_INSTANCE 12 +#define SCE_HA_COMMENTLINE 13 +#define SCE_HA_COMMENTBLOCK 14 +#define SCE_HA_COMMENTBLOCK2 15 +#define SCE_HA_COMMENTBLOCK3 16 +#define SCE_T3_DEFAULT 0 +#define SCE_T3_X_DEFAULT 1 +#define SCE_T3_PREPROCESSOR 2 +#define SCE_T3_BLOCK_COMMENT 3 +#define SCE_T3_LINE_COMMENT 4 +#define SCE_T3_OPERATOR 5 +#define SCE_T3_KEYWORD 6 +#define SCE_T3_NUMBER 7 +#define SCE_T3_IDENTIFIER 8 +#define SCE_T3_S_STRING 9 +#define SCE_T3_D_STRING 10 +#define SCE_T3_X_STRING 11 +#define SCE_T3_LIB_DIRECTIVE 12 +#define SCE_T3_MSG_PARAM 13 +#define SCE_T3_HTML_TAG 14 +#define SCE_T3_HTML_DEFAULT 15 +#define SCE_T3_HTML_STRING 16 +#define SCE_T3_USER1 17 +#define SCE_T3_USER2 18 +#define SCE_T3_USER3 19 +#define SCE_T3_BRACE 20 +#define SCE_REBOL_DEFAULT 0 +#define SCE_REBOL_COMMENTLINE 1 +#define SCE_REBOL_COMMENTBLOCK 2 +#define SCE_REBOL_PREFACE 3 +#define SCE_REBOL_OPERATOR 4 +#define SCE_REBOL_CHARACTER 5 +#define SCE_REBOL_QUOTEDSTRING 6 +#define SCE_REBOL_BRACEDSTRING 7 +#define SCE_REBOL_NUMBER 8 +#define SCE_REBOL_PAIR 9 +#define SCE_REBOL_TUPLE 10 +#define SCE_REBOL_BINARY 11 +#define SCE_REBOL_MONEY 12 +#define SCE_REBOL_ISSUE 13 +#define SCE_REBOL_TAG 14 +#define SCE_REBOL_FILE 15 +#define SCE_REBOL_EMAIL 16 +#define SCE_REBOL_URL 17 +#define SCE_REBOL_DATE 18 +#define SCE_REBOL_TIME 19 +#define SCE_REBOL_IDENTIFIER 20 +#define SCE_REBOL_WORD 21 +#define SCE_REBOL_WORD2 22 +#define SCE_REBOL_WORD3 23 +#define SCE_REBOL_WORD4 24 +#define SCE_REBOL_WORD5 25 +#define SCE_REBOL_WORD6 26 +#define SCE_REBOL_WORD7 27 +#define SCE_REBOL_WORD8 28 +#define SCE_SQL_DEFAULT 0 +#define SCE_SQL_COMMENT 1 +#define SCE_SQL_COMMENTLINE 2 +#define SCE_SQL_COMMENTDOC 3 +#define SCE_SQL_NUMBER 4 +#define SCE_SQL_WORD 5 +#define SCE_SQL_STRING 6 +#define SCE_SQL_CHARACTER 7 +#define SCE_SQL_SQLPLUS 8 +#define SCE_SQL_SQLPLUS_PROMPT 9 +#define SCE_SQL_OPERATOR 10 +#define SCE_SQL_IDENTIFIER 11 +#define SCE_SQL_SQLPLUS_COMMENT 13 +#define SCE_SQL_COMMENTLINEDOC 15 +#define SCE_SQL_WORD2 16 +#define SCE_SQL_COMMENTDOCKEYWORD 17 +#define SCE_SQL_COMMENTDOCKEYWORDERROR 18 +#define SCE_SQL_USER1 19 +#define SCE_SQL_USER2 20 +#define SCE_SQL_USER3 21 +#define SCE_SQL_USER4 22 +#define SCE_SQL_QUOTEDIDENTIFIER 23 +#define SCE_ST_DEFAULT 0 +#define SCE_ST_STRING 1 +#define SCE_ST_NUMBER 2 +#define SCE_ST_COMMENT 3 +#define SCE_ST_SYMBOL 4 +#define SCE_ST_BINARY 5 +#define SCE_ST_BOOL 6 +#define SCE_ST_SELF 7 +#define SCE_ST_SUPER 8 +#define SCE_ST_NIL 9 +#define SCE_ST_GLOBAL 10 +#define SCE_ST_RETURN 11 +#define SCE_ST_SPECIAL 12 +#define SCE_ST_KWSEND 13 +#define SCE_ST_ASSIGN 14 +#define SCE_ST_CHARACTER 15 +#define SCE_ST_SPEC_SEL 16 +#define SCE_FS_DEFAULT 0 +#define SCE_FS_COMMENT 1 +#define SCE_FS_COMMENTLINE 2 +#define SCE_FS_COMMENTDOC 3 +#define SCE_FS_COMMENTLINEDOC 4 +#define SCE_FS_COMMENTDOCKEYWORD 5 +#define SCE_FS_COMMENTDOCKEYWORDERROR 6 +#define SCE_FS_KEYWORD 7 +#define SCE_FS_KEYWORD2 8 +#define SCE_FS_KEYWORD3 9 +#define SCE_FS_KEYWORD4 10 +#define SCE_FS_NUMBER 11 +#define SCE_FS_STRING 12 +#define SCE_FS_PREPROCESSOR 13 +#define SCE_FS_OPERATOR 14 +#define SCE_FS_IDENTIFIER 15 +#define SCE_FS_DATE 16 +#define SCE_FS_STRINGEOL 17 +#define SCE_FS_CONSTANT 18 +#define SCE_FS_WORDOPERATOR 19 +#define SCE_FS_DISABLEDCODE 20 +#define SCE_FS_DEFAULT_C 21 +#define SCE_FS_COMMENTDOC_C 22 +#define SCE_FS_COMMENTLINEDOC_C 23 +#define SCE_FS_KEYWORD_C 24 +#define SCE_FS_KEYWORD2_C 25 +#define SCE_FS_NUMBER_C 26 +#define SCE_FS_STRING_C 27 +#define SCE_FS_PREPROCESSOR_C 28 +#define SCE_FS_OPERATOR_C 29 +#define SCE_FS_IDENTIFIER_C 30 +#define SCE_FS_STRINGEOL_C 31 +#define SCE_CSOUND_DEFAULT 0 +#define SCE_CSOUND_COMMENT 1 +#define SCE_CSOUND_NUMBER 2 +#define SCE_CSOUND_OPERATOR 3 +#define SCE_CSOUND_INSTR 4 +#define SCE_CSOUND_IDENTIFIER 5 +#define SCE_CSOUND_OPCODE 6 +#define SCE_CSOUND_HEADERSTMT 7 +#define SCE_CSOUND_USERKEYWORD 8 +#define SCE_CSOUND_COMMENTBLOCK 9 +#define SCE_CSOUND_PARAM 10 +#define SCE_CSOUND_ARATE_VAR 11 +#define SCE_CSOUND_KRATE_VAR 12 +#define SCE_CSOUND_IRATE_VAR 13 +#define SCE_CSOUND_GLOBAL_VAR 14 +#define SCE_CSOUND_STRINGEOL 15 +#define SCE_INNO_DEFAULT 0 +#define SCE_INNO_COMMENT 1 +#define SCE_INNO_KEYWORD 2 +#define SCE_INNO_PARAMETER 3 +#define SCE_INNO_SECTION 4 +#define SCE_INNO_PREPROC 5 +#define SCE_INNO_INLINE_EXPANSION 6 +#define SCE_INNO_COMMENT_PASCAL 7 +#define SCE_INNO_KEYWORD_PASCAL 8 +#define SCE_INNO_KEYWORD_USER 9 +#define SCE_INNO_STRING_DOUBLE 10 +#define SCE_INNO_STRING_SINGLE 11 +#define SCE_INNO_IDENTIFIER 12 +#define SCE_OPAL_SPACE 0 +#define SCE_OPAL_COMMENT_BLOCK 1 +#define SCE_OPAL_COMMENT_LINE 2 +#define SCE_OPAL_INTEGER 3 +#define SCE_OPAL_KEYWORD 4 +#define SCE_OPAL_SORT 5 +#define SCE_OPAL_STRING 6 +#define SCE_OPAL_PAR 7 +#define SCE_OPAL_BOOL_CONST 8 +#define SCE_OPAL_DEFAULT 32 +#define SCE_SPICE_DEFAULT 0 +#define SCE_SPICE_IDENTIFIER 1 +#define SCE_SPICE_KEYWORD 2 +#define SCE_SPICE_KEYWORD2 3 +#define SCE_SPICE_KEYWORD3 4 +#define SCE_SPICE_NUMBER 5 +#define SCE_SPICE_DELIMITER 6 +#define SCE_SPICE_VALUE 7 +#define SCE_SPICE_COMMENTLINE 8 +#define SCE_CMAKE_DEFAULT 0 +#define SCE_CMAKE_COMMENT 1 +#define SCE_CMAKE_STRINGDQ 2 +#define SCE_CMAKE_STRINGLQ 3 +#define SCE_CMAKE_STRINGRQ 4 +#define SCE_CMAKE_COMMANDS 5 +#define SCE_CMAKE_PARAMETERS 6 +#define SCE_CMAKE_VARIABLE 7 +#define SCE_CMAKE_USERDEFINED 8 +#define SCE_CMAKE_WHILEDEF 9 +#define SCE_CMAKE_FOREACHDEF 10 +#define SCE_CMAKE_IFDEFINEDEF 11 +#define SCE_CMAKE_MACRODEF 12 +#define SCE_CMAKE_STRINGVAR 13 +#define SCE_CMAKE_NUMBER 14 +#define SCE_GAP_DEFAULT 0 +#define SCE_GAP_IDENTIFIER 1 +#define SCE_GAP_KEYWORD 2 +#define SCE_GAP_KEYWORD2 3 +#define SCE_GAP_KEYWORD3 4 +#define SCE_GAP_KEYWORD4 5 +#define SCE_GAP_STRING 6 +#define SCE_GAP_CHAR 7 +#define SCE_GAP_OPERATOR 8 +#define SCE_GAP_COMMENT 9 +#define SCE_GAP_NUMBER 10 +#define SCE_GAP_STRINGEOL 11 +#define SCE_PLM_DEFAULT 0 +#define SCE_PLM_COMMENT 1 +#define SCE_PLM_STRING 2 +#define SCE_PLM_NUMBER 3 +#define SCE_PLM_IDENTIFIER 4 +#define SCE_PLM_OPERATOR 5 +#define SCE_PLM_CONTROL 6 +#define SCE_PLM_KEYWORD 7 +#define SCE_4GL_DEFAULT 0 +#define SCE_4GL_NUMBER 1 +#define SCE_4GL_WORD 2 +#define SCE_4GL_STRING 3 +#define SCE_4GL_CHARACTER 4 +#define SCE_4GL_PREPROCESSOR 5 +#define SCE_4GL_OPERATOR 6 +#define SCE_4GL_IDENTIFIER 7 +#define SCE_4GL_BLOCK 8 +#define SCE_4GL_END 9 +#define SCE_4GL_COMMENT1 10 +#define SCE_4GL_COMMENT2 11 +#define SCE_4GL_COMMENT3 12 +#define SCE_4GL_COMMENT4 13 +#define SCE_4GL_COMMENT5 14 +#define SCE_4GL_COMMENT6 15 +#define SCE_4GL_DEFAULT_ 16 +#define SCE_4GL_NUMBER_ 17 +#define SCE_4GL_WORD_ 18 +#define SCE_4GL_STRING_ 19 +#define SCE_4GL_CHARACTER_ 20 +#define SCE_4GL_PREPROCESSOR_ 21 +#define SCE_4GL_OPERATOR_ 22 +#define SCE_4GL_IDENTIFIER_ 23 +#define SCE_4GL_BLOCK_ 24 +#define SCE_4GL_END_ 25 +#define SCE_4GL_COMMENT1_ 26 +#define SCE_4GL_COMMENT2_ 27 +#define SCE_4GL_COMMENT3_ 28 +#define SCE_4GL_COMMENT4_ 29 +#define SCE_4GL_COMMENT5_ 30 +#define SCE_4GL_COMMENT6_ 31 +#define SCE_ABAQUS_DEFAULT 0 +#define SCE_ABAQUS_COMMENT 1 +#define SCE_ABAQUS_COMMENTBLOCK 2 +#define SCE_ABAQUS_NUMBER 3 +#define SCE_ABAQUS_STRING 4 +#define SCE_ABAQUS_OPERATOR 5 +#define SCE_ABAQUS_WORD 6 +#define SCE_ABAQUS_PROCESSOR 7 +#define SCE_ABAQUS_COMMAND 8 +#define SCE_ABAQUS_SLASHCOMMAND 9 +#define SCE_ABAQUS_STARCOMMAND 10 +#define SCE_ABAQUS_ARGUMENT 11 +#define SCE_ABAQUS_FUNCTION 12 +#define SCE_ASY_DEFAULT 0 +#define SCE_ASY_COMMENT 1 +#define SCE_ASY_COMMENTLINE 2 +#define SCE_ASY_NUMBER 3 +#define SCE_ASY_WORD 4 +#define SCE_ASY_STRING 5 +#define SCE_ASY_CHARACTER 6 +#define SCE_ASY_OPERATOR 7 +#define SCE_ASY_IDENTIFIER 8 +#define SCE_ASY_STRINGEOL 9 +#define SCE_ASY_COMMENTLINEDOC 10 +#define SCE_ASY_WORD2 11 +#define SCE_R_DEFAULT 0 +#define SCE_R_COMMENT 1 +#define SCE_R_KWORD 2 +#define SCE_R_BASEKWORD 3 +#define SCE_R_OTHERKWORD 4 +#define SCE_R_NUMBER 5 +#define SCE_R_STRING 6 +#define SCE_R_STRING2 7 +#define SCE_R_OPERATOR 8 +#define SCE_R_IDENTIFIER 9 +#define SCE_R_INFIX 10 +#define SCE_R_INFIXEOL 11 +#define SCE_MAGIK_DEFAULT 0 +#define SCE_MAGIK_COMMENT 1 +#define SCE_MAGIK_HYPER_COMMENT 16 +#define SCE_MAGIK_STRING 2 +#define SCE_MAGIK_CHARACTER 3 +#define SCE_MAGIK_NUMBER 4 +#define SCE_MAGIK_IDENTIFIER 5 +#define SCE_MAGIK_OPERATOR 6 +#define SCE_MAGIK_FLOW 7 +#define SCE_MAGIK_CONTAINER 8 +#define SCE_MAGIK_BRACKET_BLOCK 9 +#define SCE_MAGIK_BRACE_BLOCK 10 +#define SCE_MAGIK_SQBRACKET_BLOCK 11 +#define SCE_MAGIK_UNKNOWN_KEYWORD 12 +#define SCE_MAGIK_KEYWORD 13 +#define SCE_MAGIK_PRAGMA 14 +#define SCE_MAGIK_SYMBOL 15 +#define SCE_POWERSHELL_DEFAULT 0 +#define SCE_POWERSHELL_COMMENT 1 +#define SCE_POWERSHELL_STRING 2 +#define SCE_POWERSHELL_CHARACTER 3 +#define SCE_POWERSHELL_NUMBER 4 +#define SCE_POWERSHELL_VARIABLE 5 +#define SCE_POWERSHELL_OPERATOR 6 +#define SCE_POWERSHELL_IDENTIFIER 7 +#define SCE_POWERSHELL_KEYWORD 8 +#define SCE_POWERSHELL_CMDLET 9 +#define SCE_POWERSHELL_ALIAS 10 +#define SCE_POWERSHELL_FUNCTION 11 +#define SCE_POWERSHELL_USER1 12 +#define SCE_POWERSHELL_COMMENTSTREAM 13 +#define SCE_MYSQL_DEFAULT 0 +#define SCE_MYSQL_COMMENT 1 +#define SCE_MYSQL_COMMENTLINE 2 +#define SCE_MYSQL_VARIABLE 3 +#define SCE_MYSQL_SYSTEMVARIABLE 4 +#define SCE_MYSQL_KNOWNSYSTEMVARIABLE 5 +#define SCE_MYSQL_NUMBER 6 +#define SCE_MYSQL_MAJORKEYWORD 7 +#define SCE_MYSQL_KEYWORD 8 +#define SCE_MYSQL_DATABASEOBJECT 9 +#define SCE_MYSQL_PROCEDUREKEYWORD 10 +#define SCE_MYSQL_STRING 11 +#define SCE_MYSQL_SQSTRING 12 +#define SCE_MYSQL_DQSTRING 13 +#define SCE_MYSQL_OPERATOR 14 +#define SCE_MYSQL_FUNCTION 15 +#define SCE_MYSQL_IDENTIFIER 16 +#define SCE_MYSQL_QUOTEDIDENTIFIER 17 +#define SCE_MYSQL_USER1 18 +#define SCE_MYSQL_USER2 19 +#define SCE_MYSQL_USER3 20 +#define SCE_MYSQL_HIDDENCOMMAND 21 +#define SCE_PO_DEFAULT 0 +#define SCE_PO_COMMENT 1 +#define SCE_PO_MSGID 2 +#define SCE_PO_MSGID_TEXT 3 +#define SCE_PO_MSGSTR 4 +#define SCE_PO_MSGSTR_TEXT 5 +#define SCE_PO_MSGCTXT 6 +#define SCE_PO_MSGCTXT_TEXT 7 +#define SCE_PO_FUZZY 8 +#define SCE_PAS_DEFAULT 0 +#define SCE_PAS_IDENTIFIER 1 +#define SCE_PAS_COMMENT 2 +#define SCE_PAS_COMMENT2 3 +#define SCE_PAS_COMMENTLINE 4 +#define SCE_PAS_PREPROCESSOR 5 +#define SCE_PAS_PREPROCESSOR2 6 +#define SCE_PAS_NUMBER 7 +#define SCE_PAS_HEXNUMBER 8 +#define SCE_PAS_WORD 9 +#define SCE_PAS_STRING 10 +#define SCE_PAS_STRINGEOL 11 +#define SCE_PAS_CHARACTER 12 +#define SCE_PAS_OPERATOR 13 +#define SCE_PAS_ASM 14 +#define SCE_SORCUS_DEFAULT 0 +#define SCE_SORCUS_COMMAND 1 +#define SCE_SORCUS_PARAMETER 2 +#define SCE_SORCUS_COMMENTLINE 3 +#define SCE_SORCUS_STRING 4 +#define SCE_SORCUS_STRINGEOL 5 +#define SCE_SORCUS_IDENTIFIER 6 +#define SCE_SORCUS_OPERATOR 7 +#define SCE_SORCUS_NUMBER 8 +#define SCE_SORCUS_CONSTANT 9 +#define SCE_POWERPRO_DEFAULT 0 +#define SCE_POWERPRO_COMMENTBLOCK 1 +#define SCE_POWERPRO_COMMENTLINE 2 +#define SCE_POWERPRO_NUMBER 3 +#define SCE_POWERPRO_WORD 4 +#define SCE_POWERPRO_WORD2 5 +#define SCE_POWERPRO_WORD3 6 +#define SCE_POWERPRO_WORD4 7 +#define SCE_POWERPRO_DOUBLEQUOTEDSTRING 8 +#define SCE_POWERPRO_SINGLEQUOTEDSTRING 9 +#define SCE_POWERPRO_LINECONTINUE 10 +#define SCE_POWERPRO_OPERATOR 11 +#define SCE_POWERPRO_IDENTIFIER 12 +#define SCE_POWERPRO_STRINGEOL 13 +#define SCE_POWERPRO_VERBATIM 14 +#define SCE_POWERPRO_ALTQUOTE 15 +#define SCE_POWERPRO_FUNCTION 16 +#define SCE_SML_DEFAULT 0 +#define SCE_SML_IDENTIFIER 1 +#define SCE_SML_TAGNAME 2 +#define SCE_SML_KEYWORD 3 +#define SCE_SML_KEYWORD2 4 +#define SCE_SML_KEYWORD3 5 +#define SCE_SML_LINENUM 6 +#define SCE_SML_OPERATOR 7 +#define SCE_SML_NUMBER 8 +#define SCE_SML_CHAR 9 +#define SCE_SML_STRING 11 +#define SCE_SML_COMMENT 12 +#define SCE_SML_COMMENT1 13 +#define SCE_SML_COMMENT2 14 +#define SCE_SML_COMMENT3 15 +#define SCE_MARKDOWN_DEFAULT 0 +#define SCE_MARKDOWN_LINE_BEGIN 1 +#define SCE_MARKDOWN_STRONG1 2 +#define SCE_MARKDOWN_STRONG2 3 +#define SCE_MARKDOWN_EM1 4 +#define SCE_MARKDOWN_EM2 5 +#define SCE_MARKDOWN_HEADER1 6 +#define SCE_MARKDOWN_HEADER2 7 +#define SCE_MARKDOWN_HEADER3 8 +#define SCE_MARKDOWN_HEADER4 9 +#define SCE_MARKDOWN_HEADER5 10 +#define SCE_MARKDOWN_HEADER6 11 +#define SCE_MARKDOWN_PRECHAR 12 +#define SCE_MARKDOWN_ULIST_ITEM 13 +#define SCE_MARKDOWN_OLIST_ITEM 14 +#define SCE_MARKDOWN_BLOCKQUOTE 15 +#define SCE_MARKDOWN_STRIKEOUT 16 +#define SCE_MARKDOWN_HRULE 17 +#define SCE_MARKDOWN_LINK 18 +#define SCE_MARKDOWN_CODE 19 +#define SCE_MARKDOWN_CODE2 20 +#define SCE_MARKDOWN_CODEBK 21 +#define SCE_TXT2TAGS_DEFAULT 0 +#define SCE_TXT2TAGS_LINE_BEGIN 1 +#define SCE_TXT2TAGS_STRONG1 2 +#define SCE_TXT2TAGS_STRONG2 3 +#define SCE_TXT2TAGS_EM1 4 +#define SCE_TXT2TAGS_EM2 5 +#define SCE_TXT2TAGS_HEADER1 6 +#define SCE_TXT2TAGS_HEADER2 7 +#define SCE_TXT2TAGS_HEADER3 8 +#define SCE_TXT2TAGS_HEADER4 9 +#define SCE_TXT2TAGS_HEADER5 10 +#define SCE_TXT2TAGS_HEADER6 11 +#define SCE_TXT2TAGS_PRECHAR 12 +#define SCE_TXT2TAGS_ULIST_ITEM 13 +#define SCE_TXT2TAGS_OLIST_ITEM 14 +#define SCE_TXT2TAGS_BLOCKQUOTE 15 +#define SCE_TXT2TAGS_STRIKEOUT 16 +#define SCE_TXT2TAGS_HRULE 17 +#define SCE_TXT2TAGS_LINK 18 +#define SCE_TXT2TAGS_CODE 19 +#define SCE_TXT2TAGS_CODE2 20 +#define SCE_TXT2TAGS_CODEBK 21 +#define SCE_TXT2TAGS_COMMENT 22 +#define SCE_TXT2TAGS_OPTION 23 +#define SCE_TXT2TAGS_PREPROC 24 +#define SCE_TXT2TAGS_POSTPROC 25 +#define SCE_A68K_DEFAULT 0 +#define SCE_A68K_COMMENT 1 +#define SCE_A68K_NUMBER_DEC 2 +#define SCE_A68K_NUMBER_BIN 3 +#define SCE_A68K_NUMBER_HEX 4 +#define SCE_A68K_STRING1 5 +#define SCE_A68K_OPERATOR 6 +#define SCE_A68K_CPUINSTRUCTION 7 +#define SCE_A68K_EXTINSTRUCTION 8 +#define SCE_A68K_REGISTER 9 +#define SCE_A68K_DIRECTIVE 10 +#define SCE_A68K_MACRO_ARG 11 +#define SCE_A68K_LABEL 12 +#define SCE_A68K_STRING2 13 +#define SCE_A68K_IDENTIFIER 14 +#define SCE_A68K_MACRO_DECLARATION 15 +#define SCE_A68K_COMMENT_WORD 16 +#define SCE_A68K_COMMENT_SPECIAL 17 +#define SCE_A68K_COMMENT_DOXYGEN 18 +#define SCE_MODULA_DEFAULT 0 +#define SCE_MODULA_COMMENT 1 +#define SCE_MODULA_DOXYCOMM 2 +#define SCE_MODULA_DOXYKEY 3 +#define SCE_MODULA_KEYWORD 4 +#define SCE_MODULA_RESERVED 5 +#define SCE_MODULA_NUMBER 6 +#define SCE_MODULA_BASENUM 7 +#define SCE_MODULA_FLOAT 8 +#define SCE_MODULA_STRING 9 +#define SCE_MODULA_STRSPEC 10 +#define SCE_MODULA_CHAR 11 +#define SCE_MODULA_CHARSPEC 12 +#define SCE_MODULA_PROC 13 +#define SCE_MODULA_PRAGMA 14 +#define SCE_MODULA_PRGKEY 15 +#define SCE_MODULA_OPERATOR 16 +#define SCE_MODULA_BADSTR 17 +#define SCE_COFFEESCRIPT_DEFAULT 0 +#define SCE_COFFEESCRIPT_COMMENT 1 +#define SCE_COFFEESCRIPT_COMMENTLINE 2 +#define SCE_COFFEESCRIPT_COMMENTDOC 3 +#define SCE_COFFEESCRIPT_NUMBER 4 +#define SCE_COFFEESCRIPT_WORD 5 +#define SCE_COFFEESCRIPT_STRING 6 +#define SCE_COFFEESCRIPT_CHARACTER 7 +#define SCE_COFFEESCRIPT_UUID 8 +#define SCE_COFFEESCRIPT_PREPROCESSOR 9 +#define SCE_COFFEESCRIPT_OPERATOR 10 +#define SCE_COFFEESCRIPT_IDENTIFIER 11 +#define SCE_COFFEESCRIPT_STRINGEOL 12 +#define SCE_COFFEESCRIPT_VERBATIM 13 +#define SCE_COFFEESCRIPT_REGEX 14 +#define SCE_COFFEESCRIPT_COMMENTLINEDOC 15 +#define SCE_COFFEESCRIPT_WORD2 16 +#define SCE_COFFEESCRIPT_COMMENTDOCKEYWORD 17 +#define SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR 18 +#define SCE_COFFEESCRIPT_GLOBALCLASS 19 +#define SCE_COFFEESCRIPT_STRINGRAW 20 +#define SCE_COFFEESCRIPT_TRIPLEVERBATIM 21 +#define SCE_COFFEESCRIPT_HASHQUOTEDSTRING 22 +#define SCE_COFFEESCRIPT_COMMENTBLOCK 22 +#define SCE_COFFEESCRIPT_VERBOSE_REGEX 23 +#define SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT 24 +#define SCE_AVS_DEFAULT 0 +#define SCE_AVS_COMMENTBLOCK 1 +#define SCE_AVS_COMMENTBLOCKN 2 +#define SCE_AVS_COMMENTLINE 3 +#define SCE_AVS_NUMBER 4 +#define SCE_AVS_OPERATOR 5 +#define SCE_AVS_IDENTIFIER 6 +#define SCE_AVS_STRING 7 +#define SCE_AVS_TRIPLESTRING 8 +#define SCE_AVS_KEYWORD 9 +#define SCE_AVS_FILTER 10 +#define SCE_AVS_PLUGIN 11 +#define SCE_AVS_FUNCTION 12 +#define SCE_AVS_CLIPPROP 13 +#define SCE_AVS_USERDFN 14 +/* --Autogenerated -- end of section automatically generated from Scintilla.iface */ + +#endif diff --git a/scintilla/include/Scintilla.h b/ThirdLibs/scintilla/include/Scintilla.h similarity index 96% rename from scintilla/include/Scintilla.h rename to ThirdLibs/scintilla/include/Scintilla.h index 13302500..7a6f58fa 100644 --- a/scintilla/include/Scintilla.h +++ b/ThirdLibs/scintilla/include/Scintilla.h @@ -1,1050 +1,1050 @@ -/* Scintilla source code edit control */ -/** @file Scintilla.h - ** Interface to the edit control. - **/ -/* Copyright 1998-2003 by Neil Hodgson - * The License.txt file describes the conditions under which this software may be distributed. */ - -/* Most of this file is automatically generated from the Scintilla.iface interface definition - * file which contains any comments about the definitions. HFacer.py does the generation. */ - -#ifndef SCINTILLA_H -#define SCINTILLA_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(_WIN32) -/* Return false on failure: */ -int Scintilla_RegisterClasses(void *hInstance); -int Scintilla_ReleaseResources(); -#endif -int Scintilla_LinkLexers(); - -#ifdef __cplusplus -} -#endif - -/* Here should be placed typedefs for uptr_t, an unsigned integer type large enough to - * hold a pointer and sptr_t, a signed integer large enough to hold a pointer. - * May need to be changed for 64 bit platforms. */ -#if defined(_WIN32) -#include -#endif -#ifdef MAXULONG_PTR -typedef ULONG_PTR uptr_t; -typedef LONG_PTR sptr_t; -#else -typedef unsigned long uptr_t; -typedef long sptr_t; -#endif - -typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, sptr_t lParam); - -/* ++Autogenerated -- start of section automatically generated from Scintilla.iface */ -#define INVALID_POSITION -1 -#define SCI_START 2000 -#define SCI_OPTIONAL_START 3000 -#define SCI_LEXER_START 4000 -#define SCI_ADDTEXT 2001 -#define SCI_ADDSTYLEDTEXT 2002 -#define SCI_INSERTTEXT 2003 -#define SCI_CLEARALL 2004 -#define SCI_CLEARDOCUMENTSTYLE 2005 -#define SCI_GETLENGTH 2006 -#define SCI_GETCHARAT 2007 -#define SCI_GETCURRENTPOS 2008 -#define SCI_GETANCHOR 2009 -#define SCI_GETSTYLEAT 2010 -#define SCI_REDO 2011 -#define SCI_SETUNDOCOLLECTION 2012 -#define SCI_SELECTALL 2013 -#define SCI_SETSAVEPOINT 2014 -#define SCI_GETSTYLEDTEXT 2015 -#define SCI_CANREDO 2016 -#define SCI_MARKERLINEFROMHANDLE 2017 -#define SCI_MARKERDELETEHANDLE 2018 -#define SCI_GETUNDOCOLLECTION 2019 -#define SCWS_INVISIBLE 0 -#define SCWS_VISIBLEALWAYS 1 -#define SCWS_VISIBLEAFTERINDENT 2 -#define SCI_GETVIEWWS 2020 -#define SCI_SETVIEWWS 2021 -#define SCI_POSITIONFROMPOINT 2022 -#define SCI_POSITIONFROMPOINTCLOSE 2023 -#define SCI_GOTOLINE 2024 -#define SCI_GOTOPOS 2025 -#define SCI_SETANCHOR 2026 -#define SCI_GETCURLINE 2027 -#define SCI_GETENDSTYLED 2028 -#define SC_EOL_CRLF 0 -#define SC_EOL_CR 1 -#define SC_EOL_LF 2 -#define SCI_CONVERTEOLS 2029 -#define SCI_GETEOLMODE 2030 -#define SCI_SETEOLMODE 2031 -#define SCI_STARTSTYLING 2032 -#define SCI_SETSTYLING 2033 -#define SCI_GETBUFFEREDDRAW 2034 -#define SCI_SETBUFFEREDDRAW 2035 -#define SCI_SETTABWIDTH 2036 -#define SCI_GETTABWIDTH 2121 -#define SC_CP_UTF8 65001 -#define SCI_SETCODEPAGE 2037 -#define MARKER_MAX 31 -#define SC_MARK_CIRCLE 0 -#define SC_MARK_ROUNDRECT 1 -#define SC_MARK_ARROW 2 -#define SC_MARK_SMALLRECT 3 -#define SC_MARK_SHORTARROW 4 -#define SC_MARK_EMPTY 5 -#define SC_MARK_ARROWDOWN 6 -#define SC_MARK_MINUS 7 -#define SC_MARK_PLUS 8 -#define SC_MARK_VLINE 9 -#define SC_MARK_LCORNER 10 -#define SC_MARK_TCORNER 11 -#define SC_MARK_BOXPLUS 12 -#define SC_MARK_BOXPLUSCONNECTED 13 -#define SC_MARK_BOXMINUS 14 -#define SC_MARK_BOXMINUSCONNECTED 15 -#define SC_MARK_LCORNERCURVE 16 -#define SC_MARK_TCORNERCURVE 17 -#define SC_MARK_CIRCLEPLUS 18 -#define SC_MARK_CIRCLEPLUSCONNECTED 19 -#define SC_MARK_CIRCLEMINUS 20 -#define SC_MARK_CIRCLEMINUSCONNECTED 21 -#define SC_MARK_BACKGROUND 22 -#define SC_MARK_DOTDOTDOT 23 -#define SC_MARK_ARROWS 24 -#define SC_MARK_PIXMAP 25 -#define SC_MARK_FULLRECT 26 -#define SC_MARK_LEFTRECT 27 -#define SC_MARK_AVAILABLE 28 -#define SC_MARK_UNDERLINE 29 -#define SC_MARK_RGBAIMAGE 30 -#define SC_MARK_CHARACTER 10000 -#define SC_MARKNUM_FOLDEREND 25 -#define SC_MARKNUM_FOLDEROPENMID 26 -#define SC_MARKNUM_FOLDERMIDTAIL 27 -#define SC_MARKNUM_FOLDERTAIL 28 -#define SC_MARKNUM_FOLDERSUB 29 -#define SC_MARKNUM_FOLDER 30 -#define SC_MARKNUM_FOLDEROPEN 31 -#define SC_MASK_FOLDERS 0xFE000000 -#define SCI_MARKERDEFINE 2040 -#define SCI_MARKERSETFORE 2041 -#define SCI_MARKERSETBACK 2042 -#define SCI_MARKERSETBACKSELECTED 2292 -#define SCI_MARKERENABLEHIGHLIGHT 2293 -#define SCI_MARKERADD 2043 -#define SCI_MARKERDELETE 2044 -#define SCI_MARKERDELETEALL 2045 -#define SCI_MARKERGET 2046 -#define SCI_MARKERNEXT 2047 -#define SCI_MARKERPREVIOUS 2048 -#define SCI_MARKERDEFINEPIXMAP 2049 -#define SCI_MARKERADDSET 2466 -#define SCI_MARKERSETALPHA 2476 -#define SC_MARGIN_SYMBOL 0 -#define SC_MARGIN_NUMBER 1 -#define SC_MARGIN_BACK 2 -#define SC_MARGIN_FORE 3 -#define SC_MARGIN_TEXT 4 -#define SC_MARGIN_RTEXT 5 -#define SCI_SETMARGINTYPEN 2240 -#define SCI_GETMARGINTYPEN 2241 -#define SCI_SETMARGINWIDTHN 2242 -#define SCI_GETMARGINWIDTHN 2243 -#define SCI_SETMARGINMASKN 2244 -#define SCI_GETMARGINMASKN 2245 -#define SCI_SETMARGINSENSITIVEN 2246 -#define SCI_GETMARGINSENSITIVEN 2247 -#define SCI_SETMARGINCURSORN 2248 -#define SCI_GETMARGINCURSORN 2249 -#define STYLE_DEFAULT 32 -#define STYLE_LINENUMBER 33 -#define STYLE_BRACELIGHT 34 -#define STYLE_BRACEBAD 35 -#define STYLE_CONTROLCHAR 36 -#define STYLE_INDENTGUIDE 37 -#define STYLE_CALLTIP 38 -#define STYLE_LASTPREDEFINED 39 -#define STYLE_MAX 255 -#define SC_CHARSET_ANSI 0 -#define SC_CHARSET_DEFAULT 1 -#define SC_CHARSET_BALTIC 186 -#define SC_CHARSET_CHINESEBIG5 136 -#define SC_CHARSET_EASTEUROPE 238 -#define SC_CHARSET_GB2312 134 -#define SC_CHARSET_GREEK 161 -#define SC_CHARSET_HANGUL 129 -#define SC_CHARSET_MAC 77 -#define SC_CHARSET_OEM 255 -#define SC_CHARSET_RUSSIAN 204 -#define SC_CHARSET_CYRILLIC 1251 -#define SC_CHARSET_SHIFTJIS 128 -#define SC_CHARSET_SYMBOL 2 -#define SC_CHARSET_TURKISH 162 -#define SC_CHARSET_JOHAB 130 -#define SC_CHARSET_HEBREW 177 -#define SC_CHARSET_ARABIC 178 -#define SC_CHARSET_VIETNAMESE 163 -#define SC_CHARSET_THAI 222 -#define SC_CHARSET_8859_15 1000 -#define SCI_STYLECLEARALL 2050 -#define SCI_STYLESETFORE 2051 -#define SCI_STYLESETBACK 2052 -#define SCI_STYLESETBOLD 2053 -#define SCI_STYLESETITALIC 2054 -#define SCI_STYLESETSIZE 2055 -#define SCI_STYLESETFONT 2056 -#define SCI_STYLESETEOLFILLED 2057 -#define SCI_STYLERESETDEFAULT 2058 -#define SCI_STYLESETUNDERLINE 2059 -#define SC_CASE_MIXED 0 -#define SC_CASE_UPPER 1 -#define SC_CASE_LOWER 2 -#define SCI_STYLEGETFORE 2481 -#define SCI_STYLEGETBACK 2482 -#define SCI_STYLEGETBOLD 2483 -#define SCI_STYLEGETITALIC 2484 -#define SCI_STYLEGETSIZE 2485 -#define SCI_STYLEGETFONT 2486 -#define SCI_STYLEGETEOLFILLED 2487 -#define SCI_STYLEGETUNDERLINE 2488 -#define SCI_STYLEGETCASE 2489 -#define SCI_STYLEGETCHARACTERSET 2490 -#define SCI_STYLEGETVISIBLE 2491 -#define SCI_STYLEGETCHANGEABLE 2492 -#define SCI_STYLEGETHOTSPOT 2493 -#define SCI_STYLESETCASE 2060 -#define SC_FONT_SIZE_MULTIPLIER 100 -#define SCI_STYLESETSIZEFRACTIONAL 2061 -#define SCI_STYLEGETSIZEFRACTIONAL 2062 -#define SC_WEIGHT_NORMAL 400 -#define SC_WEIGHT_SEMIBOLD 600 -#define SC_WEIGHT_BOLD 700 -#define SCI_STYLESETWEIGHT 2063 -#define SCI_STYLEGETWEIGHT 2064 -#define SCI_STYLESETCHARACTERSET 2066 -#define SCI_STYLESETHOTSPOT 2409 -#define SCI_SETSELFORE 2067 -#define SCI_SETSELBACK 2068 -#define SCI_GETSELALPHA 2477 -#define SCI_SETSELALPHA 2478 -#define SCI_GETSELEOLFILLED 2479 -#define SCI_SETSELEOLFILLED 2480 -#define SCI_SETCARETFORE 2069 -#define SCI_ASSIGNCMDKEY 2070 -#define SCI_CLEARCMDKEY 2071 -#define SCI_CLEARALLCMDKEYS 2072 -#define SCI_SETSTYLINGEX 2073 -#define SCI_STYLESETVISIBLE 2074 -#define SCI_GETCARETPERIOD 2075 -#define SCI_SETCARETPERIOD 2076 -#define SCI_SETWORDCHARS 2077 -#define SCI_BEGINUNDOACTION 2078 -#define SCI_ENDUNDOACTION 2079 -#define INDIC_PLAIN 0 -#define INDIC_SQUIGGLE 1 -#define INDIC_TT 2 -#define INDIC_DIAGONAL 3 -#define INDIC_STRIKE 4 -#define INDIC_HIDDEN 5 -#define INDIC_BOX 6 -#define INDIC_ROUNDBOX 7 -#define INDIC_STRAIGHTBOX 8 -#define INDIC_DASH 9 -#define INDIC_DOTS 10 -#define INDIC_SQUIGGLELOW 11 -#define INDIC_DOTBOX 12 -#define INDIC_MAX 31 -#define INDIC_CONTAINER 8 -#define INDIC0_MASK 0x20 -#define INDIC1_MASK 0x40 -#define INDIC2_MASK 0x80 -#define INDICS_MASK 0xE0 -#define SCI_INDICSETSTYLE 2080 -#define SCI_INDICGETSTYLE 2081 -#define SCI_INDICSETFORE 2082 -#define SCI_INDICGETFORE 2083 -#define SCI_INDICSETUNDER 2510 -#define SCI_INDICGETUNDER 2511 -#define SCI_SETWHITESPACEFORE 2084 -#define SCI_SETWHITESPACEBACK 2085 -#define SCI_SETWHITESPACESIZE 2086 -#define SCI_GETWHITESPACESIZE 2087 -#define SCI_SETSTYLEBITS 2090 -#define SCI_GETSTYLEBITS 2091 -#define SCI_SETLINESTATE 2092 -#define SCI_GETLINESTATE 2093 -#define SCI_GETMAXLINESTATE 2094 -#define SCI_GETCARETLINEVISIBLE 2095 -#define SCI_SETCARETLINEVISIBLE 2096 -#define SCI_GETCARETLINEBACK 2097 -#define SCI_SETCARETLINEBACK 2098 -#define SCI_STYLESETCHANGEABLE 2099 -#define SCI_AUTOCSHOW 2100 -#define SCI_AUTOCCANCEL 2101 -#define SCI_AUTOCACTIVE 2102 -#define SCI_AUTOCPOSSTART 2103 -#define SCI_AUTOCCOMPLETE 2104 -#define SCI_AUTOCSTOPS 2105 -#define SCI_AUTOCSETSEPARATOR 2106 -#define SCI_AUTOCGETSEPARATOR 2107 -#define SCI_AUTOCSELECT 2108 -#define SCI_AUTOCSETCANCELATSTART 2110 -#define SCI_AUTOCGETCANCELATSTART 2111 -#define SCI_AUTOCSETFILLUPS 2112 -#define SCI_AUTOCSETCHOOSESINGLE 2113 -#define SCI_AUTOCGETCHOOSESINGLE 2114 -#define SCI_AUTOCSETIGNORECASE 2115 -#define SCI_AUTOCGETIGNORECASE 2116 -#define SCI_USERLISTSHOW 2117 -#define SCI_AUTOCSETAUTOHIDE 2118 -#define SCI_AUTOCGETAUTOHIDE 2119 -#define SCI_AUTOCSETDROPRESTOFWORD 2270 -#define SCI_AUTOCGETDROPRESTOFWORD 2271 -#define SCI_REGISTERIMAGE 2405 -#define SCI_CLEARREGISTEREDIMAGES 2408 -#define SCI_AUTOCGETTYPESEPARATOR 2285 -#define SCI_AUTOCSETTYPESEPARATOR 2286 -#define SCI_AUTOCSETMAXWIDTH 2208 -#define SCI_AUTOCGETMAXWIDTH 2209 -#define SCI_AUTOCSETMAXHEIGHT 2210 -#define SCI_AUTOCGETMAXHEIGHT 2211 -#define SCI_SETINDENT 2122 -#define SCI_GETINDENT 2123 -#define SCI_SETUSETABS 2124 -#define SCI_GETUSETABS 2125 -#define SCI_SETLINEINDENTATION 2126 -#define SCI_GETLINEINDENTATION 2127 -#define SCI_GETLINEINDENTPOSITION 2128 -#define SCI_GETCOLUMN 2129 -#define SCI_COUNTCHARACTERS 2633 -#define SCI_SETHSCROLLBAR 2130 -#define SCI_GETHSCROLLBAR 2131 -#define SC_IV_NONE 0 -#define SC_IV_REAL 1 -#define SC_IV_LOOKFORWARD 2 -#define SC_IV_LOOKBOTH 3 -#define SCI_SETINDENTATIONGUIDES 2132 -#define SCI_GETINDENTATIONGUIDES 2133 -#define SCI_SETHIGHLIGHTGUIDE 2134 -#define SCI_GETHIGHLIGHTGUIDE 2135 -#define SCI_GETLINEENDPOSITION 2136 -#define SCI_GETCODEPAGE 2137 -#define SCI_GETCARETFORE 2138 -#define SCI_GETREADONLY 2140 -#define SCI_SETCURRENTPOS 2141 -#define SCI_SETSELECTIONSTART 2142 -#define SCI_GETSELECTIONSTART 2143 -#define SCI_SETSELECTIONEND 2144 -#define SCI_GETSELECTIONEND 2145 -#define SCI_SETEMPTYSELECTION 2556 -#define SCI_SETPRINTMAGNIFICATION 2146 -#define SCI_GETPRINTMAGNIFICATION 2147 -#define SC_PRINT_NORMAL 0 -#define SC_PRINT_INVERTLIGHT 1 -#define SC_PRINT_BLACKONWHITE 2 -#define SC_PRINT_COLOURONWHITE 3 -#define SC_PRINT_COLOURONWHITEDEFAULTBG 4 -#define SCI_SETPRINTCOLOURMODE 2148 -#define SCI_GETPRINTCOLOURMODE 2149 -#define SCFIND_WHOLEWORD 2 -#define SCFIND_MATCHCASE 4 -#define SCFIND_WORDSTART 0x00100000 -#define SCFIND_REGEXP 0x00200000 -#define SCFIND_POSIX 0x00400000 -#define SCI_FINDTEXT 2150 -#define SCI_FORMATRANGE 2151 -#define SCI_GETFIRSTVISIBLELINE 2152 -#define SCI_GETLINE 2153 -#define SCI_GETLINECOUNT 2154 -#define SCI_SETMARGINLEFT 2155 -#define SCI_GETMARGINLEFT 2156 -#define SCI_SETMARGINRIGHT 2157 -#define SCI_GETMARGINRIGHT 2158 -#define SCI_GETMODIFY 2159 -#define SCI_SETSEL 2160 -#define SCI_GETSELTEXT 2161 -#define SCI_GETTEXTRANGE 2162 -#define SCI_HIDESELECTION 2163 -#define SCI_POINTXFROMPOSITION 2164 -#define SCI_POINTYFROMPOSITION 2165 -#define SCI_LINEFROMPOSITION 2166 -#define SCI_POSITIONFROMLINE 2167 -#define SCI_LINESCROLL 2168 -#define SCI_SCROLLCARET 2169 -#define SCI_REPLACESEL 2170 -#define SCI_SETREADONLY 2171 -#define SCI_NULL 2172 -#define SCI_CANPASTE 2173 -#define SCI_CANUNDO 2174 -#define SCI_EMPTYUNDOBUFFER 2175 -#define SCI_UNDO 2176 -#define SCI_CUT 2177 -#define SCI_COPY 2178 -#define SCI_PASTE 2179 -#define SCI_CLEAR 2180 -#define SCI_SETTEXT 2181 -#define SCI_GETTEXT 2182 -#define SCI_GETTEXTLENGTH 2183 -#define SCI_GETDIRECTFUNCTION 2184 -#define SCI_GETDIRECTPOINTER 2185 -#define SCI_SETOVERTYPE 2186 -#define SCI_GETOVERTYPE 2187 -#define SCI_SETCARETWIDTH 2188 -#define SCI_GETCARETWIDTH 2189 -#define SCI_SETTARGETSTART 2190 -#define SCI_GETTARGETSTART 2191 -#define SCI_SETTARGETEND 2192 -#define SCI_GETTARGETEND 2193 -#define SCI_REPLACETARGET 2194 -#define SCI_REPLACETARGETRE 2195 -#define SCI_SEARCHINTARGET 2197 -#define SCI_SETSEARCHFLAGS 2198 -#define SCI_GETSEARCHFLAGS 2199 -#define SCI_CALLTIPSHOW 2200 -#define SCI_CALLTIPCANCEL 2201 -#define SCI_CALLTIPACTIVE 2202 -#define SCI_CALLTIPPOSSTART 2203 -#define SCI_CALLTIPSETHLT 2204 -#define SCI_CALLTIPSETBACK 2205 -#define SCI_CALLTIPSETFORE 2206 -#define SCI_CALLTIPSETFOREHLT 2207 -#define SCI_CALLTIPUSESTYLE 2212 -#define SCI_CALLTIPSETPOSITION 2213 -#define SCI_VISIBLEFROMDOCLINE 2220 -#define SCI_DOCLINEFROMVISIBLE 2221 -#define SCI_WRAPCOUNT 2235 -#define SC_FOLDLEVELBASE 0x400 -#define SC_FOLDLEVELWHITEFLAG 0x1000 -#define SC_FOLDLEVELHEADERFLAG 0x2000 -#define SC_FOLDLEVELNUMBERMASK 0x0FFF -#define SCI_SETFOLDLEVEL 2222 -#define SCI_GETFOLDLEVEL 2223 -#define SCI_GETLASTCHILD 2224 -#define SCI_GETFOLDPARENT 2225 -#define SCI_SHOWLINES 2226 -#define SCI_HIDELINES 2227 -#define SCI_GETLINEVISIBLE 2228 -#define SCI_GETALLLINESVISIBLE 2236 -#define SCI_SETFOLDEXPANDED 2229 -#define SCI_GETFOLDEXPANDED 2230 -#define SCI_TOGGLEFOLD 2231 -#define SCI_ENSUREVISIBLE 2232 -#define SC_FOLDFLAG_LINEBEFORE_EXPANDED 0x0002 -#define SC_FOLDFLAG_LINEBEFORE_CONTRACTED 0x0004 -#define SC_FOLDFLAG_LINEAFTER_EXPANDED 0x0008 -#define SC_FOLDFLAG_LINEAFTER_CONTRACTED 0x0010 -#define SC_FOLDFLAG_LEVELNUMBERS 0x0040 -#define SCI_SETFOLDFLAGS 2233 -#define SCI_ENSUREVISIBLEENFORCEPOLICY 2234 -#define SCI_SETTABINDENTS 2260 -#define SCI_GETTABINDENTS 2261 -#define SCI_SETBACKSPACEUNINDENTS 2262 -#define SCI_GETBACKSPACEUNINDENTS 2263 -#define SC_TIME_FOREVER 10000000 -#define SCI_SETMOUSEDWELLTIME 2264 -#define SCI_GETMOUSEDWELLTIME 2265 -#define SCI_WORDSTARTPOSITION 2266 -#define SCI_WORDENDPOSITION 2267 -#define SC_WRAP_NONE 0 -#define SC_WRAP_WORD 1 -#define SC_WRAP_CHAR 2 -#define SCI_SETWRAPMODE 2268 -#define SCI_GETWRAPMODE 2269 -#define SC_WRAPVISUALFLAG_NONE 0x0000 -#define SC_WRAPVISUALFLAG_END 0x0001 -#define SC_WRAPVISUALFLAG_START 0x0002 -#define SCI_SETWRAPVISUALFLAGS 2460 -#define SCI_GETWRAPVISUALFLAGS 2461 -#define SC_WRAPVISUALFLAGLOC_DEFAULT 0x0000 -#define SC_WRAPVISUALFLAGLOC_END_BY_TEXT 0x0001 -#define SC_WRAPVISUALFLAGLOC_START_BY_TEXT 0x0002 -#define SCI_SETWRAPVISUALFLAGSLOCATION 2462 -#define SCI_GETWRAPVISUALFLAGSLOCATION 2463 -#define SCI_SETWRAPSTARTINDENT 2464 -#define SCI_GETWRAPSTARTINDENT 2465 -#define SC_WRAPINDENT_FIXED 0 -#define SC_WRAPINDENT_SAME 1 -#define SC_WRAPINDENT_INDENT 2 -#define SCI_SETWRAPINDENTMODE 2472 -#define SCI_GETWRAPINDENTMODE 2473 -#define SC_CACHE_NONE 0 -#define SC_CACHE_CARET 1 -#define SC_CACHE_PAGE 2 -#define SC_CACHE_DOCUMENT 3 -#define SCI_SETLAYOUTCACHE 2272 -#define SCI_GETLAYOUTCACHE 2273 -#define SCI_SETSCROLLWIDTH 2274 -#define SCI_GETSCROLLWIDTH 2275 -#define SCI_SETSCROLLWIDTHTRACKING 2516 -#define SCI_GETSCROLLWIDTHTRACKING 2517 -#define SCI_TEXTWIDTH 2276 -#define SCI_SETENDATLASTLINE 2277 -#define SCI_GETENDATLASTLINE 2278 -#define SCI_TEXTHEIGHT 2279 -#define SCI_SETVSCROLLBAR 2280 -#define SCI_GETVSCROLLBAR 2281 -#define SCI_APPENDTEXT 2282 -#define SCI_GETTWOPHASEDRAW 2283 -#define SCI_SETTWOPHASEDRAW 2284 -#define SC_EFF_QUALITY_MASK 0xF -#define SC_EFF_QUALITY_DEFAULT 0 -#define SC_EFF_QUALITY_NON_ANTIALIASED 1 -#define SC_EFF_QUALITY_ANTIALIASED 2 -#define SC_EFF_QUALITY_LCD_OPTIMIZED 3 -#define SCI_SETFONTQUALITY 2611 -#define SCI_GETFONTQUALITY 2612 -#define SCI_SETFIRSTVISIBLELINE 2613 -#define SC_MULTIPASTE_ONCE 0 -#define SC_MULTIPASTE_EACH 1 -#define SCI_SETMULTIPASTE 2614 -#define SCI_GETMULTIPASTE 2615 -#define SCI_GETTAG 2616 -#define SCI_TARGETFROMSELECTION 2287 -#define SCI_LINESJOIN 2288 -#define SCI_LINESSPLIT 2289 -#define SCI_SETFOLDMARGINCOLOUR 2290 -#define SCI_SETFOLDMARGINHICOLOUR 2291 -#define SCI_LINEDOWN 2300 -#define SCI_LINEDOWNEXTEND 2301 -#define SCI_LINEUP 2302 -#define SCI_LINEUPEXTEND 2303 -#define SCI_CHARLEFT 2304 -#define SCI_CHARLEFTEXTEND 2305 -#define SCI_CHARRIGHT 2306 -#define SCI_CHARRIGHTEXTEND 2307 -#define SCI_WORDLEFT 2308 -#define SCI_WORDLEFTEXTEND 2309 -#define SCI_WORDRIGHT 2310 -#define SCI_WORDRIGHTEXTEND 2311 -#define SCI_HOME 2312 -#define SCI_HOMEEXTEND 2313 -#define SCI_LINEEND 2314 -#define SCI_LINEENDEXTEND 2315 -#define SCI_DOCUMENTSTART 2316 -#define SCI_DOCUMENTSTARTEXTEND 2317 -#define SCI_DOCUMENTEND 2318 -#define SCI_DOCUMENTENDEXTEND 2319 -#define SCI_PAGEUP 2320 -#define SCI_PAGEUPEXTEND 2321 -#define SCI_PAGEDOWN 2322 -#define SCI_PAGEDOWNEXTEND 2323 -#define SCI_EDITTOGGLEOVERTYPE 2324 -#define SCI_CANCEL 2325 -#define SCI_DELETEBACK 2326 -#define SCI_TAB 2327 -#define SCI_BACKTAB 2328 -#define SCI_NEWLINE 2329 -#define SCI_FORMFEED 2330 -#define SCI_VCHOME 2331 -#define SCI_VCHOMEEXTEND 2332 -#define SCI_ZOOMIN 2333 -#define SCI_ZOOMOUT 2334 -#define SCI_DELWORDLEFT 2335 -#define SCI_DELWORDRIGHT 2336 -#define SCI_DELWORDRIGHTEND 2518 -#define SCI_LINECUT 2337 -#define SCI_LINEDELETE 2338 -#define SCI_LINETRANSPOSE 2339 -#define SCI_LINEDUPLICATE 2404 -#define SCI_LOWERCASE 2340 -#define SCI_UPPERCASE 2341 -#define SCI_LINESCROLLDOWN 2342 -#define SCI_LINESCROLLUP 2343 -#define SCI_DELETEBACKNOTLINE 2344 -#define SCI_HOMEDISPLAY 2345 -#define SCI_HOMEDISPLAYEXTEND 2346 -#define SCI_LINEENDDISPLAY 2347 -#define SCI_LINEENDDISPLAYEXTEND 2348 -#define SCI_HOMEWRAP 2349 -#define SCI_HOMEWRAPEXTEND 2450 -#define SCI_LINEENDWRAP 2451 -#define SCI_LINEENDWRAPEXTEND 2452 -#define SCI_VCHOMEWRAP 2453 -#define SCI_VCHOMEWRAPEXTEND 2454 -#define SCI_LINECOPY 2455 -#define SCI_MOVECARETINSIDEVIEW 2401 -#define SCI_LINELENGTH 2350 -#define SCI_BRACEHIGHLIGHT 2351 -#define SCI_BRACEHIGHLIGHTINDICATOR 2498 -#define SCI_BRACEBADLIGHT 2352 -#define SCI_BRACEBADLIGHTINDICATOR 2499 -#define SCI_BRACEMATCH 2353 -#define SCI_GETVIEWEOL 2355 -#define SCI_SETVIEWEOL 2356 -#define SCI_GETDOCPOINTER 2357 -#define SCI_SETDOCPOINTER 2358 -#define SCI_SETMODEVENTMASK 2359 -#define EDGE_NONE 0 -#define EDGE_LINE 1 -#define EDGE_BACKGROUND 2 -#define SCI_GETEDGECOLUMN 2360 -#define SCI_SETEDGECOLUMN 2361 -#define SCI_GETEDGEMODE 2362 -#define SCI_SETEDGEMODE 2363 -#define SCI_GETEDGECOLOUR 2364 -#define SCI_SETEDGECOLOUR 2365 -#define SCI_SEARCHANCHOR 2366 -#define SCI_SEARCHNEXT 2367 -#define SCI_SEARCHPREV 2368 -#define SCI_LINESONSCREEN 2370 -#define SCI_USEPOPUP 2371 -#define SCI_SELECTIONISRECTANGLE 2372 -#define SCI_SETZOOM 2373 -#define SCI_GETZOOM 2374 -#define SCI_CREATEDOCUMENT 2375 -#define SCI_ADDREFDOCUMENT 2376 -#define SCI_RELEASEDOCUMENT 2377 -#define SCI_GETMODEVENTMASK 2378 -#define SCI_SETFOCUS 2380 -#define SCI_GETFOCUS 2381 -#define SC_STATUS_OK 0 -#define SC_STATUS_FAILURE 1 -#define SC_STATUS_BADALLOC 2 -#define SCI_SETSTATUS 2382 -#define SCI_GETSTATUS 2383 -#define SCI_SETMOUSEDOWNCAPTURES 2384 -#define SCI_GETMOUSEDOWNCAPTURES 2385 -#define SC_CURSORNORMAL -1 -#define SC_CURSORARROW 2 -#define SC_CURSORWAIT 4 -#define SC_CURSORREVERSEARROW 7 -#define SCI_SETCURSOR 2386 -#define SCI_GETCURSOR 2387 -#define SCI_SETCONTROLCHARSYMBOL 2388 -#define SCI_GETCONTROLCHARSYMBOL 2389 -#define SCI_WORDPARTLEFT 2390 -#define SCI_WORDPARTLEFTEXTEND 2391 -#define SCI_WORDPARTRIGHT 2392 -#define SCI_WORDPARTRIGHTEXTEND 2393 -#define VISIBLE_SLOP 0x01 -#define VISIBLE_STRICT 0x04 -#define SCI_SETVISIBLEPOLICY 2394 -#define SCI_DELLINELEFT 2395 -#define SCI_DELLINERIGHT 2396 -#define SCI_SETXOFFSET 2397 -#define SCI_GETXOFFSET 2398 -#define SCI_CHOOSECARETX 2399 -#define SCI_GRABFOCUS 2400 -#define CARET_SLOP 0x01 -#define CARET_STRICT 0x04 -#define CARET_JUMPS 0x10 -#define CARET_EVEN 0x08 -#define SCI_SETXCARETPOLICY 2402 -#define SCI_SETYCARETPOLICY 2403 -#define SCI_SETPRINTWRAPMODE 2406 -#define SCI_GETPRINTWRAPMODE 2407 -#define SCI_SETHOTSPOTACTIVEFORE 2410 -#define SCI_GETHOTSPOTACTIVEFORE 2494 -#define SCI_SETHOTSPOTACTIVEBACK 2411 -#define SCI_GETHOTSPOTACTIVEBACK 2495 -#define SCI_SETHOTSPOTACTIVEUNDERLINE 2412 -#define SCI_GETHOTSPOTACTIVEUNDERLINE 2496 -#define SCI_SETHOTSPOTSINGLELINE 2421 -#define SCI_GETHOTSPOTSINGLELINE 2497 -#define SCI_PARADOWN 2413 -#define SCI_PARADOWNEXTEND 2414 -#define SCI_PARAUP 2415 -#define SCI_PARAUPEXTEND 2416 -#define SCI_POSITIONBEFORE 2417 -#define SCI_POSITIONAFTER 2418 -#define SCI_COPYRANGE 2419 -#define SCI_COPYTEXT 2420 -#define SC_SEL_STREAM 0 -#define SC_SEL_RECTANGLE 1 -#define SC_SEL_LINES 2 -#define SC_SEL_THIN 3 -#define SCI_SETSELECTIONMODE 2422 -#define SCI_GETSELECTIONMODE 2423 -#define SCI_GETLINESELSTARTPOSITION 2424 -#define SCI_GETLINESELENDPOSITION 2425 -#define SCI_LINEDOWNRECTEXTEND 2426 -#define SCI_LINEUPRECTEXTEND 2427 -#define SCI_CHARLEFTRECTEXTEND 2428 -#define SCI_CHARRIGHTRECTEXTEND 2429 -#define SCI_HOMERECTEXTEND 2430 -#define SCI_VCHOMERECTEXTEND 2431 -#define SCI_LINEENDRECTEXTEND 2432 -#define SCI_PAGEUPRECTEXTEND 2433 -#define SCI_PAGEDOWNRECTEXTEND 2434 -#define SCI_STUTTEREDPAGEUP 2435 -#define SCI_STUTTEREDPAGEUPEXTEND 2436 -#define SCI_STUTTEREDPAGEDOWN 2437 -#define SCI_STUTTEREDPAGEDOWNEXTEND 2438 -#define SCI_WORDLEFTEND 2439 -#define SCI_WORDLEFTENDEXTEND 2440 -#define SCI_WORDRIGHTEND 2441 -#define SCI_WORDRIGHTENDEXTEND 2442 -#define SCI_SETWHITESPACECHARS 2443 -#define SCI_SETCHARSDEFAULT 2444 -#define SCI_AUTOCGETCURRENT 2445 -#define SCI_AUTOCGETCURRENTTEXT 2610 -#define SCI_ALLOCATE 2446 -#define SCI_TARGETASUTF8 2447 -#define SCI_SETLENGTHFORENCODE 2448 -#define SCI_ENCODEDFROMUTF8 2449 -#define SCI_FINDCOLUMN 2456 -#define SCI_GETCARETSTICKY 2457 -#define SCI_SETCARETSTICKY 2458 -#define SC_CARETSTICKY_OFF 0 -#define SC_CARETSTICKY_ON 1 -#define SC_CARETSTICKY_WHITESPACE 2 -#define SCI_TOGGLECARETSTICKY 2459 -#define SCI_SETPASTECONVERTENDINGS 2467 -#define SCI_GETPASTECONVERTENDINGS 2468 -#define SCI_SELECTIONDUPLICATE 2469 -#define SC_ALPHA_TRANSPARENT 0 -#define SC_ALPHA_OPAQUE 255 -#define SC_ALPHA_NOALPHA 256 -#define SCI_SETCARETLINEBACKALPHA 2470 -#define SCI_GETCARETLINEBACKALPHA 2471 -#define CARETSTYLE_INVISIBLE 0 -#define CARETSTYLE_LINE 1 -#define CARETSTYLE_BLOCK 2 -#define SCI_SETCARETSTYLE 2512 -#define SCI_GETCARETSTYLE 2513 -#define SCI_SETINDICATORCURRENT 2500 -#define SCI_GETINDICATORCURRENT 2501 -#define SCI_SETINDICATORVALUE 2502 -#define SCI_GETINDICATORVALUE 2503 -#define SCI_INDICATORFILLRANGE 2504 -#define SCI_INDICATORCLEARRANGE 2505 -#define SCI_INDICATORALLONFOR 2506 -#define SCI_INDICATORVALUEAT 2507 -#define SCI_INDICATORSTART 2508 -#define SCI_INDICATOREND 2509 -#define SCI_SETPOSITIONCACHE 2514 -#define SCI_GETPOSITIONCACHE 2515 -#define SCI_COPYALLOWLINE 2519 -#define SCI_GETCHARACTERPOINTER 2520 -#define SCI_SETKEYSUNICODE 2521 -#define SCI_GETKEYSUNICODE 2522 -#define SCI_INDICSETALPHA 2523 -#define SCI_INDICGETALPHA 2524 -#define SCI_INDICSETOUTLINEALPHA 2558 -#define SCI_INDICGETOUTLINEALPHA 2559 -#define SCI_SETEXTRAASCENT 2525 -#define SCI_GETEXTRAASCENT 2526 -#define SCI_SETEXTRADESCENT 2527 -#define SCI_GETEXTRADESCENT 2528 -#define SCI_MARKERSYMBOLDEFINED 2529 -#define SCI_MARGINSETTEXT 2530 -#define SCI_MARGINGETTEXT 2531 -#define SCI_MARGINSETSTYLE 2532 -#define SCI_MARGINGETSTYLE 2533 -#define SCI_MARGINSETSTYLES 2534 -#define SCI_MARGINGETSTYLES 2535 -#define SCI_MARGINTEXTCLEARALL 2536 -#define SCI_MARGINSETSTYLEOFFSET 2537 -#define SCI_MARGINGETSTYLEOFFSET 2538 -#define SC_MARGINOPTION_NONE 0 -#define SC_MARGINOPTION_SUBLINESELECT 1 -#define SCI_SETMARGINOPTIONS 2539 -#define SCI_GETMARGINOPTIONS 2557 -#define SCI_ANNOTATIONSETTEXT 2540 -#define SCI_ANNOTATIONGETTEXT 2541 -#define SCI_ANNOTATIONSETSTYLE 2542 -#define SCI_ANNOTATIONGETSTYLE 2543 -#define SCI_ANNOTATIONSETSTYLES 2544 -#define SCI_ANNOTATIONGETSTYLES 2545 -#define SCI_ANNOTATIONGETLINES 2546 -#define SCI_ANNOTATIONCLEARALL 2547 -#define ANNOTATION_HIDDEN 0 -#define ANNOTATION_STANDARD 1 -#define ANNOTATION_BOXED 2 -#define SCI_ANNOTATIONSETVISIBLE 2548 -#define SCI_ANNOTATIONGETVISIBLE 2549 -#define SCI_ANNOTATIONSETSTYLEOFFSET 2550 -#define SCI_ANNOTATIONGETSTYLEOFFSET 2551 -#define UNDO_MAY_COALESCE 1 -#define SCI_ADDUNDOACTION 2560 -#define SCI_CHARPOSITIONFROMPOINT 2561 -#define SCI_CHARPOSITIONFROMPOINTCLOSE 2562 -#define SCI_SETMULTIPLESELECTION 2563 -#define SCI_GETMULTIPLESELECTION 2564 -#define SCI_SETADDITIONALSELECTIONTYPING 2565 -#define SCI_GETADDITIONALSELECTIONTYPING 2566 -#define SCI_SETADDITIONALCARETSBLINK 2567 -#define SCI_GETADDITIONALCARETSBLINK 2568 -#define SCI_SETADDITIONALCARETSVISIBLE 2608 -#define SCI_GETADDITIONALCARETSVISIBLE 2609 -#define SCI_GETSELECTIONS 2570 -#define SCI_CLEARSELECTIONS 2571 -#define SCI_SETSELECTION 2572 -#define SCI_ADDSELECTION 2573 -#define SCI_SETMAINSELECTION 2574 -#define SCI_GETMAINSELECTION 2575 -#define SCI_SETSELECTIONNCARET 2576 -#define SCI_GETSELECTIONNCARET 2577 -#define SCI_SETSELECTIONNANCHOR 2578 -#define SCI_GETSELECTIONNANCHOR 2579 -#define SCI_SETSELECTIONNCARETVIRTUALSPACE 2580 -#define SCI_GETSELECTIONNCARETVIRTUALSPACE 2581 -#define SCI_SETSELECTIONNANCHORVIRTUALSPACE 2582 -#define SCI_GETSELECTIONNANCHORVIRTUALSPACE 2583 -#define SCI_SETSELECTIONNSTART 2584 -#define SCI_GETSELECTIONNSTART 2585 -#define SCI_SETSELECTIONNEND 2586 -#define SCI_GETSELECTIONNEND 2587 -#define SCI_SETRECTANGULARSELECTIONCARET 2588 -#define SCI_GETRECTANGULARSELECTIONCARET 2589 -#define SCI_SETRECTANGULARSELECTIONANCHOR 2590 -#define SCI_GETRECTANGULARSELECTIONANCHOR 2591 -#define SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE 2592 -#define SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE 2593 -#define SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE 2594 -#define SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE 2595 -#define SCVS_NONE 0 -#define SCVS_RECTANGULARSELECTION 1 -#define SCVS_USERACCESSIBLE 2 -#define SCI_SETVIRTUALSPACEOPTIONS 2596 -#define SCI_GETVIRTUALSPACEOPTIONS 2597 -#define SCI_SETRECTANGULARSELECTIONMODIFIER 2598 -#define SCI_GETRECTANGULARSELECTIONMODIFIER 2599 -#define SCI_SETADDITIONALSELFORE 2600 -#define SCI_SETADDITIONALSELBACK 2601 -#define SCI_SETADDITIONALSELALPHA 2602 -#define SCI_GETADDITIONALSELALPHA 2603 -#define SCI_SETADDITIONALCARETFORE 2604 -#define SCI_GETADDITIONALCARETFORE 2605 -#define SCI_ROTATESELECTION 2606 -#define SCI_SWAPMAINANCHORCARET 2607 -#define SCI_CHANGELEXERSTATE 2617 -#define SCI_CONTRACTEDFOLDNEXT 2618 -#define SCI_VERTICALCENTRECARET 2619 -#define SCI_MOVESELECTEDLINESUP 2620 -#define SCI_MOVESELECTEDLINESDOWN 2621 -#define SCI_SETIDENTIFIER 2622 -#define SCI_GETIDENTIFIER 2623 -#define SCI_RGBAIMAGESETWIDTH 2624 -#define SCI_RGBAIMAGESETHEIGHT 2625 -#define SCI_MARKERDEFINERGBAIMAGE 2626 -#define SCI_REGISTERRGBAIMAGE 2627 -#define SCI_SCROLLTOSTART 2628 -#define SCI_SCROLLTOEND 2629 -#define SC_TECHNOLOGY_DEFAULT 0 -#define SC_TECHNOLOGY_DIRECTWRITE 1 -#define SCI_SETTECHNOLOGY 2630 -#define SCI_GETTECHNOLOGY 2631 -#define SCI_CREATELOADER 2632 -#define SCI_STARTRECORD 3001 -#define SCI_STOPRECORD 3002 -#define SCI_SETLEXER 4001 -#define SCI_GETLEXER 4002 -#define SCI_COLOURISE 4003 -#define SCI_SETPROPERTY 4004 -#define KEYWORDSET_MAX 8 -#define SCI_SETKEYWORDS 4005 -#define SCI_SETLEXERLANGUAGE 4006 -#define SCI_LOADLEXERLIBRARY 4007 -#define SCI_GETPROPERTY 4008 -#define SCI_GETPROPERTYEXPANDED 4009 -#define SCI_GETPROPERTYINT 4010 -#define SCI_GETSTYLEBITSNEEDED 4011 -#define SCI_GETLEXERLANGUAGE 4012 -#define SCI_PRIVATELEXERCALL 4013 -#define SCI_PROPERTYNAMES 4014 -#define SC_TYPE_BOOLEAN 0 -#define SC_TYPE_INTEGER 1 -#define SC_TYPE_STRING 2 -#define SCI_PROPERTYTYPE 4015 -#define SCI_DESCRIBEPROPERTY 4016 -#define SCI_DESCRIBEKEYWORDSETS 4017 -#define SC_MOD_INSERTTEXT 0x1 -#define SC_MOD_DELETETEXT 0x2 -#define SC_MOD_CHANGESTYLE 0x4 -#define SC_MOD_CHANGEFOLD 0x8 -#define SC_PERFORMED_USER 0x10 -#define SC_PERFORMED_UNDO 0x20 -#define SC_PERFORMED_REDO 0x40 -#define SC_MULTISTEPUNDOREDO 0x80 -#define SC_LASTSTEPINUNDOREDO 0x100 -#define SC_MOD_CHANGEMARKER 0x200 -#define SC_MOD_BEFOREINSERT 0x400 -#define SC_MOD_BEFOREDELETE 0x800 -#define SC_MULTILINEUNDOREDO 0x1000 -#define SC_STARTACTION 0x2000 -#define SC_MOD_CHANGEINDICATOR 0x4000 -#define SC_MOD_CHANGELINESTATE 0x8000 -#define SC_MOD_CHANGEMARGIN 0x10000 -#define SC_MOD_CHANGEANNOTATION 0x20000 -#define SC_MOD_CONTAINER 0x40000 -#define SC_MOD_LEXERSTATE 0x80000 -#define SC_MODEVENTMASKALL 0xFFFFF -#define SC_UPDATE_CONTENT 0x1 -#define SC_UPDATE_SELECTION 0x2 -#define SC_UPDATE_V_SCROLL 0x4 -#define SC_UPDATE_H_SCROLL 0x8 -#define SCEN_CHANGE 768 -#define SCEN_SETFOCUS 512 -#define SCEN_KILLFOCUS 256 -#define SCK_DOWN 300 -#define SCK_UP 301 -#define SCK_LEFT 302 -#define SCK_RIGHT 303 -#define SCK_HOME 304 -#define SCK_END 305 -#define SCK_PRIOR 306 -#define SCK_NEXT 307 -#define SCK_DELETE 308 -#define SCK_INSERT 309 -#define SCK_ESCAPE 7 -#define SCK_BACK 8 -#define SCK_TAB 9 -#define SCK_RETURN 13 -#define SCK_ADD 310 -#define SCK_SUBTRACT 311 -#define SCK_DIVIDE 312 -#define SCK_WIN 313 -#define SCK_RWIN 314 -#define SCK_MENU 315 -#define SCMOD_NORM 0 -#define SCMOD_SHIFT 1 -#define SCMOD_CTRL 2 -#define SCMOD_ALT 4 -#define SCMOD_SUPER 8 -#define SCMOD_META 16 -#define SCN_STYLENEEDED 2000 -#define SCN_CHARADDED 2001 -#define SCN_SAVEPOINTREACHED 2002 -#define SCN_SAVEPOINTLEFT 2003 -#define SCN_MODIFYATTEMPTRO 2004 -#define SCN_KEY 2005 -#define SCN_DOUBLECLICK 2006 -#define SCN_UPDATEUI 2007 -#define SCN_MODIFIED 2008 -#define SCN_MACRORECORD 2009 -#define SCN_MARGINCLICK 2010 -#define SCN_NEEDSHOWN 2011 -#define SCN_PAINTED 2013 -#define SCN_USERLISTSELECTION 2014 -#define SCN_URIDROPPED 2015 -#define SCN_DWELLSTART 2016 -#define SCN_DWELLEND 2017 -#define SCN_ZOOM 2018 -#define SCN_HOTSPOTCLICK 2019 -#define SCN_HOTSPOTDOUBLECLICK 2020 -#define SCN_CALLTIPCLICK 2021 -#define SCN_AUTOCSELECTION 2022 -#define SCN_INDICATORCLICK 2023 -#define SCN_INDICATORRELEASE 2024 -#define SCN_AUTOCCANCELLED 2025 -#define SCN_AUTOCCHARDELETED 2026 -#define SCN_HOTSPOTRELEASECLICK 2027 -/* --Autogenerated -- end of section automatically generated from Scintilla.iface */ - -/* These structures are defined to be exactly the same shape as the Win32 - * CHARRANGE, TEXTRANGE, FINDTEXTEX, FORMATRANGE, and NMHDR structs. - * So older code that treats Scintilla as a RichEdit will work. */ - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -struct Sci_CharacterRange { - long cpMin; - long cpMax; -}; - -struct Sci_TextRange { - struct Sci_CharacterRange chrg; - char *lpstrText; -}; - -struct Sci_TextToFind { - struct Sci_CharacterRange chrg; - char *lpstrText; - struct Sci_CharacterRange chrgText; -}; - -#define CharacterRange Sci_CharacterRange -#define TextRange Sci_TextRange -#define TextToFind Sci_TextToFind - -typedef void *Sci_SurfaceID; - -struct Sci_Rectangle { - int left; - int top; - int right; - int bottom; -}; - -/* This structure is used in printing and requires some of the graphics types - * from Platform.h. Not needed by most client code. */ - -struct Sci_RangeToFormat { - Sci_SurfaceID hdc; - Sci_SurfaceID hdcTarget; - struct Sci_Rectangle rc; - struct Sci_Rectangle rcPage; - struct Sci_CharacterRange chrg; -}; - -#define RangeToFormat Sci_RangeToFormat - -struct Sci_NotifyHeader { - /* Compatible with Windows NMHDR. - * hwndFrom is really an environment specific window handle or pointer - * but most clients of Scintilla.h do not have this type visible. */ - void *hwndFrom; - uptr_t idFrom; - unsigned int code; -}; - -#define NotifyHeader Sci_NotifyHeader - -struct SCNotification { - struct Sci_NotifyHeader nmhdr; - int position; - /* SCN_STYLENEEDED, SCN_DOUBLECLICK, SCN_MODIFIED, SCN_MARGINCLICK, */ - /* SCN_NEEDSHOWN, SCN_DWELLSTART, SCN_DWELLEND, SCN_CALLTIPCLICK, */ - /* SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, SCN_HOTSPOTRELEASECLICK, */ - /* SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */ - /* SCN_USERLISTSELECTION, SCN_AUTOCSELECTION */ - - int ch; /* SCN_CHARADDED, SCN_KEY */ - int modifiers; - /* SCN_KEY, SCN_DOUBLECLICK, SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, */ - /* SCN_HOTSPOTRELEASECLICK, SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */ - - int modificationType; /* SCN_MODIFIED */ - const char *text; - /* SCN_MODIFIED, SCN_USERLISTSELECTION, SCN_AUTOCSELECTION, SCN_URIDROPPED */ - - int length; /* SCN_MODIFIED */ - int linesAdded; /* SCN_MODIFIED */ - int message; /* SCN_MACRORECORD */ - uptr_t wParam; /* SCN_MACRORECORD */ - sptr_t lParam; /* SCN_MACRORECORD */ - int line; /* SCN_MODIFIED */ - int foldLevelNow; /* SCN_MODIFIED */ - int foldLevelPrev; /* SCN_MODIFIED */ - int margin; /* SCN_MARGINCLICK */ - int listType; /* SCN_USERLISTSELECTION */ - int x; /* SCN_DWELLSTART, SCN_DWELLEND */ - int y; /* SCN_DWELLSTART, SCN_DWELLEND */ - int token; /* SCN_MODIFIED with SC_MOD_CONTAINER */ - int annotationLinesAdded; /* SCN_MODIFIED with SC_MOD_CHANGEANNOTATION */ - int updated; /* SCN_UPDATEUI */ -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#ifdef INCLUDE_DEPRECATED_FEATURES - -#define SC_CP_DBCS 1 -#define SCI_SETUSEPALETTE 2039 -#define SCI_GETUSEPALETTE 2139 - -#endif - -#endif +/* Scintilla source code edit control */ +/** @file Scintilla.h + ** Interface to the edit control. + **/ +/* Copyright 1998-2003 by Neil Hodgson + * The License.txt file describes the conditions under which this software may be distributed. */ + +/* Most of this file is automatically generated from the Scintilla.iface interface definition + * file which contains any comments about the definitions. HFacer.py does the generation. */ + +#ifndef SCINTILLA_H +#define SCINTILLA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_WIN32) +/* Return false on failure: */ +int Scintilla_RegisterClasses(void *hInstance); +int Scintilla_ReleaseResources(); +#endif +int Scintilla_LinkLexers(); + +#ifdef __cplusplus +} +#endif + +/* Here should be placed typedefs for uptr_t, an unsigned integer type large enough to + * hold a pointer and sptr_t, a signed integer large enough to hold a pointer. + * May need to be changed for 64 bit platforms. */ +#if defined(_WIN32) +#include +#endif +#ifdef MAXULONG_PTR +typedef ULONG_PTR uptr_t; +typedef LONG_PTR sptr_t; +#else +typedef unsigned long uptr_t; +typedef long sptr_t; +#endif + +typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, sptr_t lParam); + +/* ++Autogenerated -- start of section automatically generated from Scintilla.iface */ +#define INVALID_POSITION -1 +#define SCI_START 2000 +#define SCI_OPTIONAL_START 3000 +#define SCI_LEXER_START 4000 +#define SCI_ADDTEXT 2001 +#define SCI_ADDSTYLEDTEXT 2002 +#define SCI_INSERTTEXT 2003 +#define SCI_CLEARALL 2004 +#define SCI_CLEARDOCUMENTSTYLE 2005 +#define SCI_GETLENGTH 2006 +#define SCI_GETCHARAT 2007 +#define SCI_GETCURRENTPOS 2008 +#define SCI_GETANCHOR 2009 +#define SCI_GETSTYLEAT 2010 +#define SCI_REDO 2011 +#define SCI_SETUNDOCOLLECTION 2012 +#define SCI_SELECTALL 2013 +#define SCI_SETSAVEPOINT 2014 +#define SCI_GETSTYLEDTEXT 2015 +#define SCI_CANREDO 2016 +#define SCI_MARKERLINEFROMHANDLE 2017 +#define SCI_MARKERDELETEHANDLE 2018 +#define SCI_GETUNDOCOLLECTION 2019 +#define SCWS_INVISIBLE 0 +#define SCWS_VISIBLEALWAYS 1 +#define SCWS_VISIBLEAFTERINDENT 2 +#define SCI_GETVIEWWS 2020 +#define SCI_SETVIEWWS 2021 +#define SCI_POSITIONFROMPOINT 2022 +#define SCI_POSITIONFROMPOINTCLOSE 2023 +#define SCI_GOTOLINE 2024 +#define SCI_GOTOPOS 2025 +#define SCI_SETANCHOR 2026 +#define SCI_GETCURLINE 2027 +#define SCI_GETENDSTYLED 2028 +#define SC_EOL_CRLF 0 +#define SC_EOL_CR 1 +#define SC_EOL_LF 2 +#define SCI_CONVERTEOLS 2029 +#define SCI_GETEOLMODE 2030 +#define SCI_SETEOLMODE 2031 +#define SCI_STARTSTYLING 2032 +#define SCI_SETSTYLING 2033 +#define SCI_GETBUFFEREDDRAW 2034 +#define SCI_SETBUFFEREDDRAW 2035 +#define SCI_SETTABWIDTH 2036 +#define SCI_GETTABWIDTH 2121 +#define SC_CP_UTF8 65001 +#define SCI_SETCODEPAGE 2037 +#define MARKER_MAX 31 +#define SC_MARK_CIRCLE 0 +#define SC_MARK_ROUNDRECT 1 +#define SC_MARK_ARROW 2 +#define SC_MARK_SMALLRECT 3 +#define SC_MARK_SHORTARROW 4 +#define SC_MARK_EMPTY 5 +#define SC_MARK_ARROWDOWN 6 +#define SC_MARK_MINUS 7 +#define SC_MARK_PLUS 8 +#define SC_MARK_VLINE 9 +#define SC_MARK_LCORNER 10 +#define SC_MARK_TCORNER 11 +#define SC_MARK_BOXPLUS 12 +#define SC_MARK_BOXPLUSCONNECTED 13 +#define SC_MARK_BOXMINUS 14 +#define SC_MARK_BOXMINUSCONNECTED 15 +#define SC_MARK_LCORNERCURVE 16 +#define SC_MARK_TCORNERCURVE 17 +#define SC_MARK_CIRCLEPLUS 18 +#define SC_MARK_CIRCLEPLUSCONNECTED 19 +#define SC_MARK_CIRCLEMINUS 20 +#define SC_MARK_CIRCLEMINUSCONNECTED 21 +#define SC_MARK_BACKGROUND 22 +#define SC_MARK_DOTDOTDOT 23 +#define SC_MARK_ARROWS 24 +#define SC_MARK_PIXMAP 25 +#define SC_MARK_FULLRECT 26 +#define SC_MARK_LEFTRECT 27 +#define SC_MARK_AVAILABLE 28 +#define SC_MARK_UNDERLINE 29 +#define SC_MARK_RGBAIMAGE 30 +#define SC_MARK_CHARACTER 10000 +#define SC_MARKNUM_FOLDEREND 25 +#define SC_MARKNUM_FOLDEROPENMID 26 +#define SC_MARKNUM_FOLDERMIDTAIL 27 +#define SC_MARKNUM_FOLDERTAIL 28 +#define SC_MARKNUM_FOLDERSUB 29 +#define SC_MARKNUM_FOLDER 30 +#define SC_MARKNUM_FOLDEROPEN 31 +#define SC_MASK_FOLDERS 0xFE000000 +#define SCI_MARKERDEFINE 2040 +#define SCI_MARKERSETFORE 2041 +#define SCI_MARKERSETBACK 2042 +#define SCI_MARKERSETBACKSELECTED 2292 +#define SCI_MARKERENABLEHIGHLIGHT 2293 +#define SCI_MARKERADD 2043 +#define SCI_MARKERDELETE 2044 +#define SCI_MARKERDELETEALL 2045 +#define SCI_MARKERGET 2046 +#define SCI_MARKERNEXT 2047 +#define SCI_MARKERPREVIOUS 2048 +#define SCI_MARKERDEFINEPIXMAP 2049 +#define SCI_MARKERADDSET 2466 +#define SCI_MARKERSETALPHA 2476 +#define SC_MARGIN_SYMBOL 0 +#define SC_MARGIN_NUMBER 1 +#define SC_MARGIN_BACK 2 +#define SC_MARGIN_FORE 3 +#define SC_MARGIN_TEXT 4 +#define SC_MARGIN_RTEXT 5 +#define SCI_SETMARGINTYPEN 2240 +#define SCI_GETMARGINTYPEN 2241 +#define SCI_SETMARGINWIDTHN 2242 +#define SCI_GETMARGINWIDTHN 2243 +#define SCI_SETMARGINMASKN 2244 +#define SCI_GETMARGINMASKN 2245 +#define SCI_SETMARGINSENSITIVEN 2246 +#define SCI_GETMARGINSENSITIVEN 2247 +#define SCI_SETMARGINCURSORN 2248 +#define SCI_GETMARGINCURSORN 2249 +#define STYLE_DEFAULT 32 +#define STYLE_LINENUMBER 33 +#define STYLE_BRACELIGHT 34 +#define STYLE_BRACEBAD 35 +#define STYLE_CONTROLCHAR 36 +#define STYLE_INDENTGUIDE 37 +#define STYLE_CALLTIP 38 +#define STYLE_LASTPREDEFINED 39 +#define STYLE_MAX 255 +#define SC_CHARSET_ANSI 0 +#define SC_CHARSET_DEFAULT 1 +#define SC_CHARSET_BALTIC 186 +#define SC_CHARSET_CHINESEBIG5 136 +#define SC_CHARSET_EASTEUROPE 238 +#define SC_CHARSET_GB2312 134 +#define SC_CHARSET_GREEK 161 +#define SC_CHARSET_HANGUL 129 +#define SC_CHARSET_MAC 77 +#define SC_CHARSET_OEM 255 +#define SC_CHARSET_RUSSIAN 204 +#define SC_CHARSET_CYRILLIC 1251 +#define SC_CHARSET_SHIFTJIS 128 +#define SC_CHARSET_SYMBOL 2 +#define SC_CHARSET_TURKISH 162 +#define SC_CHARSET_JOHAB 130 +#define SC_CHARSET_HEBREW 177 +#define SC_CHARSET_ARABIC 178 +#define SC_CHARSET_VIETNAMESE 163 +#define SC_CHARSET_THAI 222 +#define SC_CHARSET_8859_15 1000 +#define SCI_STYLECLEARALL 2050 +#define SCI_STYLESETFORE 2051 +#define SCI_STYLESETBACK 2052 +#define SCI_STYLESETBOLD 2053 +#define SCI_STYLESETITALIC 2054 +#define SCI_STYLESETSIZE 2055 +#define SCI_STYLESETFONT 2056 +#define SCI_STYLESETEOLFILLED 2057 +#define SCI_STYLERESETDEFAULT 2058 +#define SCI_STYLESETUNDERLINE 2059 +#define SC_CASE_MIXED 0 +#define SC_CASE_UPPER 1 +#define SC_CASE_LOWER 2 +#define SCI_STYLEGETFORE 2481 +#define SCI_STYLEGETBACK 2482 +#define SCI_STYLEGETBOLD 2483 +#define SCI_STYLEGETITALIC 2484 +#define SCI_STYLEGETSIZE 2485 +#define SCI_STYLEGETFONT 2486 +#define SCI_STYLEGETEOLFILLED 2487 +#define SCI_STYLEGETUNDERLINE 2488 +#define SCI_STYLEGETCASE 2489 +#define SCI_STYLEGETCHARACTERSET 2490 +#define SCI_STYLEGETVISIBLE 2491 +#define SCI_STYLEGETCHANGEABLE 2492 +#define SCI_STYLEGETHOTSPOT 2493 +#define SCI_STYLESETCASE 2060 +#define SC_FONT_SIZE_MULTIPLIER 100 +#define SCI_STYLESETSIZEFRACTIONAL 2061 +#define SCI_STYLEGETSIZEFRACTIONAL 2062 +#define SC_WEIGHT_NORMAL 400 +#define SC_WEIGHT_SEMIBOLD 600 +#define SC_WEIGHT_BOLD 700 +#define SCI_STYLESETWEIGHT 2063 +#define SCI_STYLEGETWEIGHT 2064 +#define SCI_STYLESETCHARACTERSET 2066 +#define SCI_STYLESETHOTSPOT 2409 +#define SCI_SETSELFORE 2067 +#define SCI_SETSELBACK 2068 +#define SCI_GETSELALPHA 2477 +#define SCI_SETSELALPHA 2478 +#define SCI_GETSELEOLFILLED 2479 +#define SCI_SETSELEOLFILLED 2480 +#define SCI_SETCARETFORE 2069 +#define SCI_ASSIGNCMDKEY 2070 +#define SCI_CLEARCMDKEY 2071 +#define SCI_CLEARALLCMDKEYS 2072 +#define SCI_SETSTYLINGEX 2073 +#define SCI_STYLESETVISIBLE 2074 +#define SCI_GETCARETPERIOD 2075 +#define SCI_SETCARETPERIOD 2076 +#define SCI_SETWORDCHARS 2077 +#define SCI_BEGINUNDOACTION 2078 +#define SCI_ENDUNDOACTION 2079 +#define INDIC_PLAIN 0 +#define INDIC_SQUIGGLE 1 +#define INDIC_TT 2 +#define INDIC_DIAGONAL 3 +#define INDIC_STRIKE 4 +#define INDIC_HIDDEN 5 +#define INDIC_BOX 6 +#define INDIC_ROUNDBOX 7 +#define INDIC_STRAIGHTBOX 8 +#define INDIC_DASH 9 +#define INDIC_DOTS 10 +#define INDIC_SQUIGGLELOW 11 +#define INDIC_DOTBOX 12 +#define INDIC_MAX 31 +#define INDIC_CONTAINER 8 +#define INDIC0_MASK 0x20 +#define INDIC1_MASK 0x40 +#define INDIC2_MASK 0x80 +#define INDICS_MASK 0xE0 +#define SCI_INDICSETSTYLE 2080 +#define SCI_INDICGETSTYLE 2081 +#define SCI_INDICSETFORE 2082 +#define SCI_INDICGETFORE 2083 +#define SCI_INDICSETUNDER 2510 +#define SCI_INDICGETUNDER 2511 +#define SCI_SETWHITESPACEFORE 2084 +#define SCI_SETWHITESPACEBACK 2085 +#define SCI_SETWHITESPACESIZE 2086 +#define SCI_GETWHITESPACESIZE 2087 +#define SCI_SETSTYLEBITS 2090 +#define SCI_GETSTYLEBITS 2091 +#define SCI_SETLINESTATE 2092 +#define SCI_GETLINESTATE 2093 +#define SCI_GETMAXLINESTATE 2094 +#define SCI_GETCARETLINEVISIBLE 2095 +#define SCI_SETCARETLINEVISIBLE 2096 +#define SCI_GETCARETLINEBACK 2097 +#define SCI_SETCARETLINEBACK 2098 +#define SCI_STYLESETCHANGEABLE 2099 +#define SCI_AUTOCSHOW 2100 +#define SCI_AUTOCCANCEL 2101 +#define SCI_AUTOCACTIVE 2102 +#define SCI_AUTOCPOSSTART 2103 +#define SCI_AUTOCCOMPLETE 2104 +#define SCI_AUTOCSTOPS 2105 +#define SCI_AUTOCSETSEPARATOR 2106 +#define SCI_AUTOCGETSEPARATOR 2107 +#define SCI_AUTOCSELECT 2108 +#define SCI_AUTOCSETCANCELATSTART 2110 +#define SCI_AUTOCGETCANCELATSTART 2111 +#define SCI_AUTOCSETFILLUPS 2112 +#define SCI_AUTOCSETCHOOSESINGLE 2113 +#define SCI_AUTOCGETCHOOSESINGLE 2114 +#define SCI_AUTOCSETIGNORECASE 2115 +#define SCI_AUTOCGETIGNORECASE 2116 +#define SCI_USERLISTSHOW 2117 +#define SCI_AUTOCSETAUTOHIDE 2118 +#define SCI_AUTOCGETAUTOHIDE 2119 +#define SCI_AUTOCSETDROPRESTOFWORD 2270 +#define SCI_AUTOCGETDROPRESTOFWORD 2271 +#define SCI_REGISTERIMAGE 2405 +#define SCI_CLEARREGISTEREDIMAGES 2408 +#define SCI_AUTOCGETTYPESEPARATOR 2285 +#define SCI_AUTOCSETTYPESEPARATOR 2286 +#define SCI_AUTOCSETMAXWIDTH 2208 +#define SCI_AUTOCGETMAXWIDTH 2209 +#define SCI_AUTOCSETMAXHEIGHT 2210 +#define SCI_AUTOCGETMAXHEIGHT 2211 +#define SCI_SETINDENT 2122 +#define SCI_GETINDENT 2123 +#define SCI_SETUSETABS 2124 +#define SCI_GETUSETABS 2125 +#define SCI_SETLINEINDENTATION 2126 +#define SCI_GETLINEINDENTATION 2127 +#define SCI_GETLINEINDENTPOSITION 2128 +#define SCI_GETCOLUMN 2129 +#define SCI_COUNTCHARACTERS 2633 +#define SCI_SETHSCROLLBAR 2130 +#define SCI_GETHSCROLLBAR 2131 +#define SC_IV_NONE 0 +#define SC_IV_REAL 1 +#define SC_IV_LOOKFORWARD 2 +#define SC_IV_LOOKBOTH 3 +#define SCI_SETINDENTATIONGUIDES 2132 +#define SCI_GETINDENTATIONGUIDES 2133 +#define SCI_SETHIGHLIGHTGUIDE 2134 +#define SCI_GETHIGHLIGHTGUIDE 2135 +#define SCI_GETLINEENDPOSITION 2136 +#define SCI_GETCODEPAGE 2137 +#define SCI_GETCARETFORE 2138 +#define SCI_GETREADONLY 2140 +#define SCI_SETCURRENTPOS 2141 +#define SCI_SETSELECTIONSTART 2142 +#define SCI_GETSELECTIONSTART 2143 +#define SCI_SETSELECTIONEND 2144 +#define SCI_GETSELECTIONEND 2145 +#define SCI_SETEMPTYSELECTION 2556 +#define SCI_SETPRINTMAGNIFICATION 2146 +#define SCI_GETPRINTMAGNIFICATION 2147 +#define SC_PRINT_NORMAL 0 +#define SC_PRINT_INVERTLIGHT 1 +#define SC_PRINT_BLACKONWHITE 2 +#define SC_PRINT_COLOURONWHITE 3 +#define SC_PRINT_COLOURONWHITEDEFAULTBG 4 +#define SCI_SETPRINTCOLOURMODE 2148 +#define SCI_GETPRINTCOLOURMODE 2149 +#define SCFIND_WHOLEWORD 2 +#define SCFIND_MATCHCASE 4 +#define SCFIND_WORDSTART 0x00100000 +#define SCFIND_REGEXP 0x00200000 +#define SCFIND_POSIX 0x00400000 +#define SCI_FINDTEXT 2150 +#define SCI_FORMATRANGE 2151 +#define SCI_GETFIRSTVISIBLELINE 2152 +#define SCI_GETLINE 2153 +#define SCI_GETLINECOUNT 2154 +#define SCI_SETMARGINLEFT 2155 +#define SCI_GETMARGINLEFT 2156 +#define SCI_SETMARGINRIGHT 2157 +#define SCI_GETMARGINRIGHT 2158 +#define SCI_GETMODIFY 2159 +#define SCI_SETSEL 2160 +#define SCI_GETSELTEXT 2161 +#define SCI_GETTEXTRANGE 2162 +#define SCI_HIDESELECTION 2163 +#define SCI_POINTXFROMPOSITION 2164 +#define SCI_POINTYFROMPOSITION 2165 +#define SCI_LINEFROMPOSITION 2166 +#define SCI_POSITIONFROMLINE 2167 +#define SCI_LINESCROLL 2168 +#define SCI_SCROLLCARET 2169 +#define SCI_REPLACESEL 2170 +#define SCI_SETREADONLY 2171 +#define SCI_NULL 2172 +#define SCI_CANPASTE 2173 +#define SCI_CANUNDO 2174 +#define SCI_EMPTYUNDOBUFFER 2175 +#define SCI_UNDO 2176 +#define SCI_CUT 2177 +#define SCI_COPY 2178 +#define SCI_PASTE 2179 +#define SCI_CLEAR 2180 +#define SCI_SETTEXT 2181 +#define SCI_GETTEXT 2182 +#define SCI_GETTEXTLENGTH 2183 +#define SCI_GETDIRECTFUNCTION 2184 +#define SCI_GETDIRECTPOINTER 2185 +#define SCI_SETOVERTYPE 2186 +#define SCI_GETOVERTYPE 2187 +#define SCI_SETCARETWIDTH 2188 +#define SCI_GETCARETWIDTH 2189 +#define SCI_SETTARGETSTART 2190 +#define SCI_GETTARGETSTART 2191 +#define SCI_SETTARGETEND 2192 +#define SCI_GETTARGETEND 2193 +#define SCI_REPLACETARGET 2194 +#define SCI_REPLACETARGETRE 2195 +#define SCI_SEARCHINTARGET 2197 +#define SCI_SETSEARCHFLAGS 2198 +#define SCI_GETSEARCHFLAGS 2199 +#define SCI_CALLTIPSHOW 2200 +#define SCI_CALLTIPCANCEL 2201 +#define SCI_CALLTIPACTIVE 2202 +#define SCI_CALLTIPPOSSTART 2203 +#define SCI_CALLTIPSETHLT 2204 +#define SCI_CALLTIPSETBACK 2205 +#define SCI_CALLTIPSETFORE 2206 +#define SCI_CALLTIPSETFOREHLT 2207 +#define SCI_CALLTIPUSESTYLE 2212 +#define SCI_CALLTIPSETPOSITION 2213 +#define SCI_VISIBLEFROMDOCLINE 2220 +#define SCI_DOCLINEFROMVISIBLE 2221 +#define SCI_WRAPCOUNT 2235 +#define SC_FOLDLEVELBASE 0x400 +#define SC_FOLDLEVELWHITEFLAG 0x1000 +#define SC_FOLDLEVELHEADERFLAG 0x2000 +#define SC_FOLDLEVELNUMBERMASK 0x0FFF +#define SCI_SETFOLDLEVEL 2222 +#define SCI_GETFOLDLEVEL 2223 +#define SCI_GETLASTCHILD 2224 +#define SCI_GETFOLDPARENT 2225 +#define SCI_SHOWLINES 2226 +#define SCI_HIDELINES 2227 +#define SCI_GETLINEVISIBLE 2228 +#define SCI_GETALLLINESVISIBLE 2236 +#define SCI_SETFOLDEXPANDED 2229 +#define SCI_GETFOLDEXPANDED 2230 +#define SCI_TOGGLEFOLD 2231 +#define SCI_ENSUREVISIBLE 2232 +#define SC_FOLDFLAG_LINEBEFORE_EXPANDED 0x0002 +#define SC_FOLDFLAG_LINEBEFORE_CONTRACTED 0x0004 +#define SC_FOLDFLAG_LINEAFTER_EXPANDED 0x0008 +#define SC_FOLDFLAG_LINEAFTER_CONTRACTED 0x0010 +#define SC_FOLDFLAG_LEVELNUMBERS 0x0040 +#define SCI_SETFOLDFLAGS 2233 +#define SCI_ENSUREVISIBLEENFORCEPOLICY 2234 +#define SCI_SETTABINDENTS 2260 +#define SCI_GETTABINDENTS 2261 +#define SCI_SETBACKSPACEUNINDENTS 2262 +#define SCI_GETBACKSPACEUNINDENTS 2263 +#define SC_TIME_FOREVER 10000000 +#define SCI_SETMOUSEDWELLTIME 2264 +#define SCI_GETMOUSEDWELLTIME 2265 +#define SCI_WORDSTARTPOSITION 2266 +#define SCI_WORDENDPOSITION 2267 +#define SC_WRAP_NONE 0 +#define SC_WRAP_WORD 1 +#define SC_WRAP_CHAR 2 +#define SCI_SETWRAPMODE 2268 +#define SCI_GETWRAPMODE 2269 +#define SC_WRAPVISUALFLAG_NONE 0x0000 +#define SC_WRAPVISUALFLAG_END 0x0001 +#define SC_WRAPVISUALFLAG_START 0x0002 +#define SCI_SETWRAPVISUALFLAGS 2460 +#define SCI_GETWRAPVISUALFLAGS 2461 +#define SC_WRAPVISUALFLAGLOC_DEFAULT 0x0000 +#define SC_WRAPVISUALFLAGLOC_END_BY_TEXT 0x0001 +#define SC_WRAPVISUALFLAGLOC_START_BY_TEXT 0x0002 +#define SCI_SETWRAPVISUALFLAGSLOCATION 2462 +#define SCI_GETWRAPVISUALFLAGSLOCATION 2463 +#define SCI_SETWRAPSTARTINDENT 2464 +#define SCI_GETWRAPSTARTINDENT 2465 +#define SC_WRAPINDENT_FIXED 0 +#define SC_WRAPINDENT_SAME 1 +#define SC_WRAPINDENT_INDENT 2 +#define SCI_SETWRAPINDENTMODE 2472 +#define SCI_GETWRAPINDENTMODE 2473 +#define SC_CACHE_NONE 0 +#define SC_CACHE_CARET 1 +#define SC_CACHE_PAGE 2 +#define SC_CACHE_DOCUMENT 3 +#define SCI_SETLAYOUTCACHE 2272 +#define SCI_GETLAYOUTCACHE 2273 +#define SCI_SETSCROLLWIDTH 2274 +#define SCI_GETSCROLLWIDTH 2275 +#define SCI_SETSCROLLWIDTHTRACKING 2516 +#define SCI_GETSCROLLWIDTHTRACKING 2517 +#define SCI_TEXTWIDTH 2276 +#define SCI_SETENDATLASTLINE 2277 +#define SCI_GETENDATLASTLINE 2278 +#define SCI_TEXTHEIGHT 2279 +#define SCI_SETVSCROLLBAR 2280 +#define SCI_GETVSCROLLBAR 2281 +#define SCI_APPENDTEXT 2282 +#define SCI_GETTWOPHASEDRAW 2283 +#define SCI_SETTWOPHASEDRAW 2284 +#define SC_EFF_QUALITY_MASK 0xF +#define SC_EFF_QUALITY_DEFAULT 0 +#define SC_EFF_QUALITY_NON_ANTIALIASED 1 +#define SC_EFF_QUALITY_ANTIALIASED 2 +#define SC_EFF_QUALITY_LCD_OPTIMIZED 3 +#define SCI_SETFONTQUALITY 2611 +#define SCI_GETFONTQUALITY 2612 +#define SCI_SETFIRSTVISIBLELINE 2613 +#define SC_MULTIPASTE_ONCE 0 +#define SC_MULTIPASTE_EACH 1 +#define SCI_SETMULTIPASTE 2614 +#define SCI_GETMULTIPASTE 2615 +#define SCI_GETTAG 2616 +#define SCI_TARGETFROMSELECTION 2287 +#define SCI_LINESJOIN 2288 +#define SCI_LINESSPLIT 2289 +#define SCI_SETFOLDMARGINCOLOUR 2290 +#define SCI_SETFOLDMARGINHICOLOUR 2291 +#define SCI_LINEDOWN 2300 +#define SCI_LINEDOWNEXTEND 2301 +#define SCI_LINEUP 2302 +#define SCI_LINEUPEXTEND 2303 +#define SCI_CHARLEFT 2304 +#define SCI_CHARLEFTEXTEND 2305 +#define SCI_CHARRIGHT 2306 +#define SCI_CHARRIGHTEXTEND 2307 +#define SCI_WORDLEFT 2308 +#define SCI_WORDLEFTEXTEND 2309 +#define SCI_WORDRIGHT 2310 +#define SCI_WORDRIGHTEXTEND 2311 +#define SCI_HOME 2312 +#define SCI_HOMEEXTEND 2313 +#define SCI_LINEEND 2314 +#define SCI_LINEENDEXTEND 2315 +#define SCI_DOCUMENTSTART 2316 +#define SCI_DOCUMENTSTARTEXTEND 2317 +#define SCI_DOCUMENTEND 2318 +#define SCI_DOCUMENTENDEXTEND 2319 +#define SCI_PAGEUP 2320 +#define SCI_PAGEUPEXTEND 2321 +#define SCI_PAGEDOWN 2322 +#define SCI_PAGEDOWNEXTEND 2323 +#define SCI_EDITTOGGLEOVERTYPE 2324 +#define SCI_CANCEL 2325 +#define SCI_DELETEBACK 2326 +#define SCI_TAB 2327 +#define SCI_BACKTAB 2328 +#define SCI_NEWLINE 2329 +#define SCI_FORMFEED 2330 +#define SCI_VCHOME 2331 +#define SCI_VCHOMEEXTEND 2332 +#define SCI_ZOOMIN 2333 +#define SCI_ZOOMOUT 2334 +#define SCI_DELWORDLEFT 2335 +#define SCI_DELWORDRIGHT 2336 +#define SCI_DELWORDRIGHTEND 2518 +#define SCI_LINECUT 2337 +#define SCI_LINEDELETE 2338 +#define SCI_LINETRANSPOSE 2339 +#define SCI_LINEDUPLICATE 2404 +#define SCI_LOWERCASE 2340 +#define SCI_UPPERCASE 2341 +#define SCI_LINESCROLLDOWN 2342 +#define SCI_LINESCROLLUP 2343 +#define SCI_DELETEBACKNOTLINE 2344 +#define SCI_HOMEDISPLAY 2345 +#define SCI_HOMEDISPLAYEXTEND 2346 +#define SCI_LINEENDDISPLAY 2347 +#define SCI_LINEENDDISPLAYEXTEND 2348 +#define SCI_HOMEWRAP 2349 +#define SCI_HOMEWRAPEXTEND 2450 +#define SCI_LINEENDWRAP 2451 +#define SCI_LINEENDWRAPEXTEND 2452 +#define SCI_VCHOMEWRAP 2453 +#define SCI_VCHOMEWRAPEXTEND 2454 +#define SCI_LINECOPY 2455 +#define SCI_MOVECARETINSIDEVIEW 2401 +#define SCI_LINELENGTH 2350 +#define SCI_BRACEHIGHLIGHT 2351 +#define SCI_BRACEHIGHLIGHTINDICATOR 2498 +#define SCI_BRACEBADLIGHT 2352 +#define SCI_BRACEBADLIGHTINDICATOR 2499 +#define SCI_BRACEMATCH 2353 +#define SCI_GETVIEWEOL 2355 +#define SCI_SETVIEWEOL 2356 +#define SCI_GETDOCPOINTER 2357 +#define SCI_SETDOCPOINTER 2358 +#define SCI_SETMODEVENTMASK 2359 +#define EDGE_NONE 0 +#define EDGE_LINE 1 +#define EDGE_BACKGROUND 2 +#define SCI_GETEDGECOLUMN 2360 +#define SCI_SETEDGECOLUMN 2361 +#define SCI_GETEDGEMODE 2362 +#define SCI_SETEDGEMODE 2363 +#define SCI_GETEDGECOLOUR 2364 +#define SCI_SETEDGECOLOUR 2365 +#define SCI_SEARCHANCHOR 2366 +#define SCI_SEARCHNEXT 2367 +#define SCI_SEARCHPREV 2368 +#define SCI_LINESONSCREEN 2370 +#define SCI_USEPOPUP 2371 +#define SCI_SELECTIONISRECTANGLE 2372 +#define SCI_SETZOOM 2373 +#define SCI_GETZOOM 2374 +#define SCI_CREATEDOCUMENT 2375 +#define SCI_ADDREFDOCUMENT 2376 +#define SCI_RELEASEDOCUMENT 2377 +#define SCI_GETMODEVENTMASK 2378 +#define SCI_SETFOCUS 2380 +#define SCI_GETFOCUS 2381 +#define SC_STATUS_OK 0 +#define SC_STATUS_FAILURE 1 +#define SC_STATUS_BADALLOC 2 +#define SCI_SETSTATUS 2382 +#define SCI_GETSTATUS 2383 +#define SCI_SETMOUSEDOWNCAPTURES 2384 +#define SCI_GETMOUSEDOWNCAPTURES 2385 +#define SC_CURSORNORMAL -1 +#define SC_CURSORARROW 2 +#define SC_CURSORWAIT 4 +#define SC_CURSORREVERSEARROW 7 +#define SCI_SETCURSOR 2386 +#define SCI_GETCURSOR 2387 +#define SCI_SETCONTROLCHARSYMBOL 2388 +#define SCI_GETCONTROLCHARSYMBOL 2389 +#define SCI_WORDPARTLEFT 2390 +#define SCI_WORDPARTLEFTEXTEND 2391 +#define SCI_WORDPARTRIGHT 2392 +#define SCI_WORDPARTRIGHTEXTEND 2393 +#define VISIBLE_SLOP 0x01 +#define VISIBLE_STRICT 0x04 +#define SCI_SETVISIBLEPOLICY 2394 +#define SCI_DELLINELEFT 2395 +#define SCI_DELLINERIGHT 2396 +#define SCI_SETXOFFSET 2397 +#define SCI_GETXOFFSET 2398 +#define SCI_CHOOSECARETX 2399 +#define SCI_GRABFOCUS 2400 +#define CARET_SLOP 0x01 +#define CARET_STRICT 0x04 +#define CARET_JUMPS 0x10 +#define CARET_EVEN 0x08 +#define SCI_SETXCARETPOLICY 2402 +#define SCI_SETYCARETPOLICY 2403 +#define SCI_SETPRINTWRAPMODE 2406 +#define SCI_GETPRINTWRAPMODE 2407 +#define SCI_SETHOTSPOTACTIVEFORE 2410 +#define SCI_GETHOTSPOTACTIVEFORE 2494 +#define SCI_SETHOTSPOTACTIVEBACK 2411 +#define SCI_GETHOTSPOTACTIVEBACK 2495 +#define SCI_SETHOTSPOTACTIVEUNDERLINE 2412 +#define SCI_GETHOTSPOTACTIVEUNDERLINE 2496 +#define SCI_SETHOTSPOTSINGLELINE 2421 +#define SCI_GETHOTSPOTSINGLELINE 2497 +#define SCI_PARADOWN 2413 +#define SCI_PARADOWNEXTEND 2414 +#define SCI_PARAUP 2415 +#define SCI_PARAUPEXTEND 2416 +#define SCI_POSITIONBEFORE 2417 +#define SCI_POSITIONAFTER 2418 +#define SCI_COPYRANGE 2419 +#define SCI_COPYTEXT 2420 +#define SC_SEL_STREAM 0 +#define SC_SEL_RECTANGLE 1 +#define SC_SEL_LINES 2 +#define SC_SEL_THIN 3 +#define SCI_SETSELECTIONMODE 2422 +#define SCI_GETSELECTIONMODE 2423 +#define SCI_GETLINESELSTARTPOSITION 2424 +#define SCI_GETLINESELENDPOSITION 2425 +#define SCI_LINEDOWNRECTEXTEND 2426 +#define SCI_LINEUPRECTEXTEND 2427 +#define SCI_CHARLEFTRECTEXTEND 2428 +#define SCI_CHARRIGHTRECTEXTEND 2429 +#define SCI_HOMERECTEXTEND 2430 +#define SCI_VCHOMERECTEXTEND 2431 +#define SCI_LINEENDRECTEXTEND 2432 +#define SCI_PAGEUPRECTEXTEND 2433 +#define SCI_PAGEDOWNRECTEXTEND 2434 +#define SCI_STUTTEREDPAGEUP 2435 +#define SCI_STUTTEREDPAGEUPEXTEND 2436 +#define SCI_STUTTEREDPAGEDOWN 2437 +#define SCI_STUTTEREDPAGEDOWNEXTEND 2438 +#define SCI_WORDLEFTEND 2439 +#define SCI_WORDLEFTENDEXTEND 2440 +#define SCI_WORDRIGHTEND 2441 +#define SCI_WORDRIGHTENDEXTEND 2442 +#define SCI_SETWHITESPACECHARS 2443 +#define SCI_SETCHARSDEFAULT 2444 +#define SCI_AUTOCGETCURRENT 2445 +#define SCI_AUTOCGETCURRENTTEXT 2610 +#define SCI_ALLOCATE 2446 +#define SCI_TARGETASUTF8 2447 +#define SCI_SETLENGTHFORENCODE 2448 +#define SCI_ENCODEDFROMUTF8 2449 +#define SCI_FINDCOLUMN 2456 +#define SCI_GETCARETSTICKY 2457 +#define SCI_SETCARETSTICKY 2458 +#define SC_CARETSTICKY_OFF 0 +#define SC_CARETSTICKY_ON 1 +#define SC_CARETSTICKY_WHITESPACE 2 +#define SCI_TOGGLECARETSTICKY 2459 +#define SCI_SETPASTECONVERTENDINGS 2467 +#define SCI_GETPASTECONVERTENDINGS 2468 +#define SCI_SELECTIONDUPLICATE 2469 +#define SC_ALPHA_TRANSPARENT 0 +#define SC_ALPHA_OPAQUE 255 +#define SC_ALPHA_NOALPHA 256 +#define SCI_SETCARETLINEBACKALPHA 2470 +#define SCI_GETCARETLINEBACKALPHA 2471 +#define CARETSTYLE_INVISIBLE 0 +#define CARETSTYLE_LINE 1 +#define CARETSTYLE_BLOCK 2 +#define SCI_SETCARETSTYLE 2512 +#define SCI_GETCARETSTYLE 2513 +#define SCI_SETINDICATORCURRENT 2500 +#define SCI_GETINDICATORCURRENT 2501 +#define SCI_SETINDICATORVALUE 2502 +#define SCI_GETINDICATORVALUE 2503 +#define SCI_INDICATORFILLRANGE 2504 +#define SCI_INDICATORCLEARRANGE 2505 +#define SCI_INDICATORALLONFOR 2506 +#define SCI_INDICATORVALUEAT 2507 +#define SCI_INDICATORSTART 2508 +#define SCI_INDICATOREND 2509 +#define SCI_SETPOSITIONCACHE 2514 +#define SCI_GETPOSITIONCACHE 2515 +#define SCI_COPYALLOWLINE 2519 +#define SCI_GETCHARACTERPOINTER 2520 +#define SCI_SETKEYSUNICODE 2521 +#define SCI_GETKEYSUNICODE 2522 +#define SCI_INDICSETALPHA 2523 +#define SCI_INDICGETALPHA 2524 +#define SCI_INDICSETOUTLINEALPHA 2558 +#define SCI_INDICGETOUTLINEALPHA 2559 +#define SCI_SETEXTRAASCENT 2525 +#define SCI_GETEXTRAASCENT 2526 +#define SCI_SETEXTRADESCENT 2527 +#define SCI_GETEXTRADESCENT 2528 +#define SCI_MARKERSYMBOLDEFINED 2529 +#define SCI_MARGINSETTEXT 2530 +#define SCI_MARGINGETTEXT 2531 +#define SCI_MARGINSETSTYLE 2532 +#define SCI_MARGINGETSTYLE 2533 +#define SCI_MARGINSETSTYLES 2534 +#define SCI_MARGINGETSTYLES 2535 +#define SCI_MARGINTEXTCLEARALL 2536 +#define SCI_MARGINSETSTYLEOFFSET 2537 +#define SCI_MARGINGETSTYLEOFFSET 2538 +#define SC_MARGINOPTION_NONE 0 +#define SC_MARGINOPTION_SUBLINESELECT 1 +#define SCI_SETMARGINOPTIONS 2539 +#define SCI_GETMARGINOPTIONS 2557 +#define SCI_ANNOTATIONSETTEXT 2540 +#define SCI_ANNOTATIONGETTEXT 2541 +#define SCI_ANNOTATIONSETSTYLE 2542 +#define SCI_ANNOTATIONGETSTYLE 2543 +#define SCI_ANNOTATIONSETSTYLES 2544 +#define SCI_ANNOTATIONGETSTYLES 2545 +#define SCI_ANNOTATIONGETLINES 2546 +#define SCI_ANNOTATIONCLEARALL 2547 +#define ANNOTATION_HIDDEN 0 +#define ANNOTATION_STANDARD 1 +#define ANNOTATION_BOXED 2 +#define SCI_ANNOTATIONSETVISIBLE 2548 +#define SCI_ANNOTATIONGETVISIBLE 2549 +#define SCI_ANNOTATIONSETSTYLEOFFSET 2550 +#define SCI_ANNOTATIONGETSTYLEOFFSET 2551 +#define UNDO_MAY_COALESCE 1 +#define SCI_ADDUNDOACTION 2560 +#define SCI_CHARPOSITIONFROMPOINT 2561 +#define SCI_CHARPOSITIONFROMPOINTCLOSE 2562 +#define SCI_SETMULTIPLESELECTION 2563 +#define SCI_GETMULTIPLESELECTION 2564 +#define SCI_SETADDITIONALSELECTIONTYPING 2565 +#define SCI_GETADDITIONALSELECTIONTYPING 2566 +#define SCI_SETADDITIONALCARETSBLINK 2567 +#define SCI_GETADDITIONALCARETSBLINK 2568 +#define SCI_SETADDITIONALCARETSVISIBLE 2608 +#define SCI_GETADDITIONALCARETSVISIBLE 2609 +#define SCI_GETSELECTIONS 2570 +#define SCI_CLEARSELECTIONS 2571 +#define SCI_SETSELECTION 2572 +#define SCI_ADDSELECTION 2573 +#define SCI_SETMAINSELECTION 2574 +#define SCI_GETMAINSELECTION 2575 +#define SCI_SETSELECTIONNCARET 2576 +#define SCI_GETSELECTIONNCARET 2577 +#define SCI_SETSELECTIONNANCHOR 2578 +#define SCI_GETSELECTIONNANCHOR 2579 +#define SCI_SETSELECTIONNCARETVIRTUALSPACE 2580 +#define SCI_GETSELECTIONNCARETVIRTUALSPACE 2581 +#define SCI_SETSELECTIONNANCHORVIRTUALSPACE 2582 +#define SCI_GETSELECTIONNANCHORVIRTUALSPACE 2583 +#define SCI_SETSELECTIONNSTART 2584 +#define SCI_GETSELECTIONNSTART 2585 +#define SCI_SETSELECTIONNEND 2586 +#define SCI_GETSELECTIONNEND 2587 +#define SCI_SETRECTANGULARSELECTIONCARET 2588 +#define SCI_GETRECTANGULARSELECTIONCARET 2589 +#define SCI_SETRECTANGULARSELECTIONANCHOR 2590 +#define SCI_GETRECTANGULARSELECTIONANCHOR 2591 +#define SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE 2592 +#define SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE 2593 +#define SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE 2594 +#define SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE 2595 +#define SCVS_NONE 0 +#define SCVS_RECTANGULARSELECTION 1 +#define SCVS_USERACCESSIBLE 2 +#define SCI_SETVIRTUALSPACEOPTIONS 2596 +#define SCI_GETVIRTUALSPACEOPTIONS 2597 +#define SCI_SETRECTANGULARSELECTIONMODIFIER 2598 +#define SCI_GETRECTANGULARSELECTIONMODIFIER 2599 +#define SCI_SETADDITIONALSELFORE 2600 +#define SCI_SETADDITIONALSELBACK 2601 +#define SCI_SETADDITIONALSELALPHA 2602 +#define SCI_GETADDITIONALSELALPHA 2603 +#define SCI_SETADDITIONALCARETFORE 2604 +#define SCI_GETADDITIONALCARETFORE 2605 +#define SCI_ROTATESELECTION 2606 +#define SCI_SWAPMAINANCHORCARET 2607 +#define SCI_CHANGELEXERSTATE 2617 +#define SCI_CONTRACTEDFOLDNEXT 2618 +#define SCI_VERTICALCENTRECARET 2619 +#define SCI_MOVESELECTEDLINESUP 2620 +#define SCI_MOVESELECTEDLINESDOWN 2621 +#define SCI_SETIDENTIFIER 2622 +#define SCI_GETIDENTIFIER 2623 +#define SCI_RGBAIMAGESETWIDTH 2624 +#define SCI_RGBAIMAGESETHEIGHT 2625 +#define SCI_MARKERDEFINERGBAIMAGE 2626 +#define SCI_REGISTERRGBAIMAGE 2627 +#define SCI_SCROLLTOSTART 2628 +#define SCI_SCROLLTOEND 2629 +#define SC_TECHNOLOGY_DEFAULT 0 +#define SC_TECHNOLOGY_DIRECTWRITE 1 +#define SCI_SETTECHNOLOGY 2630 +#define SCI_GETTECHNOLOGY 2631 +#define SCI_CREATELOADER 2632 +#define SCI_STARTRECORD 3001 +#define SCI_STOPRECORD 3002 +#define SCI_SETLEXER 4001 +#define SCI_GETLEXER 4002 +#define SCI_COLOURISE 4003 +#define SCI_SETPROPERTY 4004 +#define KEYWORDSET_MAX 8 +#define SCI_SETKEYWORDS 4005 +#define SCI_SETLEXERLANGUAGE 4006 +#define SCI_LOADLEXERLIBRARY 4007 +#define SCI_GETPROPERTY 4008 +#define SCI_GETPROPERTYEXPANDED 4009 +#define SCI_GETPROPERTYINT 4010 +#define SCI_GETSTYLEBITSNEEDED 4011 +#define SCI_GETLEXERLANGUAGE 4012 +#define SCI_PRIVATELEXERCALL 4013 +#define SCI_PROPERTYNAMES 4014 +#define SC_TYPE_BOOLEAN 0 +#define SC_TYPE_INTEGER 1 +#define SC_TYPE_STRING 2 +#define SCI_PROPERTYTYPE 4015 +#define SCI_DESCRIBEPROPERTY 4016 +#define SCI_DESCRIBEKEYWORDSETS 4017 +#define SC_MOD_INSERTTEXT 0x1 +#define SC_MOD_DELETETEXT 0x2 +#define SC_MOD_CHANGESTYLE 0x4 +#define SC_MOD_CHANGEFOLD 0x8 +#define SC_PERFORMED_USER 0x10 +#define SC_PERFORMED_UNDO 0x20 +#define SC_PERFORMED_REDO 0x40 +#define SC_MULTISTEPUNDOREDO 0x80 +#define SC_LASTSTEPINUNDOREDO 0x100 +#define SC_MOD_CHANGEMARKER 0x200 +#define SC_MOD_BEFOREINSERT 0x400 +#define SC_MOD_BEFOREDELETE 0x800 +#define SC_MULTILINEUNDOREDO 0x1000 +#define SC_STARTACTION 0x2000 +#define SC_MOD_CHANGEINDICATOR 0x4000 +#define SC_MOD_CHANGELINESTATE 0x8000 +#define SC_MOD_CHANGEMARGIN 0x10000 +#define SC_MOD_CHANGEANNOTATION 0x20000 +#define SC_MOD_CONTAINER 0x40000 +#define SC_MOD_LEXERSTATE 0x80000 +#define SC_MODEVENTMASKALL 0xFFFFF +#define SC_UPDATE_CONTENT 0x1 +#define SC_UPDATE_SELECTION 0x2 +#define SC_UPDATE_V_SCROLL 0x4 +#define SC_UPDATE_H_SCROLL 0x8 +#define SCEN_CHANGE 768 +#define SCEN_SETFOCUS 512 +#define SCEN_KILLFOCUS 256 +#define SCK_DOWN 300 +#define SCK_UP 301 +#define SCK_LEFT 302 +#define SCK_RIGHT 303 +#define SCK_HOME 304 +#define SCK_END 305 +#define SCK_PRIOR 306 +#define SCK_NEXT 307 +#define SCK_DELETE 308 +#define SCK_INSERT 309 +#define SCK_ESCAPE 7 +#define SCK_BACK 8 +#define SCK_TAB 9 +#define SCK_RETURN 13 +#define SCK_ADD 310 +#define SCK_SUBTRACT 311 +#define SCK_DIVIDE 312 +#define SCK_WIN 313 +#define SCK_RWIN 314 +#define SCK_MENU 315 +#define SCMOD_NORM 0 +#define SCMOD_SHIFT 1 +#define SCMOD_CTRL 2 +#define SCMOD_ALT 4 +#define SCMOD_SUPER 8 +#define SCMOD_META 16 +#define SCN_STYLENEEDED 2000 +#define SCN_CHARADDED 2001 +#define SCN_SAVEPOINTREACHED 2002 +#define SCN_SAVEPOINTLEFT 2003 +#define SCN_MODIFYATTEMPTRO 2004 +#define SCN_KEY 2005 +#define SCN_DOUBLECLICK 2006 +#define SCN_UPDATEUI 2007 +#define SCN_MODIFIED 2008 +#define SCN_MACRORECORD 2009 +#define SCN_MARGINCLICK 2010 +#define SCN_NEEDSHOWN 2011 +#define SCN_PAINTED 2013 +#define SCN_USERLISTSELECTION 2014 +#define SCN_URIDROPPED 2015 +#define SCN_DWELLSTART 2016 +#define SCN_DWELLEND 2017 +#define SCN_ZOOM 2018 +#define SCN_HOTSPOTCLICK 2019 +#define SCN_HOTSPOTDOUBLECLICK 2020 +#define SCN_CALLTIPCLICK 2021 +#define SCN_AUTOCSELECTION 2022 +#define SCN_INDICATORCLICK 2023 +#define SCN_INDICATORRELEASE 2024 +#define SCN_AUTOCCANCELLED 2025 +#define SCN_AUTOCCHARDELETED 2026 +#define SCN_HOTSPOTRELEASECLICK 2027 +/* --Autogenerated -- end of section automatically generated from Scintilla.iface */ + +/* These structures are defined to be exactly the same shape as the Win32 + * CHARRANGE, TEXTRANGE, FINDTEXTEX, FORMATRANGE, and NMHDR structs. + * So older code that treats Scintilla as a RichEdit will work. */ + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +struct Sci_CharacterRange { + long cpMin; + long cpMax; +}; + +struct Sci_TextRange { + struct Sci_CharacterRange chrg; + char *lpstrText; +}; + +struct Sci_TextToFind { + struct Sci_CharacterRange chrg; + char *lpstrText; + struct Sci_CharacterRange chrgText; +}; + +#define CharacterRange Sci_CharacterRange +#define TextRange Sci_TextRange +#define TextToFind Sci_TextToFind + +typedef void *Sci_SurfaceID; + +struct Sci_Rectangle { + int left; + int top; + int right; + int bottom; +}; + +/* This structure is used in printing and requires some of the graphics types + * from Platform.h. Not needed by most client code. */ + +struct Sci_RangeToFormat { + Sci_SurfaceID hdc; + Sci_SurfaceID hdcTarget; + struct Sci_Rectangle rc; + struct Sci_Rectangle rcPage; + struct Sci_CharacterRange chrg; +}; + +#define RangeToFormat Sci_RangeToFormat + +struct Sci_NotifyHeader { + /* Compatible with Windows NMHDR. + * hwndFrom is really an environment specific window handle or pointer + * but most clients of Scintilla.h do not have this type visible. */ + void *hwndFrom; + uptr_t idFrom; + unsigned int code; +}; + +#define NotifyHeader Sci_NotifyHeader + +struct SCNotification { + struct Sci_NotifyHeader nmhdr; + int position; + /* SCN_STYLENEEDED, SCN_DOUBLECLICK, SCN_MODIFIED, SCN_MARGINCLICK, */ + /* SCN_NEEDSHOWN, SCN_DWELLSTART, SCN_DWELLEND, SCN_CALLTIPCLICK, */ + /* SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, SCN_HOTSPOTRELEASECLICK, */ + /* SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */ + /* SCN_USERLISTSELECTION, SCN_AUTOCSELECTION */ + + int ch; /* SCN_CHARADDED, SCN_KEY */ + int modifiers; + /* SCN_KEY, SCN_DOUBLECLICK, SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, */ + /* SCN_HOTSPOTRELEASECLICK, SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */ + + int modificationType; /* SCN_MODIFIED */ + const char *text; + /* SCN_MODIFIED, SCN_USERLISTSELECTION, SCN_AUTOCSELECTION, SCN_URIDROPPED */ + + int length; /* SCN_MODIFIED */ + int linesAdded; /* SCN_MODIFIED */ + int message; /* SCN_MACRORECORD */ + uptr_t wParam; /* SCN_MACRORECORD */ + sptr_t lParam; /* SCN_MACRORECORD */ + int line; /* SCN_MODIFIED */ + int foldLevelNow; /* SCN_MODIFIED */ + int foldLevelPrev; /* SCN_MODIFIED */ + int margin; /* SCN_MARGINCLICK */ + int listType; /* SCN_USERLISTSELECTION */ + int x; /* SCN_DWELLSTART, SCN_DWELLEND */ + int y; /* SCN_DWELLSTART, SCN_DWELLEND */ + int token; /* SCN_MODIFIED with SC_MOD_CONTAINER */ + int annotationLinesAdded; /* SCN_MODIFIED with SC_MOD_CHANGEANNOTATION */ + int updated; /* SCN_UPDATEUI */ +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#ifdef INCLUDE_DEPRECATED_FEATURES + +#define SC_CP_DBCS 1 +#define SCI_SETUSEPALETTE 2039 +#define SCI_GETUSEPALETTE 2139 + +#endif + +#endif diff --git a/scintilla/include/Scintilla.iface b/ThirdLibs/scintilla/include/Scintilla.iface similarity index 96% rename from scintilla/include/Scintilla.iface rename to ThirdLibs/scintilla/include/Scintilla.iface index ca033047..f70266ea 100644 --- a/scintilla/include/Scintilla.iface +++ b/ThirdLibs/scintilla/include/Scintilla.iface @@ -1,4111 +1,4111 @@ -## First line may be used for shbang - -## This file defines the interface to Scintilla - -## Copyright 2000-2003 by Neil Hodgson -## The License.txt file describes the conditions under which this software may be distributed. - -## A line starting with ## is a pure comment and should be stripped by readers. -## A line starting with #! is for future shbang use -## A line starting with # followed by a space is a documentation comment and refers -## to the next feature definition. - -## Each feature is defined by a line starting with fun, get, set, val or evt. -## cat -> start a category -## fun -> a function -## get -> a property get function -## set -> a property set function -## val -> definition of a constant -## evt -> an event -## enu -> associate an enumeration with a set of vals with a prefix -## lex -> associate a lexer with the lexical classes it produces -## -## All other feature names should be ignored. They may be defined in the future. -## A property may have a set function, a get function or both. Each will have -## "Get" or "Set" in their names and the corresponding name will have the obvious switch. -## A property may be subscripted, in which case the first parameter is the subscript. -## fun, get, and set features have a strict syntax: -## [=,) -## where stands for white space. -## param may be empty (null value) or is [=] -## Additional white space is allowed between elements. -## The syntax for evt is [=[,]*]) -## Feature names that contain an underscore are defined by Windows, so in these -## cases, using the Windows definition is preferred where available. -## The feature numbers are stable so features will not be renumbered. -## Features may be removed but they will go through a period of deprecation -## before removal which is signalled by moving them into the Deprecated category. -## -## enu has the syntax enu=[]* where all the val -## features in this file starting with a given are considered part of the -## enumeration. -## -## lex has the syntax lex=[]* -## where name is a reasonably capitalised (Python, XML) identifier or UI name, -## lexerVal is the val used to specify the lexer, and the list of prefixes is similar -## to enu. The name may not be the same as that used within the lexer so the lexerVal -## should be used to tie these entities together. - -## Types: -## void -## int -## bool -> integer, 1=true, 0=false -## position -> integer position in a document -## colour -> colour integer containing red, green and blue bytes. -## string -> pointer to const character -## stringresult -> pointer to character, NULL-> return size of result -## cells -> pointer to array of cells, each cell containing a style byte and character byte -## textrange -> range of a min and a max position with an output string -## findtext -> searchrange, text -> foundposition -## keymod -> integer containing key in low half and modifiers in high half -## formatrange -## Types no longer used: -## findtextex -> searchrange -## charrange -> range of a min and a max position -## charrangeresult -> like charrange, but output param -## countedstring -## point -> x,y -## pointresult -> like point, but output param -## rectangle -> left,top,right,bottom -## Client code should ignore definitions containing types it does not understand, except -## for possibly #defining the constants - -## Line numbers and positions start at 0. -## String arguments may contain NUL ('\0') characters where the calls provide a length -## argument and retrieve NUL characters. All retrieved strings except for those retrieved -## by GetLine also have a NUL appended but client code should calculate the size that -## will be returned rather than relying upon the NUL whenever possible. Allow for the -## extra NUL character when allocating buffers. The size to allocate for a stringresult -## can be determined by calling with a NULL (0) pointer. - -cat Basics - -################################################ -## For Scintilla.h -val INVALID_POSITION=-1 -# Define start of Scintilla messages to be greater than all Windows edit (EM_*) messages -# as many EM_ messages can be used although that use is deprecated. -val SCI_START=2000 -val SCI_OPTIONAL_START=3000 -val SCI_LEXER_START=4000 - -# Add text to the document at current position. -fun void AddText=2001(int length, string text) - -# Add array of cells to document. -fun void AddStyledText=2002(int length, cells c) - -# Insert string at a position. -fun void InsertText=2003(position pos, string text) - -# Delete all text in the document. -fun void ClearAll=2004(,) - -# Set all style bytes to 0, remove all folding information. -fun void ClearDocumentStyle=2005(,) - -# Returns the number of bytes in the document. -get int GetLength=2006(,) - -# Returns the character byte at the position. -get int GetCharAt=2007(position pos,) - -# Returns the position of the caret. -get position GetCurrentPos=2008(,) - -# Returns the position of the opposite end of the selection to the caret. -get position GetAnchor=2009(,) - -# Returns the style byte at the position. -get int GetStyleAt=2010(position pos,) - -# Redoes the next action on the undo history. -fun void Redo=2011(,) - -# Choose between collecting actions into the undo -# history and discarding them. -set void SetUndoCollection=2012(bool collectUndo,) - -# Select all the text in the document. -fun void SelectAll=2013(,) - -# Remember the current position in the undo history as the position -# at which the document was saved. -fun void SetSavePoint=2014(,) - -# Retrieve a buffer of cells. -# Returns the number of bytes in the buffer not including terminating NULs. -fun int GetStyledText=2015(, textrange tr) - -# Are there any redoable actions in the undo history? -fun bool CanRedo=2016(,) - -# Retrieve the line number at which a particular marker is located. -fun int MarkerLineFromHandle=2017(int handle,) - -# Delete a marker. -fun void MarkerDeleteHandle=2018(int handle,) - -# Is undo history being collected? -get bool GetUndoCollection=2019(,) - -enu WhiteSpace=SCWS_ -val SCWS_INVISIBLE=0 -val SCWS_VISIBLEALWAYS=1 -val SCWS_VISIBLEAFTERINDENT=2 - -# Are white space characters currently visible? -# Returns one of SCWS_* constants. -get int GetViewWS=2020(,) - -# Make white space characters invisible, always visible or visible outside indentation. -set void SetViewWS=2021(int viewWS,) - -# Find the position from a point within the window. -fun position PositionFromPoint=2022(int x, int y) - -# Find the position from a point within the window but return -# INVALID_POSITION if not close to text. -fun position PositionFromPointClose=2023(int x, int y) - -# Set caret to start of a line and ensure it is visible. -fun void GotoLine=2024(int line,) - -# Set caret to a position and ensure it is visible. -fun void GotoPos=2025(position pos,) - -# Set the selection anchor to a position. The anchor is the opposite -# end of the selection from the caret. -set void SetAnchor=2026(position posAnchor,) - -# Retrieve the text of the line containing the caret. -# Returns the index of the caret on the line. -fun int GetCurLine=2027(int length, stringresult text) - -# Retrieve the position of the last correctly styled character. -get position GetEndStyled=2028(,) - -enu EndOfLine=SC_EOL_ -val SC_EOL_CRLF=0 -val SC_EOL_CR=1 -val SC_EOL_LF=2 - -# Convert all line endings in the document to one mode. -fun void ConvertEOLs=2029(int eolMode,) - -# Retrieve the current end of line mode - one of CRLF, CR, or LF. -get int GetEOLMode=2030(,) - -# Set the current end of line mode. -set void SetEOLMode=2031(int eolMode,) - -# Set the current styling position to pos and the styling mask to mask. -# The styling mask can be used to protect some bits in each styling byte from modification. -fun void StartStyling=2032(position pos, int mask) - -# Change style from current styling position for length characters to a style -# and move the current styling position to after this newly styled segment. -fun void SetStyling=2033(int length, int style) - -# Is drawing done first into a buffer or direct to the screen? -get bool GetBufferedDraw=2034(,) - -# If drawing is buffered then each line of text is drawn into a bitmap buffer -# before drawing it to the screen to avoid flicker. -set void SetBufferedDraw=2035(bool buffered,) - -# Change the visible size of a tab to be a multiple of the width of a space character. -set void SetTabWidth=2036(int tabWidth,) - -# Retrieve the visible size of a tab. -get int GetTabWidth=2121(,) - -# The SC_CP_UTF8 value can be used to enter Unicode mode. -# This is the same value as CP_UTF8 in Windows -val SC_CP_UTF8=65001 - -# Set the code page used to interpret the bytes of the document as characters. -# The SC_CP_UTF8 value can be used to enter Unicode mode. -set void SetCodePage=2037(int codePage,) - -enu MarkerSymbol=SC_MARK_ -val MARKER_MAX=31 -val SC_MARK_CIRCLE=0 -val SC_MARK_ROUNDRECT=1 -val SC_MARK_ARROW=2 -val SC_MARK_SMALLRECT=3 -val SC_MARK_SHORTARROW=4 -val SC_MARK_EMPTY=5 -val SC_MARK_ARROWDOWN=6 -val SC_MARK_MINUS=7 -val SC_MARK_PLUS=8 - -# Shapes used for outlining column. -val SC_MARK_VLINE=9 -val SC_MARK_LCORNER=10 -val SC_MARK_TCORNER=11 -val SC_MARK_BOXPLUS=12 -val SC_MARK_BOXPLUSCONNECTED=13 -val SC_MARK_BOXMINUS=14 -val SC_MARK_BOXMINUSCONNECTED=15 -val SC_MARK_LCORNERCURVE=16 -val SC_MARK_TCORNERCURVE=17 -val SC_MARK_CIRCLEPLUS=18 -val SC_MARK_CIRCLEPLUSCONNECTED=19 -val SC_MARK_CIRCLEMINUS=20 -val SC_MARK_CIRCLEMINUSCONNECTED=21 - -# Invisible mark that only sets the line background colour. -val SC_MARK_BACKGROUND=22 -val SC_MARK_DOTDOTDOT=23 -val SC_MARK_ARROWS=24 -val SC_MARK_PIXMAP=25 -val SC_MARK_FULLRECT=26 -val SC_MARK_LEFTRECT=27 -val SC_MARK_AVAILABLE=28 -val SC_MARK_UNDERLINE=29 -val SC_MARK_RGBAIMAGE=30 - -val SC_MARK_CHARACTER=10000 - -enu MarkerOutline=SC_MARKNUM_ -# Markers used for outlining column. -val SC_MARKNUM_FOLDEREND=25 -val SC_MARKNUM_FOLDEROPENMID=26 -val SC_MARKNUM_FOLDERMIDTAIL=27 -val SC_MARKNUM_FOLDERTAIL=28 -val SC_MARKNUM_FOLDERSUB=29 -val SC_MARKNUM_FOLDER=30 -val SC_MARKNUM_FOLDEROPEN=31 - -val SC_MASK_FOLDERS=0xFE000000 - -# Set the symbol used for a particular marker number. -fun void MarkerDefine=2040(int markerNumber, int markerSymbol) - -# Set the foreground colour used for a particular marker number. -fun void MarkerSetFore=2041(int markerNumber, colour fore) - -# Set the background colour used for a particular marker number. -fun void MarkerSetBack=2042(int markerNumber, colour back) - -# Set the background colour used for a particular marker number when its folding block is selected. -fun void MarkerSetBackSelected=2292(int markerNumber, colour back) - -# Enable/disable highlight for current folding bloc (smallest one that contains the caret) -fun void MarkerEnableHighlight=2293(bool enabled,) - -# Add a marker to a line, returning an ID which can be used to find or delete the marker. -fun int MarkerAdd=2043(int line, int markerNumber) - -# Delete a marker from a line. -fun void MarkerDelete=2044(int line, int markerNumber) - -# Delete all markers with a particular number from all lines. -fun void MarkerDeleteAll=2045(int markerNumber,) - -# Get a bit mask of all the markers set on a line. -fun int MarkerGet=2046(int line,) - -# Find the next line at or after lineStart that includes a marker in mask. -# Return -1 when no more lines. -fun int MarkerNext=2047(int lineStart, int markerMask) - -# Find the previous line before lineStart that includes a marker in mask. -fun int MarkerPrevious=2048(int lineStart, int markerMask) - -# Define a marker from a pixmap. -fun void MarkerDefinePixmap=2049(int markerNumber, string pixmap) - -# Add a set of markers to a line. -fun void MarkerAddSet=2466(int line, int set) - -# Set the alpha used for a marker that is drawn in the text area, not the margin. -fun void MarkerSetAlpha=2476(int markerNumber, int alpha) - -enu MarginType=SC_MARGIN_ -val SC_MARGIN_SYMBOL=0 -val SC_MARGIN_NUMBER=1 -val SC_MARGIN_BACK=2 -val SC_MARGIN_FORE=3 -val SC_MARGIN_TEXT=4 -val SC_MARGIN_RTEXT=5 - -# Set a margin to be either numeric or symbolic. -set void SetMarginTypeN=2240(int margin, int marginType) - -# Retrieve the type of a margin. -get int GetMarginTypeN=2241(int margin,) - -# Set the width of a margin to a width expressed in pixels. -set void SetMarginWidthN=2242(int margin, int pixelWidth) - -# Retrieve the width of a margin in pixels. -get int GetMarginWidthN=2243(int margin,) - -# Set a mask that determines which markers are displayed in a margin. -set void SetMarginMaskN=2244(int margin, int mask) - -# Retrieve the marker mask of a margin. -get int GetMarginMaskN=2245(int margin,) - -# Make a margin sensitive or insensitive to mouse clicks. -set void SetMarginSensitiveN=2246(int margin, bool sensitive) - -# Retrieve the mouse click sensitivity of a margin. -get bool GetMarginSensitiveN=2247(int margin,) - -# Set the cursor shown when the mouse is inside a margin. -set void SetMarginCursorN=2248(int margin, int cursor) - -# Retrieve the cursor shown in a margin. -get int GetMarginCursorN=2249(int margin,) - -# Styles in range 32..38 are predefined for parts of the UI and are not used as normal styles. -# Style 39 is for future use. -enu StylesCommon=STYLE_ -val STYLE_DEFAULT=32 -val STYLE_LINENUMBER=33 -val STYLE_BRACELIGHT=34 -val STYLE_BRACEBAD=35 -val STYLE_CONTROLCHAR=36 -val STYLE_INDENTGUIDE=37 -val STYLE_CALLTIP=38 -val STYLE_LASTPREDEFINED=39 -val STYLE_MAX=255 - -# Character set identifiers are used in StyleSetCharacterSet. -# The values are the same as the Windows *_CHARSET values. -enu CharacterSet=SC_CHARSET_ -val SC_CHARSET_ANSI=0 -val SC_CHARSET_DEFAULT=1 -val SC_CHARSET_BALTIC=186 -val SC_CHARSET_CHINESEBIG5=136 -val SC_CHARSET_EASTEUROPE=238 -val SC_CHARSET_GB2312=134 -val SC_CHARSET_GREEK=161 -val SC_CHARSET_HANGUL=129 -val SC_CHARSET_MAC=77 -val SC_CHARSET_OEM=255 -val SC_CHARSET_RUSSIAN=204 -val SC_CHARSET_CYRILLIC=1251 -val SC_CHARSET_SHIFTJIS=128 -val SC_CHARSET_SYMBOL=2 -val SC_CHARSET_TURKISH=162 -val SC_CHARSET_JOHAB=130 -val SC_CHARSET_HEBREW=177 -val SC_CHARSET_ARABIC=178 -val SC_CHARSET_VIETNAMESE=163 -val SC_CHARSET_THAI=222 -val SC_CHARSET_8859_15=1000 - -# Clear all the styles and make equivalent to the global default style. -set void StyleClearAll=2050(,) - -# Set the foreground colour of a style. -set void StyleSetFore=2051(int style, colour fore) - -# Set the background colour of a style. -set void StyleSetBack=2052(int style, colour back) - -# Set a style to be bold or not. -set void StyleSetBold=2053(int style, bool bold) - -# Set a style to be italic or not. -set void StyleSetItalic=2054(int style, bool italic) - -# Set the size of characters of a style. -set void StyleSetSize=2055(int style, int sizePoints) - -# Set the font of a style. -set void StyleSetFont=2056(int style, string fontName) - -# Set a style to have its end of line filled or not. -set void StyleSetEOLFilled=2057(int style, bool filled) - -# Reset the default style to its state at startup -fun void StyleResetDefault=2058(,) - -# Set a style to be underlined or not. -set void StyleSetUnderline=2059(int style, bool underline) - -enu CaseVisible=SC_CASE_ -val SC_CASE_MIXED=0 -val SC_CASE_UPPER=1 -val SC_CASE_LOWER=2 - -# Get the foreground colour of a style. -get colour StyleGetFore=2481(int style,) - -# Get the background colour of a style. -get colour StyleGetBack=2482(int style,) - -# Get is a style bold or not. -get bool StyleGetBold=2483(int style,) - -# Get is a style italic or not. -get bool StyleGetItalic=2484(int style,) - -# Get the size of characters of a style. -get int StyleGetSize=2485(int style,) - -# Get the font of a style. -# Returns the length of the fontName -fun int StyleGetFont=2486(int style, stringresult fontName) - -# Get is a style to have its end of line filled or not. -get bool StyleGetEOLFilled=2487(int style,) - -# Get is a style underlined or not. -get bool StyleGetUnderline=2488(int style,) - -# Get is a style mixed case, or to force upper or lower case. -get int StyleGetCase=2489(int style,) - -# Get the character get of the font in a style. -get int StyleGetCharacterSet=2490(int style,) - -# Get is a style visible or not. -get bool StyleGetVisible=2491(int style,) - -# Get is a style changeable or not (read only). -# Experimental feature, currently buggy. -get bool StyleGetChangeable=2492(int style,) - -# Get is a style a hotspot or not. -get bool StyleGetHotSpot=2493(int style,) - -# Set a style to be mixed case, or to force upper or lower case. -set void StyleSetCase=2060(int style, int caseForce) - -val SC_FONT_SIZE_MULTIPLIER=100 - -# Set the size of characters of a style. Size is in points multiplied by 100. -set void StyleSetSizeFractional=2061(int style, int caseForce) - -# Get the size of characters of a style in points multiplied by 100 -get int StyleGetSizeFractional=2062(int style,) - -enu FontWeight=SC_WEIGHT_ -val SC_WEIGHT_NORMAL=400 -val SC_WEIGHT_SEMIBOLD=600 -val SC_WEIGHT_BOLD=700 - -# Set the weight of characters of a style. -set void StyleSetWeight=2063(int style, int weight) - -# Get the weight of characters of a style. -get int StyleGetWeight=2064(int style,) - -# Set the character set of the font in a style. -set void StyleSetCharacterSet=2066(int style, int characterSet) - -# Set a style to be a hotspot or not. -set void StyleSetHotSpot=2409(int style, bool hotspot) - -# Set the foreground colour of the main and additional selections and whether to use this setting. -fun void SetSelFore=2067(bool useSetting, colour fore) - -# Set the background colour of the main and additional selections and whether to use this setting. -fun void SetSelBack=2068(bool useSetting, colour back) - -# Get the alpha of the selection. -get int GetSelAlpha=2477(,) - -# Set the alpha of the selection. -set void SetSelAlpha=2478(int alpha,) - -# Is the selection end of line filled? -get bool GetSelEOLFilled=2479(,) - -# Set the selection to have its end of line filled or not. -set void SetSelEOLFilled=2480(bool filled,) - -# Set the foreground colour of the caret. -set void SetCaretFore=2069(colour fore,) - -# When key+modifier combination km is pressed perform msg. -fun void AssignCmdKey=2070(keymod km, int msg) - -# When key+modifier combination km is pressed do nothing. -fun void ClearCmdKey=2071(keymod km,) - -# Drop all key mappings. -fun void ClearAllCmdKeys=2072(,) - -# Set the styles for a segment of the document. -fun void SetStylingEx=2073(int length, string styles) - -# Set a style to be visible or not. -set void StyleSetVisible=2074(int style, bool visible) - -# Get the time in milliseconds that the caret is on and off. -get int GetCaretPeriod=2075(,) - -# Get the time in milliseconds that the caret is on and off. 0 = steady on. -set void SetCaretPeriod=2076(int periodMilliseconds,) - -# Set the set of characters making up words for when moving or selecting by word. -# First sets defaults like SetCharsDefault. -set void SetWordChars=2077(, string characters) - -# Start a sequence of actions that is undone and redone as a unit. -# May be nested. -fun void BeginUndoAction=2078(,) - -# End a sequence of actions that is undone and redone as a unit. -fun void EndUndoAction=2079(,) - -# Indicator style enumeration and some constants -enu IndicatorStyle=INDIC_ -val INDIC_PLAIN=0 -val INDIC_SQUIGGLE=1 -val INDIC_TT=2 -val INDIC_DIAGONAL=3 -val INDIC_STRIKE=4 -val INDIC_HIDDEN=5 -val INDIC_BOX=6 -val INDIC_ROUNDBOX=7 -val INDIC_STRAIGHTBOX=8 -val INDIC_DASH=9 -val INDIC_DOTS=10 -val INDIC_SQUIGGLELOW=11 -val INDIC_DOTBOX=12 -val INDIC_MAX=31 -val INDIC_CONTAINER=8 -val INDIC0_MASK=0x20 -val INDIC1_MASK=0x40 -val INDIC2_MASK=0x80 -val INDICS_MASK=0xE0 - -# Set an indicator to plain, squiggle or TT. -set void IndicSetStyle=2080(int indic, int style) - -# Retrieve the style of an indicator. -get int IndicGetStyle=2081(int indic,) - -# Set the foreground colour of an indicator. -set void IndicSetFore=2082(int indic, colour fore) - -# Retrieve the foreground colour of an indicator. -get colour IndicGetFore=2083(int indic,) - -# Set an indicator to draw under text or over(default). -set void IndicSetUnder=2510(int indic, bool under) - -# Retrieve whether indicator drawn under or over text. -get bool IndicGetUnder=2511(int indic,) - -# Set the foreground colour of all whitespace and whether to use this setting. -fun void SetWhitespaceFore=2084(bool useSetting, colour fore) - -# Set the background colour of all whitespace and whether to use this setting. -fun void SetWhitespaceBack=2085(bool useSetting, colour back) - -# Set the size of the dots used to mark space characters. -set void SetWhitespaceSize=2086(int size,) - -# Get the size of the dots used to mark space characters. -get int GetWhitespaceSize=2087(,) - -# Divide each styling byte into lexical class bits (default: 5) and indicator -# bits (default: 3). If a lexer requires more than 32 lexical states, then this -# is used to expand the possible states. -set void SetStyleBits=2090(int bits,) - -# Retrieve number of bits in style bytes used to hold the lexical state. -get int GetStyleBits=2091(,) - -# Used to hold extra styling information for each line. -set void SetLineState=2092(int line, int state) - -# Retrieve the extra styling information for a line. -get int GetLineState=2093(int line,) - -# Retrieve the last line number that has line state. -get int GetMaxLineState=2094(,) - -# Is the background of the line containing the caret in a different colour? -get bool GetCaretLineVisible=2095(,) - -# Display the background of the line containing the caret in a different colour. -set void SetCaretLineVisible=2096(bool show,) - -# Get the colour of the background of the line containing the caret. -get colour GetCaretLineBack=2097(,) - -# Set the colour of the background of the line containing the caret. -set void SetCaretLineBack=2098(colour back,) - -# Set a style to be changeable or not (read only). -# Experimental feature, currently buggy. -set void StyleSetChangeable=2099(int style, bool changeable) - -# Display a auto-completion list. -# The lenEntered parameter indicates how many characters before -# the caret should be used to provide context. -fun void AutoCShow=2100(int lenEntered, string itemList) - -# Remove the auto-completion list from the screen. -fun void AutoCCancel=2101(,) - -# Is there an auto-completion list visible? -fun bool AutoCActive=2102(,) - -# Retrieve the position of the caret when the auto-completion list was displayed. -fun position AutoCPosStart=2103(,) - -# User has selected an item so remove the list and insert the selection. -fun void AutoCComplete=2104(,) - -# Define a set of character that when typed cancel the auto-completion list. -fun void AutoCStops=2105(, string characterSet) - -# Change the separator character in the string setting up an auto-completion list. -# Default is space but can be changed if items contain space. -set void AutoCSetSeparator=2106(int separatorCharacter,) - -# Retrieve the auto-completion list separator character. -get int AutoCGetSeparator=2107(,) - -# Select the item in the auto-completion list that starts with a string. -fun void AutoCSelect=2108(, string text) - -# Should the auto-completion list be cancelled if the user backspaces to a -# position before where the box was created. -set void AutoCSetCancelAtStart=2110(bool cancel,) - -# Retrieve whether auto-completion cancelled by backspacing before start. -get bool AutoCGetCancelAtStart=2111(,) - -# Define a set of characters that when typed will cause the autocompletion to -# choose the selected item. -set void AutoCSetFillUps=2112(, string characterSet) - -# Should a single item auto-completion list automatically choose the item. -set void AutoCSetChooseSingle=2113(bool chooseSingle,) - -# Retrieve whether a single item auto-completion list automatically choose the item. -get bool AutoCGetChooseSingle=2114(,) - -# Set whether case is significant when performing auto-completion searches. -set void AutoCSetIgnoreCase=2115(bool ignoreCase,) - -# Retrieve state of ignore case flag. -get bool AutoCGetIgnoreCase=2116(,) - -# Display a list of strings and send notification when user chooses one. -fun void UserListShow=2117(int listType, string itemList) - -# Set whether or not autocompletion is hidden automatically when nothing matches. -set void AutoCSetAutoHide=2118(bool autoHide,) - -# Retrieve whether or not autocompletion is hidden automatically when nothing matches. -get bool AutoCGetAutoHide=2119(,) - -# Set whether or not autocompletion deletes any word characters -# after the inserted text upon completion. -set void AutoCSetDropRestOfWord=2270(bool dropRestOfWord,) - -# Retrieve whether or not autocompletion deletes any word characters -# after the inserted text upon completion. -get bool AutoCGetDropRestOfWord=2271(,) - -# Register an XPM image for use in autocompletion lists. -fun void RegisterImage=2405(int type, string xpmData) - -# Clear all the registered XPM images. -fun void ClearRegisteredImages=2408(,) - -# Retrieve the auto-completion list type-separator character. -get int AutoCGetTypeSeparator=2285(,) - -# Change the type-separator character in the string setting up an auto-completion list. -# Default is '?' but can be changed if items contain '?'. -set void AutoCSetTypeSeparator=2286(int separatorCharacter,) - -# Set the maximum width, in characters, of auto-completion and user lists. -# Set to 0 to autosize to fit longest item, which is the default. -set void AutoCSetMaxWidth=2208(int characterCount,) - -# Get the maximum width, in characters, of auto-completion and user lists. -get int AutoCGetMaxWidth=2209(,) - -# Set the maximum height, in rows, of auto-completion and user lists. -# The default is 5 rows. -set void AutoCSetMaxHeight=2210(int rowCount,) - -# Set the maximum height, in rows, of auto-completion and user lists. -get int AutoCGetMaxHeight=2211(,) - -# Set the number of spaces used for one level of indentation. -set void SetIndent=2122(int indentSize,) - -# Retrieve indentation size. -get int GetIndent=2123(,) - -# Indentation will only use space characters if useTabs is false, otherwise -# it will use a combination of tabs and spaces. -set void SetUseTabs=2124(bool useTabs,) - -# Retrieve whether tabs will be used in indentation. -get bool GetUseTabs=2125(,) - -# Change the indentation of a line to a number of columns. -set void SetLineIndentation=2126(int line, int indentSize) - -# Retrieve the number of columns that a line is indented. -get int GetLineIndentation=2127(int line,) - -# Retrieve the position before the first non indentation character on a line. -get position GetLineIndentPosition=2128(int line,) - -# Retrieve the column number of a position, taking tab width into account. -get int GetColumn=2129(position pos,) - -# Count characters between two positions. -fun int CountCharacters=2633(int startPos, int endPos) - -# Show or hide the horizontal scroll bar. -set void SetHScrollBar=2130(bool show,) -# Is the horizontal scroll bar visible? -get bool GetHScrollBar=2131(,) - -enu IndentView=SC_IV_ -val SC_IV_NONE=0 -val SC_IV_REAL=1 -val SC_IV_LOOKFORWARD=2 -val SC_IV_LOOKBOTH=3 - -# Show or hide indentation guides. -set void SetIndentationGuides=2132(int indentView,) - -# Are the indentation guides visible? -get int GetIndentationGuides=2133(,) - -# Set the highlighted indentation guide column. -# 0 = no highlighted guide. -set void SetHighlightGuide=2134(int column,) - -# Get the highlighted indentation guide column. -get int GetHighlightGuide=2135(,) - -# Get the position after the last visible characters on a line. -get int GetLineEndPosition=2136(int line,) - -# Get the code page used to interpret the bytes of the document as characters. -get int GetCodePage=2137(,) - -# Get the foreground colour of the caret. -get colour GetCaretFore=2138(,) - -# In read-only mode? -get bool GetReadOnly=2140(,) - -# Sets the position of the caret. -set void SetCurrentPos=2141(position pos,) - -# Sets the position that starts the selection - this becomes the anchor. -set void SetSelectionStart=2142(position pos,) - -# Returns the position at the start of the selection. -get position GetSelectionStart=2143(,) - -# Sets the position that ends the selection - this becomes the currentPosition. -set void SetSelectionEnd=2144(position pos,) - -# Returns the position at the end of the selection. -get position GetSelectionEnd=2145(,) - -# Set caret to a position, while removing any existing selection. -fun void SetEmptySelection=2556(position pos,) - -# Sets the print magnification added to the point size of each style for printing. -set void SetPrintMagnification=2146(int magnification,) - -# Returns the print magnification. -get int GetPrintMagnification=2147(,) - -enu PrintOption=SC_PRINT_ -# PrintColourMode - use same colours as screen. -val SC_PRINT_NORMAL=0 -# PrintColourMode - invert the light value of each style for printing. -val SC_PRINT_INVERTLIGHT=1 -# PrintColourMode - force black text on white background for printing. -val SC_PRINT_BLACKONWHITE=2 -# PrintColourMode - text stays coloured, but all background is forced to be white for printing. -val SC_PRINT_COLOURONWHITE=3 -# PrintColourMode - only the default-background is forced to be white for printing. -val SC_PRINT_COLOURONWHITEDEFAULTBG=4 - -# Modify colours when printing for clearer printed text. -set void SetPrintColourMode=2148(int mode,) - -# Returns the print colour mode. -get int GetPrintColourMode=2149(,) - -enu FindOption=SCFIND_ -val SCFIND_WHOLEWORD=2 -val SCFIND_MATCHCASE=4 -val SCFIND_WORDSTART=0x00100000 -val SCFIND_REGEXP=0x00200000 -val SCFIND_POSIX=0x00400000 - -# Find some text in the document. -fun position FindText=2150(int flags, findtext ft) - -# On Windows, will draw the document into a display context such as a printer. -fun position FormatRange=2151(bool draw, formatrange fr) - -# Retrieve the display line at the top of the display. -get int GetFirstVisibleLine=2152(,) - -# Retrieve the contents of a line. -# Returns the length of the line. -fun int GetLine=2153(int line, stringresult text) - -# Returns the number of lines in the document. There is always at least one. -get int GetLineCount=2154(,) - -# Sets the size in pixels of the left margin. -set void SetMarginLeft=2155(, int pixelWidth) - -# Returns the size in pixels of the left margin. -get int GetMarginLeft=2156(,) - -# Sets the size in pixels of the right margin. -set void SetMarginRight=2157(, int pixelWidth) - -# Returns the size in pixels of the right margin. -get int GetMarginRight=2158(,) - -# Is the document different from when it was last saved? -get bool GetModify=2159(,) - -# Select a range of text. -fun void SetSel=2160(position start, position end) - -# Retrieve the selected text. -# Return the length of the text. -fun int GetSelText=2161(, stringresult text) - -# Retrieve a range of text. -# Return the length of the text. -fun int GetTextRange=2162(, textrange tr) - -# Draw the selection in normal style or with selection highlighted. -fun void HideSelection=2163(bool normal,) - -# Retrieve the x value of the point in the window where a position is displayed. -fun int PointXFromPosition=2164(, position pos) - -# Retrieve the y value of the point in the window where a position is displayed. -fun int PointYFromPosition=2165(, position pos) - -# Retrieve the line containing a position. -fun int LineFromPosition=2166(position pos,) - -# Retrieve the position at the start of a line. -fun position PositionFromLine=2167(int line,) - -# Scroll horizontally and vertically. -fun void LineScroll=2168(int columns, int lines) - -# Ensure the caret is visible. -fun void ScrollCaret=2169(,) - -# Replace the selected text with the argument text. -fun void ReplaceSel=2170(, string text) - -# Set to read only or read write. -set void SetReadOnly=2171(bool readOnly,) - -# Null operation. -fun void Null=2172(,) - -# Will a paste succeed? -fun bool CanPaste=2173(,) - -# Are there any undoable actions in the undo history? -fun bool CanUndo=2174(,) - -# Delete the undo history. -fun void EmptyUndoBuffer=2175(,) - -# Undo one action in the undo history. -fun void Undo=2176(,) - -# Cut the selection to the clipboard. -fun void Cut=2177(,) - -# Copy the selection to the clipboard. -fun void Copy=2178(,) - -# Paste the contents of the clipboard into the document replacing the selection. -fun void Paste=2179(,) - -# Clear the selection. -fun void Clear=2180(,) - -# Replace the contents of the document with the argument text. -fun void SetText=2181(, string text) - -# Retrieve all the text in the document. -# Returns number of characters retrieved. -fun int GetText=2182(int length, stringresult text) - -# Retrieve the number of characters in the document. -get int GetTextLength=2183(,) - -# Retrieve a pointer to a function that processes messages for this Scintilla. -get int GetDirectFunction=2184(,) - -# Retrieve a pointer value to use as the first argument when calling -# the function returned by GetDirectFunction. -get int GetDirectPointer=2185(,) - -# Set to overtype (true) or insert mode. -set void SetOvertype=2186(bool overtype,) - -# Returns true if overtype mode is active otherwise false is returned. -get bool GetOvertype=2187(,) - -# Set the width of the insert mode caret. -set void SetCaretWidth=2188(int pixelWidth,) - -# Returns the width of the insert mode caret. -get int GetCaretWidth=2189(,) - -# Sets the position that starts the target which is used for updating the -# document without affecting the scroll position. -set void SetTargetStart=2190(position pos,) - -# Get the position that starts the target. -get position GetTargetStart=2191(,) - -# Sets the position that ends the target which is used for updating the -# document without affecting the scroll position. -set void SetTargetEnd=2192(position pos,) - -# Get the position that ends the target. -get position GetTargetEnd=2193(,) - -# Replace the target text with the argument text. -# Text is counted so it can contain NULs. -# Returns the length of the replacement text. -fun int ReplaceTarget=2194(int length, string text) - -# Replace the target text with the argument text after \d processing. -# Text is counted so it can contain NULs. -# Looks for \d where d is between 1 and 9 and replaces these with the strings -# matched in the last search operation which were surrounded by \( and \). -# Returns the length of the replacement text including any change -# caused by processing the \d patterns. -fun int ReplaceTargetRE=2195(int length, string text) - -# Search for a counted string in the target and set the target to the found -# range. Text is counted so it can contain NULs. -# Returns length of range or -1 for failure in which case target is not moved. -fun int SearchInTarget=2197(int length, string text) - -# Set the search flags used by SearchInTarget. -set void SetSearchFlags=2198(int flags,) - -# Get the search flags used by SearchInTarget. -get int GetSearchFlags=2199(,) - -# Show a call tip containing a definition near position pos. -fun void CallTipShow=2200(position pos, string definition) - -# Remove the call tip from the screen. -fun void CallTipCancel=2201(,) - -# Is there an active call tip? -fun bool CallTipActive=2202(,) - -# Retrieve the position where the caret was before displaying the call tip. -fun position CallTipPosStart=2203(,) - -# Highlight a segment of the definition. -fun void CallTipSetHlt=2204(int start, int end) - -# Set the background colour for the call tip. -set void CallTipSetBack=2205(colour back,) - -# Set the foreground colour for the call tip. -set void CallTipSetFore=2206(colour fore,) - -# Set the foreground colour for the highlighted part of the call tip. -set void CallTipSetForeHlt=2207(colour fore,) - -# Enable use of STYLE_CALLTIP and set call tip tab size in pixels. -set void CallTipUseStyle=2212(int tabSize,) - -# Set position of calltip, above or below text. -set void CallTipSetPosition=2213(bool above,) - -# Find the display line of a document line taking hidden lines into account. -fun int VisibleFromDocLine=2220(int line,) - -# Find the document line of a display line taking hidden lines into account. -fun int DocLineFromVisible=2221(int lineDisplay,) - -# The number of display lines needed to wrap a document line -fun int WrapCount=2235(int line,) - -enu FoldLevel=SC_FOLDLEVEL -val SC_FOLDLEVELBASE=0x400 -val SC_FOLDLEVELWHITEFLAG=0x1000 -val SC_FOLDLEVELHEADERFLAG=0x2000 -val SC_FOLDLEVELNUMBERMASK=0x0FFF - -# Set the fold level of a line. -# This encodes an integer level along with flags indicating whether the -# line is a header and whether it is effectively white space. -set void SetFoldLevel=2222(int line, int level) - -# Retrieve the fold level of a line. -get int GetFoldLevel=2223(int line,) - -# Find the last child line of a header line. -get int GetLastChild=2224(int line, int level) - -# Find the parent line of a child line. -get int GetFoldParent=2225(int line,) - -# Make a range of lines visible. -fun void ShowLines=2226(int lineStart, int lineEnd) - -# Make a range of lines invisible. -fun void HideLines=2227(int lineStart, int lineEnd) - -# Is a line visible? -get bool GetLineVisible=2228(int line,) - -# Are all lines visible? -get bool GetAllLinesVisible=2236(,) - -# Show the children of a header line. -set void SetFoldExpanded=2229(int line, bool expanded) - -# Is a header line expanded? -get bool GetFoldExpanded=2230(int line,) - -# Switch a header line between expanded and contracted. -fun void ToggleFold=2231(int line,) - -# Ensure a particular line is visible by expanding any header line hiding it. -fun void EnsureVisible=2232(int line,) - -enu FoldFlag=SC_FOLDFLAG_ -val SC_FOLDFLAG_LINEBEFORE_EXPANDED=0x0002 -val SC_FOLDFLAG_LINEBEFORE_CONTRACTED=0x0004 -val SC_FOLDFLAG_LINEAFTER_EXPANDED=0x0008 -val SC_FOLDFLAG_LINEAFTER_CONTRACTED=0x0010 -val SC_FOLDFLAG_LEVELNUMBERS=0x0040 - -# Set some style options for folding. -fun void SetFoldFlags=2233(int flags,) - -# Ensure a particular line is visible by expanding any header line hiding it. -# Use the currently set visibility policy to determine which range to display. -fun void EnsureVisibleEnforcePolicy=2234(int line,) - -# Sets whether a tab pressed when caret is within indentation indents. -set void SetTabIndents=2260(bool tabIndents,) - -# Does a tab pressed when caret is within indentation indent? -get bool GetTabIndents=2261(,) - -# Sets whether a backspace pressed when caret is within indentation unindents. -set void SetBackSpaceUnIndents=2262(bool bsUnIndents,) - -# Does a backspace pressed when caret is within indentation unindent? -get bool GetBackSpaceUnIndents=2263(,) - -val SC_TIME_FOREVER=10000000 - -# Sets the time the mouse must sit still to generate a mouse dwell event. -set void SetMouseDwellTime=2264(int periodMilliseconds,) - -# Retrieve the time the mouse must sit still to generate a mouse dwell event. -get int GetMouseDwellTime=2265(,) - -# Get position of start of word. -fun int WordStartPosition=2266(position pos, bool onlyWordCharacters) - -# Get position of end of word. -fun int WordEndPosition=2267(position pos, bool onlyWordCharacters) - -enu Wrap=SC_WRAP_ -val SC_WRAP_NONE=0 -val SC_WRAP_WORD=1 -val SC_WRAP_CHAR=2 - -# Sets whether text is word wrapped. -set void SetWrapMode=2268(int mode,) - -# Retrieve whether text is word wrapped. -get int GetWrapMode=2269(,) - -enu WrapVisualFlag=SC_WRAPVISUALFLAG_ -val SC_WRAPVISUALFLAG_NONE=0x0000 -val SC_WRAPVISUALFLAG_END=0x0001 -val SC_WRAPVISUALFLAG_START=0x0002 - -# Set the display mode of visual flags for wrapped lines. -set void SetWrapVisualFlags=2460(int wrapVisualFlags,) - -# Retrive the display mode of visual flags for wrapped lines. -get int GetWrapVisualFlags=2461(,) - -enu WrapVisualLocation=SC_WRAPVISUALFLAGLOC_ -val SC_WRAPVISUALFLAGLOC_DEFAULT=0x0000 -val SC_WRAPVISUALFLAGLOC_END_BY_TEXT=0x0001 -val SC_WRAPVISUALFLAGLOC_START_BY_TEXT=0x0002 - -# Set the location of visual flags for wrapped lines. -set void SetWrapVisualFlagsLocation=2462(int wrapVisualFlagsLocation,) - -# Retrive the location of visual flags for wrapped lines. -get int GetWrapVisualFlagsLocation=2463(,) - -# Set the start indent for wrapped lines. -set void SetWrapStartIndent=2464(int indent,) - -# Retrive the start indent for wrapped lines. -get int GetWrapStartIndent=2465(,) - -enu WrapIndentMode=SC_WRAPINDENT_ -val SC_WRAPINDENT_FIXED=0 -val SC_WRAPINDENT_SAME=1 -val SC_WRAPINDENT_INDENT=2 - -# Sets how wrapped sublines are placed. Default is fixed. -set void SetWrapIndentMode=2472(int mode,) - -# Retrieve how wrapped sublines are placed. Default is fixed. -get int GetWrapIndentMode=2473(,) - -enu LineCache=SC_CACHE_ -val SC_CACHE_NONE=0 -val SC_CACHE_CARET=1 -val SC_CACHE_PAGE=2 -val SC_CACHE_DOCUMENT=3 - -# Sets the degree of caching of layout information. -set void SetLayoutCache=2272(int mode,) - -# Retrieve the degree of caching of layout information. -get int GetLayoutCache=2273(,) - -# Sets the document width assumed for scrolling. -set void SetScrollWidth=2274(int pixelWidth,) - -# Retrieve the document width assumed for scrolling. -get int GetScrollWidth=2275(,) - -# Sets whether the maximum width line displayed is used to set scroll width. -set void SetScrollWidthTracking=2516(bool tracking,) - -# Retrieve whether the scroll width tracks wide lines. -get bool GetScrollWidthTracking=2517(,) - -# Measure the pixel width of some text in a particular style. -# NUL terminated text argument. -# Does not handle tab or control characters. -fun int TextWidth=2276(int style, string text) - -# Sets the scroll range so that maximum scroll position has -# the last line at the bottom of the view (default). -# Setting this to false allows scrolling one page below the last line. -set void SetEndAtLastLine=2277(bool endAtLastLine,) - -# Retrieve whether the maximum scroll position has the last -# line at the bottom of the view. -get bool GetEndAtLastLine=2278(,) - -# Retrieve the height of a particular line of text in pixels. -fun int TextHeight=2279(int line,) - -# Show or hide the vertical scroll bar. -set void SetVScrollBar=2280(bool show,) - -# Is the vertical scroll bar visible? -get bool GetVScrollBar=2281(,) - -# Append a string to the end of the document without changing the selection. -fun void AppendText=2282(int length, string text) - -# Is drawing done in two phases with backgrounds drawn before faoregrounds? -get bool GetTwoPhaseDraw=2283(,) - -# In twoPhaseDraw mode, drawing is performed in two phases, first the background -# and then the foreground. This avoids chopping off characters that overlap the next run. -set void SetTwoPhaseDraw=2284(bool twoPhase,) - -# Control font anti-aliasing. - -enu FontQuality=SC_EFF_ -val SC_EFF_QUALITY_MASK=0xF -val SC_EFF_QUALITY_DEFAULT=0 -val SC_EFF_QUALITY_NON_ANTIALIASED=1 -val SC_EFF_QUALITY_ANTIALIASED=2 -val SC_EFF_QUALITY_LCD_OPTIMIZED=3 - -# Choose the quality level for text from the FontQuality enumeration. -set void SetFontQuality=2611(int fontQuality,) - -# Retrieve the quality level for text. -get int GetFontQuality=2612(,) - -# Scroll so that a display line is at the top of the display. -set void SetFirstVisibleLine=2613(int lineDisplay,) - -enu MultiPaste=SC_MULTIPASTE_ -val SC_MULTIPASTE_ONCE=0 -val SC_MULTIPASTE_EACH=1 - -# Change the effect of pasting when there are multiple selections. -set void SetMultiPaste=2614(int multiPaste,) - -# Retrieve the effect of pasting when there are multiple selections.. -get int GetMultiPaste=2615(,) - -# Retrieve the value of a tag from a regular expression search. -fun int GetTag=2616(int tagNumber, stringresult tagValue) - -# Make the target range start and end be the same as the selection range start and end. -fun void TargetFromSelection=2287(,) - -# Join the lines in the target. -fun void LinesJoin=2288(,) - -# Split the lines in the target into lines that are less wide than pixelWidth -# where possible. -fun void LinesSplit=2289(int pixelWidth,) - -# Set the colours used as a chequerboard pattern in the fold margin -fun void SetFoldMarginColour=2290(bool useSetting, colour back) -fun void SetFoldMarginHiColour=2291(bool useSetting, colour fore) - -## New messages go here - -## Start of key messages -# Move caret down one line. -fun void LineDown=2300(,) - -# Move caret down one line extending selection to new caret position. -fun void LineDownExtend=2301(,) - -# Move caret up one line. -fun void LineUp=2302(,) - -# Move caret up one line extending selection to new caret position. -fun void LineUpExtend=2303(,) - -# Move caret left one character. -fun void CharLeft=2304(,) - -# Move caret left one character extending selection to new caret position. -fun void CharLeftExtend=2305(,) - -# Move caret right one character. -fun void CharRight=2306(,) - -# Move caret right one character extending selection to new caret position. -fun void CharRightExtend=2307(,) - -# Move caret left one word. -fun void WordLeft=2308(,) - -# Move caret left one word extending selection to new caret position. -fun void WordLeftExtend=2309(,) - -# Move caret right one word. -fun void WordRight=2310(,) - -# Move caret right one word extending selection to new caret position. -fun void WordRightExtend=2311(,) - -# Move caret to first position on line. -fun void Home=2312(,) - -# Move caret to first position on line extending selection to new caret position. -fun void HomeExtend=2313(,) - -# Move caret to last position on line. -fun void LineEnd=2314(,) - -# Move caret to last position on line extending selection to new caret position. -fun void LineEndExtend=2315(,) - -# Move caret to first position in document. -fun void DocumentStart=2316(,) - -# Move caret to first position in document extending selection to new caret position. -fun void DocumentStartExtend=2317(,) - -# Move caret to last position in document. -fun void DocumentEnd=2318(,) - -# Move caret to last position in document extending selection to new caret position. -fun void DocumentEndExtend=2319(,) - -# Move caret one page up. -fun void PageUp=2320(,) - -# Move caret one page up extending selection to new caret position. -fun void PageUpExtend=2321(,) - -# Move caret one page down. -fun void PageDown=2322(,) - -# Move caret one page down extending selection to new caret position. -fun void PageDownExtend=2323(,) - -# Switch from insert to overtype mode or the reverse. -fun void EditToggleOvertype=2324(,) - -# Cancel any modes such as call tip or auto-completion list display. -fun void Cancel=2325(,) - -# Delete the selection or if no selection, the character before the caret. -fun void DeleteBack=2326(,) - -# If selection is empty or all on one line replace the selection with a tab character. -# If more than one line selected, indent the lines. -fun void Tab=2327(,) - -# Dedent the selected lines. -fun void BackTab=2328(,) - -# Insert a new line, may use a CRLF, CR or LF depending on EOL mode. -fun void NewLine=2329(,) - -# Insert a Form Feed character. -fun void FormFeed=2330(,) - -# Move caret to before first visible character on line. -# If already there move to first character on line. -fun void VCHome=2331(,) - -# Like VCHome but extending selection to new caret position. -fun void VCHomeExtend=2332(,) - -# Magnify the displayed text by increasing the sizes by 1 point. -fun void ZoomIn=2333(,) - -# Make the displayed text smaller by decreasing the sizes by 1 point. -fun void ZoomOut=2334(,) - -# Delete the word to the left of the caret. -fun void DelWordLeft=2335(,) - -# Delete the word to the right of the caret. -fun void DelWordRight=2336(,) - -# Delete the word to the right of the caret, but not the trailing non-word characters. -fun void DelWordRightEnd=2518(,) - -# Cut the line containing the caret. -fun void LineCut=2337(,) - -# Delete the line containing the caret. -fun void LineDelete=2338(,) - -# Switch the current line with the previous. -fun void LineTranspose=2339(,) - -# Duplicate the current line. -fun void LineDuplicate=2404(,) - -# Transform the selection to lower case. -fun void LowerCase=2340(,) - -# Transform the selection to upper case. -fun void UpperCase=2341(,) - -# Scroll the document down, keeping the caret visible. -fun void LineScrollDown=2342(,) - -# Scroll the document up, keeping the caret visible. -fun void LineScrollUp=2343(,) - -# Delete the selection or if no selection, the character before the caret. -# Will not delete the character before at the start of a line. -fun void DeleteBackNotLine=2344(,) - -# Move caret to first position on display line. -fun void HomeDisplay=2345(,) - -# Move caret to first position on display line extending selection to -# new caret position. -fun void HomeDisplayExtend=2346(,) - -# Move caret to last position on display line. -fun void LineEndDisplay=2347(,) - -# Move caret to last position on display line extending selection to new -# caret position. -fun void LineEndDisplayExtend=2348(,) - -# These are like their namesakes Home(Extend)?, LineEnd(Extend)?, VCHome(Extend)? -# except they behave differently when word-wrap is enabled: -# They go first to the start / end of the display line, like (Home|LineEnd)Display -# The difference is that, the cursor is already at the point, it goes on to the start -# or end of the document line, as appropriate for (Home|LineEnd|VCHome)(Extend)?. - -fun void HomeWrap=2349(,) -fun void HomeWrapExtend=2450(,) -fun void LineEndWrap=2451(,) -fun void LineEndWrapExtend=2452(,) -fun void VCHomeWrap=2453(,) -fun void VCHomeWrapExtend=2454(,) - -# Copy the line containing the caret. -fun void LineCopy=2455(,) - -# Move the caret inside current view if it's not there already. -fun void MoveCaretInsideView=2401(,) - -# How many characters are on a line, including end of line characters? -fun int LineLength=2350(int line,) - -# Highlight the characters at two positions. -fun void BraceHighlight=2351(position pos1, position pos2) - -# Use specified indicator to highlight matching braces instead of changing their style. -fun void BraceHighlightIndicator=2498(bool useBraceHighlightIndicator, int indicator) - -# Highlight the character at a position indicating there is no matching brace. -fun void BraceBadLight=2352(position pos,) - -# Use specified indicator to highlight non matching brace instead of changing its style. -fun void BraceBadLightIndicator=2499(bool useBraceBadLightIndicator, int indicator) - -# Find the position of a matching brace or INVALID_POSITION if no match. -fun position BraceMatch=2353(position pos,) - -# Are the end of line characters visible? -get bool GetViewEOL=2355(,) - -# Make the end of line characters visible or invisible. -set void SetViewEOL=2356(bool visible,) - -# Retrieve a pointer to the document object. -get int GetDocPointer=2357(,) - -# Change the document object used. -set void SetDocPointer=2358(, int pointer) - -# Set which document modification events are sent to the container. -set void SetModEventMask=2359(int mask,) - -enu EdgeVisualStyle=EDGE_ -val EDGE_NONE=0 -val EDGE_LINE=1 -val EDGE_BACKGROUND=2 - -# Retrieve the column number which text should be kept within. -get int GetEdgeColumn=2360(,) - -# Set the column number of the edge. -# If text goes past the edge then it is highlighted. -set void SetEdgeColumn=2361(int column,) - -# Retrieve the edge highlight mode. -get int GetEdgeMode=2362(,) - -# The edge may be displayed by a line (EDGE_LINE) or by highlighting text that -# goes beyond it (EDGE_BACKGROUND) or not displayed at all (EDGE_NONE). -set void SetEdgeMode=2363(int mode,) - -# Retrieve the colour used in edge indication. -get colour GetEdgeColour=2364(,) - -# Change the colour used in edge indication. -set void SetEdgeColour=2365(colour edgeColour,) - -# Sets the current caret position to be the search anchor. -fun void SearchAnchor=2366(,) - -# Find some text starting at the search anchor. -# Does not ensure the selection is visible. -fun int SearchNext=2367(int flags, string text) - -# Find some text starting at the search anchor and moving backwards. -# Does not ensure the selection is visible. -fun int SearchPrev=2368(int flags, string text) - -# Retrieves the number of lines completely visible. -get int LinesOnScreen=2370(,) - -# Set whether a pop up menu is displayed automatically when the user presses -# the wrong mouse button. -fun void UsePopUp=2371(bool allowPopUp,) - -# Is the selection rectangular? The alternative is the more common stream selection. -get bool SelectionIsRectangle=2372(,) - -# Set the zoom level. This number of points is added to the size of all fonts. -# It may be positive to magnify or negative to reduce. -set void SetZoom=2373(int zoom,) -# Retrieve the zoom level. -get int GetZoom=2374(,) - -# Create a new document object. -# Starts with reference count of 1 and not selected into editor. -fun int CreateDocument=2375(,) -# Extend life of document. -fun void AddRefDocument=2376(, int doc) -# Release a reference to the document, deleting document if it fades to black. -fun void ReleaseDocument=2377(, int doc) - -# Get which document modification events are sent to the container. -get int GetModEventMask=2378(,) - -# Change internal focus flag. -set void SetFocus=2380(bool focus,) -# Get internal focus flag. -get bool GetFocus=2381(,) - -enu Status=SC_STATUS_ -val SC_STATUS_OK=0 -val SC_STATUS_FAILURE=1 -val SC_STATUS_BADALLOC=2 - -# Change error status - 0 = OK. -set void SetStatus=2382(int statusCode,) -# Get error status. -get int GetStatus=2383(,) - -# Set whether the mouse is captured when its button is pressed. -set void SetMouseDownCaptures=2384(bool captures,) -# Get whether mouse gets captured. -get bool GetMouseDownCaptures=2385(,) - -enu CursorShape=SC_CURSOR -val SC_CURSORNORMAL=-1 -val SC_CURSORARROW=2 -val SC_CURSORWAIT=4 -val SC_CURSORREVERSEARROW=7 -# Sets the cursor to one of the SC_CURSOR* values. -set void SetCursor=2386(int cursorType,) -# Get cursor type. -get int GetCursor=2387(,) - -# Change the way control characters are displayed: -# If symbol is < 32, keep the drawn way, else, use the given character. -set void SetControlCharSymbol=2388(int symbol,) -# Get the way control characters are displayed. -get int GetControlCharSymbol=2389(,) - -# Move to the previous change in capitalisation. -fun void WordPartLeft=2390(,) -# Move to the previous change in capitalisation extending selection -# to new caret position. -fun void WordPartLeftExtend=2391(,) -# Move to the change next in capitalisation. -fun void WordPartRight=2392(,) -# Move to the next change in capitalisation extending selection -# to new caret position. -fun void WordPartRightExtend=2393(,) - -# Constants for use with SetVisiblePolicy, similar to SetCaretPolicy. -val VISIBLE_SLOP=0x01 -val VISIBLE_STRICT=0x04 -# Set the way the display area is determined when a particular line -# is to be moved to by Find, FindNext, GotoLine, etc. -fun void SetVisiblePolicy=2394(int visiblePolicy, int visibleSlop) - -# Delete back from the current position to the start of the line. -fun void DelLineLeft=2395(,) - -# Delete forwards from the current position to the end of the line. -fun void DelLineRight=2396(,) - -# Get and Set the xOffset (ie, horizonal scroll position). -set void SetXOffset=2397(int newOffset,) -get int GetXOffset=2398(,) - -# Set the last x chosen value to be the caret x position. -fun void ChooseCaretX=2399(,) - -# Set the focus to this Scintilla widget. -fun void GrabFocus=2400(,) - -enu CaretPolicy=CARET_ -# Caret policy, used by SetXCaretPolicy and SetYCaretPolicy. -# If CARET_SLOP is set, we can define a slop value: caretSlop. -# This value defines an unwanted zone (UZ) where the caret is... unwanted. -# This zone is defined as a number of pixels near the vertical margins, -# and as a number of lines near the horizontal margins. -# By keeping the caret away from the edges, it is seen within its context, -# so it is likely that the identifier that the caret is on can be completely seen, -# and that the current line is seen with some of the lines following it which are -# often dependent on that line. -val CARET_SLOP=0x01 -# If CARET_STRICT is set, the policy is enforced... strictly. -# The caret is centred on the display if slop is not set, -# and cannot go in the UZ if slop is set. -val CARET_STRICT=0x04 -# If CARET_JUMPS is set, the display is moved more energetically -# so the caret can move in the same direction longer before the policy is applied again. -val CARET_JUMPS=0x10 -# If CARET_EVEN is not set, instead of having symmetrical UZs, -# the left and bottom UZs are extended up to right and top UZs respectively. -# This way, we favour the displaying of useful information: the begining of lines, -# where most code reside, and the lines after the caret, eg. the body of a function. -val CARET_EVEN=0x08 - -# Set the way the caret is kept visible when going sideway. -# The exclusion zone is given in pixels. -fun void SetXCaretPolicy=2402(int caretPolicy, int caretSlop) - -# Set the way the line the caret is on is kept visible. -# The exclusion zone is given in lines. -fun void SetYCaretPolicy=2403(int caretPolicy, int caretSlop) - -# Set printing to line wrapped (SC_WRAP_WORD) or not line wrapped (SC_WRAP_NONE). -set void SetPrintWrapMode=2406(int mode,) - -# Is printing line wrapped? -get int GetPrintWrapMode=2407(,) - -# Set a fore colour for active hotspots. -set void SetHotspotActiveFore=2410(bool useSetting, colour fore) - -# Get the fore colour for active hotspots. -get colour GetHotspotActiveFore=2494(,) - -# Set a back colour for active hotspots. -set void SetHotspotActiveBack=2411(bool useSetting, colour back) - -# Get the back colour for active hotspots. -get colour GetHotspotActiveBack=2495(,) - -# Enable / Disable underlining active hotspots. -set void SetHotspotActiveUnderline=2412(bool underline,) - -# Get whether underlining for active hotspots. -get bool GetHotspotActiveUnderline=2496(,) - -# Limit hotspots to single line so hotspots on two lines don't merge. -set void SetHotspotSingleLine=2421(bool singleLine,) - -# Get the HotspotSingleLine property -get bool GetHotspotSingleLine=2497(,) - -# Move caret between paragraphs (delimited by empty lines). -fun void ParaDown=2413(,) -fun void ParaDownExtend=2414(,) -fun void ParaUp=2415(,) -fun void ParaUpExtend=2416(,) - -# Given a valid document position, return the previous position taking code -# page into account. Returns 0 if passed 0. -fun position PositionBefore=2417(position pos,) - -# Given a valid document position, return the next position taking code -# page into account. Maximum value returned is the last position in the document. -fun position PositionAfter=2418(position pos,) - -# Copy a range of text to the clipboard. Positions are clipped into the document. -fun void CopyRange=2419(position start, position end) - -# Copy argument text to the clipboard. -fun void CopyText=2420(int length, string text) - -enu SelectionMode=SC_SEL_ -val SC_SEL_STREAM=0 -val SC_SEL_RECTANGLE=1 -val SC_SEL_LINES=2 -val SC_SEL_THIN=3 - -# Set the selection mode to stream (SC_SEL_STREAM) or rectangular (SC_SEL_RECTANGLE/SC_SEL_THIN) or -# by lines (SC_SEL_LINES). -set void SetSelectionMode=2422(int mode,) - -# Get the mode of the current selection. -get int GetSelectionMode=2423(,) - -# Retrieve the position of the start of the selection at the given line (INVALID_POSITION if no selection on this line). -fun position GetLineSelStartPosition=2424(int line,) - -# Retrieve the position of the end of the selection at the given line (INVALID_POSITION if no selection on this line). -fun position GetLineSelEndPosition=2425(int line,) - -## RectExtended rectangular selection moves -# Move caret down one line, extending rectangular selection to new caret position. -fun void LineDownRectExtend=2426(,) - -# Move caret up one line, extending rectangular selection to new caret position. -fun void LineUpRectExtend=2427(,) - -# Move caret left one character, extending rectangular selection to new caret position. -fun void CharLeftRectExtend=2428(,) - -# Move caret right one character, extending rectangular selection to new caret position. -fun void CharRightRectExtend=2429(,) - -# Move caret to first position on line, extending rectangular selection to new caret position. -fun void HomeRectExtend=2430(,) - -# Move caret to before first visible character on line. -# If already there move to first character on line. -# In either case, extend rectangular selection to new caret position. -fun void VCHomeRectExtend=2431(,) - -# Move caret to last position on line, extending rectangular selection to new caret position. -fun void LineEndRectExtend=2432(,) - -# Move caret one page up, extending rectangular selection to new caret position. -fun void PageUpRectExtend=2433(,) - -# Move caret one page down, extending rectangular selection to new caret position. -fun void PageDownRectExtend=2434(,) - - -# Move caret to top of page, or one page up if already at top of page. -fun void StutteredPageUp=2435(,) - -# Move caret to top of page, or one page up if already at top of page, extending selection to new caret position. -fun void StutteredPageUpExtend=2436(,) - -# Move caret to bottom of page, or one page down if already at bottom of page. -fun void StutteredPageDown=2437(,) - -# Move caret to bottom of page, or one page down if already at bottom of page, extending selection to new caret position. -fun void StutteredPageDownExtend=2438(,) - - -# Move caret left one word, position cursor at end of word. -fun void WordLeftEnd=2439(,) - -# Move caret left one word, position cursor at end of word, extending selection to new caret position. -fun void WordLeftEndExtend=2440(,) - -# Move caret right one word, position cursor at end of word. -fun void WordRightEnd=2441(,) - -# Move caret right one word, position cursor at end of word, extending selection to new caret position. -fun void WordRightEndExtend=2442(,) - -# Set the set of characters making up whitespace for when moving or selecting by word. -# Should be called after SetWordChars. -set void SetWhitespaceChars=2443(, string characters) - -# Reset the set of characters for whitespace and word characters to the defaults. -fun void SetCharsDefault=2444(,) - -# Get currently selected item position in the auto-completion list -fun int AutoCGetCurrent=2445(,) - -# Get currently selected item text in the auto-completion list -# Returns the length of the item text -fun int AutoCGetCurrentText=2610(, stringresult s) - -# Enlarge the document to a particular size of text bytes. -fun void Allocate=2446(int bytes,) - -# Returns the target converted to UTF8. -# Return the length in bytes. -fun int TargetAsUTF8=2447(, stringresult s) - -# Set the length of the utf8 argument for calling EncodedFromUTF8. -# Set to -1 and the string will be measured to the first nul. -fun void SetLengthForEncode=2448(int bytes,) - -# Translates a UTF8 string into the document encoding. -# Return the length of the result in bytes. -# On error return 0. -fun int EncodedFromUTF8=2449(string utf8, stringresult encoded) - -# Find the position of a column on a line taking into account tabs and -# multi-byte characters. If beyond end of line, return line end position. -fun int FindColumn=2456(int line, int column) - -# Can the caret preferred x position only be changed by explicit movement commands? -get int GetCaretSticky=2457(,) - -# Stop the caret preferred x position changing when the user types. -set void SetCaretSticky=2458(int useCaretStickyBehaviour,) - -enu CaretSticky=SC_CARETSTICKY_ -val SC_CARETSTICKY_OFF=0 -val SC_CARETSTICKY_ON=1 -val SC_CARETSTICKY_WHITESPACE=2 - -# Switch between sticky and non-sticky: meant to be bound to a key. -fun void ToggleCaretSticky=2459(,) - -# Enable/Disable convert-on-paste for line endings -set void SetPasteConvertEndings=2467(bool convert,) - -# Get convert-on-paste setting -get bool GetPasteConvertEndings=2468(,) - -# Duplicate the selection. If selection empty duplicate the line containing the caret. -fun void SelectionDuplicate=2469(,) - -val SC_ALPHA_TRANSPARENT=0 -val SC_ALPHA_OPAQUE=255 -val SC_ALPHA_NOALPHA=256 - -# Set background alpha of the caret line. -set void SetCaretLineBackAlpha=2470(int alpha,) - -# Get the background alpha of the caret line. -get int GetCaretLineBackAlpha=2471(,) - -enu CaretStyle=CARETSTYLE_ -val CARETSTYLE_INVISIBLE=0 -val CARETSTYLE_LINE=1 -val CARETSTYLE_BLOCK=2 - -# Set the style of the caret to be drawn. -set void SetCaretStyle=2512(int caretStyle,) - -# Returns the current style of the caret. -get int GetCaretStyle=2513(,) - -# Set the indicator used for IndicatorFillRange and IndicatorClearRange -set void SetIndicatorCurrent=2500(int indicator,) - -# Get the current indicator -get int GetIndicatorCurrent=2501(,) - -# Set the value used for IndicatorFillRange -set void SetIndicatorValue=2502(int value,) - -# Get the current indicator vaue -get int GetIndicatorValue=2503(,) - -# Turn a indicator on over a range. -fun void IndicatorFillRange=2504(int position, int fillLength) - -# Turn a indicator off over a range. -fun void IndicatorClearRange=2505(int position, int clearLength) - -# Are any indicators present at position? -fun int IndicatorAllOnFor=2506(int position,) - -# What value does a particular indicator have at at a position? -fun int IndicatorValueAt=2507(int indicator, int position) - -# Where does a particular indicator start? -fun int IndicatorStart=2508(int indicator, int position) - -# Where does a particular indicator end? -fun int IndicatorEnd=2509(int indicator, int position) - -# Set number of entries in position cache -set void SetPositionCache=2514(int size,) - -# How many entries are allocated to the position cache? -get int GetPositionCache=2515(,) - -# Copy the selection, if selection empty copy the line with the caret -fun void CopyAllowLine=2519(,) - -# Compact the document buffer and return a read-only pointer to the -# characters in the document. -get int GetCharacterPointer=2520(,) - -# Always interpret keyboard input as Unicode -set void SetKeysUnicode=2521(bool keysUnicode,) - -# Are keys always interpreted as Unicode? -get bool GetKeysUnicode=2522(,) - -# Set the alpha fill colour of the given indicator. -set void IndicSetAlpha=2523(int indicator, int alpha) - -# Get the alpha fill colour of the given indicator. -get int IndicGetAlpha=2524(int indicator,) - -# Set the alpha outline colour of the given indicator. -set void IndicSetOutlineAlpha=2558(int indicator, int alpha) - -# Get the alpha outline colour of the given indicator. -get int IndicGetOutlineAlpha=2559(int indicator,) - -# Set extra ascent for each line -set void SetExtraAscent=2525(int extraAscent,) - -# Get extra ascent for each line -get int GetExtraAscent=2526(,) - -# Set extra descent for each line -set void SetExtraDescent=2527(int extraDescent,) - -# Get extra descent for each line -get int GetExtraDescent=2528(,) - -# Which symbol was defined for markerNumber with MarkerDefine -fun int MarkerSymbolDefined=2529(int markerNumber,) - -# Set the text in the text margin for a line -set void MarginSetText=2530(int line, string text) - -# Get the text in the text margin for a line -get int MarginGetText=2531(int line, stringresult text) - -# Set the style number for the text margin for a line -set void MarginSetStyle=2532(int line, int style) - -# Get the style number for the text margin for a line -get int MarginGetStyle=2533(int line,) - -# Set the style in the text margin for a line -set void MarginSetStyles=2534(int line, string styles) - -# Get the styles in the text margin for a line -get int MarginGetStyles=2535(int line, stringresult styles) - -# Clear the margin text on all lines -fun void MarginTextClearAll=2536(,) - -# Get the start of the range of style numbers used for margin text -set void MarginSetStyleOffset=2537(int style,) - -# Get the start of the range of style numbers used for margin text -get int MarginGetStyleOffset=2538(,) - -enu MarginOption=SC_MARGINOPTION_ -val SC_MARGINOPTION_NONE=0 -val SC_MARGINOPTION_SUBLINESELECT=1 - -# Set the margin options. -set void SetMarginOptions=2539(int marginOptions,) - -# Get the margin options. -get int GetMarginOptions=2557(,) - -# Set the annotation text for a line -set void AnnotationSetText=2540(int line, string text) - -# Get the annotation text for a line -get int AnnotationGetText=2541(int line, stringresult text) - -# Set the style number for the annotations for a line -set void AnnotationSetStyle=2542(int line, int style) - -# Get the style number for the annotations for a line -get int AnnotationGetStyle=2543(int line,) - -# Set the annotation styles for a line -set void AnnotationSetStyles=2544(int line, string styles) - -# Get the annotation styles for a line -get int AnnotationGetStyles=2545(int line, stringresult styles) - -# Get the number of annotation lines for a line -get int AnnotationGetLines=2546(int line,) - -# Clear the annotations from all lines -fun void AnnotationClearAll=2547(,) - -enu AnnotationVisible=ANNOTATION_ -val ANNOTATION_HIDDEN=0 -val ANNOTATION_STANDARD=1 -val ANNOTATION_BOXED=2 - -# Set the visibility for the annotations for a view -set void AnnotationSetVisible=2548(int visible,) - -# Get the visibility for the annotations for a view -get int AnnotationGetVisible=2549(,) - -# Get the start of the range of style numbers used for annotations -set void AnnotationSetStyleOffset=2550(int style,) - -# Get the start of the range of style numbers used for annotations -get int AnnotationGetStyleOffset=2551(,) - -val UNDO_MAY_COALESCE=1 - -# Add a container action to the undo stack -fun void AddUndoAction=2560(int token, int flags) - -# Find the position of a character from a point within the window. -fun position CharPositionFromPoint=2561(int x, int y) - -# Find the position of a character from a point within the window. -# Return INVALID_POSITION if not close to text. -fun position CharPositionFromPointClose=2562(int x, int y) - -# Set whether multiple selections can be made -set void SetMultipleSelection=2563(bool multipleSelection,) - -# Whether multiple selections can be made -get bool GetMultipleSelection=2564(,) - -# Set whether typing can be performed into multiple selections -set void SetAdditionalSelectionTyping=2565(bool additionalSelectionTyping,) - -# Whether typing can be performed into multiple selections -get bool GetAdditionalSelectionTyping=2566(,) - -# Set whether additional carets will blink -set void SetAdditionalCaretsBlink=2567(bool additionalCaretsBlink,) - -# Whether additional carets will blink -get bool GetAdditionalCaretsBlink=2568(,) - -# Set whether additional carets are visible -set void SetAdditionalCaretsVisible=2608(bool additionalCaretsBlink,) - -# Whether additional carets are visible -get bool GetAdditionalCaretsVisible=2609(,) - -# How many selections are there? -get int GetSelections=2570(,) - -# Clear selections to a single empty stream selection -fun void ClearSelections=2571(,) - -# Set a simple selection -fun int SetSelection=2572(int caret,int anchor) - -# Add a selection -fun int AddSelection=2573(int caret,int anchor) - -# Set the main selection -set void SetMainSelection=2574(int selection,) - -# Which selection is the main selection -get int GetMainSelection=2575(,) - -set void SetSelectionNCaret=2576(int selection, position pos) -get position GetSelectionNCaret=2577(int selection,) -set void SetSelectionNAnchor=2578(int selection, position posAnchor) -get position GetSelectionNAnchor=2579(int selection,) -set void SetSelectionNCaretVirtualSpace=2580(int selection, int space) -get int GetSelectionNCaretVirtualSpace=2581(int selection,) -set void SetSelectionNAnchorVirtualSpace=2582(int selection, int space) -get int GetSelectionNAnchorVirtualSpace=2583(int selection,) - -# Sets the position that starts the selection - this becomes the anchor. -set void SetSelectionNStart=2584(int selection, position pos) - -# Returns the position at the start of the selection. -get position GetSelectionNStart=2585(int selection,) - -# Sets the position that ends the selection - this becomes the currentPosition. -set void SetSelectionNEnd=2586(int selection, position pos,) - -# Returns the position at the end of the selection. -get position GetSelectionNEnd=2587(int selection,) - -set void SetRectangularSelectionCaret=2588(position pos,) -get position GetRectangularSelectionCaret=2589(,) -set void SetRectangularSelectionAnchor=2590(position posAnchor,) -get position GetRectangularSelectionAnchor=2591(,) -set void SetRectangularSelectionCaretVirtualSpace=2592(int space,) -get int GetRectangularSelectionCaretVirtualSpace=2593(,) -set void SetRectangularSelectionAnchorVirtualSpace=2594(int space,) -get int GetRectangularSelectionAnchorVirtualSpace=2595(,) - -enu VirtualSpace=SCVS_ -val SCVS_NONE=0 -val SCVS_RECTANGULARSELECTION=1 -val SCVS_USERACCESSIBLE=2 - -set void SetVirtualSpaceOptions=2596(int virtualSpaceOptions,) -get int GetVirtualSpaceOptions=2597(,) - -# On GTK+, allow selecting the modifier key to use for mouse-based -# rectangular selection. Often the window manager requires Alt+Mouse Drag -# for moving windows. -# Valid values are SCMOD_CTRL(default), SCMOD_ALT, or SCMOD_SUPER. - -set void SetRectangularSelectionModifier=2598(int modifier,) - -# Get the modifier key used for rectangular selection. -get int GetRectangularSelectionModifier=2599(,) - -# Set the foreground colour of additional selections. -# Must have previously called SetSelFore with non-zero first argument for this to have an effect. -set void SetAdditionalSelFore=2600(colour fore,) - -# Set the background colour of additional selections. -# Must have previously called SetSelBack with non-zero first argument for this to have an effect. -set void SetAdditionalSelBack=2601(colour back,) - -# Set the alpha of the selection. -set void SetAdditionalSelAlpha=2602(int alpha,) - -# Get the alpha of the selection. -get int GetAdditionalSelAlpha=2603(,) - -# Set the foreground colour of additional carets. -set void SetAdditionalCaretFore=2604(colour fore,) - -# Get the foreground colour of additional carets. -get colour GetAdditionalCaretFore=2605(,) - -# Set the main selection to the next selection. -fun void RotateSelection=2606(,) - -# Swap that caret and anchor of the main selection. -fun void SwapMainAnchorCaret=2607(,) - -# Indicate that the internal state of a lexer has changed over a range and therefore -# there may be a need to redraw. -fun int ChangeLexerState=2617(position start, position end) - -# Find the next line at or after lineStart that is a contracted fold header line. -# Return -1 when no more lines. -fun int ContractedFoldNext=2618(int lineStart,) - -# Centre current line in window. -fun void VerticalCentreCaret=2619(,) - -# Move the selected lines up one line, shifting the line above after the selection -fun void MoveSelectedLinesUp=2620(,) - -# Move the selected lines down one line, shifting the line below before the selection -fun void MoveSelectedLinesDown=2621(,) - -# Set the identifier reported as idFrom in notification messages. -set void SetIdentifier=2622(int identifier,) - -# Get the identifier. -get int GetIdentifier=2623(,) - -# Set the width for future RGBA image data. -set void RGBAImageSetWidth=2624(int width,) - -# Set the height for future RGBA image data. -set void RGBAImageSetHeight=2625(int height,) - -# Define a marker from RGBA data. -# It has the width and height from RGBAImageSetWidth/Height -fun void MarkerDefineRGBAImage=2626(int markerNumber, string pixels) - -# Register an RGBA image for use in autocompletion lists. -# It has the width and height from RGBAImageSetWidth/Height -fun void RegisterRGBAImage=2627(int type, string pixels) - -# Scroll to start of document. -fun void ScrollToStart=2628(,) - -# Scroll to end of document. -fun void ScrollToEnd=2629(,) - -val SC_TECHNOLOGY_DEFAULT=0 -val SC_TECHNOLOGY_DIRECTWRITE=1 - -# Set the technolgy used. -set void SetTechnology=2630(int technology,) - -# Get the tech. -get int GetTechnology=2631(,) - -# Create an ILoader*. -fun int CreateLoader=2632(int bytes,) - -# Start notifying the container of all key presses and commands. -fun void StartRecord=3001(,) - -# Stop notifying the container of all key presses and commands. -fun void StopRecord=3002(,) - -# Set the lexing language of the document. -set void SetLexer=4001(int lexer,) - -# Retrieve the lexing language of the document. -get int GetLexer=4002(,) - -# Colourise a segment of the document using the current lexing language. -fun void Colourise=4003(position start, position end) - -# Set up a value that may be used by a lexer for some optional feature. -set void SetProperty=4004(string key, string value) - -# Maximum value of keywordSet parameter of SetKeyWords. -val KEYWORDSET_MAX=8 - -# Set up the key words used by the lexer. -set void SetKeyWords=4005(int keywordSet, string keyWords) - -# Set the lexing language of the document based on string name. -set void SetLexerLanguage=4006(, string language) - -# Load a lexer library (dll / so). -fun void LoadLexerLibrary=4007(, string path) - -# Retrieve a "property" value previously set with SetProperty. -fun int GetProperty=4008(string key, stringresult buf) - -# Retrieve a "property" value previously set with SetProperty, -# with "$()" variable replacement on returned buffer. -fun int GetPropertyExpanded=4009(string key, stringresult buf) - -# Retrieve a "property" value previously set with SetProperty, -# interpreted as an int AFTER any "$()" variable replacement. -get int GetPropertyInt=4010(string key,) - -# Retrieve the number of bits the current lexer needs for styling. -get int GetStyleBitsNeeded=4011(,) - -# Retrieve the name of the lexer. -# Return the length of the text. -get int GetLexerLanguage=4012(, stringresult text) - -# For private communication between an application and a known lexer. -fun int PrivateLexerCall=4013(int operation, int pointer) - -# Retrieve a '\n' separated list of properties understood by the current lexer. -fun int PropertyNames=4014(, stringresult names) - -enu TypeProperty=SC_TYPE_ -val SC_TYPE_BOOLEAN=0 -val SC_TYPE_INTEGER=1 -val SC_TYPE_STRING=2 - -# Retrieve the type of a property. -fun int PropertyType=4015(string name,) - -# Describe a property. -fun int DescribeProperty=4016(string name, stringresult description) - -# Retrieve a '\n' separated list of descriptions of the keyword sets understood by the current lexer. -fun int DescribeKeyWordSets=4017(, stringresult descriptions) - -# Notifications -# Type of modification and the action which caused the modification. -# These are defined as a bit mask to make it easy to specify which notifications are wanted. -# One bit is set from each of SC_MOD_* and SC_PERFORMED_*. -enu ModificationFlags=SC_MOD_ SC_PERFORMED_ SC_LAST -val SC_MOD_INSERTTEXT=0x1 -val SC_MOD_DELETETEXT=0x2 -val SC_MOD_CHANGESTYLE=0x4 -val SC_MOD_CHANGEFOLD=0x8 -val SC_PERFORMED_USER=0x10 -val SC_PERFORMED_UNDO=0x20 -val SC_PERFORMED_REDO=0x40 -val SC_MULTISTEPUNDOREDO=0x80 -val SC_LASTSTEPINUNDOREDO=0x100 -val SC_MOD_CHANGEMARKER=0x200 -val SC_MOD_BEFOREINSERT=0x400 -val SC_MOD_BEFOREDELETE=0x800 -val SC_MULTILINEUNDOREDO=0x1000 -val SC_STARTACTION=0x2000 -val SC_MOD_CHANGEINDICATOR=0x4000 -val SC_MOD_CHANGELINESTATE=0x8000 -val SC_MOD_CHANGEMARGIN=0x10000 -val SC_MOD_CHANGEANNOTATION=0x20000 -val SC_MOD_CONTAINER=0x40000 -val SC_MOD_LEXERSTATE=0x80000 -val SC_MODEVENTMASKALL=0xFFFFF - -enu Update=SC_UPDATE_ -val SC_UPDATE_CONTENT=0x1 -val SC_UPDATE_SELECTION=0x2 -val SC_UPDATE_V_SCROLL=0x4 -val SC_UPDATE_H_SCROLL=0x8 - -# For compatibility, these go through the COMMAND notification rather than NOTIFY -# and should have had exactly the same values as the EN_* constants. -# Unfortunately the SETFOCUS and KILLFOCUS are flipped over from EN_* -# As clients depend on these constants, this will not be changed. -val SCEN_CHANGE=768 -val SCEN_SETFOCUS=512 -val SCEN_KILLFOCUS=256 - -# Symbolic key codes and modifier flags. -# ASCII and other printable characters below 256. -# Extended keys above 300. - -enu Keys=SCK_ -val SCK_DOWN=300 -val SCK_UP=301 -val SCK_LEFT=302 -val SCK_RIGHT=303 -val SCK_HOME=304 -val SCK_END=305 -val SCK_PRIOR=306 -val SCK_NEXT=307 -val SCK_DELETE=308 -val SCK_INSERT=309 -val SCK_ESCAPE=7 -val SCK_BACK=8 -val SCK_TAB=9 -val SCK_RETURN=13 -val SCK_ADD=310 -val SCK_SUBTRACT=311 -val SCK_DIVIDE=312 -val SCK_WIN=313 -val SCK_RWIN=314 -val SCK_MENU=315 - -enu KeyMod=SCMOD_ -val SCMOD_NORM=0 -val SCMOD_SHIFT=1 -val SCMOD_CTRL=2 -val SCMOD_ALT=4 -val SCMOD_SUPER=8 -val SCMOD_META=16 - -################################################ -# For SciLexer.h -enu Lexer=SCLEX_ -val SCLEX_CONTAINER=0 -val SCLEX_NULL=1 -val SCLEX_PYTHON=2 -val SCLEX_CPP=3 -val SCLEX_HTML=4 -val SCLEX_XML=5 -val SCLEX_PERL=6 -val SCLEX_SQL=7 -val SCLEX_VB=8 -val SCLEX_PROPERTIES=9 -val SCLEX_ERRORLIST=10 -val SCLEX_MAKEFILE=11 -val SCLEX_BATCH=12 -val SCLEX_XCODE=13 -val SCLEX_LATEX=14 -val SCLEX_LUA=15 -val SCLEX_DIFF=16 -val SCLEX_CONF=17 -val SCLEX_PASCAL=18 -val SCLEX_AVE=19 -val SCLEX_ADA=20 -val SCLEX_LISP=21 -val SCLEX_RUBY=22 -val SCLEX_EIFFEL=23 -val SCLEX_EIFFELKW=24 -val SCLEX_TCL=25 -val SCLEX_NNCRONTAB=26 -val SCLEX_BULLANT=27 -val SCLEX_VBSCRIPT=28 -val SCLEX_BAAN=31 -val SCLEX_MATLAB=32 -val SCLEX_SCRIPTOL=33 -val SCLEX_ASM=34 -val SCLEX_CPPNOCASE=35 -val SCLEX_FORTRAN=36 -val SCLEX_F77=37 -val SCLEX_CSS=38 -val SCLEX_POV=39 -val SCLEX_LOUT=40 -val SCLEX_ESCRIPT=41 -val SCLEX_PS=42 -val SCLEX_NSIS=43 -val SCLEX_MMIXAL=44 -val SCLEX_CLW=45 -val SCLEX_CLWNOCASE=46 -val SCLEX_LOT=47 -val SCLEX_YAML=48 -val SCLEX_TEX=49 -val SCLEX_METAPOST=50 -val SCLEX_POWERBASIC=51 -val SCLEX_FORTH=52 -val SCLEX_ERLANG=53 -val SCLEX_OCTAVE=54 -val SCLEX_MSSQL=55 -val SCLEX_VERILOG=56 -val SCLEX_KIX=57 -val SCLEX_GUI4CLI=58 -val SCLEX_SPECMAN=59 -val SCLEX_AU3=60 -val SCLEX_APDL=61 -val SCLEX_BASH=62 -val SCLEX_ASN1=63 -val SCLEX_VHDL=64 -val SCLEX_CAML=65 -val SCLEX_BLITZBASIC=66 -val SCLEX_PUREBASIC=67 -val SCLEX_HASKELL=68 -val SCLEX_PHPSCRIPT=69 -val SCLEX_TADS3=70 -val SCLEX_REBOL=71 -val SCLEX_SMALLTALK=72 -val SCLEX_FLAGSHIP=73 -val SCLEX_CSOUND=74 -val SCLEX_FREEBASIC=75 -val SCLEX_INNOSETUP=76 -val SCLEX_OPAL=77 -val SCLEX_SPICE=78 -val SCLEX_D=79 -val SCLEX_CMAKE=80 -val SCLEX_GAP=81 -val SCLEX_PLM=82 -val SCLEX_PROGRESS=83 -val SCLEX_ABAQUS=84 -val SCLEX_ASYMPTOTE=85 -val SCLEX_R=86 -val SCLEX_MAGIK=87 -val SCLEX_POWERSHELL=88 -val SCLEX_MYSQL=89 -val SCLEX_PO=90 -val SCLEX_TAL=91 -val SCLEX_COBOL=92 -val SCLEX_TACL=93 -val SCLEX_SORCUS=94 -val SCLEX_POWERPRO=95 -val SCLEX_NIMROD=96 -val SCLEX_SML=97 -val SCLEX_MARKDOWN=98 -val SCLEX_TXT2TAGS=99 -val SCLEX_A68K=100 -val SCLEX_MODULA=101 -val SCLEX_COFFEESCRIPT=102 -val SCLEX_TCMD=103 -val SCLEX_AVS=104 - -# When a lexer specifies its language as SCLEX_AUTOMATIC it receives a -# value assigned in sequence from SCLEX_AUTOMATIC+1. -val SCLEX_AUTOMATIC=1000 -# Lexical states for SCLEX_PYTHON -lex Python=SCLEX_PYTHON SCE_P_ -lex Nimrod=SCLEX_NIMROD SCE_P_ -val SCE_P_DEFAULT=0 -val SCE_P_COMMENTLINE=1 -val SCE_P_NUMBER=2 -val SCE_P_STRING=3 -val SCE_P_CHARACTER=4 -val SCE_P_WORD=5 -val SCE_P_TRIPLE=6 -val SCE_P_TRIPLEDOUBLE=7 -val SCE_P_CLASSNAME=8 -val SCE_P_DEFNAME=9 -val SCE_P_OPERATOR=10 -val SCE_P_IDENTIFIER=11 -val SCE_P_COMMENTBLOCK=12 -val SCE_P_STRINGEOL=13 -val SCE_P_WORD2=14 -val SCE_P_DECORATOR=15 -# Lexical states for SCLEX_CPP -lex Cpp=SCLEX_CPP SCE_C_ -lex BullAnt=SCLEX_BULLANT SCE_C_ -val SCE_C_DEFAULT=0 -val SCE_C_COMMENT=1 -val SCE_C_COMMENTLINE=2 -val SCE_C_COMMENTDOC=3 -val SCE_C_NUMBER=4 -val SCE_C_WORD=5 -val SCE_C_STRING=6 -val SCE_C_CHARACTER=7 -val SCE_C_UUID=8 -val SCE_C_PREPROCESSOR=9 -val SCE_C_OPERATOR=10 -val SCE_C_IDENTIFIER=11 -val SCE_C_STRINGEOL=12 -val SCE_C_VERBATIM=13 -val SCE_C_REGEX=14 -val SCE_C_COMMENTLINEDOC=15 -val SCE_C_WORD2=16 -val SCE_C_COMMENTDOCKEYWORD=17 -val SCE_C_COMMENTDOCKEYWORDERROR=18 -val SCE_C_GLOBALCLASS=19 -val SCE_C_STRINGRAW=20 -val SCE_C_TRIPLEVERBATIM=21 -val SCE_C_HASHQUOTEDSTRING=22 -# Lexical states for SCLEX_D -lex D=SCLEX_D SCE_D_ -val SCE_D_DEFAULT=0 -val SCE_D_COMMENT=1 -val SCE_D_COMMENTLINE=2 -val SCE_D_COMMENTDOC=3 -val SCE_D_COMMENTNESTED=4 -val SCE_D_NUMBER=5 -val SCE_D_WORD=6 -val SCE_D_WORD2=7 -val SCE_D_WORD3=8 -val SCE_D_TYPEDEF=9 -val SCE_D_STRING=10 -val SCE_D_STRINGEOL=11 -val SCE_D_CHARACTER=12 -val SCE_D_OPERATOR=13 -val SCE_D_IDENTIFIER=14 -val SCE_D_COMMENTLINEDOC=15 -val SCE_D_COMMENTDOCKEYWORD=16 -val SCE_D_COMMENTDOCKEYWORDERROR=17 -val SCE_D_STRINGB=18 -val SCE_D_STRINGR=19 -val SCE_D_WORD5=20 -val SCE_D_WORD6=21 -val SCE_D_WORD7=22 -# Lexical states for SCLEX_TCL -lex TCL=SCLEX_TCL SCE_TCL_ -val SCE_TCL_DEFAULT=0 -val SCE_TCL_COMMENT=1 -val SCE_TCL_COMMENTLINE=2 -val SCE_TCL_NUMBER=3 -val SCE_TCL_WORD_IN_QUOTE=4 -val SCE_TCL_IN_QUOTE=5 -val SCE_TCL_OPERATOR=6 -val SCE_TCL_IDENTIFIER=7 -val SCE_TCL_SUBSTITUTION=8 -val SCE_TCL_SUB_BRACE=9 -val SCE_TCL_MODIFIER=10 -val SCE_TCL_EXPAND=11 -val SCE_TCL_WORD=12 -val SCE_TCL_WORD2=13 -val SCE_TCL_WORD3=14 -val SCE_TCL_WORD4=15 -val SCE_TCL_WORD5=16 -val SCE_TCL_WORD6=17 -val SCE_TCL_WORD7=18 -val SCE_TCL_WORD8=19 -val SCE_TCL_COMMENT_BOX=20 -val SCE_TCL_BLOCK_COMMENT=21 -# Lexical states for SCLEX_HTML, SCLEX_XML -lex HTML=SCLEX_HTML SCE_H -lex XML=SCLEX_XML SCE_H -lex ASP=SCLEX_ASP SCE_H -lex PHP=SCLEX_PHP SCE_H -val SCE_H_DEFAULT=0 -val SCE_H_TAG=1 -val SCE_H_TAGUNKNOWN=2 -val SCE_H_ATTRIBUTE=3 -val SCE_H_ATTRIBUTEUNKNOWN=4 -val SCE_H_NUMBER=5 -val SCE_H_DOUBLESTRING=6 -val SCE_H_SINGLESTRING=7 -val SCE_H_OTHER=8 -val SCE_H_COMMENT=9 -val SCE_H_ENTITY=10 -# XML and ASP -val SCE_H_TAGEND=11 -val SCE_H_XMLSTART=12 -val SCE_H_XMLEND=13 -val SCE_H_SCRIPT=14 -val SCE_H_ASP=15 -val SCE_H_ASPAT=16 -val SCE_H_CDATA=17 -val SCE_H_QUESTION=18 -# More HTML -val SCE_H_VALUE=19 -# X-Code -val SCE_H_XCCOMMENT=20 -# SGML -val SCE_H_SGML_DEFAULT=21 -val SCE_H_SGML_COMMAND=22 -val SCE_H_SGML_1ST_PARAM=23 -val SCE_H_SGML_DOUBLESTRING=24 -val SCE_H_SGML_SIMPLESTRING=25 -val SCE_H_SGML_ERROR=26 -val SCE_H_SGML_SPECIAL=27 -val SCE_H_SGML_ENTITY=28 -val SCE_H_SGML_COMMENT=29 -val SCE_H_SGML_1ST_PARAM_COMMENT=30 -val SCE_H_SGML_BLOCK_DEFAULT=31 -# Embedded Javascript -val SCE_HJ_START=40 -val SCE_HJ_DEFAULT=41 -val SCE_HJ_COMMENT=42 -val SCE_HJ_COMMENTLINE=43 -val SCE_HJ_COMMENTDOC=44 -val SCE_HJ_NUMBER=45 -val SCE_HJ_WORD=46 -val SCE_HJ_KEYWORD=47 -val SCE_HJ_DOUBLESTRING=48 -val SCE_HJ_SINGLESTRING=49 -val SCE_HJ_SYMBOLS=50 -val SCE_HJ_STRINGEOL=51 -val SCE_HJ_REGEX=52 -# ASP Javascript -val SCE_HJA_START=55 -val SCE_HJA_DEFAULT=56 -val SCE_HJA_COMMENT=57 -val SCE_HJA_COMMENTLINE=58 -val SCE_HJA_COMMENTDOC=59 -val SCE_HJA_NUMBER=60 -val SCE_HJA_WORD=61 -val SCE_HJA_KEYWORD=62 -val SCE_HJA_DOUBLESTRING=63 -val SCE_HJA_SINGLESTRING=64 -val SCE_HJA_SYMBOLS=65 -val SCE_HJA_STRINGEOL=66 -val SCE_HJA_REGEX=67 -# Embedded VBScript -val SCE_HB_START=70 -val SCE_HB_DEFAULT=71 -val SCE_HB_COMMENTLINE=72 -val SCE_HB_NUMBER=73 -val SCE_HB_WORD=74 -val SCE_HB_STRING=75 -val SCE_HB_IDENTIFIER=76 -val SCE_HB_STRINGEOL=77 -# ASP VBScript -val SCE_HBA_START=80 -val SCE_HBA_DEFAULT=81 -val SCE_HBA_COMMENTLINE=82 -val SCE_HBA_NUMBER=83 -val SCE_HBA_WORD=84 -val SCE_HBA_STRING=85 -val SCE_HBA_IDENTIFIER=86 -val SCE_HBA_STRINGEOL=87 -# Embedded Python -val SCE_HP_START=90 -val SCE_HP_DEFAULT=91 -val SCE_HP_COMMENTLINE=92 -val SCE_HP_NUMBER=93 -val SCE_HP_STRING=94 -val SCE_HP_CHARACTER=95 -val SCE_HP_WORD=96 -val SCE_HP_TRIPLE=97 -val SCE_HP_TRIPLEDOUBLE=98 -val SCE_HP_CLASSNAME=99 -val SCE_HP_DEFNAME=100 -val SCE_HP_OPERATOR=101 -val SCE_HP_IDENTIFIER=102 -# PHP -val SCE_HPHP_COMPLEX_VARIABLE=104 -# ASP Python -val SCE_HPA_START=105 -val SCE_HPA_DEFAULT=106 -val SCE_HPA_COMMENTLINE=107 -val SCE_HPA_NUMBER=108 -val SCE_HPA_STRING=109 -val SCE_HPA_CHARACTER=110 -val SCE_HPA_WORD=111 -val SCE_HPA_TRIPLE=112 -val SCE_HPA_TRIPLEDOUBLE=113 -val SCE_HPA_CLASSNAME=114 -val SCE_HPA_DEFNAME=115 -val SCE_HPA_OPERATOR=116 -val SCE_HPA_IDENTIFIER=117 -# PHP -val SCE_HPHP_DEFAULT=118 -val SCE_HPHP_HSTRING=119 -val SCE_HPHP_SIMPLESTRING=120 -val SCE_HPHP_WORD=121 -val SCE_HPHP_NUMBER=122 -val SCE_HPHP_VARIABLE=123 -val SCE_HPHP_COMMENT=124 -val SCE_HPHP_COMMENTLINE=125 -val SCE_HPHP_HSTRING_VARIABLE=126 -val SCE_HPHP_OPERATOR=127 -# Lexical states for SCLEX_PERL -lex Perl=SCLEX_PERL SCE_PL_ -val SCE_PL_DEFAULT=0 -val SCE_PL_ERROR=1 -val SCE_PL_COMMENTLINE=2 -val SCE_PL_POD=3 -val SCE_PL_NUMBER=4 -val SCE_PL_WORD=5 -val SCE_PL_STRING=6 -val SCE_PL_CHARACTER=7 -val SCE_PL_PUNCTUATION=8 -val SCE_PL_PREPROCESSOR=9 -val SCE_PL_OPERATOR=10 -val SCE_PL_IDENTIFIER=11 -val SCE_PL_SCALAR=12 -val SCE_PL_ARRAY=13 -val SCE_PL_HASH=14 -val SCE_PL_SYMBOLTABLE=15 -val SCE_PL_VARIABLE_INDEXER=16 -val SCE_PL_REGEX=17 -val SCE_PL_REGSUBST=18 -val SCE_PL_LONGQUOTE=19 -val SCE_PL_BACKTICKS=20 -val SCE_PL_DATASECTION=21 -val SCE_PL_HERE_DELIM=22 -val SCE_PL_HERE_Q=23 -val SCE_PL_HERE_QQ=24 -val SCE_PL_HERE_QX=25 -val SCE_PL_STRING_Q=26 -val SCE_PL_STRING_QQ=27 -val SCE_PL_STRING_QX=28 -val SCE_PL_STRING_QR=29 -val SCE_PL_STRING_QW=30 -val SCE_PL_POD_VERB=31 -val SCE_PL_SUB_PROTOTYPE=40 -val SCE_PL_FORMAT_IDENT=41 -val SCE_PL_FORMAT=42 -val SCE_PL_STRING_VAR=43 -val SCE_PL_XLAT=44 -val SCE_PL_REGEX_VAR=54 -val SCE_PL_REGSUBST_VAR=55 -val SCE_PL_BACKTICKS_VAR=57 -val SCE_PL_HERE_QQ_VAR=61 -val SCE_PL_HERE_QX_VAR=62 -val SCE_PL_STRING_QQ_VAR=64 -val SCE_PL_STRING_QX_VAR=65 -val SCE_PL_STRING_QR_VAR=66 -# Lexical states for SCLEX_RUBY -lex Ruby=SCLEX_RUBY SCE_RB_ -val SCE_RB_DEFAULT=0 -val SCE_RB_ERROR=1 -val SCE_RB_COMMENTLINE=2 -val SCE_RB_POD=3 -val SCE_RB_NUMBER=4 -val SCE_RB_WORD=5 -val SCE_RB_STRING=6 -val SCE_RB_CHARACTER=7 -val SCE_RB_CLASSNAME=8 -val SCE_RB_DEFNAME=9 -val SCE_RB_OPERATOR=10 -val SCE_RB_IDENTIFIER=11 -val SCE_RB_REGEX=12 -val SCE_RB_GLOBAL=13 -val SCE_RB_SYMBOL=14 -val SCE_RB_MODULE_NAME=15 -val SCE_RB_INSTANCE_VAR=16 -val SCE_RB_CLASS_VAR=17 -val SCE_RB_BACKTICKS=18 -val SCE_RB_DATASECTION=19 -val SCE_RB_HERE_DELIM=20 -val SCE_RB_HERE_Q=21 -val SCE_RB_HERE_QQ=22 -val SCE_RB_HERE_QX=23 -val SCE_RB_STRING_Q=24 -val SCE_RB_STRING_QQ=25 -val SCE_RB_STRING_QX=26 -val SCE_RB_STRING_QR=27 -val SCE_RB_STRING_QW=28 -val SCE_RB_WORD_DEMOTED=29 -val SCE_RB_STDIN=30 -val SCE_RB_STDOUT=31 -val SCE_RB_STDERR=40 -val SCE_RB_UPPER_BOUND=41 -# Lexical states for SCLEX_VB, SCLEX_VBSCRIPT, SCLEX_POWERBASIC -lex VB=SCLEX_VB SCE_B_ -lex VBScript=SCLEX_VBSCRIPT SCE_B_ -lex PowerBasic=SCLEX_POWERBASIC SCE_B_ -val SCE_B_DEFAULT=0 -val SCE_B_COMMENT=1 -val SCE_B_NUMBER=2 -val SCE_B_KEYWORD=3 -val SCE_B_STRING=4 -val SCE_B_PREPROCESSOR=5 -val SCE_B_OPERATOR=6 -val SCE_B_IDENTIFIER=7 -val SCE_B_DATE=8 -val SCE_B_STRINGEOL=9 -val SCE_B_KEYWORD2=10 -val SCE_B_KEYWORD3=11 -val SCE_B_KEYWORD4=12 -val SCE_B_CONSTANT=13 -val SCE_B_ASM=14 -val SCE_B_LABEL=15 -val SCE_B_ERROR=16 -val SCE_B_HEXNUMBER=17 -val SCE_B_BINNUMBER=18 -# Lexical states for SCLEX_PROPERTIES -lex Properties=SCLEX_PROPERTIES SCE_PROPS_ -val SCE_PROPS_DEFAULT=0 -val SCE_PROPS_COMMENT=1 -val SCE_PROPS_SECTION=2 -val SCE_PROPS_ASSIGNMENT=3 -val SCE_PROPS_DEFVAL=4 -val SCE_PROPS_KEY=5 -# Lexical states for SCLEX_LATEX -lex LaTeX=SCLEX_LATEX SCE_L_ -val SCE_L_DEFAULT=0 -val SCE_L_COMMAND=1 -val SCE_L_TAG=2 -val SCE_L_MATH=3 -val SCE_L_COMMENT=4 -val SCE_L_TAG2=5 -val SCE_L_MATH2=6 -val SCE_L_COMMENT2=7 -val SCE_L_VERBATIM=8 -val SCE_L_SHORTCMD=9 -val SCE_L_SPECIAL=10 -val SCE_L_CMDOPT=11 -val SCE_L_ERROR=12 -# Lexical states for SCLEX_LUA -lex Lua=SCLEX_LUA SCE_LUA_ -val SCE_LUA_DEFAULT=0 -val SCE_LUA_COMMENT=1 -val SCE_LUA_COMMENTLINE=2 -val SCE_LUA_COMMENTDOC=3 -val SCE_LUA_NUMBER=4 -val SCE_LUA_WORD=5 -val SCE_LUA_STRING=6 -val SCE_LUA_CHARACTER=7 -val SCE_LUA_LITERALSTRING=8 -val SCE_LUA_PREPROCESSOR=9 -val SCE_LUA_OPERATOR=10 -val SCE_LUA_IDENTIFIER=11 -val SCE_LUA_STRINGEOL=12 -val SCE_LUA_WORD2=13 -val SCE_LUA_WORD3=14 -val SCE_LUA_WORD4=15 -val SCE_LUA_WORD5=16 -val SCE_LUA_WORD6=17 -val SCE_LUA_WORD7=18 -val SCE_LUA_WORD8=19 -val SCE_LUA_LABEL=20 -# Lexical states for SCLEX_ERRORLIST -lex ErrorList=SCLEX_ERRORLIST SCE_ERR_ -val SCE_ERR_DEFAULT=0 -val SCE_ERR_PYTHON=1 -val SCE_ERR_GCC=2 -val SCE_ERR_MS=3 -val SCE_ERR_CMD=4 -val SCE_ERR_BORLAND=5 -val SCE_ERR_PERL=6 -val SCE_ERR_NET=7 -val SCE_ERR_LUA=8 -val SCE_ERR_CTAG=9 -val SCE_ERR_DIFF_CHANGED=10 -val SCE_ERR_DIFF_ADDITION=11 -val SCE_ERR_DIFF_DELETION=12 -val SCE_ERR_DIFF_MESSAGE=13 -val SCE_ERR_PHP=14 -val SCE_ERR_ELF=15 -val SCE_ERR_IFC=16 -val SCE_ERR_IFORT=17 -val SCE_ERR_ABSF=18 -val SCE_ERR_TIDY=19 -val SCE_ERR_JAVA_STACK=20 -val SCE_ERR_VALUE=21 -# Lexical states for SCLEX_BATCH -lex Batch=SCLEX_BATCH SCE_BAT_ -val SCE_BAT_DEFAULT=0 -val SCE_BAT_COMMENT=1 -val SCE_BAT_WORD=2 -val SCE_BAT_LABEL=3 -val SCE_BAT_HIDE=4 -val SCE_BAT_COMMAND=5 -val SCE_BAT_IDENTIFIER=6 -val SCE_BAT_OPERATOR=7 -# Lexical states for SCLEX_TCMD -lex TCMD=SCLEX_TCMD SCE_TCMD_ -val SCE_TCMD_DEFAULT=0 -val SCE_TCMD_COMMENT=1 -val SCE_TCMD_WORD=2 -val SCE_TCMD_LABEL=3 -val SCE_TCMD_HIDE=4 -val SCE_TCMD_COMMAND=5 -val SCE_TCMD_IDENTIFIER=6 -val SCE_TCMD_OPERATOR=7 -val SCE_TCMD_ENVIRONMENT=8 -val SCE_TCMD_EXPANSION=9 -val SCE_TCMD_CLABEL=10 -# Lexical states for SCLEX_MAKEFILE -lex MakeFile=SCLEX_MAKEFILE SCE_MAKE_ -val SCE_MAKE_DEFAULT=0 -val SCE_MAKE_COMMENT=1 -val SCE_MAKE_PREPROCESSOR=2 -val SCE_MAKE_IDENTIFIER=3 -val SCE_MAKE_OPERATOR=4 -val SCE_MAKE_TARGET=5 -val SCE_MAKE_IDEOL=9 -# Lexical states for SCLEX_DIFF -lex Diff=SCLEX_DIFF SCE_DIFF_ -val SCE_DIFF_DEFAULT=0 -val SCE_DIFF_COMMENT=1 -val SCE_DIFF_COMMAND=2 -val SCE_DIFF_HEADER=3 -val SCE_DIFF_POSITION=4 -val SCE_DIFF_DELETED=5 -val SCE_DIFF_ADDED=6 -val SCE_DIFF_CHANGED=7 -# Lexical states for SCLEX_CONF (Apache Configuration Files Lexer) -lex Conf=SCLEX_CONF SCE_CONF_ -val SCE_CONF_DEFAULT=0 -val SCE_CONF_COMMENT=1 -val SCE_CONF_NUMBER=2 -val SCE_CONF_IDENTIFIER=3 -val SCE_CONF_EXTENSION=4 -val SCE_CONF_PARAMETER=5 -val SCE_CONF_STRING=6 -val SCE_CONF_OPERATOR=7 -val SCE_CONF_IP=8 -val SCE_CONF_DIRECTIVE=9 -# Lexical states for SCLEX_AVE, Avenue -lex Avenue=SCLEX_AVE SCE_AVE_ -val SCE_AVE_DEFAULT=0 -val SCE_AVE_COMMENT=1 -val SCE_AVE_NUMBER=2 -val SCE_AVE_WORD=3 -val SCE_AVE_STRING=6 -val SCE_AVE_ENUM=7 -val SCE_AVE_STRINGEOL=8 -val SCE_AVE_IDENTIFIER=9 -val SCE_AVE_OPERATOR=10 -val SCE_AVE_WORD1=11 -val SCE_AVE_WORD2=12 -val SCE_AVE_WORD3=13 -val SCE_AVE_WORD4=14 -val SCE_AVE_WORD5=15 -val SCE_AVE_WORD6=16 -# Lexical states for SCLEX_ADA -lex Ada=SCLEX_ADA SCE_ADA_ -val SCE_ADA_DEFAULT=0 -val SCE_ADA_WORD=1 -val SCE_ADA_IDENTIFIER=2 -val SCE_ADA_NUMBER=3 -val SCE_ADA_DELIMITER=4 -val SCE_ADA_CHARACTER=5 -val SCE_ADA_CHARACTEREOL=6 -val SCE_ADA_STRING=7 -val SCE_ADA_STRINGEOL=8 -val SCE_ADA_LABEL=9 -val SCE_ADA_COMMENTLINE=10 -val SCE_ADA_ILLEGAL=11 -# Lexical states for SCLEX_BAAN -lex Baan=SCLEX_BAAN SCE_BAAN_ -val SCE_BAAN_DEFAULT=0 -val SCE_BAAN_COMMENT=1 -val SCE_BAAN_COMMENTDOC=2 -val SCE_BAAN_NUMBER=3 -val SCE_BAAN_WORD=4 -val SCE_BAAN_STRING=5 -val SCE_BAAN_PREPROCESSOR=6 -val SCE_BAAN_OPERATOR=7 -val SCE_BAAN_IDENTIFIER=8 -val SCE_BAAN_STRINGEOL=9 -val SCE_BAAN_WORD2=10 -# Lexical states for SCLEX_LISP -lex Lisp=SCLEX_LISP SCE_LISP_ -val SCE_LISP_DEFAULT=0 -val SCE_LISP_COMMENT=1 -val SCE_LISP_NUMBER=2 -val SCE_LISP_KEYWORD=3 -val SCE_LISP_KEYWORD_KW=4 -val SCE_LISP_SYMBOL=5 -val SCE_LISP_STRING=6 -val SCE_LISP_STRINGEOL=8 -val SCE_LISP_IDENTIFIER=9 -val SCE_LISP_OPERATOR=10 -val SCE_LISP_SPECIAL=11 -val SCE_LISP_MULTI_COMMENT=12 -# Lexical states for SCLEX_EIFFEL and SCLEX_EIFFELKW -lex Eiffel=SCLEX_EIFFEL SCE_EIFFEL_ -lex EiffelKW=SCLEX_EIFFELKW SCE_EIFFEL_ -val SCE_EIFFEL_DEFAULT=0 -val SCE_EIFFEL_COMMENTLINE=1 -val SCE_EIFFEL_NUMBER=2 -val SCE_EIFFEL_WORD=3 -val SCE_EIFFEL_STRING=4 -val SCE_EIFFEL_CHARACTER=5 -val SCE_EIFFEL_OPERATOR=6 -val SCE_EIFFEL_IDENTIFIER=7 -val SCE_EIFFEL_STRINGEOL=8 -# Lexical states for SCLEX_NNCRONTAB (nnCron crontab Lexer) -lex NNCronTab=SCLEX_NNCRONTAB SCE_NNCRONTAB_ -val SCE_NNCRONTAB_DEFAULT=0 -val SCE_NNCRONTAB_COMMENT=1 -val SCE_NNCRONTAB_TASK=2 -val SCE_NNCRONTAB_SECTION=3 -val SCE_NNCRONTAB_KEYWORD=4 -val SCE_NNCRONTAB_MODIFIER=5 -val SCE_NNCRONTAB_ASTERISK=6 -val SCE_NNCRONTAB_NUMBER=7 -val SCE_NNCRONTAB_STRING=8 -val SCE_NNCRONTAB_ENVIRONMENT=9 -val SCE_NNCRONTAB_IDENTIFIER=10 -# Lexical states for SCLEX_FORTH (Forth Lexer) -lex Forth=SCLEX_FORTH SCE_FORTH_ -val SCE_FORTH_DEFAULT=0 -val SCE_FORTH_COMMENT=1 -val SCE_FORTH_COMMENT_ML=2 -val SCE_FORTH_IDENTIFIER=3 -val SCE_FORTH_CONTROL=4 -val SCE_FORTH_KEYWORD=5 -val SCE_FORTH_DEFWORD=6 -val SCE_FORTH_PREWORD1=7 -val SCE_FORTH_PREWORD2=8 -val SCE_FORTH_NUMBER=9 -val SCE_FORTH_STRING=10 -val SCE_FORTH_LOCALE=11 -# Lexical states for SCLEX_MATLAB -lex MatLab=SCLEX_MATLAB SCE_MATLAB_ -val SCE_MATLAB_DEFAULT=0 -val SCE_MATLAB_COMMENT=1 -val SCE_MATLAB_COMMAND=2 -val SCE_MATLAB_NUMBER=3 -val SCE_MATLAB_KEYWORD=4 -# single quoted string -val SCE_MATLAB_STRING=5 -val SCE_MATLAB_OPERATOR=6 -val SCE_MATLAB_IDENTIFIER=7 -val SCE_MATLAB_DOUBLEQUOTESTRING=8 -# Lexical states for SCLEX_SCRIPTOL -lex Sol=SCLEX_SCRIPTOL SCE_SCRIPTOL_ -val SCE_SCRIPTOL_DEFAULT=0 -val SCE_SCRIPTOL_WHITE=1 -val SCE_SCRIPTOL_COMMENTLINE=2 -val SCE_SCRIPTOL_PERSISTENT=3 -val SCE_SCRIPTOL_CSTYLE=4 -val SCE_SCRIPTOL_COMMENTBLOCK=5 -val SCE_SCRIPTOL_NUMBER=6 -val SCE_SCRIPTOL_STRING=7 -val SCE_SCRIPTOL_CHARACTER=8 -val SCE_SCRIPTOL_STRINGEOL=9 -val SCE_SCRIPTOL_KEYWORD=10 -val SCE_SCRIPTOL_OPERATOR=11 -val SCE_SCRIPTOL_IDENTIFIER=12 -val SCE_SCRIPTOL_TRIPLE=13 -val SCE_SCRIPTOL_CLASSNAME=14 -val SCE_SCRIPTOL_PREPROCESSOR=15 -# Lexical states for SCLEX_ASM -lex Asm=SCLEX_ASM SCE_ASM_ -val SCE_ASM_DEFAULT=0 -val SCE_ASM_COMMENT=1 -val SCE_ASM_NUMBER=2 -val SCE_ASM_STRING=3 -val SCE_ASM_OPERATOR=4 -val SCE_ASM_IDENTIFIER=5 -val SCE_ASM_CPUINSTRUCTION=6 -val SCE_ASM_MATHINSTRUCTION=7 -val SCE_ASM_REGISTER=8 -val SCE_ASM_DIRECTIVE=9 -val SCE_ASM_DIRECTIVEOPERAND=10 -val SCE_ASM_COMMENTBLOCK=11 -val SCE_ASM_CHARACTER=12 -val SCE_ASM_STRINGEOL=13 -val SCE_ASM_EXTINSTRUCTION=14 -val SCE_ASM_COMMENTDIRECTIVE=15 -# Lexical states for SCLEX_FORTRAN -lex Fortran=SCLEX_FORTRAN SCE_F_ -lex F77=SCLEX_F77 SCE_F_ -val SCE_F_DEFAULT=0 -val SCE_F_COMMENT=1 -val SCE_F_NUMBER=2 -val SCE_F_STRING1=3 -val SCE_F_STRING2=4 -val SCE_F_STRINGEOL=5 -val SCE_F_OPERATOR=6 -val SCE_F_IDENTIFIER=7 -val SCE_F_WORD=8 -val SCE_F_WORD2=9 -val SCE_F_WORD3=10 -val SCE_F_PREPROCESSOR=11 -val SCE_F_OPERATOR2=12 -val SCE_F_LABEL=13 -val SCE_F_CONTINUATION=14 -# Lexical states for SCLEX_CSS -lex CSS=SCLEX_CSS SCE_CSS_ -val SCE_CSS_DEFAULT=0 -val SCE_CSS_TAG=1 -val SCE_CSS_CLASS=2 -val SCE_CSS_PSEUDOCLASS=3 -val SCE_CSS_UNKNOWN_PSEUDOCLASS=4 -val SCE_CSS_OPERATOR=5 -val SCE_CSS_IDENTIFIER=6 -val SCE_CSS_UNKNOWN_IDENTIFIER=7 -val SCE_CSS_VALUE=8 -val SCE_CSS_COMMENT=9 -val SCE_CSS_ID=10 -val SCE_CSS_IMPORTANT=11 -val SCE_CSS_DIRECTIVE=12 -val SCE_CSS_DOUBLESTRING=13 -val SCE_CSS_SINGLESTRING=14 -val SCE_CSS_IDENTIFIER2=15 -val SCE_CSS_ATTRIBUTE=16 -val SCE_CSS_IDENTIFIER3=17 -val SCE_CSS_PSEUDOELEMENT=18 -val SCE_CSS_EXTENDED_IDENTIFIER=19 -val SCE_CSS_EXTENDED_PSEUDOCLASS=20 -val SCE_CSS_EXTENDED_PSEUDOELEMENT=21 -val SCE_CSS_MEDIA=22 -val SCE_CSS_VARIABLE=23 -# Lexical states for SCLEX_POV -lex POV=SCLEX_POV SCE_POV_ -val SCE_POV_DEFAULT=0 -val SCE_POV_COMMENT=1 -val SCE_POV_COMMENTLINE=2 -val SCE_POV_NUMBER=3 -val SCE_POV_OPERATOR=4 -val SCE_POV_IDENTIFIER=5 -val SCE_POV_STRING=6 -val SCE_POV_STRINGEOL=7 -val SCE_POV_DIRECTIVE=8 -val SCE_POV_BADDIRECTIVE=9 -val SCE_POV_WORD2=10 -val SCE_POV_WORD3=11 -val SCE_POV_WORD4=12 -val SCE_POV_WORD5=13 -val SCE_POV_WORD6=14 -val SCE_POV_WORD7=15 -val SCE_POV_WORD8=16 -# Lexical states for SCLEX_LOUT -lex LOUT=SCLEX_LOUT SCE_LOUT_ -val SCE_LOUT_DEFAULT=0 -val SCE_LOUT_COMMENT=1 -val SCE_LOUT_NUMBER=2 -val SCE_LOUT_WORD=3 -val SCE_LOUT_WORD2=4 -val SCE_LOUT_WORD3=5 -val SCE_LOUT_WORD4=6 -val SCE_LOUT_STRING=7 -val SCE_LOUT_OPERATOR=8 -val SCE_LOUT_IDENTIFIER=9 -val SCE_LOUT_STRINGEOL=10 -# Lexical states for SCLEX_ESCRIPT -lex ESCRIPT=SCLEX_ESCRIPT SCE_ESCRIPT_ -val SCE_ESCRIPT_DEFAULT=0 -val SCE_ESCRIPT_COMMENT=1 -val SCE_ESCRIPT_COMMENTLINE=2 -val SCE_ESCRIPT_COMMENTDOC=3 -val SCE_ESCRIPT_NUMBER=4 -val SCE_ESCRIPT_WORD=5 -val SCE_ESCRIPT_STRING=6 -val SCE_ESCRIPT_OPERATOR=7 -val SCE_ESCRIPT_IDENTIFIER=8 -val SCE_ESCRIPT_BRACE=9 -val SCE_ESCRIPT_WORD2=10 -val SCE_ESCRIPT_WORD3=11 -# Lexical states for SCLEX_PS -lex PS=SCLEX_PS SCE_PS_ -val SCE_PS_DEFAULT=0 -val SCE_PS_COMMENT=1 -val SCE_PS_DSC_COMMENT=2 -val SCE_PS_DSC_VALUE=3 -val SCE_PS_NUMBER=4 -val SCE_PS_NAME=5 -val SCE_PS_KEYWORD=6 -val SCE_PS_LITERAL=7 -val SCE_PS_IMMEVAL=8 -val SCE_PS_PAREN_ARRAY=9 -val SCE_PS_PAREN_DICT=10 -val SCE_PS_PAREN_PROC=11 -val SCE_PS_TEXT=12 -val SCE_PS_HEXSTRING=13 -val SCE_PS_BASE85STRING=14 -val SCE_PS_BADSTRINGCHAR=15 -# Lexical states for SCLEX_NSIS -lex NSIS=SCLEX_NSIS SCE_NSIS_ -val SCE_NSIS_DEFAULT=0 -val SCE_NSIS_COMMENT=1 -val SCE_NSIS_STRINGDQ=2 -val SCE_NSIS_STRINGLQ=3 -val SCE_NSIS_STRINGRQ=4 -val SCE_NSIS_FUNCTION=5 -val SCE_NSIS_VARIABLE=6 -val SCE_NSIS_LABEL=7 -val SCE_NSIS_USERDEFINED=8 -val SCE_NSIS_SECTIONDEF=9 -val SCE_NSIS_SUBSECTIONDEF=10 -val SCE_NSIS_IFDEFINEDEF=11 -val SCE_NSIS_MACRODEF=12 -val SCE_NSIS_STRINGVAR=13 -val SCE_NSIS_NUMBER=14 -val SCE_NSIS_SECTIONGROUP=15 -val SCE_NSIS_PAGEEX=16 -val SCE_NSIS_FUNCTIONDEF=17 -val SCE_NSIS_COMMENTBOX=18 -# Lexical states for SCLEX_MMIXAL -lex MMIXAL=SCLEX_MMIXAL SCE_MMIXAL_ -val SCE_MMIXAL_LEADWS=0 -val SCE_MMIXAL_COMMENT=1 -val SCE_MMIXAL_LABEL=2 -val SCE_MMIXAL_OPCODE=3 -val SCE_MMIXAL_OPCODE_PRE=4 -val SCE_MMIXAL_OPCODE_VALID=5 -val SCE_MMIXAL_OPCODE_UNKNOWN=6 -val SCE_MMIXAL_OPCODE_POST=7 -val SCE_MMIXAL_OPERANDS=8 -val SCE_MMIXAL_NUMBER=9 -val SCE_MMIXAL_REF=10 -val SCE_MMIXAL_CHAR=11 -val SCE_MMIXAL_STRING=12 -val SCE_MMIXAL_REGISTER=13 -val SCE_MMIXAL_HEX=14 -val SCE_MMIXAL_OPERATOR=15 -val SCE_MMIXAL_SYMBOL=16 -val SCE_MMIXAL_INCLUDE=17 -# Lexical states for SCLEX_CLW -lex Clarion=SCLEX_CLW SCE_CLW_ -val SCE_CLW_DEFAULT=0 -val SCE_CLW_LABEL=1 -val SCE_CLW_COMMENT=2 -val SCE_CLW_STRING=3 -val SCE_CLW_USER_IDENTIFIER=4 -val SCE_CLW_INTEGER_CONSTANT=5 -val SCE_CLW_REAL_CONSTANT=6 -val SCE_CLW_PICTURE_STRING=7 -val SCE_CLW_KEYWORD=8 -val SCE_CLW_COMPILER_DIRECTIVE=9 -val SCE_CLW_RUNTIME_EXPRESSIONS=10 -val SCE_CLW_BUILTIN_PROCEDURES_FUNCTION=11 -val SCE_CLW_STRUCTURE_DATA_TYPE=12 -val SCE_CLW_ATTRIBUTE=13 -val SCE_CLW_STANDARD_EQUATE=14 -val SCE_CLW_ERROR=15 -val SCE_CLW_DEPRECATED=16 -# Lexical states for SCLEX_LOT -lex LOT=SCLEX_LOT SCE_LOT_ -val SCE_LOT_DEFAULT=0 -val SCE_LOT_HEADER=1 -val SCE_LOT_BREAK=2 -val SCE_LOT_SET=3 -val SCE_LOT_PASS=4 -val SCE_LOT_FAIL=5 -val SCE_LOT_ABORT=6 -# Lexical states for SCLEX_YAML -lex YAML=SCLEX_YAML SCE_YAML_ -val SCE_YAML_DEFAULT=0 -val SCE_YAML_COMMENT=1 -val SCE_YAML_IDENTIFIER=2 -val SCE_YAML_KEYWORD=3 -val SCE_YAML_NUMBER=4 -val SCE_YAML_REFERENCE=5 -val SCE_YAML_DOCUMENT=6 -val SCE_YAML_TEXT=7 -val SCE_YAML_ERROR=8 -val SCE_YAML_OPERATOR=9 -# Lexical states for SCLEX_TEX -lex TeX=SCLEX_TEX SCE_TEX_ -val SCE_TEX_DEFAULT=0 -val SCE_TEX_SPECIAL=1 -val SCE_TEX_GROUP=2 -val SCE_TEX_SYMBOL=3 -val SCE_TEX_COMMAND=4 -val SCE_TEX_TEXT=5 -lex Metapost=SCLEX_METAPOST SCE_METAPOST_ -val SCE_METAPOST_DEFAULT=0 -val SCE_METAPOST_SPECIAL=1 -val SCE_METAPOST_GROUP=2 -val SCE_METAPOST_SYMBOL=3 -val SCE_METAPOST_COMMAND=4 -val SCE_METAPOST_TEXT=5 -val SCE_METAPOST_EXTRA=6 -# Lexical states for SCLEX_ERLANG -lex Erlang=SCLEX_ERLANG SCE_ERLANG_ -val SCE_ERLANG_DEFAULT=0 -val SCE_ERLANG_COMMENT=1 -val SCE_ERLANG_VARIABLE=2 -val SCE_ERLANG_NUMBER=3 -val SCE_ERLANG_KEYWORD=4 -val SCE_ERLANG_STRING=5 -val SCE_ERLANG_OPERATOR=6 -val SCE_ERLANG_ATOM=7 -val SCE_ERLANG_FUNCTION_NAME=8 -val SCE_ERLANG_CHARACTER=9 -val SCE_ERLANG_MACRO=10 -val SCE_ERLANG_RECORD=11 -val SCE_ERLANG_PREPROC=12 -val SCE_ERLANG_NODE_NAME=13 -val SCE_ERLANG_COMMENT_FUNCTION=14 -val SCE_ERLANG_COMMENT_MODULE=15 -val SCE_ERLANG_COMMENT_DOC=16 -val SCE_ERLANG_COMMENT_DOC_MACRO=17 -val SCE_ERLANG_ATOM_QUOTED=18 -val SCE_ERLANG_MACRO_QUOTED=19 -val SCE_ERLANG_RECORD_QUOTED=20 -val SCE_ERLANG_NODE_NAME_QUOTED=21 -val SCE_ERLANG_BIFS=22 -val SCE_ERLANG_MODULES=23 -val SCE_ERLANG_MODULES_ATT=24 -val SCE_ERLANG_UNKNOWN=31 -# Lexical states for SCLEX_OCTAVE are identical to MatLab -lex Octave=SCLEX_OCTAVE SCE_MATLAB_ -# Lexical states for SCLEX_MSSQL -lex MSSQL=SCLEX_MSSQL SCE_MSSQL_ -val SCE_MSSQL_DEFAULT=0 -val SCE_MSSQL_COMMENT=1 -val SCE_MSSQL_LINE_COMMENT=2 -val SCE_MSSQL_NUMBER=3 -val SCE_MSSQL_STRING=4 -val SCE_MSSQL_OPERATOR=5 -val SCE_MSSQL_IDENTIFIER=6 -val SCE_MSSQL_VARIABLE=7 -val SCE_MSSQL_COLUMN_NAME=8 -val SCE_MSSQL_STATEMENT=9 -val SCE_MSSQL_DATATYPE=10 -val SCE_MSSQL_SYSTABLE=11 -val SCE_MSSQL_GLOBAL_VARIABLE=12 -val SCE_MSSQL_FUNCTION=13 -val SCE_MSSQL_STORED_PROCEDURE=14 -val SCE_MSSQL_DEFAULT_PREF_DATATYPE=15 -val SCE_MSSQL_COLUMN_NAME_2=16 -# Lexical states for SCLEX_VERILOG -lex Verilog=SCLEX_VERILOG SCE_V_ -val SCE_V_DEFAULT=0 -val SCE_V_COMMENT=1 -val SCE_V_COMMENTLINE=2 -val SCE_V_COMMENTLINEBANG=3 -val SCE_V_NUMBER=4 -val SCE_V_WORD=5 -val SCE_V_STRING=6 -val SCE_V_WORD2=7 -val SCE_V_WORD3=8 -val SCE_V_PREPROCESSOR=9 -val SCE_V_OPERATOR=10 -val SCE_V_IDENTIFIER=11 -val SCE_V_STRINGEOL=12 -val SCE_V_USER=19 -# Lexical states for SCLEX_KIX -lex Kix=SCLEX_KIX SCE_KIX_ -val SCE_KIX_DEFAULT=0 -val SCE_KIX_COMMENT=1 -val SCE_KIX_STRING1=2 -val SCE_KIX_STRING2=3 -val SCE_KIX_NUMBER=4 -val SCE_KIX_VAR=5 -val SCE_KIX_MACRO=6 -val SCE_KIX_KEYWORD=7 -val SCE_KIX_FUNCTIONS=8 -val SCE_KIX_OPERATOR=9 -val SCE_KIX_IDENTIFIER=31 -# Lexical states for SCLEX_GUI4CLI -val SCE_GC_DEFAULT=0 -val SCE_GC_COMMENTLINE=1 -val SCE_GC_COMMENTBLOCK=2 -val SCE_GC_GLOBAL=3 -val SCE_GC_EVENT=4 -val SCE_GC_ATTRIBUTE=5 -val SCE_GC_CONTROL=6 -val SCE_GC_COMMAND=7 -val SCE_GC_STRING=8 -val SCE_GC_OPERATOR=9 -# Lexical states for SCLEX_SPECMAN -lex Specman=SCLEX_SPECMAN SCE_SN_ -val SCE_SN_DEFAULT=0 -val SCE_SN_CODE=1 -val SCE_SN_COMMENTLINE=2 -val SCE_SN_COMMENTLINEBANG=3 -val SCE_SN_NUMBER=4 -val SCE_SN_WORD=5 -val SCE_SN_STRING=6 -val SCE_SN_WORD2=7 -val SCE_SN_WORD3=8 -val SCE_SN_PREPROCESSOR=9 -val SCE_SN_OPERATOR=10 -val SCE_SN_IDENTIFIER=11 -val SCE_SN_STRINGEOL=12 -val SCE_SN_REGEXTAG=13 -val SCE_SN_SIGNAL=14 -val SCE_SN_USER=19 -# Lexical states for SCLEX_AU3 -lex Au3=SCLEX_AU3 SCE_AU3_ -val SCE_AU3_DEFAULT=0 -val SCE_AU3_COMMENT=1 -val SCE_AU3_COMMENTBLOCK=2 -val SCE_AU3_NUMBER=3 -val SCE_AU3_FUNCTION=4 -val SCE_AU3_KEYWORD=5 -val SCE_AU3_MACRO=6 -val SCE_AU3_STRING=7 -val SCE_AU3_OPERATOR=8 -val SCE_AU3_VARIABLE=9 -val SCE_AU3_SENT=10 -val SCE_AU3_PREPROCESSOR=11 -val SCE_AU3_SPECIAL=12 -val SCE_AU3_EXPAND=13 -val SCE_AU3_COMOBJ=14 -val SCE_AU3_UDF=15 -# Lexical states for SCLEX_APDL -lex APDL=SCLEX_APDL SCE_APDL_ -val SCE_APDL_DEFAULT=0 -val SCE_APDL_COMMENT=1 -val SCE_APDL_COMMENTBLOCK=2 -val SCE_APDL_NUMBER=3 -val SCE_APDL_STRING=4 -val SCE_APDL_OPERATOR=5 -val SCE_APDL_WORD=6 -val SCE_APDL_PROCESSOR=7 -val SCE_APDL_COMMAND=8 -val SCE_APDL_SLASHCOMMAND=9 -val SCE_APDL_STARCOMMAND=10 -val SCE_APDL_ARGUMENT=11 -val SCE_APDL_FUNCTION=12 -# Lexical states for SCLEX_BASH -lex Bash=SCLEX_BASH SCE_SH_ -val SCE_SH_DEFAULT=0 -val SCE_SH_ERROR=1 -val SCE_SH_COMMENTLINE=2 -val SCE_SH_NUMBER=3 -val SCE_SH_WORD=4 -val SCE_SH_STRING=5 -val SCE_SH_CHARACTER=6 -val SCE_SH_OPERATOR=7 -val SCE_SH_IDENTIFIER=8 -val SCE_SH_SCALAR=9 -val SCE_SH_PARAM=10 -val SCE_SH_BACKTICKS=11 -val SCE_SH_HERE_DELIM=12 -val SCE_SH_HERE_Q=13 -# Lexical states for SCLEX_ASN1 -lex Asn1=SCLEX_ASN1 SCE_ASN1_ -val SCE_ASN1_DEFAULT=0 -val SCE_ASN1_COMMENT=1 -val SCE_ASN1_IDENTIFIER=2 -val SCE_ASN1_STRING=3 -val SCE_ASN1_OID=4 -val SCE_ASN1_SCALAR=5 -val SCE_ASN1_KEYWORD=6 -val SCE_ASN1_ATTRIBUTE=7 -val SCE_ASN1_DESCRIPTOR=8 -val SCE_ASN1_TYPE=9 -val SCE_ASN1_OPERATOR=10 -# Lexical states for SCLEX_VHDL -lex VHDL=SCLEX_VHDL SCE_VHDL_ -val SCE_VHDL_DEFAULT=0 -val SCE_VHDL_COMMENT=1 -val SCE_VHDL_COMMENTLINEBANG=2 -val SCE_VHDL_NUMBER=3 -val SCE_VHDL_STRING=4 -val SCE_VHDL_OPERATOR=5 -val SCE_VHDL_IDENTIFIER=6 -val SCE_VHDL_STRINGEOL=7 -val SCE_VHDL_KEYWORD=8 -val SCE_VHDL_STDOPERATOR=9 -val SCE_VHDL_ATTRIBUTE=10 -val SCE_VHDL_STDFUNCTION=11 -val SCE_VHDL_STDPACKAGE=12 -val SCE_VHDL_STDTYPE=13 -val SCE_VHDL_USERWORD=14 -# Lexical states for SCLEX_CAML -lex Caml=SCLEX_CAML SCE_CAML_ -val SCE_CAML_DEFAULT=0 -val SCE_CAML_IDENTIFIER=1 -val SCE_CAML_TAGNAME=2 -val SCE_CAML_KEYWORD=3 -val SCE_CAML_KEYWORD2=4 -val SCE_CAML_KEYWORD3=5 -val SCE_CAML_LINENUM=6 -val SCE_CAML_OPERATOR=7 -val SCE_CAML_NUMBER=8 -val SCE_CAML_CHAR=9 -val SCE_CAML_WHITE=10 -val SCE_CAML_STRING=11 -val SCE_CAML_COMMENT=12 -val SCE_CAML_COMMENT1=13 -val SCE_CAML_COMMENT2=14 -val SCE_CAML_COMMENT3=15 -# Lexical states for SCLEX_HASKELL -lex Haskell=SCLEX_HASKELL SCE_HA_ -val SCE_HA_DEFAULT=0 -val SCE_HA_IDENTIFIER=1 -val SCE_HA_KEYWORD=2 -val SCE_HA_NUMBER=3 -val SCE_HA_STRING=4 -val SCE_HA_CHARACTER=5 -val SCE_HA_CLASS=6 -val SCE_HA_MODULE=7 -val SCE_HA_CAPITAL=8 -val SCE_HA_DATA=9 -val SCE_HA_IMPORT=10 -val SCE_HA_OPERATOR=11 -val SCE_HA_INSTANCE=12 -val SCE_HA_COMMENTLINE=13 -val SCE_HA_COMMENTBLOCK=14 -val SCE_HA_COMMENTBLOCK2=15 -val SCE_HA_COMMENTBLOCK3=16 -# Lexical states of SCLEX_TADS3 -lex TADS3=SCLEX_TADS3 SCE_T3_ -val SCE_T3_DEFAULT=0 -val SCE_T3_X_DEFAULT=1 -val SCE_T3_PREPROCESSOR=2 -val SCE_T3_BLOCK_COMMENT=3 -val SCE_T3_LINE_COMMENT=4 -val SCE_T3_OPERATOR=5 -val SCE_T3_KEYWORD=6 -val SCE_T3_NUMBER=7 -val SCE_T3_IDENTIFIER=8 -val SCE_T3_S_STRING=9 -val SCE_T3_D_STRING=10 -val SCE_T3_X_STRING=11 -val SCE_T3_LIB_DIRECTIVE=12 -val SCE_T3_MSG_PARAM=13 -val SCE_T3_HTML_TAG=14 -val SCE_T3_HTML_DEFAULT=15 -val SCE_T3_HTML_STRING=16 -val SCE_T3_USER1=17 -val SCE_T3_USER2=18 -val SCE_T3_USER3=19 -val SCE_T3_BRACE=20 -# Lexical states for SCLEX_REBOL -lex Rebol=SCLEX_REBOL SCE_REBOL_ -val SCE_REBOL_DEFAULT=0 -val SCE_REBOL_COMMENTLINE=1 -val SCE_REBOL_COMMENTBLOCK=2 -val SCE_REBOL_PREFACE=3 -val SCE_REBOL_OPERATOR=4 -val SCE_REBOL_CHARACTER=5 -val SCE_REBOL_QUOTEDSTRING=6 -val SCE_REBOL_BRACEDSTRING=7 -val SCE_REBOL_NUMBER=8 -val SCE_REBOL_PAIR=9 -val SCE_REBOL_TUPLE=10 -val SCE_REBOL_BINARY=11 -val SCE_REBOL_MONEY=12 -val SCE_REBOL_ISSUE=13 -val SCE_REBOL_TAG=14 -val SCE_REBOL_FILE=15 -val SCE_REBOL_EMAIL=16 -val SCE_REBOL_URL=17 -val SCE_REBOL_DATE=18 -val SCE_REBOL_TIME=19 -val SCE_REBOL_IDENTIFIER=20 -val SCE_REBOL_WORD=21 -val SCE_REBOL_WORD2=22 -val SCE_REBOL_WORD3=23 -val SCE_REBOL_WORD4=24 -val SCE_REBOL_WORD5=25 -val SCE_REBOL_WORD6=26 -val SCE_REBOL_WORD7=27 -val SCE_REBOL_WORD8=28 -# Lexical states for SCLEX_SQL -lex SQL=SCLEX_SQL SCE_SQL_ -val SCE_SQL_DEFAULT=0 -val SCE_SQL_COMMENT=1 -val SCE_SQL_COMMENTLINE=2 -val SCE_SQL_COMMENTDOC=3 -val SCE_SQL_NUMBER=4 -val SCE_SQL_WORD=5 -val SCE_SQL_STRING=6 -val SCE_SQL_CHARACTER=7 -val SCE_SQL_SQLPLUS=8 -val SCE_SQL_SQLPLUS_PROMPT=9 -val SCE_SQL_OPERATOR=10 -val SCE_SQL_IDENTIFIER=11 -val SCE_SQL_SQLPLUS_COMMENT=13 -val SCE_SQL_COMMENTLINEDOC=15 -val SCE_SQL_WORD2=16 -val SCE_SQL_COMMENTDOCKEYWORD=17 -val SCE_SQL_COMMENTDOCKEYWORDERROR=18 -val SCE_SQL_USER1=19 -val SCE_SQL_USER2=20 -val SCE_SQL_USER3=21 -val SCE_SQL_USER4=22 -val SCE_SQL_QUOTEDIDENTIFIER=23 -# Lexical states for SCLEX_SMALLTALK -lex Smalltalk=SCLEX_SMALLTALK SCE_ST_ -val SCE_ST_DEFAULT=0 -val SCE_ST_STRING=1 -val SCE_ST_NUMBER=2 -val SCE_ST_COMMENT=3 -val SCE_ST_SYMBOL=4 -val SCE_ST_BINARY=5 -val SCE_ST_BOOL=6 -val SCE_ST_SELF=7 -val SCE_ST_SUPER=8 -val SCE_ST_NIL=9 -val SCE_ST_GLOBAL=10 -val SCE_ST_RETURN=11 -val SCE_ST_SPECIAL=12 -val SCE_ST_KWSEND=13 -val SCE_ST_ASSIGN=14 -val SCE_ST_CHARACTER=15 -val SCE_ST_SPEC_SEL=16 -# Lexical states for SCLEX_FLAGSHIP (clipper) -lex FlagShip=SCLEX_FLAGSHIP SCE_FS_ -val SCE_FS_DEFAULT=0 -val SCE_FS_COMMENT=1 -val SCE_FS_COMMENTLINE=2 -val SCE_FS_COMMENTDOC=3 -val SCE_FS_COMMENTLINEDOC=4 -val SCE_FS_COMMENTDOCKEYWORD=5 -val SCE_FS_COMMENTDOCKEYWORDERROR=6 -val SCE_FS_KEYWORD=7 -val SCE_FS_KEYWORD2=8 -val SCE_FS_KEYWORD3=9 -val SCE_FS_KEYWORD4=10 -val SCE_FS_NUMBER=11 -val SCE_FS_STRING=12 -val SCE_FS_PREPROCESSOR=13 -val SCE_FS_OPERATOR=14 -val SCE_FS_IDENTIFIER=15 -val SCE_FS_DATE=16 -val SCE_FS_STRINGEOL=17 -val SCE_FS_CONSTANT=18 -val SCE_FS_WORDOPERATOR=19 -val SCE_FS_DISABLEDCODE=20 -val SCE_FS_DEFAULT_C=21 -val SCE_FS_COMMENTDOC_C=22 -val SCE_FS_COMMENTLINEDOC_C=23 -val SCE_FS_KEYWORD_C=24 -val SCE_FS_KEYWORD2_C=25 -val SCE_FS_NUMBER_C=26 -val SCE_FS_STRING_C=27 -val SCE_FS_PREPROCESSOR_C=28 -val SCE_FS_OPERATOR_C=29 -val SCE_FS_IDENTIFIER_C=30 -val SCE_FS_STRINGEOL_C=31 -# Lexical states for SCLEX_CSOUND -lex Csound=SCLEX_CSOUND SCE_CSOUND_ -val SCE_CSOUND_DEFAULT=0 -val SCE_CSOUND_COMMENT=1 -val SCE_CSOUND_NUMBER=2 -val SCE_CSOUND_OPERATOR=3 -val SCE_CSOUND_INSTR=4 -val SCE_CSOUND_IDENTIFIER=5 -val SCE_CSOUND_OPCODE=6 -val SCE_CSOUND_HEADERSTMT=7 -val SCE_CSOUND_USERKEYWORD=8 -val SCE_CSOUND_COMMENTBLOCK=9 -val SCE_CSOUND_PARAM=10 -val SCE_CSOUND_ARATE_VAR=11 -val SCE_CSOUND_KRATE_VAR=12 -val SCE_CSOUND_IRATE_VAR=13 -val SCE_CSOUND_GLOBAL_VAR=14 -val SCE_CSOUND_STRINGEOL=15 -# Lexical states for SCLEX_INNOSETUP -lex Inno=SCLEX_INNOSETUP SCE_INNO_ -val SCE_INNO_DEFAULT=0 -val SCE_INNO_COMMENT=1 -val SCE_INNO_KEYWORD=2 -val SCE_INNO_PARAMETER=3 -val SCE_INNO_SECTION=4 -val SCE_INNO_PREPROC=5 -val SCE_INNO_INLINE_EXPANSION=6 -val SCE_INNO_COMMENT_PASCAL=7 -val SCE_INNO_KEYWORD_PASCAL=8 -val SCE_INNO_KEYWORD_USER=9 -val SCE_INNO_STRING_DOUBLE=10 -val SCE_INNO_STRING_SINGLE=11 -val SCE_INNO_IDENTIFIER=12 -# Lexical states for SCLEX_OPAL -lex Opal=SCLEX_OPAL SCE_OPAL_ -val SCE_OPAL_SPACE=0 -val SCE_OPAL_COMMENT_BLOCK=1 -val SCE_OPAL_COMMENT_LINE=2 -val SCE_OPAL_INTEGER=3 -val SCE_OPAL_KEYWORD=4 -val SCE_OPAL_SORT=5 -val SCE_OPAL_STRING=6 -val SCE_OPAL_PAR=7 -val SCE_OPAL_BOOL_CONST=8 -val SCE_OPAL_DEFAULT=32 -# Lexical states for SCLEX_SPICE -lex Spice=SCLEX_SPICE SCE_SPICE_ -val SCE_SPICE_DEFAULT=0 -val SCE_SPICE_IDENTIFIER=1 -val SCE_SPICE_KEYWORD=2 -val SCE_SPICE_KEYWORD2=3 -val SCE_SPICE_KEYWORD3=4 -val SCE_SPICE_NUMBER=5 -val SCE_SPICE_DELIMITER=6 -val SCE_SPICE_VALUE=7 -val SCE_SPICE_COMMENTLINE=8 -# Lexical states for SCLEX_CMAKE -lex CMAKE=SCLEX_CMAKE SCE_CMAKE_ -val SCE_CMAKE_DEFAULT=0 -val SCE_CMAKE_COMMENT=1 -val SCE_CMAKE_STRINGDQ=2 -val SCE_CMAKE_STRINGLQ=3 -val SCE_CMAKE_STRINGRQ=4 -val SCE_CMAKE_COMMANDS=5 -val SCE_CMAKE_PARAMETERS=6 -val SCE_CMAKE_VARIABLE=7 -val SCE_CMAKE_USERDEFINED=8 -val SCE_CMAKE_WHILEDEF=9 -val SCE_CMAKE_FOREACHDEF=10 -val SCE_CMAKE_IFDEFINEDEF=11 -val SCE_CMAKE_MACRODEF=12 -val SCE_CMAKE_STRINGVAR=13 -val SCE_CMAKE_NUMBER=14 -# Lexical states for SCLEX_GAP -lex Gap=SCLEX_GAP SCE_GAP_ -val SCE_GAP_DEFAULT=0 -val SCE_GAP_IDENTIFIER=1 -val SCE_GAP_KEYWORD=2 -val SCE_GAP_KEYWORD2=3 -val SCE_GAP_KEYWORD3=4 -val SCE_GAP_KEYWORD4=5 -val SCE_GAP_STRING=6 -val SCE_GAP_CHAR=7 -val SCE_GAP_OPERATOR=8 -val SCE_GAP_COMMENT=9 -val SCE_GAP_NUMBER=10 -val SCE_GAP_STRINGEOL=11 -# Lexical state for SCLEX_PLM -lex PLM=SCLEX_PLM SCE_PLM_ -val SCE_PLM_DEFAULT=0 -val SCE_PLM_COMMENT=1 -val SCE_PLM_STRING=2 -val SCE_PLM_NUMBER=3 -val SCE_PLM_IDENTIFIER=4 -val SCE_PLM_OPERATOR=5 -val SCE_PLM_CONTROL=6 -val SCE_PLM_KEYWORD=7 -# Lexical state for SCLEX_PROGRESS -lex Progress=SCLEX_PROGRESS SCE_4GL_ -val SCE_4GL_DEFAULT=0 -val SCE_4GL_NUMBER=1 -val SCE_4GL_WORD=2 -val SCE_4GL_STRING=3 -val SCE_4GL_CHARACTER=4 -val SCE_4GL_PREPROCESSOR=5 -val SCE_4GL_OPERATOR=6 -val SCE_4GL_IDENTIFIER=7 -val SCE_4GL_BLOCK=8 -val SCE_4GL_END=9 -val SCE_4GL_COMMENT1=10 -val SCE_4GL_COMMENT2=11 -val SCE_4GL_COMMENT3=12 -val SCE_4GL_COMMENT4=13 -val SCE_4GL_COMMENT5=14 -val SCE_4GL_COMMENT6=15 -val SCE_4GL_DEFAULT_=16 -val SCE_4GL_NUMBER_=17 -val SCE_4GL_WORD_=18 -val SCE_4GL_STRING_=19 -val SCE_4GL_CHARACTER_=20 -val SCE_4GL_PREPROCESSOR_=21 -val SCE_4GL_OPERATOR_=22 -val SCE_4GL_IDENTIFIER_=23 -val SCE_4GL_BLOCK_=24 -val SCE_4GL_END_=25 -val SCE_4GL_COMMENT1_=26 -val SCE_4GL_COMMENT2_=27 -val SCE_4GL_COMMENT3_=28 -val SCE_4GL_COMMENT4_=29 -val SCE_4GL_COMMENT5_=30 -val SCE_4GL_COMMENT6_=31 -# Lexical states for SCLEX_ABAQUS -lex ABAQUS=SCLEX_ABAQUS SCE_ABAQUS_ -val SCE_ABAQUS_DEFAULT=0 -val SCE_ABAQUS_COMMENT=1 -val SCE_ABAQUS_COMMENTBLOCK=2 -val SCE_ABAQUS_NUMBER=3 -val SCE_ABAQUS_STRING=4 -val SCE_ABAQUS_OPERATOR=5 -val SCE_ABAQUS_WORD=6 -val SCE_ABAQUS_PROCESSOR=7 -val SCE_ABAQUS_COMMAND=8 -val SCE_ABAQUS_SLASHCOMMAND=9 -val SCE_ABAQUS_STARCOMMAND=10 -val SCE_ABAQUS_ARGUMENT=11 -val SCE_ABAQUS_FUNCTION=12 -# Lexical states for SCLEX_ASYMPTOTE -lex Asymptote=SCLEX_ASYMPTOTE SCE_ASY_ -val SCE_ASY_DEFAULT=0 -val SCE_ASY_COMMENT=1 -val SCE_ASY_COMMENTLINE=2 -val SCE_ASY_NUMBER=3 -val SCE_ASY_WORD=4 -val SCE_ASY_STRING=5 -val SCE_ASY_CHARACTER=6 -val SCE_ASY_OPERATOR=7 -val SCE_ASY_IDENTIFIER=8 -val SCE_ASY_STRINGEOL=9 -val SCE_ASY_COMMENTLINEDOC=10 -val SCE_ASY_WORD2=11 -# Lexical states for SCLEX_R -lex R=SCLEX_R SCE_R_ -val SCE_R_DEFAULT=0 -val SCE_R_COMMENT=1 -val SCE_R_KWORD=2 -val SCE_R_BASEKWORD=3 -val SCE_R_OTHERKWORD=4 -val SCE_R_NUMBER=5 -val SCE_R_STRING=6 -val SCE_R_STRING2=7 -val SCE_R_OPERATOR=8 -val SCE_R_IDENTIFIER=9 -val SCE_R_INFIX=10 -val SCE_R_INFIXEOL=11 -# Lexical state for SCLEX_MAGIKSF -lex MagikSF=SCLEX_MAGIKSF SCE_MAGIK_ -val SCE_MAGIK_DEFAULT=0 -val SCE_MAGIK_COMMENT=1 -val SCE_MAGIK_HYPER_COMMENT=16 -val SCE_MAGIK_STRING=2 -val SCE_MAGIK_CHARACTER=3 -val SCE_MAGIK_NUMBER=4 -val SCE_MAGIK_IDENTIFIER=5 -val SCE_MAGIK_OPERATOR=6 -val SCE_MAGIK_FLOW=7 -val SCE_MAGIK_CONTAINER=8 -val SCE_MAGIK_BRACKET_BLOCK=9 -val SCE_MAGIK_BRACE_BLOCK=10 -val SCE_MAGIK_SQBRACKET_BLOCK=11 -val SCE_MAGIK_UNKNOWN_KEYWORD=12 -val SCE_MAGIK_KEYWORD=13 -val SCE_MAGIK_PRAGMA=14 -val SCE_MAGIK_SYMBOL=15 -# Lexical state for SCLEX_POWERSHELL -lex PowerShell=SCLEX_POWERSHELL SCE_POWERSHELL_ -val SCE_POWERSHELL_DEFAULT=0 -val SCE_POWERSHELL_COMMENT=1 -val SCE_POWERSHELL_STRING=2 -val SCE_POWERSHELL_CHARACTER=3 -val SCE_POWERSHELL_NUMBER=4 -val SCE_POWERSHELL_VARIABLE=5 -val SCE_POWERSHELL_OPERATOR=6 -val SCE_POWERSHELL_IDENTIFIER=7 -val SCE_POWERSHELL_KEYWORD=8 -val SCE_POWERSHELL_CMDLET=9 -val SCE_POWERSHELL_ALIAS=10 -val SCE_POWERSHELL_FUNCTION=11 -val SCE_POWERSHELL_USER1=12 -val SCE_POWERSHELL_COMMENTSTREAM=13 -# Lexical state for SCLEX_MYSQL -lex MySQL=SCLEX_MYSQL SCE_MYSQL_ -val SCE_MYSQL_DEFAULT=0 -val SCE_MYSQL_COMMENT=1 -val SCE_MYSQL_COMMENTLINE=2 -val SCE_MYSQL_VARIABLE=3 -val SCE_MYSQL_SYSTEMVARIABLE=4 -val SCE_MYSQL_KNOWNSYSTEMVARIABLE=5 -val SCE_MYSQL_NUMBER=6 -val SCE_MYSQL_MAJORKEYWORD=7 -val SCE_MYSQL_KEYWORD=8 -val SCE_MYSQL_DATABASEOBJECT=9 -val SCE_MYSQL_PROCEDUREKEYWORD=10 -val SCE_MYSQL_STRING=11 -val SCE_MYSQL_SQSTRING=12 -val SCE_MYSQL_DQSTRING=13 -val SCE_MYSQL_OPERATOR=14 -val SCE_MYSQL_FUNCTION=15 -val SCE_MYSQL_IDENTIFIER=16 -val SCE_MYSQL_QUOTEDIDENTIFIER=17 -val SCE_MYSQL_USER1=18 -val SCE_MYSQL_USER2=19 -val SCE_MYSQL_USER3=20 -val SCE_MYSQL_HIDDENCOMMAND=21 -# Lexical state for SCLEX_PO -lex Po=SCLEX_PO SCE_PO_ -val SCE_PO_DEFAULT=0 -val SCE_PO_COMMENT=1 -val SCE_PO_MSGID=2 -val SCE_PO_MSGID_TEXT=3 -val SCE_PO_MSGSTR=4 -val SCE_PO_MSGSTR_TEXT=5 -val SCE_PO_MSGCTXT=6 -val SCE_PO_MSGCTXT_TEXT=7 -val SCE_PO_FUZZY=8 -# Lexical states for SCLEX_PASCAL -lex Pascal=SCLEX_PASCAL SCE_PAS_ -val SCE_PAS_DEFAULT=0 -val SCE_PAS_IDENTIFIER=1 -val SCE_PAS_COMMENT=2 -val SCE_PAS_COMMENT2=3 -val SCE_PAS_COMMENTLINE=4 -val SCE_PAS_PREPROCESSOR=5 -val SCE_PAS_PREPROCESSOR2=6 -val SCE_PAS_NUMBER=7 -val SCE_PAS_HEXNUMBER=8 -val SCE_PAS_WORD=9 -val SCE_PAS_STRING=10 -val SCE_PAS_STRINGEOL=11 -val SCE_PAS_CHARACTER=12 -val SCE_PAS_OPERATOR=13 -val SCE_PAS_ASM=14 -# Lexical state for SCLEX_SORCUS -lex SORCUS=SCLEX_SORCUS SCE_SORCUS_ -val SCE_SORCUS_DEFAULT=0 -val SCE_SORCUS_COMMAND=1 -val SCE_SORCUS_PARAMETER=2 -val SCE_SORCUS_COMMENTLINE=3 -val SCE_SORCUS_STRING=4 -val SCE_SORCUS_STRINGEOL=5 -val SCE_SORCUS_IDENTIFIER=6 -val SCE_SORCUS_OPERATOR=7 -val SCE_SORCUS_NUMBER=8 -val SCE_SORCUS_CONSTANT=9 -# Lexical state for SCLEX_POWERPRO -lex PowerPro=SCLEX_POWERPRO SCE_POWERPRO_ -val SCE_POWERPRO_DEFAULT=0 -val SCE_POWERPRO_COMMENTBLOCK=1 -val SCE_POWERPRO_COMMENTLINE=2 -val SCE_POWERPRO_NUMBER=3 -val SCE_POWERPRO_WORD=4 -val SCE_POWERPRO_WORD2=5 -val SCE_POWERPRO_WORD3=6 -val SCE_POWERPRO_WORD4=7 -val SCE_POWERPRO_DOUBLEQUOTEDSTRING=8 -val SCE_POWERPRO_SINGLEQUOTEDSTRING=9 -val SCE_POWERPRO_LINECONTINUE=10 -val SCE_POWERPRO_OPERATOR=11 -val SCE_POWERPRO_IDENTIFIER=12 -val SCE_POWERPRO_STRINGEOL=13 -val SCE_POWERPRO_VERBATIM=14 -val SCE_POWERPRO_ALTQUOTE=15 -val SCE_POWERPRO_FUNCTION=16 -# Lexical states for SCLEX_SML -lex SML=SCLEX_SML SCE_SML_ -val SCE_SML_DEFAULT=0 -val SCE_SML_IDENTIFIER=1 -val SCE_SML_TAGNAME=2 -val SCE_SML_KEYWORD=3 -val SCE_SML_KEYWORD2=4 -val SCE_SML_KEYWORD3=5 -val SCE_SML_LINENUM=6 -val SCE_SML_OPERATOR=7 -val SCE_SML_NUMBER=8 -val SCE_SML_CHAR=9 -val SCE_SML_STRING=11 -val SCE_SML_COMMENT=12 -val SCE_SML_COMMENT1=13 -val SCE_SML_COMMENT2=14 -val SCE_SML_COMMENT3=15 -# Lexical state for SCLEX_MARKDOWN -lex Markdown=SCLEX_MARKDOWN SCE_MARKDOWN_ -val SCE_MARKDOWN_DEFAULT=0 -val SCE_MARKDOWN_LINE_BEGIN=1 -val SCE_MARKDOWN_STRONG1=2 -val SCE_MARKDOWN_STRONG2=3 -val SCE_MARKDOWN_EM1=4 -val SCE_MARKDOWN_EM2=5 -val SCE_MARKDOWN_HEADER1=6 -val SCE_MARKDOWN_HEADER2=7 -val SCE_MARKDOWN_HEADER3=8 -val SCE_MARKDOWN_HEADER4=9 -val SCE_MARKDOWN_HEADER5=10 -val SCE_MARKDOWN_HEADER6=11 -val SCE_MARKDOWN_PRECHAR=12 -val SCE_MARKDOWN_ULIST_ITEM=13 -val SCE_MARKDOWN_OLIST_ITEM=14 -val SCE_MARKDOWN_BLOCKQUOTE=15 -val SCE_MARKDOWN_STRIKEOUT=16 -val SCE_MARKDOWN_HRULE=17 -val SCE_MARKDOWN_LINK=18 -val SCE_MARKDOWN_CODE=19 -val SCE_MARKDOWN_CODE2=20 -val SCE_MARKDOWN_CODEBK=21 -# Lexical state for SCLEX_TXT2TAGS -lex Txt2tags=SCLEX_TXT2TAGS SCE_TXT2TAGS_ -val SCE_TXT2TAGS_DEFAULT=0 -val SCE_TXT2TAGS_LINE_BEGIN=1 -val SCE_TXT2TAGS_STRONG1=2 -val SCE_TXT2TAGS_STRONG2=3 -val SCE_TXT2TAGS_EM1=4 -val SCE_TXT2TAGS_EM2=5 -val SCE_TXT2TAGS_HEADER1=6 -val SCE_TXT2TAGS_HEADER2=7 -val SCE_TXT2TAGS_HEADER3=8 -val SCE_TXT2TAGS_HEADER4=9 -val SCE_TXT2TAGS_HEADER5=10 -val SCE_TXT2TAGS_HEADER6=11 -val SCE_TXT2TAGS_PRECHAR=12 -val SCE_TXT2TAGS_ULIST_ITEM=13 -val SCE_TXT2TAGS_OLIST_ITEM=14 -val SCE_TXT2TAGS_BLOCKQUOTE=15 -val SCE_TXT2TAGS_STRIKEOUT=16 -val SCE_TXT2TAGS_HRULE=17 -val SCE_TXT2TAGS_LINK=18 -val SCE_TXT2TAGS_CODE=19 -val SCE_TXT2TAGS_CODE2=20 -val SCE_TXT2TAGS_CODEBK=21 -val SCE_TXT2TAGS_COMMENT=22 -val SCE_TXT2TAGS_OPTION=23 -val SCE_TXT2TAGS_PREPROC=24 -val SCE_TXT2TAGS_POSTPROC=25 -# Lexical states for SCLEX_A68K -lex A68k=SCLEX_A68K SCE_A68K_ -val SCE_A68K_DEFAULT=0 -val SCE_A68K_COMMENT=1 -val SCE_A68K_NUMBER_DEC=2 -val SCE_A68K_NUMBER_BIN=3 -val SCE_A68K_NUMBER_HEX=4 -val SCE_A68K_STRING1=5 -val SCE_A68K_OPERATOR=6 -val SCE_A68K_CPUINSTRUCTION=7 -val SCE_A68K_EXTINSTRUCTION=8 -val SCE_A68K_REGISTER=9 -val SCE_A68K_DIRECTIVE=10 -val SCE_A68K_MACRO_ARG=11 -val SCE_A68K_LABEL=12 -val SCE_A68K_STRING2=13 -val SCE_A68K_IDENTIFIER=14 -val SCE_A68K_MACRO_DECLARATION=15 -val SCE_A68K_COMMENT_WORD=16 -val SCE_A68K_COMMENT_SPECIAL=17 -val SCE_A68K_COMMENT_DOXYGEN=18 -# Lexical states for SCLEX_MODULA -lex Modula=SCLEX_MODULA SCE_MODULA_ -val SCE_MODULA_DEFAULT=0 -val SCE_MODULA_COMMENT=1 -val SCE_MODULA_DOXYCOMM=2 -val SCE_MODULA_DOXYKEY=3 -val SCE_MODULA_KEYWORD=4 -val SCE_MODULA_RESERVED=5 -val SCE_MODULA_NUMBER=6 -val SCE_MODULA_BASENUM=7 -val SCE_MODULA_FLOAT=8 -val SCE_MODULA_STRING=9 -val SCE_MODULA_STRSPEC=10 -val SCE_MODULA_CHAR=11 -val SCE_MODULA_CHARSPEC=12 -val SCE_MODULA_PROC=13 -val SCE_MODULA_PRAGMA=14 -val SCE_MODULA_PRGKEY=15 -val SCE_MODULA_OPERATOR=16 -val SCE_MODULA_BADSTR=17 -# Lexical states for SCLEX_COFFEESCRIPT -lex CoffeeScript=SCLEX_COFFEESCRIPT SCE_COFFEESCRIPT_ -val SCE_COFFEESCRIPT_DEFAULT=0 -val SCE_COFFEESCRIPT_COMMENT=1 -val SCE_COFFEESCRIPT_COMMENTLINE=2 -val SCE_COFFEESCRIPT_COMMENTDOC=3 -val SCE_COFFEESCRIPT_NUMBER=4 -val SCE_COFFEESCRIPT_WORD=5 -val SCE_COFFEESCRIPT_STRING=6 -val SCE_COFFEESCRIPT_CHARACTER=7 -val SCE_COFFEESCRIPT_UUID=8 -val SCE_COFFEESCRIPT_PREPROCESSOR=9 -val SCE_COFFEESCRIPT_OPERATOR=10 -val SCE_COFFEESCRIPT_IDENTIFIER=11 -val SCE_COFFEESCRIPT_STRINGEOL=12 -val SCE_COFFEESCRIPT_VERBATIM=13 -val SCE_COFFEESCRIPT_REGEX=14 -val SCE_COFFEESCRIPT_COMMENTLINEDOC=15 -val SCE_COFFEESCRIPT_WORD2=16 -val SCE_COFFEESCRIPT_COMMENTDOCKEYWORD=17 -val SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR=18 -val SCE_COFFEESCRIPT_GLOBALCLASS=19 -val SCE_COFFEESCRIPT_STRINGRAW=20 -val SCE_COFFEESCRIPT_TRIPLEVERBATIM=21 -val SCE_COFFEESCRIPT_HASHQUOTEDSTRING=22 -val SCE_COFFEESCRIPT_COMMENTBLOCK=22 -val SCE_COFFEESCRIPT_VERBOSE_REGEX=23 -val SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT=24 -# Lexical states for SCLEX_AVS -lex AVS=SCLEX_AVS SCE_AVS_ -val SCE_AVS_DEFAULT=0 -val SCE_AVS_COMMENTBLOCK=1 -val SCE_AVS_COMMENTBLOCKN=2 -val SCE_AVS_COMMENTLINE=3 -val SCE_AVS_NUMBER=4 -val SCE_AVS_OPERATOR=5 -val SCE_AVS_IDENTIFIER=6 -val SCE_AVS_STRING=7 -val SCE_AVS_TRIPLESTRING=8 -val SCE_AVS_KEYWORD=9 -val SCE_AVS_FILTER=10 -val SCE_AVS_PLUGIN=11 -val SCE_AVS_FUNCTION=12 -val SCE_AVS_CLIPPROP=13 -val SCE_AVS_USERDFN=14 - -# Events - -evt void StyleNeeded=2000(int position) -evt void CharAdded=2001(int ch) -evt void SavePointReached=2002(void) -evt void SavePointLeft=2003(void) -evt void ModifyAttemptRO=2004(void) -# GTK+ Specific to work around focus and accelerator problems: -evt void Key=2005(int ch, int modifiers) -evt void DoubleClick=2006(int modifiers, int position, int line) -evt void UpdateUI=2007(int updated) -evt void Modified=2008(int position, int modificationType, string text, int length, int linesAdded, int line, int foldLevelNow, int foldLevelPrev, int token, int annotationLinesAdded) -evt void MacroRecord=2009(int message, int wParam, int lParam) -evt void MarginClick=2010(int modifiers, int position, int margin) -evt void NeedShown=2011(int position, int length) -evt void Painted=2013(void) -evt void UserListSelection=2014(int listType, string text, int position) -evt void URIDropped=2015(string text) -evt void DwellStart=2016(int position, int x, int y) -evt void DwellEnd=2017(int position, int x, int y) -evt void Zoom=2018(void) -evt void HotSpotClick=2019(int modifiers, int position) -evt void HotSpotDoubleClick=2020(int modifiers, int position) -evt void CallTipClick=2021(int position) -evt void AutoCSelection=2022(string text, int position) -evt void IndicatorClick=2023(int modifiers, int position) -evt void IndicatorRelease=2024(int modifiers, int position) -evt void AutoCCancelled=2025(void) -evt void AutoCCharDeleted=2026(void) -evt void HotSpotReleaseClick=2027(int modifiers, int position) - -cat Deprecated - -# Deprecated in 2.21 -# The SC_CP_DBCS value can be used to indicate a DBCS mode for GTK+. -val SC_CP_DBCS=1 - -# Deprecated in 2.30 - -# In palette mode? -get bool GetUsePalette=2139(,) - -# In palette mode, Scintilla uses the environment's palette calls to display -# more colours. This may lead to ugly displays. -set void SetUsePalette=2039(bool usePalette,) +## First line may be used for shbang + +## This file defines the interface to Scintilla + +## Copyright 2000-2003 by Neil Hodgson +## The License.txt file describes the conditions under which this software may be distributed. + +## A line starting with ## is a pure comment and should be stripped by readers. +## A line starting with #! is for future shbang use +## A line starting with # followed by a space is a documentation comment and refers +## to the next feature definition. + +## Each feature is defined by a line starting with fun, get, set, val or evt. +## cat -> start a category +## fun -> a function +## get -> a property get function +## set -> a property set function +## val -> definition of a constant +## evt -> an event +## enu -> associate an enumeration with a set of vals with a prefix +## lex -> associate a lexer with the lexical classes it produces +## +## All other feature names should be ignored. They may be defined in the future. +## A property may have a set function, a get function or both. Each will have +## "Get" or "Set" in their names and the corresponding name will have the obvious switch. +## A property may be subscripted, in which case the first parameter is the subscript. +## fun, get, and set features have a strict syntax: +## [=,) +## where stands for white space. +## param may be empty (null value) or is [=] +## Additional white space is allowed between elements. +## The syntax for evt is [=[,]*]) +## Feature names that contain an underscore are defined by Windows, so in these +## cases, using the Windows definition is preferred where available. +## The feature numbers are stable so features will not be renumbered. +## Features may be removed but they will go through a period of deprecation +## before removal which is signalled by moving them into the Deprecated category. +## +## enu has the syntax enu=[]* where all the val +## features in this file starting with a given are considered part of the +## enumeration. +## +## lex has the syntax lex=[]* +## where name is a reasonably capitalised (Python, XML) identifier or UI name, +## lexerVal is the val used to specify the lexer, and the list of prefixes is similar +## to enu. The name may not be the same as that used within the lexer so the lexerVal +## should be used to tie these entities together. + +## Types: +## void +## int +## bool -> integer, 1=true, 0=false +## position -> integer position in a document +## colour -> colour integer containing red, green and blue bytes. +## string -> pointer to const character +## stringresult -> pointer to character, NULL-> return size of result +## cells -> pointer to array of cells, each cell containing a style byte and character byte +## textrange -> range of a min and a max position with an output string +## findtext -> searchrange, text -> foundposition +## keymod -> integer containing key in low half and modifiers in high half +## formatrange +## Types no longer used: +## findtextex -> searchrange +## charrange -> range of a min and a max position +## charrangeresult -> like charrange, but output param +## countedstring +## point -> x,y +## pointresult -> like point, but output param +## rectangle -> left,top,right,bottom +## Client code should ignore definitions containing types it does not understand, except +## for possibly #defining the constants + +## Line numbers and positions start at 0. +## String arguments may contain NUL ('\0') characters where the calls provide a length +## argument and retrieve NUL characters. All retrieved strings except for those retrieved +## by GetLine also have a NUL appended but client code should calculate the size that +## will be returned rather than relying upon the NUL whenever possible. Allow for the +## extra NUL character when allocating buffers. The size to allocate for a stringresult +## can be determined by calling with a NULL (0) pointer. + +cat Basics + +################################################ +## For Scintilla.h +val INVALID_POSITION=-1 +# Define start of Scintilla messages to be greater than all Windows edit (EM_*) messages +# as many EM_ messages can be used although that use is deprecated. +val SCI_START=2000 +val SCI_OPTIONAL_START=3000 +val SCI_LEXER_START=4000 + +# Add text to the document at current position. +fun void AddText=2001(int length, string text) + +# Add array of cells to document. +fun void AddStyledText=2002(int length, cells c) + +# Insert string at a position. +fun void InsertText=2003(position pos, string text) + +# Delete all text in the document. +fun void ClearAll=2004(,) + +# Set all style bytes to 0, remove all folding information. +fun void ClearDocumentStyle=2005(,) + +# Returns the number of bytes in the document. +get int GetLength=2006(,) + +# Returns the character byte at the position. +get int GetCharAt=2007(position pos,) + +# Returns the position of the caret. +get position GetCurrentPos=2008(,) + +# Returns the position of the opposite end of the selection to the caret. +get position GetAnchor=2009(,) + +# Returns the style byte at the position. +get int GetStyleAt=2010(position pos,) + +# Redoes the next action on the undo history. +fun void Redo=2011(,) + +# Choose between collecting actions into the undo +# history and discarding them. +set void SetUndoCollection=2012(bool collectUndo,) + +# Select all the text in the document. +fun void SelectAll=2013(,) + +# Remember the current position in the undo history as the position +# at which the document was saved. +fun void SetSavePoint=2014(,) + +# Retrieve a buffer of cells. +# Returns the number of bytes in the buffer not including terminating NULs. +fun int GetStyledText=2015(, textrange tr) + +# Are there any redoable actions in the undo history? +fun bool CanRedo=2016(,) + +# Retrieve the line number at which a particular marker is located. +fun int MarkerLineFromHandle=2017(int handle,) + +# Delete a marker. +fun void MarkerDeleteHandle=2018(int handle,) + +# Is undo history being collected? +get bool GetUndoCollection=2019(,) + +enu WhiteSpace=SCWS_ +val SCWS_INVISIBLE=0 +val SCWS_VISIBLEALWAYS=1 +val SCWS_VISIBLEAFTERINDENT=2 + +# Are white space characters currently visible? +# Returns one of SCWS_* constants. +get int GetViewWS=2020(,) + +# Make white space characters invisible, always visible or visible outside indentation. +set void SetViewWS=2021(int viewWS,) + +# Find the position from a point within the window. +fun position PositionFromPoint=2022(int x, int y) + +# Find the position from a point within the window but return +# INVALID_POSITION if not close to text. +fun position PositionFromPointClose=2023(int x, int y) + +# Set caret to start of a line and ensure it is visible. +fun void GotoLine=2024(int line,) + +# Set caret to a position and ensure it is visible. +fun void GotoPos=2025(position pos,) + +# Set the selection anchor to a position. The anchor is the opposite +# end of the selection from the caret. +set void SetAnchor=2026(position posAnchor,) + +# Retrieve the text of the line containing the caret. +# Returns the index of the caret on the line. +fun int GetCurLine=2027(int length, stringresult text) + +# Retrieve the position of the last correctly styled character. +get position GetEndStyled=2028(,) + +enu EndOfLine=SC_EOL_ +val SC_EOL_CRLF=0 +val SC_EOL_CR=1 +val SC_EOL_LF=2 + +# Convert all line endings in the document to one mode. +fun void ConvertEOLs=2029(int eolMode,) + +# Retrieve the current end of line mode - one of CRLF, CR, or LF. +get int GetEOLMode=2030(,) + +# Set the current end of line mode. +set void SetEOLMode=2031(int eolMode,) + +# Set the current styling position to pos and the styling mask to mask. +# The styling mask can be used to protect some bits in each styling byte from modification. +fun void StartStyling=2032(position pos, int mask) + +# Change style from current styling position for length characters to a style +# and move the current styling position to after this newly styled segment. +fun void SetStyling=2033(int length, int style) + +# Is drawing done first into a buffer or direct to the screen? +get bool GetBufferedDraw=2034(,) + +# If drawing is buffered then each line of text is drawn into a bitmap buffer +# before drawing it to the screen to avoid flicker. +set void SetBufferedDraw=2035(bool buffered,) + +# Change the visible size of a tab to be a multiple of the width of a space character. +set void SetTabWidth=2036(int tabWidth,) + +# Retrieve the visible size of a tab. +get int GetTabWidth=2121(,) + +# The SC_CP_UTF8 value can be used to enter Unicode mode. +# This is the same value as CP_UTF8 in Windows +val SC_CP_UTF8=65001 + +# Set the code page used to interpret the bytes of the document as characters. +# The SC_CP_UTF8 value can be used to enter Unicode mode. +set void SetCodePage=2037(int codePage,) + +enu MarkerSymbol=SC_MARK_ +val MARKER_MAX=31 +val SC_MARK_CIRCLE=0 +val SC_MARK_ROUNDRECT=1 +val SC_MARK_ARROW=2 +val SC_MARK_SMALLRECT=3 +val SC_MARK_SHORTARROW=4 +val SC_MARK_EMPTY=5 +val SC_MARK_ARROWDOWN=6 +val SC_MARK_MINUS=7 +val SC_MARK_PLUS=8 + +# Shapes used for outlining column. +val SC_MARK_VLINE=9 +val SC_MARK_LCORNER=10 +val SC_MARK_TCORNER=11 +val SC_MARK_BOXPLUS=12 +val SC_MARK_BOXPLUSCONNECTED=13 +val SC_MARK_BOXMINUS=14 +val SC_MARK_BOXMINUSCONNECTED=15 +val SC_MARK_LCORNERCURVE=16 +val SC_MARK_TCORNERCURVE=17 +val SC_MARK_CIRCLEPLUS=18 +val SC_MARK_CIRCLEPLUSCONNECTED=19 +val SC_MARK_CIRCLEMINUS=20 +val SC_MARK_CIRCLEMINUSCONNECTED=21 + +# Invisible mark that only sets the line background colour. +val SC_MARK_BACKGROUND=22 +val SC_MARK_DOTDOTDOT=23 +val SC_MARK_ARROWS=24 +val SC_MARK_PIXMAP=25 +val SC_MARK_FULLRECT=26 +val SC_MARK_LEFTRECT=27 +val SC_MARK_AVAILABLE=28 +val SC_MARK_UNDERLINE=29 +val SC_MARK_RGBAIMAGE=30 + +val SC_MARK_CHARACTER=10000 + +enu MarkerOutline=SC_MARKNUM_ +# Markers used for outlining column. +val SC_MARKNUM_FOLDEREND=25 +val SC_MARKNUM_FOLDEROPENMID=26 +val SC_MARKNUM_FOLDERMIDTAIL=27 +val SC_MARKNUM_FOLDERTAIL=28 +val SC_MARKNUM_FOLDERSUB=29 +val SC_MARKNUM_FOLDER=30 +val SC_MARKNUM_FOLDEROPEN=31 + +val SC_MASK_FOLDERS=0xFE000000 + +# Set the symbol used for a particular marker number. +fun void MarkerDefine=2040(int markerNumber, int markerSymbol) + +# Set the foreground colour used for a particular marker number. +fun void MarkerSetFore=2041(int markerNumber, colour fore) + +# Set the background colour used for a particular marker number. +fun void MarkerSetBack=2042(int markerNumber, colour back) + +# Set the background colour used for a particular marker number when its folding block is selected. +fun void MarkerSetBackSelected=2292(int markerNumber, colour back) + +# Enable/disable highlight for current folding bloc (smallest one that contains the caret) +fun void MarkerEnableHighlight=2293(bool enabled,) + +# Add a marker to a line, returning an ID which can be used to find or delete the marker. +fun int MarkerAdd=2043(int line, int markerNumber) + +# Delete a marker from a line. +fun void MarkerDelete=2044(int line, int markerNumber) + +# Delete all markers with a particular number from all lines. +fun void MarkerDeleteAll=2045(int markerNumber,) + +# Get a bit mask of all the markers set on a line. +fun int MarkerGet=2046(int line,) + +# Find the next line at or after lineStart that includes a marker in mask. +# Return -1 when no more lines. +fun int MarkerNext=2047(int lineStart, int markerMask) + +# Find the previous line before lineStart that includes a marker in mask. +fun int MarkerPrevious=2048(int lineStart, int markerMask) + +# Define a marker from a pixmap. +fun void MarkerDefinePixmap=2049(int markerNumber, string pixmap) + +# Add a set of markers to a line. +fun void MarkerAddSet=2466(int line, int set) + +# Set the alpha used for a marker that is drawn in the text area, not the margin. +fun void MarkerSetAlpha=2476(int markerNumber, int alpha) + +enu MarginType=SC_MARGIN_ +val SC_MARGIN_SYMBOL=0 +val SC_MARGIN_NUMBER=1 +val SC_MARGIN_BACK=2 +val SC_MARGIN_FORE=3 +val SC_MARGIN_TEXT=4 +val SC_MARGIN_RTEXT=5 + +# Set a margin to be either numeric or symbolic. +set void SetMarginTypeN=2240(int margin, int marginType) + +# Retrieve the type of a margin. +get int GetMarginTypeN=2241(int margin,) + +# Set the width of a margin to a width expressed in pixels. +set void SetMarginWidthN=2242(int margin, int pixelWidth) + +# Retrieve the width of a margin in pixels. +get int GetMarginWidthN=2243(int margin,) + +# Set a mask that determines which markers are displayed in a margin. +set void SetMarginMaskN=2244(int margin, int mask) + +# Retrieve the marker mask of a margin. +get int GetMarginMaskN=2245(int margin,) + +# Make a margin sensitive or insensitive to mouse clicks. +set void SetMarginSensitiveN=2246(int margin, bool sensitive) + +# Retrieve the mouse click sensitivity of a margin. +get bool GetMarginSensitiveN=2247(int margin,) + +# Set the cursor shown when the mouse is inside a margin. +set void SetMarginCursorN=2248(int margin, int cursor) + +# Retrieve the cursor shown in a margin. +get int GetMarginCursorN=2249(int margin,) + +# Styles in range 32..38 are predefined for parts of the UI and are not used as normal styles. +# Style 39 is for future use. +enu StylesCommon=STYLE_ +val STYLE_DEFAULT=32 +val STYLE_LINENUMBER=33 +val STYLE_BRACELIGHT=34 +val STYLE_BRACEBAD=35 +val STYLE_CONTROLCHAR=36 +val STYLE_INDENTGUIDE=37 +val STYLE_CALLTIP=38 +val STYLE_LASTPREDEFINED=39 +val STYLE_MAX=255 + +# Character set identifiers are used in StyleSetCharacterSet. +# The values are the same as the Windows *_CHARSET values. +enu CharacterSet=SC_CHARSET_ +val SC_CHARSET_ANSI=0 +val SC_CHARSET_DEFAULT=1 +val SC_CHARSET_BALTIC=186 +val SC_CHARSET_CHINESEBIG5=136 +val SC_CHARSET_EASTEUROPE=238 +val SC_CHARSET_GB2312=134 +val SC_CHARSET_GREEK=161 +val SC_CHARSET_HANGUL=129 +val SC_CHARSET_MAC=77 +val SC_CHARSET_OEM=255 +val SC_CHARSET_RUSSIAN=204 +val SC_CHARSET_CYRILLIC=1251 +val SC_CHARSET_SHIFTJIS=128 +val SC_CHARSET_SYMBOL=2 +val SC_CHARSET_TURKISH=162 +val SC_CHARSET_JOHAB=130 +val SC_CHARSET_HEBREW=177 +val SC_CHARSET_ARABIC=178 +val SC_CHARSET_VIETNAMESE=163 +val SC_CHARSET_THAI=222 +val SC_CHARSET_8859_15=1000 + +# Clear all the styles and make equivalent to the global default style. +set void StyleClearAll=2050(,) + +# Set the foreground colour of a style. +set void StyleSetFore=2051(int style, colour fore) + +# Set the background colour of a style. +set void StyleSetBack=2052(int style, colour back) + +# Set a style to be bold or not. +set void StyleSetBold=2053(int style, bool bold) + +# Set a style to be italic or not. +set void StyleSetItalic=2054(int style, bool italic) + +# Set the size of characters of a style. +set void StyleSetSize=2055(int style, int sizePoints) + +# Set the font of a style. +set void StyleSetFont=2056(int style, string fontName) + +# Set a style to have its end of line filled or not. +set void StyleSetEOLFilled=2057(int style, bool filled) + +# Reset the default style to its state at startup +fun void StyleResetDefault=2058(,) + +# Set a style to be underlined or not. +set void StyleSetUnderline=2059(int style, bool underline) + +enu CaseVisible=SC_CASE_ +val SC_CASE_MIXED=0 +val SC_CASE_UPPER=1 +val SC_CASE_LOWER=2 + +# Get the foreground colour of a style. +get colour StyleGetFore=2481(int style,) + +# Get the background colour of a style. +get colour StyleGetBack=2482(int style,) + +# Get is a style bold or not. +get bool StyleGetBold=2483(int style,) + +# Get is a style italic or not. +get bool StyleGetItalic=2484(int style,) + +# Get the size of characters of a style. +get int StyleGetSize=2485(int style,) + +# Get the font of a style. +# Returns the length of the fontName +fun int StyleGetFont=2486(int style, stringresult fontName) + +# Get is a style to have its end of line filled or not. +get bool StyleGetEOLFilled=2487(int style,) + +# Get is a style underlined or not. +get bool StyleGetUnderline=2488(int style,) + +# Get is a style mixed case, or to force upper or lower case. +get int StyleGetCase=2489(int style,) + +# Get the character get of the font in a style. +get int StyleGetCharacterSet=2490(int style,) + +# Get is a style visible or not. +get bool StyleGetVisible=2491(int style,) + +# Get is a style changeable or not (read only). +# Experimental feature, currently buggy. +get bool StyleGetChangeable=2492(int style,) + +# Get is a style a hotspot or not. +get bool StyleGetHotSpot=2493(int style,) + +# Set a style to be mixed case, or to force upper or lower case. +set void StyleSetCase=2060(int style, int caseForce) + +val SC_FONT_SIZE_MULTIPLIER=100 + +# Set the size of characters of a style. Size is in points multiplied by 100. +set void StyleSetSizeFractional=2061(int style, int caseForce) + +# Get the size of characters of a style in points multiplied by 100 +get int StyleGetSizeFractional=2062(int style,) + +enu FontWeight=SC_WEIGHT_ +val SC_WEIGHT_NORMAL=400 +val SC_WEIGHT_SEMIBOLD=600 +val SC_WEIGHT_BOLD=700 + +# Set the weight of characters of a style. +set void StyleSetWeight=2063(int style, int weight) + +# Get the weight of characters of a style. +get int StyleGetWeight=2064(int style,) + +# Set the character set of the font in a style. +set void StyleSetCharacterSet=2066(int style, int characterSet) + +# Set a style to be a hotspot or not. +set void StyleSetHotSpot=2409(int style, bool hotspot) + +# Set the foreground colour of the main and additional selections and whether to use this setting. +fun void SetSelFore=2067(bool useSetting, colour fore) + +# Set the background colour of the main and additional selections and whether to use this setting. +fun void SetSelBack=2068(bool useSetting, colour back) + +# Get the alpha of the selection. +get int GetSelAlpha=2477(,) + +# Set the alpha of the selection. +set void SetSelAlpha=2478(int alpha,) + +# Is the selection end of line filled? +get bool GetSelEOLFilled=2479(,) + +# Set the selection to have its end of line filled or not. +set void SetSelEOLFilled=2480(bool filled,) + +# Set the foreground colour of the caret. +set void SetCaretFore=2069(colour fore,) + +# When key+modifier combination km is pressed perform msg. +fun void AssignCmdKey=2070(keymod km, int msg) + +# When key+modifier combination km is pressed do nothing. +fun void ClearCmdKey=2071(keymod km,) + +# Drop all key mappings. +fun void ClearAllCmdKeys=2072(,) + +# Set the styles for a segment of the document. +fun void SetStylingEx=2073(int length, string styles) + +# Set a style to be visible or not. +set void StyleSetVisible=2074(int style, bool visible) + +# Get the time in milliseconds that the caret is on and off. +get int GetCaretPeriod=2075(,) + +# Get the time in milliseconds that the caret is on and off. 0 = steady on. +set void SetCaretPeriod=2076(int periodMilliseconds,) + +# Set the set of characters making up words for when moving or selecting by word. +# First sets defaults like SetCharsDefault. +set void SetWordChars=2077(, string characters) + +# Start a sequence of actions that is undone and redone as a unit. +# May be nested. +fun void BeginUndoAction=2078(,) + +# End a sequence of actions that is undone and redone as a unit. +fun void EndUndoAction=2079(,) + +# Indicator style enumeration and some constants +enu IndicatorStyle=INDIC_ +val INDIC_PLAIN=0 +val INDIC_SQUIGGLE=1 +val INDIC_TT=2 +val INDIC_DIAGONAL=3 +val INDIC_STRIKE=4 +val INDIC_HIDDEN=5 +val INDIC_BOX=6 +val INDIC_ROUNDBOX=7 +val INDIC_STRAIGHTBOX=8 +val INDIC_DASH=9 +val INDIC_DOTS=10 +val INDIC_SQUIGGLELOW=11 +val INDIC_DOTBOX=12 +val INDIC_MAX=31 +val INDIC_CONTAINER=8 +val INDIC0_MASK=0x20 +val INDIC1_MASK=0x40 +val INDIC2_MASK=0x80 +val INDICS_MASK=0xE0 + +# Set an indicator to plain, squiggle or TT. +set void IndicSetStyle=2080(int indic, int style) + +# Retrieve the style of an indicator. +get int IndicGetStyle=2081(int indic,) + +# Set the foreground colour of an indicator. +set void IndicSetFore=2082(int indic, colour fore) + +# Retrieve the foreground colour of an indicator. +get colour IndicGetFore=2083(int indic,) + +# Set an indicator to draw under text or over(default). +set void IndicSetUnder=2510(int indic, bool under) + +# Retrieve whether indicator drawn under or over text. +get bool IndicGetUnder=2511(int indic,) + +# Set the foreground colour of all whitespace and whether to use this setting. +fun void SetWhitespaceFore=2084(bool useSetting, colour fore) + +# Set the background colour of all whitespace and whether to use this setting. +fun void SetWhitespaceBack=2085(bool useSetting, colour back) + +# Set the size of the dots used to mark space characters. +set void SetWhitespaceSize=2086(int size,) + +# Get the size of the dots used to mark space characters. +get int GetWhitespaceSize=2087(,) + +# Divide each styling byte into lexical class bits (default: 5) and indicator +# bits (default: 3). If a lexer requires more than 32 lexical states, then this +# is used to expand the possible states. +set void SetStyleBits=2090(int bits,) + +# Retrieve number of bits in style bytes used to hold the lexical state. +get int GetStyleBits=2091(,) + +# Used to hold extra styling information for each line. +set void SetLineState=2092(int line, int state) + +# Retrieve the extra styling information for a line. +get int GetLineState=2093(int line,) + +# Retrieve the last line number that has line state. +get int GetMaxLineState=2094(,) + +# Is the background of the line containing the caret in a different colour? +get bool GetCaretLineVisible=2095(,) + +# Display the background of the line containing the caret in a different colour. +set void SetCaretLineVisible=2096(bool show,) + +# Get the colour of the background of the line containing the caret. +get colour GetCaretLineBack=2097(,) + +# Set the colour of the background of the line containing the caret. +set void SetCaretLineBack=2098(colour back,) + +# Set a style to be changeable or not (read only). +# Experimental feature, currently buggy. +set void StyleSetChangeable=2099(int style, bool changeable) + +# Display a auto-completion list. +# The lenEntered parameter indicates how many characters before +# the caret should be used to provide context. +fun void AutoCShow=2100(int lenEntered, string itemList) + +# Remove the auto-completion list from the screen. +fun void AutoCCancel=2101(,) + +# Is there an auto-completion list visible? +fun bool AutoCActive=2102(,) + +# Retrieve the position of the caret when the auto-completion list was displayed. +fun position AutoCPosStart=2103(,) + +# User has selected an item so remove the list and insert the selection. +fun void AutoCComplete=2104(,) + +# Define a set of character that when typed cancel the auto-completion list. +fun void AutoCStops=2105(, string characterSet) + +# Change the separator character in the string setting up an auto-completion list. +# Default is space but can be changed if items contain space. +set void AutoCSetSeparator=2106(int separatorCharacter,) + +# Retrieve the auto-completion list separator character. +get int AutoCGetSeparator=2107(,) + +# Select the item in the auto-completion list that starts with a string. +fun void AutoCSelect=2108(, string text) + +# Should the auto-completion list be cancelled if the user backspaces to a +# position before where the box was created. +set void AutoCSetCancelAtStart=2110(bool cancel,) + +# Retrieve whether auto-completion cancelled by backspacing before start. +get bool AutoCGetCancelAtStart=2111(,) + +# Define a set of characters that when typed will cause the autocompletion to +# choose the selected item. +set void AutoCSetFillUps=2112(, string characterSet) + +# Should a single item auto-completion list automatically choose the item. +set void AutoCSetChooseSingle=2113(bool chooseSingle,) + +# Retrieve whether a single item auto-completion list automatically choose the item. +get bool AutoCGetChooseSingle=2114(,) + +# Set whether case is significant when performing auto-completion searches. +set void AutoCSetIgnoreCase=2115(bool ignoreCase,) + +# Retrieve state of ignore case flag. +get bool AutoCGetIgnoreCase=2116(,) + +# Display a list of strings and send notification when user chooses one. +fun void UserListShow=2117(int listType, string itemList) + +# Set whether or not autocompletion is hidden automatically when nothing matches. +set void AutoCSetAutoHide=2118(bool autoHide,) + +# Retrieve whether or not autocompletion is hidden automatically when nothing matches. +get bool AutoCGetAutoHide=2119(,) + +# Set whether or not autocompletion deletes any word characters +# after the inserted text upon completion. +set void AutoCSetDropRestOfWord=2270(bool dropRestOfWord,) + +# Retrieve whether or not autocompletion deletes any word characters +# after the inserted text upon completion. +get bool AutoCGetDropRestOfWord=2271(,) + +# Register an XPM image for use in autocompletion lists. +fun void RegisterImage=2405(int type, string xpmData) + +# Clear all the registered XPM images. +fun void ClearRegisteredImages=2408(,) + +# Retrieve the auto-completion list type-separator character. +get int AutoCGetTypeSeparator=2285(,) + +# Change the type-separator character in the string setting up an auto-completion list. +# Default is '?' but can be changed if items contain '?'. +set void AutoCSetTypeSeparator=2286(int separatorCharacter,) + +# Set the maximum width, in characters, of auto-completion and user lists. +# Set to 0 to autosize to fit longest item, which is the default. +set void AutoCSetMaxWidth=2208(int characterCount,) + +# Get the maximum width, in characters, of auto-completion and user lists. +get int AutoCGetMaxWidth=2209(,) + +# Set the maximum height, in rows, of auto-completion and user lists. +# The default is 5 rows. +set void AutoCSetMaxHeight=2210(int rowCount,) + +# Set the maximum height, in rows, of auto-completion and user lists. +get int AutoCGetMaxHeight=2211(,) + +# Set the number of spaces used for one level of indentation. +set void SetIndent=2122(int indentSize,) + +# Retrieve indentation size. +get int GetIndent=2123(,) + +# Indentation will only use space characters if useTabs is false, otherwise +# it will use a combination of tabs and spaces. +set void SetUseTabs=2124(bool useTabs,) + +# Retrieve whether tabs will be used in indentation. +get bool GetUseTabs=2125(,) + +# Change the indentation of a line to a number of columns. +set void SetLineIndentation=2126(int line, int indentSize) + +# Retrieve the number of columns that a line is indented. +get int GetLineIndentation=2127(int line,) + +# Retrieve the position before the first non indentation character on a line. +get position GetLineIndentPosition=2128(int line,) + +# Retrieve the column number of a position, taking tab width into account. +get int GetColumn=2129(position pos,) + +# Count characters between two positions. +fun int CountCharacters=2633(int startPos, int endPos) + +# Show or hide the horizontal scroll bar. +set void SetHScrollBar=2130(bool show,) +# Is the horizontal scroll bar visible? +get bool GetHScrollBar=2131(,) + +enu IndentView=SC_IV_ +val SC_IV_NONE=0 +val SC_IV_REAL=1 +val SC_IV_LOOKFORWARD=2 +val SC_IV_LOOKBOTH=3 + +# Show or hide indentation guides. +set void SetIndentationGuides=2132(int indentView,) + +# Are the indentation guides visible? +get int GetIndentationGuides=2133(,) + +# Set the highlighted indentation guide column. +# 0 = no highlighted guide. +set void SetHighlightGuide=2134(int column,) + +# Get the highlighted indentation guide column. +get int GetHighlightGuide=2135(,) + +# Get the position after the last visible characters on a line. +get int GetLineEndPosition=2136(int line,) + +# Get the code page used to interpret the bytes of the document as characters. +get int GetCodePage=2137(,) + +# Get the foreground colour of the caret. +get colour GetCaretFore=2138(,) + +# In read-only mode? +get bool GetReadOnly=2140(,) + +# Sets the position of the caret. +set void SetCurrentPos=2141(position pos,) + +# Sets the position that starts the selection - this becomes the anchor. +set void SetSelectionStart=2142(position pos,) + +# Returns the position at the start of the selection. +get position GetSelectionStart=2143(,) + +# Sets the position that ends the selection - this becomes the currentPosition. +set void SetSelectionEnd=2144(position pos,) + +# Returns the position at the end of the selection. +get position GetSelectionEnd=2145(,) + +# Set caret to a position, while removing any existing selection. +fun void SetEmptySelection=2556(position pos,) + +# Sets the print magnification added to the point size of each style for printing. +set void SetPrintMagnification=2146(int magnification,) + +# Returns the print magnification. +get int GetPrintMagnification=2147(,) + +enu PrintOption=SC_PRINT_ +# PrintColourMode - use same colours as screen. +val SC_PRINT_NORMAL=0 +# PrintColourMode - invert the light value of each style for printing. +val SC_PRINT_INVERTLIGHT=1 +# PrintColourMode - force black text on white background for printing. +val SC_PRINT_BLACKONWHITE=2 +# PrintColourMode - text stays coloured, but all background is forced to be white for printing. +val SC_PRINT_COLOURONWHITE=3 +# PrintColourMode - only the default-background is forced to be white for printing. +val SC_PRINT_COLOURONWHITEDEFAULTBG=4 + +# Modify colours when printing for clearer printed text. +set void SetPrintColourMode=2148(int mode,) + +# Returns the print colour mode. +get int GetPrintColourMode=2149(,) + +enu FindOption=SCFIND_ +val SCFIND_WHOLEWORD=2 +val SCFIND_MATCHCASE=4 +val SCFIND_WORDSTART=0x00100000 +val SCFIND_REGEXP=0x00200000 +val SCFIND_POSIX=0x00400000 + +# Find some text in the document. +fun position FindText=2150(int flags, findtext ft) + +# On Windows, will draw the document into a display context such as a printer. +fun position FormatRange=2151(bool draw, formatrange fr) + +# Retrieve the display line at the top of the display. +get int GetFirstVisibleLine=2152(,) + +# Retrieve the contents of a line. +# Returns the length of the line. +fun int GetLine=2153(int line, stringresult text) + +# Returns the number of lines in the document. There is always at least one. +get int GetLineCount=2154(,) + +# Sets the size in pixels of the left margin. +set void SetMarginLeft=2155(, int pixelWidth) + +# Returns the size in pixels of the left margin. +get int GetMarginLeft=2156(,) + +# Sets the size in pixels of the right margin. +set void SetMarginRight=2157(, int pixelWidth) + +# Returns the size in pixels of the right margin. +get int GetMarginRight=2158(,) + +# Is the document different from when it was last saved? +get bool GetModify=2159(,) + +# Select a range of text. +fun void SetSel=2160(position start, position end) + +# Retrieve the selected text. +# Return the length of the text. +fun int GetSelText=2161(, stringresult text) + +# Retrieve a range of text. +# Return the length of the text. +fun int GetTextRange=2162(, textrange tr) + +# Draw the selection in normal style or with selection highlighted. +fun void HideSelection=2163(bool normal,) + +# Retrieve the x value of the point in the window where a position is displayed. +fun int PointXFromPosition=2164(, position pos) + +# Retrieve the y value of the point in the window where a position is displayed. +fun int PointYFromPosition=2165(, position pos) + +# Retrieve the line containing a position. +fun int LineFromPosition=2166(position pos,) + +# Retrieve the position at the start of a line. +fun position PositionFromLine=2167(int line,) + +# Scroll horizontally and vertically. +fun void LineScroll=2168(int columns, int lines) + +# Ensure the caret is visible. +fun void ScrollCaret=2169(,) + +# Replace the selected text with the argument text. +fun void ReplaceSel=2170(, string text) + +# Set to read only or read write. +set void SetReadOnly=2171(bool readOnly,) + +# Null operation. +fun void Null=2172(,) + +# Will a paste succeed? +fun bool CanPaste=2173(,) + +# Are there any undoable actions in the undo history? +fun bool CanUndo=2174(,) + +# Delete the undo history. +fun void EmptyUndoBuffer=2175(,) + +# Undo one action in the undo history. +fun void Undo=2176(,) + +# Cut the selection to the clipboard. +fun void Cut=2177(,) + +# Copy the selection to the clipboard. +fun void Copy=2178(,) + +# Paste the contents of the clipboard into the document replacing the selection. +fun void Paste=2179(,) + +# Clear the selection. +fun void Clear=2180(,) + +# Replace the contents of the document with the argument text. +fun void SetText=2181(, string text) + +# Retrieve all the text in the document. +# Returns number of characters retrieved. +fun int GetText=2182(int length, stringresult text) + +# Retrieve the number of characters in the document. +get int GetTextLength=2183(,) + +# Retrieve a pointer to a function that processes messages for this Scintilla. +get int GetDirectFunction=2184(,) + +# Retrieve a pointer value to use as the first argument when calling +# the function returned by GetDirectFunction. +get int GetDirectPointer=2185(,) + +# Set to overtype (true) or insert mode. +set void SetOvertype=2186(bool overtype,) + +# Returns true if overtype mode is active otherwise false is returned. +get bool GetOvertype=2187(,) + +# Set the width of the insert mode caret. +set void SetCaretWidth=2188(int pixelWidth,) + +# Returns the width of the insert mode caret. +get int GetCaretWidth=2189(,) + +# Sets the position that starts the target which is used for updating the +# document without affecting the scroll position. +set void SetTargetStart=2190(position pos,) + +# Get the position that starts the target. +get position GetTargetStart=2191(,) + +# Sets the position that ends the target which is used for updating the +# document without affecting the scroll position. +set void SetTargetEnd=2192(position pos,) + +# Get the position that ends the target. +get position GetTargetEnd=2193(,) + +# Replace the target text with the argument text. +# Text is counted so it can contain NULs. +# Returns the length of the replacement text. +fun int ReplaceTarget=2194(int length, string text) + +# Replace the target text with the argument text after \d processing. +# Text is counted so it can contain NULs. +# Looks for \d where d is between 1 and 9 and replaces these with the strings +# matched in the last search operation which were surrounded by \( and \). +# Returns the length of the replacement text including any change +# caused by processing the \d patterns. +fun int ReplaceTargetRE=2195(int length, string text) + +# Search for a counted string in the target and set the target to the found +# range. Text is counted so it can contain NULs. +# Returns length of range or -1 for failure in which case target is not moved. +fun int SearchInTarget=2197(int length, string text) + +# Set the search flags used by SearchInTarget. +set void SetSearchFlags=2198(int flags,) + +# Get the search flags used by SearchInTarget. +get int GetSearchFlags=2199(,) + +# Show a call tip containing a definition near position pos. +fun void CallTipShow=2200(position pos, string definition) + +# Remove the call tip from the screen. +fun void CallTipCancel=2201(,) + +# Is there an active call tip? +fun bool CallTipActive=2202(,) + +# Retrieve the position where the caret was before displaying the call tip. +fun position CallTipPosStart=2203(,) + +# Highlight a segment of the definition. +fun void CallTipSetHlt=2204(int start, int end) + +# Set the background colour for the call tip. +set void CallTipSetBack=2205(colour back,) + +# Set the foreground colour for the call tip. +set void CallTipSetFore=2206(colour fore,) + +# Set the foreground colour for the highlighted part of the call tip. +set void CallTipSetForeHlt=2207(colour fore,) + +# Enable use of STYLE_CALLTIP and set call tip tab size in pixels. +set void CallTipUseStyle=2212(int tabSize,) + +# Set position of calltip, above or below text. +set void CallTipSetPosition=2213(bool above,) + +# Find the display line of a document line taking hidden lines into account. +fun int VisibleFromDocLine=2220(int line,) + +# Find the document line of a display line taking hidden lines into account. +fun int DocLineFromVisible=2221(int lineDisplay,) + +# The number of display lines needed to wrap a document line +fun int WrapCount=2235(int line,) + +enu FoldLevel=SC_FOLDLEVEL +val SC_FOLDLEVELBASE=0x400 +val SC_FOLDLEVELWHITEFLAG=0x1000 +val SC_FOLDLEVELHEADERFLAG=0x2000 +val SC_FOLDLEVELNUMBERMASK=0x0FFF + +# Set the fold level of a line. +# This encodes an integer level along with flags indicating whether the +# line is a header and whether it is effectively white space. +set void SetFoldLevel=2222(int line, int level) + +# Retrieve the fold level of a line. +get int GetFoldLevel=2223(int line,) + +# Find the last child line of a header line. +get int GetLastChild=2224(int line, int level) + +# Find the parent line of a child line. +get int GetFoldParent=2225(int line,) + +# Make a range of lines visible. +fun void ShowLines=2226(int lineStart, int lineEnd) + +# Make a range of lines invisible. +fun void HideLines=2227(int lineStart, int lineEnd) + +# Is a line visible? +get bool GetLineVisible=2228(int line,) + +# Are all lines visible? +get bool GetAllLinesVisible=2236(,) + +# Show the children of a header line. +set void SetFoldExpanded=2229(int line, bool expanded) + +# Is a header line expanded? +get bool GetFoldExpanded=2230(int line,) + +# Switch a header line between expanded and contracted. +fun void ToggleFold=2231(int line,) + +# Ensure a particular line is visible by expanding any header line hiding it. +fun void EnsureVisible=2232(int line,) + +enu FoldFlag=SC_FOLDFLAG_ +val SC_FOLDFLAG_LINEBEFORE_EXPANDED=0x0002 +val SC_FOLDFLAG_LINEBEFORE_CONTRACTED=0x0004 +val SC_FOLDFLAG_LINEAFTER_EXPANDED=0x0008 +val SC_FOLDFLAG_LINEAFTER_CONTRACTED=0x0010 +val SC_FOLDFLAG_LEVELNUMBERS=0x0040 + +# Set some style options for folding. +fun void SetFoldFlags=2233(int flags,) + +# Ensure a particular line is visible by expanding any header line hiding it. +# Use the currently set visibility policy to determine which range to display. +fun void EnsureVisibleEnforcePolicy=2234(int line,) + +# Sets whether a tab pressed when caret is within indentation indents. +set void SetTabIndents=2260(bool tabIndents,) + +# Does a tab pressed when caret is within indentation indent? +get bool GetTabIndents=2261(,) + +# Sets whether a backspace pressed when caret is within indentation unindents. +set void SetBackSpaceUnIndents=2262(bool bsUnIndents,) + +# Does a backspace pressed when caret is within indentation unindent? +get bool GetBackSpaceUnIndents=2263(,) + +val SC_TIME_FOREVER=10000000 + +# Sets the time the mouse must sit still to generate a mouse dwell event. +set void SetMouseDwellTime=2264(int periodMilliseconds,) + +# Retrieve the time the mouse must sit still to generate a mouse dwell event. +get int GetMouseDwellTime=2265(,) + +# Get position of start of word. +fun int WordStartPosition=2266(position pos, bool onlyWordCharacters) + +# Get position of end of word. +fun int WordEndPosition=2267(position pos, bool onlyWordCharacters) + +enu Wrap=SC_WRAP_ +val SC_WRAP_NONE=0 +val SC_WRAP_WORD=1 +val SC_WRAP_CHAR=2 + +# Sets whether text is word wrapped. +set void SetWrapMode=2268(int mode,) + +# Retrieve whether text is word wrapped. +get int GetWrapMode=2269(,) + +enu WrapVisualFlag=SC_WRAPVISUALFLAG_ +val SC_WRAPVISUALFLAG_NONE=0x0000 +val SC_WRAPVISUALFLAG_END=0x0001 +val SC_WRAPVISUALFLAG_START=0x0002 + +# Set the display mode of visual flags for wrapped lines. +set void SetWrapVisualFlags=2460(int wrapVisualFlags,) + +# Retrive the display mode of visual flags for wrapped lines. +get int GetWrapVisualFlags=2461(,) + +enu WrapVisualLocation=SC_WRAPVISUALFLAGLOC_ +val SC_WRAPVISUALFLAGLOC_DEFAULT=0x0000 +val SC_WRAPVISUALFLAGLOC_END_BY_TEXT=0x0001 +val SC_WRAPVISUALFLAGLOC_START_BY_TEXT=0x0002 + +# Set the location of visual flags for wrapped lines. +set void SetWrapVisualFlagsLocation=2462(int wrapVisualFlagsLocation,) + +# Retrive the location of visual flags for wrapped lines. +get int GetWrapVisualFlagsLocation=2463(,) + +# Set the start indent for wrapped lines. +set void SetWrapStartIndent=2464(int indent,) + +# Retrive the start indent for wrapped lines. +get int GetWrapStartIndent=2465(,) + +enu WrapIndentMode=SC_WRAPINDENT_ +val SC_WRAPINDENT_FIXED=0 +val SC_WRAPINDENT_SAME=1 +val SC_WRAPINDENT_INDENT=2 + +# Sets how wrapped sublines are placed. Default is fixed. +set void SetWrapIndentMode=2472(int mode,) + +# Retrieve how wrapped sublines are placed. Default is fixed. +get int GetWrapIndentMode=2473(,) + +enu LineCache=SC_CACHE_ +val SC_CACHE_NONE=0 +val SC_CACHE_CARET=1 +val SC_CACHE_PAGE=2 +val SC_CACHE_DOCUMENT=3 + +# Sets the degree of caching of layout information. +set void SetLayoutCache=2272(int mode,) + +# Retrieve the degree of caching of layout information. +get int GetLayoutCache=2273(,) + +# Sets the document width assumed for scrolling. +set void SetScrollWidth=2274(int pixelWidth,) + +# Retrieve the document width assumed for scrolling. +get int GetScrollWidth=2275(,) + +# Sets whether the maximum width line displayed is used to set scroll width. +set void SetScrollWidthTracking=2516(bool tracking,) + +# Retrieve whether the scroll width tracks wide lines. +get bool GetScrollWidthTracking=2517(,) + +# Measure the pixel width of some text in a particular style. +# NUL terminated text argument. +# Does not handle tab or control characters. +fun int TextWidth=2276(int style, string text) + +# Sets the scroll range so that maximum scroll position has +# the last line at the bottom of the view (default). +# Setting this to false allows scrolling one page below the last line. +set void SetEndAtLastLine=2277(bool endAtLastLine,) + +# Retrieve whether the maximum scroll position has the last +# line at the bottom of the view. +get bool GetEndAtLastLine=2278(,) + +# Retrieve the height of a particular line of text in pixels. +fun int TextHeight=2279(int line,) + +# Show or hide the vertical scroll bar. +set void SetVScrollBar=2280(bool show,) + +# Is the vertical scroll bar visible? +get bool GetVScrollBar=2281(,) + +# Append a string to the end of the document without changing the selection. +fun void AppendText=2282(int length, string text) + +# Is drawing done in two phases with backgrounds drawn before faoregrounds? +get bool GetTwoPhaseDraw=2283(,) + +# In twoPhaseDraw mode, drawing is performed in two phases, first the background +# and then the foreground. This avoids chopping off characters that overlap the next run. +set void SetTwoPhaseDraw=2284(bool twoPhase,) + +# Control font anti-aliasing. + +enu FontQuality=SC_EFF_ +val SC_EFF_QUALITY_MASK=0xF +val SC_EFF_QUALITY_DEFAULT=0 +val SC_EFF_QUALITY_NON_ANTIALIASED=1 +val SC_EFF_QUALITY_ANTIALIASED=2 +val SC_EFF_QUALITY_LCD_OPTIMIZED=3 + +# Choose the quality level for text from the FontQuality enumeration. +set void SetFontQuality=2611(int fontQuality,) + +# Retrieve the quality level for text. +get int GetFontQuality=2612(,) + +# Scroll so that a display line is at the top of the display. +set void SetFirstVisibleLine=2613(int lineDisplay,) + +enu MultiPaste=SC_MULTIPASTE_ +val SC_MULTIPASTE_ONCE=0 +val SC_MULTIPASTE_EACH=1 + +# Change the effect of pasting when there are multiple selections. +set void SetMultiPaste=2614(int multiPaste,) + +# Retrieve the effect of pasting when there are multiple selections.. +get int GetMultiPaste=2615(,) + +# Retrieve the value of a tag from a regular expression search. +fun int GetTag=2616(int tagNumber, stringresult tagValue) + +# Make the target range start and end be the same as the selection range start and end. +fun void TargetFromSelection=2287(,) + +# Join the lines in the target. +fun void LinesJoin=2288(,) + +# Split the lines in the target into lines that are less wide than pixelWidth +# where possible. +fun void LinesSplit=2289(int pixelWidth,) + +# Set the colours used as a chequerboard pattern in the fold margin +fun void SetFoldMarginColour=2290(bool useSetting, colour back) +fun void SetFoldMarginHiColour=2291(bool useSetting, colour fore) + +## New messages go here + +## Start of key messages +# Move caret down one line. +fun void LineDown=2300(,) + +# Move caret down one line extending selection to new caret position. +fun void LineDownExtend=2301(,) + +# Move caret up one line. +fun void LineUp=2302(,) + +# Move caret up one line extending selection to new caret position. +fun void LineUpExtend=2303(,) + +# Move caret left one character. +fun void CharLeft=2304(,) + +# Move caret left one character extending selection to new caret position. +fun void CharLeftExtend=2305(,) + +# Move caret right one character. +fun void CharRight=2306(,) + +# Move caret right one character extending selection to new caret position. +fun void CharRightExtend=2307(,) + +# Move caret left one word. +fun void WordLeft=2308(,) + +# Move caret left one word extending selection to new caret position. +fun void WordLeftExtend=2309(,) + +# Move caret right one word. +fun void WordRight=2310(,) + +# Move caret right one word extending selection to new caret position. +fun void WordRightExtend=2311(,) + +# Move caret to first position on line. +fun void Home=2312(,) + +# Move caret to first position on line extending selection to new caret position. +fun void HomeExtend=2313(,) + +# Move caret to last position on line. +fun void LineEnd=2314(,) + +# Move caret to last position on line extending selection to new caret position. +fun void LineEndExtend=2315(,) + +# Move caret to first position in document. +fun void DocumentStart=2316(,) + +# Move caret to first position in document extending selection to new caret position. +fun void DocumentStartExtend=2317(,) + +# Move caret to last position in document. +fun void DocumentEnd=2318(,) + +# Move caret to last position in document extending selection to new caret position. +fun void DocumentEndExtend=2319(,) + +# Move caret one page up. +fun void PageUp=2320(,) + +# Move caret one page up extending selection to new caret position. +fun void PageUpExtend=2321(,) + +# Move caret one page down. +fun void PageDown=2322(,) + +# Move caret one page down extending selection to new caret position. +fun void PageDownExtend=2323(,) + +# Switch from insert to overtype mode or the reverse. +fun void EditToggleOvertype=2324(,) + +# Cancel any modes such as call tip or auto-completion list display. +fun void Cancel=2325(,) + +# Delete the selection or if no selection, the character before the caret. +fun void DeleteBack=2326(,) + +# If selection is empty or all on one line replace the selection with a tab character. +# If more than one line selected, indent the lines. +fun void Tab=2327(,) + +# Dedent the selected lines. +fun void BackTab=2328(,) + +# Insert a new line, may use a CRLF, CR or LF depending on EOL mode. +fun void NewLine=2329(,) + +# Insert a Form Feed character. +fun void FormFeed=2330(,) + +# Move caret to before first visible character on line. +# If already there move to first character on line. +fun void VCHome=2331(,) + +# Like VCHome but extending selection to new caret position. +fun void VCHomeExtend=2332(,) + +# Magnify the displayed text by increasing the sizes by 1 point. +fun void ZoomIn=2333(,) + +# Make the displayed text smaller by decreasing the sizes by 1 point. +fun void ZoomOut=2334(,) + +# Delete the word to the left of the caret. +fun void DelWordLeft=2335(,) + +# Delete the word to the right of the caret. +fun void DelWordRight=2336(,) + +# Delete the word to the right of the caret, but not the trailing non-word characters. +fun void DelWordRightEnd=2518(,) + +# Cut the line containing the caret. +fun void LineCut=2337(,) + +# Delete the line containing the caret. +fun void LineDelete=2338(,) + +# Switch the current line with the previous. +fun void LineTranspose=2339(,) + +# Duplicate the current line. +fun void LineDuplicate=2404(,) + +# Transform the selection to lower case. +fun void LowerCase=2340(,) + +# Transform the selection to upper case. +fun void UpperCase=2341(,) + +# Scroll the document down, keeping the caret visible. +fun void LineScrollDown=2342(,) + +# Scroll the document up, keeping the caret visible. +fun void LineScrollUp=2343(,) + +# Delete the selection or if no selection, the character before the caret. +# Will not delete the character before at the start of a line. +fun void DeleteBackNotLine=2344(,) + +# Move caret to first position on display line. +fun void HomeDisplay=2345(,) + +# Move caret to first position on display line extending selection to +# new caret position. +fun void HomeDisplayExtend=2346(,) + +# Move caret to last position on display line. +fun void LineEndDisplay=2347(,) + +# Move caret to last position on display line extending selection to new +# caret position. +fun void LineEndDisplayExtend=2348(,) + +# These are like their namesakes Home(Extend)?, LineEnd(Extend)?, VCHome(Extend)? +# except they behave differently when word-wrap is enabled: +# They go first to the start / end of the display line, like (Home|LineEnd)Display +# The difference is that, the cursor is already at the point, it goes on to the start +# or end of the document line, as appropriate for (Home|LineEnd|VCHome)(Extend)?. + +fun void HomeWrap=2349(,) +fun void HomeWrapExtend=2450(,) +fun void LineEndWrap=2451(,) +fun void LineEndWrapExtend=2452(,) +fun void VCHomeWrap=2453(,) +fun void VCHomeWrapExtend=2454(,) + +# Copy the line containing the caret. +fun void LineCopy=2455(,) + +# Move the caret inside current view if it's not there already. +fun void MoveCaretInsideView=2401(,) + +# How many characters are on a line, including end of line characters? +fun int LineLength=2350(int line,) + +# Highlight the characters at two positions. +fun void BraceHighlight=2351(position pos1, position pos2) + +# Use specified indicator to highlight matching braces instead of changing their style. +fun void BraceHighlightIndicator=2498(bool useBraceHighlightIndicator, int indicator) + +# Highlight the character at a position indicating there is no matching brace. +fun void BraceBadLight=2352(position pos,) + +# Use specified indicator to highlight non matching brace instead of changing its style. +fun void BraceBadLightIndicator=2499(bool useBraceBadLightIndicator, int indicator) + +# Find the position of a matching brace or INVALID_POSITION if no match. +fun position BraceMatch=2353(position pos,) + +# Are the end of line characters visible? +get bool GetViewEOL=2355(,) + +# Make the end of line characters visible or invisible. +set void SetViewEOL=2356(bool visible,) + +# Retrieve a pointer to the document object. +get int GetDocPointer=2357(,) + +# Change the document object used. +set void SetDocPointer=2358(, int pointer) + +# Set which document modification events are sent to the container. +set void SetModEventMask=2359(int mask,) + +enu EdgeVisualStyle=EDGE_ +val EDGE_NONE=0 +val EDGE_LINE=1 +val EDGE_BACKGROUND=2 + +# Retrieve the column number which text should be kept within. +get int GetEdgeColumn=2360(,) + +# Set the column number of the edge. +# If text goes past the edge then it is highlighted. +set void SetEdgeColumn=2361(int column,) + +# Retrieve the edge highlight mode. +get int GetEdgeMode=2362(,) + +# The edge may be displayed by a line (EDGE_LINE) or by highlighting text that +# goes beyond it (EDGE_BACKGROUND) or not displayed at all (EDGE_NONE). +set void SetEdgeMode=2363(int mode,) + +# Retrieve the colour used in edge indication. +get colour GetEdgeColour=2364(,) + +# Change the colour used in edge indication. +set void SetEdgeColour=2365(colour edgeColour,) + +# Sets the current caret position to be the search anchor. +fun void SearchAnchor=2366(,) + +# Find some text starting at the search anchor. +# Does not ensure the selection is visible. +fun int SearchNext=2367(int flags, string text) + +# Find some text starting at the search anchor and moving backwards. +# Does not ensure the selection is visible. +fun int SearchPrev=2368(int flags, string text) + +# Retrieves the number of lines completely visible. +get int LinesOnScreen=2370(,) + +# Set whether a pop up menu is displayed automatically when the user presses +# the wrong mouse button. +fun void UsePopUp=2371(bool allowPopUp,) + +# Is the selection rectangular? The alternative is the more common stream selection. +get bool SelectionIsRectangle=2372(,) + +# Set the zoom level. This number of points is added to the size of all fonts. +# It may be positive to magnify or negative to reduce. +set void SetZoom=2373(int zoom,) +# Retrieve the zoom level. +get int GetZoom=2374(,) + +# Create a new document object. +# Starts with reference count of 1 and not selected into editor. +fun int CreateDocument=2375(,) +# Extend life of document. +fun void AddRefDocument=2376(, int doc) +# Release a reference to the document, deleting document if it fades to black. +fun void ReleaseDocument=2377(, int doc) + +# Get which document modification events are sent to the container. +get int GetModEventMask=2378(,) + +# Change internal focus flag. +set void SetFocus=2380(bool focus,) +# Get internal focus flag. +get bool GetFocus=2381(,) + +enu Status=SC_STATUS_ +val SC_STATUS_OK=0 +val SC_STATUS_FAILURE=1 +val SC_STATUS_BADALLOC=2 + +# Change error status - 0 = OK. +set void SetStatus=2382(int statusCode,) +# Get error status. +get int GetStatus=2383(,) + +# Set whether the mouse is captured when its button is pressed. +set void SetMouseDownCaptures=2384(bool captures,) +# Get whether mouse gets captured. +get bool GetMouseDownCaptures=2385(,) + +enu CursorShape=SC_CURSOR +val SC_CURSORNORMAL=-1 +val SC_CURSORARROW=2 +val SC_CURSORWAIT=4 +val SC_CURSORREVERSEARROW=7 +# Sets the cursor to one of the SC_CURSOR* values. +set void SetCursor=2386(int cursorType,) +# Get cursor type. +get int GetCursor=2387(,) + +# Change the way control characters are displayed: +# If symbol is < 32, keep the drawn way, else, use the given character. +set void SetControlCharSymbol=2388(int symbol,) +# Get the way control characters are displayed. +get int GetControlCharSymbol=2389(,) + +# Move to the previous change in capitalisation. +fun void WordPartLeft=2390(,) +# Move to the previous change in capitalisation extending selection +# to new caret position. +fun void WordPartLeftExtend=2391(,) +# Move to the change next in capitalisation. +fun void WordPartRight=2392(,) +# Move to the next change in capitalisation extending selection +# to new caret position. +fun void WordPartRightExtend=2393(,) + +# Constants for use with SetVisiblePolicy, similar to SetCaretPolicy. +val VISIBLE_SLOP=0x01 +val VISIBLE_STRICT=0x04 +# Set the way the display area is determined when a particular line +# is to be moved to by Find, FindNext, GotoLine, etc. +fun void SetVisiblePolicy=2394(int visiblePolicy, int visibleSlop) + +# Delete back from the current position to the start of the line. +fun void DelLineLeft=2395(,) + +# Delete forwards from the current position to the end of the line. +fun void DelLineRight=2396(,) + +# Get and Set the xOffset (ie, horizonal scroll position). +set void SetXOffset=2397(int newOffset,) +get int GetXOffset=2398(,) + +# Set the last x chosen value to be the caret x position. +fun void ChooseCaretX=2399(,) + +# Set the focus to this Scintilla widget. +fun void GrabFocus=2400(,) + +enu CaretPolicy=CARET_ +# Caret policy, used by SetXCaretPolicy and SetYCaretPolicy. +# If CARET_SLOP is set, we can define a slop value: caretSlop. +# This value defines an unwanted zone (UZ) where the caret is... unwanted. +# This zone is defined as a number of pixels near the vertical margins, +# and as a number of lines near the horizontal margins. +# By keeping the caret away from the edges, it is seen within its context, +# so it is likely that the identifier that the caret is on can be completely seen, +# and that the current line is seen with some of the lines following it which are +# often dependent on that line. +val CARET_SLOP=0x01 +# If CARET_STRICT is set, the policy is enforced... strictly. +# The caret is centred on the display if slop is not set, +# and cannot go in the UZ if slop is set. +val CARET_STRICT=0x04 +# If CARET_JUMPS is set, the display is moved more energetically +# so the caret can move in the same direction longer before the policy is applied again. +val CARET_JUMPS=0x10 +# If CARET_EVEN is not set, instead of having symmetrical UZs, +# the left and bottom UZs are extended up to right and top UZs respectively. +# This way, we favour the displaying of useful information: the begining of lines, +# where most code reside, and the lines after the caret, eg. the body of a function. +val CARET_EVEN=0x08 + +# Set the way the caret is kept visible when going sideway. +# The exclusion zone is given in pixels. +fun void SetXCaretPolicy=2402(int caretPolicy, int caretSlop) + +# Set the way the line the caret is on is kept visible. +# The exclusion zone is given in lines. +fun void SetYCaretPolicy=2403(int caretPolicy, int caretSlop) + +# Set printing to line wrapped (SC_WRAP_WORD) or not line wrapped (SC_WRAP_NONE). +set void SetPrintWrapMode=2406(int mode,) + +# Is printing line wrapped? +get int GetPrintWrapMode=2407(,) + +# Set a fore colour for active hotspots. +set void SetHotspotActiveFore=2410(bool useSetting, colour fore) + +# Get the fore colour for active hotspots. +get colour GetHotspotActiveFore=2494(,) + +# Set a back colour for active hotspots. +set void SetHotspotActiveBack=2411(bool useSetting, colour back) + +# Get the back colour for active hotspots. +get colour GetHotspotActiveBack=2495(,) + +# Enable / Disable underlining active hotspots. +set void SetHotspotActiveUnderline=2412(bool underline,) + +# Get whether underlining for active hotspots. +get bool GetHotspotActiveUnderline=2496(,) + +# Limit hotspots to single line so hotspots on two lines don't merge. +set void SetHotspotSingleLine=2421(bool singleLine,) + +# Get the HotspotSingleLine property +get bool GetHotspotSingleLine=2497(,) + +# Move caret between paragraphs (delimited by empty lines). +fun void ParaDown=2413(,) +fun void ParaDownExtend=2414(,) +fun void ParaUp=2415(,) +fun void ParaUpExtend=2416(,) + +# Given a valid document position, return the previous position taking code +# page into account. Returns 0 if passed 0. +fun position PositionBefore=2417(position pos,) + +# Given a valid document position, return the next position taking code +# page into account. Maximum value returned is the last position in the document. +fun position PositionAfter=2418(position pos,) + +# Copy a range of text to the clipboard. Positions are clipped into the document. +fun void CopyRange=2419(position start, position end) + +# Copy argument text to the clipboard. +fun void CopyText=2420(int length, string text) + +enu SelectionMode=SC_SEL_ +val SC_SEL_STREAM=0 +val SC_SEL_RECTANGLE=1 +val SC_SEL_LINES=2 +val SC_SEL_THIN=3 + +# Set the selection mode to stream (SC_SEL_STREAM) or rectangular (SC_SEL_RECTANGLE/SC_SEL_THIN) or +# by lines (SC_SEL_LINES). +set void SetSelectionMode=2422(int mode,) + +# Get the mode of the current selection. +get int GetSelectionMode=2423(,) + +# Retrieve the position of the start of the selection at the given line (INVALID_POSITION if no selection on this line). +fun position GetLineSelStartPosition=2424(int line,) + +# Retrieve the position of the end of the selection at the given line (INVALID_POSITION if no selection on this line). +fun position GetLineSelEndPosition=2425(int line,) + +## RectExtended rectangular selection moves +# Move caret down one line, extending rectangular selection to new caret position. +fun void LineDownRectExtend=2426(,) + +# Move caret up one line, extending rectangular selection to new caret position. +fun void LineUpRectExtend=2427(,) + +# Move caret left one character, extending rectangular selection to new caret position. +fun void CharLeftRectExtend=2428(,) + +# Move caret right one character, extending rectangular selection to new caret position. +fun void CharRightRectExtend=2429(,) + +# Move caret to first position on line, extending rectangular selection to new caret position. +fun void HomeRectExtend=2430(,) + +# Move caret to before first visible character on line. +# If already there move to first character on line. +# In either case, extend rectangular selection to new caret position. +fun void VCHomeRectExtend=2431(,) + +# Move caret to last position on line, extending rectangular selection to new caret position. +fun void LineEndRectExtend=2432(,) + +# Move caret one page up, extending rectangular selection to new caret position. +fun void PageUpRectExtend=2433(,) + +# Move caret one page down, extending rectangular selection to new caret position. +fun void PageDownRectExtend=2434(,) + + +# Move caret to top of page, or one page up if already at top of page. +fun void StutteredPageUp=2435(,) + +# Move caret to top of page, or one page up if already at top of page, extending selection to new caret position. +fun void StutteredPageUpExtend=2436(,) + +# Move caret to bottom of page, or one page down if already at bottom of page. +fun void StutteredPageDown=2437(,) + +# Move caret to bottom of page, or one page down if already at bottom of page, extending selection to new caret position. +fun void StutteredPageDownExtend=2438(,) + + +# Move caret left one word, position cursor at end of word. +fun void WordLeftEnd=2439(,) + +# Move caret left one word, position cursor at end of word, extending selection to new caret position. +fun void WordLeftEndExtend=2440(,) + +# Move caret right one word, position cursor at end of word. +fun void WordRightEnd=2441(,) + +# Move caret right one word, position cursor at end of word, extending selection to new caret position. +fun void WordRightEndExtend=2442(,) + +# Set the set of characters making up whitespace for when moving or selecting by word. +# Should be called after SetWordChars. +set void SetWhitespaceChars=2443(, string characters) + +# Reset the set of characters for whitespace and word characters to the defaults. +fun void SetCharsDefault=2444(,) + +# Get currently selected item position in the auto-completion list +fun int AutoCGetCurrent=2445(,) + +# Get currently selected item text in the auto-completion list +# Returns the length of the item text +fun int AutoCGetCurrentText=2610(, stringresult s) + +# Enlarge the document to a particular size of text bytes. +fun void Allocate=2446(int bytes,) + +# Returns the target converted to UTF8. +# Return the length in bytes. +fun int TargetAsUTF8=2447(, stringresult s) + +# Set the length of the utf8 argument for calling EncodedFromUTF8. +# Set to -1 and the string will be measured to the first nul. +fun void SetLengthForEncode=2448(int bytes,) + +# Translates a UTF8 string into the document encoding. +# Return the length of the result in bytes. +# On error return 0. +fun int EncodedFromUTF8=2449(string utf8, stringresult encoded) + +# Find the position of a column on a line taking into account tabs and +# multi-byte characters. If beyond end of line, return line end position. +fun int FindColumn=2456(int line, int column) + +# Can the caret preferred x position only be changed by explicit movement commands? +get int GetCaretSticky=2457(,) + +# Stop the caret preferred x position changing when the user types. +set void SetCaretSticky=2458(int useCaretStickyBehaviour,) + +enu CaretSticky=SC_CARETSTICKY_ +val SC_CARETSTICKY_OFF=0 +val SC_CARETSTICKY_ON=1 +val SC_CARETSTICKY_WHITESPACE=2 + +# Switch between sticky and non-sticky: meant to be bound to a key. +fun void ToggleCaretSticky=2459(,) + +# Enable/Disable convert-on-paste for line endings +set void SetPasteConvertEndings=2467(bool convert,) + +# Get convert-on-paste setting +get bool GetPasteConvertEndings=2468(,) + +# Duplicate the selection. If selection empty duplicate the line containing the caret. +fun void SelectionDuplicate=2469(,) + +val SC_ALPHA_TRANSPARENT=0 +val SC_ALPHA_OPAQUE=255 +val SC_ALPHA_NOALPHA=256 + +# Set background alpha of the caret line. +set void SetCaretLineBackAlpha=2470(int alpha,) + +# Get the background alpha of the caret line. +get int GetCaretLineBackAlpha=2471(,) + +enu CaretStyle=CARETSTYLE_ +val CARETSTYLE_INVISIBLE=0 +val CARETSTYLE_LINE=1 +val CARETSTYLE_BLOCK=2 + +# Set the style of the caret to be drawn. +set void SetCaretStyle=2512(int caretStyle,) + +# Returns the current style of the caret. +get int GetCaretStyle=2513(,) + +# Set the indicator used for IndicatorFillRange and IndicatorClearRange +set void SetIndicatorCurrent=2500(int indicator,) + +# Get the current indicator +get int GetIndicatorCurrent=2501(,) + +# Set the value used for IndicatorFillRange +set void SetIndicatorValue=2502(int value,) + +# Get the current indicator vaue +get int GetIndicatorValue=2503(,) + +# Turn a indicator on over a range. +fun void IndicatorFillRange=2504(int position, int fillLength) + +# Turn a indicator off over a range. +fun void IndicatorClearRange=2505(int position, int clearLength) + +# Are any indicators present at position? +fun int IndicatorAllOnFor=2506(int position,) + +# What value does a particular indicator have at at a position? +fun int IndicatorValueAt=2507(int indicator, int position) + +# Where does a particular indicator start? +fun int IndicatorStart=2508(int indicator, int position) + +# Where does a particular indicator end? +fun int IndicatorEnd=2509(int indicator, int position) + +# Set number of entries in position cache +set void SetPositionCache=2514(int size,) + +# How many entries are allocated to the position cache? +get int GetPositionCache=2515(,) + +# Copy the selection, if selection empty copy the line with the caret +fun void CopyAllowLine=2519(,) + +# Compact the document buffer and return a read-only pointer to the +# characters in the document. +get int GetCharacterPointer=2520(,) + +# Always interpret keyboard input as Unicode +set void SetKeysUnicode=2521(bool keysUnicode,) + +# Are keys always interpreted as Unicode? +get bool GetKeysUnicode=2522(,) + +# Set the alpha fill colour of the given indicator. +set void IndicSetAlpha=2523(int indicator, int alpha) + +# Get the alpha fill colour of the given indicator. +get int IndicGetAlpha=2524(int indicator,) + +# Set the alpha outline colour of the given indicator. +set void IndicSetOutlineAlpha=2558(int indicator, int alpha) + +# Get the alpha outline colour of the given indicator. +get int IndicGetOutlineAlpha=2559(int indicator,) + +# Set extra ascent for each line +set void SetExtraAscent=2525(int extraAscent,) + +# Get extra ascent for each line +get int GetExtraAscent=2526(,) + +# Set extra descent for each line +set void SetExtraDescent=2527(int extraDescent,) + +# Get extra descent for each line +get int GetExtraDescent=2528(,) + +# Which symbol was defined for markerNumber with MarkerDefine +fun int MarkerSymbolDefined=2529(int markerNumber,) + +# Set the text in the text margin for a line +set void MarginSetText=2530(int line, string text) + +# Get the text in the text margin for a line +get int MarginGetText=2531(int line, stringresult text) + +# Set the style number for the text margin for a line +set void MarginSetStyle=2532(int line, int style) + +# Get the style number for the text margin for a line +get int MarginGetStyle=2533(int line,) + +# Set the style in the text margin for a line +set void MarginSetStyles=2534(int line, string styles) + +# Get the styles in the text margin for a line +get int MarginGetStyles=2535(int line, stringresult styles) + +# Clear the margin text on all lines +fun void MarginTextClearAll=2536(,) + +# Get the start of the range of style numbers used for margin text +set void MarginSetStyleOffset=2537(int style,) + +# Get the start of the range of style numbers used for margin text +get int MarginGetStyleOffset=2538(,) + +enu MarginOption=SC_MARGINOPTION_ +val SC_MARGINOPTION_NONE=0 +val SC_MARGINOPTION_SUBLINESELECT=1 + +# Set the margin options. +set void SetMarginOptions=2539(int marginOptions,) + +# Get the margin options. +get int GetMarginOptions=2557(,) + +# Set the annotation text for a line +set void AnnotationSetText=2540(int line, string text) + +# Get the annotation text for a line +get int AnnotationGetText=2541(int line, stringresult text) + +# Set the style number for the annotations for a line +set void AnnotationSetStyle=2542(int line, int style) + +# Get the style number for the annotations for a line +get int AnnotationGetStyle=2543(int line,) + +# Set the annotation styles for a line +set void AnnotationSetStyles=2544(int line, string styles) + +# Get the annotation styles for a line +get int AnnotationGetStyles=2545(int line, stringresult styles) + +# Get the number of annotation lines for a line +get int AnnotationGetLines=2546(int line,) + +# Clear the annotations from all lines +fun void AnnotationClearAll=2547(,) + +enu AnnotationVisible=ANNOTATION_ +val ANNOTATION_HIDDEN=0 +val ANNOTATION_STANDARD=1 +val ANNOTATION_BOXED=2 + +# Set the visibility for the annotations for a view +set void AnnotationSetVisible=2548(int visible,) + +# Get the visibility for the annotations for a view +get int AnnotationGetVisible=2549(,) + +# Get the start of the range of style numbers used for annotations +set void AnnotationSetStyleOffset=2550(int style,) + +# Get the start of the range of style numbers used for annotations +get int AnnotationGetStyleOffset=2551(,) + +val UNDO_MAY_COALESCE=1 + +# Add a container action to the undo stack +fun void AddUndoAction=2560(int token, int flags) + +# Find the position of a character from a point within the window. +fun position CharPositionFromPoint=2561(int x, int y) + +# Find the position of a character from a point within the window. +# Return INVALID_POSITION if not close to text. +fun position CharPositionFromPointClose=2562(int x, int y) + +# Set whether multiple selections can be made +set void SetMultipleSelection=2563(bool multipleSelection,) + +# Whether multiple selections can be made +get bool GetMultipleSelection=2564(,) + +# Set whether typing can be performed into multiple selections +set void SetAdditionalSelectionTyping=2565(bool additionalSelectionTyping,) + +# Whether typing can be performed into multiple selections +get bool GetAdditionalSelectionTyping=2566(,) + +# Set whether additional carets will blink +set void SetAdditionalCaretsBlink=2567(bool additionalCaretsBlink,) + +# Whether additional carets will blink +get bool GetAdditionalCaretsBlink=2568(,) + +# Set whether additional carets are visible +set void SetAdditionalCaretsVisible=2608(bool additionalCaretsBlink,) + +# Whether additional carets are visible +get bool GetAdditionalCaretsVisible=2609(,) + +# How many selections are there? +get int GetSelections=2570(,) + +# Clear selections to a single empty stream selection +fun void ClearSelections=2571(,) + +# Set a simple selection +fun int SetSelection=2572(int caret,int anchor) + +# Add a selection +fun int AddSelection=2573(int caret,int anchor) + +# Set the main selection +set void SetMainSelection=2574(int selection,) + +# Which selection is the main selection +get int GetMainSelection=2575(,) + +set void SetSelectionNCaret=2576(int selection, position pos) +get position GetSelectionNCaret=2577(int selection,) +set void SetSelectionNAnchor=2578(int selection, position posAnchor) +get position GetSelectionNAnchor=2579(int selection,) +set void SetSelectionNCaretVirtualSpace=2580(int selection, int space) +get int GetSelectionNCaretVirtualSpace=2581(int selection,) +set void SetSelectionNAnchorVirtualSpace=2582(int selection, int space) +get int GetSelectionNAnchorVirtualSpace=2583(int selection,) + +# Sets the position that starts the selection - this becomes the anchor. +set void SetSelectionNStart=2584(int selection, position pos) + +# Returns the position at the start of the selection. +get position GetSelectionNStart=2585(int selection,) + +# Sets the position that ends the selection - this becomes the currentPosition. +set void SetSelectionNEnd=2586(int selection, position pos,) + +# Returns the position at the end of the selection. +get position GetSelectionNEnd=2587(int selection,) + +set void SetRectangularSelectionCaret=2588(position pos,) +get position GetRectangularSelectionCaret=2589(,) +set void SetRectangularSelectionAnchor=2590(position posAnchor,) +get position GetRectangularSelectionAnchor=2591(,) +set void SetRectangularSelectionCaretVirtualSpace=2592(int space,) +get int GetRectangularSelectionCaretVirtualSpace=2593(,) +set void SetRectangularSelectionAnchorVirtualSpace=2594(int space,) +get int GetRectangularSelectionAnchorVirtualSpace=2595(,) + +enu VirtualSpace=SCVS_ +val SCVS_NONE=0 +val SCVS_RECTANGULARSELECTION=1 +val SCVS_USERACCESSIBLE=2 + +set void SetVirtualSpaceOptions=2596(int virtualSpaceOptions,) +get int GetVirtualSpaceOptions=2597(,) + +# On GTK+, allow selecting the modifier key to use for mouse-based +# rectangular selection. Often the window manager requires Alt+Mouse Drag +# for moving windows. +# Valid values are SCMOD_CTRL(default), SCMOD_ALT, or SCMOD_SUPER. + +set void SetRectangularSelectionModifier=2598(int modifier,) + +# Get the modifier key used for rectangular selection. +get int GetRectangularSelectionModifier=2599(,) + +# Set the foreground colour of additional selections. +# Must have previously called SetSelFore with non-zero first argument for this to have an effect. +set void SetAdditionalSelFore=2600(colour fore,) + +# Set the background colour of additional selections. +# Must have previously called SetSelBack with non-zero first argument for this to have an effect. +set void SetAdditionalSelBack=2601(colour back,) + +# Set the alpha of the selection. +set void SetAdditionalSelAlpha=2602(int alpha,) + +# Get the alpha of the selection. +get int GetAdditionalSelAlpha=2603(,) + +# Set the foreground colour of additional carets. +set void SetAdditionalCaretFore=2604(colour fore,) + +# Get the foreground colour of additional carets. +get colour GetAdditionalCaretFore=2605(,) + +# Set the main selection to the next selection. +fun void RotateSelection=2606(,) + +# Swap that caret and anchor of the main selection. +fun void SwapMainAnchorCaret=2607(,) + +# Indicate that the internal state of a lexer has changed over a range and therefore +# there may be a need to redraw. +fun int ChangeLexerState=2617(position start, position end) + +# Find the next line at or after lineStart that is a contracted fold header line. +# Return -1 when no more lines. +fun int ContractedFoldNext=2618(int lineStart,) + +# Centre current line in window. +fun void VerticalCentreCaret=2619(,) + +# Move the selected lines up one line, shifting the line above after the selection +fun void MoveSelectedLinesUp=2620(,) + +# Move the selected lines down one line, shifting the line below before the selection +fun void MoveSelectedLinesDown=2621(,) + +# Set the identifier reported as idFrom in notification messages. +set void SetIdentifier=2622(int identifier,) + +# Get the identifier. +get int GetIdentifier=2623(,) + +# Set the width for future RGBA image data. +set void RGBAImageSetWidth=2624(int width,) + +# Set the height for future RGBA image data. +set void RGBAImageSetHeight=2625(int height,) + +# Define a marker from RGBA data. +# It has the width and height from RGBAImageSetWidth/Height +fun void MarkerDefineRGBAImage=2626(int markerNumber, string pixels) + +# Register an RGBA image for use in autocompletion lists. +# It has the width and height from RGBAImageSetWidth/Height +fun void RegisterRGBAImage=2627(int type, string pixels) + +# Scroll to start of document. +fun void ScrollToStart=2628(,) + +# Scroll to end of document. +fun void ScrollToEnd=2629(,) + +val SC_TECHNOLOGY_DEFAULT=0 +val SC_TECHNOLOGY_DIRECTWRITE=1 + +# Set the technolgy used. +set void SetTechnology=2630(int technology,) + +# Get the tech. +get int GetTechnology=2631(,) + +# Create an ILoader*. +fun int CreateLoader=2632(int bytes,) + +# Start notifying the container of all key presses and commands. +fun void StartRecord=3001(,) + +# Stop notifying the container of all key presses and commands. +fun void StopRecord=3002(,) + +# Set the lexing language of the document. +set void SetLexer=4001(int lexer,) + +# Retrieve the lexing language of the document. +get int GetLexer=4002(,) + +# Colourise a segment of the document using the current lexing language. +fun void Colourise=4003(position start, position end) + +# Set up a value that may be used by a lexer for some optional feature. +set void SetProperty=4004(string key, string value) + +# Maximum value of keywordSet parameter of SetKeyWords. +val KEYWORDSET_MAX=8 + +# Set up the key words used by the lexer. +set void SetKeyWords=4005(int keywordSet, string keyWords) + +# Set the lexing language of the document based on string name. +set void SetLexerLanguage=4006(, string language) + +# Load a lexer library (dll / so). +fun void LoadLexerLibrary=4007(, string path) + +# Retrieve a "property" value previously set with SetProperty. +fun int GetProperty=4008(string key, stringresult buf) + +# Retrieve a "property" value previously set with SetProperty, +# with "$()" variable replacement on returned buffer. +fun int GetPropertyExpanded=4009(string key, stringresult buf) + +# Retrieve a "property" value previously set with SetProperty, +# interpreted as an int AFTER any "$()" variable replacement. +get int GetPropertyInt=4010(string key,) + +# Retrieve the number of bits the current lexer needs for styling. +get int GetStyleBitsNeeded=4011(,) + +# Retrieve the name of the lexer. +# Return the length of the text. +get int GetLexerLanguage=4012(, stringresult text) + +# For private communication between an application and a known lexer. +fun int PrivateLexerCall=4013(int operation, int pointer) + +# Retrieve a '\n' separated list of properties understood by the current lexer. +fun int PropertyNames=4014(, stringresult names) + +enu TypeProperty=SC_TYPE_ +val SC_TYPE_BOOLEAN=0 +val SC_TYPE_INTEGER=1 +val SC_TYPE_STRING=2 + +# Retrieve the type of a property. +fun int PropertyType=4015(string name,) + +# Describe a property. +fun int DescribeProperty=4016(string name, stringresult description) + +# Retrieve a '\n' separated list of descriptions of the keyword sets understood by the current lexer. +fun int DescribeKeyWordSets=4017(, stringresult descriptions) + +# Notifications +# Type of modification and the action which caused the modification. +# These are defined as a bit mask to make it easy to specify which notifications are wanted. +# One bit is set from each of SC_MOD_* and SC_PERFORMED_*. +enu ModificationFlags=SC_MOD_ SC_PERFORMED_ SC_LAST +val SC_MOD_INSERTTEXT=0x1 +val SC_MOD_DELETETEXT=0x2 +val SC_MOD_CHANGESTYLE=0x4 +val SC_MOD_CHANGEFOLD=0x8 +val SC_PERFORMED_USER=0x10 +val SC_PERFORMED_UNDO=0x20 +val SC_PERFORMED_REDO=0x40 +val SC_MULTISTEPUNDOREDO=0x80 +val SC_LASTSTEPINUNDOREDO=0x100 +val SC_MOD_CHANGEMARKER=0x200 +val SC_MOD_BEFOREINSERT=0x400 +val SC_MOD_BEFOREDELETE=0x800 +val SC_MULTILINEUNDOREDO=0x1000 +val SC_STARTACTION=0x2000 +val SC_MOD_CHANGEINDICATOR=0x4000 +val SC_MOD_CHANGELINESTATE=0x8000 +val SC_MOD_CHANGEMARGIN=0x10000 +val SC_MOD_CHANGEANNOTATION=0x20000 +val SC_MOD_CONTAINER=0x40000 +val SC_MOD_LEXERSTATE=0x80000 +val SC_MODEVENTMASKALL=0xFFFFF + +enu Update=SC_UPDATE_ +val SC_UPDATE_CONTENT=0x1 +val SC_UPDATE_SELECTION=0x2 +val SC_UPDATE_V_SCROLL=0x4 +val SC_UPDATE_H_SCROLL=0x8 + +# For compatibility, these go through the COMMAND notification rather than NOTIFY +# and should have had exactly the same values as the EN_* constants. +# Unfortunately the SETFOCUS and KILLFOCUS are flipped over from EN_* +# As clients depend on these constants, this will not be changed. +val SCEN_CHANGE=768 +val SCEN_SETFOCUS=512 +val SCEN_KILLFOCUS=256 + +# Symbolic key codes and modifier flags. +# ASCII and other printable characters below 256. +# Extended keys above 300. + +enu Keys=SCK_ +val SCK_DOWN=300 +val SCK_UP=301 +val SCK_LEFT=302 +val SCK_RIGHT=303 +val SCK_HOME=304 +val SCK_END=305 +val SCK_PRIOR=306 +val SCK_NEXT=307 +val SCK_DELETE=308 +val SCK_INSERT=309 +val SCK_ESCAPE=7 +val SCK_BACK=8 +val SCK_TAB=9 +val SCK_RETURN=13 +val SCK_ADD=310 +val SCK_SUBTRACT=311 +val SCK_DIVIDE=312 +val SCK_WIN=313 +val SCK_RWIN=314 +val SCK_MENU=315 + +enu KeyMod=SCMOD_ +val SCMOD_NORM=0 +val SCMOD_SHIFT=1 +val SCMOD_CTRL=2 +val SCMOD_ALT=4 +val SCMOD_SUPER=8 +val SCMOD_META=16 + +################################################ +# For SciLexer.h +enu Lexer=SCLEX_ +val SCLEX_CONTAINER=0 +val SCLEX_NULL=1 +val SCLEX_PYTHON=2 +val SCLEX_CPP=3 +val SCLEX_HTML=4 +val SCLEX_XML=5 +val SCLEX_PERL=6 +val SCLEX_SQL=7 +val SCLEX_VB=8 +val SCLEX_PROPERTIES=9 +val SCLEX_ERRORLIST=10 +val SCLEX_MAKEFILE=11 +val SCLEX_BATCH=12 +val SCLEX_XCODE=13 +val SCLEX_LATEX=14 +val SCLEX_LUA=15 +val SCLEX_DIFF=16 +val SCLEX_CONF=17 +val SCLEX_PASCAL=18 +val SCLEX_AVE=19 +val SCLEX_ADA=20 +val SCLEX_LISP=21 +val SCLEX_RUBY=22 +val SCLEX_EIFFEL=23 +val SCLEX_EIFFELKW=24 +val SCLEX_TCL=25 +val SCLEX_NNCRONTAB=26 +val SCLEX_BULLANT=27 +val SCLEX_VBSCRIPT=28 +val SCLEX_BAAN=31 +val SCLEX_MATLAB=32 +val SCLEX_SCRIPTOL=33 +val SCLEX_ASM=34 +val SCLEX_CPPNOCASE=35 +val SCLEX_FORTRAN=36 +val SCLEX_F77=37 +val SCLEX_CSS=38 +val SCLEX_POV=39 +val SCLEX_LOUT=40 +val SCLEX_ESCRIPT=41 +val SCLEX_PS=42 +val SCLEX_NSIS=43 +val SCLEX_MMIXAL=44 +val SCLEX_CLW=45 +val SCLEX_CLWNOCASE=46 +val SCLEX_LOT=47 +val SCLEX_YAML=48 +val SCLEX_TEX=49 +val SCLEX_METAPOST=50 +val SCLEX_POWERBASIC=51 +val SCLEX_FORTH=52 +val SCLEX_ERLANG=53 +val SCLEX_OCTAVE=54 +val SCLEX_MSSQL=55 +val SCLEX_VERILOG=56 +val SCLEX_KIX=57 +val SCLEX_GUI4CLI=58 +val SCLEX_SPECMAN=59 +val SCLEX_AU3=60 +val SCLEX_APDL=61 +val SCLEX_BASH=62 +val SCLEX_ASN1=63 +val SCLEX_VHDL=64 +val SCLEX_CAML=65 +val SCLEX_BLITZBASIC=66 +val SCLEX_PUREBASIC=67 +val SCLEX_HASKELL=68 +val SCLEX_PHPSCRIPT=69 +val SCLEX_TADS3=70 +val SCLEX_REBOL=71 +val SCLEX_SMALLTALK=72 +val SCLEX_FLAGSHIP=73 +val SCLEX_CSOUND=74 +val SCLEX_FREEBASIC=75 +val SCLEX_INNOSETUP=76 +val SCLEX_OPAL=77 +val SCLEX_SPICE=78 +val SCLEX_D=79 +val SCLEX_CMAKE=80 +val SCLEX_GAP=81 +val SCLEX_PLM=82 +val SCLEX_PROGRESS=83 +val SCLEX_ABAQUS=84 +val SCLEX_ASYMPTOTE=85 +val SCLEX_R=86 +val SCLEX_MAGIK=87 +val SCLEX_POWERSHELL=88 +val SCLEX_MYSQL=89 +val SCLEX_PO=90 +val SCLEX_TAL=91 +val SCLEX_COBOL=92 +val SCLEX_TACL=93 +val SCLEX_SORCUS=94 +val SCLEX_POWERPRO=95 +val SCLEX_NIMROD=96 +val SCLEX_SML=97 +val SCLEX_MARKDOWN=98 +val SCLEX_TXT2TAGS=99 +val SCLEX_A68K=100 +val SCLEX_MODULA=101 +val SCLEX_COFFEESCRIPT=102 +val SCLEX_TCMD=103 +val SCLEX_AVS=104 + +# When a lexer specifies its language as SCLEX_AUTOMATIC it receives a +# value assigned in sequence from SCLEX_AUTOMATIC+1. +val SCLEX_AUTOMATIC=1000 +# Lexical states for SCLEX_PYTHON +lex Python=SCLEX_PYTHON SCE_P_ +lex Nimrod=SCLEX_NIMROD SCE_P_ +val SCE_P_DEFAULT=0 +val SCE_P_COMMENTLINE=1 +val SCE_P_NUMBER=2 +val SCE_P_STRING=3 +val SCE_P_CHARACTER=4 +val SCE_P_WORD=5 +val SCE_P_TRIPLE=6 +val SCE_P_TRIPLEDOUBLE=7 +val SCE_P_CLASSNAME=8 +val SCE_P_DEFNAME=9 +val SCE_P_OPERATOR=10 +val SCE_P_IDENTIFIER=11 +val SCE_P_COMMENTBLOCK=12 +val SCE_P_STRINGEOL=13 +val SCE_P_WORD2=14 +val SCE_P_DECORATOR=15 +# Lexical states for SCLEX_CPP +lex Cpp=SCLEX_CPP SCE_C_ +lex BullAnt=SCLEX_BULLANT SCE_C_ +val SCE_C_DEFAULT=0 +val SCE_C_COMMENT=1 +val SCE_C_COMMENTLINE=2 +val SCE_C_COMMENTDOC=3 +val SCE_C_NUMBER=4 +val SCE_C_WORD=5 +val SCE_C_STRING=6 +val SCE_C_CHARACTER=7 +val SCE_C_UUID=8 +val SCE_C_PREPROCESSOR=9 +val SCE_C_OPERATOR=10 +val SCE_C_IDENTIFIER=11 +val SCE_C_STRINGEOL=12 +val SCE_C_VERBATIM=13 +val SCE_C_REGEX=14 +val SCE_C_COMMENTLINEDOC=15 +val SCE_C_WORD2=16 +val SCE_C_COMMENTDOCKEYWORD=17 +val SCE_C_COMMENTDOCKEYWORDERROR=18 +val SCE_C_GLOBALCLASS=19 +val SCE_C_STRINGRAW=20 +val SCE_C_TRIPLEVERBATIM=21 +val SCE_C_HASHQUOTEDSTRING=22 +# Lexical states for SCLEX_D +lex D=SCLEX_D SCE_D_ +val SCE_D_DEFAULT=0 +val SCE_D_COMMENT=1 +val SCE_D_COMMENTLINE=2 +val SCE_D_COMMENTDOC=3 +val SCE_D_COMMENTNESTED=4 +val SCE_D_NUMBER=5 +val SCE_D_WORD=6 +val SCE_D_WORD2=7 +val SCE_D_WORD3=8 +val SCE_D_TYPEDEF=9 +val SCE_D_STRING=10 +val SCE_D_STRINGEOL=11 +val SCE_D_CHARACTER=12 +val SCE_D_OPERATOR=13 +val SCE_D_IDENTIFIER=14 +val SCE_D_COMMENTLINEDOC=15 +val SCE_D_COMMENTDOCKEYWORD=16 +val SCE_D_COMMENTDOCKEYWORDERROR=17 +val SCE_D_STRINGB=18 +val SCE_D_STRINGR=19 +val SCE_D_WORD5=20 +val SCE_D_WORD6=21 +val SCE_D_WORD7=22 +# Lexical states for SCLEX_TCL +lex TCL=SCLEX_TCL SCE_TCL_ +val SCE_TCL_DEFAULT=0 +val SCE_TCL_COMMENT=1 +val SCE_TCL_COMMENTLINE=2 +val SCE_TCL_NUMBER=3 +val SCE_TCL_WORD_IN_QUOTE=4 +val SCE_TCL_IN_QUOTE=5 +val SCE_TCL_OPERATOR=6 +val SCE_TCL_IDENTIFIER=7 +val SCE_TCL_SUBSTITUTION=8 +val SCE_TCL_SUB_BRACE=9 +val SCE_TCL_MODIFIER=10 +val SCE_TCL_EXPAND=11 +val SCE_TCL_WORD=12 +val SCE_TCL_WORD2=13 +val SCE_TCL_WORD3=14 +val SCE_TCL_WORD4=15 +val SCE_TCL_WORD5=16 +val SCE_TCL_WORD6=17 +val SCE_TCL_WORD7=18 +val SCE_TCL_WORD8=19 +val SCE_TCL_COMMENT_BOX=20 +val SCE_TCL_BLOCK_COMMENT=21 +# Lexical states for SCLEX_HTML, SCLEX_XML +lex HTML=SCLEX_HTML SCE_H +lex XML=SCLEX_XML SCE_H +lex ASP=SCLEX_ASP SCE_H +lex PHP=SCLEX_PHP SCE_H +val SCE_H_DEFAULT=0 +val SCE_H_TAG=1 +val SCE_H_TAGUNKNOWN=2 +val SCE_H_ATTRIBUTE=3 +val SCE_H_ATTRIBUTEUNKNOWN=4 +val SCE_H_NUMBER=5 +val SCE_H_DOUBLESTRING=6 +val SCE_H_SINGLESTRING=7 +val SCE_H_OTHER=8 +val SCE_H_COMMENT=9 +val SCE_H_ENTITY=10 +# XML and ASP +val SCE_H_TAGEND=11 +val SCE_H_XMLSTART=12 +val SCE_H_XMLEND=13 +val SCE_H_SCRIPT=14 +val SCE_H_ASP=15 +val SCE_H_ASPAT=16 +val SCE_H_CDATA=17 +val SCE_H_QUESTION=18 +# More HTML +val SCE_H_VALUE=19 +# X-Code +val SCE_H_XCCOMMENT=20 +# SGML +val SCE_H_SGML_DEFAULT=21 +val SCE_H_SGML_COMMAND=22 +val SCE_H_SGML_1ST_PARAM=23 +val SCE_H_SGML_DOUBLESTRING=24 +val SCE_H_SGML_SIMPLESTRING=25 +val SCE_H_SGML_ERROR=26 +val SCE_H_SGML_SPECIAL=27 +val SCE_H_SGML_ENTITY=28 +val SCE_H_SGML_COMMENT=29 +val SCE_H_SGML_1ST_PARAM_COMMENT=30 +val SCE_H_SGML_BLOCK_DEFAULT=31 +# Embedded Javascript +val SCE_HJ_START=40 +val SCE_HJ_DEFAULT=41 +val SCE_HJ_COMMENT=42 +val SCE_HJ_COMMENTLINE=43 +val SCE_HJ_COMMENTDOC=44 +val SCE_HJ_NUMBER=45 +val SCE_HJ_WORD=46 +val SCE_HJ_KEYWORD=47 +val SCE_HJ_DOUBLESTRING=48 +val SCE_HJ_SINGLESTRING=49 +val SCE_HJ_SYMBOLS=50 +val SCE_HJ_STRINGEOL=51 +val SCE_HJ_REGEX=52 +# ASP Javascript +val SCE_HJA_START=55 +val SCE_HJA_DEFAULT=56 +val SCE_HJA_COMMENT=57 +val SCE_HJA_COMMENTLINE=58 +val SCE_HJA_COMMENTDOC=59 +val SCE_HJA_NUMBER=60 +val SCE_HJA_WORD=61 +val SCE_HJA_KEYWORD=62 +val SCE_HJA_DOUBLESTRING=63 +val SCE_HJA_SINGLESTRING=64 +val SCE_HJA_SYMBOLS=65 +val SCE_HJA_STRINGEOL=66 +val SCE_HJA_REGEX=67 +# Embedded VBScript +val SCE_HB_START=70 +val SCE_HB_DEFAULT=71 +val SCE_HB_COMMENTLINE=72 +val SCE_HB_NUMBER=73 +val SCE_HB_WORD=74 +val SCE_HB_STRING=75 +val SCE_HB_IDENTIFIER=76 +val SCE_HB_STRINGEOL=77 +# ASP VBScript +val SCE_HBA_START=80 +val SCE_HBA_DEFAULT=81 +val SCE_HBA_COMMENTLINE=82 +val SCE_HBA_NUMBER=83 +val SCE_HBA_WORD=84 +val SCE_HBA_STRING=85 +val SCE_HBA_IDENTIFIER=86 +val SCE_HBA_STRINGEOL=87 +# Embedded Python +val SCE_HP_START=90 +val SCE_HP_DEFAULT=91 +val SCE_HP_COMMENTLINE=92 +val SCE_HP_NUMBER=93 +val SCE_HP_STRING=94 +val SCE_HP_CHARACTER=95 +val SCE_HP_WORD=96 +val SCE_HP_TRIPLE=97 +val SCE_HP_TRIPLEDOUBLE=98 +val SCE_HP_CLASSNAME=99 +val SCE_HP_DEFNAME=100 +val SCE_HP_OPERATOR=101 +val SCE_HP_IDENTIFIER=102 +# PHP +val SCE_HPHP_COMPLEX_VARIABLE=104 +# ASP Python +val SCE_HPA_START=105 +val SCE_HPA_DEFAULT=106 +val SCE_HPA_COMMENTLINE=107 +val SCE_HPA_NUMBER=108 +val SCE_HPA_STRING=109 +val SCE_HPA_CHARACTER=110 +val SCE_HPA_WORD=111 +val SCE_HPA_TRIPLE=112 +val SCE_HPA_TRIPLEDOUBLE=113 +val SCE_HPA_CLASSNAME=114 +val SCE_HPA_DEFNAME=115 +val SCE_HPA_OPERATOR=116 +val SCE_HPA_IDENTIFIER=117 +# PHP +val SCE_HPHP_DEFAULT=118 +val SCE_HPHP_HSTRING=119 +val SCE_HPHP_SIMPLESTRING=120 +val SCE_HPHP_WORD=121 +val SCE_HPHP_NUMBER=122 +val SCE_HPHP_VARIABLE=123 +val SCE_HPHP_COMMENT=124 +val SCE_HPHP_COMMENTLINE=125 +val SCE_HPHP_HSTRING_VARIABLE=126 +val SCE_HPHP_OPERATOR=127 +# Lexical states for SCLEX_PERL +lex Perl=SCLEX_PERL SCE_PL_ +val SCE_PL_DEFAULT=0 +val SCE_PL_ERROR=1 +val SCE_PL_COMMENTLINE=2 +val SCE_PL_POD=3 +val SCE_PL_NUMBER=4 +val SCE_PL_WORD=5 +val SCE_PL_STRING=6 +val SCE_PL_CHARACTER=7 +val SCE_PL_PUNCTUATION=8 +val SCE_PL_PREPROCESSOR=9 +val SCE_PL_OPERATOR=10 +val SCE_PL_IDENTIFIER=11 +val SCE_PL_SCALAR=12 +val SCE_PL_ARRAY=13 +val SCE_PL_HASH=14 +val SCE_PL_SYMBOLTABLE=15 +val SCE_PL_VARIABLE_INDEXER=16 +val SCE_PL_REGEX=17 +val SCE_PL_REGSUBST=18 +val SCE_PL_LONGQUOTE=19 +val SCE_PL_BACKTICKS=20 +val SCE_PL_DATASECTION=21 +val SCE_PL_HERE_DELIM=22 +val SCE_PL_HERE_Q=23 +val SCE_PL_HERE_QQ=24 +val SCE_PL_HERE_QX=25 +val SCE_PL_STRING_Q=26 +val SCE_PL_STRING_QQ=27 +val SCE_PL_STRING_QX=28 +val SCE_PL_STRING_QR=29 +val SCE_PL_STRING_QW=30 +val SCE_PL_POD_VERB=31 +val SCE_PL_SUB_PROTOTYPE=40 +val SCE_PL_FORMAT_IDENT=41 +val SCE_PL_FORMAT=42 +val SCE_PL_STRING_VAR=43 +val SCE_PL_XLAT=44 +val SCE_PL_REGEX_VAR=54 +val SCE_PL_REGSUBST_VAR=55 +val SCE_PL_BACKTICKS_VAR=57 +val SCE_PL_HERE_QQ_VAR=61 +val SCE_PL_HERE_QX_VAR=62 +val SCE_PL_STRING_QQ_VAR=64 +val SCE_PL_STRING_QX_VAR=65 +val SCE_PL_STRING_QR_VAR=66 +# Lexical states for SCLEX_RUBY +lex Ruby=SCLEX_RUBY SCE_RB_ +val SCE_RB_DEFAULT=0 +val SCE_RB_ERROR=1 +val SCE_RB_COMMENTLINE=2 +val SCE_RB_POD=3 +val SCE_RB_NUMBER=4 +val SCE_RB_WORD=5 +val SCE_RB_STRING=6 +val SCE_RB_CHARACTER=7 +val SCE_RB_CLASSNAME=8 +val SCE_RB_DEFNAME=9 +val SCE_RB_OPERATOR=10 +val SCE_RB_IDENTIFIER=11 +val SCE_RB_REGEX=12 +val SCE_RB_GLOBAL=13 +val SCE_RB_SYMBOL=14 +val SCE_RB_MODULE_NAME=15 +val SCE_RB_INSTANCE_VAR=16 +val SCE_RB_CLASS_VAR=17 +val SCE_RB_BACKTICKS=18 +val SCE_RB_DATASECTION=19 +val SCE_RB_HERE_DELIM=20 +val SCE_RB_HERE_Q=21 +val SCE_RB_HERE_QQ=22 +val SCE_RB_HERE_QX=23 +val SCE_RB_STRING_Q=24 +val SCE_RB_STRING_QQ=25 +val SCE_RB_STRING_QX=26 +val SCE_RB_STRING_QR=27 +val SCE_RB_STRING_QW=28 +val SCE_RB_WORD_DEMOTED=29 +val SCE_RB_STDIN=30 +val SCE_RB_STDOUT=31 +val SCE_RB_STDERR=40 +val SCE_RB_UPPER_BOUND=41 +# Lexical states for SCLEX_VB, SCLEX_VBSCRIPT, SCLEX_POWERBASIC +lex VB=SCLEX_VB SCE_B_ +lex VBScript=SCLEX_VBSCRIPT SCE_B_ +lex PowerBasic=SCLEX_POWERBASIC SCE_B_ +val SCE_B_DEFAULT=0 +val SCE_B_COMMENT=1 +val SCE_B_NUMBER=2 +val SCE_B_KEYWORD=3 +val SCE_B_STRING=4 +val SCE_B_PREPROCESSOR=5 +val SCE_B_OPERATOR=6 +val SCE_B_IDENTIFIER=7 +val SCE_B_DATE=8 +val SCE_B_STRINGEOL=9 +val SCE_B_KEYWORD2=10 +val SCE_B_KEYWORD3=11 +val SCE_B_KEYWORD4=12 +val SCE_B_CONSTANT=13 +val SCE_B_ASM=14 +val SCE_B_LABEL=15 +val SCE_B_ERROR=16 +val SCE_B_HEXNUMBER=17 +val SCE_B_BINNUMBER=18 +# Lexical states for SCLEX_PROPERTIES +lex Properties=SCLEX_PROPERTIES SCE_PROPS_ +val SCE_PROPS_DEFAULT=0 +val SCE_PROPS_COMMENT=1 +val SCE_PROPS_SECTION=2 +val SCE_PROPS_ASSIGNMENT=3 +val SCE_PROPS_DEFVAL=4 +val SCE_PROPS_KEY=5 +# Lexical states for SCLEX_LATEX +lex LaTeX=SCLEX_LATEX SCE_L_ +val SCE_L_DEFAULT=0 +val SCE_L_COMMAND=1 +val SCE_L_TAG=2 +val SCE_L_MATH=3 +val SCE_L_COMMENT=4 +val SCE_L_TAG2=5 +val SCE_L_MATH2=6 +val SCE_L_COMMENT2=7 +val SCE_L_VERBATIM=8 +val SCE_L_SHORTCMD=9 +val SCE_L_SPECIAL=10 +val SCE_L_CMDOPT=11 +val SCE_L_ERROR=12 +# Lexical states for SCLEX_LUA +lex Lua=SCLEX_LUA SCE_LUA_ +val SCE_LUA_DEFAULT=0 +val SCE_LUA_COMMENT=1 +val SCE_LUA_COMMENTLINE=2 +val SCE_LUA_COMMENTDOC=3 +val SCE_LUA_NUMBER=4 +val SCE_LUA_WORD=5 +val SCE_LUA_STRING=6 +val SCE_LUA_CHARACTER=7 +val SCE_LUA_LITERALSTRING=8 +val SCE_LUA_PREPROCESSOR=9 +val SCE_LUA_OPERATOR=10 +val SCE_LUA_IDENTIFIER=11 +val SCE_LUA_STRINGEOL=12 +val SCE_LUA_WORD2=13 +val SCE_LUA_WORD3=14 +val SCE_LUA_WORD4=15 +val SCE_LUA_WORD5=16 +val SCE_LUA_WORD6=17 +val SCE_LUA_WORD7=18 +val SCE_LUA_WORD8=19 +val SCE_LUA_LABEL=20 +# Lexical states for SCLEX_ERRORLIST +lex ErrorList=SCLEX_ERRORLIST SCE_ERR_ +val SCE_ERR_DEFAULT=0 +val SCE_ERR_PYTHON=1 +val SCE_ERR_GCC=2 +val SCE_ERR_MS=3 +val SCE_ERR_CMD=4 +val SCE_ERR_BORLAND=5 +val SCE_ERR_PERL=6 +val SCE_ERR_NET=7 +val SCE_ERR_LUA=8 +val SCE_ERR_CTAG=9 +val SCE_ERR_DIFF_CHANGED=10 +val SCE_ERR_DIFF_ADDITION=11 +val SCE_ERR_DIFF_DELETION=12 +val SCE_ERR_DIFF_MESSAGE=13 +val SCE_ERR_PHP=14 +val SCE_ERR_ELF=15 +val SCE_ERR_IFC=16 +val SCE_ERR_IFORT=17 +val SCE_ERR_ABSF=18 +val SCE_ERR_TIDY=19 +val SCE_ERR_JAVA_STACK=20 +val SCE_ERR_VALUE=21 +# Lexical states for SCLEX_BATCH +lex Batch=SCLEX_BATCH SCE_BAT_ +val SCE_BAT_DEFAULT=0 +val SCE_BAT_COMMENT=1 +val SCE_BAT_WORD=2 +val SCE_BAT_LABEL=3 +val SCE_BAT_HIDE=4 +val SCE_BAT_COMMAND=5 +val SCE_BAT_IDENTIFIER=6 +val SCE_BAT_OPERATOR=7 +# Lexical states for SCLEX_TCMD +lex TCMD=SCLEX_TCMD SCE_TCMD_ +val SCE_TCMD_DEFAULT=0 +val SCE_TCMD_COMMENT=1 +val SCE_TCMD_WORD=2 +val SCE_TCMD_LABEL=3 +val SCE_TCMD_HIDE=4 +val SCE_TCMD_COMMAND=5 +val SCE_TCMD_IDENTIFIER=6 +val SCE_TCMD_OPERATOR=7 +val SCE_TCMD_ENVIRONMENT=8 +val SCE_TCMD_EXPANSION=9 +val SCE_TCMD_CLABEL=10 +# Lexical states for SCLEX_MAKEFILE +lex MakeFile=SCLEX_MAKEFILE SCE_MAKE_ +val SCE_MAKE_DEFAULT=0 +val SCE_MAKE_COMMENT=1 +val SCE_MAKE_PREPROCESSOR=2 +val SCE_MAKE_IDENTIFIER=3 +val SCE_MAKE_OPERATOR=4 +val SCE_MAKE_TARGET=5 +val SCE_MAKE_IDEOL=9 +# Lexical states for SCLEX_DIFF +lex Diff=SCLEX_DIFF SCE_DIFF_ +val SCE_DIFF_DEFAULT=0 +val SCE_DIFF_COMMENT=1 +val SCE_DIFF_COMMAND=2 +val SCE_DIFF_HEADER=3 +val SCE_DIFF_POSITION=4 +val SCE_DIFF_DELETED=5 +val SCE_DIFF_ADDED=6 +val SCE_DIFF_CHANGED=7 +# Lexical states for SCLEX_CONF (Apache Configuration Files Lexer) +lex Conf=SCLEX_CONF SCE_CONF_ +val SCE_CONF_DEFAULT=0 +val SCE_CONF_COMMENT=1 +val SCE_CONF_NUMBER=2 +val SCE_CONF_IDENTIFIER=3 +val SCE_CONF_EXTENSION=4 +val SCE_CONF_PARAMETER=5 +val SCE_CONF_STRING=6 +val SCE_CONF_OPERATOR=7 +val SCE_CONF_IP=8 +val SCE_CONF_DIRECTIVE=9 +# Lexical states for SCLEX_AVE, Avenue +lex Avenue=SCLEX_AVE SCE_AVE_ +val SCE_AVE_DEFAULT=0 +val SCE_AVE_COMMENT=1 +val SCE_AVE_NUMBER=2 +val SCE_AVE_WORD=3 +val SCE_AVE_STRING=6 +val SCE_AVE_ENUM=7 +val SCE_AVE_STRINGEOL=8 +val SCE_AVE_IDENTIFIER=9 +val SCE_AVE_OPERATOR=10 +val SCE_AVE_WORD1=11 +val SCE_AVE_WORD2=12 +val SCE_AVE_WORD3=13 +val SCE_AVE_WORD4=14 +val SCE_AVE_WORD5=15 +val SCE_AVE_WORD6=16 +# Lexical states for SCLEX_ADA +lex Ada=SCLEX_ADA SCE_ADA_ +val SCE_ADA_DEFAULT=0 +val SCE_ADA_WORD=1 +val SCE_ADA_IDENTIFIER=2 +val SCE_ADA_NUMBER=3 +val SCE_ADA_DELIMITER=4 +val SCE_ADA_CHARACTER=5 +val SCE_ADA_CHARACTEREOL=6 +val SCE_ADA_STRING=7 +val SCE_ADA_STRINGEOL=8 +val SCE_ADA_LABEL=9 +val SCE_ADA_COMMENTLINE=10 +val SCE_ADA_ILLEGAL=11 +# Lexical states for SCLEX_BAAN +lex Baan=SCLEX_BAAN SCE_BAAN_ +val SCE_BAAN_DEFAULT=0 +val SCE_BAAN_COMMENT=1 +val SCE_BAAN_COMMENTDOC=2 +val SCE_BAAN_NUMBER=3 +val SCE_BAAN_WORD=4 +val SCE_BAAN_STRING=5 +val SCE_BAAN_PREPROCESSOR=6 +val SCE_BAAN_OPERATOR=7 +val SCE_BAAN_IDENTIFIER=8 +val SCE_BAAN_STRINGEOL=9 +val SCE_BAAN_WORD2=10 +# Lexical states for SCLEX_LISP +lex Lisp=SCLEX_LISP SCE_LISP_ +val SCE_LISP_DEFAULT=0 +val SCE_LISP_COMMENT=1 +val SCE_LISP_NUMBER=2 +val SCE_LISP_KEYWORD=3 +val SCE_LISP_KEYWORD_KW=4 +val SCE_LISP_SYMBOL=5 +val SCE_LISP_STRING=6 +val SCE_LISP_STRINGEOL=8 +val SCE_LISP_IDENTIFIER=9 +val SCE_LISP_OPERATOR=10 +val SCE_LISP_SPECIAL=11 +val SCE_LISP_MULTI_COMMENT=12 +# Lexical states for SCLEX_EIFFEL and SCLEX_EIFFELKW +lex Eiffel=SCLEX_EIFFEL SCE_EIFFEL_ +lex EiffelKW=SCLEX_EIFFELKW SCE_EIFFEL_ +val SCE_EIFFEL_DEFAULT=0 +val SCE_EIFFEL_COMMENTLINE=1 +val SCE_EIFFEL_NUMBER=2 +val SCE_EIFFEL_WORD=3 +val SCE_EIFFEL_STRING=4 +val SCE_EIFFEL_CHARACTER=5 +val SCE_EIFFEL_OPERATOR=6 +val SCE_EIFFEL_IDENTIFIER=7 +val SCE_EIFFEL_STRINGEOL=8 +# Lexical states for SCLEX_NNCRONTAB (nnCron crontab Lexer) +lex NNCronTab=SCLEX_NNCRONTAB SCE_NNCRONTAB_ +val SCE_NNCRONTAB_DEFAULT=0 +val SCE_NNCRONTAB_COMMENT=1 +val SCE_NNCRONTAB_TASK=2 +val SCE_NNCRONTAB_SECTION=3 +val SCE_NNCRONTAB_KEYWORD=4 +val SCE_NNCRONTAB_MODIFIER=5 +val SCE_NNCRONTAB_ASTERISK=6 +val SCE_NNCRONTAB_NUMBER=7 +val SCE_NNCRONTAB_STRING=8 +val SCE_NNCRONTAB_ENVIRONMENT=9 +val SCE_NNCRONTAB_IDENTIFIER=10 +# Lexical states for SCLEX_FORTH (Forth Lexer) +lex Forth=SCLEX_FORTH SCE_FORTH_ +val SCE_FORTH_DEFAULT=0 +val SCE_FORTH_COMMENT=1 +val SCE_FORTH_COMMENT_ML=2 +val SCE_FORTH_IDENTIFIER=3 +val SCE_FORTH_CONTROL=4 +val SCE_FORTH_KEYWORD=5 +val SCE_FORTH_DEFWORD=6 +val SCE_FORTH_PREWORD1=7 +val SCE_FORTH_PREWORD2=8 +val SCE_FORTH_NUMBER=9 +val SCE_FORTH_STRING=10 +val SCE_FORTH_LOCALE=11 +# Lexical states for SCLEX_MATLAB +lex MatLab=SCLEX_MATLAB SCE_MATLAB_ +val SCE_MATLAB_DEFAULT=0 +val SCE_MATLAB_COMMENT=1 +val SCE_MATLAB_COMMAND=2 +val SCE_MATLAB_NUMBER=3 +val SCE_MATLAB_KEYWORD=4 +# single quoted string +val SCE_MATLAB_STRING=5 +val SCE_MATLAB_OPERATOR=6 +val SCE_MATLAB_IDENTIFIER=7 +val SCE_MATLAB_DOUBLEQUOTESTRING=8 +# Lexical states for SCLEX_SCRIPTOL +lex Sol=SCLEX_SCRIPTOL SCE_SCRIPTOL_ +val SCE_SCRIPTOL_DEFAULT=0 +val SCE_SCRIPTOL_WHITE=1 +val SCE_SCRIPTOL_COMMENTLINE=2 +val SCE_SCRIPTOL_PERSISTENT=3 +val SCE_SCRIPTOL_CSTYLE=4 +val SCE_SCRIPTOL_COMMENTBLOCK=5 +val SCE_SCRIPTOL_NUMBER=6 +val SCE_SCRIPTOL_STRING=7 +val SCE_SCRIPTOL_CHARACTER=8 +val SCE_SCRIPTOL_STRINGEOL=9 +val SCE_SCRIPTOL_KEYWORD=10 +val SCE_SCRIPTOL_OPERATOR=11 +val SCE_SCRIPTOL_IDENTIFIER=12 +val SCE_SCRIPTOL_TRIPLE=13 +val SCE_SCRIPTOL_CLASSNAME=14 +val SCE_SCRIPTOL_PREPROCESSOR=15 +# Lexical states for SCLEX_ASM +lex Asm=SCLEX_ASM SCE_ASM_ +val SCE_ASM_DEFAULT=0 +val SCE_ASM_COMMENT=1 +val SCE_ASM_NUMBER=2 +val SCE_ASM_STRING=3 +val SCE_ASM_OPERATOR=4 +val SCE_ASM_IDENTIFIER=5 +val SCE_ASM_CPUINSTRUCTION=6 +val SCE_ASM_MATHINSTRUCTION=7 +val SCE_ASM_REGISTER=8 +val SCE_ASM_DIRECTIVE=9 +val SCE_ASM_DIRECTIVEOPERAND=10 +val SCE_ASM_COMMENTBLOCK=11 +val SCE_ASM_CHARACTER=12 +val SCE_ASM_STRINGEOL=13 +val SCE_ASM_EXTINSTRUCTION=14 +val SCE_ASM_COMMENTDIRECTIVE=15 +# Lexical states for SCLEX_FORTRAN +lex Fortran=SCLEX_FORTRAN SCE_F_ +lex F77=SCLEX_F77 SCE_F_ +val SCE_F_DEFAULT=0 +val SCE_F_COMMENT=1 +val SCE_F_NUMBER=2 +val SCE_F_STRING1=3 +val SCE_F_STRING2=4 +val SCE_F_STRINGEOL=5 +val SCE_F_OPERATOR=6 +val SCE_F_IDENTIFIER=7 +val SCE_F_WORD=8 +val SCE_F_WORD2=9 +val SCE_F_WORD3=10 +val SCE_F_PREPROCESSOR=11 +val SCE_F_OPERATOR2=12 +val SCE_F_LABEL=13 +val SCE_F_CONTINUATION=14 +# Lexical states for SCLEX_CSS +lex CSS=SCLEX_CSS SCE_CSS_ +val SCE_CSS_DEFAULT=0 +val SCE_CSS_TAG=1 +val SCE_CSS_CLASS=2 +val SCE_CSS_PSEUDOCLASS=3 +val SCE_CSS_UNKNOWN_PSEUDOCLASS=4 +val SCE_CSS_OPERATOR=5 +val SCE_CSS_IDENTIFIER=6 +val SCE_CSS_UNKNOWN_IDENTIFIER=7 +val SCE_CSS_VALUE=8 +val SCE_CSS_COMMENT=9 +val SCE_CSS_ID=10 +val SCE_CSS_IMPORTANT=11 +val SCE_CSS_DIRECTIVE=12 +val SCE_CSS_DOUBLESTRING=13 +val SCE_CSS_SINGLESTRING=14 +val SCE_CSS_IDENTIFIER2=15 +val SCE_CSS_ATTRIBUTE=16 +val SCE_CSS_IDENTIFIER3=17 +val SCE_CSS_PSEUDOELEMENT=18 +val SCE_CSS_EXTENDED_IDENTIFIER=19 +val SCE_CSS_EXTENDED_PSEUDOCLASS=20 +val SCE_CSS_EXTENDED_PSEUDOELEMENT=21 +val SCE_CSS_MEDIA=22 +val SCE_CSS_VARIABLE=23 +# Lexical states for SCLEX_POV +lex POV=SCLEX_POV SCE_POV_ +val SCE_POV_DEFAULT=0 +val SCE_POV_COMMENT=1 +val SCE_POV_COMMENTLINE=2 +val SCE_POV_NUMBER=3 +val SCE_POV_OPERATOR=4 +val SCE_POV_IDENTIFIER=5 +val SCE_POV_STRING=6 +val SCE_POV_STRINGEOL=7 +val SCE_POV_DIRECTIVE=8 +val SCE_POV_BADDIRECTIVE=9 +val SCE_POV_WORD2=10 +val SCE_POV_WORD3=11 +val SCE_POV_WORD4=12 +val SCE_POV_WORD5=13 +val SCE_POV_WORD6=14 +val SCE_POV_WORD7=15 +val SCE_POV_WORD8=16 +# Lexical states for SCLEX_LOUT +lex LOUT=SCLEX_LOUT SCE_LOUT_ +val SCE_LOUT_DEFAULT=0 +val SCE_LOUT_COMMENT=1 +val SCE_LOUT_NUMBER=2 +val SCE_LOUT_WORD=3 +val SCE_LOUT_WORD2=4 +val SCE_LOUT_WORD3=5 +val SCE_LOUT_WORD4=6 +val SCE_LOUT_STRING=7 +val SCE_LOUT_OPERATOR=8 +val SCE_LOUT_IDENTIFIER=9 +val SCE_LOUT_STRINGEOL=10 +# Lexical states for SCLEX_ESCRIPT +lex ESCRIPT=SCLEX_ESCRIPT SCE_ESCRIPT_ +val SCE_ESCRIPT_DEFAULT=0 +val SCE_ESCRIPT_COMMENT=1 +val SCE_ESCRIPT_COMMENTLINE=2 +val SCE_ESCRIPT_COMMENTDOC=3 +val SCE_ESCRIPT_NUMBER=4 +val SCE_ESCRIPT_WORD=5 +val SCE_ESCRIPT_STRING=6 +val SCE_ESCRIPT_OPERATOR=7 +val SCE_ESCRIPT_IDENTIFIER=8 +val SCE_ESCRIPT_BRACE=9 +val SCE_ESCRIPT_WORD2=10 +val SCE_ESCRIPT_WORD3=11 +# Lexical states for SCLEX_PS +lex PS=SCLEX_PS SCE_PS_ +val SCE_PS_DEFAULT=0 +val SCE_PS_COMMENT=1 +val SCE_PS_DSC_COMMENT=2 +val SCE_PS_DSC_VALUE=3 +val SCE_PS_NUMBER=4 +val SCE_PS_NAME=5 +val SCE_PS_KEYWORD=6 +val SCE_PS_LITERAL=7 +val SCE_PS_IMMEVAL=8 +val SCE_PS_PAREN_ARRAY=9 +val SCE_PS_PAREN_DICT=10 +val SCE_PS_PAREN_PROC=11 +val SCE_PS_TEXT=12 +val SCE_PS_HEXSTRING=13 +val SCE_PS_BASE85STRING=14 +val SCE_PS_BADSTRINGCHAR=15 +# Lexical states for SCLEX_NSIS +lex NSIS=SCLEX_NSIS SCE_NSIS_ +val SCE_NSIS_DEFAULT=0 +val SCE_NSIS_COMMENT=1 +val SCE_NSIS_STRINGDQ=2 +val SCE_NSIS_STRINGLQ=3 +val SCE_NSIS_STRINGRQ=4 +val SCE_NSIS_FUNCTION=5 +val SCE_NSIS_VARIABLE=6 +val SCE_NSIS_LABEL=7 +val SCE_NSIS_USERDEFINED=8 +val SCE_NSIS_SECTIONDEF=9 +val SCE_NSIS_SUBSECTIONDEF=10 +val SCE_NSIS_IFDEFINEDEF=11 +val SCE_NSIS_MACRODEF=12 +val SCE_NSIS_STRINGVAR=13 +val SCE_NSIS_NUMBER=14 +val SCE_NSIS_SECTIONGROUP=15 +val SCE_NSIS_PAGEEX=16 +val SCE_NSIS_FUNCTIONDEF=17 +val SCE_NSIS_COMMENTBOX=18 +# Lexical states for SCLEX_MMIXAL +lex MMIXAL=SCLEX_MMIXAL SCE_MMIXAL_ +val SCE_MMIXAL_LEADWS=0 +val SCE_MMIXAL_COMMENT=1 +val SCE_MMIXAL_LABEL=2 +val SCE_MMIXAL_OPCODE=3 +val SCE_MMIXAL_OPCODE_PRE=4 +val SCE_MMIXAL_OPCODE_VALID=5 +val SCE_MMIXAL_OPCODE_UNKNOWN=6 +val SCE_MMIXAL_OPCODE_POST=7 +val SCE_MMIXAL_OPERANDS=8 +val SCE_MMIXAL_NUMBER=9 +val SCE_MMIXAL_REF=10 +val SCE_MMIXAL_CHAR=11 +val SCE_MMIXAL_STRING=12 +val SCE_MMIXAL_REGISTER=13 +val SCE_MMIXAL_HEX=14 +val SCE_MMIXAL_OPERATOR=15 +val SCE_MMIXAL_SYMBOL=16 +val SCE_MMIXAL_INCLUDE=17 +# Lexical states for SCLEX_CLW +lex Clarion=SCLEX_CLW SCE_CLW_ +val SCE_CLW_DEFAULT=0 +val SCE_CLW_LABEL=1 +val SCE_CLW_COMMENT=2 +val SCE_CLW_STRING=3 +val SCE_CLW_USER_IDENTIFIER=4 +val SCE_CLW_INTEGER_CONSTANT=5 +val SCE_CLW_REAL_CONSTANT=6 +val SCE_CLW_PICTURE_STRING=7 +val SCE_CLW_KEYWORD=8 +val SCE_CLW_COMPILER_DIRECTIVE=9 +val SCE_CLW_RUNTIME_EXPRESSIONS=10 +val SCE_CLW_BUILTIN_PROCEDURES_FUNCTION=11 +val SCE_CLW_STRUCTURE_DATA_TYPE=12 +val SCE_CLW_ATTRIBUTE=13 +val SCE_CLW_STANDARD_EQUATE=14 +val SCE_CLW_ERROR=15 +val SCE_CLW_DEPRECATED=16 +# Lexical states for SCLEX_LOT +lex LOT=SCLEX_LOT SCE_LOT_ +val SCE_LOT_DEFAULT=0 +val SCE_LOT_HEADER=1 +val SCE_LOT_BREAK=2 +val SCE_LOT_SET=3 +val SCE_LOT_PASS=4 +val SCE_LOT_FAIL=5 +val SCE_LOT_ABORT=6 +# Lexical states for SCLEX_YAML +lex YAML=SCLEX_YAML SCE_YAML_ +val SCE_YAML_DEFAULT=0 +val SCE_YAML_COMMENT=1 +val SCE_YAML_IDENTIFIER=2 +val SCE_YAML_KEYWORD=3 +val SCE_YAML_NUMBER=4 +val SCE_YAML_REFERENCE=5 +val SCE_YAML_DOCUMENT=6 +val SCE_YAML_TEXT=7 +val SCE_YAML_ERROR=8 +val SCE_YAML_OPERATOR=9 +# Lexical states for SCLEX_TEX +lex TeX=SCLEX_TEX SCE_TEX_ +val SCE_TEX_DEFAULT=0 +val SCE_TEX_SPECIAL=1 +val SCE_TEX_GROUP=2 +val SCE_TEX_SYMBOL=3 +val SCE_TEX_COMMAND=4 +val SCE_TEX_TEXT=5 +lex Metapost=SCLEX_METAPOST SCE_METAPOST_ +val SCE_METAPOST_DEFAULT=0 +val SCE_METAPOST_SPECIAL=1 +val SCE_METAPOST_GROUP=2 +val SCE_METAPOST_SYMBOL=3 +val SCE_METAPOST_COMMAND=4 +val SCE_METAPOST_TEXT=5 +val SCE_METAPOST_EXTRA=6 +# Lexical states for SCLEX_ERLANG +lex Erlang=SCLEX_ERLANG SCE_ERLANG_ +val SCE_ERLANG_DEFAULT=0 +val SCE_ERLANG_COMMENT=1 +val SCE_ERLANG_VARIABLE=2 +val SCE_ERLANG_NUMBER=3 +val SCE_ERLANG_KEYWORD=4 +val SCE_ERLANG_STRING=5 +val SCE_ERLANG_OPERATOR=6 +val SCE_ERLANG_ATOM=7 +val SCE_ERLANG_FUNCTION_NAME=8 +val SCE_ERLANG_CHARACTER=9 +val SCE_ERLANG_MACRO=10 +val SCE_ERLANG_RECORD=11 +val SCE_ERLANG_PREPROC=12 +val SCE_ERLANG_NODE_NAME=13 +val SCE_ERLANG_COMMENT_FUNCTION=14 +val SCE_ERLANG_COMMENT_MODULE=15 +val SCE_ERLANG_COMMENT_DOC=16 +val SCE_ERLANG_COMMENT_DOC_MACRO=17 +val SCE_ERLANG_ATOM_QUOTED=18 +val SCE_ERLANG_MACRO_QUOTED=19 +val SCE_ERLANG_RECORD_QUOTED=20 +val SCE_ERLANG_NODE_NAME_QUOTED=21 +val SCE_ERLANG_BIFS=22 +val SCE_ERLANG_MODULES=23 +val SCE_ERLANG_MODULES_ATT=24 +val SCE_ERLANG_UNKNOWN=31 +# Lexical states for SCLEX_OCTAVE are identical to MatLab +lex Octave=SCLEX_OCTAVE SCE_MATLAB_ +# Lexical states for SCLEX_MSSQL +lex MSSQL=SCLEX_MSSQL SCE_MSSQL_ +val SCE_MSSQL_DEFAULT=0 +val SCE_MSSQL_COMMENT=1 +val SCE_MSSQL_LINE_COMMENT=2 +val SCE_MSSQL_NUMBER=3 +val SCE_MSSQL_STRING=4 +val SCE_MSSQL_OPERATOR=5 +val SCE_MSSQL_IDENTIFIER=6 +val SCE_MSSQL_VARIABLE=7 +val SCE_MSSQL_COLUMN_NAME=8 +val SCE_MSSQL_STATEMENT=9 +val SCE_MSSQL_DATATYPE=10 +val SCE_MSSQL_SYSTABLE=11 +val SCE_MSSQL_GLOBAL_VARIABLE=12 +val SCE_MSSQL_FUNCTION=13 +val SCE_MSSQL_STORED_PROCEDURE=14 +val SCE_MSSQL_DEFAULT_PREF_DATATYPE=15 +val SCE_MSSQL_COLUMN_NAME_2=16 +# Lexical states for SCLEX_VERILOG +lex Verilog=SCLEX_VERILOG SCE_V_ +val SCE_V_DEFAULT=0 +val SCE_V_COMMENT=1 +val SCE_V_COMMENTLINE=2 +val SCE_V_COMMENTLINEBANG=3 +val SCE_V_NUMBER=4 +val SCE_V_WORD=5 +val SCE_V_STRING=6 +val SCE_V_WORD2=7 +val SCE_V_WORD3=8 +val SCE_V_PREPROCESSOR=9 +val SCE_V_OPERATOR=10 +val SCE_V_IDENTIFIER=11 +val SCE_V_STRINGEOL=12 +val SCE_V_USER=19 +# Lexical states for SCLEX_KIX +lex Kix=SCLEX_KIX SCE_KIX_ +val SCE_KIX_DEFAULT=0 +val SCE_KIX_COMMENT=1 +val SCE_KIX_STRING1=2 +val SCE_KIX_STRING2=3 +val SCE_KIX_NUMBER=4 +val SCE_KIX_VAR=5 +val SCE_KIX_MACRO=6 +val SCE_KIX_KEYWORD=7 +val SCE_KIX_FUNCTIONS=8 +val SCE_KIX_OPERATOR=9 +val SCE_KIX_IDENTIFIER=31 +# Lexical states for SCLEX_GUI4CLI +val SCE_GC_DEFAULT=0 +val SCE_GC_COMMENTLINE=1 +val SCE_GC_COMMENTBLOCK=2 +val SCE_GC_GLOBAL=3 +val SCE_GC_EVENT=4 +val SCE_GC_ATTRIBUTE=5 +val SCE_GC_CONTROL=6 +val SCE_GC_COMMAND=7 +val SCE_GC_STRING=8 +val SCE_GC_OPERATOR=9 +# Lexical states for SCLEX_SPECMAN +lex Specman=SCLEX_SPECMAN SCE_SN_ +val SCE_SN_DEFAULT=0 +val SCE_SN_CODE=1 +val SCE_SN_COMMENTLINE=2 +val SCE_SN_COMMENTLINEBANG=3 +val SCE_SN_NUMBER=4 +val SCE_SN_WORD=5 +val SCE_SN_STRING=6 +val SCE_SN_WORD2=7 +val SCE_SN_WORD3=8 +val SCE_SN_PREPROCESSOR=9 +val SCE_SN_OPERATOR=10 +val SCE_SN_IDENTIFIER=11 +val SCE_SN_STRINGEOL=12 +val SCE_SN_REGEXTAG=13 +val SCE_SN_SIGNAL=14 +val SCE_SN_USER=19 +# Lexical states for SCLEX_AU3 +lex Au3=SCLEX_AU3 SCE_AU3_ +val SCE_AU3_DEFAULT=0 +val SCE_AU3_COMMENT=1 +val SCE_AU3_COMMENTBLOCK=2 +val SCE_AU3_NUMBER=3 +val SCE_AU3_FUNCTION=4 +val SCE_AU3_KEYWORD=5 +val SCE_AU3_MACRO=6 +val SCE_AU3_STRING=7 +val SCE_AU3_OPERATOR=8 +val SCE_AU3_VARIABLE=9 +val SCE_AU3_SENT=10 +val SCE_AU3_PREPROCESSOR=11 +val SCE_AU3_SPECIAL=12 +val SCE_AU3_EXPAND=13 +val SCE_AU3_COMOBJ=14 +val SCE_AU3_UDF=15 +# Lexical states for SCLEX_APDL +lex APDL=SCLEX_APDL SCE_APDL_ +val SCE_APDL_DEFAULT=0 +val SCE_APDL_COMMENT=1 +val SCE_APDL_COMMENTBLOCK=2 +val SCE_APDL_NUMBER=3 +val SCE_APDL_STRING=4 +val SCE_APDL_OPERATOR=5 +val SCE_APDL_WORD=6 +val SCE_APDL_PROCESSOR=7 +val SCE_APDL_COMMAND=8 +val SCE_APDL_SLASHCOMMAND=9 +val SCE_APDL_STARCOMMAND=10 +val SCE_APDL_ARGUMENT=11 +val SCE_APDL_FUNCTION=12 +# Lexical states for SCLEX_BASH +lex Bash=SCLEX_BASH SCE_SH_ +val SCE_SH_DEFAULT=0 +val SCE_SH_ERROR=1 +val SCE_SH_COMMENTLINE=2 +val SCE_SH_NUMBER=3 +val SCE_SH_WORD=4 +val SCE_SH_STRING=5 +val SCE_SH_CHARACTER=6 +val SCE_SH_OPERATOR=7 +val SCE_SH_IDENTIFIER=8 +val SCE_SH_SCALAR=9 +val SCE_SH_PARAM=10 +val SCE_SH_BACKTICKS=11 +val SCE_SH_HERE_DELIM=12 +val SCE_SH_HERE_Q=13 +# Lexical states for SCLEX_ASN1 +lex Asn1=SCLEX_ASN1 SCE_ASN1_ +val SCE_ASN1_DEFAULT=0 +val SCE_ASN1_COMMENT=1 +val SCE_ASN1_IDENTIFIER=2 +val SCE_ASN1_STRING=3 +val SCE_ASN1_OID=4 +val SCE_ASN1_SCALAR=5 +val SCE_ASN1_KEYWORD=6 +val SCE_ASN1_ATTRIBUTE=7 +val SCE_ASN1_DESCRIPTOR=8 +val SCE_ASN1_TYPE=9 +val SCE_ASN1_OPERATOR=10 +# Lexical states for SCLEX_VHDL +lex VHDL=SCLEX_VHDL SCE_VHDL_ +val SCE_VHDL_DEFAULT=0 +val SCE_VHDL_COMMENT=1 +val SCE_VHDL_COMMENTLINEBANG=2 +val SCE_VHDL_NUMBER=3 +val SCE_VHDL_STRING=4 +val SCE_VHDL_OPERATOR=5 +val SCE_VHDL_IDENTIFIER=6 +val SCE_VHDL_STRINGEOL=7 +val SCE_VHDL_KEYWORD=8 +val SCE_VHDL_STDOPERATOR=9 +val SCE_VHDL_ATTRIBUTE=10 +val SCE_VHDL_STDFUNCTION=11 +val SCE_VHDL_STDPACKAGE=12 +val SCE_VHDL_STDTYPE=13 +val SCE_VHDL_USERWORD=14 +# Lexical states for SCLEX_CAML +lex Caml=SCLEX_CAML SCE_CAML_ +val SCE_CAML_DEFAULT=0 +val SCE_CAML_IDENTIFIER=1 +val SCE_CAML_TAGNAME=2 +val SCE_CAML_KEYWORD=3 +val SCE_CAML_KEYWORD2=4 +val SCE_CAML_KEYWORD3=5 +val SCE_CAML_LINENUM=6 +val SCE_CAML_OPERATOR=7 +val SCE_CAML_NUMBER=8 +val SCE_CAML_CHAR=9 +val SCE_CAML_WHITE=10 +val SCE_CAML_STRING=11 +val SCE_CAML_COMMENT=12 +val SCE_CAML_COMMENT1=13 +val SCE_CAML_COMMENT2=14 +val SCE_CAML_COMMENT3=15 +# Lexical states for SCLEX_HASKELL +lex Haskell=SCLEX_HASKELL SCE_HA_ +val SCE_HA_DEFAULT=0 +val SCE_HA_IDENTIFIER=1 +val SCE_HA_KEYWORD=2 +val SCE_HA_NUMBER=3 +val SCE_HA_STRING=4 +val SCE_HA_CHARACTER=5 +val SCE_HA_CLASS=6 +val SCE_HA_MODULE=7 +val SCE_HA_CAPITAL=8 +val SCE_HA_DATA=9 +val SCE_HA_IMPORT=10 +val SCE_HA_OPERATOR=11 +val SCE_HA_INSTANCE=12 +val SCE_HA_COMMENTLINE=13 +val SCE_HA_COMMENTBLOCK=14 +val SCE_HA_COMMENTBLOCK2=15 +val SCE_HA_COMMENTBLOCK3=16 +# Lexical states of SCLEX_TADS3 +lex TADS3=SCLEX_TADS3 SCE_T3_ +val SCE_T3_DEFAULT=0 +val SCE_T3_X_DEFAULT=1 +val SCE_T3_PREPROCESSOR=2 +val SCE_T3_BLOCK_COMMENT=3 +val SCE_T3_LINE_COMMENT=4 +val SCE_T3_OPERATOR=5 +val SCE_T3_KEYWORD=6 +val SCE_T3_NUMBER=7 +val SCE_T3_IDENTIFIER=8 +val SCE_T3_S_STRING=9 +val SCE_T3_D_STRING=10 +val SCE_T3_X_STRING=11 +val SCE_T3_LIB_DIRECTIVE=12 +val SCE_T3_MSG_PARAM=13 +val SCE_T3_HTML_TAG=14 +val SCE_T3_HTML_DEFAULT=15 +val SCE_T3_HTML_STRING=16 +val SCE_T3_USER1=17 +val SCE_T3_USER2=18 +val SCE_T3_USER3=19 +val SCE_T3_BRACE=20 +# Lexical states for SCLEX_REBOL +lex Rebol=SCLEX_REBOL SCE_REBOL_ +val SCE_REBOL_DEFAULT=0 +val SCE_REBOL_COMMENTLINE=1 +val SCE_REBOL_COMMENTBLOCK=2 +val SCE_REBOL_PREFACE=3 +val SCE_REBOL_OPERATOR=4 +val SCE_REBOL_CHARACTER=5 +val SCE_REBOL_QUOTEDSTRING=6 +val SCE_REBOL_BRACEDSTRING=7 +val SCE_REBOL_NUMBER=8 +val SCE_REBOL_PAIR=9 +val SCE_REBOL_TUPLE=10 +val SCE_REBOL_BINARY=11 +val SCE_REBOL_MONEY=12 +val SCE_REBOL_ISSUE=13 +val SCE_REBOL_TAG=14 +val SCE_REBOL_FILE=15 +val SCE_REBOL_EMAIL=16 +val SCE_REBOL_URL=17 +val SCE_REBOL_DATE=18 +val SCE_REBOL_TIME=19 +val SCE_REBOL_IDENTIFIER=20 +val SCE_REBOL_WORD=21 +val SCE_REBOL_WORD2=22 +val SCE_REBOL_WORD3=23 +val SCE_REBOL_WORD4=24 +val SCE_REBOL_WORD5=25 +val SCE_REBOL_WORD6=26 +val SCE_REBOL_WORD7=27 +val SCE_REBOL_WORD8=28 +# Lexical states for SCLEX_SQL +lex SQL=SCLEX_SQL SCE_SQL_ +val SCE_SQL_DEFAULT=0 +val SCE_SQL_COMMENT=1 +val SCE_SQL_COMMENTLINE=2 +val SCE_SQL_COMMENTDOC=3 +val SCE_SQL_NUMBER=4 +val SCE_SQL_WORD=5 +val SCE_SQL_STRING=6 +val SCE_SQL_CHARACTER=7 +val SCE_SQL_SQLPLUS=8 +val SCE_SQL_SQLPLUS_PROMPT=9 +val SCE_SQL_OPERATOR=10 +val SCE_SQL_IDENTIFIER=11 +val SCE_SQL_SQLPLUS_COMMENT=13 +val SCE_SQL_COMMENTLINEDOC=15 +val SCE_SQL_WORD2=16 +val SCE_SQL_COMMENTDOCKEYWORD=17 +val SCE_SQL_COMMENTDOCKEYWORDERROR=18 +val SCE_SQL_USER1=19 +val SCE_SQL_USER2=20 +val SCE_SQL_USER3=21 +val SCE_SQL_USER4=22 +val SCE_SQL_QUOTEDIDENTIFIER=23 +# Lexical states for SCLEX_SMALLTALK +lex Smalltalk=SCLEX_SMALLTALK SCE_ST_ +val SCE_ST_DEFAULT=0 +val SCE_ST_STRING=1 +val SCE_ST_NUMBER=2 +val SCE_ST_COMMENT=3 +val SCE_ST_SYMBOL=4 +val SCE_ST_BINARY=5 +val SCE_ST_BOOL=6 +val SCE_ST_SELF=7 +val SCE_ST_SUPER=8 +val SCE_ST_NIL=9 +val SCE_ST_GLOBAL=10 +val SCE_ST_RETURN=11 +val SCE_ST_SPECIAL=12 +val SCE_ST_KWSEND=13 +val SCE_ST_ASSIGN=14 +val SCE_ST_CHARACTER=15 +val SCE_ST_SPEC_SEL=16 +# Lexical states for SCLEX_FLAGSHIP (clipper) +lex FlagShip=SCLEX_FLAGSHIP SCE_FS_ +val SCE_FS_DEFAULT=0 +val SCE_FS_COMMENT=1 +val SCE_FS_COMMENTLINE=2 +val SCE_FS_COMMENTDOC=3 +val SCE_FS_COMMENTLINEDOC=4 +val SCE_FS_COMMENTDOCKEYWORD=5 +val SCE_FS_COMMENTDOCKEYWORDERROR=6 +val SCE_FS_KEYWORD=7 +val SCE_FS_KEYWORD2=8 +val SCE_FS_KEYWORD3=9 +val SCE_FS_KEYWORD4=10 +val SCE_FS_NUMBER=11 +val SCE_FS_STRING=12 +val SCE_FS_PREPROCESSOR=13 +val SCE_FS_OPERATOR=14 +val SCE_FS_IDENTIFIER=15 +val SCE_FS_DATE=16 +val SCE_FS_STRINGEOL=17 +val SCE_FS_CONSTANT=18 +val SCE_FS_WORDOPERATOR=19 +val SCE_FS_DISABLEDCODE=20 +val SCE_FS_DEFAULT_C=21 +val SCE_FS_COMMENTDOC_C=22 +val SCE_FS_COMMENTLINEDOC_C=23 +val SCE_FS_KEYWORD_C=24 +val SCE_FS_KEYWORD2_C=25 +val SCE_FS_NUMBER_C=26 +val SCE_FS_STRING_C=27 +val SCE_FS_PREPROCESSOR_C=28 +val SCE_FS_OPERATOR_C=29 +val SCE_FS_IDENTIFIER_C=30 +val SCE_FS_STRINGEOL_C=31 +# Lexical states for SCLEX_CSOUND +lex Csound=SCLEX_CSOUND SCE_CSOUND_ +val SCE_CSOUND_DEFAULT=0 +val SCE_CSOUND_COMMENT=1 +val SCE_CSOUND_NUMBER=2 +val SCE_CSOUND_OPERATOR=3 +val SCE_CSOUND_INSTR=4 +val SCE_CSOUND_IDENTIFIER=5 +val SCE_CSOUND_OPCODE=6 +val SCE_CSOUND_HEADERSTMT=7 +val SCE_CSOUND_USERKEYWORD=8 +val SCE_CSOUND_COMMENTBLOCK=9 +val SCE_CSOUND_PARAM=10 +val SCE_CSOUND_ARATE_VAR=11 +val SCE_CSOUND_KRATE_VAR=12 +val SCE_CSOUND_IRATE_VAR=13 +val SCE_CSOUND_GLOBAL_VAR=14 +val SCE_CSOUND_STRINGEOL=15 +# Lexical states for SCLEX_INNOSETUP +lex Inno=SCLEX_INNOSETUP SCE_INNO_ +val SCE_INNO_DEFAULT=0 +val SCE_INNO_COMMENT=1 +val SCE_INNO_KEYWORD=2 +val SCE_INNO_PARAMETER=3 +val SCE_INNO_SECTION=4 +val SCE_INNO_PREPROC=5 +val SCE_INNO_INLINE_EXPANSION=6 +val SCE_INNO_COMMENT_PASCAL=7 +val SCE_INNO_KEYWORD_PASCAL=8 +val SCE_INNO_KEYWORD_USER=9 +val SCE_INNO_STRING_DOUBLE=10 +val SCE_INNO_STRING_SINGLE=11 +val SCE_INNO_IDENTIFIER=12 +# Lexical states for SCLEX_OPAL +lex Opal=SCLEX_OPAL SCE_OPAL_ +val SCE_OPAL_SPACE=0 +val SCE_OPAL_COMMENT_BLOCK=1 +val SCE_OPAL_COMMENT_LINE=2 +val SCE_OPAL_INTEGER=3 +val SCE_OPAL_KEYWORD=4 +val SCE_OPAL_SORT=5 +val SCE_OPAL_STRING=6 +val SCE_OPAL_PAR=7 +val SCE_OPAL_BOOL_CONST=8 +val SCE_OPAL_DEFAULT=32 +# Lexical states for SCLEX_SPICE +lex Spice=SCLEX_SPICE SCE_SPICE_ +val SCE_SPICE_DEFAULT=0 +val SCE_SPICE_IDENTIFIER=1 +val SCE_SPICE_KEYWORD=2 +val SCE_SPICE_KEYWORD2=3 +val SCE_SPICE_KEYWORD3=4 +val SCE_SPICE_NUMBER=5 +val SCE_SPICE_DELIMITER=6 +val SCE_SPICE_VALUE=7 +val SCE_SPICE_COMMENTLINE=8 +# Lexical states for SCLEX_CMAKE +lex CMAKE=SCLEX_CMAKE SCE_CMAKE_ +val SCE_CMAKE_DEFAULT=0 +val SCE_CMAKE_COMMENT=1 +val SCE_CMAKE_STRINGDQ=2 +val SCE_CMAKE_STRINGLQ=3 +val SCE_CMAKE_STRINGRQ=4 +val SCE_CMAKE_COMMANDS=5 +val SCE_CMAKE_PARAMETERS=6 +val SCE_CMAKE_VARIABLE=7 +val SCE_CMAKE_USERDEFINED=8 +val SCE_CMAKE_WHILEDEF=9 +val SCE_CMAKE_FOREACHDEF=10 +val SCE_CMAKE_IFDEFINEDEF=11 +val SCE_CMAKE_MACRODEF=12 +val SCE_CMAKE_STRINGVAR=13 +val SCE_CMAKE_NUMBER=14 +# Lexical states for SCLEX_GAP +lex Gap=SCLEX_GAP SCE_GAP_ +val SCE_GAP_DEFAULT=0 +val SCE_GAP_IDENTIFIER=1 +val SCE_GAP_KEYWORD=2 +val SCE_GAP_KEYWORD2=3 +val SCE_GAP_KEYWORD3=4 +val SCE_GAP_KEYWORD4=5 +val SCE_GAP_STRING=6 +val SCE_GAP_CHAR=7 +val SCE_GAP_OPERATOR=8 +val SCE_GAP_COMMENT=9 +val SCE_GAP_NUMBER=10 +val SCE_GAP_STRINGEOL=11 +# Lexical state for SCLEX_PLM +lex PLM=SCLEX_PLM SCE_PLM_ +val SCE_PLM_DEFAULT=0 +val SCE_PLM_COMMENT=1 +val SCE_PLM_STRING=2 +val SCE_PLM_NUMBER=3 +val SCE_PLM_IDENTIFIER=4 +val SCE_PLM_OPERATOR=5 +val SCE_PLM_CONTROL=6 +val SCE_PLM_KEYWORD=7 +# Lexical state for SCLEX_PROGRESS +lex Progress=SCLEX_PROGRESS SCE_4GL_ +val SCE_4GL_DEFAULT=0 +val SCE_4GL_NUMBER=1 +val SCE_4GL_WORD=2 +val SCE_4GL_STRING=3 +val SCE_4GL_CHARACTER=4 +val SCE_4GL_PREPROCESSOR=5 +val SCE_4GL_OPERATOR=6 +val SCE_4GL_IDENTIFIER=7 +val SCE_4GL_BLOCK=8 +val SCE_4GL_END=9 +val SCE_4GL_COMMENT1=10 +val SCE_4GL_COMMENT2=11 +val SCE_4GL_COMMENT3=12 +val SCE_4GL_COMMENT4=13 +val SCE_4GL_COMMENT5=14 +val SCE_4GL_COMMENT6=15 +val SCE_4GL_DEFAULT_=16 +val SCE_4GL_NUMBER_=17 +val SCE_4GL_WORD_=18 +val SCE_4GL_STRING_=19 +val SCE_4GL_CHARACTER_=20 +val SCE_4GL_PREPROCESSOR_=21 +val SCE_4GL_OPERATOR_=22 +val SCE_4GL_IDENTIFIER_=23 +val SCE_4GL_BLOCK_=24 +val SCE_4GL_END_=25 +val SCE_4GL_COMMENT1_=26 +val SCE_4GL_COMMENT2_=27 +val SCE_4GL_COMMENT3_=28 +val SCE_4GL_COMMENT4_=29 +val SCE_4GL_COMMENT5_=30 +val SCE_4GL_COMMENT6_=31 +# Lexical states for SCLEX_ABAQUS +lex ABAQUS=SCLEX_ABAQUS SCE_ABAQUS_ +val SCE_ABAQUS_DEFAULT=0 +val SCE_ABAQUS_COMMENT=1 +val SCE_ABAQUS_COMMENTBLOCK=2 +val SCE_ABAQUS_NUMBER=3 +val SCE_ABAQUS_STRING=4 +val SCE_ABAQUS_OPERATOR=5 +val SCE_ABAQUS_WORD=6 +val SCE_ABAQUS_PROCESSOR=7 +val SCE_ABAQUS_COMMAND=8 +val SCE_ABAQUS_SLASHCOMMAND=9 +val SCE_ABAQUS_STARCOMMAND=10 +val SCE_ABAQUS_ARGUMENT=11 +val SCE_ABAQUS_FUNCTION=12 +# Lexical states for SCLEX_ASYMPTOTE +lex Asymptote=SCLEX_ASYMPTOTE SCE_ASY_ +val SCE_ASY_DEFAULT=0 +val SCE_ASY_COMMENT=1 +val SCE_ASY_COMMENTLINE=2 +val SCE_ASY_NUMBER=3 +val SCE_ASY_WORD=4 +val SCE_ASY_STRING=5 +val SCE_ASY_CHARACTER=6 +val SCE_ASY_OPERATOR=7 +val SCE_ASY_IDENTIFIER=8 +val SCE_ASY_STRINGEOL=9 +val SCE_ASY_COMMENTLINEDOC=10 +val SCE_ASY_WORD2=11 +# Lexical states for SCLEX_R +lex R=SCLEX_R SCE_R_ +val SCE_R_DEFAULT=0 +val SCE_R_COMMENT=1 +val SCE_R_KWORD=2 +val SCE_R_BASEKWORD=3 +val SCE_R_OTHERKWORD=4 +val SCE_R_NUMBER=5 +val SCE_R_STRING=6 +val SCE_R_STRING2=7 +val SCE_R_OPERATOR=8 +val SCE_R_IDENTIFIER=9 +val SCE_R_INFIX=10 +val SCE_R_INFIXEOL=11 +# Lexical state for SCLEX_MAGIKSF +lex MagikSF=SCLEX_MAGIKSF SCE_MAGIK_ +val SCE_MAGIK_DEFAULT=0 +val SCE_MAGIK_COMMENT=1 +val SCE_MAGIK_HYPER_COMMENT=16 +val SCE_MAGIK_STRING=2 +val SCE_MAGIK_CHARACTER=3 +val SCE_MAGIK_NUMBER=4 +val SCE_MAGIK_IDENTIFIER=5 +val SCE_MAGIK_OPERATOR=6 +val SCE_MAGIK_FLOW=7 +val SCE_MAGIK_CONTAINER=8 +val SCE_MAGIK_BRACKET_BLOCK=9 +val SCE_MAGIK_BRACE_BLOCK=10 +val SCE_MAGIK_SQBRACKET_BLOCK=11 +val SCE_MAGIK_UNKNOWN_KEYWORD=12 +val SCE_MAGIK_KEYWORD=13 +val SCE_MAGIK_PRAGMA=14 +val SCE_MAGIK_SYMBOL=15 +# Lexical state for SCLEX_POWERSHELL +lex PowerShell=SCLEX_POWERSHELL SCE_POWERSHELL_ +val SCE_POWERSHELL_DEFAULT=0 +val SCE_POWERSHELL_COMMENT=1 +val SCE_POWERSHELL_STRING=2 +val SCE_POWERSHELL_CHARACTER=3 +val SCE_POWERSHELL_NUMBER=4 +val SCE_POWERSHELL_VARIABLE=5 +val SCE_POWERSHELL_OPERATOR=6 +val SCE_POWERSHELL_IDENTIFIER=7 +val SCE_POWERSHELL_KEYWORD=8 +val SCE_POWERSHELL_CMDLET=9 +val SCE_POWERSHELL_ALIAS=10 +val SCE_POWERSHELL_FUNCTION=11 +val SCE_POWERSHELL_USER1=12 +val SCE_POWERSHELL_COMMENTSTREAM=13 +# Lexical state for SCLEX_MYSQL +lex MySQL=SCLEX_MYSQL SCE_MYSQL_ +val SCE_MYSQL_DEFAULT=0 +val SCE_MYSQL_COMMENT=1 +val SCE_MYSQL_COMMENTLINE=2 +val SCE_MYSQL_VARIABLE=3 +val SCE_MYSQL_SYSTEMVARIABLE=4 +val SCE_MYSQL_KNOWNSYSTEMVARIABLE=5 +val SCE_MYSQL_NUMBER=6 +val SCE_MYSQL_MAJORKEYWORD=7 +val SCE_MYSQL_KEYWORD=8 +val SCE_MYSQL_DATABASEOBJECT=9 +val SCE_MYSQL_PROCEDUREKEYWORD=10 +val SCE_MYSQL_STRING=11 +val SCE_MYSQL_SQSTRING=12 +val SCE_MYSQL_DQSTRING=13 +val SCE_MYSQL_OPERATOR=14 +val SCE_MYSQL_FUNCTION=15 +val SCE_MYSQL_IDENTIFIER=16 +val SCE_MYSQL_QUOTEDIDENTIFIER=17 +val SCE_MYSQL_USER1=18 +val SCE_MYSQL_USER2=19 +val SCE_MYSQL_USER3=20 +val SCE_MYSQL_HIDDENCOMMAND=21 +# Lexical state for SCLEX_PO +lex Po=SCLEX_PO SCE_PO_ +val SCE_PO_DEFAULT=0 +val SCE_PO_COMMENT=1 +val SCE_PO_MSGID=2 +val SCE_PO_MSGID_TEXT=3 +val SCE_PO_MSGSTR=4 +val SCE_PO_MSGSTR_TEXT=5 +val SCE_PO_MSGCTXT=6 +val SCE_PO_MSGCTXT_TEXT=7 +val SCE_PO_FUZZY=8 +# Lexical states for SCLEX_PASCAL +lex Pascal=SCLEX_PASCAL SCE_PAS_ +val SCE_PAS_DEFAULT=0 +val SCE_PAS_IDENTIFIER=1 +val SCE_PAS_COMMENT=2 +val SCE_PAS_COMMENT2=3 +val SCE_PAS_COMMENTLINE=4 +val SCE_PAS_PREPROCESSOR=5 +val SCE_PAS_PREPROCESSOR2=6 +val SCE_PAS_NUMBER=7 +val SCE_PAS_HEXNUMBER=8 +val SCE_PAS_WORD=9 +val SCE_PAS_STRING=10 +val SCE_PAS_STRINGEOL=11 +val SCE_PAS_CHARACTER=12 +val SCE_PAS_OPERATOR=13 +val SCE_PAS_ASM=14 +# Lexical state for SCLEX_SORCUS +lex SORCUS=SCLEX_SORCUS SCE_SORCUS_ +val SCE_SORCUS_DEFAULT=0 +val SCE_SORCUS_COMMAND=1 +val SCE_SORCUS_PARAMETER=2 +val SCE_SORCUS_COMMENTLINE=3 +val SCE_SORCUS_STRING=4 +val SCE_SORCUS_STRINGEOL=5 +val SCE_SORCUS_IDENTIFIER=6 +val SCE_SORCUS_OPERATOR=7 +val SCE_SORCUS_NUMBER=8 +val SCE_SORCUS_CONSTANT=9 +# Lexical state for SCLEX_POWERPRO +lex PowerPro=SCLEX_POWERPRO SCE_POWERPRO_ +val SCE_POWERPRO_DEFAULT=0 +val SCE_POWERPRO_COMMENTBLOCK=1 +val SCE_POWERPRO_COMMENTLINE=2 +val SCE_POWERPRO_NUMBER=3 +val SCE_POWERPRO_WORD=4 +val SCE_POWERPRO_WORD2=5 +val SCE_POWERPRO_WORD3=6 +val SCE_POWERPRO_WORD4=7 +val SCE_POWERPRO_DOUBLEQUOTEDSTRING=8 +val SCE_POWERPRO_SINGLEQUOTEDSTRING=9 +val SCE_POWERPRO_LINECONTINUE=10 +val SCE_POWERPRO_OPERATOR=11 +val SCE_POWERPRO_IDENTIFIER=12 +val SCE_POWERPRO_STRINGEOL=13 +val SCE_POWERPRO_VERBATIM=14 +val SCE_POWERPRO_ALTQUOTE=15 +val SCE_POWERPRO_FUNCTION=16 +# Lexical states for SCLEX_SML +lex SML=SCLEX_SML SCE_SML_ +val SCE_SML_DEFAULT=0 +val SCE_SML_IDENTIFIER=1 +val SCE_SML_TAGNAME=2 +val SCE_SML_KEYWORD=3 +val SCE_SML_KEYWORD2=4 +val SCE_SML_KEYWORD3=5 +val SCE_SML_LINENUM=6 +val SCE_SML_OPERATOR=7 +val SCE_SML_NUMBER=8 +val SCE_SML_CHAR=9 +val SCE_SML_STRING=11 +val SCE_SML_COMMENT=12 +val SCE_SML_COMMENT1=13 +val SCE_SML_COMMENT2=14 +val SCE_SML_COMMENT3=15 +# Lexical state for SCLEX_MARKDOWN +lex Markdown=SCLEX_MARKDOWN SCE_MARKDOWN_ +val SCE_MARKDOWN_DEFAULT=0 +val SCE_MARKDOWN_LINE_BEGIN=1 +val SCE_MARKDOWN_STRONG1=2 +val SCE_MARKDOWN_STRONG2=3 +val SCE_MARKDOWN_EM1=4 +val SCE_MARKDOWN_EM2=5 +val SCE_MARKDOWN_HEADER1=6 +val SCE_MARKDOWN_HEADER2=7 +val SCE_MARKDOWN_HEADER3=8 +val SCE_MARKDOWN_HEADER4=9 +val SCE_MARKDOWN_HEADER5=10 +val SCE_MARKDOWN_HEADER6=11 +val SCE_MARKDOWN_PRECHAR=12 +val SCE_MARKDOWN_ULIST_ITEM=13 +val SCE_MARKDOWN_OLIST_ITEM=14 +val SCE_MARKDOWN_BLOCKQUOTE=15 +val SCE_MARKDOWN_STRIKEOUT=16 +val SCE_MARKDOWN_HRULE=17 +val SCE_MARKDOWN_LINK=18 +val SCE_MARKDOWN_CODE=19 +val SCE_MARKDOWN_CODE2=20 +val SCE_MARKDOWN_CODEBK=21 +# Lexical state for SCLEX_TXT2TAGS +lex Txt2tags=SCLEX_TXT2TAGS SCE_TXT2TAGS_ +val SCE_TXT2TAGS_DEFAULT=0 +val SCE_TXT2TAGS_LINE_BEGIN=1 +val SCE_TXT2TAGS_STRONG1=2 +val SCE_TXT2TAGS_STRONG2=3 +val SCE_TXT2TAGS_EM1=4 +val SCE_TXT2TAGS_EM2=5 +val SCE_TXT2TAGS_HEADER1=6 +val SCE_TXT2TAGS_HEADER2=7 +val SCE_TXT2TAGS_HEADER3=8 +val SCE_TXT2TAGS_HEADER4=9 +val SCE_TXT2TAGS_HEADER5=10 +val SCE_TXT2TAGS_HEADER6=11 +val SCE_TXT2TAGS_PRECHAR=12 +val SCE_TXT2TAGS_ULIST_ITEM=13 +val SCE_TXT2TAGS_OLIST_ITEM=14 +val SCE_TXT2TAGS_BLOCKQUOTE=15 +val SCE_TXT2TAGS_STRIKEOUT=16 +val SCE_TXT2TAGS_HRULE=17 +val SCE_TXT2TAGS_LINK=18 +val SCE_TXT2TAGS_CODE=19 +val SCE_TXT2TAGS_CODE2=20 +val SCE_TXT2TAGS_CODEBK=21 +val SCE_TXT2TAGS_COMMENT=22 +val SCE_TXT2TAGS_OPTION=23 +val SCE_TXT2TAGS_PREPROC=24 +val SCE_TXT2TAGS_POSTPROC=25 +# Lexical states for SCLEX_A68K +lex A68k=SCLEX_A68K SCE_A68K_ +val SCE_A68K_DEFAULT=0 +val SCE_A68K_COMMENT=1 +val SCE_A68K_NUMBER_DEC=2 +val SCE_A68K_NUMBER_BIN=3 +val SCE_A68K_NUMBER_HEX=4 +val SCE_A68K_STRING1=5 +val SCE_A68K_OPERATOR=6 +val SCE_A68K_CPUINSTRUCTION=7 +val SCE_A68K_EXTINSTRUCTION=8 +val SCE_A68K_REGISTER=9 +val SCE_A68K_DIRECTIVE=10 +val SCE_A68K_MACRO_ARG=11 +val SCE_A68K_LABEL=12 +val SCE_A68K_STRING2=13 +val SCE_A68K_IDENTIFIER=14 +val SCE_A68K_MACRO_DECLARATION=15 +val SCE_A68K_COMMENT_WORD=16 +val SCE_A68K_COMMENT_SPECIAL=17 +val SCE_A68K_COMMENT_DOXYGEN=18 +# Lexical states for SCLEX_MODULA +lex Modula=SCLEX_MODULA SCE_MODULA_ +val SCE_MODULA_DEFAULT=0 +val SCE_MODULA_COMMENT=1 +val SCE_MODULA_DOXYCOMM=2 +val SCE_MODULA_DOXYKEY=3 +val SCE_MODULA_KEYWORD=4 +val SCE_MODULA_RESERVED=5 +val SCE_MODULA_NUMBER=6 +val SCE_MODULA_BASENUM=7 +val SCE_MODULA_FLOAT=8 +val SCE_MODULA_STRING=9 +val SCE_MODULA_STRSPEC=10 +val SCE_MODULA_CHAR=11 +val SCE_MODULA_CHARSPEC=12 +val SCE_MODULA_PROC=13 +val SCE_MODULA_PRAGMA=14 +val SCE_MODULA_PRGKEY=15 +val SCE_MODULA_OPERATOR=16 +val SCE_MODULA_BADSTR=17 +# Lexical states for SCLEX_COFFEESCRIPT +lex CoffeeScript=SCLEX_COFFEESCRIPT SCE_COFFEESCRIPT_ +val SCE_COFFEESCRIPT_DEFAULT=0 +val SCE_COFFEESCRIPT_COMMENT=1 +val SCE_COFFEESCRIPT_COMMENTLINE=2 +val SCE_COFFEESCRIPT_COMMENTDOC=3 +val SCE_COFFEESCRIPT_NUMBER=4 +val SCE_COFFEESCRIPT_WORD=5 +val SCE_COFFEESCRIPT_STRING=6 +val SCE_COFFEESCRIPT_CHARACTER=7 +val SCE_COFFEESCRIPT_UUID=8 +val SCE_COFFEESCRIPT_PREPROCESSOR=9 +val SCE_COFFEESCRIPT_OPERATOR=10 +val SCE_COFFEESCRIPT_IDENTIFIER=11 +val SCE_COFFEESCRIPT_STRINGEOL=12 +val SCE_COFFEESCRIPT_VERBATIM=13 +val SCE_COFFEESCRIPT_REGEX=14 +val SCE_COFFEESCRIPT_COMMENTLINEDOC=15 +val SCE_COFFEESCRIPT_WORD2=16 +val SCE_COFFEESCRIPT_COMMENTDOCKEYWORD=17 +val SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR=18 +val SCE_COFFEESCRIPT_GLOBALCLASS=19 +val SCE_COFFEESCRIPT_STRINGRAW=20 +val SCE_COFFEESCRIPT_TRIPLEVERBATIM=21 +val SCE_COFFEESCRIPT_HASHQUOTEDSTRING=22 +val SCE_COFFEESCRIPT_COMMENTBLOCK=22 +val SCE_COFFEESCRIPT_VERBOSE_REGEX=23 +val SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT=24 +# Lexical states for SCLEX_AVS +lex AVS=SCLEX_AVS SCE_AVS_ +val SCE_AVS_DEFAULT=0 +val SCE_AVS_COMMENTBLOCK=1 +val SCE_AVS_COMMENTBLOCKN=2 +val SCE_AVS_COMMENTLINE=3 +val SCE_AVS_NUMBER=4 +val SCE_AVS_OPERATOR=5 +val SCE_AVS_IDENTIFIER=6 +val SCE_AVS_STRING=7 +val SCE_AVS_TRIPLESTRING=8 +val SCE_AVS_KEYWORD=9 +val SCE_AVS_FILTER=10 +val SCE_AVS_PLUGIN=11 +val SCE_AVS_FUNCTION=12 +val SCE_AVS_CLIPPROP=13 +val SCE_AVS_USERDFN=14 + +# Events + +evt void StyleNeeded=2000(int position) +evt void CharAdded=2001(int ch) +evt void SavePointReached=2002(void) +evt void SavePointLeft=2003(void) +evt void ModifyAttemptRO=2004(void) +# GTK+ Specific to work around focus and accelerator problems: +evt void Key=2005(int ch, int modifiers) +evt void DoubleClick=2006(int modifiers, int position, int line) +evt void UpdateUI=2007(int updated) +evt void Modified=2008(int position, int modificationType, string text, int length, int linesAdded, int line, int foldLevelNow, int foldLevelPrev, int token, int annotationLinesAdded) +evt void MacroRecord=2009(int message, int wParam, int lParam) +evt void MarginClick=2010(int modifiers, int position, int margin) +evt void NeedShown=2011(int position, int length) +evt void Painted=2013(void) +evt void UserListSelection=2014(int listType, string text, int position) +evt void URIDropped=2015(string text) +evt void DwellStart=2016(int position, int x, int y) +evt void DwellEnd=2017(int position, int x, int y) +evt void Zoom=2018(void) +evt void HotSpotClick=2019(int modifiers, int position) +evt void HotSpotDoubleClick=2020(int modifiers, int position) +evt void CallTipClick=2021(int position) +evt void AutoCSelection=2022(string text, int position) +evt void IndicatorClick=2023(int modifiers, int position) +evt void IndicatorRelease=2024(int modifiers, int position) +evt void AutoCCancelled=2025(void) +evt void AutoCCharDeleted=2026(void) +evt void HotSpotReleaseClick=2027(int modifiers, int position) + +cat Deprecated + +# Deprecated in 2.21 +# The SC_CP_DBCS value can be used to indicate a DBCS mode for GTK+. +val SC_CP_DBCS=1 + +# Deprecated in 2.30 + +# In palette mode? +get bool GetUsePalette=2139(,) + +# In palette mode, Scintilla uses the environment's palette calls to display +# more colours. This may lead to ugly displays. +set void SetUsePalette=2039(bool usePalette,) diff --git a/scintilla/include/ScintillaWidget.h b/ThirdLibs/scintilla/include/ScintillaWidget.h similarity index 96% rename from scintilla/include/ScintillaWidget.h rename to ThirdLibs/scintilla/include/ScintillaWidget.h index 3a3c7ca9..021af2a3 100644 --- a/scintilla/include/ScintillaWidget.h +++ b/ThirdLibs/scintilla/include/ScintillaWidget.h @@ -1,51 +1,51 @@ -/* Scintilla source code edit control */ -/** @file ScintillaWidget.h - ** Definition of Scintilla widget for GTK+. - ** Only needed by GTK+ code but is harmless on other platforms. - **/ -/* Copyright 1998-2001 by Neil Hodgson - * The License.txt file describes the conditions under which this software may be distributed. */ - -#ifndef SCINTILLAWIDGET_H -#define SCINTILLAWIDGET_H - -#if defined(GTK) - -#ifdef __cplusplus -extern "C" { -#endif - -#define SCINTILLA(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, scintilla_get_type (), ScintillaObject) -#define SCINTILLA_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, scintilla_get_type (), ScintillaClass) -#define IS_SCINTILLA(obj) GTK_CHECK_TYPE (obj, scintilla_get_type ()) - -typedef struct _ScintillaObject ScintillaObject; -typedef struct _ScintillaClass ScintillaClass; - -struct _ScintillaObject { - GtkContainer cont; - void *pscin; -}; - -struct _ScintillaClass { - GtkContainerClass parent_class; - - void (* command) (ScintillaObject *ttt); - void (* notify) (ScintillaObject *ttt); -}; - -GType scintilla_get_type (void); -GtkWidget* scintilla_new (void); -void scintilla_set_id (ScintillaObject *sci, uptr_t id); -sptr_t scintilla_send_message (ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam); -void scintilla_release_resources(void); - -#define SCINTILLA_NOTIFY "sci-notify" - -#ifdef __cplusplus -} -#endif - -#endif - -#endif +/* Scintilla source code edit control */ +/** @file ScintillaWidget.h + ** Definition of Scintilla widget for GTK+. + ** Only needed by GTK+ code but is harmless on other platforms. + **/ +/* Copyright 1998-2001 by Neil Hodgson + * The License.txt file describes the conditions under which this software may be distributed. */ + +#ifndef SCINTILLAWIDGET_H +#define SCINTILLAWIDGET_H + +#if defined(GTK) + +#ifdef __cplusplus +extern "C" { +#endif + +#define SCINTILLA(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, scintilla_get_type (), ScintillaObject) +#define SCINTILLA_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, scintilla_get_type (), ScintillaClass) +#define IS_SCINTILLA(obj) GTK_CHECK_TYPE (obj, scintilla_get_type ()) + +typedef struct _ScintillaObject ScintillaObject; +typedef struct _ScintillaClass ScintillaClass; + +struct _ScintillaObject { + GtkContainer cont; + void *pscin; +}; + +struct _ScintillaClass { + GtkContainerClass parent_class; + + void (* command) (ScintillaObject *ttt); + void (* notify) (ScintillaObject *ttt); +}; + +GType scintilla_get_type (void); +GtkWidget* scintilla_new (void); +void scintilla_set_id (ScintillaObject *sci, uptr_t id); +sptr_t scintilla_send_message (ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam); +void scintilla_release_resources(void); + +#define SCINTILLA_NOTIFY "sci-notify" + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/scintilla/lexers/LexA68k.cxx b/ThirdLibs/scintilla/lexers/LexA68k.cxx similarity index 97% rename from scintilla/lexers/LexA68k.cxx rename to ThirdLibs/scintilla/lexers/LexA68k.cxx index cbf26810..970e429c 100644 --- a/scintilla/lexers/LexA68k.cxx +++ b/ThirdLibs/scintilla/lexers/LexA68k.cxx @@ -1,318 +1,318 @@ -// Scintilla source code edit control -/** @file LexA68k.cxx - ** Lexer for Assembler, just for the MASM syntax - ** Written by Martial Demolins AKA Folco - **/ -// Copyright 2010 Martial Demolins -// The License.txt file describes the conditions under which this software -// may be distributed. - - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - - -// Return values for GetOperatorType -#define NO_OPERATOR 0 -#define OPERATOR_1CHAR 1 -#define OPERATOR_2CHAR 2 - - -/** - * IsIdentifierStart - * - * Return true if the given char is a valid identifier first char - */ - -static inline bool IsIdentifierStart (const int ch) -{ - return (isalpha(ch) || (ch == '_') || (ch == '\\')); -} - - -/** - * IsIdentifierChar - * - * Return true if the given char is a valid identifier char - */ - -static inline bool IsIdentifierChar (const int ch) -{ - return (isalnum(ch) || (ch == '_') || (ch == '@') || (ch == ':') || (ch == '.')); -} - - -/** - * GetOperatorType - * - * Return: - * NO_OPERATOR if char is not an operator - * OPERATOR_1CHAR if the operator is one char long - * OPERATOR_2CHAR if the operator is two chars long - */ - -static inline int GetOperatorType (const int ch1, const int ch2) -{ - int OpType = NO_OPERATOR; - - if ((ch1 == '+') || (ch1 == '-') || (ch1 == '*') || (ch1 == '/') || (ch1 == '#') || - (ch1 == '(') || (ch1 == ')') || (ch1 == '~') || (ch1 == '&') || (ch1 == '|') || (ch1 == ',')) - OpType = OPERATOR_1CHAR; - - else if ((ch1 == ch2) && (ch1 == '<' || ch1 == '>')) - OpType = OPERATOR_2CHAR; - - return OpType; -} - - -/** - * IsBin - * - * Return true if the given char is 0 or 1 - */ - -static inline bool IsBin (const int ch) -{ - return (ch == '0') || (ch == '1'); -} - - -/** - * IsDoxygenChar - * - * Return true if the char may be part of a Doxygen keyword - */ - -static inline bool IsDoxygenChar (const int ch) -{ - return isalpha(ch) || (ch == '$') || (ch == '[') || (ch == ']') || (ch == '{') || (ch == '}'); -} - - -/** - * ColouriseA68kDoc - * - * Main function, which colourises a 68k source - */ - -static void ColouriseA68kDoc (unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) -{ - - // Get references to keywords lists - WordList &cpuInstruction = *keywordlists[0]; - WordList ®isters = *keywordlists[1]; - WordList &directive = *keywordlists[2]; - WordList &extInstruction = *keywordlists[3]; - WordList &commentSpecial = *keywordlists[4]; - WordList &doxygenKeyword = *keywordlists[5]; - - - // Instanciate a context for our source - StyleContext sc(startPos, length, initStyle, styler); - - - /************************************************************ - * - * Parse the text - * - ************************************************************/ - - for ( ; sc.More(); sc.Forward()) - { - char Buffer[100]; - int OpType; - - // Reset style at beginning of line - if (sc.atLineStart) - sc.SetState(SCE_A68K_DEFAULT); - - - /************************************************************ - * - * Handle current state if we are not in the "default style" - * - ************************************************************/ - - if (sc.state != SCE_A68K_DEFAULT) - { - // Check if current style continue. - // If this case, we loop because there is nothing else to do - if (((sc.state == SCE_A68K_NUMBER_DEC) && isdigit(sc.ch)) // Decimal number - || ((sc.state == SCE_A68K_NUMBER_BIN) && IsBin(sc.ch)) // Binary number - || ((sc.state == SCE_A68K_NUMBER_HEX) && isxdigit(sc.ch)) // Hexa number - || ((sc.state == SCE_A68K_MACRO_ARG) && isdigit(sc.ch)) // Arg of macro - || ((sc.state == SCE_A68K_STRING1) && (sc.ch != '\'')) // String single-quoted - || ((sc.state == SCE_A68K_STRING2) && (sc.ch != '\"')) // String double-quoted - || ((sc.state == SCE_A68K_MACRO_ARG) && isdigit(sc.ch)) // Macro argument - // Label. ' ' and '\t' are needed to handle macro declarations - || ((sc.state == SCE_A68K_LABEL) && (sc.ch != ':') && (sc.ch != ' ') && (sc.ch != '\t')) - || ((sc.state == SCE_A68K_IDENTIFIER) && (sc.ch < 0x80) && IsIdentifierChar(sc.ch)) // Identifier - || ((sc.state == SCE_A68K_COMMENT_DOXYGEN) && (sc.ch < 0x80) && IsDoxygenChar(sc.ch)) // Doxygen keyword - || ((sc.state == SCE_A68K_COMMENT_WORD) && (sc.ch < 0x80) && isalpha(sc.ch))) // Comment current word - { - continue; - } - - // Check if some states terminate at the current char: - // we must include this char in the current style context - else if (((sc.state == SCE_A68K_STRING1) && (sc.ch < 0x80) && (sc.ch == '\'')) // String single-quoted - || ((sc.state == SCE_A68K_STRING2) && (sc.ch < 0x80) && (sc.ch == '\"')) // String double-quoted - || ((sc.state == SCE_A68K_LABEL) && (sc.ch < 0x80) && (sc.ch == ':'))) // Label - { - sc.ForwardSetState(SCE_A68K_DEFAULT); - } - - // Check for special words or Doxygen keywords in comments - else if (sc.state == SCE_A68K_COMMENT) - { - if (sc.ch == '\\') { - sc.SetState(SCE_A68K_COMMENT_DOXYGEN); - } - else if ((sc.ch < 0x80) && isalpha(sc.ch)) { - sc.SetState(SCE_A68K_COMMENT_WORD); - } - continue; - } - - // Check for special words in comment - else if ((sc.state == SCE_A68K_COMMENT_WORD) && (sc.ch < 0x80) && !isalpha(sc.ch)) - { - sc.GetCurrent(Buffer, sizeof(Buffer)); - if (commentSpecial.InList(Buffer)) { - sc.ChangeState(SCE_A68K_COMMENT_SPECIAL); - } - else { - sc.ChangeState(SCE_A68K_COMMENT); - } - sc.SetState(SCE_A68K_COMMENT); - continue; - } - - // Check for Doxygen keywords - else if ((sc.state == SCE_A68K_COMMENT_DOXYGEN) && (sc.ch < 0x80) && !IsDoxygenChar(sc.ch)) - { - sc.GetCurrentLowered(Buffer, sizeof(Buffer)); // Buffer the string of the current context - if (!doxygenKeyword.InList(Buffer)) { - sc.ChangeState(SCE_A68K_COMMENT); - } - sc.SetState(SCE_A68K_COMMENT); - continue; - } - - // Check if we are in the case of a label which terminates without ':' - // It should be a macro declaration, not a label - else if ((sc.state == SCE_A68K_LABEL) && (sc.ch < 0x80) && ((sc.ch == ' ') || (sc.ch == '\t'))) - { - sc.ChangeState(SCE_A68K_MACRO_DECLARATION); - } - - // Check if we are at the end of an identifier - // In this case, colourise it if was a keyword. - else if ((sc.state == SCE_A68K_IDENTIFIER) && !IsIdentifierChar(sc.ch)) - { - sc.GetCurrentLowered(Buffer, sizeof(Buffer)); // Buffer the string of the current context - if (cpuInstruction.InList(Buffer)) { // And check if it belongs to a keyword list - sc.ChangeState(SCE_A68K_CPUINSTRUCTION); - } - else if (extInstruction.InList(Buffer)) { - sc.ChangeState(SCE_A68K_EXTINSTRUCTION); - } - else if (registers.InList(Buffer)) { - sc.ChangeState(SCE_A68K_REGISTER); - } - else if (directive.InList(Buffer)) { - sc.ChangeState(SCE_A68K_DIRECTIVE); - } - } - - // All special contexts are now handled.Come back to default style - sc.SetState(SCE_A68K_DEFAULT); - } - - - /************************************************************ - * - * Check if we must enter a new state - * - ************************************************************/ - - // Label and macro identifiers start at the beginning of a line - // We set both as a label, but if it wasn't one (no ':' at the end), - // it will be changed as a macro identifier. - if (sc.atLineStart && (sc.ch < 0x80) && IsIdentifierStart(sc.ch)) { - sc.SetState(SCE_A68K_LABEL); - } - else if ((sc.ch < 0x80) && (sc.ch == ';')) { // Comment - sc.SetState(SCE_A68K_COMMENT); - } - else if ((sc.ch < 0x80) && isdigit(sc.ch)) { // Decimal numbers haven't prefix - sc.SetState(SCE_A68K_NUMBER_DEC); - } - else if ((sc.ch < 0x80) && (sc.ch == '%')) { // Binary numbers are prefixed with '%' - sc.SetState(SCE_A68K_NUMBER_BIN); - } - else if ((sc.ch < 0x80) && (sc.ch == '$')) { // Hexadecimal numbers are prefixed with '$' - sc.SetState(SCE_A68K_NUMBER_HEX); - } - else if ((sc.ch < 0x80) && (sc.ch == '\'')) { // String (single-quoted) - sc.SetState(SCE_A68K_STRING1); - } - else if ((sc.ch < 0x80) && (sc.ch == '\"')) { // String (double-quoted) - sc.SetState(SCE_A68K_STRING2); - } - else if ((sc.ch < 0x80) && (sc.ch == '\\') && (isdigit(sc.chNext))) { // Replacement symbols in macro - sc.SetState(SCE_A68K_MACRO_ARG); - } - else if ((sc.ch < 0x80) && IsIdentifierStart(sc.ch)) { // An identifier: constant, label, etc... - sc.SetState(SCE_A68K_IDENTIFIER); - } - else { - if (sc.ch < 0x80) { - OpType = GetOperatorType(sc.ch, sc.chNext); // Check if current char is an operator - if (OpType != NO_OPERATOR) { - sc.SetState(SCE_A68K_OPERATOR); - if (OpType == OPERATOR_2CHAR) { // Check if the operator is 2 bytes long - sc.ForwardSetState(SCE_A68K_OPERATOR); // (>> or <<) - } - } - } - } - } // End of for() - sc.Complete(); -} - - -// Names of the keyword lists - -static const char * const a68kWordListDesc[] = -{ - "CPU instructions", - "Registers", - "Directives", - "Extended instructions", - "Comment special words", - "Doxygen keywords", - 0 -}; - -LexerModule lmA68k(SCLEX_A68K, ColouriseA68kDoc, "a68k", 0, a68kWordListDesc); +// Scintilla source code edit control +/** @file LexA68k.cxx + ** Lexer for Assembler, just for the MASM syntax + ** Written by Martial Demolins AKA Folco + **/ +// Copyright 2010 Martial Demolins +// The License.txt file describes the conditions under which this software +// may be distributed. + + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + + +// Return values for GetOperatorType +#define NO_OPERATOR 0 +#define OPERATOR_1CHAR 1 +#define OPERATOR_2CHAR 2 + + +/** + * IsIdentifierStart + * + * Return true if the given char is a valid identifier first char + */ + +static inline bool IsIdentifierStart (const int ch) +{ + return (isalpha(ch) || (ch == '_') || (ch == '\\')); +} + + +/** + * IsIdentifierChar + * + * Return true if the given char is a valid identifier char + */ + +static inline bool IsIdentifierChar (const int ch) +{ + return (isalnum(ch) || (ch == '_') || (ch == '@') || (ch == ':') || (ch == '.')); +} + + +/** + * GetOperatorType + * + * Return: + * NO_OPERATOR if char is not an operator + * OPERATOR_1CHAR if the operator is one char long + * OPERATOR_2CHAR if the operator is two chars long + */ + +static inline int GetOperatorType (const int ch1, const int ch2) +{ + int OpType = NO_OPERATOR; + + if ((ch1 == '+') || (ch1 == '-') || (ch1 == '*') || (ch1 == '/') || (ch1 == '#') || + (ch1 == '(') || (ch1 == ')') || (ch1 == '~') || (ch1 == '&') || (ch1 == '|') || (ch1 == ',')) + OpType = OPERATOR_1CHAR; + + else if ((ch1 == ch2) && (ch1 == '<' || ch1 == '>')) + OpType = OPERATOR_2CHAR; + + return OpType; +} + + +/** + * IsBin + * + * Return true if the given char is 0 or 1 + */ + +static inline bool IsBin (const int ch) +{ + return (ch == '0') || (ch == '1'); +} + + +/** + * IsDoxygenChar + * + * Return true if the char may be part of a Doxygen keyword + */ + +static inline bool IsDoxygenChar (const int ch) +{ + return isalpha(ch) || (ch == '$') || (ch == '[') || (ch == ']') || (ch == '{') || (ch == '}'); +} + + +/** + * ColouriseA68kDoc + * + * Main function, which colourises a 68k source + */ + +static void ColouriseA68kDoc (unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) +{ + + // Get references to keywords lists + WordList &cpuInstruction = *keywordlists[0]; + WordList ®isters = *keywordlists[1]; + WordList &directive = *keywordlists[2]; + WordList &extInstruction = *keywordlists[3]; + WordList &commentSpecial = *keywordlists[4]; + WordList &doxygenKeyword = *keywordlists[5]; + + + // Instanciate a context for our source + StyleContext sc(startPos, length, initStyle, styler); + + + /************************************************************ + * + * Parse the text + * + ************************************************************/ + + for ( ; sc.More(); sc.Forward()) + { + char Buffer[100]; + int OpType; + + // Reset style at beginning of line + if (sc.atLineStart) + sc.SetState(SCE_A68K_DEFAULT); + + + /************************************************************ + * + * Handle current state if we are not in the "default style" + * + ************************************************************/ + + if (sc.state != SCE_A68K_DEFAULT) + { + // Check if current style continue. + // If this case, we loop because there is nothing else to do + if (((sc.state == SCE_A68K_NUMBER_DEC) && isdigit(sc.ch)) // Decimal number + || ((sc.state == SCE_A68K_NUMBER_BIN) && IsBin(sc.ch)) // Binary number + || ((sc.state == SCE_A68K_NUMBER_HEX) && isxdigit(sc.ch)) // Hexa number + || ((sc.state == SCE_A68K_MACRO_ARG) && isdigit(sc.ch)) // Arg of macro + || ((sc.state == SCE_A68K_STRING1) && (sc.ch != '\'')) // String single-quoted + || ((sc.state == SCE_A68K_STRING2) && (sc.ch != '\"')) // String double-quoted + || ((sc.state == SCE_A68K_MACRO_ARG) && isdigit(sc.ch)) // Macro argument + // Label. ' ' and '\t' are needed to handle macro declarations + || ((sc.state == SCE_A68K_LABEL) && (sc.ch != ':') && (sc.ch != ' ') && (sc.ch != '\t')) + || ((sc.state == SCE_A68K_IDENTIFIER) && (sc.ch < 0x80) && IsIdentifierChar(sc.ch)) // Identifier + || ((sc.state == SCE_A68K_COMMENT_DOXYGEN) && (sc.ch < 0x80) && IsDoxygenChar(sc.ch)) // Doxygen keyword + || ((sc.state == SCE_A68K_COMMENT_WORD) && (sc.ch < 0x80) && isalpha(sc.ch))) // Comment current word + { + continue; + } + + // Check if some states terminate at the current char: + // we must include this char in the current style context + else if (((sc.state == SCE_A68K_STRING1) && (sc.ch < 0x80) && (sc.ch == '\'')) // String single-quoted + || ((sc.state == SCE_A68K_STRING2) && (sc.ch < 0x80) && (sc.ch == '\"')) // String double-quoted + || ((sc.state == SCE_A68K_LABEL) && (sc.ch < 0x80) && (sc.ch == ':'))) // Label + { + sc.ForwardSetState(SCE_A68K_DEFAULT); + } + + // Check for special words or Doxygen keywords in comments + else if (sc.state == SCE_A68K_COMMENT) + { + if (sc.ch == '\\') { + sc.SetState(SCE_A68K_COMMENT_DOXYGEN); + } + else if ((sc.ch < 0x80) && isalpha(sc.ch)) { + sc.SetState(SCE_A68K_COMMENT_WORD); + } + continue; + } + + // Check for special words in comment + else if ((sc.state == SCE_A68K_COMMENT_WORD) && (sc.ch < 0x80) && !isalpha(sc.ch)) + { + sc.GetCurrent(Buffer, sizeof(Buffer)); + if (commentSpecial.InList(Buffer)) { + sc.ChangeState(SCE_A68K_COMMENT_SPECIAL); + } + else { + sc.ChangeState(SCE_A68K_COMMENT); + } + sc.SetState(SCE_A68K_COMMENT); + continue; + } + + // Check for Doxygen keywords + else if ((sc.state == SCE_A68K_COMMENT_DOXYGEN) && (sc.ch < 0x80) && !IsDoxygenChar(sc.ch)) + { + sc.GetCurrentLowered(Buffer, sizeof(Buffer)); // Buffer the string of the current context + if (!doxygenKeyword.InList(Buffer)) { + sc.ChangeState(SCE_A68K_COMMENT); + } + sc.SetState(SCE_A68K_COMMENT); + continue; + } + + // Check if we are in the case of a label which terminates without ':' + // It should be a macro declaration, not a label + else if ((sc.state == SCE_A68K_LABEL) && (sc.ch < 0x80) && ((sc.ch == ' ') || (sc.ch == '\t'))) + { + sc.ChangeState(SCE_A68K_MACRO_DECLARATION); + } + + // Check if we are at the end of an identifier + // In this case, colourise it if was a keyword. + else if ((sc.state == SCE_A68K_IDENTIFIER) && !IsIdentifierChar(sc.ch)) + { + sc.GetCurrentLowered(Buffer, sizeof(Buffer)); // Buffer the string of the current context + if (cpuInstruction.InList(Buffer)) { // And check if it belongs to a keyword list + sc.ChangeState(SCE_A68K_CPUINSTRUCTION); + } + else if (extInstruction.InList(Buffer)) { + sc.ChangeState(SCE_A68K_EXTINSTRUCTION); + } + else if (registers.InList(Buffer)) { + sc.ChangeState(SCE_A68K_REGISTER); + } + else if (directive.InList(Buffer)) { + sc.ChangeState(SCE_A68K_DIRECTIVE); + } + } + + // All special contexts are now handled.Come back to default style + sc.SetState(SCE_A68K_DEFAULT); + } + + + /************************************************************ + * + * Check if we must enter a new state + * + ************************************************************/ + + // Label and macro identifiers start at the beginning of a line + // We set both as a label, but if it wasn't one (no ':' at the end), + // it will be changed as a macro identifier. + if (sc.atLineStart && (sc.ch < 0x80) && IsIdentifierStart(sc.ch)) { + sc.SetState(SCE_A68K_LABEL); + } + else if ((sc.ch < 0x80) && (sc.ch == ';')) { // Comment + sc.SetState(SCE_A68K_COMMENT); + } + else if ((sc.ch < 0x80) && isdigit(sc.ch)) { // Decimal numbers haven't prefix + sc.SetState(SCE_A68K_NUMBER_DEC); + } + else if ((sc.ch < 0x80) && (sc.ch == '%')) { // Binary numbers are prefixed with '%' + sc.SetState(SCE_A68K_NUMBER_BIN); + } + else if ((sc.ch < 0x80) && (sc.ch == '$')) { // Hexadecimal numbers are prefixed with '$' + sc.SetState(SCE_A68K_NUMBER_HEX); + } + else if ((sc.ch < 0x80) && (sc.ch == '\'')) { // String (single-quoted) + sc.SetState(SCE_A68K_STRING1); + } + else if ((sc.ch < 0x80) && (sc.ch == '\"')) { // String (double-quoted) + sc.SetState(SCE_A68K_STRING2); + } + else if ((sc.ch < 0x80) && (sc.ch == '\\') && (isdigit(sc.chNext))) { // Replacement symbols in macro + sc.SetState(SCE_A68K_MACRO_ARG); + } + else if ((sc.ch < 0x80) && IsIdentifierStart(sc.ch)) { // An identifier: constant, label, etc... + sc.SetState(SCE_A68K_IDENTIFIER); + } + else { + if (sc.ch < 0x80) { + OpType = GetOperatorType(sc.ch, sc.chNext); // Check if current char is an operator + if (OpType != NO_OPERATOR) { + sc.SetState(SCE_A68K_OPERATOR); + if (OpType == OPERATOR_2CHAR) { // Check if the operator is 2 bytes long + sc.ForwardSetState(SCE_A68K_OPERATOR); // (>> or <<) + } + } + } + } + } // End of for() + sc.Complete(); +} + + +// Names of the keyword lists + +static const char * const a68kWordListDesc[] = +{ + "CPU instructions", + "Registers", + "Directives", + "Extended instructions", + "Comment special words", + "Doxygen keywords", + 0 +}; + +LexerModule lmA68k(SCLEX_A68K, ColouriseA68kDoc, "a68k", 0, a68kWordListDesc); diff --git a/scintilla/lexers/LexAPDL.cxx b/ThirdLibs/scintilla/lexers/LexAPDL.cxx similarity index 96% rename from scintilla/lexers/LexAPDL.cxx rename to ThirdLibs/scintilla/lexers/LexAPDL.cxx index 5df1d650..7d65a561 100644 --- a/scintilla/lexers/LexAPDL.cxx +++ b/ThirdLibs/scintilla/lexers/LexAPDL.cxx @@ -1,259 +1,259 @@ -// Scintilla source code edit control -/** @file LexAPDL.cxx - ** Lexer for APDL. Based on the lexer for Assembler by The Black Horus. - ** By Hadar Raz. - **/ -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80 && (isalnum(ch) || ch == '_')); -} - -static inline bool IsAnOperator(char ch) { - // '.' left out as it is used to make up numbers - if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || ch == '^' || - ch == '[' || ch == ']' || ch == '<' || ch == '&' || - ch == '>' || ch == ',' || ch == '|' || ch == '~' || - ch == '$' || ch == ':' || ch == '%') - return true; - return false; -} - -static void ColouriseAPDLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - int stringStart = ' '; - - WordList &processors = *keywordlists[0]; - WordList &commands = *keywordlists[1]; - WordList &slashcommands = *keywordlists[2]; - WordList &starcommands = *keywordlists[3]; - WordList &arguments = *keywordlists[4]; - WordList &functions = *keywordlists[5]; - - // Do not leak onto next line - initStyle = SCE_APDL_DEFAULT; - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - // Determine if the current state should terminate. - if (sc.state == SCE_APDL_NUMBER) { - if (!(IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || - ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { - sc.SetState(SCE_APDL_DEFAULT); - } - } else if (sc.state == SCE_APDL_COMMENT) { - if (sc.atLineEnd) { - sc.SetState(SCE_APDL_DEFAULT); - } - } else if (sc.state == SCE_APDL_COMMENTBLOCK) { - if (sc.atLineEnd) { - if (sc.ch == '\r') { - sc.Forward(); - } - sc.ForwardSetState(SCE_APDL_DEFAULT); - } - } else if (sc.state == SCE_APDL_STRING) { - if (sc.atLineEnd) { - sc.SetState(SCE_APDL_DEFAULT); - } else if ((sc.ch == '\'' && stringStart == '\'') || (sc.ch == '\"' && stringStart == '\"')) { - sc.ForwardSetState(SCE_APDL_DEFAULT); - } - } else if (sc.state == SCE_APDL_WORD) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (processors.InList(s)) { - sc.ChangeState(SCE_APDL_PROCESSOR); - } else if (slashcommands.InList(s)) { - sc.ChangeState(SCE_APDL_SLASHCOMMAND); - } else if (starcommands.InList(s)) { - sc.ChangeState(SCE_APDL_STARCOMMAND); - } else if (commands.InList(s)) { - sc.ChangeState(SCE_APDL_COMMAND); - } else if (arguments.InList(s)) { - sc.ChangeState(SCE_APDL_ARGUMENT); - } else if (functions.InList(s)) { - sc.ChangeState(SCE_APDL_FUNCTION); - } - sc.SetState(SCE_APDL_DEFAULT); - } - } else if (sc.state == SCE_APDL_OPERATOR) { - if (!IsAnOperator(static_cast(sc.ch))) { - sc.SetState(SCE_APDL_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_APDL_DEFAULT) { - if (sc.ch == '!' && sc.chNext == '!') { - sc.SetState(SCE_APDL_COMMENTBLOCK); - } else if (sc.ch == '!') { - sc.SetState(SCE_APDL_COMMENT); - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_APDL_NUMBER); - } else if (sc.ch == '\'' || sc.ch == '\"') { - sc.SetState(SCE_APDL_STRING); - stringStart = sc.ch; - } else if (IsAWordChar(sc.ch) || ((sc.ch == '*' || sc.ch == '/') && !isgraph(sc.chPrev))) { - sc.SetState(SCE_APDL_WORD); - } else if (IsAnOperator(static_cast(sc.ch))) { - sc.SetState(SCE_APDL_OPERATOR); - } - } - } - sc.Complete(); -} - -//------------------------------------------------------------------------------ -// 06-27-07 Sergio Lucato -// - Included code folding for Ansys APDL lexer -// - Copyied from LexBasic.cxx and modified for APDL -//------------------------------------------------------------------------------ - -/* Bits: - * 1 - whitespace - * 2 - operator - * 4 - identifier - * 8 - decimal digit - * 16 - hex digit - * 32 - bin digit - */ -static int character_classification[128] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 10, 6, - 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, - 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4, - 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0 -}; - -static bool IsSpace(int c) { - return c < 128 && (character_classification[c] & 1); -} - -static bool IsIdentifier(int c) { - return c < 128 && (character_classification[c] & 4); -} - -static int LowerCase(int c) -{ - if (c >= 'A' && c <= 'Z') - return 'a' + c - 'A'; - return c; -} - -static int CheckAPDLFoldPoint(char const *token, int &level) { - if (!strcmp(token, "*if") || - !strcmp(token, "*do") || - !strcmp(token, "*dowhile") ) { - level |= SC_FOLDLEVELHEADERFLAG; - return 1; - } - if (!strcmp(token, "*endif") || - !strcmp(token, "*enddo") ) { - return -1; - } - return 0; -} - -static void FoldAPDLDoc(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) { - - int line = styler.GetLine(startPos); - int level = styler.LevelAt(line); - int go = 0, done = 0; - int endPos = startPos + length; - char word[256]; - int wordlen = 0; - int i; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - // Scan for tokens at the start of the line (they may include - // whitespace, for tokens like "End Function" - for (i = startPos; i < endPos; i++) { - int c = styler.SafeGetCharAt(i); - if (!done && !go) { - if (wordlen) { // are we scanning a token already? - word[wordlen] = static_cast(LowerCase(c)); - if (!IsIdentifier(c)) { // done with token - word[wordlen] = '\0'; - go = CheckAPDLFoldPoint(word, level); - if (!go) { - // Treat any whitespace as single blank, for - // things like "End Function". - if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) { - word[wordlen] = ' '; - if (wordlen < 255) - wordlen++; - } - else // done with this line - done = 1; - } - } else if (wordlen < 255) { - wordlen++; - } - } else { // start scanning at first non-whitespace character - if (!IsSpace(c)) { - if (IsIdentifier(c)) { - word[0] = static_cast(LowerCase(c)); - wordlen = 1; - } else // done with this line - done = 1; - } - } - } - if (c == '\n') { // line end - if (!done && wordlen == 0 && foldCompact) // line was only space - level |= SC_FOLDLEVELWHITEFLAG; - if (level != styler.LevelAt(line)) - styler.SetLevel(line, level); - level += go; - line++; - // reset state - wordlen = 0; - level &= ~SC_FOLDLEVELHEADERFLAG; - level &= ~SC_FOLDLEVELWHITEFLAG; - go = 0; - done = 0; - } - } -} - -static const char * const apdlWordListDesc[] = { - "processors", - "commands", - "slashommands", - "starcommands", - "arguments", - "functions", - 0 -}; - -LexerModule lmAPDL(SCLEX_APDL, ColouriseAPDLDoc, "apdl", FoldAPDLDoc, apdlWordListDesc); +// Scintilla source code edit control +/** @file LexAPDL.cxx + ** Lexer for APDL. Based on the lexer for Assembler by The Black Horus. + ** By Hadar Raz. + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80 && (isalnum(ch) || ch == '_')); +} + +static inline bool IsAnOperator(char ch) { + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '^' || + ch == '[' || ch == ']' || ch == '<' || ch == '&' || + ch == '>' || ch == ',' || ch == '|' || ch == '~' || + ch == '$' || ch == ':' || ch == '%') + return true; + return false; +} + +static void ColouriseAPDLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + int stringStart = ' '; + + WordList &processors = *keywordlists[0]; + WordList &commands = *keywordlists[1]; + WordList &slashcommands = *keywordlists[2]; + WordList &starcommands = *keywordlists[3]; + WordList &arguments = *keywordlists[4]; + WordList &functions = *keywordlists[5]; + + // Do not leak onto next line + initStyle = SCE_APDL_DEFAULT; + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + // Determine if the current state should terminate. + if (sc.state == SCE_APDL_NUMBER) { + if (!(IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || + ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { + sc.SetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_COMMENTBLOCK) { + if (sc.atLineEnd) { + if (sc.ch == '\r') { + sc.Forward(); + } + sc.ForwardSetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_STRING) { + if (sc.atLineEnd) { + sc.SetState(SCE_APDL_DEFAULT); + } else if ((sc.ch == '\'' && stringStart == '\'') || (sc.ch == '\"' && stringStart == '\"')) { + sc.ForwardSetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_WORD) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (processors.InList(s)) { + sc.ChangeState(SCE_APDL_PROCESSOR); + } else if (slashcommands.InList(s)) { + sc.ChangeState(SCE_APDL_SLASHCOMMAND); + } else if (starcommands.InList(s)) { + sc.ChangeState(SCE_APDL_STARCOMMAND); + } else if (commands.InList(s)) { + sc.ChangeState(SCE_APDL_COMMAND); + } else if (arguments.InList(s)) { + sc.ChangeState(SCE_APDL_ARGUMENT); + } else if (functions.InList(s)) { + sc.ChangeState(SCE_APDL_FUNCTION); + } + sc.SetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_OPERATOR) { + if (!IsAnOperator(static_cast(sc.ch))) { + sc.SetState(SCE_APDL_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_APDL_DEFAULT) { + if (sc.ch == '!' && sc.chNext == '!') { + sc.SetState(SCE_APDL_COMMENTBLOCK); + } else if (sc.ch == '!') { + sc.SetState(SCE_APDL_COMMENT); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_APDL_NUMBER); + } else if (sc.ch == '\'' || sc.ch == '\"') { + sc.SetState(SCE_APDL_STRING); + stringStart = sc.ch; + } else if (IsAWordChar(sc.ch) || ((sc.ch == '*' || sc.ch == '/') && !isgraph(sc.chPrev))) { + sc.SetState(SCE_APDL_WORD); + } else if (IsAnOperator(static_cast(sc.ch))) { + sc.SetState(SCE_APDL_OPERATOR); + } + } + } + sc.Complete(); +} + +//------------------------------------------------------------------------------ +// 06-27-07 Sergio Lucato +// - Included code folding for Ansys APDL lexer +// - Copyied from LexBasic.cxx and modified for APDL +//------------------------------------------------------------------------------ + +/* Bits: + * 1 - whitespace + * 2 - operator + * 4 - identifier + * 8 - decimal digit + * 16 - hex digit + * 32 - bin digit + */ +static int character_classification[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 10, 6, + 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0 +}; + +static bool IsSpace(int c) { + return c < 128 && (character_classification[c] & 1); +} + +static bool IsIdentifier(int c) { + return c < 128 && (character_classification[c] & 4); +} + +static int LowerCase(int c) +{ + if (c >= 'A' && c <= 'Z') + return 'a' + c - 'A'; + return c; +} + +static int CheckAPDLFoldPoint(char const *token, int &level) { + if (!strcmp(token, "*if") || + !strcmp(token, "*do") || + !strcmp(token, "*dowhile") ) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "*endif") || + !strcmp(token, "*enddo") ) { + return -1; + } + return 0; +} + +static void FoldAPDLDoc(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) { + + int line = styler.GetLine(startPos); + int level = styler.LevelAt(line); + int go = 0, done = 0; + int endPos = startPos + length; + char word[256]; + int wordlen = 0; + int i; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + // Scan for tokens at the start of the line (they may include + // whitespace, for tokens like "End Function" + for (i = startPos; i < endPos; i++) { + int c = styler.SafeGetCharAt(i); + if (!done && !go) { + if (wordlen) { // are we scanning a token already? + word[wordlen] = static_cast(LowerCase(c)); + if (!IsIdentifier(c)) { // done with token + word[wordlen] = '\0'; + go = CheckAPDLFoldPoint(word, level); + if (!go) { + // Treat any whitespace as single blank, for + // things like "End Function". + if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) { + word[wordlen] = ' '; + if (wordlen < 255) + wordlen++; + } + else // done with this line + done = 1; + } + } else if (wordlen < 255) { + wordlen++; + } + } else { // start scanning at first non-whitespace character + if (!IsSpace(c)) { + if (IsIdentifier(c)) { + word[0] = static_cast(LowerCase(c)); + wordlen = 1; + } else // done with this line + done = 1; + } + } + } + if (c == '\n') { // line end + if (!done && wordlen == 0 && foldCompact) // line was only space + level |= SC_FOLDLEVELWHITEFLAG; + if (level != styler.LevelAt(line)) + styler.SetLevel(line, level); + level += go; + line++; + // reset state + wordlen = 0; + level &= ~SC_FOLDLEVELHEADERFLAG; + level &= ~SC_FOLDLEVELWHITEFLAG; + go = 0; + done = 0; + } + } +} + +static const char * const apdlWordListDesc[] = { + "processors", + "commands", + "slashommands", + "starcommands", + "arguments", + "functions", + 0 +}; + +LexerModule lmAPDL(SCLEX_APDL, ColouriseAPDLDoc, "apdl", FoldAPDLDoc, apdlWordListDesc); diff --git a/scintilla/lexers/LexASY.cxx b/ThirdLibs/scintilla/lexers/LexASY.cxx similarity index 96% rename from scintilla/lexers/LexASY.cxx rename to ThirdLibs/scintilla/lexers/LexASY.cxx index d58fb4ba..9e3470cd 100644 --- a/scintilla/lexers/LexASY.cxx +++ b/ThirdLibs/scintilla/lexers/LexASY.cxx @@ -1,271 +1,271 @@ -// Scintilla source code edit control -//Author: instanton (email: soft_share126com) -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static void ColouriseAsyDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - - CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); - - int visibleChars = 0; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.atLineStart) { - if (sc.state == SCE_ASY_STRING) { - sc.SetState(SCE_ASY_STRING); - } - visibleChars = 0; - } - - if (sc.ch == '\\') { - if (sc.chNext == '\n' || sc.chNext == '\r') { - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - sc.Forward(); - } -// continuationLine = true; - continue; - } - } - - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_ASY_OPERATOR: - sc.SetState(SCE_ASY_DEFAULT); - break; - case SCE_ASY_NUMBER: - if (!setWord.Contains(sc.ch)) { - sc.SetState(SCE_ASY_DEFAULT); - } - break; - case SCE_ASY_IDENTIFIER: - if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { - char s[1000]; - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_ASY_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_ASY_WORD2); - } - sc.SetState(SCE_ASY_DEFAULT); - } - break; - case SCE_ASY_COMMENT: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_ASY_DEFAULT); - } - break; - case SCE_ASY_COMMENTLINE: - if (sc.atLineStart) { - sc.SetState(SCE_ASY_DEFAULT); - } - break; - case SCE_ASY_STRING: - if (sc.atLineEnd) { - sc.ChangeState(SCE_ASY_STRINGEOL); - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_ASY_DEFAULT); - } - break; - case SCE_ASY_CHARACTER: - if (sc.atLineEnd) { - sc.ChangeState(SCE_ASY_STRINGEOL); - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_ASY_DEFAULT); - } - break; - } - - // Determine if a new state should be entered. - if (sc.state == SCE_ASY_DEFAULT) { - if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { - sc.SetState(SCE_ASY_IDENTIFIER); - } else if (sc.Match('/', '*')) { - sc.SetState(SCE_ASY_COMMENT); - sc.Forward(); // - } else if (sc.Match('/', '/')) { - sc.SetState(SCE_ASY_COMMENTLINE); - } else if (sc.ch == '\"') { - sc.SetState(SCE_ASY_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_ASY_CHARACTER); - } else if (sc.ch == '#' && visibleChars == 0) { - do { - sc.Forward(); - } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); - if (sc.atLineEnd) { - sc.SetState(SCE_ASY_DEFAULT); - } - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_ASY_OPERATOR); - } - } - - } - sc.Complete(); -} - -static bool IsAsyCommentStyle(int style) { - return style == SCE_ASY_COMMENT; -} - - -static inline bool isASYidentifier(int ch) { - return - ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ; -} - -static int ParseASYWord(unsigned int pos, Accessor &styler, char *word) -{ - int length=0; - char ch=styler.SafeGetCharAt(pos); - *word=0; - - while(isASYidentifier(ch) && length<100){ - word[length]=ch; - length++; - ch=styler.SafeGetCharAt(pos+length); - } - word[length]=0; - return length; -} - -static bool IsASYDrawingLine(int line, Accessor &styler) { - int pos = styler.LineStart(line); - int eol_pos = styler.LineStart(line + 1) - 1; - - int startpos = pos; - char buffer[100]=""; - - while (startpos 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelMinCurrent = levelCurrent; - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && IsAsyCommentStyle(style)) { - if (!IsAsyCommentStyle(stylePrev) && (stylePrev != SCE_ASY_COMMENTLINEDOC)) { - levelNext++; - } else if (!IsAsyCommentStyle(styleNext) && (styleNext != SCE_ASY_COMMENTLINEDOC) && !atEOL) { - levelNext--; - } - } - if (style == SCE_ASY_OPERATOR) { - if (ch == '{') { - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (ch == '}') { - levelNext--; - } - } - - if (atEOL && IsASYDrawingLine(lineCurrent, styler)){ - if (lineCurrent==0 && IsASYDrawingLine(lineCurrent + 1, styler)) - levelNext++; - else if (lineCurrent!=0 && !IsASYDrawingLine(lineCurrent - 1, styler) - && IsASYDrawingLine(lineCurrent + 1, styler) - ) - levelNext++; - else if (lineCurrent!=0 && IsASYDrawingLine(lineCurrent - 1, styler) && - !IsASYDrawingLine(lineCurrent+1, styler)) - levelNext--; - } - - if (atEOL) { - int levelUse = levelCurrent; - if (foldAtElse) { - levelUse = levelMinCurrent; - } - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - levelMinCurrent = levelCurrent; - visibleChars = 0; - } - if (!IsASpace(ch)) - visibleChars++; - } -} - -static const char * const asyWordLists[] = { - "Primary keywords and identifiers", - "Secondary keywords and identifiers", - 0, - }; - -LexerModule lmASY(SCLEX_ASYMPTOTE, ColouriseAsyDoc, "asy", FoldAsyDoc, asyWordLists); +// Scintilla source code edit control +//Author: instanton (email: soft_share126com) +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static void ColouriseAsyDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + + CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); + + int visibleChars = 0; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart) { + if (sc.state == SCE_ASY_STRING) { + sc.SetState(SCE_ASY_STRING); + } + visibleChars = 0; + } + + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } +// continuationLine = true; + continue; + } + } + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_ASY_OPERATOR: + sc.SetState(SCE_ASY_DEFAULT); + break; + case SCE_ASY_NUMBER: + if (!setWord.Contains(sc.ch)) { + sc.SetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_IDENTIFIER: + if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { + char s[1000]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_ASY_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_ASY_WORD2); + } + sc.SetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_ASY_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_CHARACTER: + if (sc.atLineEnd) { + sc.ChangeState(SCE_ASY_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_ASY_DEFAULT); + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_ASY_DEFAULT) { + if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { + sc.SetState(SCE_ASY_IDENTIFIER); + } else if (sc.Match('/', '*')) { + sc.SetState(SCE_ASY_COMMENT); + sc.Forward(); // + } else if (sc.Match('/', '/')) { + sc.SetState(SCE_ASY_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_ASY_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_ASY_CHARACTER); + } else if (sc.ch == '#' && visibleChars == 0) { + do { + sc.Forward(); + } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); + if (sc.atLineEnd) { + sc.SetState(SCE_ASY_DEFAULT); + } + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_ASY_OPERATOR); + } + } + + } + sc.Complete(); +} + +static bool IsAsyCommentStyle(int style) { + return style == SCE_ASY_COMMENT; +} + + +static inline bool isASYidentifier(int ch) { + return + ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ; +} + +static int ParseASYWord(unsigned int pos, Accessor &styler, char *word) +{ + int length=0; + char ch=styler.SafeGetCharAt(pos); + *word=0; + + while(isASYidentifier(ch) && length<100){ + word[length]=ch; + length++; + ch=styler.SafeGetCharAt(pos+length); + } + word[length]=0; + return length; +} + +static bool IsASYDrawingLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + + int startpos = pos; + char buffer[100]=""; + + while (startpos 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && IsAsyCommentStyle(style)) { + if (!IsAsyCommentStyle(stylePrev) && (stylePrev != SCE_ASY_COMMENTLINEDOC)) { + levelNext++; + } else if (!IsAsyCommentStyle(styleNext) && (styleNext != SCE_ASY_COMMENTLINEDOC) && !atEOL) { + levelNext--; + } + } + if (style == SCE_ASY_OPERATOR) { + if (ch == '{') { + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + + if (atEOL && IsASYDrawingLine(lineCurrent, styler)){ + if (lineCurrent==0 && IsASYDrawingLine(lineCurrent + 1, styler)) + levelNext++; + else if (lineCurrent!=0 && !IsASYDrawingLine(lineCurrent - 1, styler) + && IsASYDrawingLine(lineCurrent + 1, styler) + ) + levelNext++; + else if (lineCurrent!=0 && IsASYDrawingLine(lineCurrent - 1, styler) && + !IsASYDrawingLine(lineCurrent+1, styler)) + levelNext--; + } + + if (atEOL) { + int levelUse = levelCurrent; + if (foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + visibleChars = 0; + } + if (!IsASpace(ch)) + visibleChars++; + } +} + +static const char * const asyWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + 0, + }; + +LexerModule lmASY(SCLEX_ASYMPTOTE, ColouriseAsyDoc, "asy", FoldAsyDoc, asyWordLists); diff --git a/scintilla/lexers/LexAU3.cxx b/ThirdLibs/scintilla/lexers/LexAU3.cxx similarity index 96% rename from scintilla/lexers/LexAU3.cxx rename to ThirdLibs/scintilla/lexers/LexAU3.cxx index d09c52f9..e9ab7577 100644 --- a/scintilla/lexers/LexAU3.cxx +++ b/ThirdLibs/scintilla/lexers/LexAU3.cxx @@ -1,910 +1,910 @@ -// Scintilla source code edit control -// @file LexAU3.cxx -// Lexer for AutoIt3 http://www.hiddensoft.com/autoit3 -// by Jos van der Zande, jvdzande@yahoo.com -// -// Changes: -// March 28, 2004 - Added the standard Folding code -// April 21, 2004 - Added Preprosessor Table + Syntax Highlighting -// Fixed Number highlighting -// Changed default isoperator to IsAOperator to have a better match to AutoIt3 -// Fixed "#comments_start" -> "#comments-start" -// Fixed "#comments_end" -> "#comments-end" -// Fixed Sendkeys in Strings when not terminated with } -// Added support for Sendkey strings that have second parameter e.g. {UP 5} or {a down} -// April 26, 2004 - Fixed # pre-processor statement inside of comment block would invalidly change the color. -// Added logic for #include to treat the <> as string -// Added underscore to IsAOperator. -// May 17, 2004 - Changed the folding logic from indent to keyword folding. -// Added Folding logic for blocks of single-commentlines or commentblock. -// triggered by: fold.comment=1 -// Added Folding logic for preprocessor blocks triggered by fold.preprocessor=1 -// Added Special for #region - #endregion syntax highlight and folding. -// May 30, 2004 - Fixed issue with continuation lines on If statements. -// June 5, 2004 - Added comma to Operators for better readability. -// Added fold.compact support set with fold.compact=1 -// Changed folding inside of #cs-#ce. Default is no keyword folding inside comment blocks when fold.comment=1 -// it will now only happen when fold.comment=2. -// Sep 5, 2004 - Added logic to handle colourizing words on the last line. -// Typed Characters now show as "default" till they match any table. -// Oct 10, 2004 - Added logic to show Comments in "Special" directives. -// Nov 1, 2004 - Added better testing for Numbers supporting x and e notation. -// Nov 28, 2004 - Added logic to handle continuation lines for syntax highlighting. -// Jan 10, 2005 - Added Abbreviations Keyword used for expansion -// Mar 24, 2005 - Updated Abbreviations Keywords to fix when followed by Operator. -// Apr 18, 2005 - Updated #CE/#Comment-End logic to take a linecomment ";" into account -// - Added folding support for With...EndWith -// - Added support for a DOT in variable names -// - Fixed Underscore in CommentBlock -// May 23, 2005 - Fixed the SentKey lexing in case of a missing } -// Aug 11, 2005 - Fixed possible bug with s_save length > 100. -// Aug 23, 2005 - Added Switch/endswitch support to the folding logic. -// Sep 27, 2005 - Fixed the SentKey lexing logic in case of multiple sentkeys. -// Mar 12, 2006 - Fixed issue with <> coloring as String in stead of Operator in rare occasions. -// Apr 8, 2006 - Added support for AutoIt3 Standard UDF library (SCE_AU3_UDF) -// Mar 9, 2007 - Fixed bug with + following a String getting the wrong Color. -// Jun 20, 2007 - Fixed Commentblock issue when LF's are used as EOL. -// Jul 26, 2007 - Fixed #endregion undetected bug. -// -// Copyright for Scintilla: 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. -// Scintilla source code edit control - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsTypeCharacter(const int ch) -{ - return ch == '$'; -} -static inline bool IsAWordChar(const int ch) -{ - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAWordStart(const int ch) -{ - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$' || ch == '.'); -} - -static inline bool IsAOperator(char ch) { - if (isascii(ch) && isalnum(ch)) - return false; - if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || - ch == '&' || ch == '^' || ch == '=' || ch == '<' || ch == '>' || - ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == ',' ) - return true; - return false; -} - -/////////////////////////////////////////////////////////////////////////////// -// GetSendKey() filters the portion before and after a/multiple space(s) -// and return the first portion to be looked-up in the table -// also check if the second portion is valid... (up,down.on.off,toggle or a number) -/////////////////////////////////////////////////////////////////////////////// - -static int GetSendKey(const char *szLine, char *szKey) -{ - int nFlag = 0; - int nStartFound = 0; - int nKeyPos = 0; - int nSpecPos= 0; - int nSpecNum= 1; - int nPos = 0; - char cTemp; - char szSpecial[100]; - - // split the portion of the sendkey in the part before and after the spaces - while ( ( (cTemp = szLine[nPos]) != '\0')) - { - // skip leading Ctrl/Shift/Alt state - if (cTemp == '{') { - nStartFound = 1; - } - // - if (nStartFound == 1) { - if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space - { - nFlag = 1; - // Add } to the end of the first bit for table lookup later. - szKey[nKeyPos++] = '}'; - } - else if (cTemp == ' ') - { - // skip other spaces - } - else if (nFlag == 0) - { - // save first portion into var till space or } is hit - szKey[nKeyPos++] = cTemp; - } - else if ((nFlag == 1) && (cTemp != '}')) - { - // Save second portion into var... - szSpecial[nSpecPos++] = cTemp; - // check if Second portion is all numbers for repeat fuction - if (isdigit(cTemp) == false) {nSpecNum = 0;} - } - } - nPos++; // skip to next char - - } // End While - - - // Check if the second portion is either a number or one of these keywords - szKey[nKeyPos] = '\0'; - szSpecial[nSpecPos] = '\0'; - if (strcmp(szSpecial,"down")== 0 || strcmp(szSpecial,"up")== 0 || - strcmp(szSpecial,"on")== 0 || strcmp(szSpecial,"off")== 0 || - strcmp(szSpecial,"toggle")== 0 || nSpecNum == 1 ) - { - nFlag = 0; - } - else - { - nFlag = 1; - } - return nFlag; // 1 is bad, 0 is good - -} // GetSendKey() - -// -// Routine to check the last "none comment" character on a line to see if its a continuation -// -static bool IsContinuationLine(unsigned int szLine, Accessor &styler) -{ - int nsPos = styler.LineStart(szLine); - int nePos = styler.LineStart(szLine+1) - 2; - //int stylech = styler.StyleAt(nsPos); - while (nsPos < nePos) - { - //stylech = styler.StyleAt(nePos); - int stylech = styler.StyleAt(nsPos); - if (!(stylech == SCE_AU3_COMMENT)) { - char ch = styler.SafeGetCharAt(nePos); - if (!isspacechar(ch)) { - if (ch == '_') - return true; - else - return false; - } - } - nePos--; // skip to next char - } // End While - return false; -} // IsContinuationLine() - -// -// syntax highlighting logic -static void ColouriseAU3Doc(unsigned int startPos, - int length, int initStyle, - WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - WordList &keywords6 = *keywordlists[5]; - WordList &keywords7 = *keywordlists[6]; - WordList &keywords8 = *keywordlists[7]; - // find the first previous line without continuation character at the end - int lineCurrent = styler.GetLine(startPos); - int s_startPos = startPos; - // When not inside a Block comment: find First line without _ - if (!(initStyle==SCE_AU3_COMMENTBLOCK)) { - while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || - (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); // get start position - initStyle = 0; // reset the start style to 0 - } - } - // Set the new length to include it from the start and set the start position - length = length + s_startPos - startPos; // correct the total length to process - styler.StartAt(startPos); - - StyleContext sc(startPos, length, initStyle, styler); - char si; // string indicator "=1 '=2 - char ni; // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 Enot=3 - char ci; // comment indicator 0=not linecomment(;) - char s_save[100]; - si=0; - ni=0; - ci=0; - //$$$ - for (; sc.More(); sc.Forward()) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - // ********************************************** - // save the total current word for eof processing - if (IsAWordChar(sc.ch) || sc.ch == '}') - { - strcpy(s_save,s); - int tp = static_cast(strlen(s_save)); - if (tp < 99) { - s_save[tp] = static_cast(tolower(sc.ch)); - s_save[tp+1] = '\0'; - } - } - // ********************************************** - // - switch (sc.state) - { - case SCE_AU3_COMMENTBLOCK: - { - //Reset at line end - if (sc.atLineEnd) { - ci=0; - if (strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0) { - if (sc.atLineEnd) - sc.SetState(SCE_AU3_DEFAULT); - else - sc.SetState(SCE_AU3_COMMENTBLOCK); - } - break; - } - //skip rest of line when a ; is encountered - if (sc.chPrev == ';') { - ci=2; - sc.SetState(SCE_AU3_COMMENTBLOCK); - } - // skip rest of the line - if (ci==2) - break; - // check when first character is detected on the line - if (ci==0) { - if (IsAWordStart(static_cast(sc.ch)) || IsAOperator(static_cast(sc.ch))) { - ci=1; - sc.SetState(SCE_AU3_COMMENTBLOCK); - } - break; - } - if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments") == 0))) { - if ((strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0)) - sc.SetState(SCE_AU3_COMMENT); // set to comment line for the rest of the line - else - ci=2; // line doesn't begin with #CE so skip the rest of the line - } - break; - } - case SCE_AU3_COMMENT: - { - if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} - break; - } - case SCE_AU3_OPERATOR: - { - // check if its a COMobject - if (sc.chPrev == '.' && IsAWordChar(sc.ch)) { - sc.SetState(SCE_AU3_COMOBJ); - } - else { - sc.SetState(SCE_AU3_DEFAULT); - } - break; - } - case SCE_AU3_SPECIAL: - { - if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);} - if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} - break; - } - case SCE_AU3_KEYWORD: - { - if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && (strcmp(s, "#comments") == 0 || strcmp(s, "#include") == 0)))) - { - if (!IsTypeCharacter(sc.ch)) - { - if (strcmp(s, "#cs")== 0 || strcmp(s, "#comments-start")== 0 ) - { - sc.ChangeState(SCE_AU3_COMMENTBLOCK); - sc.SetState(SCE_AU3_COMMENTBLOCK); - break; - } - else if (keywords.InList(s)) { - sc.ChangeState(SCE_AU3_KEYWORD); - sc.SetState(SCE_AU3_DEFAULT); - } - else if (keywords2.InList(s)) { - sc.ChangeState(SCE_AU3_FUNCTION); - sc.SetState(SCE_AU3_DEFAULT); - } - else if (keywords3.InList(s)) { - sc.ChangeState(SCE_AU3_MACRO); - sc.SetState(SCE_AU3_DEFAULT); - } - else if (keywords5.InList(s)) { - sc.ChangeState(SCE_AU3_PREPROCESSOR); - sc.SetState(SCE_AU3_DEFAULT); - if (strcmp(s, "#include")== 0) - { - si = 3; // use to determine string start for #inlude <> - } - } - else if (keywords6.InList(s)) { - sc.ChangeState(SCE_AU3_SPECIAL); - sc.SetState(SCE_AU3_SPECIAL); - } - else if ((keywords7.InList(s)) && (!IsAOperator(static_cast(sc.ch)))) { - sc.ChangeState(SCE_AU3_EXPAND); - sc.SetState(SCE_AU3_DEFAULT); - } - else if (keywords8.InList(s)) { - sc.ChangeState(SCE_AU3_UDF); - sc.SetState(SCE_AU3_DEFAULT); - } - else if (strcmp(s, "_") == 0) { - sc.ChangeState(SCE_AU3_OPERATOR); - sc.SetState(SCE_AU3_DEFAULT); - } - else if (!IsAWordChar(sc.ch)) { - sc.ChangeState(SCE_AU3_DEFAULT); - sc.SetState(SCE_AU3_DEFAULT); - } - } - } - if (sc.atLineEnd) { - sc.SetState(SCE_AU3_DEFAULT);} - break; - } - case SCE_AU3_NUMBER: - { - // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 E-not=3 - // - // test for Hex notation - if (strcmp(s, "0") == 0 && (sc.ch == 'x' || sc.ch == 'X') && ni == 0) - { - ni = 2; - break; - } - // test for E notation - if (IsADigit(sc.chPrev) && (sc.ch == 'e' || sc.ch == 'E') && ni <= 1) - { - ni = 3; - break; - } - // Allow Hex characters inside hex numeric strings - if ((ni == 2) && - (sc.ch == 'a' || sc.ch == 'b' || sc.ch == 'c' || sc.ch == 'd' || sc.ch == 'e' || sc.ch == 'f' || - sc.ch == 'A' || sc.ch == 'B' || sc.ch == 'C' || sc.ch == 'D' || sc.ch == 'E' || sc.ch == 'F' )) - { - break; - } - // test for 1 dec point only - if (sc.ch == '.') - { - if (ni==0) - { - ni=1; - } - else - { - ni=9; - } - break; - } - // end of numeric string ? - if (!(IsADigit(sc.ch))) - { - if (ni==9) - { - sc.ChangeState(SCE_AU3_DEFAULT); - } - sc.SetState(SCE_AU3_DEFAULT); - } - break; - } - case SCE_AU3_VARIABLE: - { - // Check if its a COMObject - if (sc.ch == '.' && !IsADigit(sc.chNext)) { - sc.SetState(SCE_AU3_OPERATOR); - } - else if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_AU3_DEFAULT); - } - break; - } - case SCE_AU3_COMOBJ: - { - if (!(IsAWordChar(sc.ch))) { - sc.SetState(SCE_AU3_DEFAULT); - } - break; - } - case SCE_AU3_STRING: - { - // check for " to end a double qouted string or - // check for ' to end a single qouted string - if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'') || (si == 3 && sc.ch == '>')) - { - sc.ForwardSetState(SCE_AU3_DEFAULT); - si=0; - break; - } - if (sc.atLineEnd) - { - si=0; - // at line end and not found a continuation char then reset to default - int lineCurrent = styler.GetLine(sc.currentPos); - if (!IsContinuationLine(lineCurrent,styler)) - { - sc.SetState(SCE_AU3_DEFAULT); - break; - } - } - // find Sendkeys in a STRING - if (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ) { - sc.SetState(SCE_AU3_SENT);} - break; - } - - case SCE_AU3_SENT: - { - // Send key string ended - if (sc.chPrev == '}' && sc.ch != '}') - { - // set color to SENDKEY when valid sendkey .. else set back to regular string - char sk[100]; - // split {111 222} and return {111} and check if 222 is valid. - // if return code = 1 then invalid 222 so must be string - if (GetSendKey(s,sk)) - { - sc.ChangeState(SCE_AU3_STRING); - } - // if single char between {?} then its ok as sendkey for a single character - else if (strlen(sk) == 3) - { - sc.ChangeState(SCE_AU3_SENT); - } - // if sendkey {111} is in table then ok as sendkey - else if (keywords4.InList(sk)) - { - sc.ChangeState(SCE_AU3_SENT); - } - else - { - sc.ChangeState(SCE_AU3_STRING); - } - sc.SetState(SCE_AU3_STRING); - } - else - { - // check if the start is a valid SendKey start - int nPos = 0; - int nState = 1; - char cTemp; - while (!(nState == 2) && ((cTemp = s[nPos]) != '\0')) - { - if (cTemp == '{' && nState == 1) - { - nState = 2; - } - if (nState == 1 && !(cTemp == '+' || cTemp == '!' || cTemp == '^' || cTemp == '#' )) - { - nState = 0; - } - nPos++; - } - //Verify characters infront of { ... if not assume regular string - if (nState == 1 && (!(sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ))) { - sc.ChangeState(SCE_AU3_STRING); - sc.SetState(SCE_AU3_STRING); - } - // If invalid character found then assume its a regular string - if (nState == 0) { - sc.ChangeState(SCE_AU3_STRING); - sc.SetState(SCE_AU3_STRING); - } - } - // check if next portion is again a sendkey - if (sc.atLineEnd) - { - sc.ChangeState(SCE_AU3_STRING); - sc.SetState(SCE_AU3_DEFAULT); - si = 0; // reset string indicator - } - //* check in next characters following a sentkey are again a sent key - // Need this test incase of 2 sentkeys like {F1}{ENTER} but not detect {{} - if (sc.state == SCE_AU3_STRING && (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' )) { - sc.SetState(SCE_AU3_SENT);} - // check to see if the string ended... - // Sendkey string isn't complete but the string ended.... - if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'')) - { - sc.ChangeState(SCE_AU3_STRING); - sc.ForwardSetState(SCE_AU3_DEFAULT); - } - break; - } - } //switch (sc.state) - - // Determine if a new state should be entered: - - if (sc.state == SCE_AU3_DEFAULT) - { - if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);} - else if (sc.ch == '#') {sc.SetState(SCE_AU3_KEYWORD);} - else if (sc.ch == '$') {sc.SetState(SCE_AU3_VARIABLE);} - else if (sc.ch == '.' && !IsADigit(sc.chNext)) {sc.SetState(SCE_AU3_OPERATOR);} - else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);} - //else if (sc.ch == '_') {sc.SetState(SCE_AU3_KEYWORD);} - else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);} // string after #include - else if (sc.ch == '\"') { - sc.SetState(SCE_AU3_STRING); - si = 1; } - else if (sc.ch == '\'') { - sc.SetState(SCE_AU3_STRING); - si = 2; } - else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) - { - sc.SetState(SCE_AU3_NUMBER); - ni = 0; - } - else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);} - else if (IsAOperator(static_cast(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);} - else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} - } - } //for (; sc.More(); sc.Forward()) - - //************************************* - // Colourize the last word correctly - //************************************* - if (sc.state == SCE_AU3_KEYWORD) - { - if (strcmp(s_save, "#cs")== 0 || strcmp(s_save, "#comments-start")== 0 ) - { - sc.ChangeState(SCE_AU3_COMMENTBLOCK); - sc.SetState(SCE_AU3_COMMENTBLOCK); - } - else if (keywords.InList(s_save)) { - sc.ChangeState(SCE_AU3_KEYWORD); - sc.SetState(SCE_AU3_KEYWORD); - } - else if (keywords2.InList(s_save)) { - sc.ChangeState(SCE_AU3_FUNCTION); - sc.SetState(SCE_AU3_FUNCTION); - } - else if (keywords3.InList(s_save)) { - sc.ChangeState(SCE_AU3_MACRO); - sc.SetState(SCE_AU3_MACRO); - } - else if (keywords5.InList(s_save)) { - sc.ChangeState(SCE_AU3_PREPROCESSOR); - sc.SetState(SCE_AU3_PREPROCESSOR); - } - else if (keywords6.InList(s_save)) { - sc.ChangeState(SCE_AU3_SPECIAL); - sc.SetState(SCE_AU3_SPECIAL); - } - else if (keywords7.InList(s_save) && sc.atLineEnd) { - sc.ChangeState(SCE_AU3_EXPAND); - sc.SetState(SCE_AU3_EXPAND); - } - else if (keywords8.InList(s_save)) { - sc.ChangeState(SCE_AU3_UDF); - sc.SetState(SCE_AU3_UDF); - } - else { - sc.ChangeState(SCE_AU3_DEFAULT); - sc.SetState(SCE_AU3_DEFAULT); - } - } - if (sc.state == SCE_AU3_SENT) - { - // Send key string ended - if (sc.chPrev == '}' && sc.ch != '}') - { - // set color to SENDKEY when valid sendkey .. else set back to regular string - char sk[100]; - // split {111 222} and return {111} and check if 222 is valid. - // if return code = 1 then invalid 222 so must be string - if (GetSendKey(s_save,sk)) - { - sc.ChangeState(SCE_AU3_STRING); - } - // if single char between {?} then its ok as sendkey for a single character - else if (strlen(sk) == 3) - { - sc.ChangeState(SCE_AU3_SENT); - } - // if sendkey {111} is in table then ok as sendkey - else if (keywords4.InList(sk)) - { - sc.ChangeState(SCE_AU3_SENT); - } - else - { - sc.ChangeState(SCE_AU3_STRING); - } - sc.SetState(SCE_AU3_STRING); - } - // check if next portion is again a sendkey - if (sc.atLineEnd) - { - sc.ChangeState(SCE_AU3_STRING); - sc.SetState(SCE_AU3_DEFAULT); - } - } - //************************************* - sc.Complete(); -} - -// -static bool IsStreamCommentStyle(int style) { - return style == SCE_AU3_COMMENT || style == SCE_AU3_COMMENTBLOCK; -} - -// -// Routine to find first none space on the current line and return its Style -// needed for comment lines not starting on pos 1 -static int GetStyleFirstWord(unsigned int szLine, Accessor &styler) -{ - int nsPos = styler.LineStart(szLine); - int nePos = styler.LineStart(szLine+1) - 1; - while (isspacechar(styler.SafeGetCharAt(nsPos)) && nsPos < nePos) - { - nsPos++; // skip to next char - - } // End While - return styler.StyleAt(nsPos); - -} // GetStyleFirstWord() - - -// -static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) -{ - int endPos = startPos + length; - // get settings from the config files for folding comments and preprocessor lines - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldInComment = styler.GetPropertyInt("fold.comment") == 2; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldpreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; - // Backtrack to previous line in case need to fix its fold status - int lineCurrent = styler.GetLine(startPos); - if (startPos > 0) { - if (lineCurrent > 0) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); - } - } - // vars for style of previous/current/next lines - int style = GetStyleFirstWord(lineCurrent,styler); - int stylePrev = 0; - // find the first previous line without continuation character at the end - while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || - (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); - } - if (lineCurrent > 0) { - stylePrev = GetStyleFirstWord(lineCurrent-1,styler); - } - // vars for getting first word to check for keywords - bool FirstWordStart = false; - bool FirstWordEnd = false; - char szKeyword[11]=""; - int szKeywordlen = 0; - char szThen[5]=""; - int szThenlen = 0; - bool ThenFoundLast = false; - // var for indentlevel - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelNext = levelCurrent; - // - int visibleChars = 0; - char chNext = styler.SafeGetCharAt(startPos); - char chPrev = ' '; - // - for (int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - if (IsAWordChar(ch)) { - visibleChars++; - } - // get the syle for the current character neede to check in comment - int stylech = styler.StyleAt(i); - // get first word for the line for indent check max 9 characters - if (FirstWordStart && (!(FirstWordEnd))) { - if (!IsAWordChar(ch)) { - FirstWordEnd = true; - szKeyword[szKeywordlen] = '\0'; - } - else { - if (szKeywordlen < 10) { - szKeyword[szKeywordlen++] = static_cast(tolower(ch)); - } - } - } - // start the capture of the first word - if (!(FirstWordStart)) { - if (IsAWordChar(ch) || IsAWordStart(ch) || ch == ';') { - FirstWordStart = true; - szKeyword[szKeywordlen++] = static_cast(tolower(ch)); - } - } - // only process this logic when not in comment section - if (!(stylech == SCE_AU3_COMMENT)) { - if (ThenFoundLast) { - if (IsAWordChar(ch)) { - ThenFoundLast = false; - } - } - // find out if the word "then" is the last on a "if" line - if (FirstWordEnd && strcmp(szKeyword,"if") == 0) { - if (szThenlen == 4) { - szThen[0] = szThen[1]; - szThen[1] = szThen[2]; - szThen[2] = szThen[3]; - szThen[3] = static_cast(tolower(ch)); - if (strcmp(szThen,"then") == 0 ) { - ThenFoundLast = true; - } - } - else { - szThen[szThenlen++] = static_cast(tolower(ch)); - if (szThenlen == 5) { - szThen[4] = '\0'; - } - } - } - } - // End of Line found so process the information - if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { - // ************************** - // Folding logic for Keywords - // ************************** - // if a keyword is found on the current line and the line doesn't end with _ (continuation) - // and we are not inside a commentblock. - if (szKeywordlen > 0 && (!(chPrev == '_')) && - ((!(IsStreamCommentStyle(style)) || foldInComment)) ) { - szKeyword[szKeywordlen] = '\0'; - // only fold "if" last keyword is "then" (else its a one line if) - if (strcmp(szKeyword,"if") == 0 && ThenFoundLast) { - levelNext++; - } - // create new fold for these words - if (strcmp(szKeyword,"do") == 0 || strcmp(szKeyword,"for") == 0 || - strcmp(szKeyword,"func") == 0 || strcmp(szKeyword,"while") == 0|| - strcmp(szKeyword,"with") == 0 || strcmp(szKeyword,"#region") == 0 ) { - levelNext++; - } - // create double Fold for select&switch because Case will subtract one of the current level - if (strcmp(szKeyword,"select") == 0 || strcmp(szKeyword,"switch") == 0) { - levelNext++; - levelNext++; - } - // end the fold for these words before the current line - if (strcmp(szKeyword,"endfunc") == 0 || strcmp(szKeyword,"endif") == 0 || - strcmp(szKeyword,"next") == 0 || strcmp(szKeyword,"until") == 0 || - strcmp(szKeyword,"endwith") == 0 ||strcmp(szKeyword,"wend") == 0){ - levelNext--; - levelCurrent--; - } - // end the fold for these words before the current line and Start new fold - if (strcmp(szKeyword,"case") == 0 || strcmp(szKeyword,"else") == 0 || - strcmp(szKeyword,"elseif") == 0 ) { - levelCurrent--; - } - // end the double fold for this word before the current line - if (strcmp(szKeyword,"endselect") == 0 || strcmp(szKeyword,"endswitch") == 0 ) { - levelNext--; - levelNext--; - levelCurrent--; - levelCurrent--; - } - // end the fold for these words on the current line - if (strcmp(szKeyword,"#endregion") == 0 ) { - levelNext--; - } - } - // Preprocessor and Comment folding - int styleNext = GetStyleFirstWord(lineCurrent + 1,styler); - // ************************************* - // Folding logic for preprocessor blocks - // ************************************* - // process preprosessor line - if (foldpreprocessor && style == SCE_AU3_PREPROCESSOR) { - if (!(stylePrev == SCE_AU3_PREPROCESSOR) && (styleNext == SCE_AU3_PREPROCESSOR)) { - levelNext++; - } - // fold till the last line for normal comment lines - else if (stylePrev == SCE_AU3_PREPROCESSOR && !(styleNext == SCE_AU3_PREPROCESSOR)) { - levelNext--; - } - } - // ********************************* - // Folding logic for Comment blocks - // ********************************* - if (foldComment && IsStreamCommentStyle(style)) { - // Start of a comment block - if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) { - levelNext++; - } - // fold till the last line for normal comment lines - else if (IsStreamCommentStyle(stylePrev) - && !(styleNext == SCE_AU3_COMMENT) - && stylePrev == SCE_AU3_COMMENT - && style == SCE_AU3_COMMENT) { - levelNext--; - } - // fold till the one but last line for Blockcomment lines - else if (IsStreamCommentStyle(stylePrev) - && !(styleNext == SCE_AU3_COMMENTBLOCK) - && style == SCE_AU3_COMMENTBLOCK) { - levelNext--; - levelCurrent--; - } - } - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - // reset values for the next line - lineCurrent++; - stylePrev = style; - style = styleNext; - levelCurrent = levelNext; - visibleChars = 0; - // if the last character is an Underscore then don't reset since the line continues on the next line. - if (!(chPrev == '_')) { - szKeywordlen = 0; - szThenlen = 0; - FirstWordStart = false; - FirstWordEnd = false; - ThenFoundLast = false; - } - } - // save the last processed character - if (!isspacechar(ch)) { - chPrev = ch; - visibleChars++; - } - } -} - - -// - -static const char * const AU3WordLists[] = { - "#autoit keywords", - "#autoit functions", - "#autoit macros", - "#autoit Sent keys", - "#autoit Pre-processors", - "#autoit Special", - "#autoit Expand", - "#autoit UDF", - 0 -}; -LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3", FoldAU3Doc , AU3WordLists); +// Scintilla source code edit control +// @file LexAU3.cxx +// Lexer for AutoIt3 http://www.hiddensoft.com/autoit3 +// by Jos van der Zande, jvdzande@yahoo.com +// +// Changes: +// March 28, 2004 - Added the standard Folding code +// April 21, 2004 - Added Preprosessor Table + Syntax Highlighting +// Fixed Number highlighting +// Changed default isoperator to IsAOperator to have a better match to AutoIt3 +// Fixed "#comments_start" -> "#comments-start" +// Fixed "#comments_end" -> "#comments-end" +// Fixed Sendkeys in Strings when not terminated with } +// Added support for Sendkey strings that have second parameter e.g. {UP 5} or {a down} +// April 26, 2004 - Fixed # pre-processor statement inside of comment block would invalidly change the color. +// Added logic for #include to treat the <> as string +// Added underscore to IsAOperator. +// May 17, 2004 - Changed the folding logic from indent to keyword folding. +// Added Folding logic for blocks of single-commentlines or commentblock. +// triggered by: fold.comment=1 +// Added Folding logic for preprocessor blocks triggered by fold.preprocessor=1 +// Added Special for #region - #endregion syntax highlight and folding. +// May 30, 2004 - Fixed issue with continuation lines on If statements. +// June 5, 2004 - Added comma to Operators for better readability. +// Added fold.compact support set with fold.compact=1 +// Changed folding inside of #cs-#ce. Default is no keyword folding inside comment blocks when fold.comment=1 +// it will now only happen when fold.comment=2. +// Sep 5, 2004 - Added logic to handle colourizing words on the last line. +// Typed Characters now show as "default" till they match any table. +// Oct 10, 2004 - Added logic to show Comments in "Special" directives. +// Nov 1, 2004 - Added better testing for Numbers supporting x and e notation. +// Nov 28, 2004 - Added logic to handle continuation lines for syntax highlighting. +// Jan 10, 2005 - Added Abbreviations Keyword used for expansion +// Mar 24, 2005 - Updated Abbreviations Keywords to fix when followed by Operator. +// Apr 18, 2005 - Updated #CE/#Comment-End logic to take a linecomment ";" into account +// - Added folding support for With...EndWith +// - Added support for a DOT in variable names +// - Fixed Underscore in CommentBlock +// May 23, 2005 - Fixed the SentKey lexing in case of a missing } +// Aug 11, 2005 - Fixed possible bug with s_save length > 100. +// Aug 23, 2005 - Added Switch/endswitch support to the folding logic. +// Sep 27, 2005 - Fixed the SentKey lexing logic in case of multiple sentkeys. +// Mar 12, 2006 - Fixed issue with <> coloring as String in stead of Operator in rare occasions. +// Apr 8, 2006 - Added support for AutoIt3 Standard UDF library (SCE_AU3_UDF) +// Mar 9, 2007 - Fixed bug with + following a String getting the wrong Color. +// Jun 20, 2007 - Fixed Commentblock issue when LF's are used as EOL. +// Jul 26, 2007 - Fixed #endregion undetected bug. +// +// Copyright for Scintilla: 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. +// Scintilla source code edit control + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsTypeCharacter(const int ch) +{ + return ch == '$'; +} +static inline bool IsAWordChar(const int ch) +{ + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(const int ch) +{ + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$' || ch == '.'); +} + +static inline bool IsAOperator(char ch) { + if (isascii(ch) && isalnum(ch)) + return false; + if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || + ch == '&' || ch == '^' || ch == '=' || ch == '<' || ch == '>' || + ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == ',' ) + return true; + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetSendKey() filters the portion before and after a/multiple space(s) +// and return the first portion to be looked-up in the table +// also check if the second portion is valid... (up,down.on.off,toggle or a number) +/////////////////////////////////////////////////////////////////////////////// + +static int GetSendKey(const char *szLine, char *szKey) +{ + int nFlag = 0; + int nStartFound = 0; + int nKeyPos = 0; + int nSpecPos= 0; + int nSpecNum= 1; + int nPos = 0; + char cTemp; + char szSpecial[100]; + + // split the portion of the sendkey in the part before and after the spaces + while ( ( (cTemp = szLine[nPos]) != '\0')) + { + // skip leading Ctrl/Shift/Alt state + if (cTemp == '{') { + nStartFound = 1; + } + // + if (nStartFound == 1) { + if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space + { + nFlag = 1; + // Add } to the end of the first bit for table lookup later. + szKey[nKeyPos++] = '}'; + } + else if (cTemp == ' ') + { + // skip other spaces + } + else if (nFlag == 0) + { + // save first portion into var till space or } is hit + szKey[nKeyPos++] = cTemp; + } + else if ((nFlag == 1) && (cTemp != '}')) + { + // Save second portion into var... + szSpecial[nSpecPos++] = cTemp; + // check if Second portion is all numbers for repeat fuction + if (isdigit(cTemp) == false) {nSpecNum = 0;} + } + } + nPos++; // skip to next char + + } // End While + + + // Check if the second portion is either a number or one of these keywords + szKey[nKeyPos] = '\0'; + szSpecial[nSpecPos] = '\0'; + if (strcmp(szSpecial,"down")== 0 || strcmp(szSpecial,"up")== 0 || + strcmp(szSpecial,"on")== 0 || strcmp(szSpecial,"off")== 0 || + strcmp(szSpecial,"toggle")== 0 || nSpecNum == 1 ) + { + nFlag = 0; + } + else + { + nFlag = 1; + } + return nFlag; // 1 is bad, 0 is good + +} // GetSendKey() + +// +// Routine to check the last "none comment" character on a line to see if its a continuation +// +static bool IsContinuationLine(unsigned int szLine, Accessor &styler) +{ + int nsPos = styler.LineStart(szLine); + int nePos = styler.LineStart(szLine+1) - 2; + //int stylech = styler.StyleAt(nsPos); + while (nsPos < nePos) + { + //stylech = styler.StyleAt(nePos); + int stylech = styler.StyleAt(nsPos); + if (!(stylech == SCE_AU3_COMMENT)) { + char ch = styler.SafeGetCharAt(nePos); + if (!isspacechar(ch)) { + if (ch == '_') + return true; + else + return false; + } + } + nePos--; // skip to next char + } // End While + return false; +} // IsContinuationLine() + +// +// syntax highlighting logic +static void ColouriseAU3Doc(unsigned int startPos, + int length, int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; + WordList &keywords7 = *keywordlists[6]; + WordList &keywords8 = *keywordlists[7]; + // find the first previous line without continuation character at the end + int lineCurrent = styler.GetLine(startPos); + int s_startPos = startPos; + // When not inside a Block comment: find First line without _ + if (!(initStyle==SCE_AU3_COMMENTBLOCK)) { + while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || + (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); // get start position + initStyle = 0; // reset the start style to 0 + } + } + // Set the new length to include it from the start and set the start position + length = length + s_startPos - startPos; // correct the total length to process + styler.StartAt(startPos); + + StyleContext sc(startPos, length, initStyle, styler); + char si; // string indicator "=1 '=2 + char ni; // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 Enot=3 + char ci; // comment indicator 0=not linecomment(;) + char s_save[100]; + si=0; + ni=0; + ci=0; + //$$$ + for (; sc.More(); sc.Forward()) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + // ********************************************** + // save the total current word for eof processing + if (IsAWordChar(sc.ch) || sc.ch == '}') + { + strcpy(s_save,s); + int tp = static_cast(strlen(s_save)); + if (tp < 99) { + s_save[tp] = static_cast(tolower(sc.ch)); + s_save[tp+1] = '\0'; + } + } + // ********************************************** + // + switch (sc.state) + { + case SCE_AU3_COMMENTBLOCK: + { + //Reset at line end + if (sc.atLineEnd) { + ci=0; + if (strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0) { + if (sc.atLineEnd) + sc.SetState(SCE_AU3_DEFAULT); + else + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + break; + } + //skip rest of line when a ; is encountered + if (sc.chPrev == ';') { + ci=2; + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + // skip rest of the line + if (ci==2) + break; + // check when first character is detected on the line + if (ci==0) { + if (IsAWordStart(static_cast(sc.ch)) || IsAOperator(static_cast(sc.ch))) { + ci=1; + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + break; + } + if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments") == 0))) { + if ((strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0)) + sc.SetState(SCE_AU3_COMMENT); // set to comment line for the rest of the line + else + ci=2; // line doesn't begin with #CE so skip the rest of the line + } + break; + } + case SCE_AU3_COMMENT: + { + if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} + break; + } + case SCE_AU3_OPERATOR: + { + // check if its a COMobject + if (sc.chPrev == '.' && IsAWordChar(sc.ch)) { + sc.SetState(SCE_AU3_COMOBJ); + } + else { + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_SPECIAL: + { + if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);} + if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} + break; + } + case SCE_AU3_KEYWORD: + { + if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && (strcmp(s, "#comments") == 0 || strcmp(s, "#include") == 0)))) + { + if (!IsTypeCharacter(sc.ch)) + { + if (strcmp(s, "#cs")== 0 || strcmp(s, "#comments-start")== 0 ) + { + sc.ChangeState(SCE_AU3_COMMENTBLOCK); + sc.SetState(SCE_AU3_COMMENTBLOCK); + break; + } + else if (keywords.InList(s)) { + sc.ChangeState(SCE_AU3_KEYWORD); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords2.InList(s)) { + sc.ChangeState(SCE_AU3_FUNCTION); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords3.InList(s)) { + sc.ChangeState(SCE_AU3_MACRO); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords5.InList(s)) { + sc.ChangeState(SCE_AU3_PREPROCESSOR); + sc.SetState(SCE_AU3_DEFAULT); + if (strcmp(s, "#include")== 0) + { + si = 3; // use to determine string start for #inlude <> + } + } + else if (keywords6.InList(s)) { + sc.ChangeState(SCE_AU3_SPECIAL); + sc.SetState(SCE_AU3_SPECIAL); + } + else if ((keywords7.InList(s)) && (!IsAOperator(static_cast(sc.ch)))) { + sc.ChangeState(SCE_AU3_EXPAND); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords8.InList(s)) { + sc.ChangeState(SCE_AU3_UDF); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (strcmp(s, "_") == 0) { + sc.ChangeState(SCE_AU3_OPERATOR); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (!IsAWordChar(sc.ch)) { + sc.ChangeState(SCE_AU3_DEFAULT); + sc.SetState(SCE_AU3_DEFAULT); + } + } + } + if (sc.atLineEnd) { + sc.SetState(SCE_AU3_DEFAULT);} + break; + } + case SCE_AU3_NUMBER: + { + // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 E-not=3 + // + // test for Hex notation + if (strcmp(s, "0") == 0 && (sc.ch == 'x' || sc.ch == 'X') && ni == 0) + { + ni = 2; + break; + } + // test for E notation + if (IsADigit(sc.chPrev) && (sc.ch == 'e' || sc.ch == 'E') && ni <= 1) + { + ni = 3; + break; + } + // Allow Hex characters inside hex numeric strings + if ((ni == 2) && + (sc.ch == 'a' || sc.ch == 'b' || sc.ch == 'c' || sc.ch == 'd' || sc.ch == 'e' || sc.ch == 'f' || + sc.ch == 'A' || sc.ch == 'B' || sc.ch == 'C' || sc.ch == 'D' || sc.ch == 'E' || sc.ch == 'F' )) + { + break; + } + // test for 1 dec point only + if (sc.ch == '.') + { + if (ni==0) + { + ni=1; + } + else + { + ni=9; + } + break; + } + // end of numeric string ? + if (!(IsADigit(sc.ch))) + { + if (ni==9) + { + sc.ChangeState(SCE_AU3_DEFAULT); + } + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_VARIABLE: + { + // Check if its a COMObject + if (sc.ch == '.' && !IsADigit(sc.chNext)) { + sc.SetState(SCE_AU3_OPERATOR); + } + else if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_COMOBJ: + { + if (!(IsAWordChar(sc.ch))) { + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_STRING: + { + // check for " to end a double qouted string or + // check for ' to end a single qouted string + if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'') || (si == 3 && sc.ch == '>')) + { + sc.ForwardSetState(SCE_AU3_DEFAULT); + si=0; + break; + } + if (sc.atLineEnd) + { + si=0; + // at line end and not found a continuation char then reset to default + int lineCurrent = styler.GetLine(sc.currentPos); + if (!IsContinuationLine(lineCurrent,styler)) + { + sc.SetState(SCE_AU3_DEFAULT); + break; + } + } + // find Sendkeys in a STRING + if (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ) { + sc.SetState(SCE_AU3_SENT);} + break; + } + + case SCE_AU3_SENT: + { + // Send key string ended + if (sc.chPrev == '}' && sc.ch != '}') + { + // set color to SENDKEY when valid sendkey .. else set back to regular string + char sk[100]; + // split {111 222} and return {111} and check if 222 is valid. + // if return code = 1 then invalid 222 so must be string + if (GetSendKey(s,sk)) + { + sc.ChangeState(SCE_AU3_STRING); + } + // if single char between {?} then its ok as sendkey for a single character + else if (strlen(sk) == 3) + { + sc.ChangeState(SCE_AU3_SENT); + } + // if sendkey {111} is in table then ok as sendkey + else if (keywords4.InList(sk)) + { + sc.ChangeState(SCE_AU3_SENT); + } + else + { + sc.ChangeState(SCE_AU3_STRING); + } + sc.SetState(SCE_AU3_STRING); + } + else + { + // check if the start is a valid SendKey start + int nPos = 0; + int nState = 1; + char cTemp; + while (!(nState == 2) && ((cTemp = s[nPos]) != '\0')) + { + if (cTemp == '{' && nState == 1) + { + nState = 2; + } + if (nState == 1 && !(cTemp == '+' || cTemp == '!' || cTemp == '^' || cTemp == '#' )) + { + nState = 0; + } + nPos++; + } + //Verify characters infront of { ... if not assume regular string + if (nState == 1 && (!(sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ))) { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_STRING); + } + // If invalid character found then assume its a regular string + if (nState == 0) { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_STRING); + } + } + // check if next portion is again a sendkey + if (sc.atLineEnd) + { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_DEFAULT); + si = 0; // reset string indicator + } + //* check in next characters following a sentkey are again a sent key + // Need this test incase of 2 sentkeys like {F1}{ENTER} but not detect {{} + if (sc.state == SCE_AU3_STRING && (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' )) { + sc.SetState(SCE_AU3_SENT);} + // check to see if the string ended... + // Sendkey string isn't complete but the string ended.... + if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'')) + { + sc.ChangeState(SCE_AU3_STRING); + sc.ForwardSetState(SCE_AU3_DEFAULT); + } + break; + } + } //switch (sc.state) + + // Determine if a new state should be entered: + + if (sc.state == SCE_AU3_DEFAULT) + { + if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);} + else if (sc.ch == '#') {sc.SetState(SCE_AU3_KEYWORD);} + else if (sc.ch == '$') {sc.SetState(SCE_AU3_VARIABLE);} + else if (sc.ch == '.' && !IsADigit(sc.chNext)) {sc.SetState(SCE_AU3_OPERATOR);} + else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);} + //else if (sc.ch == '_') {sc.SetState(SCE_AU3_KEYWORD);} + else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);} // string after #include + else if (sc.ch == '\"') { + sc.SetState(SCE_AU3_STRING); + si = 1; } + else if (sc.ch == '\'') { + sc.SetState(SCE_AU3_STRING); + si = 2; } + else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) + { + sc.SetState(SCE_AU3_NUMBER); + ni = 0; + } + else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);} + else if (IsAOperator(static_cast(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);} + else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} + } + } //for (; sc.More(); sc.Forward()) + + //************************************* + // Colourize the last word correctly + //************************************* + if (sc.state == SCE_AU3_KEYWORD) + { + if (strcmp(s_save, "#cs")== 0 || strcmp(s_save, "#comments-start")== 0 ) + { + sc.ChangeState(SCE_AU3_COMMENTBLOCK); + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + else if (keywords.InList(s_save)) { + sc.ChangeState(SCE_AU3_KEYWORD); + sc.SetState(SCE_AU3_KEYWORD); + } + else if (keywords2.InList(s_save)) { + sc.ChangeState(SCE_AU3_FUNCTION); + sc.SetState(SCE_AU3_FUNCTION); + } + else if (keywords3.InList(s_save)) { + sc.ChangeState(SCE_AU3_MACRO); + sc.SetState(SCE_AU3_MACRO); + } + else if (keywords5.InList(s_save)) { + sc.ChangeState(SCE_AU3_PREPROCESSOR); + sc.SetState(SCE_AU3_PREPROCESSOR); + } + else if (keywords6.InList(s_save)) { + sc.ChangeState(SCE_AU3_SPECIAL); + sc.SetState(SCE_AU3_SPECIAL); + } + else if (keywords7.InList(s_save) && sc.atLineEnd) { + sc.ChangeState(SCE_AU3_EXPAND); + sc.SetState(SCE_AU3_EXPAND); + } + else if (keywords8.InList(s_save)) { + sc.ChangeState(SCE_AU3_UDF); + sc.SetState(SCE_AU3_UDF); + } + else { + sc.ChangeState(SCE_AU3_DEFAULT); + sc.SetState(SCE_AU3_DEFAULT); + } + } + if (sc.state == SCE_AU3_SENT) + { + // Send key string ended + if (sc.chPrev == '}' && sc.ch != '}') + { + // set color to SENDKEY when valid sendkey .. else set back to regular string + char sk[100]; + // split {111 222} and return {111} and check if 222 is valid. + // if return code = 1 then invalid 222 so must be string + if (GetSendKey(s_save,sk)) + { + sc.ChangeState(SCE_AU3_STRING); + } + // if single char between {?} then its ok as sendkey for a single character + else if (strlen(sk) == 3) + { + sc.ChangeState(SCE_AU3_SENT); + } + // if sendkey {111} is in table then ok as sendkey + else if (keywords4.InList(sk)) + { + sc.ChangeState(SCE_AU3_SENT); + } + else + { + sc.ChangeState(SCE_AU3_STRING); + } + sc.SetState(SCE_AU3_STRING); + } + // check if next portion is again a sendkey + if (sc.atLineEnd) + { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_DEFAULT); + } + } + //************************************* + sc.Complete(); +} + +// +static bool IsStreamCommentStyle(int style) { + return style == SCE_AU3_COMMENT || style == SCE_AU3_COMMENTBLOCK; +} + +// +// Routine to find first none space on the current line and return its Style +// needed for comment lines not starting on pos 1 +static int GetStyleFirstWord(unsigned int szLine, Accessor &styler) +{ + int nsPos = styler.LineStart(szLine); + int nePos = styler.LineStart(szLine+1) - 1; + while (isspacechar(styler.SafeGetCharAt(nsPos)) && nsPos < nePos) + { + nsPos++; // skip to next char + + } // End While + return styler.StyleAt(nsPos); + +} // GetStyleFirstWord() + + +// +static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) +{ + int endPos = startPos + length; + // get settings from the config files for folding comments and preprocessor lines + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldInComment = styler.GetPropertyInt("fold.comment") == 2; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldpreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; + // Backtrack to previous line in case need to fix its fold status + int lineCurrent = styler.GetLine(startPos); + if (startPos > 0) { + if (lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + } + // vars for style of previous/current/next lines + int style = GetStyleFirstWord(lineCurrent,styler); + int stylePrev = 0; + // find the first previous line without continuation character at the end + while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || + (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + if (lineCurrent > 0) { + stylePrev = GetStyleFirstWord(lineCurrent-1,styler); + } + // vars for getting first word to check for keywords + bool FirstWordStart = false; + bool FirstWordEnd = false; + char szKeyword[11]=""; + int szKeywordlen = 0; + char szThen[5]=""; + int szThenlen = 0; + bool ThenFoundLast = false; + // var for indentlevel + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelNext = levelCurrent; + // + int visibleChars = 0; + char chNext = styler.SafeGetCharAt(startPos); + char chPrev = ' '; + // + for (int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + if (IsAWordChar(ch)) { + visibleChars++; + } + // get the syle for the current character neede to check in comment + int stylech = styler.StyleAt(i); + // get first word for the line for indent check max 9 characters + if (FirstWordStart && (!(FirstWordEnd))) { + if (!IsAWordChar(ch)) { + FirstWordEnd = true; + szKeyword[szKeywordlen] = '\0'; + } + else { + if (szKeywordlen < 10) { + szKeyword[szKeywordlen++] = static_cast(tolower(ch)); + } + } + } + // start the capture of the first word + if (!(FirstWordStart)) { + if (IsAWordChar(ch) || IsAWordStart(ch) || ch == ';') { + FirstWordStart = true; + szKeyword[szKeywordlen++] = static_cast(tolower(ch)); + } + } + // only process this logic when not in comment section + if (!(stylech == SCE_AU3_COMMENT)) { + if (ThenFoundLast) { + if (IsAWordChar(ch)) { + ThenFoundLast = false; + } + } + // find out if the word "then" is the last on a "if" line + if (FirstWordEnd && strcmp(szKeyword,"if") == 0) { + if (szThenlen == 4) { + szThen[0] = szThen[1]; + szThen[1] = szThen[2]; + szThen[2] = szThen[3]; + szThen[3] = static_cast(tolower(ch)); + if (strcmp(szThen,"then") == 0 ) { + ThenFoundLast = true; + } + } + else { + szThen[szThenlen++] = static_cast(tolower(ch)); + if (szThenlen == 5) { + szThen[4] = '\0'; + } + } + } + } + // End of Line found so process the information + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { + // ************************** + // Folding logic for Keywords + // ************************** + // if a keyword is found on the current line and the line doesn't end with _ (continuation) + // and we are not inside a commentblock. + if (szKeywordlen > 0 && (!(chPrev == '_')) && + ((!(IsStreamCommentStyle(style)) || foldInComment)) ) { + szKeyword[szKeywordlen] = '\0'; + // only fold "if" last keyword is "then" (else its a one line if) + if (strcmp(szKeyword,"if") == 0 && ThenFoundLast) { + levelNext++; + } + // create new fold for these words + if (strcmp(szKeyword,"do") == 0 || strcmp(szKeyword,"for") == 0 || + strcmp(szKeyword,"func") == 0 || strcmp(szKeyword,"while") == 0|| + strcmp(szKeyword,"with") == 0 || strcmp(szKeyword,"#region") == 0 ) { + levelNext++; + } + // create double Fold for select&switch because Case will subtract one of the current level + if (strcmp(szKeyword,"select") == 0 || strcmp(szKeyword,"switch") == 0) { + levelNext++; + levelNext++; + } + // end the fold for these words before the current line + if (strcmp(szKeyword,"endfunc") == 0 || strcmp(szKeyword,"endif") == 0 || + strcmp(szKeyword,"next") == 0 || strcmp(szKeyword,"until") == 0 || + strcmp(szKeyword,"endwith") == 0 ||strcmp(szKeyword,"wend") == 0){ + levelNext--; + levelCurrent--; + } + // end the fold for these words before the current line and Start new fold + if (strcmp(szKeyword,"case") == 0 || strcmp(szKeyword,"else") == 0 || + strcmp(szKeyword,"elseif") == 0 ) { + levelCurrent--; + } + // end the double fold for this word before the current line + if (strcmp(szKeyword,"endselect") == 0 || strcmp(szKeyword,"endswitch") == 0 ) { + levelNext--; + levelNext--; + levelCurrent--; + levelCurrent--; + } + // end the fold for these words on the current line + if (strcmp(szKeyword,"#endregion") == 0 ) { + levelNext--; + } + } + // Preprocessor and Comment folding + int styleNext = GetStyleFirstWord(lineCurrent + 1,styler); + // ************************************* + // Folding logic for preprocessor blocks + // ************************************* + // process preprosessor line + if (foldpreprocessor && style == SCE_AU3_PREPROCESSOR) { + if (!(stylePrev == SCE_AU3_PREPROCESSOR) && (styleNext == SCE_AU3_PREPROCESSOR)) { + levelNext++; + } + // fold till the last line for normal comment lines + else if (stylePrev == SCE_AU3_PREPROCESSOR && !(styleNext == SCE_AU3_PREPROCESSOR)) { + levelNext--; + } + } + // ********************************* + // Folding logic for Comment blocks + // ********************************* + if (foldComment && IsStreamCommentStyle(style)) { + // Start of a comment block + if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) { + levelNext++; + } + // fold till the last line for normal comment lines + else if (IsStreamCommentStyle(stylePrev) + && !(styleNext == SCE_AU3_COMMENT) + && stylePrev == SCE_AU3_COMMENT + && style == SCE_AU3_COMMENT) { + levelNext--; + } + // fold till the one but last line for Blockcomment lines + else if (IsStreamCommentStyle(stylePrev) + && !(styleNext == SCE_AU3_COMMENTBLOCK) + && style == SCE_AU3_COMMENTBLOCK) { + levelNext--; + levelCurrent--; + } + } + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + // reset values for the next line + lineCurrent++; + stylePrev = style; + style = styleNext; + levelCurrent = levelNext; + visibleChars = 0; + // if the last character is an Underscore then don't reset since the line continues on the next line. + if (!(chPrev == '_')) { + szKeywordlen = 0; + szThenlen = 0; + FirstWordStart = false; + FirstWordEnd = false; + ThenFoundLast = false; + } + } + // save the last processed character + if (!isspacechar(ch)) { + chPrev = ch; + visibleChars++; + } + } +} + + +// + +static const char * const AU3WordLists[] = { + "#autoit keywords", + "#autoit functions", + "#autoit macros", + "#autoit Sent keys", + "#autoit Pre-processors", + "#autoit Special", + "#autoit Expand", + "#autoit UDF", + 0 +}; +LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3", FoldAU3Doc , AU3WordLists); diff --git a/scintilla/lexers/LexAVE.cxx b/ThirdLibs/scintilla/lexers/LexAVE.cxx similarity index 96% rename from scintilla/lexers/LexAVE.cxx rename to ThirdLibs/scintilla/lexers/LexAVE.cxx index e7d26055..373173ca 100644 --- a/scintilla/lexers/LexAVE.cxx +++ b/ThirdLibs/scintilla/lexers/LexAVE.cxx @@ -1,231 +1,231 @@ -// SciTE - Scintilla based Text Editor -/** @file LexAVE.cxx - ** Lexer for Avenue. - ** - ** Written by Alexey Yutkin . - **/ -// Copyright 1998-2002 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); -} -static inline bool IsEnumChar(const int ch) { - return (ch < 0x80) && (isalnum(ch)|| ch == '_'); -} -static inline bool IsANumberChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' ); -} - -inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -inline bool isAveOperator(char ch) { - if (isascii(ch) && isalnum(ch)) - return false; - // '.' left out as it is used to make up numbers - if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || - ch == '{' || ch == '}' || - ch == '[' || ch == ']' || ch == ';' || - ch == '<' || ch == '>' || ch == ',' || - ch == '.' ) - return true; - return false; -} - -static void ColouriseAveDoc( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - WordList &keywords6 = *keywordlists[5]; - - // Do not leak onto next line - if (initStyle == SCE_AVE_STRINGEOL) { - initStyle = SCE_AVE_DEFAULT; - } - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - if (sc.atLineEnd) { - // Update the line state, so it can be seen by next line - int currentLine = styler.GetLine(sc.currentPos); - styler.SetLineState(currentLine, 0); - } - if (sc.atLineStart && (sc.state == SCE_AVE_STRING)) { - // Prevent SCE_AVE_STRINGEOL from leaking back to previous line - sc.SetState(SCE_AVE_STRING); - } - - - // Determine if the current state should terminate. - if (sc.state == SCE_AVE_OPERATOR) { - sc.SetState(SCE_AVE_DEFAULT); - } else if (sc.state == SCE_AVE_NUMBER) { - if (!IsANumberChar(sc.ch)) { - sc.SetState(SCE_AVE_DEFAULT); - } - } else if (sc.state == SCE_AVE_ENUM) { - if (!IsEnumChar(sc.ch)) { - sc.SetState(SCE_AVE_DEFAULT); - } - } else if (sc.state == SCE_AVE_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { - char s[100]; - //sc.GetCurrent(s, sizeof(s)); - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_AVE_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_AVE_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_AVE_WORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_AVE_WORD4); - } else if (keywords5.InList(s)) { - sc.ChangeState(SCE_AVE_WORD5); - } else if (keywords6.InList(s)) { - sc.ChangeState(SCE_AVE_WORD6); - } - sc.SetState(SCE_AVE_DEFAULT); - } - } else if (sc.state == SCE_AVE_COMMENT) { - if (sc.atLineEnd) { - sc.SetState(SCE_AVE_DEFAULT); - } - } else if (sc.state == SCE_AVE_STRING) { - if (sc.ch == '\"') { - sc.ForwardSetState(SCE_AVE_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_AVE_STRINGEOL); - sc.ForwardSetState(SCE_AVE_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_AVE_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_AVE_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_AVE_IDENTIFIER); - } else if (sc.Match('\"')) { - sc.SetState(SCE_AVE_STRING); - } else if (sc.Match('\'')) { - sc.SetState(SCE_AVE_COMMENT); - sc.Forward(); - } else if (isAveOperator(static_cast(sc.ch))) { - sc.SetState(SCE_AVE_OPERATOR); - } else if (sc.Match('#')) { - sc.SetState(SCE_AVE_ENUM); - sc.Forward(); - } - } - } - sc.Complete(); -} - -static void FoldAveDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[], - Accessor &styler) { - unsigned int lengthDoc = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = static_cast(tolower(styler[startPos])); - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - int styleNext = styler.StyleAt(startPos); - char s[10]; - - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = static_cast(tolower(chNext)); - chNext = static_cast(tolower(styler.SafeGetCharAt(i + 1))); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (style == SCE_AVE_WORD) { - if (ch == 't' || ch == 'f' || ch == 'w' || ch == 'e') { - for (unsigned int j = 0; j < 6; j++) { - if (!iswordchar(styler[i + j])) { - break; - } - s[j] = static_cast(tolower(styler[i + j])); - s[j + 1] = '\0'; - } - - if ((strcmp(s, "then") == 0) || (strcmp(s, "for") == 0) || (strcmp(s, "while") == 0)) { - levelCurrent++; - } - if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0)) { - // Normally "elseif" and "then" will be on the same line and will cancel - // each other out. // As implemented, this does not support fold.at.else. - levelCurrent--; - } - } - } else if (style == SCE_AVE_OPERATOR) { - if (ch == '{' || ch == '(') { - levelCurrent++; - } else if (ch == '}' || ch == ')') { - levelCurrent--; - } - } - - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) { - lev |= SC_FOLDLEVELWHITEFLAG; - } - if ((levelCurrent > levelPrev) && (visibleChars > 0)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) { - visibleChars++; - } - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -LexerModule lmAVE(SCLEX_AVE, ColouriseAveDoc, "ave", FoldAveDoc); - +// SciTE - Scintilla based Text Editor +/** @file LexAVE.cxx + ** Lexer for Avenue. + ** + ** Written by Alexey Yutkin . + **/ +// Copyright 1998-2002 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); +} +static inline bool IsEnumChar(const int ch) { + return (ch < 0x80) && (isalnum(ch)|| ch == '_'); +} +static inline bool IsANumberChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' ); +} + +inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +inline bool isAveOperator(char ch) { + if (isascii(ch) && isalnum(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || + ch == '{' || ch == '}' || + ch == '[' || ch == ']' || ch == ';' || + ch == '<' || ch == '>' || ch == ',' || + ch == '.' ) + return true; + return false; +} + +static void ColouriseAveDoc( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; + + // Do not leak onto next line + if (initStyle == SCE_AVE_STRINGEOL) { + initStyle = SCE_AVE_DEFAULT; + } + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + if (sc.atLineEnd) { + // Update the line state, so it can be seen by next line + int currentLine = styler.GetLine(sc.currentPos); + styler.SetLineState(currentLine, 0); + } + if (sc.atLineStart && (sc.state == SCE_AVE_STRING)) { + // Prevent SCE_AVE_STRINGEOL from leaking back to previous line + sc.SetState(SCE_AVE_STRING); + } + + + // Determine if the current state should terminate. + if (sc.state == SCE_AVE_OPERATOR) { + sc.SetState(SCE_AVE_DEFAULT); + } else if (sc.state == SCE_AVE_NUMBER) { + if (!IsANumberChar(sc.ch)) { + sc.SetState(SCE_AVE_DEFAULT); + } + } else if (sc.state == SCE_AVE_ENUM) { + if (!IsEnumChar(sc.ch)) { + sc.SetState(SCE_AVE_DEFAULT); + } + } else if (sc.state == SCE_AVE_IDENTIFIER) { + if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { + char s[100]; + //sc.GetCurrent(s, sizeof(s)); + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_AVE_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_AVE_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_AVE_WORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_AVE_WORD4); + } else if (keywords5.InList(s)) { + sc.ChangeState(SCE_AVE_WORD5); + } else if (keywords6.InList(s)) { + sc.ChangeState(SCE_AVE_WORD6); + } + sc.SetState(SCE_AVE_DEFAULT); + } + } else if (sc.state == SCE_AVE_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_AVE_DEFAULT); + } + } else if (sc.state == SCE_AVE_STRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_AVE_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_AVE_STRINGEOL); + sc.ForwardSetState(SCE_AVE_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_AVE_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_AVE_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_AVE_IDENTIFIER); + } else if (sc.Match('\"')) { + sc.SetState(SCE_AVE_STRING); + } else if (sc.Match('\'')) { + sc.SetState(SCE_AVE_COMMENT); + sc.Forward(); + } else if (isAveOperator(static_cast(sc.ch))) { + sc.SetState(SCE_AVE_OPERATOR); + } else if (sc.Match('#')) { + sc.SetState(SCE_AVE_ENUM); + sc.Forward(); + } + } + } + sc.Complete(); +} + +static void FoldAveDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[], + Accessor &styler) { + unsigned int lengthDoc = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = static_cast(tolower(styler[startPos])); + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + int styleNext = styler.StyleAt(startPos); + char s[10]; + + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = static_cast(tolower(chNext)); + chNext = static_cast(tolower(styler.SafeGetCharAt(i + 1))); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (style == SCE_AVE_WORD) { + if (ch == 't' || ch == 'f' || ch == 'w' || ch == 'e') { + for (unsigned int j = 0; j < 6; j++) { + if (!iswordchar(styler[i + j])) { + break; + } + s[j] = static_cast(tolower(styler[i + j])); + s[j + 1] = '\0'; + } + + if ((strcmp(s, "then") == 0) || (strcmp(s, "for") == 0) || (strcmp(s, "while") == 0)) { + levelCurrent++; + } + if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0)) { + // Normally "elseif" and "then" will be on the same line and will cancel + // each other out. // As implemented, this does not support fold.at.else. + levelCurrent--; + } + } + } else if (style == SCE_AVE_OPERATOR) { + if (ch == '{' || ch == '(') { + levelCurrent++; + } else if (ch == '}' || ch == ')') { + levelCurrent--; + } + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) { + lev |= SC_FOLDLEVELWHITEFLAG; + } + if ((levelCurrent > levelPrev) && (visibleChars > 0)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) { + visibleChars++; + } + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +LexerModule lmAVE(SCLEX_AVE, ColouriseAveDoc, "ave", FoldAveDoc); + diff --git a/scintilla/lexers/LexAVS.cxx b/ThirdLibs/scintilla/lexers/LexAVS.cxx similarity index 96% rename from scintilla/lexers/LexAVS.cxx rename to ThirdLibs/scintilla/lexers/LexAVS.cxx index f9f21dc8..82e43457 100644 --- a/scintilla/lexers/LexAVS.cxx +++ b/ThirdLibs/scintilla/lexers/LexAVS.cxx @@ -1,293 +1,293 @@ -// Scintilla source code edit control -/** @file LexAVS.cxx - ** Lexer for AviSynth. - **/ -// Copyright 2012 by Bruno Barbieri -// Heavily based on LexPOV by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAWordStart(int ch) { - return isalpha(ch) || (ch != ' ' && ch != '\n' && ch != '(' && ch != '.' && ch != ','); -} - -static inline bool IsANumberChar(int ch) { - // Not exactly following number definition (several dots are seen as OK, etc.) - // but probably enough in most cases. - return (ch < 0x80) && - (isdigit(ch) || ch == '.' || ch == '-' || ch == '+'); -} - -static void ColouriseAvsDoc( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &filters = *keywordlists[1]; - WordList &plugins = *keywordlists[2]; - WordList &functions = *keywordlists[3]; - WordList &clipProperties = *keywordlists[4]; - WordList &userDefined = *keywordlists[5]; - - int currentLine = styler.GetLine(startPos); - // Initialize the block comment nesting level, if we are inside such a comment. - int blockCommentLevel = 0; - if (initStyle == SCE_AVS_COMMENTBLOCK || initStyle == SCE_AVS_COMMENTBLOCKN) { - blockCommentLevel = styler.GetLineState(currentLine - 1); - } - - // Do not leak onto next line - if (initStyle == SCE_AVS_COMMENTLINE) { - initStyle = SCE_AVS_DEFAULT; - } - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - if (sc.atLineEnd) { - // Update the line state, so it can be seen by next line - currentLine = styler.GetLine(sc.currentPos); - if (sc.state == SCE_AVS_COMMENTBLOCK || sc.state == SCE_AVS_COMMENTBLOCKN) { - // Inside a block comment, we set the line state - styler.SetLineState(currentLine, blockCommentLevel); - } else { - // Reset the line state - styler.SetLineState(currentLine, 0); - } - } - - // Determine if the current state should terminate. - if (sc.state == SCE_AVS_OPERATOR) { - sc.SetState(SCE_AVS_DEFAULT); - } else if (sc.state == SCE_AVS_NUMBER) { - // We stop the number definition on non-numerical non-dot non-sign char - if (!IsANumberChar(sc.ch)) { - sc.SetState(SCE_AVS_DEFAULT); - } - } else if (sc.state == SCE_AVS_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - - if (keywords.InList(s)) { - sc.ChangeState(SCE_AVS_KEYWORD); - } else if (filters.InList(s)) { - sc.ChangeState(SCE_AVS_FILTER); - } else if (plugins.InList(s)) { - sc.ChangeState(SCE_AVS_PLUGIN); - } else if (functions.InList(s)) { - sc.ChangeState(SCE_AVS_FUNCTION); - } else if (clipProperties.InList(s)) { - sc.ChangeState(SCE_AVS_CLIPPROP); - } else if (userDefined.InList(s)) { - sc.ChangeState(SCE_AVS_USERDFN); - } - sc.SetState(SCE_AVS_DEFAULT); - } - } else if (sc.state == SCE_AVS_COMMENTBLOCK) { - if (sc.Match('/', '*')) { - blockCommentLevel++; - sc.Forward(); - } else if (sc.Match('*', '/') && blockCommentLevel > 0) { - blockCommentLevel--; - sc.Forward(); - if (blockCommentLevel == 0) { - sc.ForwardSetState(SCE_AVS_DEFAULT); - } - } - } else if (sc.state == SCE_AVS_COMMENTBLOCKN) { - if (sc.Match('[', '*')) { - blockCommentLevel++; - sc.Forward(); - } else if (sc.Match('*', ']') && blockCommentLevel > 0) { - blockCommentLevel--; - sc.Forward(); - if (blockCommentLevel == 0) { - sc.ForwardSetState(SCE_AVS_DEFAULT); - } - } - } else if (sc.state == SCE_AVS_COMMENTLINE) { - if (sc.atLineEnd) { - sc.ForwardSetState(SCE_AVS_DEFAULT); - } - } else if (sc.state == SCE_AVS_STRING) { - if (sc.ch == '\"') { - sc.ForwardSetState(SCE_AVS_DEFAULT); - } - } else if (sc.state == SCE_AVS_TRIPLESTRING) { - if (sc.Match("\"\"\"")) { - sc.Forward(); - sc.Forward(); - sc.ForwardSetState(SCE_AVS_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_AVS_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_AVS_NUMBER); - } else if (IsADigit(sc.ch) || (sc.ch == ',' && IsADigit(sc.chNext))) { - sc.Forward(); - sc.SetState(SCE_AVS_NUMBER); - } else if (sc.Match('/', '*')) { - blockCommentLevel = 1; - sc.SetState(SCE_AVS_COMMENTBLOCK); - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('[', '*')) { - blockCommentLevel = 1; - sc.SetState(SCE_AVS_COMMENTBLOCKN); - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.ch == '#') { - sc.SetState(SCE_AVS_COMMENTLINE); - } else if (sc.ch == '\"') { - if (sc.Match("\"\"\"")) { - sc.SetState(SCE_AVS_TRIPLESTRING); - } else { - sc.SetState(SCE_AVS_STRING); - } - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_AVS_OPERATOR); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_AVS_IDENTIFIER); - } - } - } - - // End of file: complete any pending changeState - if (sc.state == SCE_AVS_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - - if (keywords.InList(s)) { - sc.ChangeState(SCE_AVS_KEYWORD); - } else if (filters.InList(s)) { - sc.ChangeState(SCE_AVS_FILTER); - } else if (plugins.InList(s)) { - sc.ChangeState(SCE_AVS_PLUGIN); - } else if (functions.InList(s)) { - sc.ChangeState(SCE_AVS_FUNCTION); - } else if (clipProperties.InList(s)) { - sc.ChangeState(SCE_AVS_CLIPPROP); - } else if (userDefined.InList(s)) { - sc.ChangeState(SCE_AVS_USERDFN); - } - sc.SetState(SCE_AVS_DEFAULT); - } - } - - sc.Complete(); -} - -static void FoldAvsDoc( - unsigned int startPos, - int length, - int initStyle, - WordList *[], - Accessor &styler) { - - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && style == SCE_AVS_COMMENTBLOCK) { - if (stylePrev != SCE_AVS_COMMENTBLOCK) { - levelCurrent++; - } else if ((styleNext != SCE_AVS_COMMENTBLOCK) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelCurrent--; - } - } - - if (foldComment && style == SCE_AVS_COMMENTBLOCKN) { - if (stylePrev != SCE_AVS_COMMENTBLOCKN) { - levelCurrent++; - } else if ((styleNext != SCE_AVS_COMMENTBLOCKN) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelCurrent--; - } - } - - if (style == SCE_AVS_OPERATOR) { - if (ch == '{') { - levelCurrent++; - } else if (ch == '}') { - levelCurrent--; - } - } - - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const avsWordLists[] = { - "Keywords", - "Filters", - "Plugins", - "Functions", - "Clip properties", - "User defined functions", - 0, -}; - -LexerModule lmAVS(SCLEX_AVS, ColouriseAvsDoc, "avs", FoldAvsDoc, avsWordLists); +// Scintilla source code edit control +/** @file LexAVS.cxx + ** Lexer for AviSynth. + **/ +// Copyright 2012 by Bruno Barbieri +// Heavily based on LexPOV by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(int ch) { + return isalpha(ch) || (ch != ' ' && ch != '\n' && ch != '(' && ch != '.' && ch != ','); +} + +static inline bool IsANumberChar(int ch) { + // Not exactly following number definition (several dots are seen as OK, etc.) + // but probably enough in most cases. + return (ch < 0x80) && + (isdigit(ch) || ch == '.' || ch == '-' || ch == '+'); +} + +static void ColouriseAvsDoc( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &filters = *keywordlists[1]; + WordList &plugins = *keywordlists[2]; + WordList &functions = *keywordlists[3]; + WordList &clipProperties = *keywordlists[4]; + WordList &userDefined = *keywordlists[5]; + + int currentLine = styler.GetLine(startPos); + // Initialize the block comment nesting level, if we are inside such a comment. + int blockCommentLevel = 0; + if (initStyle == SCE_AVS_COMMENTBLOCK || initStyle == SCE_AVS_COMMENTBLOCKN) { + blockCommentLevel = styler.GetLineState(currentLine - 1); + } + + // Do not leak onto next line + if (initStyle == SCE_AVS_COMMENTLINE) { + initStyle = SCE_AVS_DEFAULT; + } + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + if (sc.atLineEnd) { + // Update the line state, so it can be seen by next line + currentLine = styler.GetLine(sc.currentPos); + if (sc.state == SCE_AVS_COMMENTBLOCK || sc.state == SCE_AVS_COMMENTBLOCKN) { + // Inside a block comment, we set the line state + styler.SetLineState(currentLine, blockCommentLevel); + } else { + // Reset the line state + styler.SetLineState(currentLine, 0); + } + } + + // Determine if the current state should terminate. + if (sc.state == SCE_AVS_OPERATOR) { + sc.SetState(SCE_AVS_DEFAULT); + } else if (sc.state == SCE_AVS_NUMBER) { + // We stop the number definition on non-numerical non-dot non-sign char + if (!IsANumberChar(sc.ch)) { + sc.SetState(SCE_AVS_DEFAULT); + } + } else if (sc.state == SCE_AVS_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if (keywords.InList(s)) { + sc.ChangeState(SCE_AVS_KEYWORD); + } else if (filters.InList(s)) { + sc.ChangeState(SCE_AVS_FILTER); + } else if (plugins.InList(s)) { + sc.ChangeState(SCE_AVS_PLUGIN); + } else if (functions.InList(s)) { + sc.ChangeState(SCE_AVS_FUNCTION); + } else if (clipProperties.InList(s)) { + sc.ChangeState(SCE_AVS_CLIPPROP); + } else if (userDefined.InList(s)) { + sc.ChangeState(SCE_AVS_USERDFN); + } + sc.SetState(SCE_AVS_DEFAULT); + } + } else if (sc.state == SCE_AVS_COMMENTBLOCK) { + if (sc.Match('/', '*')) { + blockCommentLevel++; + sc.Forward(); + } else if (sc.Match('*', '/') && blockCommentLevel > 0) { + blockCommentLevel--; + sc.Forward(); + if (blockCommentLevel == 0) { + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } + } else if (sc.state == SCE_AVS_COMMENTBLOCKN) { + if (sc.Match('[', '*')) { + blockCommentLevel++; + sc.Forward(); + } else if (sc.Match('*', ']') && blockCommentLevel > 0) { + blockCommentLevel--; + sc.Forward(); + if (blockCommentLevel == 0) { + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } + } else if (sc.state == SCE_AVS_COMMENTLINE) { + if (sc.atLineEnd) { + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } else if (sc.state == SCE_AVS_STRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } else if (sc.state == SCE_AVS_TRIPLESTRING) { + if (sc.Match("\"\"\"")) { + sc.Forward(); + sc.Forward(); + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_AVS_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_AVS_NUMBER); + } else if (IsADigit(sc.ch) || (sc.ch == ',' && IsADigit(sc.chNext))) { + sc.Forward(); + sc.SetState(SCE_AVS_NUMBER); + } else if (sc.Match('/', '*')) { + blockCommentLevel = 1; + sc.SetState(SCE_AVS_COMMENTBLOCK); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('[', '*')) { + blockCommentLevel = 1; + sc.SetState(SCE_AVS_COMMENTBLOCKN); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.ch == '#') { + sc.SetState(SCE_AVS_COMMENTLINE); + } else if (sc.ch == '\"') { + if (sc.Match("\"\"\"")) { + sc.SetState(SCE_AVS_TRIPLESTRING); + } else { + sc.SetState(SCE_AVS_STRING); + } + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_AVS_OPERATOR); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_AVS_IDENTIFIER); + } + } + } + + // End of file: complete any pending changeState + if (sc.state == SCE_AVS_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if (keywords.InList(s)) { + sc.ChangeState(SCE_AVS_KEYWORD); + } else if (filters.InList(s)) { + sc.ChangeState(SCE_AVS_FILTER); + } else if (plugins.InList(s)) { + sc.ChangeState(SCE_AVS_PLUGIN); + } else if (functions.InList(s)) { + sc.ChangeState(SCE_AVS_FUNCTION); + } else if (clipProperties.InList(s)) { + sc.ChangeState(SCE_AVS_CLIPPROP); + } else if (userDefined.InList(s)) { + sc.ChangeState(SCE_AVS_USERDFN); + } + sc.SetState(SCE_AVS_DEFAULT); + } + } + + sc.Complete(); +} + +static void FoldAvsDoc( + unsigned int startPos, + int length, + int initStyle, + WordList *[], + Accessor &styler) { + + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && style == SCE_AVS_COMMENTBLOCK) { + if (stylePrev != SCE_AVS_COMMENTBLOCK) { + levelCurrent++; + } else if ((styleNext != SCE_AVS_COMMENTBLOCK) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + + if (foldComment && style == SCE_AVS_COMMENTBLOCKN) { + if (stylePrev != SCE_AVS_COMMENTBLOCKN) { + levelCurrent++; + } else if ((styleNext != SCE_AVS_COMMENTBLOCKN) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + + if (style == SCE_AVS_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const avsWordLists[] = { + "Keywords", + "Filters", + "Plugins", + "Functions", + "Clip properties", + "User defined functions", + 0, +}; + +LexerModule lmAVS(SCLEX_AVS, ColouriseAvsDoc, "avs", FoldAvsDoc, avsWordLists); diff --git a/scintilla/lexers/LexAbaqus.cxx b/ThirdLibs/scintilla/lexers/LexAbaqus.cxx similarity index 96% rename from scintilla/lexers/LexAbaqus.cxx rename to ThirdLibs/scintilla/lexers/LexAbaqus.cxx index 267449f3..13417007 100644 --- a/scintilla/lexers/LexAbaqus.cxx +++ b/ThirdLibs/scintilla/lexers/LexAbaqus.cxx @@ -1,620 +1,620 @@ -// Scintilla source code edit control -/** @file LexABAQUS.cxx - ** Lexer for ABAQUS. Based on the lexer for APDL by Hadar Raz. - ** By Sergio Lucato. - ** Sort of completely rewritten by Gertjan Kloosterman - **/ -// The License.txt file describes the conditions under which this software may be distributed. - -// Code folding copyied and modified from LexBasic.cxx - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80 && (isalnum(ch) || (ch == '_'))); -} - -static inline bool IsAKeywordChar(const int ch) { - return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == ' '))); -} - -static inline bool IsASetChar(const int ch) { - return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == '.') || (ch == '-'))); -} - -static inline bool IsAnOperator(char ch) { - // '.' left out as it is used to make up numbers - if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || ch == '^' || - ch == '[' || ch == ']' || ch == '<' || ch == '&' || - ch == '>' || ch == ',' || ch == '|' || ch == '~' || - ch == '$' || ch == ':' || ch == '%') - return true; - return false; -} - -static void ColouriseABAQUSDoc(unsigned int startPos, int length, int initStyle, WordList*[] /* *keywordlists[] */, - Accessor &styler) { - enum localState { KW_LINE_KW, KW_LINE_COMMA, KW_LINE_PAR, KW_LINE_EQ, KW_LINE_VAL, \ - DAT_LINE_VAL, DAT_LINE_COMMA,\ - COMMENT_LINE,\ - ST_ERROR, LINE_END } state ; - - // Do not leak onto next line - state = LINE_END ; - initStyle = SCE_ABAQUS_DEFAULT; - StyleContext sc(startPos, length, initStyle, styler); - - // Things are actually quite simple - // we have commentlines - // keywordlines and datalines - // On a data line there will only be colouring of numbers - // a keyword line is constructed as - // *word,[ paramname[=paramvalue]]* - // if the line ends with a , the keyword line continues onto the new line - - for (; sc.More(); sc.Forward()) { - switch ( state ) { - case KW_LINE_KW : - if ( sc.atLineEnd ) { - // finished the line in keyword state, switch to LINE_END - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = LINE_END ; - } else if ( IsAKeywordChar(sc.ch) ) { - // nothing changes - state = KW_LINE_KW ; - } else if ( sc.ch == ',' ) { - // Well well we say a comma, arguments *MUST* follow - sc.SetState(SCE_ABAQUS_OPERATOR) ; - state = KW_LINE_COMMA ; - } else { - // Flag an error - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - // Done with processing - break ; - case KW_LINE_COMMA : - // acomma on a keywordline was seen - if ( IsAKeywordChar(sc.ch)) { - sc.SetState(SCE_ABAQUS_ARGUMENT) ; - state = KW_LINE_PAR ; - } else if ( sc.atLineEnd || (sc.ch == ',') ) { - // we remain in keyword mode - state = KW_LINE_COMMA ; - } else if ( sc.ch == ' ' ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = KW_LINE_COMMA ; - } else { - // Anything else constitutes an error - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - break ; - case KW_LINE_PAR : - if ( sc.atLineEnd ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = LINE_END ; - } else if ( IsAKeywordChar(sc.ch) || (sc.ch == '-') ) { - // remain in this state - state = KW_LINE_PAR ; - } else if ( sc.ch == ',' ) { - sc.SetState(SCE_ABAQUS_OPERATOR) ; - state = KW_LINE_COMMA ; - } else if ( sc.ch == '=' ) { - sc.SetState(SCE_ABAQUS_OPERATOR) ; - state = KW_LINE_EQ ; - } else { - // Anything else constitutes an error - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - break ; - case KW_LINE_EQ : - if ( sc.ch == ' ' ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - // remain in this state - state = KW_LINE_EQ ; - } else if ( IsADigit(sc.ch) || (sc.ch == '-') || (sc.ch == '.' && IsADigit(sc.chNext)) ) { - sc.SetState(SCE_ABAQUS_NUMBER) ; - state = KW_LINE_VAL ; - } else if ( IsAKeywordChar(sc.ch) ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = KW_LINE_VAL ; - } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { - sc.SetState(SCE_ABAQUS_STRING) ; - state = KW_LINE_VAL ; - } else { - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - break ; - case KW_LINE_VAL : - if ( sc.atLineEnd ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = LINE_END ; - } else if ( IsASetChar(sc.ch) && (sc.state == SCE_ABAQUS_DEFAULT) ) { - // nothing changes - state = KW_LINE_VAL ; - } else if (( (IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || - ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) && - (sc.state == SCE_ABAQUS_NUMBER)) { - // remain in number mode - state = KW_LINE_VAL ; - } else if (sc.state == SCE_ABAQUS_STRING) { - // accept everything until a closing quote - if ( sc.ch == '\'' || sc.ch == '\"' ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = KW_LINE_VAL ; - } - } else if ( sc.ch == ',' ) { - sc.SetState(SCE_ABAQUS_OPERATOR) ; - state = KW_LINE_COMMA ; - } else { - // anything else is an error - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - break ; - case DAT_LINE_VAL : - if ( sc.atLineEnd ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = LINE_END ; - } else if ( IsASetChar(sc.ch) && (sc.state == SCE_ABAQUS_DEFAULT) ) { - // nothing changes - state = DAT_LINE_VAL ; - } else if (( (IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || - ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) && - (sc.state == SCE_ABAQUS_NUMBER)) { - // remain in number mode - state = DAT_LINE_VAL ; - } else if (sc.state == SCE_ABAQUS_STRING) { - // accept everything until a closing quote - if ( sc.ch == '\'' || sc.ch == '\"' ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = DAT_LINE_VAL ; - } - } else if ( sc.ch == ',' ) { - sc.SetState(SCE_ABAQUS_OPERATOR) ; - state = DAT_LINE_COMMA ; - } else { - // anything else is an error - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - break ; - case DAT_LINE_COMMA : - // a comma on a data line was seen - if ( sc.atLineEnd ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = LINE_END ; - } else if ( sc.ch == ' ' ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = DAT_LINE_COMMA ; - } else if (sc.ch == ',') { - sc.SetState(SCE_ABAQUS_OPERATOR) ; - state = DAT_LINE_COMMA ; - } else if ( IsADigit(sc.ch) || (sc.ch == '-')|| (sc.ch == '.' && IsADigit(sc.chNext)) ) { - sc.SetState(SCE_ABAQUS_NUMBER) ; - state = DAT_LINE_VAL ; - } else if ( IsAKeywordChar(sc.ch) ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = DAT_LINE_VAL ; - } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { - sc.SetState(SCE_ABAQUS_STRING) ; - state = DAT_LINE_VAL ; - } else { - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - break ; - case COMMENT_LINE : - if ( sc.atLineEnd ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = LINE_END ; - } - break ; - case ST_ERROR : - if ( sc.atLineEnd ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = LINE_END ; - } - break ; - case LINE_END : - if ( sc.atLineEnd || sc.ch == ' ' ) { - // nothing changes - state = LINE_END ; - } else if ( sc.ch == '*' ) { - if ( sc.chNext == '*' ) { - state = COMMENT_LINE ; - sc.SetState(SCE_ABAQUS_COMMENT) ; - } else { - state = KW_LINE_KW ; - sc.SetState(SCE_ABAQUS_STARCOMMAND) ; - } - } else { - // it must be a data line, things are as if we are in DAT_LINE_COMMA - if ( sc.ch == ',' ) { - sc.SetState(SCE_ABAQUS_OPERATOR) ; - state = DAT_LINE_COMMA ; - } else if ( IsADigit(sc.ch) || (sc.ch == '-')|| (sc.ch == '.' && IsADigit(sc.chNext)) ) { - sc.SetState(SCE_ABAQUS_NUMBER) ; - state = DAT_LINE_VAL ; - } else if ( IsAKeywordChar(sc.ch) ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = DAT_LINE_VAL ; - } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { - sc.SetState(SCE_ABAQUS_STRING) ; - state = DAT_LINE_VAL ; - } else { - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - } - break ; - } - } - sc.Complete(); -} - -//------------------------------------------------------------------------------ -// This copyied and modified from LexBasic.cxx -//------------------------------------------------------------------------------ - -/* Bits: - * 1 - whitespace - * 2 - operator - * 4 - identifier - * 8 - decimal digit - * 16 - hex digit - * 32 - bin digit - */ -static int character_classification[128] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 10, 6, - 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, - 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4, - 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0 -}; - -static bool IsSpace(int c) { - return c < 128 && (character_classification[c] & 1); -} - -static bool IsIdentifier(int c) { - return c < 128 && (character_classification[c] & 4); -} - -static int LowerCase(int c) -{ - if (c >= 'A' && c <= 'Z') - return 'a' + c - 'A'; - return c; -} - -static int LineEnd(int line, Accessor &styler) -{ - const int docLines = styler.GetLine(styler.Length() - 1); // Available last line - int eol_pos ; - // if the line is the last line, the eol_pos is styler.Length() - // eol will contain a new line, or a virtual new line - if ( docLines == line ) - eol_pos = styler.Length() ; - else - eol_pos = styler.LineStart(line + 1) - 1; - return eol_pos ; -} - -static int LineStart(int line, Accessor &styler) -{ - return styler.LineStart(line) ; -} - -// LineType -// -// bits determines the line type -// 1 : data line -// 2 : only whitespace -// 3 : data line with only whitespace -// 4 : keyword line -// 5 : block open keyword line -// 6 : block close keyword line -// 7 : keyword line in error -// 8 : comment line -static int LineType(int line, Accessor &styler) { - int pos = LineStart(line, styler) ; - int eol_pos = LineEnd(line, styler) ; - - int c ; - char ch = ' '; - - int i = pos ; - while ( i < eol_pos ) { - c = styler.SafeGetCharAt(i); - ch = static_cast(LowerCase(c)); - // We can say something as soon as no whitespace - // was encountered - if ( !IsSpace(c) ) - break ; - i++ ; - } - - if ( i >= eol_pos ) { - // This is a whitespace line, currently - // classifies as data line - return 3 ; - } - - if ( ch != '*' ) { - // This is a data line - return 1 ; - } - - if ( i == eol_pos - 1 ) { - // Only a single *, error but make keyword line - return 4+3 ; - } - - // This means we can have a second character - // if that is also a * this means a comment - // otherwise it is a keyword. - c = styler.SafeGetCharAt(i+1); - ch = static_cast(LowerCase(c)); - if ( ch == '*' ) { - return 8 ; - } - - // At this point we know this is a keyword line - // the character at position i is a * - // it is not a comment line - char word[256] ; - int wlen = 0; - - word[wlen] = '*' ; - wlen++ ; - - i++ ; - while ( (i < eol_pos) && (wlen < 255) ) { - c = styler.SafeGetCharAt(i); - ch = static_cast(LowerCase(c)); - - if ( (!IsSpace(c)) && (!IsIdentifier(c)) ) - break ; - - if ( IsIdentifier(c) ) { - word[wlen] = ch ; - wlen++ ; - } - - i++ ; - } - - word[wlen] = 0 ; - - // Make a comparison - if ( !strcmp(word, "*step") || - !strcmp(word, "*part") || - !strcmp(word, "*instance") || - !strcmp(word, "*assembly")) { - return 4+1 ; - } - - if ( !strcmp(word, "*endstep") || - !strcmp(word, "*endpart") || - !strcmp(word, "*endinstance") || - !strcmp(word, "*endassembly")) { - return 4+2 ; - } - - return 4 ; -} - -static void SafeSetLevel(int line, int level, Accessor &styler) -{ - if ( line < 0 ) - return ; - - int mask = ((~SC_FOLDLEVELHEADERFLAG) | (~SC_FOLDLEVELWHITEFLAG)); - - if ( (level & mask) < 0 ) - return ; - - if ( styler.LevelAt(line) != level ) - styler.SetLevel(line, level) ; -} - -static void FoldABAQUSDoc(unsigned int startPos, int length, int, -WordList *[], Accessor &styler) { - int startLine = styler.GetLine(startPos) ; - int endLine = styler.GetLine(startPos+length-1) ; - - // bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - // We want to deal with all the cases - // To know the correct indentlevel, we need to look back to the - // previous command line indentation level - // order of formatting keyline datalines commentlines - int beginData = -1 ; - int beginComment = -1 ; - int prvKeyLine = startLine ; - int prvKeyLineTp = 0 ; - - // Scan until we find the previous keyword line - // this will give us the level reference that we need - while ( prvKeyLine > 0 ) { - prvKeyLine-- ; - prvKeyLineTp = LineType(prvKeyLine, styler) ; - if ( prvKeyLineTp & 4 ) - break ; - } - - // Determine the base line level of all lines following - // the previous keyword - // new keyword lines are placed on this level - //if ( prvKeyLineTp & 4 ) { - int level = styler.LevelAt(prvKeyLine) & ~SC_FOLDLEVELHEADERFLAG ; - //} - - // uncomment line below if weird behaviour continues - prvKeyLine = -1 ; - - // Now start scanning over the lines. - for ( int line = startLine; line <= endLine; line++ ) { - int lineType = LineType(line, styler) ; - - // Check for comment line - if ( lineType == 8 ) { - if ( beginComment < 0 ) { - beginComment = line ; - } - } - - // Check for data line - if ( (lineType == 1) || (lineType == 3) ) { - if ( beginData < 0 ) { - if ( beginComment >= 0 ) { - beginData = beginComment ; - } else { - beginData = line ; - } - } - beginComment = -1 ; - } - - // Check for keywordline. - // As soon as a keyword line is encountered, we can set the - // levels of everything from the previous keyword line to this one - if ( lineType & 4 ) { - // this is a keyword, we can now place the previous keyword - // all its data lines and the remainder - - // Write comments and data line - if ( beginComment < 0 ) { - beginComment = line ; - } - - if ( beginData < 0 ) { - beginData = beginComment ; - if ( prvKeyLineTp != 5 ) - SafeSetLevel(prvKeyLine, level, styler) ; - else - SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; - } else { - SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; - } - - int datLevel = level + 1 ; - if ( !(prvKeyLineTp & 4) ) { - datLevel = level ; - } - - for ( int ll = beginData; ll < beginComment; ll++ ) - SafeSetLevel(ll, datLevel, styler) ; - - // The keyword we just found is going to be written at another level - // if we have a type 5 and type 6 - if ( prvKeyLineTp == 5 ) { - level += 1 ; - } - - if ( prvKeyLineTp == 6 ) { - level -= 1 ; - if ( level < 0 ) { - level = 0 ; - } - } - - for ( int lll = beginComment; lll < line; lll++ ) - SafeSetLevel(lll, level, styler) ; - - // wrap and reset - beginComment = -1 ; - beginData = -1 ; - prvKeyLine = line ; - prvKeyLineTp = lineType ; - } - - } - - if ( beginComment < 0 ) { - beginComment = endLine + 1 ; - } else { - // We need to find out whether this comment block is followed by - // a data line or a keyword line - const int docLines = styler.GetLine(styler.Length() - 1); - - for ( int line = endLine + 1; line <= docLines; line++ ) { - int lineType = LineType(line, styler) ; - - if ( lineType != 8 ) { - if ( !(lineType & 4) ) { - beginComment = endLine + 1 ; - } - break ; - } - } - } - - if ( beginData < 0 ) { - beginData = beginComment ; - if ( prvKeyLineTp != 5 ) - SafeSetLevel(prvKeyLine, level, styler) ; - else - SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; - } else { - SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; - } - - int datLevel = level + 1 ; - if ( !(prvKeyLineTp & 4) ) { - datLevel = level ; - } - - for ( int ll = beginData; ll < beginComment; ll++ ) - SafeSetLevel(ll, datLevel, styler) ; - - if ( prvKeyLineTp == 5 ) { - level += 1 ; - } - - if ( prvKeyLineTp == 6 ) { - level -= 1 ; - } - for ( int m = beginComment; m <= endLine; m++ ) - SafeSetLevel(m, level, styler) ; -} - -static const char * const abaqusWordListDesc[] = { - "processors", - "commands", - "slashommands", - "starcommands", - "arguments", - "functions", - 0 -}; - -LexerModule lmAbaqus(SCLEX_ABAQUS, ColouriseABAQUSDoc, "abaqus", FoldABAQUSDoc, abaqusWordListDesc); +// Scintilla source code edit control +/** @file LexABAQUS.cxx + ** Lexer for ABAQUS. Based on the lexer for APDL by Hadar Raz. + ** By Sergio Lucato. + ** Sort of completely rewritten by Gertjan Kloosterman + **/ +// The License.txt file describes the conditions under which this software may be distributed. + +// Code folding copyied and modified from LexBasic.cxx + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80 && (isalnum(ch) || (ch == '_'))); +} + +static inline bool IsAKeywordChar(const int ch) { + return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == ' '))); +} + +static inline bool IsASetChar(const int ch) { + return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == '.') || (ch == '-'))); +} + +static inline bool IsAnOperator(char ch) { + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '^' || + ch == '[' || ch == ']' || ch == '<' || ch == '&' || + ch == '>' || ch == ',' || ch == '|' || ch == '~' || + ch == '$' || ch == ':' || ch == '%') + return true; + return false; +} + +static void ColouriseABAQUSDoc(unsigned int startPos, int length, int initStyle, WordList*[] /* *keywordlists[] */, + Accessor &styler) { + enum localState { KW_LINE_KW, KW_LINE_COMMA, KW_LINE_PAR, KW_LINE_EQ, KW_LINE_VAL, \ + DAT_LINE_VAL, DAT_LINE_COMMA,\ + COMMENT_LINE,\ + ST_ERROR, LINE_END } state ; + + // Do not leak onto next line + state = LINE_END ; + initStyle = SCE_ABAQUS_DEFAULT; + StyleContext sc(startPos, length, initStyle, styler); + + // Things are actually quite simple + // we have commentlines + // keywordlines and datalines + // On a data line there will only be colouring of numbers + // a keyword line is constructed as + // *word,[ paramname[=paramvalue]]* + // if the line ends with a , the keyword line continues onto the new line + + for (; sc.More(); sc.Forward()) { + switch ( state ) { + case KW_LINE_KW : + if ( sc.atLineEnd ) { + // finished the line in keyword state, switch to LINE_END + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( IsAKeywordChar(sc.ch) ) { + // nothing changes + state = KW_LINE_KW ; + } else if ( sc.ch == ',' ) { + // Well well we say a comma, arguments *MUST* follow + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = KW_LINE_COMMA ; + } else { + // Flag an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + // Done with processing + break ; + case KW_LINE_COMMA : + // acomma on a keywordline was seen + if ( IsAKeywordChar(sc.ch)) { + sc.SetState(SCE_ABAQUS_ARGUMENT) ; + state = KW_LINE_PAR ; + } else if ( sc.atLineEnd || (sc.ch == ',') ) { + // we remain in keyword mode + state = KW_LINE_COMMA ; + } else if ( sc.ch == ' ' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = KW_LINE_COMMA ; + } else { + // Anything else constitutes an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case KW_LINE_PAR : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( IsAKeywordChar(sc.ch) || (sc.ch == '-') ) { + // remain in this state + state = KW_LINE_PAR ; + } else if ( sc.ch == ',' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = KW_LINE_COMMA ; + } else if ( sc.ch == '=' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = KW_LINE_EQ ; + } else { + // Anything else constitutes an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case KW_LINE_EQ : + if ( sc.ch == ' ' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + // remain in this state + state = KW_LINE_EQ ; + } else if ( IsADigit(sc.ch) || (sc.ch == '-') || (sc.ch == '.' && IsADigit(sc.chNext)) ) { + sc.SetState(SCE_ABAQUS_NUMBER) ; + state = KW_LINE_VAL ; + } else if ( IsAKeywordChar(sc.ch) ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = KW_LINE_VAL ; + } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { + sc.SetState(SCE_ABAQUS_STRING) ; + state = KW_LINE_VAL ; + } else { + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case KW_LINE_VAL : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( IsASetChar(sc.ch) && (sc.state == SCE_ABAQUS_DEFAULT) ) { + // nothing changes + state = KW_LINE_VAL ; + } else if (( (IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || + ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) && + (sc.state == SCE_ABAQUS_NUMBER)) { + // remain in number mode + state = KW_LINE_VAL ; + } else if (sc.state == SCE_ABAQUS_STRING) { + // accept everything until a closing quote + if ( sc.ch == '\'' || sc.ch == '\"' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = KW_LINE_VAL ; + } + } else if ( sc.ch == ',' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = KW_LINE_COMMA ; + } else { + // anything else is an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case DAT_LINE_VAL : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( IsASetChar(sc.ch) && (sc.state == SCE_ABAQUS_DEFAULT) ) { + // nothing changes + state = DAT_LINE_VAL ; + } else if (( (IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || + ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) && + (sc.state == SCE_ABAQUS_NUMBER)) { + // remain in number mode + state = DAT_LINE_VAL ; + } else if (sc.state == SCE_ABAQUS_STRING) { + // accept everything until a closing quote + if ( sc.ch == '\'' || sc.ch == '\"' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = DAT_LINE_VAL ; + } + } else if ( sc.ch == ',' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = DAT_LINE_COMMA ; + } else { + // anything else is an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case DAT_LINE_COMMA : + // a comma on a data line was seen + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( sc.ch == ' ' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = DAT_LINE_COMMA ; + } else if (sc.ch == ',') { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = DAT_LINE_COMMA ; + } else if ( IsADigit(sc.ch) || (sc.ch == '-')|| (sc.ch == '.' && IsADigit(sc.chNext)) ) { + sc.SetState(SCE_ABAQUS_NUMBER) ; + state = DAT_LINE_VAL ; + } else if ( IsAKeywordChar(sc.ch) ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = DAT_LINE_VAL ; + } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { + sc.SetState(SCE_ABAQUS_STRING) ; + state = DAT_LINE_VAL ; + } else { + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case COMMENT_LINE : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } + break ; + case ST_ERROR : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } + break ; + case LINE_END : + if ( sc.atLineEnd || sc.ch == ' ' ) { + // nothing changes + state = LINE_END ; + } else if ( sc.ch == '*' ) { + if ( sc.chNext == '*' ) { + state = COMMENT_LINE ; + sc.SetState(SCE_ABAQUS_COMMENT) ; + } else { + state = KW_LINE_KW ; + sc.SetState(SCE_ABAQUS_STARCOMMAND) ; + } + } else { + // it must be a data line, things are as if we are in DAT_LINE_COMMA + if ( sc.ch == ',' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = DAT_LINE_COMMA ; + } else if ( IsADigit(sc.ch) || (sc.ch == '-')|| (sc.ch == '.' && IsADigit(sc.chNext)) ) { + sc.SetState(SCE_ABAQUS_NUMBER) ; + state = DAT_LINE_VAL ; + } else if ( IsAKeywordChar(sc.ch) ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = DAT_LINE_VAL ; + } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { + sc.SetState(SCE_ABAQUS_STRING) ; + state = DAT_LINE_VAL ; + } else { + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + } + break ; + } + } + sc.Complete(); +} + +//------------------------------------------------------------------------------ +// This copyied and modified from LexBasic.cxx +//------------------------------------------------------------------------------ + +/* Bits: + * 1 - whitespace + * 2 - operator + * 4 - identifier + * 8 - decimal digit + * 16 - hex digit + * 32 - bin digit + */ +static int character_classification[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 10, 6, + 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0 +}; + +static bool IsSpace(int c) { + return c < 128 && (character_classification[c] & 1); +} + +static bool IsIdentifier(int c) { + return c < 128 && (character_classification[c] & 4); +} + +static int LowerCase(int c) +{ + if (c >= 'A' && c <= 'Z') + return 'a' + c - 'A'; + return c; +} + +static int LineEnd(int line, Accessor &styler) +{ + const int docLines = styler.GetLine(styler.Length() - 1); // Available last line + int eol_pos ; + // if the line is the last line, the eol_pos is styler.Length() + // eol will contain a new line, or a virtual new line + if ( docLines == line ) + eol_pos = styler.Length() ; + else + eol_pos = styler.LineStart(line + 1) - 1; + return eol_pos ; +} + +static int LineStart(int line, Accessor &styler) +{ + return styler.LineStart(line) ; +} + +// LineType +// +// bits determines the line type +// 1 : data line +// 2 : only whitespace +// 3 : data line with only whitespace +// 4 : keyword line +// 5 : block open keyword line +// 6 : block close keyword line +// 7 : keyword line in error +// 8 : comment line +static int LineType(int line, Accessor &styler) { + int pos = LineStart(line, styler) ; + int eol_pos = LineEnd(line, styler) ; + + int c ; + char ch = ' '; + + int i = pos ; + while ( i < eol_pos ) { + c = styler.SafeGetCharAt(i); + ch = static_cast(LowerCase(c)); + // We can say something as soon as no whitespace + // was encountered + if ( !IsSpace(c) ) + break ; + i++ ; + } + + if ( i >= eol_pos ) { + // This is a whitespace line, currently + // classifies as data line + return 3 ; + } + + if ( ch != '*' ) { + // This is a data line + return 1 ; + } + + if ( i == eol_pos - 1 ) { + // Only a single *, error but make keyword line + return 4+3 ; + } + + // This means we can have a second character + // if that is also a * this means a comment + // otherwise it is a keyword. + c = styler.SafeGetCharAt(i+1); + ch = static_cast(LowerCase(c)); + if ( ch == '*' ) { + return 8 ; + } + + // At this point we know this is a keyword line + // the character at position i is a * + // it is not a comment line + char word[256] ; + int wlen = 0; + + word[wlen] = '*' ; + wlen++ ; + + i++ ; + while ( (i < eol_pos) && (wlen < 255) ) { + c = styler.SafeGetCharAt(i); + ch = static_cast(LowerCase(c)); + + if ( (!IsSpace(c)) && (!IsIdentifier(c)) ) + break ; + + if ( IsIdentifier(c) ) { + word[wlen] = ch ; + wlen++ ; + } + + i++ ; + } + + word[wlen] = 0 ; + + // Make a comparison + if ( !strcmp(word, "*step") || + !strcmp(word, "*part") || + !strcmp(word, "*instance") || + !strcmp(word, "*assembly")) { + return 4+1 ; + } + + if ( !strcmp(word, "*endstep") || + !strcmp(word, "*endpart") || + !strcmp(word, "*endinstance") || + !strcmp(word, "*endassembly")) { + return 4+2 ; + } + + return 4 ; +} + +static void SafeSetLevel(int line, int level, Accessor &styler) +{ + if ( line < 0 ) + return ; + + int mask = ((~SC_FOLDLEVELHEADERFLAG) | (~SC_FOLDLEVELWHITEFLAG)); + + if ( (level & mask) < 0 ) + return ; + + if ( styler.LevelAt(line) != level ) + styler.SetLevel(line, level) ; +} + +static void FoldABAQUSDoc(unsigned int startPos, int length, int, +WordList *[], Accessor &styler) { + int startLine = styler.GetLine(startPos) ; + int endLine = styler.GetLine(startPos+length-1) ; + + // bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + // We want to deal with all the cases + // To know the correct indentlevel, we need to look back to the + // previous command line indentation level + // order of formatting keyline datalines commentlines + int beginData = -1 ; + int beginComment = -1 ; + int prvKeyLine = startLine ; + int prvKeyLineTp = 0 ; + + // Scan until we find the previous keyword line + // this will give us the level reference that we need + while ( prvKeyLine > 0 ) { + prvKeyLine-- ; + prvKeyLineTp = LineType(prvKeyLine, styler) ; + if ( prvKeyLineTp & 4 ) + break ; + } + + // Determine the base line level of all lines following + // the previous keyword + // new keyword lines are placed on this level + //if ( prvKeyLineTp & 4 ) { + int level = styler.LevelAt(prvKeyLine) & ~SC_FOLDLEVELHEADERFLAG ; + //} + + // uncomment line below if weird behaviour continues + prvKeyLine = -1 ; + + // Now start scanning over the lines. + for ( int line = startLine; line <= endLine; line++ ) { + int lineType = LineType(line, styler) ; + + // Check for comment line + if ( lineType == 8 ) { + if ( beginComment < 0 ) { + beginComment = line ; + } + } + + // Check for data line + if ( (lineType == 1) || (lineType == 3) ) { + if ( beginData < 0 ) { + if ( beginComment >= 0 ) { + beginData = beginComment ; + } else { + beginData = line ; + } + } + beginComment = -1 ; + } + + // Check for keywordline. + // As soon as a keyword line is encountered, we can set the + // levels of everything from the previous keyword line to this one + if ( lineType & 4 ) { + // this is a keyword, we can now place the previous keyword + // all its data lines and the remainder + + // Write comments and data line + if ( beginComment < 0 ) { + beginComment = line ; + } + + if ( beginData < 0 ) { + beginData = beginComment ; + if ( prvKeyLineTp != 5 ) + SafeSetLevel(prvKeyLine, level, styler) ; + else + SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; + } else { + SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; + } + + int datLevel = level + 1 ; + if ( !(prvKeyLineTp & 4) ) { + datLevel = level ; + } + + for ( int ll = beginData; ll < beginComment; ll++ ) + SafeSetLevel(ll, datLevel, styler) ; + + // The keyword we just found is going to be written at another level + // if we have a type 5 and type 6 + if ( prvKeyLineTp == 5 ) { + level += 1 ; + } + + if ( prvKeyLineTp == 6 ) { + level -= 1 ; + if ( level < 0 ) { + level = 0 ; + } + } + + for ( int lll = beginComment; lll < line; lll++ ) + SafeSetLevel(lll, level, styler) ; + + // wrap and reset + beginComment = -1 ; + beginData = -1 ; + prvKeyLine = line ; + prvKeyLineTp = lineType ; + } + + } + + if ( beginComment < 0 ) { + beginComment = endLine + 1 ; + } else { + // We need to find out whether this comment block is followed by + // a data line or a keyword line + const int docLines = styler.GetLine(styler.Length() - 1); + + for ( int line = endLine + 1; line <= docLines; line++ ) { + int lineType = LineType(line, styler) ; + + if ( lineType != 8 ) { + if ( !(lineType & 4) ) { + beginComment = endLine + 1 ; + } + break ; + } + } + } + + if ( beginData < 0 ) { + beginData = beginComment ; + if ( prvKeyLineTp != 5 ) + SafeSetLevel(prvKeyLine, level, styler) ; + else + SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; + } else { + SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; + } + + int datLevel = level + 1 ; + if ( !(prvKeyLineTp & 4) ) { + datLevel = level ; + } + + for ( int ll = beginData; ll < beginComment; ll++ ) + SafeSetLevel(ll, datLevel, styler) ; + + if ( prvKeyLineTp == 5 ) { + level += 1 ; + } + + if ( prvKeyLineTp == 6 ) { + level -= 1 ; + } + for ( int m = beginComment; m <= endLine; m++ ) + SafeSetLevel(m, level, styler) ; +} + +static const char * const abaqusWordListDesc[] = { + "processors", + "commands", + "slashommands", + "starcommands", + "arguments", + "functions", + 0 +}; + +LexerModule lmAbaqus(SCLEX_ABAQUS, ColouriseABAQUSDoc, "abaqus", FoldABAQUSDoc, abaqusWordListDesc); diff --git a/scintilla/lexers/LexAda.cxx b/ThirdLibs/scintilla/lexers/LexAda.cxx similarity index 95% rename from scintilla/lexers/LexAda.cxx rename to ThirdLibs/scintilla/lexers/LexAda.cxx index 47a408b0..49eb2c68 100644 --- a/scintilla/lexers/LexAda.cxx +++ b/ThirdLibs/scintilla/lexers/LexAda.cxx @@ -1,530 +1,530 @@ -// Scintilla source code edit control -/** @file LexAda.cxx - ** Lexer for Ada 95 - **/ -// Copyright 2002 by Sergey Koshcheyev -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/* - * Interface - */ - -static void ColouriseDocument( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler); - -static const char * const adaWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmAda(SCLEX_ADA, ColouriseDocument, "ada", NULL, adaWordListDesc); - -/* - * Implementation - */ - -// Functions that have apostropheStartsAttribute as a parameter set it according to whether -// an apostrophe encountered after processing the current token will start an attribute or -// a character literal. -static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL); -static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute); -static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute); - -static inline bool IsDelimiterCharacter(int ch); -static inline bool IsNumberStartCharacter(int ch); -static inline bool IsNumberCharacter(int ch); -static inline bool IsSeparatorOrDelimiterCharacter(int ch); -static bool IsValidIdentifier(const std::string& identifier); -static bool IsValidNumber(const std::string& number); -static inline bool IsWordStartCharacter(int ch); -static inline bool IsWordCharacter(int ch); - -static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = true; - - sc.SetState(SCE_ADA_CHARACTER); - - // Skip the apostrophe and one more character (so that '' is shown as non-terminated and ''' - // is handled correctly) - sc.Forward(); - sc.Forward(); - - ColouriseContext(sc, '\'', SCE_ADA_CHARACTEREOL); -} - -static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL) { - while (!sc.atLineEnd && !sc.Match(chEnd)) { - sc.Forward(); - } - - if (!sc.atLineEnd) { - sc.ForwardSetState(SCE_ADA_DEFAULT); - } else { - sc.ChangeState(stateEOL); - } -} - -static void ColouriseComment(StyleContext& sc, bool& /*apostropheStartsAttribute*/) { - // Apostrophe meaning is not changed, but the parameter is present for uniformity - - sc.SetState(SCE_ADA_COMMENTLINE); - - while (!sc.atLineEnd) { - sc.Forward(); - } -} - -static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = sc.Match (')'); - sc.SetState(SCE_ADA_DELIMITER); - sc.ForwardSetState(SCE_ADA_DEFAULT); -} - -static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = false; - - sc.SetState(SCE_ADA_LABEL); - - // Skip "<<" - sc.Forward(); - sc.Forward(); - - std::string identifier; - - while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) { - identifier += static_cast(tolower(sc.ch)); - sc.Forward(); - } - - // Skip ">>" - if (sc.Match('>', '>')) { - sc.Forward(); - sc.Forward(); - } else { - sc.ChangeState(SCE_ADA_ILLEGAL); - } - - // If the name is an invalid identifier or a keyword, then make it invalid label - if (!IsValidIdentifier(identifier) || keywords.InList(identifier.c_str())) { - sc.ChangeState(SCE_ADA_ILLEGAL); - } - - sc.SetState(SCE_ADA_DEFAULT); - -} - -static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = true; - - std::string number; - sc.SetState(SCE_ADA_NUMBER); - - // Get all characters up to a delimiter or a separator, including points, but excluding - // double points (ranges). - while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) { - number += static_cast(sc.ch); - sc.Forward(); - } - - // Special case: exponent with sign - if ((sc.chPrev == 'e' || sc.chPrev == 'E') && - (sc.ch == '+' || sc.ch == '-')) { - number += static_cast(sc.ch); - sc.Forward (); - - while (!IsSeparatorOrDelimiterCharacter(sc.ch)) { - number += static_cast(sc.ch); - sc.Forward(); - } - } - - if (!IsValidNumber(number)) { - sc.ChangeState(SCE_ADA_ILLEGAL); - } - - sc.SetState(SCE_ADA_DEFAULT); -} - -static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = true; - - sc.SetState(SCE_ADA_STRING); - sc.Forward(); - - ColouriseContext(sc, '"', SCE_ADA_STRINGEOL); -} - -static void ColouriseWhiteSpace(StyleContext& sc, bool& /*apostropheStartsAttribute*/) { - // Apostrophe meaning is not changed, but the parameter is present for uniformity - sc.SetState(SCE_ADA_DEFAULT); - sc.ForwardSetState(SCE_ADA_DEFAULT); -} - -static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = true; - sc.SetState(SCE_ADA_IDENTIFIER); - - std::string word; - - while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) { - word += static_cast(tolower(sc.ch)); - sc.Forward(); - } - - if (!IsValidIdentifier(word)) { - sc.ChangeState(SCE_ADA_ILLEGAL); - - } else if (keywords.InList(word.c_str())) { - sc.ChangeState(SCE_ADA_WORD); - - if (word != "all") { - apostropheStartsAttribute = false; - } - } - - sc.SetState(SCE_ADA_DEFAULT); -} - -// -// ColouriseDocument -// - -static void ColouriseDocument( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) { - WordList &keywords = *keywordlists[0]; - - StyleContext sc(startPos, length, initStyle, styler); - - int lineCurrent = styler.GetLine(startPos); - bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0; - - while (sc.More()) { - if (sc.atLineEnd) { - // Go to the next line - sc.Forward(); - lineCurrent++; - - // Remember the line state for future incremental lexing - styler.SetLineState(lineCurrent, apostropheStartsAttribute); - - // Don't continue any styles on the next line - sc.SetState(SCE_ADA_DEFAULT); - } - - // Comments - if (sc.Match('-', '-')) { - ColouriseComment(sc, apostropheStartsAttribute); - - // Strings - } else if (sc.Match('"')) { - ColouriseString(sc, apostropheStartsAttribute); - - // Characters - } else if (sc.Match('\'') && !apostropheStartsAttribute) { - ColouriseCharacter(sc, apostropheStartsAttribute); - - // Labels - } else if (sc.Match('<', '<')) { - ColouriseLabel(sc, keywords, apostropheStartsAttribute); - - // Whitespace - } else if (IsASpace(sc.ch)) { - ColouriseWhiteSpace(sc, apostropheStartsAttribute); - - // Delimiters - } else if (IsDelimiterCharacter(sc.ch)) { - ColouriseDelimiter(sc, apostropheStartsAttribute); - - // Numbers - } else if (IsADigit(sc.ch) || sc.ch == '#') { - ColouriseNumber(sc, apostropheStartsAttribute); - - // Keywords or identifiers - } else { - ColouriseWord(sc, keywords, apostropheStartsAttribute); - } - } - - sc.Complete(); -} - -static inline bool IsDelimiterCharacter(int ch) { - switch (ch) { - case '&': - case '\'': - case '(': - case ')': - case '*': - case '+': - case ',': - case '-': - case '.': - case '/': - case ':': - case ';': - case '<': - case '=': - case '>': - case '|': - return true; - default: - return false; - } -} - -static inline bool IsNumberCharacter(int ch) { - return IsNumberStartCharacter(ch) || - ch == '_' || - ch == '.' || - ch == '#' || - (ch >= 'a' && ch <= 'f') || - (ch >= 'A' && ch <= 'F'); -} - -static inline bool IsNumberStartCharacter(int ch) { - return IsADigit(ch); -} - -static inline bool IsSeparatorOrDelimiterCharacter(int ch) { - return IsASpace(ch) || IsDelimiterCharacter(ch); -} - -static bool IsValidIdentifier(const std::string& identifier) { - // First character can't be '_', so initialize the flag to true - bool lastWasUnderscore = true; - - size_t length = identifier.length(); - - // Zero-length identifiers are not valid (these can occur inside labels) - if (length == 0) { - return false; - } - - // Check for valid character at the start - if (!IsWordStartCharacter(identifier[0])) { - return false; - } - - // Check for only valid characters and no double underscores - for (size_t i = 0; i < length; i++) { - if (!IsWordCharacter(identifier[i]) || - (identifier[i] == '_' && lastWasUnderscore)) { - return false; - } - lastWasUnderscore = identifier[i] == '_'; - } - - // Check for underscore at the end - if (lastWasUnderscore == true) { - return false; - } - - // All checks passed - return true; -} - -static bool IsValidNumber(const std::string& number) { - size_t hashPos = number.find("#"); - bool seenDot = false; - - size_t i = 0; - size_t length = number.length(); - - if (length == 0) - return false; // Just in case - - // Decimal number - if (hashPos == std::string::npos) { - bool canBeSpecial = false; - - for (; i < length; i++) { - if (number[i] == '_') { - if (!canBeSpecial) { - return false; - } - canBeSpecial = false; - } else if (number[i] == '.') { - if (!canBeSpecial || seenDot) { - return false; - } - canBeSpecial = false; - seenDot = true; - } else if (IsADigit(number[i])) { - canBeSpecial = true; - } else { - break; - } - } - - if (!canBeSpecial) - return false; - } else { - // Based number - bool canBeSpecial = false; - int base = 0; - - // Parse base - for (; i < length; i++) { - int ch = number[i]; - if (ch == '_') { - if (!canBeSpecial) - return false; - canBeSpecial = false; - } else if (IsADigit(ch)) { - base = base * 10 + (ch - '0'); - if (base > 16) - return false; - canBeSpecial = true; - } else if (ch == '#' && canBeSpecial) { - break; - } else { - return false; - } - } - - if (base < 2) - return false; - if (i == length) - return false; - - i++; // Skip over '#' - - // Parse number - canBeSpecial = false; - - for (; i < length; i++) { - int ch = tolower(number[i]); - - if (ch == '_') { - if (!canBeSpecial) { - return false; - } - canBeSpecial = false; - - } else if (ch == '.') { - if (!canBeSpecial || seenDot) { - return false; - } - canBeSpecial = false; - seenDot = true; - - } else if (IsADigit(ch)) { - if (ch - '0' >= base) { - return false; - } - canBeSpecial = true; - - } else if (ch >= 'a' && ch <= 'f') { - if (ch - 'a' + 10 >= base) { - return false; - } - canBeSpecial = true; - - } else if (ch == '#' && canBeSpecial) { - break; - - } else { - return false; - } - } - - if (i == length) { - return false; - } - - i++; - } - - // Exponent (optional) - if (i < length) { - if (number[i] != 'e' && number[i] != 'E') - return false; - - i++; // Move past 'E' - - if (i == length) { - return false; - } - - if (number[i] == '+') - i++; - else if (number[i] == '-') { - if (seenDot) { - i++; - } else { - return false; // Integer literals should not have negative exponents - } - } - - if (i == length) { - return false; - } - - bool canBeSpecial = false; - - for (; i < length; i++) { - if (number[i] == '_') { - if (!canBeSpecial) { - return false; - } - canBeSpecial = false; - } else if (IsADigit(number[i])) { - canBeSpecial = true; - } else { - return false; - } - } - - if (!canBeSpecial) - return false; - } - - // if i == length, number was parsed successfully. - return i == length; -} - -static inline bool IsWordCharacter(int ch) { - return IsWordStartCharacter(ch) || IsADigit(ch); -} - -static inline bool IsWordStartCharacter(int ch) { - return (isascii(ch) && isalpha(ch)) || ch == '_'; -} +// Scintilla source code edit control +/** @file LexAda.cxx + ** Lexer for Ada 95 + **/ +// Copyright 2002 by Sergey Koshcheyev +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +/* + * Interface + */ + +static void ColouriseDocument( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler); + +static const char * const adaWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmAda(SCLEX_ADA, ColouriseDocument, "ada", NULL, adaWordListDesc); + +/* + * Implementation + */ + +// Functions that have apostropheStartsAttribute as a parameter set it according to whether +// an apostrophe encountered after processing the current token will start an attribute or +// a character literal. +static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL); +static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute); +static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute); + +static inline bool IsDelimiterCharacter(int ch); +static inline bool IsNumberStartCharacter(int ch); +static inline bool IsNumberCharacter(int ch); +static inline bool IsSeparatorOrDelimiterCharacter(int ch); +static bool IsValidIdentifier(const std::string& identifier); +static bool IsValidNumber(const std::string& number); +static inline bool IsWordStartCharacter(int ch); +static inline bool IsWordCharacter(int ch); + +static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = true; + + sc.SetState(SCE_ADA_CHARACTER); + + // Skip the apostrophe and one more character (so that '' is shown as non-terminated and ''' + // is handled correctly) + sc.Forward(); + sc.Forward(); + + ColouriseContext(sc, '\'', SCE_ADA_CHARACTEREOL); +} + +static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL) { + while (!sc.atLineEnd && !sc.Match(chEnd)) { + sc.Forward(); + } + + if (!sc.atLineEnd) { + sc.ForwardSetState(SCE_ADA_DEFAULT); + } else { + sc.ChangeState(stateEOL); + } +} + +static void ColouriseComment(StyleContext& sc, bool& /*apostropheStartsAttribute*/) { + // Apostrophe meaning is not changed, but the parameter is present for uniformity + + sc.SetState(SCE_ADA_COMMENTLINE); + + while (!sc.atLineEnd) { + sc.Forward(); + } +} + +static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = sc.Match (')'); + sc.SetState(SCE_ADA_DELIMITER); + sc.ForwardSetState(SCE_ADA_DEFAULT); +} + +static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = false; + + sc.SetState(SCE_ADA_LABEL); + + // Skip "<<" + sc.Forward(); + sc.Forward(); + + std::string identifier; + + while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) { + identifier += static_cast(tolower(sc.ch)); + sc.Forward(); + } + + // Skip ">>" + if (sc.Match('>', '>')) { + sc.Forward(); + sc.Forward(); + } else { + sc.ChangeState(SCE_ADA_ILLEGAL); + } + + // If the name is an invalid identifier or a keyword, then make it invalid label + if (!IsValidIdentifier(identifier) || keywords.InList(identifier.c_str())) { + sc.ChangeState(SCE_ADA_ILLEGAL); + } + + sc.SetState(SCE_ADA_DEFAULT); + +} + +static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = true; + + std::string number; + sc.SetState(SCE_ADA_NUMBER); + + // Get all characters up to a delimiter or a separator, including points, but excluding + // double points (ranges). + while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) { + number += static_cast(sc.ch); + sc.Forward(); + } + + // Special case: exponent with sign + if ((sc.chPrev == 'e' || sc.chPrev == 'E') && + (sc.ch == '+' || sc.ch == '-')) { + number += static_cast(sc.ch); + sc.Forward (); + + while (!IsSeparatorOrDelimiterCharacter(sc.ch)) { + number += static_cast(sc.ch); + sc.Forward(); + } + } + + if (!IsValidNumber(number)) { + sc.ChangeState(SCE_ADA_ILLEGAL); + } + + sc.SetState(SCE_ADA_DEFAULT); +} + +static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = true; + + sc.SetState(SCE_ADA_STRING); + sc.Forward(); + + ColouriseContext(sc, '"', SCE_ADA_STRINGEOL); +} + +static void ColouriseWhiteSpace(StyleContext& sc, bool& /*apostropheStartsAttribute*/) { + // Apostrophe meaning is not changed, but the parameter is present for uniformity + sc.SetState(SCE_ADA_DEFAULT); + sc.ForwardSetState(SCE_ADA_DEFAULT); +} + +static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = true; + sc.SetState(SCE_ADA_IDENTIFIER); + + std::string word; + + while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) { + word += static_cast(tolower(sc.ch)); + sc.Forward(); + } + + if (!IsValidIdentifier(word)) { + sc.ChangeState(SCE_ADA_ILLEGAL); + + } else if (keywords.InList(word.c_str())) { + sc.ChangeState(SCE_ADA_WORD); + + if (word != "all") { + apostropheStartsAttribute = false; + } + } + + sc.SetState(SCE_ADA_DEFAULT); +} + +// +// ColouriseDocument +// + +static void ColouriseDocument( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + WordList &keywords = *keywordlists[0]; + + StyleContext sc(startPos, length, initStyle, styler); + + int lineCurrent = styler.GetLine(startPos); + bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0; + + while (sc.More()) { + if (sc.atLineEnd) { + // Go to the next line + sc.Forward(); + lineCurrent++; + + // Remember the line state for future incremental lexing + styler.SetLineState(lineCurrent, apostropheStartsAttribute); + + // Don't continue any styles on the next line + sc.SetState(SCE_ADA_DEFAULT); + } + + // Comments + if (sc.Match('-', '-')) { + ColouriseComment(sc, apostropheStartsAttribute); + + // Strings + } else if (sc.Match('"')) { + ColouriseString(sc, apostropheStartsAttribute); + + // Characters + } else if (sc.Match('\'') && !apostropheStartsAttribute) { + ColouriseCharacter(sc, apostropheStartsAttribute); + + // Labels + } else if (sc.Match('<', '<')) { + ColouriseLabel(sc, keywords, apostropheStartsAttribute); + + // Whitespace + } else if (IsASpace(sc.ch)) { + ColouriseWhiteSpace(sc, apostropheStartsAttribute); + + // Delimiters + } else if (IsDelimiterCharacter(sc.ch)) { + ColouriseDelimiter(sc, apostropheStartsAttribute); + + // Numbers + } else if (IsADigit(sc.ch) || sc.ch == '#') { + ColouriseNumber(sc, apostropheStartsAttribute); + + // Keywords or identifiers + } else { + ColouriseWord(sc, keywords, apostropheStartsAttribute); + } + } + + sc.Complete(); +} + +static inline bool IsDelimiterCharacter(int ch) { + switch (ch) { + case '&': + case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + case '-': + case '.': + case '/': + case ':': + case ';': + case '<': + case '=': + case '>': + case '|': + return true; + default: + return false; + } +} + +static inline bool IsNumberCharacter(int ch) { + return IsNumberStartCharacter(ch) || + ch == '_' || + ch == '.' || + ch == '#' || + (ch >= 'a' && ch <= 'f') || + (ch >= 'A' && ch <= 'F'); +} + +static inline bool IsNumberStartCharacter(int ch) { + return IsADigit(ch); +} + +static inline bool IsSeparatorOrDelimiterCharacter(int ch) { + return IsASpace(ch) || IsDelimiterCharacter(ch); +} + +static bool IsValidIdentifier(const std::string& identifier) { + // First character can't be '_', so initialize the flag to true + bool lastWasUnderscore = true; + + size_t length = identifier.length(); + + // Zero-length identifiers are not valid (these can occur inside labels) + if (length == 0) { + return false; + } + + // Check for valid character at the start + if (!IsWordStartCharacter(identifier[0])) { + return false; + } + + // Check for only valid characters and no double underscores + for (size_t i = 0; i < length; i++) { + if (!IsWordCharacter(identifier[i]) || + (identifier[i] == '_' && lastWasUnderscore)) { + return false; + } + lastWasUnderscore = identifier[i] == '_'; + } + + // Check for underscore at the end + if (lastWasUnderscore == true) { + return false; + } + + // All checks passed + return true; +} + +static bool IsValidNumber(const std::string& number) { + size_t hashPos = number.find("#"); + bool seenDot = false; + + size_t i = 0; + size_t length = number.length(); + + if (length == 0) + return false; // Just in case + + // Decimal number + if (hashPos == std::string::npos) { + bool canBeSpecial = false; + + for (; i < length; i++) { + if (number[i] == '_') { + if (!canBeSpecial) { + return false; + } + canBeSpecial = false; + } else if (number[i] == '.') { + if (!canBeSpecial || seenDot) { + return false; + } + canBeSpecial = false; + seenDot = true; + } else if (IsADigit(number[i])) { + canBeSpecial = true; + } else { + break; + } + } + + if (!canBeSpecial) + return false; + } else { + // Based number + bool canBeSpecial = false; + int base = 0; + + // Parse base + for (; i < length; i++) { + int ch = number[i]; + if (ch == '_') { + if (!canBeSpecial) + return false; + canBeSpecial = false; + } else if (IsADigit(ch)) { + base = base * 10 + (ch - '0'); + if (base > 16) + return false; + canBeSpecial = true; + } else if (ch == '#' && canBeSpecial) { + break; + } else { + return false; + } + } + + if (base < 2) + return false; + if (i == length) + return false; + + i++; // Skip over '#' + + // Parse number + canBeSpecial = false; + + for (; i < length; i++) { + int ch = tolower(number[i]); + + if (ch == '_') { + if (!canBeSpecial) { + return false; + } + canBeSpecial = false; + + } else if (ch == '.') { + if (!canBeSpecial || seenDot) { + return false; + } + canBeSpecial = false; + seenDot = true; + + } else if (IsADigit(ch)) { + if (ch - '0' >= base) { + return false; + } + canBeSpecial = true; + + } else if (ch >= 'a' && ch <= 'f') { + if (ch - 'a' + 10 >= base) { + return false; + } + canBeSpecial = true; + + } else if (ch == '#' && canBeSpecial) { + break; + + } else { + return false; + } + } + + if (i == length) { + return false; + } + + i++; + } + + // Exponent (optional) + if (i < length) { + if (number[i] != 'e' && number[i] != 'E') + return false; + + i++; // Move past 'E' + + if (i == length) { + return false; + } + + if (number[i] == '+') + i++; + else if (number[i] == '-') { + if (seenDot) { + i++; + } else { + return false; // Integer literals should not have negative exponents + } + } + + if (i == length) { + return false; + } + + bool canBeSpecial = false; + + for (; i < length; i++) { + if (number[i] == '_') { + if (!canBeSpecial) { + return false; + } + canBeSpecial = false; + } else if (IsADigit(number[i])) { + canBeSpecial = true; + } else { + return false; + } + } + + if (!canBeSpecial) + return false; + } + + // if i == length, number was parsed successfully. + return i == length; +} + +static inline bool IsWordCharacter(int ch) { + return IsWordStartCharacter(ch) || IsADigit(ch); +} + +static inline bool IsWordStartCharacter(int ch) { + return (isascii(ch) && isalpha(ch)) || ch == '_'; +} diff --git a/scintilla/lexers/LexAsm.cxx b/ThirdLibs/scintilla/lexers/LexAsm.cxx similarity index 96% rename from scintilla/lexers/LexAsm.cxx rename to ThirdLibs/scintilla/lexers/LexAsm.cxx index 42e9b419..71e24bcc 100644 --- a/scintilla/lexers/LexAsm.cxx +++ b/ThirdLibs/scintilla/lexers/LexAsm.cxx @@ -1,460 +1,460 @@ -// Scintilla source code edit control -/** @file LexAsm.cxx - ** Lexer for Assembler, just for the MASM syntax - ** Written by The Black Horus - ** Enhancements and NASM stuff by Kein-Hong Man, 2003-10 - ** SCE_ASM_COMMENTBLOCK and SCE_ASM_CHARACTER are for future GNU as colouring - ** Converted to lexer object and added further folding features/properties by "Udo Lechner" - **/ -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" -#include "OptionSet.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || - ch == '_' || ch == '?'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' || - ch == '%' || ch == '@' || ch == '$' || ch == '?'); -} - -static inline bool IsAsmOperator(const int ch) { - if ((ch < 0x80) && (isalnum(ch))) - return false; - // '.' left out as it is used to make up numbers - if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || ch == '^' || - ch == '[' || ch == ']' || ch == '<' || ch == '&' || - ch == '>' || ch == ',' || ch == '|' || ch == '~' || - ch == '%' || ch == ':') - return true; - return false; -} - -static bool IsStreamCommentStyle(int style) { - return style == SCE_ASM_COMMENTDIRECTIVE || style == SCE_ASM_COMMENTBLOCK; -} - -static inline int LowerCase(int c) { - if (c >= 'A' && c <= 'Z') - return 'a' + c - 'A'; - return c; -} - -// An individual named option for use in an OptionSet - -// Options used for LexerAsm -struct OptionsAsm { - std::string delimiter; - bool fold; - bool foldSyntaxBased; - bool foldCommentMultiline; - bool foldCommentExplicit; - std::string foldExplicitStart; - std::string foldExplicitEnd; - bool foldExplicitAnywhere; - bool foldCompact; - OptionsAsm() { - delimiter = ""; - fold = false; - foldSyntaxBased = true; - foldCommentMultiline = false; - foldCommentExplicit = false; - foldExplicitStart = ""; - foldExplicitEnd = ""; - foldExplicitAnywhere = false; - foldCompact = true; - } -}; - -static const char * const asmWordListDesc[] = { - "CPU instructions", - "FPU instructions", - "Registers", - "Directives", - "Directive operands", - "Extended instructions", - "Directives4Foldstart", - "Directives4Foldend", - 0 -}; - -struct OptionSetAsm : public OptionSet { - OptionSetAsm() { - DefineProperty("lexer.asm.comment.delimiter", &OptionsAsm::delimiter, - "Character used for COMMENT directive's delimiter, replacing the standard \"~\"."); - - DefineProperty("fold", &OptionsAsm::fold); - - DefineProperty("fold.asm.syntax.based", &OptionsAsm::foldSyntaxBased, - "Set this property to 0 to disable syntax based folding."); - - DefineProperty("fold.asm.comment.multiline", &OptionsAsm::foldCommentMultiline, - "Set this property to 1 to enable folding multi-line comments."); - - DefineProperty("fold.asm.comment.explicit", &OptionsAsm::foldCommentExplicit, - "This option enables folding explicit fold points when using the Asm lexer. " - "Explicit fold points allows adding extra folding by placing a ;{ comment at the start and a ;} " - "at the end of a section that should fold."); - - DefineProperty("fold.asm.explicit.start", &OptionsAsm::foldExplicitStart, - "The string to use for explicit fold start points, replacing the standard ;{."); - - DefineProperty("fold.asm.explicit.end", &OptionsAsm::foldExplicitEnd, - "The string to use for explicit fold end points, replacing the standard ;}."); - - DefineProperty("fold.asm.explicit.anywhere", &OptionsAsm::foldExplicitAnywhere, - "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); - - DefineProperty("fold.compact", &OptionsAsm::foldCompact); - - DefineWordListSets(asmWordListDesc); - } -}; - -class LexerAsm : public ILexer { - WordList cpuInstruction; - WordList mathInstruction; - WordList registers; - WordList directive; - WordList directiveOperand; - WordList extInstruction; - WordList directives4foldstart; - WordList directives4foldend; - OptionsAsm options; - OptionSetAsm osAsm; -public: - LexerAsm() { - } - ~LexerAsm() { - } - void SCI_METHOD Release() { - delete this; - } - int SCI_METHOD Version() const { - return lvOriginal; - } - const char * SCI_METHOD PropertyNames() { - return osAsm.PropertyNames(); - } - int SCI_METHOD PropertyType(const char *name) { - return osAsm.PropertyType(name); - } - const char * SCI_METHOD DescribeProperty(const char *name) { - return osAsm.DescribeProperty(name); - } - int SCI_METHOD PropertySet(const char *key, const char *val); - const char * SCI_METHOD DescribeWordListSets() { - return osAsm.DescribeWordListSets(); - } - int SCI_METHOD WordListSet(int n, const char *wl); - void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); - void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); - - void * SCI_METHOD PrivateCall(int, void *) { - return 0; - } - - static ILexer *LexerFactoryAsm() { - return new LexerAsm(); - } -}; - -int SCI_METHOD LexerAsm::PropertySet(const char *key, const char *val) { - if (osAsm.PropertySet(&options, key, val)) { - return 0; - } - return -1; -} - -int SCI_METHOD LexerAsm::WordListSet(int n, const char *wl) { - WordList *wordListN = 0; - switch (n) { - case 0: - wordListN = &cpuInstruction; - break; - case 1: - wordListN = &mathInstruction; - break; - case 2: - wordListN = ®isters; - break; - case 3: - wordListN = &directive; - break; - case 4: - wordListN = &directiveOperand; - break; - case 5: - wordListN = &extInstruction; - break; - case 6: - wordListN = &directives4foldstart; - break; - case 7: - wordListN = &directives4foldend; - break; - } - int firstModification = -1; - if (wordListN) { - WordList wlNew; - wlNew.Set(wl); - if (*wordListN != wlNew) { - wordListN->Set(wl); - firstModification = 0; - } - } - return firstModification; -} - -void SCI_METHOD LexerAsm::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { - LexAccessor styler(pAccess); - - // Do not leak onto next line - if (initStyle == SCE_ASM_STRINGEOL) - initStyle = SCE_ASM_DEFAULT; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) - { - - // Prevent SCE_ASM_STRINGEOL from leaking back to previous line - if (sc.atLineStart && (sc.state == SCE_ASM_STRING)) { - sc.SetState(SCE_ASM_STRING); - } else if (sc.atLineStart && (sc.state == SCE_ASM_CHARACTER)) { - sc.SetState(SCE_ASM_CHARACTER); - } - - // Handle line continuation generically. - if (sc.ch == '\\') { - if (sc.chNext == '\n' || sc.chNext == '\r') { - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - sc.Forward(); - } - continue; - } - } - - // Determine if the current state should terminate. - if (sc.state == SCE_ASM_OPERATOR) { - if (!IsAsmOperator(sc.ch)) { - sc.SetState(SCE_ASM_DEFAULT); - } - } else if (sc.state == SCE_ASM_NUMBER) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_ASM_DEFAULT); - } - } else if (sc.state == SCE_ASM_IDENTIFIER) { - if (!IsAWordChar(sc.ch) ) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - bool IsDirective = false; - - if (cpuInstruction.InList(s)) { - sc.ChangeState(SCE_ASM_CPUINSTRUCTION); - } else if (mathInstruction.InList(s)) { - sc.ChangeState(SCE_ASM_MATHINSTRUCTION); - } else if (registers.InList(s)) { - sc.ChangeState(SCE_ASM_REGISTER); - } else if (directive.InList(s)) { - sc.ChangeState(SCE_ASM_DIRECTIVE); - IsDirective = true; - } else if (directiveOperand.InList(s)) { - sc.ChangeState(SCE_ASM_DIRECTIVEOPERAND); - } else if (extInstruction.InList(s)) { - sc.ChangeState(SCE_ASM_EXTINSTRUCTION); - } - sc.SetState(SCE_ASM_DEFAULT); - if (IsDirective && !strcmp(s, "comment")) { - char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0]; - while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) { - sc.ForwardSetState(SCE_ASM_DEFAULT); - } - if (sc.ch == delimiter) { - sc.SetState(SCE_ASM_COMMENTDIRECTIVE); - } - } - } - } else if (sc.state == SCE_ASM_COMMENTDIRECTIVE) { - char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0]; - if (sc.ch == delimiter) { - while (!sc.atLineEnd) { - sc.Forward(); - } - sc.SetState(SCE_ASM_DEFAULT); - } - } else if (sc.state == SCE_ASM_COMMENT ) { - if (sc.atLineEnd) { - sc.SetState(SCE_ASM_DEFAULT); - } - } else if (sc.state == SCE_ASM_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_ASM_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_ASM_STRINGEOL); - sc.ForwardSetState(SCE_ASM_DEFAULT); - } - } else if (sc.state == SCE_ASM_CHARACTER) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_ASM_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_ASM_STRINGEOL); - sc.ForwardSetState(SCE_ASM_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_ASM_DEFAULT) { - if (sc.ch == ';'){ - sc.SetState(SCE_ASM_COMMENT); - } else if (isascii(sc.ch) && (isdigit(sc.ch) || (sc.ch == '.' && isascii(sc.chNext) && isdigit(sc.chNext)))) { - sc.SetState(SCE_ASM_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_ASM_IDENTIFIER); - } else if (sc.ch == '\"') { - sc.SetState(SCE_ASM_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_ASM_CHARACTER); - } else if (IsAsmOperator(sc.ch)) { - sc.SetState(SCE_ASM_OPERATOR); - } - } - - } - sc.Complete(); -} - -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment -// and to make it possible to fiddle the current level for "else". - -void SCI_METHOD LexerAsm::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { - - if (!options.fold) - return; - - LexAccessor styler(pAccess); - - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - char word[100]; - int wordlen = 0; - const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (options.foldCommentMultiline && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev)) { - levelNext++; - } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelNext--; - } - } - if (options.foldCommentExplicit && ((style == SCE_ASM_COMMENT) || options.foldExplicitAnywhere)) { - if (userDefinedFoldMarkers) { - if (styler.Match(i, options.foldExplicitStart.c_str())) { - levelNext++; - } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { - levelNext--; - } - } else { - if (ch == ';') { - if (chNext == '{') { - levelNext++; - } else if (chNext == '}') { - levelNext--; - } - } - } - } - if (options.foldSyntaxBased && (style == SCE_ASM_DIRECTIVE)) { - word[wordlen++] = static_cast(LowerCase(ch)); - if (wordlen == 100) { // prevent overflow - word[0] = '\0'; - wordlen = 1; - } - if (styleNext != SCE_ASM_DIRECTIVE) { // reading directive ready - word[wordlen] = '\0'; - wordlen = 0; - if (directives4foldstart.InList(word)) { - levelNext++; - } else if (directives4foldend.InList(word)){ - levelNext--; - } - } - } - if (!IsASpace(ch)) - visibleChars++; - if (atEOL || (i == endPos-1)) { - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && options.foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - if (atEOL && (i == static_cast(styler.Length()-1))) { - // There is an empty line at end of file so give it same level and empty - styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); - } - visibleChars = 0; - } - } -} - -LexerModule lmAsm(SCLEX_ASM, LexerAsm::LexerFactoryAsm, "asm", asmWordListDesc); - +// Scintilla source code edit control +/** @file LexAsm.cxx + ** Lexer for Assembler, just for the MASM syntax + ** Written by The Black Horus + ** Enhancements and NASM stuff by Kein-Hong Man, 2003-10 + ** SCE_ASM_COMMENTBLOCK and SCE_ASM_CHARACTER are for future GNU as colouring + ** Converted to lexer object and added further folding features/properties by "Udo Lechner" + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || + ch == '_' || ch == '?'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' || + ch == '%' || ch == '@' || ch == '$' || ch == '?'); +} + +static inline bool IsAsmOperator(const int ch) { + if ((ch < 0x80) && (isalnum(ch))) + return false; + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '^' || + ch == '[' || ch == ']' || ch == '<' || ch == '&' || + ch == '>' || ch == ',' || ch == '|' || ch == '~' || + ch == '%' || ch == ':') + return true; + return false; +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_ASM_COMMENTDIRECTIVE || style == SCE_ASM_COMMENTBLOCK; +} + +static inline int LowerCase(int c) { + if (c >= 'A' && c <= 'Z') + return 'a' + c - 'A'; + return c; +} + +// An individual named option for use in an OptionSet + +// Options used for LexerAsm +struct OptionsAsm { + std::string delimiter; + bool fold; + bool foldSyntaxBased; + bool foldCommentMultiline; + bool foldCommentExplicit; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere; + bool foldCompact; + OptionsAsm() { + delimiter = ""; + fold = false; + foldSyntaxBased = true; + foldCommentMultiline = false; + foldCommentExplicit = false; + foldExplicitStart = ""; + foldExplicitEnd = ""; + foldExplicitAnywhere = false; + foldCompact = true; + } +}; + +static const char * const asmWordListDesc[] = { + "CPU instructions", + "FPU instructions", + "Registers", + "Directives", + "Directive operands", + "Extended instructions", + "Directives4Foldstart", + "Directives4Foldend", + 0 +}; + +struct OptionSetAsm : public OptionSet { + OptionSetAsm() { + DefineProperty("lexer.asm.comment.delimiter", &OptionsAsm::delimiter, + "Character used for COMMENT directive's delimiter, replacing the standard \"~\"."); + + DefineProperty("fold", &OptionsAsm::fold); + + DefineProperty("fold.asm.syntax.based", &OptionsAsm::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("fold.asm.comment.multiline", &OptionsAsm::foldCommentMultiline, + "Set this property to 1 to enable folding multi-line comments."); + + DefineProperty("fold.asm.comment.explicit", &OptionsAsm::foldCommentExplicit, + "This option enables folding explicit fold points when using the Asm lexer. " + "Explicit fold points allows adding extra folding by placing a ;{ comment at the start and a ;} " + "at the end of a section that should fold."); + + DefineProperty("fold.asm.explicit.start", &OptionsAsm::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard ;{."); + + DefineProperty("fold.asm.explicit.end", &OptionsAsm::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard ;}."); + + DefineProperty("fold.asm.explicit.anywhere", &OptionsAsm::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + + DefineProperty("fold.compact", &OptionsAsm::foldCompact); + + DefineWordListSets(asmWordListDesc); + } +}; + +class LexerAsm : public ILexer { + WordList cpuInstruction; + WordList mathInstruction; + WordList registers; + WordList directive; + WordList directiveOperand; + WordList extInstruction; + WordList directives4foldstart; + WordList directives4foldend; + OptionsAsm options; + OptionSetAsm osAsm; +public: + LexerAsm() { + } + ~LexerAsm() { + } + void SCI_METHOD Release() { + delete this; + } + int SCI_METHOD Version() const { + return lvOriginal; + } + const char * SCI_METHOD PropertyNames() { + return osAsm.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) { + return osAsm.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) { + return osAsm.DescribeProperty(name); + } + int SCI_METHOD PropertySet(const char *key, const char *val); + const char * SCI_METHOD DescribeWordListSets() { + return osAsm.DescribeWordListSets(); + } + int SCI_METHOD WordListSet(int n, const char *wl); + void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + + void * SCI_METHOD PrivateCall(int, void *) { + return 0; + } + + static ILexer *LexerFactoryAsm() { + return new LexerAsm(); + } +}; + +int SCI_METHOD LexerAsm::PropertySet(const char *key, const char *val) { + if (osAsm.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +int SCI_METHOD LexerAsm::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &cpuInstruction; + break; + case 1: + wordListN = &mathInstruction; + break; + case 2: + wordListN = ®isters; + break; + case 3: + wordListN = &directive; + break; + case 4: + wordListN = &directiveOperand; + break; + case 5: + wordListN = &extInstruction; + break; + case 6: + wordListN = &directives4foldstart; + break; + case 7: + wordListN = &directives4foldend; + break; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerAsm::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + + // Do not leak onto next line + if (initStyle == SCE_ASM_STRINGEOL) + initStyle = SCE_ASM_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) + { + + // Prevent SCE_ASM_STRINGEOL from leaking back to previous line + if (sc.atLineStart && (sc.state == SCE_ASM_STRING)) { + sc.SetState(SCE_ASM_STRING); + } else if (sc.atLineStart && (sc.state == SCE_ASM_CHARACTER)) { + sc.SetState(SCE_ASM_CHARACTER); + } + + // Handle line continuation generically. + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continue; + } + } + + // Determine if the current state should terminate. + if (sc.state == SCE_ASM_OPERATOR) { + if (!IsAsmOperator(sc.ch)) { + sc.SetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_IDENTIFIER) { + if (!IsAWordChar(sc.ch) ) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + bool IsDirective = false; + + if (cpuInstruction.InList(s)) { + sc.ChangeState(SCE_ASM_CPUINSTRUCTION); + } else if (mathInstruction.InList(s)) { + sc.ChangeState(SCE_ASM_MATHINSTRUCTION); + } else if (registers.InList(s)) { + sc.ChangeState(SCE_ASM_REGISTER); + } else if (directive.InList(s)) { + sc.ChangeState(SCE_ASM_DIRECTIVE); + IsDirective = true; + } else if (directiveOperand.InList(s)) { + sc.ChangeState(SCE_ASM_DIRECTIVEOPERAND); + } else if (extInstruction.InList(s)) { + sc.ChangeState(SCE_ASM_EXTINSTRUCTION); + } + sc.SetState(SCE_ASM_DEFAULT); + if (IsDirective && !strcmp(s, "comment")) { + char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0]; + while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) { + sc.ForwardSetState(SCE_ASM_DEFAULT); + } + if (sc.ch == delimiter) { + sc.SetState(SCE_ASM_COMMENTDIRECTIVE); + } + } + } + } else if (sc.state == SCE_ASM_COMMENTDIRECTIVE) { + char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0]; + if (sc.ch == delimiter) { + while (!sc.atLineEnd) { + sc.Forward(); + } + sc.SetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_COMMENT ) { + if (sc.atLineEnd) { + sc.SetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_ASM_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_ASM_STRINGEOL); + sc.ForwardSetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_CHARACTER) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_ASM_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_ASM_STRINGEOL); + sc.ForwardSetState(SCE_ASM_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_ASM_DEFAULT) { + if (sc.ch == ';'){ + sc.SetState(SCE_ASM_COMMENT); + } else if (isascii(sc.ch) && (isdigit(sc.ch) || (sc.ch == '.' && isascii(sc.chNext) && isdigit(sc.chNext)))) { + sc.SetState(SCE_ASM_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_ASM_IDENTIFIER); + } else if (sc.ch == '\"') { + sc.SetState(SCE_ASM_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_ASM_CHARACTER); + } else if (IsAsmOperator(sc.ch)) { + sc.SetState(SCE_ASM_OPERATOR); + } + } + + } + sc.Complete(); +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "else". + +void SCI_METHOD LexerAsm::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + char word[100]; + int wordlen = 0; + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (options.foldCommentMultiline && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (options.foldCommentExplicit && ((style == SCE_ASM_COMMENT) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { + levelNext++; + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + levelNext--; + } + } else { + if (ch == ';') { + if (chNext == '{') { + levelNext++; + } else if (chNext == '}') { + levelNext--; + } + } + } + } + if (options.foldSyntaxBased && (style == SCE_ASM_DIRECTIVE)) { + word[wordlen++] = static_cast(LowerCase(ch)); + if (wordlen == 100) { // prevent overflow + word[0] = '\0'; + wordlen = 1; + } + if (styleNext != SCE_ASM_DIRECTIVE) { // reading directive ready + word[wordlen] = '\0'; + wordlen = 0; + if (directives4foldstart.InList(word)) { + levelNext++; + } else if (directives4foldend.InList(word)){ + levelNext--; + } + } + } + if (!IsASpace(ch)) + visibleChars++; + if (atEOL || (i == endPos-1)) { + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && options.foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + if (atEOL && (i == static_cast(styler.Length()-1))) { + // There is an empty line at end of file so give it same level and empty + styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); + } + visibleChars = 0; + } + } +} + +LexerModule lmAsm(SCLEX_ASM, LexerAsm::LexerFactoryAsm, "asm", asmWordListDesc); + diff --git a/scintilla/lexers/LexAsn1.cxx b/ThirdLibs/scintilla/lexers/LexAsn1.cxx similarity index 96% rename from scintilla/lexers/LexAsn1.cxx rename to ThirdLibs/scintilla/lexers/LexAsn1.cxx index dd168a74..3545b3fa 100644 --- a/scintilla/lexers/LexAsn1.cxx +++ b/ThirdLibs/scintilla/lexers/LexAsn1.cxx @@ -1,188 +1,188 @@ -// Scintilla source code edit control -/** @file LexAsn1.cxx - ** Lexer for ASN.1 - **/ -// Copyright 2004 by Herr Pfarrer rpfarrer yahoo de -// Last Updated: 20/07/2004 -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// Some char test functions -static bool isAsn1Number(int ch) -{ - return (ch >= '0' && ch <= '9'); -} - -static bool isAsn1Letter(int ch) -{ - return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); -} - -static bool isAsn1Char(int ch) -{ - return (ch == '-' ) || isAsn1Number(ch) || isAsn1Letter (ch); -} - -// -// Function determining the color of a given code portion -// Based on a "state" -// -static void ColouriseAsn1Doc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[], Accessor &styler) -{ - // The keywords - WordList &Keywords = *keywordLists[0]; - WordList &Attributes = *keywordLists[1]; - WordList &Descriptors = *keywordLists[2]; - WordList &Types = *keywordLists[3]; - - // Parse the whole buffer character by character using StyleContext - StyleContext sc(startPos, length, initStyle, styler); - for (; sc.More(); sc.Forward()) - { - // The state engine - switch (sc.state) - { - case SCE_ASN1_DEFAULT: // Plain characters -asn1_default: - if (sc.ch == '-' && sc.chNext == '-') - // A comment begins here - sc.SetState(SCE_ASN1_COMMENT); - else if (sc.ch == '"') - // A string begins here - sc.SetState(SCE_ASN1_STRING); - else if (isAsn1Number (sc.ch)) - // A number starts here (identifier should start with a letter in ASN.1) - sc.SetState(SCE_ASN1_SCALAR); - else if (isAsn1Char (sc.ch)) - // An identifier starts here (identifier always start with a letter) - sc.SetState(SCE_ASN1_IDENTIFIER); - else if (sc.ch == ':') - // A ::= operator starts here - sc.SetState(SCE_ASN1_OPERATOR); - break; - case SCE_ASN1_COMMENT: // A comment - if (sc.ch == '\r' || sc.ch == '\n') - // A comment ends here - sc.SetState(SCE_ASN1_DEFAULT); - break; - case SCE_ASN1_IDENTIFIER: // An identifier (keyword, attribute, descriptor or type) - if (!isAsn1Char (sc.ch)) - { - // The end of identifier is here: we can look for it in lists by now and change its state - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if (Keywords.InList(s)) - // It's a keyword, change its state - sc.ChangeState(SCE_ASN1_KEYWORD); - else if (Attributes.InList(s)) - // It's an attribute, change its state - sc.ChangeState(SCE_ASN1_ATTRIBUTE); - else if (Descriptors.InList(s)) - // It's a descriptor, change its state - sc.ChangeState(SCE_ASN1_DESCRIPTOR); - else if (Types.InList(s)) - // It's a type, change its state - sc.ChangeState(SCE_ASN1_TYPE); - - // Set to default now - sc.SetState(SCE_ASN1_DEFAULT); - } - break; - case SCE_ASN1_STRING: // A string delimited by "" - if (sc.ch == '"') - { - // A string ends here - sc.ForwardSetState(SCE_ASN1_DEFAULT); - - // To correctly manage a char sticking to the string quote - goto asn1_default; - } - break; - case SCE_ASN1_SCALAR: // A plain number - if (!isAsn1Number (sc.ch)) - // A number ends here - sc.SetState(SCE_ASN1_DEFAULT); - break; - case SCE_ASN1_OPERATOR: // The affectation operator ::= and wath follows (eg: ::= { org 6 } OID or ::= 12 trap) - if (sc.ch == '{') - { - // An OID definition starts here: enter the sub loop - for (; sc.More(); sc.Forward()) - { - if (isAsn1Number (sc.ch) && (!isAsn1Char (sc.chPrev) || isAsn1Number (sc.chPrev))) - // The OID number is highlighted - sc.SetState(SCE_ASN1_OID); - else if (isAsn1Char (sc.ch)) - // The OID parent identifier is plain - sc.SetState(SCE_ASN1_IDENTIFIER); - else - sc.SetState(SCE_ASN1_DEFAULT); - - if (sc.ch == '}') - // Here ends the OID and the operator sub loop: go back to main loop - break; - } - } - else if (isAsn1Number (sc.ch)) - { - // A trap number definition starts here: enter the sub loop - for (; sc.More(); sc.Forward()) - { - if (isAsn1Number (sc.ch)) - // The trap number is highlighted - sc.SetState(SCE_ASN1_OID); - else - { - // The number ends here: go back to main loop - sc.SetState(SCE_ASN1_DEFAULT); - break; - } - } - } - else if (sc.ch != ':' && sc.ch != '=' && sc.ch != ' ') - // The operator doesn't imply an OID definition nor a trap, back to main loop - goto asn1_default; // To be sure to handle actually the state change - break; - } - } - sc.Complete(); -} - -static void FoldAsn1Doc(unsigned int, int, int, WordList *[], Accessor &styler) -{ - // No folding enabled, no reason to continue... - if( styler.GetPropertyInt("fold") == 0 ) - return; - - // No folding implemented: doesn't make sense for ASN.1 -} - -static const char * const asn1WordLists[] = { - "Keywords", - "Attributes", - "Descriptors", - "Types", - 0, }; - - -LexerModule lmAns1(SCLEX_ASN1, ColouriseAsn1Doc, "asn1", FoldAsn1Doc, asn1WordLists); +// Scintilla source code edit control +/** @file LexAsn1.cxx + ** Lexer for ASN.1 + **/ +// Copyright 2004 by Herr Pfarrer rpfarrer yahoo de +// Last Updated: 20/07/2004 +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// Some char test functions +static bool isAsn1Number(int ch) +{ + return (ch >= '0' && ch <= '9'); +} + +static bool isAsn1Letter(int ch) +{ + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); +} + +static bool isAsn1Char(int ch) +{ + return (ch == '-' ) || isAsn1Number(ch) || isAsn1Letter (ch); +} + +// +// Function determining the color of a given code portion +// Based on a "state" +// +static void ColouriseAsn1Doc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[], Accessor &styler) +{ + // The keywords + WordList &Keywords = *keywordLists[0]; + WordList &Attributes = *keywordLists[1]; + WordList &Descriptors = *keywordLists[2]; + WordList &Types = *keywordLists[3]; + + // Parse the whole buffer character by character using StyleContext + StyleContext sc(startPos, length, initStyle, styler); + for (; sc.More(); sc.Forward()) + { + // The state engine + switch (sc.state) + { + case SCE_ASN1_DEFAULT: // Plain characters +asn1_default: + if (sc.ch == '-' && sc.chNext == '-') + // A comment begins here + sc.SetState(SCE_ASN1_COMMENT); + else if (sc.ch == '"') + // A string begins here + sc.SetState(SCE_ASN1_STRING); + else if (isAsn1Number (sc.ch)) + // A number starts here (identifier should start with a letter in ASN.1) + sc.SetState(SCE_ASN1_SCALAR); + else if (isAsn1Char (sc.ch)) + // An identifier starts here (identifier always start with a letter) + sc.SetState(SCE_ASN1_IDENTIFIER); + else if (sc.ch == ':') + // A ::= operator starts here + sc.SetState(SCE_ASN1_OPERATOR); + break; + case SCE_ASN1_COMMENT: // A comment + if (sc.ch == '\r' || sc.ch == '\n') + // A comment ends here + sc.SetState(SCE_ASN1_DEFAULT); + break; + case SCE_ASN1_IDENTIFIER: // An identifier (keyword, attribute, descriptor or type) + if (!isAsn1Char (sc.ch)) + { + // The end of identifier is here: we can look for it in lists by now and change its state + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if (Keywords.InList(s)) + // It's a keyword, change its state + sc.ChangeState(SCE_ASN1_KEYWORD); + else if (Attributes.InList(s)) + // It's an attribute, change its state + sc.ChangeState(SCE_ASN1_ATTRIBUTE); + else if (Descriptors.InList(s)) + // It's a descriptor, change its state + sc.ChangeState(SCE_ASN1_DESCRIPTOR); + else if (Types.InList(s)) + // It's a type, change its state + sc.ChangeState(SCE_ASN1_TYPE); + + // Set to default now + sc.SetState(SCE_ASN1_DEFAULT); + } + break; + case SCE_ASN1_STRING: // A string delimited by "" + if (sc.ch == '"') + { + // A string ends here + sc.ForwardSetState(SCE_ASN1_DEFAULT); + + // To correctly manage a char sticking to the string quote + goto asn1_default; + } + break; + case SCE_ASN1_SCALAR: // A plain number + if (!isAsn1Number (sc.ch)) + // A number ends here + sc.SetState(SCE_ASN1_DEFAULT); + break; + case SCE_ASN1_OPERATOR: // The affectation operator ::= and wath follows (eg: ::= { org 6 } OID or ::= 12 trap) + if (sc.ch == '{') + { + // An OID definition starts here: enter the sub loop + for (; sc.More(); sc.Forward()) + { + if (isAsn1Number (sc.ch) && (!isAsn1Char (sc.chPrev) || isAsn1Number (sc.chPrev))) + // The OID number is highlighted + sc.SetState(SCE_ASN1_OID); + else if (isAsn1Char (sc.ch)) + // The OID parent identifier is plain + sc.SetState(SCE_ASN1_IDENTIFIER); + else + sc.SetState(SCE_ASN1_DEFAULT); + + if (sc.ch == '}') + // Here ends the OID and the operator sub loop: go back to main loop + break; + } + } + else if (isAsn1Number (sc.ch)) + { + // A trap number definition starts here: enter the sub loop + for (; sc.More(); sc.Forward()) + { + if (isAsn1Number (sc.ch)) + // The trap number is highlighted + sc.SetState(SCE_ASN1_OID); + else + { + // The number ends here: go back to main loop + sc.SetState(SCE_ASN1_DEFAULT); + break; + } + } + } + else if (sc.ch != ':' && sc.ch != '=' && sc.ch != ' ') + // The operator doesn't imply an OID definition nor a trap, back to main loop + goto asn1_default; // To be sure to handle actually the state change + break; + } + } + sc.Complete(); +} + +static void FoldAsn1Doc(unsigned int, int, int, WordList *[], Accessor &styler) +{ + // No folding enabled, no reason to continue... + if( styler.GetPropertyInt("fold") == 0 ) + return; + + // No folding implemented: doesn't make sense for ASN.1 +} + +static const char * const asn1WordLists[] = { + "Keywords", + "Attributes", + "Descriptors", + "Types", + 0, }; + + +LexerModule lmAns1(SCLEX_ASN1, ColouriseAsn1Doc, "asn1", FoldAsn1Doc, asn1WordLists); diff --git a/scintilla/lexers/LexBaan.cxx b/ThirdLibs/scintilla/lexers/LexBaan.cxx similarity index 96% rename from scintilla/lexers/LexBaan.cxx rename to ThirdLibs/scintilla/lexers/LexBaan.cxx index 1542150c..3784f3c3 100644 --- a/scintilla/lexers/LexBaan.cxx +++ b/ThirdLibs/scintilla/lexers/LexBaan.cxx @@ -1,196 +1,196 @@ -// Scintilla source code edit control -/** @file LexBaan.cxx - ** Lexer for Baan. - ** Based heavily on LexCPP.cxx - **/ -// Copyright 2001- by Vamsi Potluru & Praveen Ambekar -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '$' || ch == ':'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static void ColouriseBaanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; - - if (initStyle == SCE_BAAN_STRINGEOL) // Does not leak onto next line - initStyle = SCE_BAAN_DEFAULT; - - int visibleChars = 0; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.state == SCE_BAAN_OPERATOR) { - sc.SetState(SCE_BAAN_DEFAULT); - } else if (sc.state == SCE_BAAN_NUMBER) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_BAAN_DEFAULT); - } - } else if (sc.state == SCE_BAAN_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_BAAN_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_BAAN_WORD2); - } - sc.SetState(SCE_BAAN_DEFAULT); - } - } else if (sc.state == SCE_BAAN_PREPROCESSOR) { - if (stylingWithinPreprocessor) { - if (IsASpace(sc.ch)) { - sc.SetState(SCE_BAAN_DEFAULT); - } - } else { - if (sc.atLineEnd && (sc.chNext != '^')) { - sc.SetState(SCE_BAAN_DEFAULT); - } - } - } else if (sc.state == SCE_BAAN_COMMENT) { - if (sc.atLineEnd) { - sc.SetState(SCE_BAAN_DEFAULT); - } - } else if (sc.state == SCE_BAAN_COMMENTDOC) { - if (sc.MatchIgnoreCase("enddllusage")) { - for (unsigned int i = 0; i < 10; i++){ - sc.Forward(); - } - sc.ForwardSetState(SCE_BAAN_DEFAULT); - } - } else if (sc.state == SCE_BAAN_STRING) { - if (sc.ch == '\"') { - sc.ForwardSetState(SCE_BAAN_DEFAULT); - } else if ((sc.atLineEnd) && (sc.chNext != '^')) { - sc.ChangeState(SCE_BAAN_STRINGEOL); - sc.ForwardSetState(SCE_C_DEFAULT); - visibleChars = 0; - } - } - - if (sc.state == SCE_BAAN_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_BAAN_NUMBER); - } else if (sc.MatchIgnoreCase("dllusage")){ - sc.SetState(SCE_BAAN_COMMENTDOC); - do { - sc.Forward(); - } while ((!sc.atLineEnd) && sc.More()); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_BAAN_IDENTIFIER); - } else if (sc.Match('|')){ - sc.SetState(SCE_BAAN_COMMENT); - } else if (sc.ch == '\"') { - sc.SetState(SCE_BAAN_STRING); - } else if (sc.ch == '#' && visibleChars == 0) { - // Preprocessor commands are alone on their line - sc.SetState(SCE_BAAN_PREPROCESSOR); - // Skip whitespace between # and preprocessor word - do { - sc.Forward(); - } while (IsASpace(sc.ch) && sc.More()); - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_BAAN_OPERATOR); - } - } - if (sc.atLineEnd) { - // Reset states to begining of colourise so no surprises - // if different sets of lines lexed. - visibleChars = 0; - } - if (!IsASpace(sc.ch)) { - visibleChars++; - } - } - sc.Complete(); -} - -static void FoldBaanDoc(unsigned int startPos, int length, int initStyle, WordList *[], - Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && - (style == SCE_BAAN_COMMENT || style == SCE_BAAN_COMMENTDOC)) { - if (style != stylePrev) { - levelCurrent++; - } else if ((style != styleNext) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelCurrent--; - } - } - if (style == SCE_BAAN_OPERATOR) { - if (ch == '{') { - levelCurrent++; - } else if (ch == '}') { - levelCurrent--; - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -LexerModule lmBaan(SCLEX_BAAN, ColouriseBaanDoc, "baan", FoldBaanDoc); +// Scintilla source code edit control +/** @file LexBaan.cxx + ** Lexer for Baan. + ** Based heavily on LexCPP.cxx + **/ +// Copyright 2001- by Vamsi Potluru & Praveen Ambekar +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '$' || ch == ':'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static void ColouriseBaanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; + + if (initStyle == SCE_BAAN_STRINGEOL) // Does not leak onto next line + initStyle = SCE_BAAN_DEFAULT; + + int visibleChars = 0; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.state == SCE_BAAN_OPERATOR) { + sc.SetState(SCE_BAAN_DEFAULT); + } else if (sc.state == SCE_BAAN_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_BAAN_DEFAULT); + } + } else if (sc.state == SCE_BAAN_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_BAAN_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_BAAN_WORD2); + } + sc.SetState(SCE_BAAN_DEFAULT); + } + } else if (sc.state == SCE_BAAN_PREPROCESSOR) { + if (stylingWithinPreprocessor) { + if (IsASpace(sc.ch)) { + sc.SetState(SCE_BAAN_DEFAULT); + } + } else { + if (sc.atLineEnd && (sc.chNext != '^')) { + sc.SetState(SCE_BAAN_DEFAULT); + } + } + } else if (sc.state == SCE_BAAN_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_BAAN_DEFAULT); + } + } else if (sc.state == SCE_BAAN_COMMENTDOC) { + if (sc.MatchIgnoreCase("enddllusage")) { + for (unsigned int i = 0; i < 10; i++){ + sc.Forward(); + } + sc.ForwardSetState(SCE_BAAN_DEFAULT); + } + } else if (sc.state == SCE_BAAN_STRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_BAAN_DEFAULT); + } else if ((sc.atLineEnd) && (sc.chNext != '^')) { + sc.ChangeState(SCE_BAAN_STRINGEOL); + sc.ForwardSetState(SCE_C_DEFAULT); + visibleChars = 0; + } + } + + if (sc.state == SCE_BAAN_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_BAAN_NUMBER); + } else if (sc.MatchIgnoreCase("dllusage")){ + sc.SetState(SCE_BAAN_COMMENTDOC); + do { + sc.Forward(); + } while ((!sc.atLineEnd) && sc.More()); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_BAAN_IDENTIFIER); + } else if (sc.Match('|')){ + sc.SetState(SCE_BAAN_COMMENT); + } else if (sc.ch == '\"') { + sc.SetState(SCE_BAAN_STRING); + } else if (sc.ch == '#' && visibleChars == 0) { + // Preprocessor commands are alone on their line + sc.SetState(SCE_BAAN_PREPROCESSOR); + // Skip whitespace between # and preprocessor word + do { + sc.Forward(); + } while (IsASpace(sc.ch) && sc.More()); + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_BAAN_OPERATOR); + } + } + if (sc.atLineEnd) { + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + } + if (!IsASpace(sc.ch)) { + visibleChars++; + } + } + sc.Complete(); +} + +static void FoldBaanDoc(unsigned int startPos, int length, int initStyle, WordList *[], + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && + (style == SCE_BAAN_COMMENT || style == SCE_BAAN_COMMENTDOC)) { + if (style != stylePrev) { + levelCurrent++; + } else if ((style != styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + if (style == SCE_BAAN_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +LexerModule lmBaan(SCLEX_BAAN, ColouriseBaanDoc, "baan", FoldBaanDoc); diff --git a/scintilla/lexers/LexBash.cxx b/ThirdLibs/scintilla/lexers/LexBash.cxx similarity index 96% rename from scintilla/lexers/LexBash.cxx rename to ThirdLibs/scintilla/lexers/LexBash.cxx index 97d8c86d..165e1049 100644 --- a/scintilla/lexers/LexBash.cxx +++ b/ThirdLibs/scintilla/lexers/LexBash.cxx @@ -1,676 +1,676 @@ -// Scintilla source code edit control -/** @file LexBash.cxx - ** Lexer for Bash. - **/ -// Copyright 2004-2010 by Neil Hodgson -// Adapted from LexPerl by Kein-Hong Man 2004 -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#define HERE_DELIM_MAX 256 - -// define this if you want 'invalid octals' to be marked as errors -// usually, this is not a good idea, permissive lexing is better -#undef PEDANTIC_OCTAL - -#define BASH_BASE_ERROR 65 -#define BASH_BASE_DECIMAL 66 -#define BASH_BASE_HEX 67 -#ifdef PEDANTIC_OCTAL -#define BASH_BASE_OCTAL 68 -#define BASH_BASE_OCTAL_ERROR 69 -#endif - -// state constants for parts of a bash command segment -#define BASH_CMD_BODY 0 -#define BASH_CMD_START 1 -#define BASH_CMD_WORD 2 -#define BASH_CMD_TEST 3 -#define BASH_CMD_ARITH 4 -#define BASH_CMD_DELIM 5 - -static inline int translateBashDigit(int ch) { - if (ch >= '0' && ch <= '9') { - return ch - '0'; - } else if (ch >= 'a' && ch <= 'z') { - return ch - 'a' + 10; - } else if (ch >= 'A' && ch <= 'Z') { - return ch - 'A' + 36; - } else if (ch == '@') { - return 62; - } else if (ch == '_') { - return 63; - } - return BASH_BASE_ERROR; -} - -static inline int getBashNumberBase(char *s) { - int i = 0; - int base = 0; - while (*s) { - base = base * 10 + (*s++ - '0'); - i++; - } - if (base > 64 || i > 2) { - return BASH_BASE_ERROR; - } - return base; -} - -static int opposite(int ch) { - if (ch == '(') return ')'; - if (ch == '[') return ']'; - if (ch == '{') return '}'; - if (ch == '<') return '>'; - return ch; -} - -static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList cmdDelimiter, bashStruct, bashStruct_in; - cmdDelimiter.Set("| || |& & && ; ;; ( ) { }"); - bashStruct.Set("if elif fi while until else then do done esac eval"); - bashStruct_in.Set("for case select"); - - CharacterSet setWordStart(CharacterSet::setAlpha, "_"); - // note that [+-] are often parts of identifiers in shell scripts - CharacterSet setWord(CharacterSet::setAlphaNum, "._+-"); - CharacterSet setBashOperator(CharacterSet::setNone, "^&%()-+=|{}[]:;>,*/(ch); - Delimiter[DelimiterLength] = '\0'; - } - ~HereDocCls() { - delete []Delimiter; - } - }; - HereDocCls HereDoc; - - class QuoteCls { // Class to manage quote pairs (simplified vs LexPerl) - public: - int Count; - int Up, Down; - QuoteCls() { - Count = 0; - Up = '\0'; - Down = '\0'; - } - void Open(int u) { - Count++; - Up = u; - Down = opposite(Up); - } - void Start(int u) { - Count = 0; - Open(u); - } - }; - QuoteCls Quote; - - int numBase = 0; - int digit; - unsigned int endPos = startPos + length; - int cmdState = BASH_CMD_START; - int testExprType = 0; - - // Always backtracks to the start of a line that is not a continuation - // of the previous line (i.e. start of a bash command segment) - int ln = styler.GetLine(startPos); - for (;;) { - startPos = styler.LineStart(ln); - if (ln == 0 || styler.GetLineState(ln) == BASH_CMD_START) - break; - ln--; - } - initStyle = SCE_SH_DEFAULT; - - StyleContext sc(startPos, endPos - startPos, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - // handle line continuation, updates per-line stored state - if (sc.atLineStart) { - ln = styler.GetLine(sc.currentPos); - if (sc.state == SCE_SH_STRING - || sc.state == SCE_SH_BACKTICKS - || sc.state == SCE_SH_CHARACTER - || sc.state == SCE_SH_HERE_Q - || sc.state == SCE_SH_COMMENTLINE - || sc.state == SCE_SH_PARAM) { - // force backtrack while retaining cmdState - styler.SetLineState(ln, BASH_CMD_BODY); - } else { - if (ln > 0) { - if ((sc.GetRelative(-3) == '\\' && sc.GetRelative(-2) == '\r' && sc.chPrev == '\n') - || sc.GetRelative(-2) == '\\') { // handle '\' line continuation - // retain last line's state - } else - cmdState = BASH_CMD_START; - } - styler.SetLineState(ln, cmdState); - } - } - - // controls change of cmdState at the end of a non-whitespace element - // states BODY|TEST|ARITH persist until the end of a command segment - // state WORD persist, but ends with 'in' or 'do' construct keywords - int cmdStateNew = BASH_CMD_BODY; - if (cmdState == BASH_CMD_TEST || cmdState == BASH_CMD_ARITH || cmdState == BASH_CMD_WORD) - cmdStateNew = cmdState; - int stylePrev = sc.state; - - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_SH_OPERATOR: - sc.SetState(SCE_SH_DEFAULT); - if (cmdState == BASH_CMD_DELIM) // if command delimiter, start new command - cmdStateNew = BASH_CMD_START; - else if (sc.chPrev == '\\') // propagate command state if line continued - cmdStateNew = cmdState; - break; - case SCE_SH_WORD: - // "." never used in Bash variable names but used in file names - if (!setWord.Contains(sc.ch)) { - char s[500]; - char s2[10]; - sc.GetCurrent(s, sizeof(s)); - // allow keywords ending in a whitespace or command delimiter - s2[0] = static_cast(sc.ch); - s2[1] = '\0'; - bool keywordEnds = IsASpace(sc.ch) || cmdDelimiter.InList(s2); - // 'in' or 'do' may be construct keywords - if (cmdState == BASH_CMD_WORD) { - if (strcmp(s, "in") == 0 && keywordEnds) - cmdStateNew = BASH_CMD_BODY; - else if (strcmp(s, "do") == 0 && keywordEnds) - cmdStateNew = BASH_CMD_START; - else - sc.ChangeState(SCE_SH_IDENTIFIER); - sc.SetState(SCE_SH_DEFAULT); - break; - } - // a 'test' keyword starts a test expression - if (strcmp(s, "test") == 0) { - if (cmdState == BASH_CMD_START && keywordEnds) { - cmdStateNew = BASH_CMD_TEST; - testExprType = 0; - } else - sc.ChangeState(SCE_SH_IDENTIFIER); - } - // detect bash construct keywords - else if (bashStruct.InList(s)) { - if (cmdState == BASH_CMD_START && keywordEnds) - cmdStateNew = BASH_CMD_START; - else - sc.ChangeState(SCE_SH_IDENTIFIER); - } - // 'for'|'case'|'select' needs 'in'|'do' to be highlighted later - else if (bashStruct_in.InList(s)) { - if (cmdState == BASH_CMD_START && keywordEnds) - cmdStateNew = BASH_CMD_WORD; - else - sc.ChangeState(SCE_SH_IDENTIFIER); - } - // disambiguate option items and file test operators - else if (s[0] == '-') { - if (cmdState != BASH_CMD_TEST) - sc.ChangeState(SCE_SH_IDENTIFIER); - } - // disambiguate keywords and identifiers - else if (cmdState != BASH_CMD_START - || !(keywords.InList(s) && keywordEnds)) { - sc.ChangeState(SCE_SH_IDENTIFIER); - } - sc.SetState(SCE_SH_DEFAULT); - } - break; - case SCE_SH_IDENTIFIER: - if (sc.chPrev == '\\') { // for escaped chars - sc.ForwardSetState(SCE_SH_DEFAULT); - } else if (!setWord.Contains(sc.ch)) { - sc.SetState(SCE_SH_DEFAULT); - } - break; - case SCE_SH_NUMBER: - digit = translateBashDigit(sc.ch); - if (numBase == BASH_BASE_DECIMAL) { - if (sc.ch == '#') { - char s[10]; - sc.GetCurrent(s, sizeof(s)); - numBase = getBashNumberBase(s); - if (numBase != BASH_BASE_ERROR) - break; - } else if (IsADigit(sc.ch)) - break; - } else if (numBase == BASH_BASE_HEX) { - if (IsADigit(sc.ch, 16)) - break; -#ifdef PEDANTIC_OCTAL - } else if (numBase == BASH_BASE_OCTAL || - numBase == BASH_BASE_OCTAL_ERROR) { - if (digit <= 7) - break; - if (digit <= 9) { - numBase = BASH_BASE_OCTAL_ERROR; - break; - } -#endif - } else if (numBase == BASH_BASE_ERROR) { - if (digit <= 9) - break; - } else { // DD#DDDD number style handling - if (digit != BASH_BASE_ERROR) { - if (numBase <= 36) { - // case-insensitive if base<=36 - if (digit >= 36) digit -= 26; - } - if (digit < numBase) - break; - if (digit <= 9) { - numBase = BASH_BASE_ERROR; - break; - } - } - } - // fallthrough when number is at an end or error - if (numBase == BASH_BASE_ERROR -#ifdef PEDANTIC_OCTAL - || numBase == BASH_BASE_OCTAL_ERROR -#endif - ) { - sc.ChangeState(SCE_SH_ERROR); - } - sc.SetState(SCE_SH_DEFAULT); - break; - case SCE_SH_COMMENTLINE: - if (sc.atLineEnd && sc.chPrev != '\\') { - sc.SetState(SCE_SH_DEFAULT); - } - break; - case SCE_SH_HERE_DELIM: - // From Bash info: - // --------------- - // Specifier format is: <<[-]WORD - // Optional '-' is for removal of leading tabs from here-doc. - // Whitespace acceptable after <<[-] operator - // - if (HereDoc.State == 0) { // '<<' encountered - HereDoc.Quote = sc.chNext; - HereDoc.Quoted = false; - HereDoc.DelimiterLength = 0; - HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; - if (sc.chNext == '\'' || sc.chNext == '\"') { // a quoted here-doc delimiter (' or ") - sc.Forward(); - HereDoc.Quoted = true; - HereDoc.State = 1; - } else if (!HereDoc.Indent && sc.chNext == '-') { // <<- indent case - HereDoc.Indent = true; - } else if (setHereDoc.Contains(sc.chNext)) { - // an unquoted here-doc delimiter, no special handling - // TODO check what exactly bash considers part of the delim - HereDoc.State = 1; - } else if (sc.chNext == '<') { // HERE string <<< - sc.Forward(); - sc.ForwardSetState(SCE_SH_DEFAULT); - } else if (IsASpace(sc.chNext)) { - // eat whitespace - } else if (setLeftShift.Contains(sc.chNext)) { - // left shift << or <<= operator cases - sc.ChangeState(SCE_SH_OPERATOR); - sc.ForwardSetState(SCE_SH_DEFAULT); - } else { - // symbols terminates; deprecated zero-length delimiter - HereDoc.State = 1; - } - } else if (HereDoc.State == 1) { // collect the delimiter - if (setHereDoc2.Contains(sc.ch) || sc.chPrev == '\\') { - HereDoc.Append(sc.ch); - } else if (HereDoc.Quoted && sc.ch == HereDoc.Quote) { // closing quote => end of delimiter - sc.ForwardSetState(SCE_SH_DEFAULT); - } else if (sc.ch == '\\') { - // skip escape prefix - } else { - sc.SetState(SCE_SH_DEFAULT); - } - if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) { // force blowup - sc.SetState(SCE_SH_ERROR); - HereDoc.State = 0; - } - } - break; - case SCE_SH_HERE_Q: - // HereDoc.State == 2 - if (sc.atLineStart) { - sc.SetState(SCE_SH_HERE_Q); - int prefixws = 0; - while (IsASpace(sc.ch) && !sc.atLineEnd) { // whitespace prefix - sc.Forward(); - prefixws++; - } - if (prefixws > 0) - sc.SetState(SCE_SH_HERE_Q); - while (!sc.atLineEnd) { - sc.Forward(); - } - char s[HERE_DELIM_MAX]; - sc.GetCurrent(s, sizeof(s)); - if (sc.LengthCurrent() == 0) - break; - if (s[strlen(s) - 1] == '\r') - s[strlen(s) - 1] = '\0'; - if (strcmp(HereDoc.Delimiter, s) == 0) { - if ((prefixws == 0) || // indentation rule - (prefixws > 0 && HereDoc.Indent)) { - sc.SetState(SCE_SH_DEFAULT); - break; - } - } - } - break; - case SCE_SH_SCALAR: // variable names - if (!setParam.Contains(sc.ch)) { - if (sc.LengthCurrent() == 1) { - // Special variable: $(, $_ etc. - sc.ForwardSetState(SCE_SH_DEFAULT); - } else { - sc.SetState(SCE_SH_DEFAULT); - } - } - break; - case SCE_SH_STRING: // delimited styles - case SCE_SH_CHARACTER: - case SCE_SH_BACKTICKS: - case SCE_SH_PARAM: - if (sc.ch == '\\' && Quote.Up != '\\') { - sc.Forward(); - } else if (sc.ch == Quote.Down) { - Quote.Count--; - if (Quote.Count == 0) { - sc.ForwardSetState(SCE_SH_DEFAULT); - } - } else if (sc.ch == Quote.Up) { - Quote.Count++; - } - break; - } - - // Must check end of HereDoc state 1 before default state is handled - if (HereDoc.State == 1 && sc.atLineEnd) { - // Begin of here-doc (the line after the here-doc delimiter): - // Lexically, the here-doc starts from the next line after the >>, but the - // first line of here-doc seem to follow the style of the last EOL sequence - HereDoc.State = 2; - if (HereDoc.Quoted) { - if (sc.state == SCE_SH_HERE_DELIM) { - // Missing quote at end of string! We are stricter than bash. - // Colour here-doc anyway while marking this bit as an error. - sc.ChangeState(SCE_SH_ERROR); - } - // HereDoc.Quote always == '\'' - } - sc.SetState(SCE_SH_HERE_Q); - } - - // update cmdState about the current command segment - if (stylePrev != SCE_SH_DEFAULT && sc.state == SCE_SH_DEFAULT) { - cmdState = cmdStateNew; - } - // Determine if a new state should be entered. - if (sc.state == SCE_SH_DEFAULT) { - if (sc.ch == '\\') { - // Bash can escape any non-newline as a literal - sc.SetState(SCE_SH_IDENTIFIER); - if (sc.chNext == '\r' || sc.chNext == '\n') - sc.SetState(SCE_SH_OPERATOR); - } else if (IsADigit(sc.ch)) { - sc.SetState(SCE_SH_NUMBER); - numBase = BASH_BASE_DECIMAL; - if (sc.ch == '0') { // hex,octal - if (sc.chNext == 'x' || sc.chNext == 'X') { - numBase = BASH_BASE_HEX; - sc.Forward(); - } else if (IsADigit(sc.chNext)) { -#ifdef PEDANTIC_OCTAL - numBase = BASH_BASE_OCTAL; -#else - numBase = BASH_BASE_HEX; -#endif - } - } - } else if (setWordStart.Contains(sc.ch)) { - sc.SetState(SCE_SH_WORD); - } else if (sc.ch == '#') { - sc.SetState(SCE_SH_COMMENTLINE); - } else if (sc.ch == '\"') { - sc.SetState(SCE_SH_STRING); - Quote.Start(sc.ch); - } else if (sc.ch == '\'') { - sc.SetState(SCE_SH_CHARACTER); - Quote.Start(sc.ch); - } else if (sc.ch == '`') { - sc.SetState(SCE_SH_BACKTICKS); - Quote.Start(sc.ch); - } else if (sc.ch == '$') { - if (sc.Match("$((")) { - sc.SetState(SCE_SH_OPERATOR); // handle '((' later - continue; - } - sc.SetState(SCE_SH_SCALAR); - sc.Forward(); - if (sc.ch == '{') { - sc.ChangeState(SCE_SH_PARAM); - } else if (sc.ch == '\'') { - sc.ChangeState(SCE_SH_CHARACTER); - } else if (sc.ch == '"') { - sc.ChangeState(SCE_SH_STRING); - } else if (sc.ch == '(' || sc.ch == '`') { - sc.ChangeState(SCE_SH_BACKTICKS); - } else { - continue; // scalar has no delimiter pair - } - // fallthrough, open delim for $[{'"(`] - Quote.Start(sc.ch); - } else if (sc.Match('<', '<')) { - sc.SetState(SCE_SH_HERE_DELIM); - HereDoc.State = 0; - HereDoc.Indent = false; - } else if (sc.ch == '-' && // one-char file test operators - setSingleCharOp.Contains(sc.chNext) && - !setWord.Contains(sc.GetRelative(2)) && - IsASpace(sc.chPrev)) { - sc.SetState(SCE_SH_WORD); - sc.Forward(); - } else if (setBashOperator.Contains(sc.ch)) { - char s[10]; - bool isCmdDelim = false; - sc.SetState(SCE_SH_OPERATOR); - // handle opening delimiters for test/arithmetic expressions - ((,[[,[ - if (cmdState == BASH_CMD_START - || cmdState == BASH_CMD_BODY) { - if (sc.Match('(', '(')) { - cmdState = BASH_CMD_ARITH; - sc.Forward(); - } else if (sc.Match('[', '[') && IsASpace(sc.GetRelative(2))) { - cmdState = BASH_CMD_TEST; - testExprType = 1; - sc.Forward(); - } else if (sc.ch == '[' && IsASpace(sc.chNext)) { - cmdState = BASH_CMD_TEST; - testExprType = 2; - } - } - // special state -- for ((x;y;z)) in ... looping - if (cmdState == BASH_CMD_WORD && sc.Match('(', '(')) { - cmdState = BASH_CMD_ARITH; - sc.Forward(); - continue; - } - // handle command delimiters in command START|BODY|WORD state, also TEST if 'test' - if (cmdState == BASH_CMD_START - || cmdState == BASH_CMD_BODY - || cmdState == BASH_CMD_WORD - || (cmdState == BASH_CMD_TEST && testExprType == 0)) { - s[0] = static_cast(sc.ch); - if (setBashOperator.Contains(sc.chNext)) { - s[1] = static_cast(sc.chNext); - s[2] = '\0'; - isCmdDelim = cmdDelimiter.InList(s); - if (isCmdDelim) - sc.Forward(); - } - if (!isCmdDelim) { - s[1] = '\0'; - isCmdDelim = cmdDelimiter.InList(s); - } - if (isCmdDelim) { - cmdState = BASH_CMD_DELIM; - continue; - } - } - // handle closing delimiters for test/arithmetic expressions - )),]],] - if (cmdState == BASH_CMD_ARITH && sc.Match(')', ')')) { - cmdState = BASH_CMD_BODY; - sc.Forward(); - } else if (cmdState == BASH_CMD_TEST && IsASpace(sc.chPrev)) { - if (sc.Match(']', ']') && testExprType == 1) { - sc.Forward(); - cmdState = BASH_CMD_BODY; - } else if (sc.ch == ']' && testExprType == 2) { - cmdState = BASH_CMD_BODY; - } - } - } - }// sc.state - } - sc.Complete(); -} - -static bool IsCommentLine(int line, Accessor &styler) { - int pos = styler.LineStart(line); - int eol_pos = styler.LineStart(line + 1) - 1; - for (int i = pos; i < eol_pos; i++) { - char ch = styler[i]; - if (ch == '#') - return true; - else if (ch != ' ' && ch != '\t') - return false; - } - return false; -} - -static void FoldBashDoc(unsigned int startPos, int length, int, WordList *[], - Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - // Comment folding - if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) - { - if (!IsCommentLine(lineCurrent - 1, styler) - && IsCommentLine(lineCurrent + 1, styler)) - levelCurrent++; - else if (IsCommentLine(lineCurrent - 1, styler) - && !IsCommentLine(lineCurrent + 1, styler)) - levelCurrent--; - } - if (style == SCE_SH_OPERATOR) { - if (ch == '{') { - levelCurrent++; - } else if (ch == '}') { - levelCurrent--; - } - } - // Here Document folding - if (style == SCE_SH_HERE_DELIM) { - if (ch == '<' && chNext == '<') { - levelCurrent++; - } - } else if (style == SCE_SH_HERE_Q && styler.StyleAt(i+1) == SCE_PL_DEFAULT) { - levelCurrent--; - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const bashWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmBash(SCLEX_BASH, ColouriseBashDoc, "bash", FoldBashDoc, bashWordListDesc); +// Scintilla source code edit control +/** @file LexBash.cxx + ** Lexer for Bash. + **/ +// Copyright 2004-2010 by Neil Hodgson +// Adapted from LexPerl by Kein-Hong Man 2004 +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#define HERE_DELIM_MAX 256 + +// define this if you want 'invalid octals' to be marked as errors +// usually, this is not a good idea, permissive lexing is better +#undef PEDANTIC_OCTAL + +#define BASH_BASE_ERROR 65 +#define BASH_BASE_DECIMAL 66 +#define BASH_BASE_HEX 67 +#ifdef PEDANTIC_OCTAL +#define BASH_BASE_OCTAL 68 +#define BASH_BASE_OCTAL_ERROR 69 +#endif + +// state constants for parts of a bash command segment +#define BASH_CMD_BODY 0 +#define BASH_CMD_START 1 +#define BASH_CMD_WORD 2 +#define BASH_CMD_TEST 3 +#define BASH_CMD_ARITH 4 +#define BASH_CMD_DELIM 5 + +static inline int translateBashDigit(int ch) { + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } else if (ch >= 'a' && ch <= 'z') { + return ch - 'a' + 10; + } else if (ch >= 'A' && ch <= 'Z') { + return ch - 'A' + 36; + } else if (ch == '@') { + return 62; + } else if (ch == '_') { + return 63; + } + return BASH_BASE_ERROR; +} + +static inline int getBashNumberBase(char *s) { + int i = 0; + int base = 0; + while (*s) { + base = base * 10 + (*s++ - '0'); + i++; + } + if (base > 64 || i > 2) { + return BASH_BASE_ERROR; + } + return base; +} + +static int opposite(int ch) { + if (ch == '(') return ')'; + if (ch == '[') return ']'; + if (ch == '{') return '}'; + if (ch == '<') return '>'; + return ch; +} + +static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList cmdDelimiter, bashStruct, bashStruct_in; + cmdDelimiter.Set("| || |& & && ; ;; ( ) { }"); + bashStruct.Set("if elif fi while until else then do done esac eval"); + bashStruct_in.Set("for case select"); + + CharacterSet setWordStart(CharacterSet::setAlpha, "_"); + // note that [+-] are often parts of identifiers in shell scripts + CharacterSet setWord(CharacterSet::setAlphaNum, "._+-"); + CharacterSet setBashOperator(CharacterSet::setNone, "^&%()-+=|{}[]:;>,*/(ch); + Delimiter[DelimiterLength] = '\0'; + } + ~HereDocCls() { + delete []Delimiter; + } + }; + HereDocCls HereDoc; + + class QuoteCls { // Class to manage quote pairs (simplified vs LexPerl) + public: + int Count; + int Up, Down; + QuoteCls() { + Count = 0; + Up = '\0'; + Down = '\0'; + } + void Open(int u) { + Count++; + Up = u; + Down = opposite(Up); + } + void Start(int u) { + Count = 0; + Open(u); + } + }; + QuoteCls Quote; + + int numBase = 0; + int digit; + unsigned int endPos = startPos + length; + int cmdState = BASH_CMD_START; + int testExprType = 0; + + // Always backtracks to the start of a line that is not a continuation + // of the previous line (i.e. start of a bash command segment) + int ln = styler.GetLine(startPos); + for (;;) { + startPos = styler.LineStart(ln); + if (ln == 0 || styler.GetLineState(ln) == BASH_CMD_START) + break; + ln--; + } + initStyle = SCE_SH_DEFAULT; + + StyleContext sc(startPos, endPos - startPos, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + // handle line continuation, updates per-line stored state + if (sc.atLineStart) { + ln = styler.GetLine(sc.currentPos); + if (sc.state == SCE_SH_STRING + || sc.state == SCE_SH_BACKTICKS + || sc.state == SCE_SH_CHARACTER + || sc.state == SCE_SH_HERE_Q + || sc.state == SCE_SH_COMMENTLINE + || sc.state == SCE_SH_PARAM) { + // force backtrack while retaining cmdState + styler.SetLineState(ln, BASH_CMD_BODY); + } else { + if (ln > 0) { + if ((sc.GetRelative(-3) == '\\' && sc.GetRelative(-2) == '\r' && sc.chPrev == '\n') + || sc.GetRelative(-2) == '\\') { // handle '\' line continuation + // retain last line's state + } else + cmdState = BASH_CMD_START; + } + styler.SetLineState(ln, cmdState); + } + } + + // controls change of cmdState at the end of a non-whitespace element + // states BODY|TEST|ARITH persist until the end of a command segment + // state WORD persist, but ends with 'in' or 'do' construct keywords + int cmdStateNew = BASH_CMD_BODY; + if (cmdState == BASH_CMD_TEST || cmdState == BASH_CMD_ARITH || cmdState == BASH_CMD_WORD) + cmdStateNew = cmdState; + int stylePrev = sc.state; + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_SH_OPERATOR: + sc.SetState(SCE_SH_DEFAULT); + if (cmdState == BASH_CMD_DELIM) // if command delimiter, start new command + cmdStateNew = BASH_CMD_START; + else if (sc.chPrev == '\\') // propagate command state if line continued + cmdStateNew = cmdState; + break; + case SCE_SH_WORD: + // "." never used in Bash variable names but used in file names + if (!setWord.Contains(sc.ch)) { + char s[500]; + char s2[10]; + sc.GetCurrent(s, sizeof(s)); + // allow keywords ending in a whitespace or command delimiter + s2[0] = static_cast(sc.ch); + s2[1] = '\0'; + bool keywordEnds = IsASpace(sc.ch) || cmdDelimiter.InList(s2); + // 'in' or 'do' may be construct keywords + if (cmdState == BASH_CMD_WORD) { + if (strcmp(s, "in") == 0 && keywordEnds) + cmdStateNew = BASH_CMD_BODY; + else if (strcmp(s, "do") == 0 && keywordEnds) + cmdStateNew = BASH_CMD_START; + else + sc.ChangeState(SCE_SH_IDENTIFIER); + sc.SetState(SCE_SH_DEFAULT); + break; + } + // a 'test' keyword starts a test expression + if (strcmp(s, "test") == 0) { + if (cmdState == BASH_CMD_START && keywordEnds) { + cmdStateNew = BASH_CMD_TEST; + testExprType = 0; + } else + sc.ChangeState(SCE_SH_IDENTIFIER); + } + // detect bash construct keywords + else if (bashStruct.InList(s)) { + if (cmdState == BASH_CMD_START && keywordEnds) + cmdStateNew = BASH_CMD_START; + else + sc.ChangeState(SCE_SH_IDENTIFIER); + } + // 'for'|'case'|'select' needs 'in'|'do' to be highlighted later + else if (bashStruct_in.InList(s)) { + if (cmdState == BASH_CMD_START && keywordEnds) + cmdStateNew = BASH_CMD_WORD; + else + sc.ChangeState(SCE_SH_IDENTIFIER); + } + // disambiguate option items and file test operators + else if (s[0] == '-') { + if (cmdState != BASH_CMD_TEST) + sc.ChangeState(SCE_SH_IDENTIFIER); + } + // disambiguate keywords and identifiers + else if (cmdState != BASH_CMD_START + || !(keywords.InList(s) && keywordEnds)) { + sc.ChangeState(SCE_SH_IDENTIFIER); + } + sc.SetState(SCE_SH_DEFAULT); + } + break; + case SCE_SH_IDENTIFIER: + if (sc.chPrev == '\\') { // for escaped chars + sc.ForwardSetState(SCE_SH_DEFAULT); + } else if (!setWord.Contains(sc.ch)) { + sc.SetState(SCE_SH_DEFAULT); + } + break; + case SCE_SH_NUMBER: + digit = translateBashDigit(sc.ch); + if (numBase == BASH_BASE_DECIMAL) { + if (sc.ch == '#') { + char s[10]; + sc.GetCurrent(s, sizeof(s)); + numBase = getBashNumberBase(s); + if (numBase != BASH_BASE_ERROR) + break; + } else if (IsADigit(sc.ch)) + break; + } else if (numBase == BASH_BASE_HEX) { + if (IsADigit(sc.ch, 16)) + break; +#ifdef PEDANTIC_OCTAL + } else if (numBase == BASH_BASE_OCTAL || + numBase == BASH_BASE_OCTAL_ERROR) { + if (digit <= 7) + break; + if (digit <= 9) { + numBase = BASH_BASE_OCTAL_ERROR; + break; + } +#endif + } else if (numBase == BASH_BASE_ERROR) { + if (digit <= 9) + break; + } else { // DD#DDDD number style handling + if (digit != BASH_BASE_ERROR) { + if (numBase <= 36) { + // case-insensitive if base<=36 + if (digit >= 36) digit -= 26; + } + if (digit < numBase) + break; + if (digit <= 9) { + numBase = BASH_BASE_ERROR; + break; + } + } + } + // fallthrough when number is at an end or error + if (numBase == BASH_BASE_ERROR +#ifdef PEDANTIC_OCTAL + || numBase == BASH_BASE_OCTAL_ERROR +#endif + ) { + sc.ChangeState(SCE_SH_ERROR); + } + sc.SetState(SCE_SH_DEFAULT); + break; + case SCE_SH_COMMENTLINE: + if (sc.atLineEnd && sc.chPrev != '\\') { + sc.SetState(SCE_SH_DEFAULT); + } + break; + case SCE_SH_HERE_DELIM: + // From Bash info: + // --------------- + // Specifier format is: <<[-]WORD + // Optional '-' is for removal of leading tabs from here-doc. + // Whitespace acceptable after <<[-] operator + // + if (HereDoc.State == 0) { // '<<' encountered + HereDoc.Quote = sc.chNext; + HereDoc.Quoted = false; + HereDoc.DelimiterLength = 0; + HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; + if (sc.chNext == '\'' || sc.chNext == '\"') { // a quoted here-doc delimiter (' or ") + sc.Forward(); + HereDoc.Quoted = true; + HereDoc.State = 1; + } else if (!HereDoc.Indent && sc.chNext == '-') { // <<- indent case + HereDoc.Indent = true; + } else if (setHereDoc.Contains(sc.chNext)) { + // an unquoted here-doc delimiter, no special handling + // TODO check what exactly bash considers part of the delim + HereDoc.State = 1; + } else if (sc.chNext == '<') { // HERE string <<< + sc.Forward(); + sc.ForwardSetState(SCE_SH_DEFAULT); + } else if (IsASpace(sc.chNext)) { + // eat whitespace + } else if (setLeftShift.Contains(sc.chNext)) { + // left shift << or <<= operator cases + sc.ChangeState(SCE_SH_OPERATOR); + sc.ForwardSetState(SCE_SH_DEFAULT); + } else { + // symbols terminates; deprecated zero-length delimiter + HereDoc.State = 1; + } + } else if (HereDoc.State == 1) { // collect the delimiter + if (setHereDoc2.Contains(sc.ch) || sc.chPrev == '\\') { + HereDoc.Append(sc.ch); + } else if (HereDoc.Quoted && sc.ch == HereDoc.Quote) { // closing quote => end of delimiter + sc.ForwardSetState(SCE_SH_DEFAULT); + } else if (sc.ch == '\\') { + // skip escape prefix + } else { + sc.SetState(SCE_SH_DEFAULT); + } + if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) { // force blowup + sc.SetState(SCE_SH_ERROR); + HereDoc.State = 0; + } + } + break; + case SCE_SH_HERE_Q: + // HereDoc.State == 2 + if (sc.atLineStart) { + sc.SetState(SCE_SH_HERE_Q); + int prefixws = 0; + while (IsASpace(sc.ch) && !sc.atLineEnd) { // whitespace prefix + sc.Forward(); + prefixws++; + } + if (prefixws > 0) + sc.SetState(SCE_SH_HERE_Q); + while (!sc.atLineEnd) { + sc.Forward(); + } + char s[HERE_DELIM_MAX]; + sc.GetCurrent(s, sizeof(s)); + if (sc.LengthCurrent() == 0) + break; + if (s[strlen(s) - 1] == '\r') + s[strlen(s) - 1] = '\0'; + if (strcmp(HereDoc.Delimiter, s) == 0) { + if ((prefixws == 0) || // indentation rule + (prefixws > 0 && HereDoc.Indent)) { + sc.SetState(SCE_SH_DEFAULT); + break; + } + } + } + break; + case SCE_SH_SCALAR: // variable names + if (!setParam.Contains(sc.ch)) { + if (sc.LengthCurrent() == 1) { + // Special variable: $(, $_ etc. + sc.ForwardSetState(SCE_SH_DEFAULT); + } else { + sc.SetState(SCE_SH_DEFAULT); + } + } + break; + case SCE_SH_STRING: // delimited styles + case SCE_SH_CHARACTER: + case SCE_SH_BACKTICKS: + case SCE_SH_PARAM: + if (sc.ch == '\\' && Quote.Up != '\\') { + sc.Forward(); + } else if (sc.ch == Quote.Down) { + Quote.Count--; + if (Quote.Count == 0) { + sc.ForwardSetState(SCE_SH_DEFAULT); + } + } else if (sc.ch == Quote.Up) { + Quote.Count++; + } + break; + } + + // Must check end of HereDoc state 1 before default state is handled + if (HereDoc.State == 1 && sc.atLineEnd) { + // Begin of here-doc (the line after the here-doc delimiter): + // Lexically, the here-doc starts from the next line after the >>, but the + // first line of here-doc seem to follow the style of the last EOL sequence + HereDoc.State = 2; + if (HereDoc.Quoted) { + if (sc.state == SCE_SH_HERE_DELIM) { + // Missing quote at end of string! We are stricter than bash. + // Colour here-doc anyway while marking this bit as an error. + sc.ChangeState(SCE_SH_ERROR); + } + // HereDoc.Quote always == '\'' + } + sc.SetState(SCE_SH_HERE_Q); + } + + // update cmdState about the current command segment + if (stylePrev != SCE_SH_DEFAULT && sc.state == SCE_SH_DEFAULT) { + cmdState = cmdStateNew; + } + // Determine if a new state should be entered. + if (sc.state == SCE_SH_DEFAULT) { + if (sc.ch == '\\') { + // Bash can escape any non-newline as a literal + sc.SetState(SCE_SH_IDENTIFIER); + if (sc.chNext == '\r' || sc.chNext == '\n') + sc.SetState(SCE_SH_OPERATOR); + } else if (IsADigit(sc.ch)) { + sc.SetState(SCE_SH_NUMBER); + numBase = BASH_BASE_DECIMAL; + if (sc.ch == '0') { // hex,octal + if (sc.chNext == 'x' || sc.chNext == 'X') { + numBase = BASH_BASE_HEX; + sc.Forward(); + } else if (IsADigit(sc.chNext)) { +#ifdef PEDANTIC_OCTAL + numBase = BASH_BASE_OCTAL; +#else + numBase = BASH_BASE_HEX; +#endif + } + } + } else if (setWordStart.Contains(sc.ch)) { + sc.SetState(SCE_SH_WORD); + } else if (sc.ch == '#') { + sc.SetState(SCE_SH_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_SH_STRING); + Quote.Start(sc.ch); + } else if (sc.ch == '\'') { + sc.SetState(SCE_SH_CHARACTER); + Quote.Start(sc.ch); + } else if (sc.ch == '`') { + sc.SetState(SCE_SH_BACKTICKS); + Quote.Start(sc.ch); + } else if (sc.ch == '$') { + if (sc.Match("$((")) { + sc.SetState(SCE_SH_OPERATOR); // handle '((' later + continue; + } + sc.SetState(SCE_SH_SCALAR); + sc.Forward(); + if (sc.ch == '{') { + sc.ChangeState(SCE_SH_PARAM); + } else if (sc.ch == '\'') { + sc.ChangeState(SCE_SH_CHARACTER); + } else if (sc.ch == '"') { + sc.ChangeState(SCE_SH_STRING); + } else if (sc.ch == '(' || sc.ch == '`') { + sc.ChangeState(SCE_SH_BACKTICKS); + } else { + continue; // scalar has no delimiter pair + } + // fallthrough, open delim for $[{'"(`] + Quote.Start(sc.ch); + } else if (sc.Match('<', '<')) { + sc.SetState(SCE_SH_HERE_DELIM); + HereDoc.State = 0; + HereDoc.Indent = false; + } else if (sc.ch == '-' && // one-char file test operators + setSingleCharOp.Contains(sc.chNext) && + !setWord.Contains(sc.GetRelative(2)) && + IsASpace(sc.chPrev)) { + sc.SetState(SCE_SH_WORD); + sc.Forward(); + } else if (setBashOperator.Contains(sc.ch)) { + char s[10]; + bool isCmdDelim = false; + sc.SetState(SCE_SH_OPERATOR); + // handle opening delimiters for test/arithmetic expressions - ((,[[,[ + if (cmdState == BASH_CMD_START + || cmdState == BASH_CMD_BODY) { + if (sc.Match('(', '(')) { + cmdState = BASH_CMD_ARITH; + sc.Forward(); + } else if (sc.Match('[', '[') && IsASpace(sc.GetRelative(2))) { + cmdState = BASH_CMD_TEST; + testExprType = 1; + sc.Forward(); + } else if (sc.ch == '[' && IsASpace(sc.chNext)) { + cmdState = BASH_CMD_TEST; + testExprType = 2; + } + } + // special state -- for ((x;y;z)) in ... looping + if (cmdState == BASH_CMD_WORD && sc.Match('(', '(')) { + cmdState = BASH_CMD_ARITH; + sc.Forward(); + continue; + } + // handle command delimiters in command START|BODY|WORD state, also TEST if 'test' + if (cmdState == BASH_CMD_START + || cmdState == BASH_CMD_BODY + || cmdState == BASH_CMD_WORD + || (cmdState == BASH_CMD_TEST && testExprType == 0)) { + s[0] = static_cast(sc.ch); + if (setBashOperator.Contains(sc.chNext)) { + s[1] = static_cast(sc.chNext); + s[2] = '\0'; + isCmdDelim = cmdDelimiter.InList(s); + if (isCmdDelim) + sc.Forward(); + } + if (!isCmdDelim) { + s[1] = '\0'; + isCmdDelim = cmdDelimiter.InList(s); + } + if (isCmdDelim) { + cmdState = BASH_CMD_DELIM; + continue; + } + } + // handle closing delimiters for test/arithmetic expressions - )),]],] + if (cmdState == BASH_CMD_ARITH && sc.Match(')', ')')) { + cmdState = BASH_CMD_BODY; + sc.Forward(); + } else if (cmdState == BASH_CMD_TEST && IsASpace(sc.chPrev)) { + if (sc.Match(']', ']') && testExprType == 1) { + sc.Forward(); + cmdState = BASH_CMD_BODY; + } else if (sc.ch == ']' && testExprType == 2) { + cmdState = BASH_CMD_BODY; + } + } + } + }// sc.state + } + sc.Complete(); +} + +static bool IsCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eol_pos; i++) { + char ch = styler[i]; + if (ch == '#') + return true; + else if (ch != ' ' && ch != '\t') + return false; + } + return false; +} + +static void FoldBashDoc(unsigned int startPos, int length, int, WordList *[], + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + // Comment folding + if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) + { + if (!IsCommentLine(lineCurrent - 1, styler) + && IsCommentLine(lineCurrent + 1, styler)) + levelCurrent++; + else if (IsCommentLine(lineCurrent - 1, styler) + && !IsCommentLine(lineCurrent + 1, styler)) + levelCurrent--; + } + if (style == SCE_SH_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + // Here Document folding + if (style == SCE_SH_HERE_DELIM) { + if (ch == '<' && chNext == '<') { + levelCurrent++; + } + } else if (style == SCE_SH_HERE_Q && styler.StyleAt(i+1) == SCE_PL_DEFAULT) { + levelCurrent--; + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const bashWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmBash(SCLEX_BASH, ColouriseBashDoc, "bash", FoldBashDoc, bashWordListDesc); diff --git a/scintilla/lexers/LexBasic.cxx b/ThirdLibs/scintilla/lexers/LexBasic.cxx similarity index 96% rename from scintilla/lexers/LexBasic.cxx rename to ThirdLibs/scintilla/lexers/LexBasic.cxx index 59f7f05c..b15ce094 100644 --- a/scintilla/lexers/LexBasic.cxx +++ b/ThirdLibs/scintilla/lexers/LexBasic.cxx @@ -1,510 +1,510 @@ -// Scintilla source code edit control -/** @file LexBasic.cxx - ** Lexer for BlitzBasic and PureBasic. - ** Converted to lexer object and added further folding features/properties by "Udo Lechner" - **/ -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -// This tries to be a unified Lexer/Folder for all the BlitzBasic/BlitzMax/PurBasic basics -// and derivatives. Once they diverge enough, might want to split it into multiple -// lexers for more code clearity. -// -// Mail me (elias users sf net) for any bugs. - -// Folding only works for simple things like functions or types. - -// You may want to have a look at my ctags lexer as well, if you additionally to coloring -// and folding need to extract things like label tags in your editor. - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" -#include "OptionSet.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/* Bits: - * 1 - whitespace - * 2 - operator - * 4 - identifier - * 8 - decimal digit - * 16 - hex digit - * 32 - bin digit - */ -static int character_classification[128] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 2, - 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, - 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4, - 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0 -}; - -static bool IsSpace(int c) { - return c < 128 && (character_classification[c] & 1); -} - -static bool IsOperator(int c) { - return c < 128 && (character_classification[c] & 2); -} - -static bool IsIdentifier(int c) { - return c < 128 && (character_classification[c] & 4); -} - -static bool IsDigit(int c) { - return c < 128 && (character_classification[c] & 8); -} - -static bool IsHexDigit(int c) { - return c < 128 && (character_classification[c] & 16); -} - -static bool IsBinDigit(int c) { - return c < 128 && (character_classification[c] & 32); -} - -static int LowerCase(int c) -{ - if (c >= 'A' && c <= 'Z') - return 'a' + c - 'A'; - return c; -} - -static int CheckBlitzFoldPoint(char const *token, int &level) { - if (!strcmp(token, "function") || - !strcmp(token, "type")) { - level |= SC_FOLDLEVELHEADERFLAG; - return 1; - } - if (!strcmp(token, "end function") || - !strcmp(token, "end type")) { - return -1; - } - return 0; -} - -static int CheckPureFoldPoint(char const *token, int &level) { - if (!strcmp(token, "procedure") || - !strcmp(token, "enumeration") || - !strcmp(token, "interface") || - !strcmp(token, "structure")) { - level |= SC_FOLDLEVELHEADERFLAG; - return 1; - } - if (!strcmp(token, "endprocedure") || - !strcmp(token, "endenumeration") || - !strcmp(token, "endinterface") || - !strcmp(token, "endstructure")) { - return -1; - } - return 0; -} - -static int CheckFreeFoldPoint(char const *token, int &level) { - if (!strcmp(token, "function") || - !strcmp(token, "sub") || - !strcmp(token, "type")) { - level |= SC_FOLDLEVELHEADERFLAG; - return 1; - } - if (!strcmp(token, "end function") || - !strcmp(token, "end sub") || - !strcmp(token, "end type")) { - return -1; - } - return 0; -} - -// An individual named option for use in an OptionSet - -// Options used for LexerBasic -struct OptionsBasic { - bool fold; - bool foldSyntaxBased; - bool foldCommentExplicit; - std::string foldExplicitStart; - std::string foldExplicitEnd; - bool foldExplicitAnywhere; - bool foldCompact; - OptionsBasic() { - fold = false; - foldSyntaxBased = true; - foldCommentExplicit = false; - foldExplicitStart = ""; - foldExplicitEnd = ""; - foldExplicitAnywhere = false; - foldCompact = true; - } -}; - -static const char * const blitzbasicWordListDesc[] = { - "BlitzBasic Keywords", - "user1", - "user2", - "user3", - 0 -}; - -static const char * const purebasicWordListDesc[] = { - "PureBasic Keywords", - "PureBasic PreProcessor Keywords", - "user defined 1", - "user defined 2", - 0 -}; - -static const char * const freebasicWordListDesc[] = { - "FreeBasic Keywords", - "FreeBasic PreProcessor Keywords", - "user defined 1", - "user defined 2", - 0 -}; - -struct OptionSetBasic : public OptionSet { - OptionSetBasic(const char * const wordListDescriptions[]) { - DefineProperty("fold", &OptionsBasic::fold); - - DefineProperty("fold.basic.syntax.based", &OptionsBasic::foldSyntaxBased, - "Set this property to 0 to disable syntax based folding."); - - DefineProperty("fold.basic.comment.explicit", &OptionsBasic::foldCommentExplicit, - "This option enables folding explicit fold points when using the Basic lexer. " - "Explicit fold points allows adding extra folding by placing a ;{ (BB/PB) or '{ (FB) comment at the start " - "and a ;} (BB/PB) or '} (FB) at the end of a section that should be folded."); - - DefineProperty("fold.basic.explicit.start", &OptionsBasic::foldExplicitStart, - "The string to use for explicit fold start points, replacing the standard ;{ (BB/PB) or '{ (FB)."); - - DefineProperty("fold.basic.explicit.end", &OptionsBasic::foldExplicitEnd, - "The string to use for explicit fold end points, replacing the standard ;} (BB/PB) or '} (FB)."); - - DefineProperty("fold.basic.explicit.anywhere", &OptionsBasic::foldExplicitAnywhere, - "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); - - DefineProperty("fold.compact", &OptionsBasic::foldCompact); - - DefineWordListSets(wordListDescriptions); - } -}; - -class LexerBasic : public ILexer { - char comment_char; - int (*CheckFoldPoint)(char const *, int &); - WordList keywordlists[4]; - OptionsBasic options; - OptionSetBasic osBasic; -public: - LexerBasic(char comment_char_, int (*CheckFoldPoint_)(char const *, int &), const char * const wordListDescriptions[]) : - comment_char(comment_char_), - CheckFoldPoint(CheckFoldPoint_), - osBasic(wordListDescriptions) { - } - ~LexerBasic() { - } - void SCI_METHOD Release() { - delete this; - } - int SCI_METHOD Version() const { - return lvOriginal; - } - const char * SCI_METHOD PropertyNames() { - return osBasic.PropertyNames(); - } - int SCI_METHOD PropertyType(const char *name) { - return osBasic.PropertyType(name); - } - const char * SCI_METHOD DescribeProperty(const char *name) { - return osBasic.DescribeProperty(name); - } - int SCI_METHOD PropertySet(const char *key, const char *val); - const char * SCI_METHOD DescribeWordListSets() { - return osBasic.DescribeWordListSets(); - } - int SCI_METHOD WordListSet(int n, const char *wl); - void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); - void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); - - void * SCI_METHOD PrivateCall(int, void *) { - return 0; - } - static ILexer *LexerFactoryBlitzBasic() { - return new LexerBasic(';', CheckBlitzFoldPoint, blitzbasicWordListDesc); - } - static ILexer *LexerFactoryPureBasic() { - return new LexerBasic(';', CheckPureFoldPoint, purebasicWordListDesc); - } - static ILexer *LexerFactoryFreeBasic() { - return new LexerBasic('\'', CheckFreeFoldPoint, freebasicWordListDesc ); - } -}; - -int SCI_METHOD LexerBasic::PropertySet(const char *key, const char *val) { - if (osBasic.PropertySet(&options, key, val)) { - return 0; - } - return -1; -} - -int SCI_METHOD LexerBasic::WordListSet(int n, const char *wl) { - WordList *wordListN = 0; - switch (n) { - case 0: - wordListN = &keywordlists[0]; - break; - case 1: - wordListN = &keywordlists[1]; - break; - case 2: - wordListN = &keywordlists[2]; - break; - case 3: - wordListN = &keywordlists[3]; - break; - } - int firstModification = -1; - if (wordListN) { - WordList wlNew; - wlNew.Set(wl); - if (*wordListN != wlNew) { - wordListN->Set(wl); - firstModification = 0; - } - } - return firstModification; -} - -void SCI_METHOD LexerBasic::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { - LexAccessor styler(pAccess); - - bool wasfirst = true, isfirst = true; // true if first token in a line - styler.StartAt(startPos); - - StyleContext sc(startPos, length, initStyle, styler); - - // Can't use sc.More() here else we miss the last character - for (; ; sc.Forward()) { - if (sc.state == SCE_B_IDENTIFIER) { - if (!IsIdentifier(sc.ch)) { - // Labels - if (wasfirst && sc.Match(':')) { - sc.ChangeState(SCE_B_LABEL); - sc.ForwardSetState(SCE_B_DEFAULT); - } else { - char s[100]; - int kstates[4] = { - SCE_B_KEYWORD, - SCE_B_KEYWORD2, - SCE_B_KEYWORD3, - SCE_B_KEYWORD4, - }; - sc.GetCurrentLowered(s, sizeof(s)); - for (int i = 0; i < 4; i++) { - if (keywordlists[i].InList(s)) { - sc.ChangeState(kstates[i]); - } - } - // Types, must set them as operator else they will be - // matched as number/constant - if (sc.Match('.') || sc.Match('$') || sc.Match('%') || - sc.Match('#')) { - sc.SetState(SCE_B_OPERATOR); - } else { - sc.SetState(SCE_B_DEFAULT); - } - } - } - } else if (sc.state == SCE_B_OPERATOR) { - if (!IsOperator(sc.ch) || sc.Match('#')) - sc.SetState(SCE_B_DEFAULT); - } else if (sc.state == SCE_B_LABEL) { - if (!IsIdentifier(sc.ch)) - sc.SetState(SCE_B_DEFAULT); - } else if (sc.state == SCE_B_CONSTANT) { - if (!IsIdentifier(sc.ch)) - sc.SetState(SCE_B_DEFAULT); - } else if (sc.state == SCE_B_NUMBER) { - if (!IsDigit(sc.ch)) - sc.SetState(SCE_B_DEFAULT); - } else if (sc.state == SCE_B_HEXNUMBER) { - if (!IsHexDigit(sc.ch)) - sc.SetState(SCE_B_DEFAULT); - } else if (sc.state == SCE_B_BINNUMBER) { - if (!IsBinDigit(sc.ch)) - sc.SetState(SCE_B_DEFAULT); - } else if (sc.state == SCE_B_STRING) { - if (sc.ch == '"') { - sc.ForwardSetState(SCE_B_DEFAULT); - } - if (sc.atLineEnd) { - sc.ChangeState(SCE_B_ERROR); - sc.SetState(SCE_B_DEFAULT); - } - } else if (sc.state == SCE_B_COMMENT || sc.state == SCE_B_PREPROCESSOR) { - if (sc.atLineEnd) { - sc.SetState(SCE_B_DEFAULT); - } - } - - if (sc.atLineStart) - isfirst = true; - - if (sc.state == SCE_B_DEFAULT || sc.state == SCE_B_ERROR) { - if (isfirst && sc.Match('.')) { - sc.SetState(SCE_B_LABEL); - } else if (isfirst && sc.Match('#')) { - wasfirst = isfirst; - sc.SetState(SCE_B_IDENTIFIER); - } else if (sc.Match(comment_char)) { - // Hack to make deprecated QBASIC '$Include show - // up in freebasic with SCE_B_PREPROCESSOR. - if (comment_char == '\'' && sc.Match(comment_char, '$')) - sc.SetState(SCE_B_PREPROCESSOR); - else - sc.SetState(SCE_B_COMMENT); - } else if (sc.Match('"')) { - sc.SetState(SCE_B_STRING); - } else if (IsDigit(sc.ch)) { - sc.SetState(SCE_B_NUMBER); - } else if (sc.Match('$')) { - sc.SetState(SCE_B_HEXNUMBER); - } else if (sc.Match('%')) { - sc.SetState(SCE_B_BINNUMBER); - } else if (sc.Match('#')) { - sc.SetState(SCE_B_CONSTANT); - } else if (IsOperator(sc.ch)) { - sc.SetState(SCE_B_OPERATOR); - } else if (IsIdentifier(sc.ch)) { - wasfirst = isfirst; - sc.SetState(SCE_B_IDENTIFIER); - } else if (!IsSpace(sc.ch)) { - sc.SetState(SCE_B_ERROR); - } - } - - if (!IsSpace(sc.ch)) - isfirst = false; - - if (!sc.More()) - break; - } - sc.Complete(); -} - - -void SCI_METHOD LexerBasic::Fold(unsigned int startPos, int length, int /* initStyle */, IDocument *pAccess) { - - if (!options.fold) - return; - - LexAccessor styler(pAccess); - - int line = styler.GetLine(startPos); - int level = styler.LevelAt(line); - int go = 0, done = 0; - int endPos = startPos + length; - char word[256]; - int wordlen = 0; - const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); - int cNext = styler[startPos]; - - // Scan for tokens at the start of the line (they may include - // whitespace, for tokens like "End Function" - for (int i = startPos; i < endPos; i++) { - int c = cNext; - cNext = styler.SafeGetCharAt(i + 1); - bool atEOL = (c == '\r' && cNext != '\n') || (c == '\n'); - if (options.foldSyntaxBased && !done && !go) { - if (wordlen) { // are we scanning a token already? - word[wordlen] = static_cast(LowerCase(c)); - if (!IsIdentifier(c)) { // done with token - word[wordlen] = '\0'; - go = CheckFoldPoint(word, level); - if (!go) { - // Treat any whitespace as single blank, for - // things like "End Function". - if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) { - word[wordlen] = ' '; - if (wordlen < 255) - wordlen++; - } - else // done with this line - done = 1; - } - } else if (wordlen < 255) { - wordlen++; - } - } else { // start scanning at first non-whitespace character - if (!IsSpace(c)) { - if (IsIdentifier(c)) { - word[0] = static_cast(LowerCase(c)); - wordlen = 1; - } else // done with this line - done = 1; - } - } - } - if (options.foldCommentExplicit && ((styler.StyleAt(i) == SCE_B_COMMENT) || options.foldExplicitAnywhere)) { - if (userDefinedFoldMarkers) { - if (styler.Match(i, options.foldExplicitStart.c_str())) { - level |= SC_FOLDLEVELHEADERFLAG; - go = 1; - } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { - go = -1; - } - } else { - if (c == comment_char) { - if (cNext == '{') { - level |= SC_FOLDLEVELHEADERFLAG; - go = 1; - } else if (cNext == '}') { - go = -1; - } - } - } - } - if (atEOL) { // line end - if (!done && wordlen == 0 && options.foldCompact) // line was only space - level |= SC_FOLDLEVELWHITEFLAG; - if (level != styler.LevelAt(line)) - styler.SetLevel(line, level); - level += go; - line++; - // reset state - wordlen = 0; - level &= ~SC_FOLDLEVELHEADERFLAG; - level &= ~SC_FOLDLEVELWHITEFLAG; - go = 0; - done = 0; - } - } -} - -LexerModule lmBlitzBasic(SCLEX_BLITZBASIC, LexerBasic::LexerFactoryBlitzBasic, "blitzbasic", blitzbasicWordListDesc); - -LexerModule lmPureBasic(SCLEX_PUREBASIC, LexerBasic::LexerFactoryPureBasic, "purebasic", purebasicWordListDesc); - -LexerModule lmFreeBasic(SCLEX_FREEBASIC, LexerBasic::LexerFactoryFreeBasic, "freebasic", freebasicWordListDesc); +// Scintilla source code edit control +/** @file LexBasic.cxx + ** Lexer for BlitzBasic and PureBasic. + ** Converted to lexer object and added further folding features/properties by "Udo Lechner" + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +// This tries to be a unified Lexer/Folder for all the BlitzBasic/BlitzMax/PurBasic basics +// and derivatives. Once they diverge enough, might want to split it into multiple +// lexers for more code clearity. +// +// Mail me (elias users sf net) for any bugs. + +// Folding only works for simple things like functions or types. + +// You may want to have a look at my ctags lexer as well, if you additionally to coloring +// and folding need to extract things like label tags in your editor. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +/* Bits: + * 1 - whitespace + * 2 - operator + * 4 - identifier + * 8 - decimal digit + * 16 - hex digit + * 32 - bin digit + */ +static int character_classification[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 2, + 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0 +}; + +static bool IsSpace(int c) { + return c < 128 && (character_classification[c] & 1); +} + +static bool IsOperator(int c) { + return c < 128 && (character_classification[c] & 2); +} + +static bool IsIdentifier(int c) { + return c < 128 && (character_classification[c] & 4); +} + +static bool IsDigit(int c) { + return c < 128 && (character_classification[c] & 8); +} + +static bool IsHexDigit(int c) { + return c < 128 && (character_classification[c] & 16); +} + +static bool IsBinDigit(int c) { + return c < 128 && (character_classification[c] & 32); +} + +static int LowerCase(int c) +{ + if (c >= 'A' && c <= 'Z') + return 'a' + c - 'A'; + return c; +} + +static int CheckBlitzFoldPoint(char const *token, int &level) { + if (!strcmp(token, "function") || + !strcmp(token, "type")) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "end function") || + !strcmp(token, "end type")) { + return -1; + } + return 0; +} + +static int CheckPureFoldPoint(char const *token, int &level) { + if (!strcmp(token, "procedure") || + !strcmp(token, "enumeration") || + !strcmp(token, "interface") || + !strcmp(token, "structure")) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "endprocedure") || + !strcmp(token, "endenumeration") || + !strcmp(token, "endinterface") || + !strcmp(token, "endstructure")) { + return -1; + } + return 0; +} + +static int CheckFreeFoldPoint(char const *token, int &level) { + if (!strcmp(token, "function") || + !strcmp(token, "sub") || + !strcmp(token, "type")) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "end function") || + !strcmp(token, "end sub") || + !strcmp(token, "end type")) { + return -1; + } + return 0; +} + +// An individual named option for use in an OptionSet + +// Options used for LexerBasic +struct OptionsBasic { + bool fold; + bool foldSyntaxBased; + bool foldCommentExplicit; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere; + bool foldCompact; + OptionsBasic() { + fold = false; + foldSyntaxBased = true; + foldCommentExplicit = false; + foldExplicitStart = ""; + foldExplicitEnd = ""; + foldExplicitAnywhere = false; + foldCompact = true; + } +}; + +static const char * const blitzbasicWordListDesc[] = { + "BlitzBasic Keywords", + "user1", + "user2", + "user3", + 0 +}; + +static const char * const purebasicWordListDesc[] = { + "PureBasic Keywords", + "PureBasic PreProcessor Keywords", + "user defined 1", + "user defined 2", + 0 +}; + +static const char * const freebasicWordListDesc[] = { + "FreeBasic Keywords", + "FreeBasic PreProcessor Keywords", + "user defined 1", + "user defined 2", + 0 +}; + +struct OptionSetBasic : public OptionSet { + OptionSetBasic(const char * const wordListDescriptions[]) { + DefineProperty("fold", &OptionsBasic::fold); + + DefineProperty("fold.basic.syntax.based", &OptionsBasic::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("fold.basic.comment.explicit", &OptionsBasic::foldCommentExplicit, + "This option enables folding explicit fold points when using the Basic lexer. " + "Explicit fold points allows adding extra folding by placing a ;{ (BB/PB) or '{ (FB) comment at the start " + "and a ;} (BB/PB) or '} (FB) at the end of a section that should be folded."); + + DefineProperty("fold.basic.explicit.start", &OptionsBasic::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard ;{ (BB/PB) or '{ (FB)."); + + DefineProperty("fold.basic.explicit.end", &OptionsBasic::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard ;} (BB/PB) or '} (FB)."); + + DefineProperty("fold.basic.explicit.anywhere", &OptionsBasic::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + + DefineProperty("fold.compact", &OptionsBasic::foldCompact); + + DefineWordListSets(wordListDescriptions); + } +}; + +class LexerBasic : public ILexer { + char comment_char; + int (*CheckFoldPoint)(char const *, int &); + WordList keywordlists[4]; + OptionsBasic options; + OptionSetBasic osBasic; +public: + LexerBasic(char comment_char_, int (*CheckFoldPoint_)(char const *, int &), const char * const wordListDescriptions[]) : + comment_char(comment_char_), + CheckFoldPoint(CheckFoldPoint_), + osBasic(wordListDescriptions) { + } + ~LexerBasic() { + } + void SCI_METHOD Release() { + delete this; + } + int SCI_METHOD Version() const { + return lvOriginal; + } + const char * SCI_METHOD PropertyNames() { + return osBasic.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) { + return osBasic.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) { + return osBasic.DescribeProperty(name); + } + int SCI_METHOD PropertySet(const char *key, const char *val); + const char * SCI_METHOD DescribeWordListSets() { + return osBasic.DescribeWordListSets(); + } + int SCI_METHOD WordListSet(int n, const char *wl); + void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + + void * SCI_METHOD PrivateCall(int, void *) { + return 0; + } + static ILexer *LexerFactoryBlitzBasic() { + return new LexerBasic(';', CheckBlitzFoldPoint, blitzbasicWordListDesc); + } + static ILexer *LexerFactoryPureBasic() { + return new LexerBasic(';', CheckPureFoldPoint, purebasicWordListDesc); + } + static ILexer *LexerFactoryFreeBasic() { + return new LexerBasic('\'', CheckFreeFoldPoint, freebasicWordListDesc ); + } +}; + +int SCI_METHOD LexerBasic::PropertySet(const char *key, const char *val) { + if (osBasic.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +int SCI_METHOD LexerBasic::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywordlists[0]; + break; + case 1: + wordListN = &keywordlists[1]; + break; + case 2: + wordListN = &keywordlists[2]; + break; + case 3: + wordListN = &keywordlists[3]; + break; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerBasic::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + + bool wasfirst = true, isfirst = true; // true if first token in a line + styler.StartAt(startPos); + + StyleContext sc(startPos, length, initStyle, styler); + + // Can't use sc.More() here else we miss the last character + for (; ; sc.Forward()) { + if (sc.state == SCE_B_IDENTIFIER) { + if (!IsIdentifier(sc.ch)) { + // Labels + if (wasfirst && sc.Match(':')) { + sc.ChangeState(SCE_B_LABEL); + sc.ForwardSetState(SCE_B_DEFAULT); + } else { + char s[100]; + int kstates[4] = { + SCE_B_KEYWORD, + SCE_B_KEYWORD2, + SCE_B_KEYWORD3, + SCE_B_KEYWORD4, + }; + sc.GetCurrentLowered(s, sizeof(s)); + for (int i = 0; i < 4; i++) { + if (keywordlists[i].InList(s)) { + sc.ChangeState(kstates[i]); + } + } + // Types, must set them as operator else they will be + // matched as number/constant + if (sc.Match('.') || sc.Match('$') || sc.Match('%') || + sc.Match('#')) { + sc.SetState(SCE_B_OPERATOR); + } else { + sc.SetState(SCE_B_DEFAULT); + } + } + } + } else if (sc.state == SCE_B_OPERATOR) { + if (!IsOperator(sc.ch) || sc.Match('#')) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_LABEL) { + if (!IsIdentifier(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_CONSTANT) { + if (!IsIdentifier(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_NUMBER) { + if (!IsDigit(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_HEXNUMBER) { + if (!IsHexDigit(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_BINNUMBER) { + if (!IsBinDigit(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_STRING) { + if (sc.ch == '"') { + sc.ForwardSetState(SCE_B_DEFAULT); + } + if (sc.atLineEnd) { + sc.ChangeState(SCE_B_ERROR); + sc.SetState(SCE_B_DEFAULT); + } + } else if (sc.state == SCE_B_COMMENT || sc.state == SCE_B_PREPROCESSOR) { + if (sc.atLineEnd) { + sc.SetState(SCE_B_DEFAULT); + } + } + + if (sc.atLineStart) + isfirst = true; + + if (sc.state == SCE_B_DEFAULT || sc.state == SCE_B_ERROR) { + if (isfirst && sc.Match('.')) { + sc.SetState(SCE_B_LABEL); + } else if (isfirst && sc.Match('#')) { + wasfirst = isfirst; + sc.SetState(SCE_B_IDENTIFIER); + } else if (sc.Match(comment_char)) { + // Hack to make deprecated QBASIC '$Include show + // up in freebasic with SCE_B_PREPROCESSOR. + if (comment_char == '\'' && sc.Match(comment_char, '$')) + sc.SetState(SCE_B_PREPROCESSOR); + else + sc.SetState(SCE_B_COMMENT); + } else if (sc.Match('"')) { + sc.SetState(SCE_B_STRING); + } else if (IsDigit(sc.ch)) { + sc.SetState(SCE_B_NUMBER); + } else if (sc.Match('$')) { + sc.SetState(SCE_B_HEXNUMBER); + } else if (sc.Match('%')) { + sc.SetState(SCE_B_BINNUMBER); + } else if (sc.Match('#')) { + sc.SetState(SCE_B_CONSTANT); + } else if (IsOperator(sc.ch)) { + sc.SetState(SCE_B_OPERATOR); + } else if (IsIdentifier(sc.ch)) { + wasfirst = isfirst; + sc.SetState(SCE_B_IDENTIFIER); + } else if (!IsSpace(sc.ch)) { + sc.SetState(SCE_B_ERROR); + } + } + + if (!IsSpace(sc.ch)) + isfirst = false; + + if (!sc.More()) + break; + } + sc.Complete(); +} + + +void SCI_METHOD LexerBasic::Fold(unsigned int startPos, int length, int /* initStyle */, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + + int line = styler.GetLine(startPos); + int level = styler.LevelAt(line); + int go = 0, done = 0; + int endPos = startPos + length; + char word[256]; + int wordlen = 0; + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); + int cNext = styler[startPos]; + + // Scan for tokens at the start of the line (they may include + // whitespace, for tokens like "End Function" + for (int i = startPos; i < endPos; i++) { + int c = cNext; + cNext = styler.SafeGetCharAt(i + 1); + bool atEOL = (c == '\r' && cNext != '\n') || (c == '\n'); + if (options.foldSyntaxBased && !done && !go) { + if (wordlen) { // are we scanning a token already? + word[wordlen] = static_cast(LowerCase(c)); + if (!IsIdentifier(c)) { // done with token + word[wordlen] = '\0'; + go = CheckFoldPoint(word, level); + if (!go) { + // Treat any whitespace as single blank, for + // things like "End Function". + if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) { + word[wordlen] = ' '; + if (wordlen < 255) + wordlen++; + } + else // done with this line + done = 1; + } + } else if (wordlen < 255) { + wordlen++; + } + } else { // start scanning at first non-whitespace character + if (!IsSpace(c)) { + if (IsIdentifier(c)) { + word[0] = static_cast(LowerCase(c)); + wordlen = 1; + } else // done with this line + done = 1; + } + } + } + if (options.foldCommentExplicit && ((styler.StyleAt(i) == SCE_B_COMMENT) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { + level |= SC_FOLDLEVELHEADERFLAG; + go = 1; + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + go = -1; + } + } else { + if (c == comment_char) { + if (cNext == '{') { + level |= SC_FOLDLEVELHEADERFLAG; + go = 1; + } else if (cNext == '}') { + go = -1; + } + } + } + } + if (atEOL) { // line end + if (!done && wordlen == 0 && options.foldCompact) // line was only space + level |= SC_FOLDLEVELWHITEFLAG; + if (level != styler.LevelAt(line)) + styler.SetLevel(line, level); + level += go; + line++; + // reset state + wordlen = 0; + level &= ~SC_FOLDLEVELHEADERFLAG; + level &= ~SC_FOLDLEVELWHITEFLAG; + go = 0; + done = 0; + } + } +} + +LexerModule lmBlitzBasic(SCLEX_BLITZBASIC, LexerBasic::LexerFactoryBlitzBasic, "blitzbasic", blitzbasicWordListDesc); + +LexerModule lmPureBasic(SCLEX_PUREBASIC, LexerBasic::LexerFactoryPureBasic, "purebasic", purebasicWordListDesc); + +LexerModule lmFreeBasic(SCLEX_FREEBASIC, LexerBasic::LexerFactoryFreeBasic, "freebasic", freebasicWordListDesc); diff --git a/scintilla/lexers/LexBullant.cxx b/ThirdLibs/scintilla/lexers/LexBullant.cxx similarity index 96% rename from scintilla/lexers/LexBullant.cxx rename to ThirdLibs/scintilla/lexers/LexBullant.cxx index fabfd8c3..bb5c9c4a 100644 --- a/scintilla/lexers/LexBullant.cxx +++ b/ThirdLibs/scintilla/lexers/LexBullant.cxx @@ -1,233 +1,233 @@ -// SciTE - Scintilla based Text Editor -// LexBullant.cxx - lexer for Bullant - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static int classifyWordBullant(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { - char s[100]; - s[0] = '\0'; - for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) { - s[i] = static_cast(tolower(styler[start + i])); - s[i + 1] = '\0'; - } - int lev= 0; - char chAttr = SCE_C_IDENTIFIER; - if (isdigit(s[0]) || (s[0] == '.')){ - chAttr = SCE_C_NUMBER; - } - else { - if (keywords.InList(s)) { - chAttr = SCE_C_WORD; - if (strcmp(s, "end") == 0) - lev = -1; - else if (strcmp(s, "method") == 0 || - strcmp(s, "case") == 0 || - strcmp(s, "class") == 0 || - strcmp(s, "debug") == 0 || - strcmp(s, "test") == 0 || - strcmp(s, "if") == 0 || - strcmp(s, "lock") == 0 || - strcmp(s, "transaction") == 0 || - strcmp(s, "trap") == 0 || - strcmp(s, "until") == 0 || - strcmp(s, "while") == 0) - lev = 1; - } - } - styler.ColourTo(end, chAttr); - return lev; -} - -static void ColouriseBullantDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - WordList &keywords = *keywordlists[0]; - - styler.StartAt(startPos); - - bool fold = styler.GetPropertyInt("fold") != 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - - int state = initStyle; - if (state == SCE_C_STRINGEOL) // Does not leak onto next line - state = SCE_C_DEFAULT; - char chPrev = ' '; - char chNext = styler[startPos]; - unsigned int lengthDoc = startPos + length; - int visibleChars = 0; - styler.StartSegment(startPos); - int endFoundThisLine = 0; - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { - // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) - // Avoid triggering two times on Dos/Win - // End of line - endFoundThisLine = 0; - if (state == SCE_C_STRINGEOL) { - styler.ColourTo(i, state); - state = SCE_C_DEFAULT; - } - if (fold) { - int lev = levelPrev; - if (visibleChars == 0) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - styler.SetLevel(lineCurrent, lev); - lineCurrent++; - levelPrev = levelCurrent; - } - visibleChars = 0; - -/* int indentBlock = GetLineIndentation(lineCurrent); - if (blockChange==1){ - lineCurrent++; - int pos=SetLineIndentation(lineCurrent, indentBlock + indentSize); - } else if (blockChange==-1) { - indentBlock -= indentSize; - if (indentBlock < 0) - indentBlock = 0; - SetLineIndentation(lineCurrent, indentBlock); - lineCurrent++; - } - blockChange=0; -*/ } - if (!(isascii(ch) && isspace(ch))) - visibleChars++; - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - chPrev = ' '; - i += 1; - continue; - } - - if (state == SCE_C_DEFAULT) { - if (iswordstart(ch)) { - styler.ColourTo(i-1, state); - state = SCE_C_IDENTIFIER; - } else if (ch == '@' && chNext == 'o') { - if ((styler.SafeGetCharAt(i+2) =='f') && (styler.SafeGetCharAt(i+3) == 'f')) { - styler.ColourTo(i-1, state); - state = SCE_C_COMMENT; - } - } else if (ch == '#') { - styler.ColourTo(i-1, state); - state = SCE_C_COMMENTLINE; - } else if (ch == '\"') { - styler.ColourTo(i-1, state); - state = SCE_C_STRING; - } else if (ch == '\'') { - styler.ColourTo(i-1, state); - state = SCE_C_CHARACTER; - } else if (isoperator(ch)) { - styler.ColourTo(i-1, state); - styler.ColourTo(i, SCE_C_OPERATOR); - } - } else if (state == SCE_C_IDENTIFIER) { - if (!iswordchar(ch)) { - int levelChange = classifyWordBullant(styler.GetStartSegment(), i - 1, keywords, styler); - state = SCE_C_DEFAULT; - chNext = styler.SafeGetCharAt(i + 1); - if (ch == '#') { - state = SCE_C_COMMENTLINE; - } else if (ch == '\"') { - state = SCE_C_STRING; - } else if (ch == '\'') { - state = SCE_C_CHARACTER; - } else if (isoperator(ch)) { - styler.ColourTo(i, SCE_C_OPERATOR); - } - if (endFoundThisLine == 0) - levelCurrent+=levelChange; - if (levelChange == -1) - endFoundThisLine=1; - } - } else if (state == SCE_C_COMMENT) { - if (ch == '@' && chNext == 'o') { - if (styler.SafeGetCharAt(i+2) == 'n') { - styler.ColourTo(i+2, state); - state = SCE_C_DEFAULT; - i+=2; - } - } - } else if (state == SCE_C_COMMENTLINE) { - if (ch == '\r' || ch == '\n') { - endFoundThisLine = 0; - styler.ColourTo(i-1, state); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_STRING) { - if (ch == '\\') { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') { - i++; - ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - } - } else if (ch == '\"') { - styler.ColourTo(i, state); - state = SCE_C_DEFAULT; - } else if (chNext == '\r' || chNext == '\n') { - endFoundThisLine = 0; - styler.ColourTo(i-1, SCE_C_STRINGEOL); - state = SCE_C_STRINGEOL; - } - } else if (state == SCE_C_CHARACTER) { - if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) { - endFoundThisLine = 0; - styler.ColourTo(i-1, SCE_C_STRINGEOL); - state = SCE_C_STRINGEOL; - } else if (ch == '\\') { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') { - i++; - ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - } - } else if (ch == '\'') { - styler.ColourTo(i, state); - state = SCE_C_DEFAULT; - } - } - chPrev = ch; - } - styler.ColourTo(lengthDoc - 1, state); - - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - if (fold) { - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - //styler.SetLevel(lineCurrent, levelCurrent | flagsNext); - styler.SetLevel(lineCurrent, levelPrev | flagsNext); - - } -} - -static const char * const bullantWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmBullant(SCLEX_BULLANT, ColouriseBullantDoc, "bullant", 0, bullantWordListDesc); +// SciTE - Scintilla based Text Editor +// LexBullant.cxx - lexer for Bullant + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static int classifyWordBullant(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { + char s[100]; + s[0] = '\0'; + for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) { + s[i] = static_cast(tolower(styler[start + i])); + s[i + 1] = '\0'; + } + int lev= 0; + char chAttr = SCE_C_IDENTIFIER; + if (isdigit(s[0]) || (s[0] == '.')){ + chAttr = SCE_C_NUMBER; + } + else { + if (keywords.InList(s)) { + chAttr = SCE_C_WORD; + if (strcmp(s, "end") == 0) + lev = -1; + else if (strcmp(s, "method") == 0 || + strcmp(s, "case") == 0 || + strcmp(s, "class") == 0 || + strcmp(s, "debug") == 0 || + strcmp(s, "test") == 0 || + strcmp(s, "if") == 0 || + strcmp(s, "lock") == 0 || + strcmp(s, "transaction") == 0 || + strcmp(s, "trap") == 0 || + strcmp(s, "until") == 0 || + strcmp(s, "while") == 0) + lev = 1; + } + } + styler.ColourTo(end, chAttr); + return lev; +} + +static void ColouriseBullantDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + WordList &keywords = *keywordlists[0]; + + styler.StartAt(startPos); + + bool fold = styler.GetPropertyInt("fold") != 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + + int state = initStyle; + if (state == SCE_C_STRINGEOL) // Does not leak onto next line + state = SCE_C_DEFAULT; + char chPrev = ' '; + char chNext = styler[startPos]; + unsigned int lengthDoc = startPos + length; + int visibleChars = 0; + styler.StartSegment(startPos); + int endFoundThisLine = 0; + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // End of line + endFoundThisLine = 0; + if (state == SCE_C_STRINGEOL) { + styler.ColourTo(i, state); + state = SCE_C_DEFAULT; + } + if (fold) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + styler.SetLevel(lineCurrent, lev); + lineCurrent++; + levelPrev = levelCurrent; + } + visibleChars = 0; + +/* int indentBlock = GetLineIndentation(lineCurrent); + if (blockChange==1){ + lineCurrent++; + int pos=SetLineIndentation(lineCurrent, indentBlock + indentSize); + } else if (blockChange==-1) { + indentBlock -= indentSize; + if (indentBlock < 0) + indentBlock = 0; + SetLineIndentation(lineCurrent, indentBlock); + lineCurrent++; + } + blockChange=0; +*/ } + if (!(isascii(ch) && isspace(ch))) + visibleChars++; + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + chPrev = ' '; + i += 1; + continue; + } + + if (state == SCE_C_DEFAULT) { + if (iswordstart(ch)) { + styler.ColourTo(i-1, state); + state = SCE_C_IDENTIFIER; + } else if (ch == '@' && chNext == 'o') { + if ((styler.SafeGetCharAt(i+2) =='f') && (styler.SafeGetCharAt(i+3) == 'f')) { + styler.ColourTo(i-1, state); + state = SCE_C_COMMENT; + } + } else if (ch == '#') { + styler.ColourTo(i-1, state); + state = SCE_C_COMMENTLINE; + } else if (ch == '\"') { + styler.ColourTo(i-1, state); + state = SCE_C_STRING; + } else if (ch == '\'') { + styler.ColourTo(i-1, state); + state = SCE_C_CHARACTER; + } else if (isoperator(ch)) { + styler.ColourTo(i-1, state); + styler.ColourTo(i, SCE_C_OPERATOR); + } + } else if (state == SCE_C_IDENTIFIER) { + if (!iswordchar(ch)) { + int levelChange = classifyWordBullant(styler.GetStartSegment(), i - 1, keywords, styler); + state = SCE_C_DEFAULT; + chNext = styler.SafeGetCharAt(i + 1); + if (ch == '#') { + state = SCE_C_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_C_STRING; + } else if (ch == '\'') { + state = SCE_C_CHARACTER; + } else if (isoperator(ch)) { + styler.ColourTo(i, SCE_C_OPERATOR); + } + if (endFoundThisLine == 0) + levelCurrent+=levelChange; + if (levelChange == -1) + endFoundThisLine=1; + } + } else if (state == SCE_C_COMMENT) { + if (ch == '@' && chNext == 'o') { + if (styler.SafeGetCharAt(i+2) == 'n') { + styler.ColourTo(i+2, state); + state = SCE_C_DEFAULT; + i+=2; + } + } + } else if (state == SCE_C_COMMENTLINE) { + if (ch == '\r' || ch == '\n') { + endFoundThisLine = 0; + styler.ColourTo(i-1, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_STRING) { + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + } + } else if (ch == '\"') { + styler.ColourTo(i, state); + state = SCE_C_DEFAULT; + } else if (chNext == '\r' || chNext == '\n') { + endFoundThisLine = 0; + styler.ColourTo(i-1, SCE_C_STRINGEOL); + state = SCE_C_STRINGEOL; + } + } else if (state == SCE_C_CHARACTER) { + if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) { + endFoundThisLine = 0; + styler.ColourTo(i-1, SCE_C_STRINGEOL); + state = SCE_C_STRINGEOL; + } else if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + } + } else if (ch == '\'') { + styler.ColourTo(i, state); + state = SCE_C_DEFAULT; + } + } + chPrev = ch; + } + styler.ColourTo(lengthDoc - 1, state); + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + if (fold) { + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + //styler.SetLevel(lineCurrent, levelCurrent | flagsNext); + styler.SetLevel(lineCurrent, levelPrev | flagsNext); + + } +} + +static const char * const bullantWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmBullant(SCLEX_BULLANT, ColouriseBullantDoc, "bullant", 0, bullantWordListDesc); diff --git a/scintilla/lexers/LexCLW.cxx b/ThirdLibs/scintilla/lexers/LexCLW.cxx similarity index 97% rename from scintilla/lexers/LexCLW.cxx rename to ThirdLibs/scintilla/lexers/LexCLW.cxx index dbe067f9..c1dea607 100644 --- a/scintilla/lexers/LexCLW.cxx +++ b/ThirdLibs/scintilla/lexers/LexCLW.cxx @@ -1,682 +1,682 @@ -// Scintilla source code edit control -/** @file LexClw.cxx - ** Lexer for Clarion. - ** 2004/12/17 Updated Lexer - **/ -// Copyright 2003-2004 by Ron Schofield -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// Is an end of line character -inline bool IsEOL(const int ch) { - - return(ch == '\n'); -} - -// Convert character to uppercase -static char CharacterUpper(char chChar) { - - if (chChar < 'a' || chChar > 'z') { - return(chChar); - } - else { - return(static_cast(chChar - 'a' + 'A')); - } -} - -// Convert string to uppercase -static void StringUpper(char *szString) { - - while (*szString) { - *szString = CharacterUpper(*szString); - szString++; - } -} - -// Is a label start character -inline bool IsALabelStart(const int iChar) { - - return(isalpha(iChar) || iChar == '_'); -} - -// Is a label character -inline bool IsALabelCharacter(const int iChar) { - - return(isalnum(iChar) || iChar == '_' || iChar == ':'); -} - -// Is the character is a ! and the the next character is not a ! -inline bool IsACommentStart(const int iChar) { - - return(iChar == '!'); -} - -// Is the character a Clarion hex character (ABCDEF) -inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) { - - // Case insensitive. - if (!bCaseSensitive) { - if (strchr("ABCDEFabcdef", iChar) != NULL) { - return(true); - } - } - // Case sensitive - else { - if (strchr("ABCDEF", iChar) != NULL) { - return(true); - } - } - return(false); -} - -// Is the character a Clarion base character (B=Binary, O=Octal, H=Hex) -inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) { - - // Case insensitive. - if (!bCaseSensitive) { - // If character is a numeric base character - if (strchr("BOHboh", iChar) != NULL) { - return(true); - } - } - // Case sensitive - else { - // If character is a numeric base character - if (strchr("BOH", iChar) != NULL) { - return(true); - } - } - return(false); -} - -// Set the correct numeric constant state -inline bool SetNumericConstantState(StyleContext &scDoc) { - - int iPoints = 0; // Point counter - char cNumericString[512]; // Numeric string buffer - - // Buffer the current numberic string - scDoc.GetCurrent(cNumericString, sizeof(cNumericString)); - // Loop through the string until end of string (NULL termination) - for (int iIndex = 0; cNumericString[iIndex] != '\0'; iIndex++) { - // Depending on the character - switch (cNumericString[iIndex]) { - // Is a . (point) - case '.' : - // Increment point counter - iPoints++; - break; - default : - break; - } - } - // If points found (can be more than one for improper formatted number - if (iPoints > 0) { - return(true); - } - // Else no points found - else { - return(false); - } -} - -// Get the next word in uppercase from the current position (keyword lookahead) -inline bool GetNextWordUpper(Accessor &styler, unsigned int uiStartPos, int iLength, char *cWord) { - - unsigned int iIndex = 0; // Buffer Index - - // Loop through the remaining string from the current position - for (int iOffset = uiStartPos; iOffset < iLength; iOffset++) { - // Get the character from the buffer using the offset - char cCharacter = styler[iOffset]; - if (IsEOL(cCharacter)) { - break; - } - // If the character is alphabet character - if (isalpha(cCharacter)) { - // Add UPPERCASE character to the word buffer - cWord[iIndex++] = CharacterUpper(cCharacter); - } - } - // Add null termination - cWord[iIndex] = '\0'; - // If no word was found - if (iIndex == 0) { - // Return failure - return(false); - } - // Else word was found - else { - // Return success - return(true); - } -} - -// Clarion Language Colouring Procedure -static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) { - - int iParenthesesLevel = 0; // Parenthese Level - int iColumn1Label = false; // Label starts in Column 1 - - WordList &wlClarionKeywords = *wlKeywords[0]; // Clarion Keywords - WordList &wlCompilerDirectives = *wlKeywords[1]; // Compiler Directives - WordList &wlRuntimeExpressions = *wlKeywords[2]; // Runtime Expressions - WordList &wlBuiltInProcsFuncs = *wlKeywords[3]; // Builtin Procedures and Functions - WordList &wlStructsDataTypes = *wlKeywords[4]; // Structures and Data Types - WordList &wlAttributes = *wlKeywords[5]; // Procedure Attributes - WordList &wlStandardEquates = *wlKeywords[6]; // Standard Equates - WordList &wlLabelReservedWords = *wlKeywords[7]; // Clarion Reserved Keywords (Labels) - WordList &wlProcLabelReservedWords = *wlKeywords[8]; // Clarion Reserved Keywords (Procedure Labels) - - const char wlProcReservedKeywordList[] = - "PROCEDURE FUNCTION"; - WordList wlProcReservedKeywords; - wlProcReservedKeywords.Set(wlProcReservedKeywordList); - - const char wlCompilerKeywordList[] = - "COMPILE OMIT"; - WordList wlCompilerKeywords; - wlCompilerKeywords.Set(wlCompilerKeywordList); - - const char wlLegacyStatementsList[] = - "BOF EOF FUNCTION POINTER SHARE"; - WordList wlLegacyStatements; - wlLegacyStatements.Set(wlLegacyStatementsList); - - StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler); - - // lex source code - for (; scDoc.More(); scDoc.Forward()) - { - // - // Determine if the current state should terminate. - // - - // Label State Handling - if (scDoc.state == SCE_CLW_LABEL) { - // If the character is not a valid label - if (!IsALabelCharacter(scDoc.ch)) { - // If the character is a . (dot syntax) - if (scDoc.ch == '.') { - // Turn off column 1 label flag as label now cannot be reserved work - iColumn1Label = false; - // Uncolour the . (dot) to default state, move forward one character, - // and change back to the label state. - scDoc.SetState(SCE_CLW_DEFAULT); - scDoc.Forward(); - scDoc.SetState(SCE_CLW_LABEL); - } - // Else check label - else { - char cLabel[512]; // Label buffer - // Buffer the current label string - scDoc.GetCurrent(cLabel,sizeof(cLabel)); - // If case insensitive, convert string to UPPERCASE to match passed keywords. - if (!bCaseSensitive) { - StringUpper(cLabel); - } - // Else if UPPERCASE label string is in the Clarion compiler keyword list - if (wlCompilerKeywords.InList(cLabel) && iColumn1Label){ - // change the label to error state - scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); - } - // Else if UPPERCASE label string is in the Clarion reserved keyword list - else if (wlLabelReservedWords.InList(cLabel) && iColumn1Label){ - // change the label to error state - scDoc.ChangeState(SCE_CLW_ERROR); - } - // Else if UPPERCASE label string is - else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) { - char cWord[512]; // Word buffer - // Get the next word from the current position - if (GetNextWordUpper(accStyler,scDoc.currentPos,uiStartPos+iLength,cWord)) { - // If the next word is a procedure reserved word - if (wlProcReservedKeywords.InList(cWord)) { - // Change the label to error state - scDoc.ChangeState(SCE_CLW_ERROR); - } - } - } - // Else if label string is in the compiler directive keyword list - else if (wlCompilerDirectives.InList(cLabel)) { - // change the state to compiler directive state - scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); - } - // Terminate the label state and set to default state - scDoc.SetState(SCE_CLW_DEFAULT); - } - } - } - // Keyword State Handling - else if (scDoc.state == SCE_CLW_KEYWORD) { - // If character is : (colon) - if (scDoc.ch == ':') { - char cEquate[512]; // Equate buffer - // Move forward to include : (colon) in buffer - scDoc.Forward(); - // Buffer the equate string - scDoc.GetCurrent(cEquate,sizeof(cEquate)); - // If case insensitive, convert string to UPPERCASE to match passed keywords. - if (!bCaseSensitive) { - StringUpper(cEquate); - } - // If statement string is in the equate list - if (wlStandardEquates.InList(cEquate)) { - // Change to equate state - scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE); - } - } - // If the character is not a valid label character - else if (!IsALabelCharacter(scDoc.ch)) { - char cStatement[512]; // Statement buffer - // Buffer the statement string - scDoc.GetCurrent(cStatement,sizeof(cStatement)); - // If case insensitive, convert string to UPPERCASE to match passed keywords. - if (!bCaseSensitive) { - StringUpper(cStatement); - } - // If statement string is in the Clarion keyword list - if (wlClarionKeywords.InList(cStatement)) { - // Change the statement string to the Clarion keyword state - scDoc.ChangeState(SCE_CLW_KEYWORD); - } - // Else if statement string is in the compiler directive keyword list - else if (wlCompilerDirectives.InList(cStatement)) { - // Change the statement string to the compiler directive state - scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); - } - // Else if statement string is in the runtime expressions keyword list - else if (wlRuntimeExpressions.InList(cStatement)) { - // Change the statement string to the runtime expressions state - scDoc.ChangeState(SCE_CLW_RUNTIME_EXPRESSIONS); - } - // Else if statement string is in the builtin procedures and functions keyword list - else if (wlBuiltInProcsFuncs.InList(cStatement)) { - // Change the statement string to the builtin procedures and functions state - scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION); - } - // Else if statement string is in the tructures and data types keyword list - else if (wlStructsDataTypes.InList(cStatement)) { - // Change the statement string to the structures and data types state - scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE); - } - // Else if statement string is in the procedure attribute keyword list - else if (wlAttributes.InList(cStatement)) { - // Change the statement string to the procedure attribute state - scDoc.ChangeState(SCE_CLW_ATTRIBUTE); - } - // Else if statement string is in the standard equate keyword list - else if (wlStandardEquates.InList(cStatement)) { - // Change the statement string to the standard equate state - scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE); - } - // Else if statement string is in the deprecated or legacy keyword list - else if (wlLegacyStatements.InList(cStatement)) { - // Change the statement string to the standard equate state - scDoc.ChangeState(SCE_CLW_DEPRECATED); - } - // Else the statement string doesn't match any work list - else { - // Change the statement string to the default state - scDoc.ChangeState(SCE_CLW_DEFAULT); - } - // Terminate the keyword state and set to default state - scDoc.SetState(SCE_CLW_DEFAULT); - } - } - // String State Handling - else if (scDoc.state == SCE_CLW_STRING) { - // If the character is an ' (single quote) - if (scDoc.ch == '\'') { - // Set the state to default and move forward colouring - // the ' (single quote) as default state - // terminating the string state - scDoc.SetState(SCE_CLW_DEFAULT); - scDoc.Forward(); - } - // If the next character is an ' (single quote) - if (scDoc.chNext == '\'') { - // Move forward one character and set to default state - // colouring the next ' (single quote) as default state - // terminating the string state - scDoc.ForwardSetState(SCE_CLW_DEFAULT); - scDoc.Forward(); - } - } - // Picture String State Handling - else if (scDoc.state == SCE_CLW_PICTURE_STRING) { - // If the character is an ( (open parenthese) - if (scDoc.ch == '(') { - // Increment the parenthese level - iParenthesesLevel++; - } - // Else if the character is a ) (close parenthese) - else if (scDoc.ch == ')') { - // If the parenthese level is set to zero - // parentheses matched - if (!iParenthesesLevel) { - scDoc.SetState(SCE_CLW_DEFAULT); - } - // Else parenthese level is greater than zero - // still looking for matching parentheses - else { - // Decrement the parenthese level - iParenthesesLevel--; - } - } - } - // Standard Equate State Handling - else if (scDoc.state == SCE_CLW_STANDARD_EQUATE) { - if (!isalnum(scDoc.ch)) { - scDoc.SetState(SCE_CLW_DEFAULT); - } - } - // Integer Constant State Handling - else if (scDoc.state == SCE_CLW_INTEGER_CONSTANT) { - // If the character is not a digit (0-9) - // or character is not a hexidecimal character (A-F) - // or character is not a . (point) - // or character is not a numberic base character (B,O,H) - if (!(isdigit(scDoc.ch) - || IsAHexCharacter(scDoc.ch, bCaseSensitive) - || scDoc.ch == '.' - || IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) { - // If the number was a real - if (SetNumericConstantState(scDoc)) { - // Colour the matched string to the real constant state - scDoc.ChangeState(SCE_CLW_REAL_CONSTANT); - } - // Else the number was an integer - else { - // Colour the matched string to an integer constant state - scDoc.ChangeState(SCE_CLW_INTEGER_CONSTANT); - } - // Terminate the integer constant state and set to default state - scDoc.SetState(SCE_CLW_DEFAULT); - } - } - - // - // Determine if a new state should be entered. - // - - // Beginning of Line Handling - if (scDoc.atLineStart) { - // Reset the column 1 label flag - iColumn1Label = false; - // If column 1 character is a label start character - if (IsALabelStart(scDoc.ch)) { - // Label character is found in column 1 - // so set column 1 label flag and clear last column 1 label - iColumn1Label = true; - // Set the state to label - scDoc.SetState(SCE_CLW_LABEL); - } - // else if character is a space or tab - else if (IsASpace(scDoc.ch)){ - // Set to default state - scDoc.SetState(SCE_CLW_DEFAULT); - } - // else if comment start (!) or is an * (asterisk) - else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) { - // then set the state to comment. - scDoc.SetState(SCE_CLW_COMMENT); - } - // else the character is a ? (question mark) - else if (scDoc.ch == '?') { - // Change to the compiler directive state, move forward, - // colouring the ? (question mark), change back to default state. - scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); - scDoc.Forward(); - scDoc.SetState(SCE_CLW_DEFAULT); - } - // else an invalid character in column 1 - else { - // Set to error state - scDoc.SetState(SCE_CLW_ERROR); - } - } - // End of Line Handling - else if (scDoc.atLineEnd) { - // Reset to the default state at the end of each line. - scDoc.SetState(SCE_CLW_DEFAULT); - } - // Default Handling - else { - // If in default state - if (scDoc.state == SCE_CLW_DEFAULT) { - // If is a letter could be a possible statement - if (isalpha(scDoc.ch)) { - // Set the state to Clarion Keyword and verify later - scDoc.SetState(SCE_CLW_KEYWORD); - } - // else is a number - else if (isdigit(scDoc.ch)) { - // Set the state to Integer Constant and verify later - scDoc.SetState(SCE_CLW_INTEGER_CONSTANT); - } - // else if the start of a comment or a | (line continuation) - else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') { - // then set the state to comment. - scDoc.SetState(SCE_CLW_COMMENT); - } - // else if the character is a ' (single quote) - else if (scDoc.ch == '\'') { - // If the character is also a ' (single quote) - // Embedded Apostrophe - if (scDoc.chNext == '\'') { - // Move forward colouring it as default state - scDoc.ForwardSetState(SCE_CLW_DEFAULT); - } - else { - // move to the next character and then set the state to comment. - scDoc.ForwardSetState(SCE_CLW_STRING); - } - } - // else the character is an @ (ampersand) - else if (scDoc.ch == '@') { - // Case insensitive. - if (!bCaseSensitive) { - // If character is a valid picture token character - if (strchr("DEKNPSTdeknpst", scDoc.chNext) != NULL) { - // Set to the picture string state - scDoc.SetState(SCE_CLW_PICTURE_STRING); - } - } - // Case sensitive - else { - // If character is a valid picture token character - if (strchr("DEKNPST", scDoc.chNext) != NULL) { - // Set the picture string state - scDoc.SetState(SCE_CLW_PICTURE_STRING); - } - } - } - } - } - } - // lexing complete - scDoc.Complete(); -} - -// Clarion Language Case Sensitive Colouring Procedure -static void ColouriseClarionDocSensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) { - - ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true); -} - -// Clarion Language Case Insensitive Colouring Procedure -static void ColouriseClarionDocInsensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) { - - ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false); -} - -// Fill Buffer - -static void FillBuffer(unsigned int uiStart, unsigned int uiEnd, Accessor &accStyler, char *szBuffer, unsigned int uiLength) { - - unsigned int uiPos = 0; - - while ((uiPos < uiEnd - uiStart + 1) && (uiPos < uiLength-1)) { - szBuffer[uiPos] = static_cast(toupper(accStyler[uiStart + uiPos])); - uiPos++; - } - szBuffer[uiPos] = '\0'; -} - -// Classify Clarion Fold Point - -static int ClassifyClarionFoldPoint(int iLevel, const char* szString) { - - if (!(isdigit(szString[0]) || (szString[0] == '.'))) { - if (strcmp(szString, "PROCEDURE") == 0) { - // iLevel = SC_FOLDLEVELBASE + 1; - } - else if (strcmp(szString, "MAP") == 0 || - strcmp(szString,"ACCEPT") == 0 || - strcmp(szString,"BEGIN") == 0 || - strcmp(szString,"CASE") == 0 || - strcmp(szString,"EXECUTE") == 0 || - strcmp(szString,"IF") == 0 || - strcmp(szString,"ITEMIZE") == 0 || - strcmp(szString,"INTERFACE") == 0 || - strcmp(szString,"JOIN") == 0 || - strcmp(szString,"LOOP") == 0 || - strcmp(szString,"MODULE") == 0 || - strcmp(szString,"RECORD") == 0) { - iLevel++; - } - else if (strcmp(szString, "APPLICATION") == 0 || - strcmp(szString, "CLASS") == 0 || - strcmp(szString, "DETAIL") == 0 || - strcmp(szString, "FILE") == 0 || - strcmp(szString, "FOOTER") == 0 || - strcmp(szString, "FORM") == 0 || - strcmp(szString, "GROUP") == 0 || - strcmp(szString, "HEADER") == 0 || - strcmp(szString, "INTERFACE") == 0 || - strcmp(szString, "MENU") == 0 || - strcmp(szString, "MENUBAR") == 0 || - strcmp(szString, "OLE") == 0 || - strcmp(szString, "OPTION") == 0 || - strcmp(szString, "QUEUE") == 0 || - strcmp(szString, "REPORT") == 0 || - strcmp(szString, "SHEET") == 0 || - strcmp(szString, "TAB") == 0 || - strcmp(szString, "TOOLBAR") == 0 || - strcmp(szString, "VIEW") == 0 || - strcmp(szString, "WINDOW") == 0) { - iLevel++; - } - else if (strcmp(szString, "END") == 0 || - strcmp(szString, "UNTIL") == 0 || - strcmp(szString, "WHILE") == 0) { - iLevel--; - } - } - return(iLevel); -} - -// Clarion Language Folding Procedure -static void FoldClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *[], Accessor &accStyler) { - - unsigned int uiEndPos = uiStartPos + iLength; - int iLineCurrent = accStyler.GetLine(uiStartPos); - int iLevelPrev = accStyler.LevelAt(iLineCurrent) & SC_FOLDLEVELNUMBERMASK; - int iLevelCurrent = iLevelPrev; - char chNext = accStyler[uiStartPos]; - int iStyle = iInitStyle; - int iStyleNext = accStyler.StyleAt(uiStartPos); - int iVisibleChars = 0; - int iLastStart = 0; - - for (unsigned int uiPos = uiStartPos; uiPos < uiEndPos; uiPos++) { - - char chChar = chNext; - chNext = accStyler.SafeGetCharAt(uiPos + 1); - int iStylePrev = iStyle; - iStyle = iStyleNext; - iStyleNext = accStyler.StyleAt(uiPos + 1); - bool bEOL = (chChar == '\r' && chNext != '\n') || (chChar == '\n'); - - if (iStylePrev == SCE_CLW_DEFAULT) { - if (iStyle == SCE_CLW_KEYWORD || iStyle == SCE_CLW_STRUCTURE_DATA_TYPE) { - // Store last word start point. - iLastStart = uiPos; - } - } - - if (iStylePrev == SCE_CLW_KEYWORD || iStylePrev == SCE_CLW_STRUCTURE_DATA_TYPE) { - if(iswordchar(chChar) && !iswordchar(chNext)) { - char chBuffer[100]; - FillBuffer(iLastStart, uiPos, accStyler, chBuffer, sizeof(chBuffer)); - iLevelCurrent = ClassifyClarionFoldPoint(iLevelCurrent,chBuffer); - // if ((iLevelCurrent == SC_FOLDLEVELBASE + 1) && iLineCurrent > 1) { - // accStyler.SetLevel(iLineCurrent-1,SC_FOLDLEVELBASE); - // iLevelPrev = SC_FOLDLEVELBASE; - // } - } - } - - if (bEOL) { - int iLevel = iLevelPrev; - if ((iLevelCurrent > iLevelPrev) && (iVisibleChars > 0)) - iLevel |= SC_FOLDLEVELHEADERFLAG; - if (iLevel != accStyler.LevelAt(iLineCurrent)) { - accStyler.SetLevel(iLineCurrent,iLevel); - } - iLineCurrent++; - iLevelPrev = iLevelCurrent; - iVisibleChars = 0; - } - - if (!isspacechar(chChar)) - iVisibleChars++; - } - - // Fill in the real level of the next line, keeping the current flags - // as they will be filled in later. - int iFlagsNext = accStyler.LevelAt(iLineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - accStyler.SetLevel(iLineCurrent, iLevelPrev | iFlagsNext); -} - -// Word List Descriptions -static const char * const rgWordListDescriptions[] = { - "Clarion Keywords", - "Compiler Directives", - "Built-in Procedures and Functions", - "Runtime Expressions", - "Structure and Data Types", - "Attributes", - "Standard Equates", - "Reserved Words (Labels)", - "Reserved Words (Procedure Labels)", - 0, -}; - -// Case Sensitive Clarion Language Lexer -LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions); - -// Case Insensitive Clarion Language Lexer -LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions); +// Scintilla source code edit control +/** @file LexClw.cxx + ** Lexer for Clarion. + ** 2004/12/17 Updated Lexer + **/ +// Copyright 2003-2004 by Ron Schofield +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// Is an end of line character +inline bool IsEOL(const int ch) { + + return(ch == '\n'); +} + +// Convert character to uppercase +static char CharacterUpper(char chChar) { + + if (chChar < 'a' || chChar > 'z') { + return(chChar); + } + else { + return(static_cast(chChar - 'a' + 'A')); + } +} + +// Convert string to uppercase +static void StringUpper(char *szString) { + + while (*szString) { + *szString = CharacterUpper(*szString); + szString++; + } +} + +// Is a label start character +inline bool IsALabelStart(const int iChar) { + + return(isalpha(iChar) || iChar == '_'); +} + +// Is a label character +inline bool IsALabelCharacter(const int iChar) { + + return(isalnum(iChar) || iChar == '_' || iChar == ':'); +} + +// Is the character is a ! and the the next character is not a ! +inline bool IsACommentStart(const int iChar) { + + return(iChar == '!'); +} + +// Is the character a Clarion hex character (ABCDEF) +inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) { + + // Case insensitive. + if (!bCaseSensitive) { + if (strchr("ABCDEFabcdef", iChar) != NULL) { + return(true); + } + } + // Case sensitive + else { + if (strchr("ABCDEF", iChar) != NULL) { + return(true); + } + } + return(false); +} + +// Is the character a Clarion base character (B=Binary, O=Octal, H=Hex) +inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) { + + // Case insensitive. + if (!bCaseSensitive) { + // If character is a numeric base character + if (strchr("BOHboh", iChar) != NULL) { + return(true); + } + } + // Case sensitive + else { + // If character is a numeric base character + if (strchr("BOH", iChar) != NULL) { + return(true); + } + } + return(false); +} + +// Set the correct numeric constant state +inline bool SetNumericConstantState(StyleContext &scDoc) { + + int iPoints = 0; // Point counter + char cNumericString[512]; // Numeric string buffer + + // Buffer the current numberic string + scDoc.GetCurrent(cNumericString, sizeof(cNumericString)); + // Loop through the string until end of string (NULL termination) + for (int iIndex = 0; cNumericString[iIndex] != '\0'; iIndex++) { + // Depending on the character + switch (cNumericString[iIndex]) { + // Is a . (point) + case '.' : + // Increment point counter + iPoints++; + break; + default : + break; + } + } + // If points found (can be more than one for improper formatted number + if (iPoints > 0) { + return(true); + } + // Else no points found + else { + return(false); + } +} + +// Get the next word in uppercase from the current position (keyword lookahead) +inline bool GetNextWordUpper(Accessor &styler, unsigned int uiStartPos, int iLength, char *cWord) { + + unsigned int iIndex = 0; // Buffer Index + + // Loop through the remaining string from the current position + for (int iOffset = uiStartPos; iOffset < iLength; iOffset++) { + // Get the character from the buffer using the offset + char cCharacter = styler[iOffset]; + if (IsEOL(cCharacter)) { + break; + } + // If the character is alphabet character + if (isalpha(cCharacter)) { + // Add UPPERCASE character to the word buffer + cWord[iIndex++] = CharacterUpper(cCharacter); + } + } + // Add null termination + cWord[iIndex] = '\0'; + // If no word was found + if (iIndex == 0) { + // Return failure + return(false); + } + // Else word was found + else { + // Return success + return(true); + } +} + +// Clarion Language Colouring Procedure +static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) { + + int iParenthesesLevel = 0; // Parenthese Level + int iColumn1Label = false; // Label starts in Column 1 + + WordList &wlClarionKeywords = *wlKeywords[0]; // Clarion Keywords + WordList &wlCompilerDirectives = *wlKeywords[1]; // Compiler Directives + WordList &wlRuntimeExpressions = *wlKeywords[2]; // Runtime Expressions + WordList &wlBuiltInProcsFuncs = *wlKeywords[3]; // Builtin Procedures and Functions + WordList &wlStructsDataTypes = *wlKeywords[4]; // Structures and Data Types + WordList &wlAttributes = *wlKeywords[5]; // Procedure Attributes + WordList &wlStandardEquates = *wlKeywords[6]; // Standard Equates + WordList &wlLabelReservedWords = *wlKeywords[7]; // Clarion Reserved Keywords (Labels) + WordList &wlProcLabelReservedWords = *wlKeywords[8]; // Clarion Reserved Keywords (Procedure Labels) + + const char wlProcReservedKeywordList[] = + "PROCEDURE FUNCTION"; + WordList wlProcReservedKeywords; + wlProcReservedKeywords.Set(wlProcReservedKeywordList); + + const char wlCompilerKeywordList[] = + "COMPILE OMIT"; + WordList wlCompilerKeywords; + wlCompilerKeywords.Set(wlCompilerKeywordList); + + const char wlLegacyStatementsList[] = + "BOF EOF FUNCTION POINTER SHARE"; + WordList wlLegacyStatements; + wlLegacyStatements.Set(wlLegacyStatementsList); + + StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler); + + // lex source code + for (; scDoc.More(); scDoc.Forward()) + { + // + // Determine if the current state should terminate. + // + + // Label State Handling + if (scDoc.state == SCE_CLW_LABEL) { + // If the character is not a valid label + if (!IsALabelCharacter(scDoc.ch)) { + // If the character is a . (dot syntax) + if (scDoc.ch == '.') { + // Turn off column 1 label flag as label now cannot be reserved work + iColumn1Label = false; + // Uncolour the . (dot) to default state, move forward one character, + // and change back to the label state. + scDoc.SetState(SCE_CLW_DEFAULT); + scDoc.Forward(); + scDoc.SetState(SCE_CLW_LABEL); + } + // Else check label + else { + char cLabel[512]; // Label buffer + // Buffer the current label string + scDoc.GetCurrent(cLabel,sizeof(cLabel)); + // If case insensitive, convert string to UPPERCASE to match passed keywords. + if (!bCaseSensitive) { + StringUpper(cLabel); + } + // Else if UPPERCASE label string is in the Clarion compiler keyword list + if (wlCompilerKeywords.InList(cLabel) && iColumn1Label){ + // change the label to error state + scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); + } + // Else if UPPERCASE label string is in the Clarion reserved keyword list + else if (wlLabelReservedWords.InList(cLabel) && iColumn1Label){ + // change the label to error state + scDoc.ChangeState(SCE_CLW_ERROR); + } + // Else if UPPERCASE label string is + else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) { + char cWord[512]; // Word buffer + // Get the next word from the current position + if (GetNextWordUpper(accStyler,scDoc.currentPos,uiStartPos+iLength,cWord)) { + // If the next word is a procedure reserved word + if (wlProcReservedKeywords.InList(cWord)) { + // Change the label to error state + scDoc.ChangeState(SCE_CLW_ERROR); + } + } + } + // Else if label string is in the compiler directive keyword list + else if (wlCompilerDirectives.InList(cLabel)) { + // change the state to compiler directive state + scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); + } + // Terminate the label state and set to default state + scDoc.SetState(SCE_CLW_DEFAULT); + } + } + } + // Keyword State Handling + else if (scDoc.state == SCE_CLW_KEYWORD) { + // If character is : (colon) + if (scDoc.ch == ':') { + char cEquate[512]; // Equate buffer + // Move forward to include : (colon) in buffer + scDoc.Forward(); + // Buffer the equate string + scDoc.GetCurrent(cEquate,sizeof(cEquate)); + // If case insensitive, convert string to UPPERCASE to match passed keywords. + if (!bCaseSensitive) { + StringUpper(cEquate); + } + // If statement string is in the equate list + if (wlStandardEquates.InList(cEquate)) { + // Change to equate state + scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE); + } + } + // If the character is not a valid label character + else if (!IsALabelCharacter(scDoc.ch)) { + char cStatement[512]; // Statement buffer + // Buffer the statement string + scDoc.GetCurrent(cStatement,sizeof(cStatement)); + // If case insensitive, convert string to UPPERCASE to match passed keywords. + if (!bCaseSensitive) { + StringUpper(cStatement); + } + // If statement string is in the Clarion keyword list + if (wlClarionKeywords.InList(cStatement)) { + // Change the statement string to the Clarion keyword state + scDoc.ChangeState(SCE_CLW_KEYWORD); + } + // Else if statement string is in the compiler directive keyword list + else if (wlCompilerDirectives.InList(cStatement)) { + // Change the statement string to the compiler directive state + scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); + } + // Else if statement string is in the runtime expressions keyword list + else if (wlRuntimeExpressions.InList(cStatement)) { + // Change the statement string to the runtime expressions state + scDoc.ChangeState(SCE_CLW_RUNTIME_EXPRESSIONS); + } + // Else if statement string is in the builtin procedures and functions keyword list + else if (wlBuiltInProcsFuncs.InList(cStatement)) { + // Change the statement string to the builtin procedures and functions state + scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION); + } + // Else if statement string is in the tructures and data types keyword list + else if (wlStructsDataTypes.InList(cStatement)) { + // Change the statement string to the structures and data types state + scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE); + } + // Else if statement string is in the procedure attribute keyword list + else if (wlAttributes.InList(cStatement)) { + // Change the statement string to the procedure attribute state + scDoc.ChangeState(SCE_CLW_ATTRIBUTE); + } + // Else if statement string is in the standard equate keyword list + else if (wlStandardEquates.InList(cStatement)) { + // Change the statement string to the standard equate state + scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE); + } + // Else if statement string is in the deprecated or legacy keyword list + else if (wlLegacyStatements.InList(cStatement)) { + // Change the statement string to the standard equate state + scDoc.ChangeState(SCE_CLW_DEPRECATED); + } + // Else the statement string doesn't match any work list + else { + // Change the statement string to the default state + scDoc.ChangeState(SCE_CLW_DEFAULT); + } + // Terminate the keyword state and set to default state + scDoc.SetState(SCE_CLW_DEFAULT); + } + } + // String State Handling + else if (scDoc.state == SCE_CLW_STRING) { + // If the character is an ' (single quote) + if (scDoc.ch == '\'') { + // Set the state to default and move forward colouring + // the ' (single quote) as default state + // terminating the string state + scDoc.SetState(SCE_CLW_DEFAULT); + scDoc.Forward(); + } + // If the next character is an ' (single quote) + if (scDoc.chNext == '\'') { + // Move forward one character and set to default state + // colouring the next ' (single quote) as default state + // terminating the string state + scDoc.ForwardSetState(SCE_CLW_DEFAULT); + scDoc.Forward(); + } + } + // Picture String State Handling + else if (scDoc.state == SCE_CLW_PICTURE_STRING) { + // If the character is an ( (open parenthese) + if (scDoc.ch == '(') { + // Increment the parenthese level + iParenthesesLevel++; + } + // Else if the character is a ) (close parenthese) + else if (scDoc.ch == ')') { + // If the parenthese level is set to zero + // parentheses matched + if (!iParenthesesLevel) { + scDoc.SetState(SCE_CLW_DEFAULT); + } + // Else parenthese level is greater than zero + // still looking for matching parentheses + else { + // Decrement the parenthese level + iParenthesesLevel--; + } + } + } + // Standard Equate State Handling + else if (scDoc.state == SCE_CLW_STANDARD_EQUATE) { + if (!isalnum(scDoc.ch)) { + scDoc.SetState(SCE_CLW_DEFAULT); + } + } + // Integer Constant State Handling + else if (scDoc.state == SCE_CLW_INTEGER_CONSTANT) { + // If the character is not a digit (0-9) + // or character is not a hexidecimal character (A-F) + // or character is not a . (point) + // or character is not a numberic base character (B,O,H) + if (!(isdigit(scDoc.ch) + || IsAHexCharacter(scDoc.ch, bCaseSensitive) + || scDoc.ch == '.' + || IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) { + // If the number was a real + if (SetNumericConstantState(scDoc)) { + // Colour the matched string to the real constant state + scDoc.ChangeState(SCE_CLW_REAL_CONSTANT); + } + // Else the number was an integer + else { + // Colour the matched string to an integer constant state + scDoc.ChangeState(SCE_CLW_INTEGER_CONSTANT); + } + // Terminate the integer constant state and set to default state + scDoc.SetState(SCE_CLW_DEFAULT); + } + } + + // + // Determine if a new state should be entered. + // + + // Beginning of Line Handling + if (scDoc.atLineStart) { + // Reset the column 1 label flag + iColumn1Label = false; + // If column 1 character is a label start character + if (IsALabelStart(scDoc.ch)) { + // Label character is found in column 1 + // so set column 1 label flag and clear last column 1 label + iColumn1Label = true; + // Set the state to label + scDoc.SetState(SCE_CLW_LABEL); + } + // else if character is a space or tab + else if (IsASpace(scDoc.ch)){ + // Set to default state + scDoc.SetState(SCE_CLW_DEFAULT); + } + // else if comment start (!) or is an * (asterisk) + else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) { + // then set the state to comment. + scDoc.SetState(SCE_CLW_COMMENT); + } + // else the character is a ? (question mark) + else if (scDoc.ch == '?') { + // Change to the compiler directive state, move forward, + // colouring the ? (question mark), change back to default state. + scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); + scDoc.Forward(); + scDoc.SetState(SCE_CLW_DEFAULT); + } + // else an invalid character in column 1 + else { + // Set to error state + scDoc.SetState(SCE_CLW_ERROR); + } + } + // End of Line Handling + else if (scDoc.atLineEnd) { + // Reset to the default state at the end of each line. + scDoc.SetState(SCE_CLW_DEFAULT); + } + // Default Handling + else { + // If in default state + if (scDoc.state == SCE_CLW_DEFAULT) { + // If is a letter could be a possible statement + if (isalpha(scDoc.ch)) { + // Set the state to Clarion Keyword and verify later + scDoc.SetState(SCE_CLW_KEYWORD); + } + // else is a number + else if (isdigit(scDoc.ch)) { + // Set the state to Integer Constant and verify later + scDoc.SetState(SCE_CLW_INTEGER_CONSTANT); + } + // else if the start of a comment or a | (line continuation) + else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') { + // then set the state to comment. + scDoc.SetState(SCE_CLW_COMMENT); + } + // else if the character is a ' (single quote) + else if (scDoc.ch == '\'') { + // If the character is also a ' (single quote) + // Embedded Apostrophe + if (scDoc.chNext == '\'') { + // Move forward colouring it as default state + scDoc.ForwardSetState(SCE_CLW_DEFAULT); + } + else { + // move to the next character and then set the state to comment. + scDoc.ForwardSetState(SCE_CLW_STRING); + } + } + // else the character is an @ (ampersand) + else if (scDoc.ch == '@') { + // Case insensitive. + if (!bCaseSensitive) { + // If character is a valid picture token character + if (strchr("DEKNPSTdeknpst", scDoc.chNext) != NULL) { + // Set to the picture string state + scDoc.SetState(SCE_CLW_PICTURE_STRING); + } + } + // Case sensitive + else { + // If character is a valid picture token character + if (strchr("DEKNPST", scDoc.chNext) != NULL) { + // Set the picture string state + scDoc.SetState(SCE_CLW_PICTURE_STRING); + } + } + } + } + } + } + // lexing complete + scDoc.Complete(); +} + +// Clarion Language Case Sensitive Colouring Procedure +static void ColouriseClarionDocSensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) { + + ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true); +} + +// Clarion Language Case Insensitive Colouring Procedure +static void ColouriseClarionDocInsensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) { + + ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false); +} + +// Fill Buffer + +static void FillBuffer(unsigned int uiStart, unsigned int uiEnd, Accessor &accStyler, char *szBuffer, unsigned int uiLength) { + + unsigned int uiPos = 0; + + while ((uiPos < uiEnd - uiStart + 1) && (uiPos < uiLength-1)) { + szBuffer[uiPos] = static_cast(toupper(accStyler[uiStart + uiPos])); + uiPos++; + } + szBuffer[uiPos] = '\0'; +} + +// Classify Clarion Fold Point + +static int ClassifyClarionFoldPoint(int iLevel, const char* szString) { + + if (!(isdigit(szString[0]) || (szString[0] == '.'))) { + if (strcmp(szString, "PROCEDURE") == 0) { + // iLevel = SC_FOLDLEVELBASE + 1; + } + else if (strcmp(szString, "MAP") == 0 || + strcmp(szString,"ACCEPT") == 0 || + strcmp(szString,"BEGIN") == 0 || + strcmp(szString,"CASE") == 0 || + strcmp(szString,"EXECUTE") == 0 || + strcmp(szString,"IF") == 0 || + strcmp(szString,"ITEMIZE") == 0 || + strcmp(szString,"INTERFACE") == 0 || + strcmp(szString,"JOIN") == 0 || + strcmp(szString,"LOOP") == 0 || + strcmp(szString,"MODULE") == 0 || + strcmp(szString,"RECORD") == 0) { + iLevel++; + } + else if (strcmp(szString, "APPLICATION") == 0 || + strcmp(szString, "CLASS") == 0 || + strcmp(szString, "DETAIL") == 0 || + strcmp(szString, "FILE") == 0 || + strcmp(szString, "FOOTER") == 0 || + strcmp(szString, "FORM") == 0 || + strcmp(szString, "GROUP") == 0 || + strcmp(szString, "HEADER") == 0 || + strcmp(szString, "INTERFACE") == 0 || + strcmp(szString, "MENU") == 0 || + strcmp(szString, "MENUBAR") == 0 || + strcmp(szString, "OLE") == 0 || + strcmp(szString, "OPTION") == 0 || + strcmp(szString, "QUEUE") == 0 || + strcmp(szString, "REPORT") == 0 || + strcmp(szString, "SHEET") == 0 || + strcmp(szString, "TAB") == 0 || + strcmp(szString, "TOOLBAR") == 0 || + strcmp(szString, "VIEW") == 0 || + strcmp(szString, "WINDOW") == 0) { + iLevel++; + } + else if (strcmp(szString, "END") == 0 || + strcmp(szString, "UNTIL") == 0 || + strcmp(szString, "WHILE") == 0) { + iLevel--; + } + } + return(iLevel); +} + +// Clarion Language Folding Procedure +static void FoldClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *[], Accessor &accStyler) { + + unsigned int uiEndPos = uiStartPos + iLength; + int iLineCurrent = accStyler.GetLine(uiStartPos); + int iLevelPrev = accStyler.LevelAt(iLineCurrent) & SC_FOLDLEVELNUMBERMASK; + int iLevelCurrent = iLevelPrev; + char chNext = accStyler[uiStartPos]; + int iStyle = iInitStyle; + int iStyleNext = accStyler.StyleAt(uiStartPos); + int iVisibleChars = 0; + int iLastStart = 0; + + for (unsigned int uiPos = uiStartPos; uiPos < uiEndPos; uiPos++) { + + char chChar = chNext; + chNext = accStyler.SafeGetCharAt(uiPos + 1); + int iStylePrev = iStyle; + iStyle = iStyleNext; + iStyleNext = accStyler.StyleAt(uiPos + 1); + bool bEOL = (chChar == '\r' && chNext != '\n') || (chChar == '\n'); + + if (iStylePrev == SCE_CLW_DEFAULT) { + if (iStyle == SCE_CLW_KEYWORD || iStyle == SCE_CLW_STRUCTURE_DATA_TYPE) { + // Store last word start point. + iLastStart = uiPos; + } + } + + if (iStylePrev == SCE_CLW_KEYWORD || iStylePrev == SCE_CLW_STRUCTURE_DATA_TYPE) { + if(iswordchar(chChar) && !iswordchar(chNext)) { + char chBuffer[100]; + FillBuffer(iLastStart, uiPos, accStyler, chBuffer, sizeof(chBuffer)); + iLevelCurrent = ClassifyClarionFoldPoint(iLevelCurrent,chBuffer); + // if ((iLevelCurrent == SC_FOLDLEVELBASE + 1) && iLineCurrent > 1) { + // accStyler.SetLevel(iLineCurrent-1,SC_FOLDLEVELBASE); + // iLevelPrev = SC_FOLDLEVELBASE; + // } + } + } + + if (bEOL) { + int iLevel = iLevelPrev; + if ((iLevelCurrent > iLevelPrev) && (iVisibleChars > 0)) + iLevel |= SC_FOLDLEVELHEADERFLAG; + if (iLevel != accStyler.LevelAt(iLineCurrent)) { + accStyler.SetLevel(iLineCurrent,iLevel); + } + iLineCurrent++; + iLevelPrev = iLevelCurrent; + iVisibleChars = 0; + } + + if (!isspacechar(chChar)) + iVisibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags + // as they will be filled in later. + int iFlagsNext = accStyler.LevelAt(iLineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + accStyler.SetLevel(iLineCurrent, iLevelPrev | iFlagsNext); +} + +// Word List Descriptions +static const char * const rgWordListDescriptions[] = { + "Clarion Keywords", + "Compiler Directives", + "Built-in Procedures and Functions", + "Runtime Expressions", + "Structure and Data Types", + "Attributes", + "Standard Equates", + "Reserved Words (Labels)", + "Reserved Words (Procedure Labels)", + 0, +}; + +// Case Sensitive Clarion Language Lexer +LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions); + +// Case Insensitive Clarion Language Lexer +LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions); diff --git a/scintilla/lexers/LexCOBOL.cxx b/ThirdLibs/scintilla/lexers/LexCOBOL.cxx similarity index 97% rename from scintilla/lexers/LexCOBOL.cxx rename to ThirdLibs/scintilla/lexers/LexCOBOL.cxx index 4fe09742..b3bc011d 100644 --- a/scintilla/lexers/LexCOBOL.cxx +++ b/ThirdLibs/scintilla/lexers/LexCOBOL.cxx @@ -1,379 +1,379 @@ -// Scintilla source code edit control -/** @file LexCOBOL.cxx - ** Lexer for COBOL - ** Based on LexPascal.cxx - ** Written by Laurent le Tynevez - ** Updated by Simon Steele September 2002 - ** Updated by Mathias Rauen May 2003 (Delphi adjustments) - ** Updated by Rod Falck, Aug 2006 Converted to COBOL - **/ - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#define IN_DIVISION 0x01 -#define IN_DECLARATIVES 0x02 -#define IN_SECTION 0x04 -#define IN_PARAGRAPH 0x08 -#define IN_FLAGS 0xF -#define NOT_HEADER 0x10 - -inline bool isCOBOLoperator(char ch) - { - return isoperator(ch); - } - -inline bool isCOBOLwordchar(char ch) - { - return isascii(ch) && (isalnum(ch) || ch == '-'); - - } - -inline bool isCOBOLwordstart(char ch) - { - return isascii(ch) && isalnum(ch); - } - -static int CountBits(int nBits) - { - int count = 0; - for (int i = 0; i < 32; ++i) - { - count += nBits & 1; - nBits >>= 1; - } - return count; - } - -static void getRange(unsigned int start, - unsigned int end, - Accessor &styler, - char *s, - unsigned int len) { - unsigned int i = 0; - while ((i < end - start + 1) && (i < len-1)) { - s[i] = static_cast(tolower(styler[start + i])); - i++; - } - s[i] = '\0'; -} - -static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr) { - styler.ColourTo(end, attr); -} - - -static int classifyWordCOBOL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, int nContainment, bool *bAarea) { - int ret = 0; - - WordList& a_keywords = *keywordlists[0]; - WordList& b_keywords = *keywordlists[1]; - WordList& c_keywords = *keywordlists[2]; - - char s[100]; - getRange(start, end, styler, s, sizeof(s)); - - char chAttr = SCE_C_IDENTIFIER; - if (isdigit(s[0]) || (s[0] == '.') || (s[0] == 'v')) { - chAttr = SCE_C_NUMBER; - char *p = s + 1; - while (*p) { - if ((!isdigit(*p) && (*p) != 'v') && isCOBOLwordchar(*p)) { - chAttr = SCE_C_IDENTIFIER; - break; - } - ++p; - } - } - else { - if (a_keywords.InList(s)) { - chAttr = SCE_C_WORD; - } - else if (b_keywords.InList(s)) { - chAttr = SCE_C_WORD2; - } - else if (c_keywords.InList(s)) { - chAttr = SCE_C_UUID; - } - } - if (*bAarea) { - if (strcmp(s, "division") == 0) { - ret = IN_DIVISION; - // we've determined the containment, anything else is just ignored for those purposes - *bAarea = false; - } else if (strcmp(s, "declaratives") == 0) { - ret = IN_DIVISION | IN_DECLARATIVES; - if (nContainment & IN_DECLARATIVES) - ret |= NOT_HEADER | IN_SECTION; - // we've determined the containment, anything else is just ignored for those purposes - *bAarea = false; - } else if (strcmp(s, "section") == 0) { - ret = (nContainment &~ IN_PARAGRAPH) | IN_SECTION; - // we've determined the containment, anything else is just ignored for those purposes - *bAarea = false; - } else if (strcmp(s, "end") == 0 && (nContainment & IN_DECLARATIVES)) { - ret = IN_DIVISION | IN_DECLARATIVES | IN_SECTION | NOT_HEADER; - } else { - ret = nContainment | IN_PARAGRAPH; - } - } - ColourTo(styler, end, chAttr); - return ret; -} - -static void ColouriseCOBOLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - styler.StartAt(startPos); - - int state = initStyle; - if (state == SCE_C_CHARACTER) // Does not leak onto next line - state = SCE_C_DEFAULT; - char chPrev = ' '; - char chNext = styler[startPos]; - unsigned int lengthDoc = startPos + length; - - int nContainment; - - int currentLine = styler.GetLine(startPos); - if (currentLine > 0) { - styler.SetLineState(currentLine, styler.GetLineState(currentLine-1)); - nContainment = styler.GetLineState(currentLine); - nContainment &= ~NOT_HEADER; - } else { - styler.SetLineState(currentLine, 0); - nContainment = 0; - } - - styler.StartSegment(startPos); - bool bNewLine = true; - bool bAarea = !isspacechar(chNext); - int column = 0; - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - - chNext = styler.SafeGetCharAt(i + 1); - - ++column; - - if (bNewLine) { - column = 0; - } - if (column <= 1 && !bAarea) { - bAarea = !isspacechar(ch); - } - bool bSetNewLine = false; - if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { - // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) - // Avoid triggering two times on Dos/Win - // End of line - if (state == SCE_C_CHARACTER) { - ColourTo(styler, i, state); - state = SCE_C_DEFAULT; - } - styler.SetLineState(currentLine, nContainment); - currentLine++; - bSetNewLine = true; - if (nContainment & NOT_HEADER) - nContainment &= ~(NOT_HEADER | IN_DECLARATIVES | IN_SECTION); - } - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - chPrev = ' '; - i += 1; - continue; - } - - if (state == SCE_C_DEFAULT) { - if (isCOBOLwordstart(ch) || (ch == '$' && isascii(chNext) && isalpha(chNext))) { - ColourTo(styler, i-1, state); - state = SCE_C_IDENTIFIER; - } else if (column == 6 && ch == '*') { - // Cobol comment line: asterisk in column 7. - ColourTo(styler, i-1, state); - state = SCE_C_COMMENTLINE; - } else if (ch == '*' && chNext == '>') { - // Cobol inline comment: asterisk, followed by greater than. - ColourTo(styler, i-1, state); - state = SCE_C_COMMENTLINE; - } else if (column == 0 && ch == '*' && chNext != '*') { - ColourTo(styler, i-1, state); - state = SCE_C_COMMENTLINE; - } else if (column == 0 && ch == '/' && chNext != '*') { - ColourTo(styler, i-1, state); - state = SCE_C_COMMENTLINE; - } else if (column == 0 && ch == '*' && chNext == '*') { - ColourTo(styler, i-1, state); - state = SCE_C_COMMENTDOC; - } else if (column == 0 && ch == '/' && chNext == '*') { - ColourTo(styler, i-1, state); - state = SCE_C_COMMENTDOC; - } else if (ch == '"') { - ColourTo(styler, i-1, state); - state = SCE_C_STRING; - } else if (ch == '\'') { - ColourTo(styler, i-1, state); - state = SCE_C_CHARACTER; - } else if (ch == '?' && column == 0) { - ColourTo(styler, i-1, state); - state = SCE_C_PREPROCESSOR; - } else if (isCOBOLoperator(ch)) { - ColourTo(styler, i-1, state); - ColourTo(styler, i, SCE_C_OPERATOR); - } - } else if (state == SCE_C_IDENTIFIER) { - if (!isCOBOLwordchar(ch)) { - int lStateChange = classifyWordCOBOL(styler.GetStartSegment(), i - 1, keywordlists, styler, nContainment, &bAarea); - - if(lStateChange != 0) { - styler.SetLineState(currentLine, lStateChange); - nContainment = lStateChange; - } - - state = SCE_C_DEFAULT; - chNext = styler.SafeGetCharAt(i + 1); - if (ch == '"') { - state = SCE_C_STRING; - } else if (ch == '\'') { - state = SCE_C_CHARACTER; - } else if (isCOBOLoperator(ch)) { - ColourTo(styler, i, SCE_C_OPERATOR); - } - } - } else { - if (state == SCE_C_PREPROCESSOR) { - if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) { - ColourTo(styler, i-1, state); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_COMMENT) { - if (ch == '\r' || ch == '\n') { - ColourTo(styler, i, state); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_COMMENTDOC) { - if (ch == '\r' || ch == '\n') { - if (((i > styler.GetStartSegment() + 2) || ( - (initStyle == SCE_C_COMMENTDOC) && - (styler.GetStartSegment() == static_cast(startPos))))) { - ColourTo(styler, i, state); - state = SCE_C_DEFAULT; - } - } - } else if (state == SCE_C_COMMENTLINE) { - if (ch == '\r' || ch == '\n') { - ColourTo(styler, i-1, state); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_STRING) { - if (ch == '"') { - ColourTo(styler, i, state); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_CHARACTER) { - if (ch == '\'') { - ColourTo(styler, i, state); - state = SCE_C_DEFAULT; - } - } - } - chPrev = ch; - bNewLine = bSetNewLine; - if (bNewLine) - { - bAarea = false; - } - } - ColourTo(styler, lengthDoc - 1, state); -} - -static void FoldCOBOLDoc(unsigned int startPos, int length, int, WordList *[], - Accessor &styler) { - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) & SC_FOLDLEVELNUMBERMASK : 0xFFF; - char chNext = styler[startPos]; - - bool bNewLine = true; - bool bAarea = !isspacechar(chNext); - int column = 0; - bool bComment = false; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - ++column; - - if (bNewLine) { - column = 0; - bComment = (ch == '*' || ch == '/' || ch == '?'); - } - if (column <= 1 && !bAarea) { - bAarea = !isspacechar(ch); - } - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (atEOL) { - int nContainment = styler.GetLineState(lineCurrent); - int lev = CountBits(nContainment & IN_FLAGS) | SC_FOLDLEVELBASE; - if (bAarea && !bComment) - --lev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((bAarea) && (visibleChars > 0) && !(nContainment & NOT_HEADER) && !bComment) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - if ((lev & SC_FOLDLEVELNUMBERMASK) <= (levelPrev & SC_FOLDLEVELNUMBERMASK)) { - // this level is at the same level or less than the previous line - // therefore these is nothing for the previous header to collapse, so remove the header - styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG); - } - levelPrev = lev; - visibleChars = 0; - bAarea = false; - bNewLine = true; - lineCurrent++; - } else { - bNewLine = false; - } - - - if (!isspacechar(ch)) - visibleChars++; - } - - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const COBOLWordListDesc[] = { - "A Keywords", - "B Keywords", - "Extended Keywords", - 0 -}; - -LexerModule lmCOBOL(SCLEX_COBOL, ColouriseCOBOLDoc, "COBOL", FoldCOBOLDoc, COBOLWordListDesc); +// Scintilla source code edit control +/** @file LexCOBOL.cxx + ** Lexer for COBOL + ** Based on LexPascal.cxx + ** Written by Laurent le Tynevez + ** Updated by Simon Steele September 2002 + ** Updated by Mathias Rauen May 2003 (Delphi adjustments) + ** Updated by Rod Falck, Aug 2006 Converted to COBOL + **/ + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#define IN_DIVISION 0x01 +#define IN_DECLARATIVES 0x02 +#define IN_SECTION 0x04 +#define IN_PARAGRAPH 0x08 +#define IN_FLAGS 0xF +#define NOT_HEADER 0x10 + +inline bool isCOBOLoperator(char ch) + { + return isoperator(ch); + } + +inline bool isCOBOLwordchar(char ch) + { + return isascii(ch) && (isalnum(ch) || ch == '-'); + + } + +inline bool isCOBOLwordstart(char ch) + { + return isascii(ch) && isalnum(ch); + } + +static int CountBits(int nBits) + { + int count = 0; + for (int i = 0; i < 32; ++i) + { + count += nBits & 1; + nBits >>= 1; + } + return count; + } + +static void getRange(unsigned int start, + unsigned int end, + Accessor &styler, + char *s, + unsigned int len) { + unsigned int i = 0; + while ((i < end - start + 1) && (i < len-1)) { + s[i] = static_cast(tolower(styler[start + i])); + i++; + } + s[i] = '\0'; +} + +static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr) { + styler.ColourTo(end, attr); +} + + +static int classifyWordCOBOL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, int nContainment, bool *bAarea) { + int ret = 0; + + WordList& a_keywords = *keywordlists[0]; + WordList& b_keywords = *keywordlists[1]; + WordList& c_keywords = *keywordlists[2]; + + char s[100]; + getRange(start, end, styler, s, sizeof(s)); + + char chAttr = SCE_C_IDENTIFIER; + if (isdigit(s[0]) || (s[0] == '.') || (s[0] == 'v')) { + chAttr = SCE_C_NUMBER; + char *p = s + 1; + while (*p) { + if ((!isdigit(*p) && (*p) != 'v') && isCOBOLwordchar(*p)) { + chAttr = SCE_C_IDENTIFIER; + break; + } + ++p; + } + } + else { + if (a_keywords.InList(s)) { + chAttr = SCE_C_WORD; + } + else if (b_keywords.InList(s)) { + chAttr = SCE_C_WORD2; + } + else if (c_keywords.InList(s)) { + chAttr = SCE_C_UUID; + } + } + if (*bAarea) { + if (strcmp(s, "division") == 0) { + ret = IN_DIVISION; + // we've determined the containment, anything else is just ignored for those purposes + *bAarea = false; + } else if (strcmp(s, "declaratives") == 0) { + ret = IN_DIVISION | IN_DECLARATIVES; + if (nContainment & IN_DECLARATIVES) + ret |= NOT_HEADER | IN_SECTION; + // we've determined the containment, anything else is just ignored for those purposes + *bAarea = false; + } else if (strcmp(s, "section") == 0) { + ret = (nContainment &~ IN_PARAGRAPH) | IN_SECTION; + // we've determined the containment, anything else is just ignored for those purposes + *bAarea = false; + } else if (strcmp(s, "end") == 0 && (nContainment & IN_DECLARATIVES)) { + ret = IN_DIVISION | IN_DECLARATIVES | IN_SECTION | NOT_HEADER; + } else { + ret = nContainment | IN_PARAGRAPH; + } + } + ColourTo(styler, end, chAttr); + return ret; +} + +static void ColouriseCOBOLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + styler.StartAt(startPos); + + int state = initStyle; + if (state == SCE_C_CHARACTER) // Does not leak onto next line + state = SCE_C_DEFAULT; + char chPrev = ' '; + char chNext = styler[startPos]; + unsigned int lengthDoc = startPos + length; + + int nContainment; + + int currentLine = styler.GetLine(startPos); + if (currentLine > 0) { + styler.SetLineState(currentLine, styler.GetLineState(currentLine-1)); + nContainment = styler.GetLineState(currentLine); + nContainment &= ~NOT_HEADER; + } else { + styler.SetLineState(currentLine, 0); + nContainment = 0; + } + + styler.StartSegment(startPos); + bool bNewLine = true; + bool bAarea = !isspacechar(chNext); + int column = 0; + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + + chNext = styler.SafeGetCharAt(i + 1); + + ++column; + + if (bNewLine) { + column = 0; + } + if (column <= 1 && !bAarea) { + bAarea = !isspacechar(ch); + } + bool bSetNewLine = false; + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // End of line + if (state == SCE_C_CHARACTER) { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + styler.SetLineState(currentLine, nContainment); + currentLine++; + bSetNewLine = true; + if (nContainment & NOT_HEADER) + nContainment &= ~(NOT_HEADER | IN_DECLARATIVES | IN_SECTION); + } + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + chPrev = ' '; + i += 1; + continue; + } + + if (state == SCE_C_DEFAULT) { + if (isCOBOLwordstart(ch) || (ch == '$' && isascii(chNext) && isalpha(chNext))) { + ColourTo(styler, i-1, state); + state = SCE_C_IDENTIFIER; + } else if (column == 6 && ch == '*') { + // Cobol comment line: asterisk in column 7. + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTLINE; + } else if (ch == '*' && chNext == '>') { + // Cobol inline comment: asterisk, followed by greater than. + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTLINE; + } else if (column == 0 && ch == '*' && chNext != '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTLINE; + } else if (column == 0 && ch == '/' && chNext != '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTLINE; + } else if (column == 0 && ch == '*' && chNext == '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTDOC; + } else if (column == 0 && ch == '/' && chNext == '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTDOC; + } else if (ch == '"') { + ColourTo(styler, i-1, state); + state = SCE_C_STRING; + } else if (ch == '\'') { + ColourTo(styler, i-1, state); + state = SCE_C_CHARACTER; + } else if (ch == '?' && column == 0) { + ColourTo(styler, i-1, state); + state = SCE_C_PREPROCESSOR; + } else if (isCOBOLoperator(ch)) { + ColourTo(styler, i-1, state); + ColourTo(styler, i, SCE_C_OPERATOR); + } + } else if (state == SCE_C_IDENTIFIER) { + if (!isCOBOLwordchar(ch)) { + int lStateChange = classifyWordCOBOL(styler.GetStartSegment(), i - 1, keywordlists, styler, nContainment, &bAarea); + + if(lStateChange != 0) { + styler.SetLineState(currentLine, lStateChange); + nContainment = lStateChange; + } + + state = SCE_C_DEFAULT; + chNext = styler.SafeGetCharAt(i + 1); + if (ch == '"') { + state = SCE_C_STRING; + } else if (ch == '\'') { + state = SCE_C_CHARACTER; + } else if (isCOBOLoperator(ch)) { + ColourTo(styler, i, SCE_C_OPERATOR); + } + } + } else { + if (state == SCE_C_PREPROCESSOR) { + if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) { + ColourTo(styler, i-1, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENT) { + if (ch == '\r' || ch == '\n') { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENTDOC) { + if (ch == '\r' || ch == '\n') { + if (((i > styler.GetStartSegment() + 2) || ( + (initStyle == SCE_C_COMMENTDOC) && + (styler.GetStartSegment() == static_cast(startPos))))) { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + } + } else if (state == SCE_C_COMMENTLINE) { + if (ch == '\r' || ch == '\n') { + ColourTo(styler, i-1, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_STRING) { + if (ch == '"') { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_CHARACTER) { + if (ch == '\'') { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + } + } + chPrev = ch; + bNewLine = bSetNewLine; + if (bNewLine) + { + bAarea = false; + } + } + ColourTo(styler, lengthDoc - 1, state); +} + +static void FoldCOBOLDoc(unsigned int startPos, int length, int, WordList *[], + Accessor &styler) { + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) & SC_FOLDLEVELNUMBERMASK : 0xFFF; + char chNext = styler[startPos]; + + bool bNewLine = true; + bool bAarea = !isspacechar(chNext); + int column = 0; + bool bComment = false; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + ++column; + + if (bNewLine) { + column = 0; + bComment = (ch == '*' || ch == '/' || ch == '?'); + } + if (column <= 1 && !bAarea) { + bAarea = !isspacechar(ch); + } + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (atEOL) { + int nContainment = styler.GetLineState(lineCurrent); + int lev = CountBits(nContainment & IN_FLAGS) | SC_FOLDLEVELBASE; + if (bAarea && !bComment) + --lev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((bAarea) && (visibleChars > 0) && !(nContainment & NOT_HEADER) && !bComment) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + if ((lev & SC_FOLDLEVELNUMBERMASK) <= (levelPrev & SC_FOLDLEVELNUMBERMASK)) { + // this level is at the same level or less than the previous line + // therefore these is nothing for the previous header to collapse, so remove the header + styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG); + } + levelPrev = lev; + visibleChars = 0; + bAarea = false; + bNewLine = true; + lineCurrent++; + } else { + bNewLine = false; + } + + + if (!isspacechar(ch)) + visibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const COBOLWordListDesc[] = { + "A Keywords", + "B Keywords", + "Extended Keywords", + 0 +}; + +LexerModule lmCOBOL(SCLEX_COBOL, ColouriseCOBOLDoc, "COBOL", FoldCOBOLDoc, COBOLWordListDesc); diff --git a/scintilla/lexers/LexCPP.cxx b/ThirdLibs/scintilla/lexers/LexCPP.cxx similarity index 96% rename from scintilla/lexers/LexCPP.cxx rename to ThirdLibs/scintilla/lexers/LexCPP.cxx index 633cc4d2..b92f279d 100644 --- a/scintilla/lexers/LexCPP.cxx +++ b/ThirdLibs/scintilla/lexers/LexCPP.cxx @@ -1,1196 +1,1196 @@ -// Scintilla source code edit control -/** @file LexCPP.cxx - ** Lexer for C++, C, Java, and JavaScript. - ** Further folding features and configuration properties added by "Udo Lechner" - **/ -// Copyright 1998-2005 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" -#include "OptionSet.h" -#include "SparseState.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static bool IsSpaceEquiv(int state) { - return (state <= SCE_C_COMMENTDOC) || - // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE - (state == SCE_C_COMMENTLINEDOC) || (state == SCE_C_COMMENTDOCKEYWORD) || - (state == SCE_C_COMMENTDOCKEYWORDERROR); -} - -// Preconditions: sc.currentPos points to a character after '+' or '-'. -// The test for pos reaching 0 should be redundant, -// and is in only for safety measures. -// Limitation: this code will give the incorrect answer for code like -// a = b+++/ptn/... -// Putting a space between the '++' post-inc operator and the '+' binary op -// fixes this, and is highly recommended for readability anyway. -static bool FollowsPostfixOperator(StyleContext &sc, LexAccessor &styler) { - int pos = (int) sc.currentPos; - while (--pos > 0) { - char ch = styler[pos]; - if (ch == '+' || ch == '-') { - return styler[pos - 1] == ch; - } - } - return false; -} - -static bool followsReturnKeyword(StyleContext &sc, LexAccessor &styler) { - // Don't look at styles, so no need to flush. - int pos = (int) sc.currentPos; - int currentLine = styler.GetLine(pos); - int lineStartPos = styler.LineStart(currentLine); - char ch; - while (--pos > lineStartPos) { - ch = styler.SafeGetCharAt(pos); - if (ch != ' ' && ch != '\t') { - break; - } - } - const char *retBack = "nruter"; - const char *s = retBack; - while (*s - && pos >= lineStartPos - && styler.SafeGetCharAt(pos) == *s) { - s++; - pos--; - } - return !*s; -} - -static std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace) { - std::string restOfLine; - int i =0; - char ch = styler.SafeGetCharAt(start, '\n'); - while ((ch != '\r') && (ch != '\n')) { - if (allowSpace || (ch != ' ')) - restOfLine += ch; - i++; - ch = styler.SafeGetCharAt(start + i, '\n'); - } - return restOfLine; -} - -static bool IsStreamCommentStyle(int style) { - return style == SCE_C_COMMENT || - style == SCE_C_COMMENTDOC || - style == SCE_C_COMMENTDOCKEYWORD || - style == SCE_C_COMMENTDOCKEYWORDERROR; -} - -static std::vector Tokenize(const std::string &s) { - // Break into space separated tokens - std::string word; - std::vector tokens; - for (const char *cp = s.c_str(); *cp; cp++) { - if ((*cp == ' ') || (*cp == '\t')) { - if (!word.empty()) { - tokens.push_back(word); - word = ""; - } - } else { - word += *cp; - } - } - if (!word.empty()) { - tokens.push_back(word); - } - return tokens; -} - -struct PPDefinition { - int line; - std::string key; - std::string value; - PPDefinition(int line_, const std::string &key_, const std::string &value_) : - line(line_), key(key_), value(value_) { - } -}; - -class LinePPState { - int state; - int ifTaken; - int level; - bool ValidLevel() const { - return level >= 0 && level < 32; - } - int maskLevel() const { - return 1 << level; - } -public: - LinePPState() : state(0), ifTaken(0), level(-1) { - } - bool IsInactive() const { - return state != 0; - } - bool CurrentIfTaken() { - return (ifTaken & maskLevel()) != 0; - } - void StartSection(bool on) { - level++; - if (ValidLevel()) { - if (on) { - state &= ~maskLevel(); - ifTaken |= maskLevel(); - } else { - state |= maskLevel(); - ifTaken &= ~maskLevel(); - } - } - } - void EndSection() { - if (ValidLevel()) { - state &= ~maskLevel(); - ifTaken &= ~maskLevel(); - } - level--; - } - void InvertCurrentLevel() { - if (ValidLevel()) { - state ^= maskLevel(); - ifTaken |= maskLevel(); - } - } -}; - -// Hold the preprocessor state for each line seen. -// Currently one entry per line but could become sparse with just one entry per preprocessor line. -class PPStates { - std::vector vlls; -public: - LinePPState ForLine(int line) { - if ((line > 0) && (vlls.size() > static_cast(line))) { - return vlls[line]; - } else { - return LinePPState(); - } - } - void Add(int line, LinePPState lls) { - vlls.resize(line+1); - vlls[line] = lls; - } -}; - -// An individual named option for use in an OptionSet - -// Options used for LexerCPP -struct OptionsCPP { - bool stylingWithinPreprocessor; - bool identifiersAllowDollars; - bool trackPreprocessor; - bool updatePreprocessor; - bool triplequotedStrings; - bool hashquotedStrings; - bool fold; - bool foldSyntaxBased; - bool foldComment; - bool foldCommentMultiline; - bool foldCommentExplicit; - std::string foldExplicitStart; - std::string foldExplicitEnd; - bool foldExplicitAnywhere; - bool foldPreprocessor; - bool foldCompact; - bool foldAtElse; - OptionsCPP() { - stylingWithinPreprocessor = false; - identifiersAllowDollars = true; - trackPreprocessor = true; - updatePreprocessor = true; - triplequotedStrings = false; - hashquotedStrings = false; - fold = false; - foldSyntaxBased = true; - foldComment = false; - foldCommentMultiline = true; - foldCommentExplicit = true; - foldExplicitStart = ""; - foldExplicitEnd = ""; - foldExplicitAnywhere = false; - foldPreprocessor = false; - foldCompact = false; - foldAtElse = false; - } -}; - -static const char *const cppWordLists[] = { - "Primary keywords and identifiers", - "Secondary keywords and identifiers", - "Documentation comment keywords", - "Global classes and typedefs", - "Preprocessor definitions", - 0, -}; - -struct OptionSetCPP : public OptionSet { - OptionSetCPP() { - DefineProperty("styling.within.preprocessor", &OptionsCPP::stylingWithinPreprocessor, - "For C++ code, determines whether all preprocessor code is styled in the " - "preprocessor style (0, the default) or only from the initial # to the end " - "of the command word(1)."); - - DefineProperty("lexer.cpp.allow.dollars", &OptionsCPP::identifiersAllowDollars, - "Set to 0 to disallow the '$' character in identifiers with the cpp lexer."); - - DefineProperty("lexer.cpp.track.preprocessor", &OptionsCPP::trackPreprocessor, - "Set to 1 to interpret #if/#else/#endif to grey out code that is not active."); - - DefineProperty("lexer.cpp.update.preprocessor", &OptionsCPP::updatePreprocessor, - "Set to 1 to update preprocessor definitions when #define found."); - - DefineProperty("lexer.cpp.triplequoted.strings", &OptionsCPP::triplequotedStrings, - "Set to 1 to enable highlighting of triple-quoted strings."); - - DefineProperty("lexer.cpp.hashquoted.strings", &OptionsCPP::hashquotedStrings, - "Set to 1 to enable highlighting of hash-quoted strings."); - - DefineProperty("fold", &OptionsCPP::fold); - - DefineProperty("fold.cpp.syntax.based", &OptionsCPP::foldSyntaxBased, - "Set this property to 0 to disable syntax based folding."); - - DefineProperty("fold.comment", &OptionsCPP::foldComment, - "This option enables folding multi-line comments and explicit fold points when using the C++ lexer. " - "Explicit fold points allows adding extra folding by placing a //{ comment at the start and a //} " - "at the end of a section that should fold."); - - DefineProperty("fold.cpp.comment.multiline", &OptionsCPP::foldCommentMultiline, - "Set this property to 0 to disable folding multi-line comments when fold.comment=1."); - - DefineProperty("fold.cpp.comment.explicit", &OptionsCPP::foldCommentExplicit, - "Set this property to 0 to disable folding explicit fold points when fold.comment=1."); - - DefineProperty("fold.cpp.explicit.start", &OptionsCPP::foldExplicitStart, - "The string to use for explicit fold start points, replacing the standard //{."); - - DefineProperty("fold.cpp.explicit.end", &OptionsCPP::foldExplicitEnd, - "The string to use for explicit fold end points, replacing the standard //}."); - - DefineProperty("fold.cpp.explicit.anywhere", &OptionsCPP::foldExplicitAnywhere, - "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); - - DefineProperty("fold.preprocessor", &OptionsCPP::foldPreprocessor, - "This option enables folding preprocessor directives when using the C++ lexer. " - "Includes C#'s explicit #region and #endregion folding directives."); - - DefineProperty("fold.compact", &OptionsCPP::foldCompact); - - DefineProperty("fold.at.else", &OptionsCPP::foldAtElse, - "This option enables C++ folding on a \"} else {\" line of an if statement."); - - DefineWordListSets(cppWordLists); - } -}; - -class LexerCPP : public ILexer { - bool caseSensitive; - CharacterSet setWord; - CharacterSet setNegationOp; - CharacterSet setArithmethicOp; - CharacterSet setRelOp; - CharacterSet setLogicalOp; - PPStates vlls; - std::vector ppDefineHistory; - WordList keywords; - WordList keywords2; - WordList keywords3; - WordList keywords4; - WordList ppDefinitions; - std::map preprocessorDefinitionsStart; - OptionsCPP options; - OptionSetCPP osCPP; - SparseState rawStringTerminators; - enum { activeFlag = 0x40 }; -public: - LexerCPP(bool caseSensitive_) : - caseSensitive(caseSensitive_), - setWord(CharacterSet::setAlphaNum, "._", 0x80, true), - setNegationOp(CharacterSet::setNone, "!"), - setArithmethicOp(CharacterSet::setNone, "+-/*%"), - setRelOp(CharacterSet::setNone, "=!<>"), - setLogicalOp(CharacterSet::setNone, "|&") { - } - ~LexerCPP() { - } - void SCI_METHOD Release() { - delete this; - } - int SCI_METHOD Version() const { - return lvOriginal; - } - const char * SCI_METHOD PropertyNames() { - return osCPP.PropertyNames(); - } - int SCI_METHOD PropertyType(const char *name) { - return osCPP.PropertyType(name); - } - const char * SCI_METHOD DescribeProperty(const char *name) { - return osCPP.DescribeProperty(name); - } - int SCI_METHOD PropertySet(const char *key, const char *val); - const char * SCI_METHOD DescribeWordListSets() { - return osCPP.DescribeWordListSets(); - } - int SCI_METHOD WordListSet(int n, const char *wl); - void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); - void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); - - void * SCI_METHOD PrivateCall(int, void *) { - return 0; - } - - static ILexer *LexerFactoryCPP() { - return new LexerCPP(true); - } - static ILexer *LexerFactoryCPPInsensitive() { - return new LexerCPP(false); - } - static int MaskActive(int style) { - return style & ~activeFlag; - } - void EvaluateTokens(std::vector &tokens); - bool EvaluateExpression(const std::string &expr, const std::map &preprocessorDefinitions); -}; - -int SCI_METHOD LexerCPP::PropertySet(const char *key, const char *val) { - if (osCPP.PropertySet(&options, key, val)) { - return 0; - } - return -1; -} - -int SCI_METHOD LexerCPP::WordListSet(int n, const char *wl) { - WordList *wordListN = 0; - switch (n) { - case 0: - wordListN = &keywords; - break; - case 1: - wordListN = &keywords2; - break; - case 2: - wordListN = &keywords3; - break; - case 3: - wordListN = &keywords4; - break; - case 4: - wordListN = &ppDefinitions; - break; - } - int firstModification = -1; - if (wordListN) { - WordList wlNew; - wlNew.Set(wl); - if (*wordListN != wlNew) { - wordListN->Set(wl); - firstModification = 0; - if (n == 4) { - // Rebuild preprocessorDefinitions - preprocessorDefinitionsStart.clear(); - for (int nDefinition = 0; nDefinition < ppDefinitions.len; nDefinition++) { - char *cpDefinition = ppDefinitions.words[nDefinition]; - char *cpEquals = strchr(cpDefinition, '='); - if (cpEquals) { - std::string name(cpDefinition, cpEquals - cpDefinition); - std::string val(cpEquals+1); - preprocessorDefinitionsStart[name] = val; - } else { - std::string name(cpDefinition); - std::string val("1"); - preprocessorDefinitionsStart[name] = val; - } - } - } - } - } - return firstModification; -} - -// Functor used to truncate history -struct After { - int line; - After(int line_) : line(line_) {} - bool operator()(PPDefinition &p) const { - return p.line > line; - } -}; - -void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { - LexAccessor styler(pAccess); - - CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-"); - CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-"); - - CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); - - CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - - if (options.identifiersAllowDollars) { - setWordStart.Add('$'); - setWord.Add('$'); - } - - int chPrevNonWhite = ' '; - int visibleChars = 0; - bool lastWordWasUUID = false; - int styleBeforeDCKeyword = SCE_C_DEFAULT; - bool continuationLine = false; - bool isIncludePreprocessor = false; - - int lineCurrent = styler.GetLine(startPos); - if ((initStyle == SCE_C_PREPROCESSOR) || - (initStyle == SCE_C_COMMENTLINE) || - (initStyle == SCE_C_COMMENTLINEDOC)) { - // Set continuationLine if last character of previous line is '\' - if (lineCurrent > 0) { - int chBack = styler.SafeGetCharAt(startPos-1, 0); - int chBack2 = styler.SafeGetCharAt(startPos-2, 0); - int lineEndChar = '!'; - if (chBack2 == '\r' && chBack == '\n') { - lineEndChar = styler.SafeGetCharAt(startPos-3, 0); - } else if (chBack == '\n' || chBack == '\r') { - lineEndChar = chBack2; - } - continuationLine = lineEndChar == '\\'; - } - } - - // look back to set chPrevNonWhite properly for better regex colouring - if (startPos > 0) { - int back = startPos; - while (--back && IsSpaceEquiv(styler.StyleAt(back))) - ; - if (styler.StyleAt(back) == SCE_C_OPERATOR) { - chPrevNonWhite = styler.SafeGetCharAt(back); - } - } - - StyleContext sc(startPos, length, initStyle, styler, 0x7f); - LinePPState preproc = vlls.ForLine(lineCurrent); - - bool definitionsChanged = false; - - // Truncate ppDefineHistory before current line - - if (!options.updatePreprocessor) - ppDefineHistory.clear(); - - std::vector::iterator itInvalid = std::find_if(ppDefineHistory.begin(), ppDefineHistory.end(), After(lineCurrent-1)); - if (itInvalid != ppDefineHistory.end()) { - ppDefineHistory.erase(itInvalid, ppDefineHistory.end()); - definitionsChanged = true; - } - - std::map preprocessorDefinitions = preprocessorDefinitionsStart; - for (std::vector::iterator itDef = ppDefineHistory.begin(); itDef != ppDefineHistory.end(); ++itDef) { - preprocessorDefinitions[itDef->key] = itDef->value; - } - - std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1); - SparseState rawSTNew(lineCurrent); - - int activitySet = preproc.IsInactive() ? activeFlag : 0; - - for (; sc.More(); sc.Forward()) { - - if (sc.atLineStart) { - if ((sc.state == SCE_C_STRING) || (sc.state == SCE_C_CHARACTER)) { - // Prevent SCE_C_STRINGEOL from leaking back to previous line which - // ends with a line continuation by locking in the state upto this position. - sc.SetState(sc.state); - } - // Reset states to begining of colourise so no surprises - // if different sets of lines lexed. - visibleChars = 0; - lastWordWasUUID = false; - isIncludePreprocessor = false; - if (preproc.IsInactive()) { - activitySet = activeFlag; - sc.SetState(sc.state | activitySet); - } - if (activitySet) { - if (sc.ch == '#') { - if (sc.Match("#else") || sc.Match("#end") || sc.Match("#if")) { - //activitySet = 0; - } - } - } - } - - if (sc.atLineEnd) { - lineCurrent++; - vlls.Add(lineCurrent, preproc); - if (rawStringTerminator != "") { - rawSTNew.Set(lineCurrent-1, rawStringTerminator); - } - } - - // Handle line continuation generically. - if (sc.ch == '\\') { - if (sc.chNext == '\n' || sc.chNext == '\r') { - lineCurrent++; - vlls.Add(lineCurrent, preproc); - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - sc.Forward(); - } - continuationLine = true; - continue; - } - } - - const bool atLineEndBeforeSwitch = sc.atLineEnd; - - // Determine if the current state should terminate. - switch (MaskActive(sc.state)) { - case SCE_C_OPERATOR: - sc.SetState(SCE_C_DEFAULT|activitySet); - break; - case SCE_C_NUMBER: - // We accept almost anything because of hex. and number suffixes - if (!(setWord.Contains(sc.ch) || ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { - sc.SetState(SCE_C_DEFAULT|activitySet); - } - break; - case SCE_C_IDENTIFIER: - if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { - char s[1000]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - if (keywords.InList(s)) { - lastWordWasUUID = strcmp(s, "uuid") == 0; - sc.ChangeState(SCE_C_WORD|activitySet); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_C_WORD2|activitySet); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_C_GLOBALCLASS|activitySet); - } - const bool literalString = sc.ch == '\"'; - if (literalString || sc.ch == '\'') { - size_t lenS = strlen(s); - const bool raw = literalString && sc.chPrev == 'R'; - if (raw) - s[lenS--] = '\0'; - bool valid = - (lenS == 0) || - ((lenS == 1) && ((s[0] == 'L') || (s[0] == 'u') || (s[0] == 'U'))) || - ((lenS == 2) && literalString && (s[0] == 'u') && (s[1] == '8')); - if (valid) { - if (literalString) - sc.ChangeState((raw ? SCE_C_STRINGRAW : SCE_C_STRING)|activitySet); - else - sc.ChangeState(SCE_C_CHARACTER|activitySet); - } - } - sc.SetState(SCE_C_DEFAULT|activitySet); - } - break; - case SCE_C_PREPROCESSOR: - if (sc.atLineStart && !continuationLine) { - sc.SetState(SCE_C_DEFAULT|activitySet); - } else if (options.stylingWithinPreprocessor) { - if (IsASpace(sc.ch)) { - sc.SetState(SCE_C_DEFAULT|activitySet); - } - } else { - if (sc.Match('/', '*') || sc.Match('/', '/')) { - sc.SetState(SCE_C_DEFAULT|activitySet); - } - } - break; - case SCE_C_COMMENT: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT|activitySet); - } - break; - case SCE_C_COMMENTDOC: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT|activitySet); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_C_COMMENTDOC; - sc.SetState(SCE_C_COMMENTDOCKEYWORD|activitySet); - } - } - break; - case SCE_C_COMMENTLINE: - if (sc.atLineStart && !continuationLine) { - sc.SetState(SCE_C_DEFAULT|activitySet); - } - break; - case SCE_C_COMMENTLINEDOC: - if (sc.atLineStart && !continuationLine) { - sc.SetState(SCE_C_DEFAULT|activitySet); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC; - sc.SetState(SCE_C_COMMENTDOCKEYWORD|activitySet); - } - } - break; - case SCE_C_COMMENTDOCKEYWORD: - if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) { - sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); - sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT|activitySet); - } else if (!setDoxygen.Contains(sc.ch)) { - char s[100]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { - sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR|activitySet); - } - sc.SetState(styleBeforeDCKeyword); - } - break; - case SCE_C_STRING: - if (sc.atLineEnd) { - sc.ChangeState(SCE_C_STRINGEOL|activitySet); - } else if (isIncludePreprocessor) { - if (sc.ch == '>') { - sc.ForwardSetState(SCE_C_DEFAULT|activitySet); - isIncludePreprocessor = false; - } - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_C_DEFAULT|activitySet); - } - break; - case SCE_C_HASHQUOTEDSTRING: - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_C_DEFAULT|activitySet); - } - break; - case SCE_C_STRINGRAW: - if (sc.Match(rawStringTerminator.c_str())) { - for (size_t termPos=rawStringTerminator.size(); termPos; termPos--) - sc.Forward(); - sc.SetState(SCE_C_DEFAULT|activitySet); - rawStringTerminator = ""; - } - break; - case SCE_C_CHARACTER: - if (sc.atLineEnd) { - sc.ChangeState(SCE_C_STRINGEOL|activitySet); - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_C_DEFAULT|activitySet); - } - break; - case SCE_C_REGEX: - if (sc.atLineStart) { - sc.SetState(SCE_C_DEFAULT|activitySet); - } else if (sc.ch == '/') { - sc.Forward(); - while ((sc.ch < 0x80) && islower(sc.ch)) - sc.Forward(); // gobble regex flags - sc.SetState(SCE_C_DEFAULT|activitySet); - } else if (sc.ch == '\\') { - // Gobble up the quoted character - if (sc.chNext == '\\' || sc.chNext == '/') { - sc.Forward(); - } - } - break; - case SCE_C_STRINGEOL: - if (sc.atLineStart) { - sc.SetState(SCE_C_DEFAULT|activitySet); - } - break; - case SCE_C_VERBATIM: - if (sc.ch == '\"') { - if (sc.chNext == '\"') { - sc.Forward(); - } else { - sc.ForwardSetState(SCE_C_DEFAULT|activitySet); - } - } - break; - case SCE_C_TRIPLEVERBATIM: - if (sc.Match("\"\"\"")) { - while (sc.Match('"')) { - sc.Forward(); - } - sc.SetState(SCE_C_DEFAULT|activitySet); - } - break; - case SCE_C_UUID: - if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { - sc.SetState(SCE_C_DEFAULT|activitySet); - } - } - - if (sc.atLineEnd && !atLineEndBeforeSwitch) { - // State exit processing consumed characters up to end of line. - lineCurrent++; - vlls.Add(lineCurrent, preproc); - } - - // Determine if a new state should be entered. - if (MaskActive(sc.state) == SCE_C_DEFAULT) { - if (sc.Match('@', '\"')) { - sc.SetState(SCE_C_VERBATIM|activitySet); - sc.Forward(); - } else if (options.triplequotedStrings && sc.Match("\"\"\"")) { - sc.SetState(SCE_C_TRIPLEVERBATIM|activitySet); - sc.Forward(2); - } else if (options.hashquotedStrings && sc.Match('#', '\"')) { - sc.SetState(SCE_C_HASHQUOTEDSTRING|activitySet); - sc.Forward(); - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - if (lastWordWasUUID) { - sc.SetState(SCE_C_UUID|activitySet); - lastWordWasUUID = false; - } else { - sc.SetState(SCE_C_NUMBER|activitySet); - } - } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { - if (lastWordWasUUID) { - sc.SetState(SCE_C_UUID|activitySet); - lastWordWasUUID = false; - } else { - sc.SetState(SCE_C_IDENTIFIER|activitySet); - } - } else if (sc.Match('/', '*')) { - if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style - sc.SetState(SCE_C_COMMENTDOC|activitySet); - } else { - sc.SetState(SCE_C_COMMENT|activitySet); - } - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('/', '/')) { - if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) - // Support of Qt/Doxygen doc. style - sc.SetState(SCE_C_COMMENTLINEDOC|activitySet); - else - sc.SetState(SCE_C_COMMENTLINE|activitySet); - } else if (sc.ch == '/' - && (setOKBeforeRE.Contains(chPrevNonWhite) - || followsReturnKeyword(sc, styler)) - && (!setCouldBePostOp.Contains(chPrevNonWhite) - || !FollowsPostfixOperator(sc, styler))) { - sc.SetState(SCE_C_REGEX|activitySet); // JavaScript's RegEx - } else if (sc.ch == '\"') { - if (sc.chPrev == 'R') { - styler.Flush(); - if (MaskActive(styler.StyleAt(sc.currentPos - 1)) == SCE_C_STRINGRAW) { - sc.SetState(SCE_C_STRINGRAW|activitySet); - rawStringTerminator = ")"; - for (int termPos = sc.currentPos + 1;; termPos++) { - char chTerminator = styler.SafeGetCharAt(termPos, '('); - if (chTerminator == '(') - break; - rawStringTerminator += chTerminator; - } - rawStringTerminator += '\"'; - } else { - sc.SetState(SCE_C_STRING|activitySet); - } - } else { - sc.SetState(SCE_C_STRING|activitySet); - } - isIncludePreprocessor = false; // ensure that '>' won't end the string - } else if (isIncludePreprocessor && sc.ch == '<') { - sc.SetState(SCE_C_STRING|activitySet); - } else if (sc.ch == '\'') { - sc.SetState(SCE_C_CHARACTER|activitySet); - } else if (sc.ch == '#' && visibleChars == 0) { - // Preprocessor commands are alone on their line - sc.SetState(SCE_C_PREPROCESSOR|activitySet); - // Skip whitespace between # and preprocessor word - do { - sc.Forward(); - } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); - if (sc.atLineEnd) { - sc.SetState(SCE_C_DEFAULT|activitySet); - } else if (sc.Match("include")) { - isIncludePreprocessor = true; - } else { - if (options.trackPreprocessor) { - if (sc.Match("ifdef") || sc.Match("ifndef")) { - bool isIfDef = sc.Match("ifdef"); - int i = isIfDef ? 5 : 6; - std::string restOfLine = GetRestOfLine(styler, sc.currentPos + i + 1, false); - bool foundDef = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end(); - preproc.StartSection(isIfDef == foundDef); - } else if (sc.Match("if")) { - std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 2, true); - bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions); - preproc.StartSection(ifGood); - } else if (sc.Match("else")) { - if (!preproc.CurrentIfTaken()) { - preproc.InvertCurrentLevel(); - activitySet = preproc.IsInactive() ? activeFlag : 0; - if (!activitySet) - sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); - } else if (!preproc.IsInactive()) { - preproc.InvertCurrentLevel(); - activitySet = preproc.IsInactive() ? activeFlag : 0; - if (!activitySet) - sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); - } - } else if (sc.Match("elif")) { - // Ensure only one chosen out of #if .. #elif .. #elif .. #else .. #endif - if (!preproc.CurrentIfTaken()) { - // Similar to #if - std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 2, true); - bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions); - if (ifGood) { - preproc.InvertCurrentLevel(); - activitySet = preproc.IsInactive() ? activeFlag : 0; - if (!activitySet) - sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); - } - } else if (!preproc.IsInactive()) { - preproc.InvertCurrentLevel(); - activitySet = preproc.IsInactive() ? activeFlag : 0; - if (!activitySet) - sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); - } - } else if (sc.Match("endif")) { - preproc.EndSection(); - activitySet = preproc.IsInactive() ? activeFlag : 0; - sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); - } else if (sc.Match("define")) { - if (options.updatePreprocessor && !preproc.IsInactive()) { - std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true); - if (restOfLine.find(")") == std::string::npos) { // Don't handle macros with arguments - std::vector tokens = Tokenize(restOfLine); - std::string key; - std::string value("1"); - if (tokens.size() >= 1) { - key = tokens[0]; - if (tokens.size() >= 2) { - value = tokens[1]; - } - preprocessorDefinitions[key] = value; - ppDefineHistory.push_back(PPDefinition(lineCurrent, key, value)); - definitionsChanged = true; - } - } - } - } - } - } - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_C_OPERATOR|activitySet); - } - } - - if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) { - chPrevNonWhite = sc.ch; - visibleChars++; - } - continuationLine = false; - } - const bool rawStringsChanged = rawStringTerminators.Merge(rawSTNew, lineCurrent); - if (definitionsChanged || rawStringsChanged) - styler.ChangeLexerState(startPos, startPos + length); - sc.Complete(); -} - -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment -// and to make it possible to fiddle the current level for "} else {". - -void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { - - if (!options.fold) - return; - - LexAccessor styler(pAccess); - - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelMinCurrent = levelCurrent; - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = MaskActive(styler.StyleAt(startPos)); - int style = MaskActive(initStyle); - const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = MaskActive(styler.StyleAt(i + 1)); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_C_COMMENTLINEDOC)) { - levelNext++; - } else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_C_COMMENTLINEDOC) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelNext--; - } - } - if (options.foldComment && options.foldCommentExplicit && ((style == SCE_C_COMMENTLINE) || options.foldExplicitAnywhere)) { - if (userDefinedFoldMarkers) { - if (styler.Match(i, options.foldExplicitStart.c_str())) { - levelNext++; - } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { - levelNext--; - } - } else { - if ((ch == '/') && (chNext == '/')) { - char chNext2 = styler.SafeGetCharAt(i + 2); - if (chNext2 == '{') { - levelNext++; - } else if (chNext2 == '}') { - levelNext--; - } - } - } - } - if (options.foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { - if (ch == '#') { - unsigned int j = i + 1; - while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { - j++; - } - if (styler.Match(j, "region") || styler.Match(j, "if")) { - levelNext++; - } else if (styler.Match(j, "end")) { - levelNext--; - } - } - } - if (options.foldSyntaxBased && (style == SCE_C_OPERATOR)) { - if (ch == '{') { - // Measure the minimum before a '{' to allow - // folding on "} else {" - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (ch == '}') { - levelNext--; - } - } - if (!IsASpace(ch)) - visibleChars++; - if (atEOL || (i == endPos-1)) { - int levelUse = levelCurrent; - if (options.foldSyntaxBased && options.foldAtElse) { - levelUse = levelMinCurrent; - } - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && options.foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - levelMinCurrent = levelCurrent; - if (atEOL && (i == static_cast(styler.Length()-1))) { - // There is an empty line at end of file so give it same level and empty - styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); - } - visibleChars = 0; - } - } -} - -void LexerCPP::EvaluateTokens(std::vector &tokens) { - - // Evaluate defined() statements to either 0 or 1 - for (size_t i=0; (i+2)) - tokens.erase(tokens.begin() + i + 1, tokens.begin() + i + 4); - val = "1"; - } - tokens[i] = val; - } else { - i++; - } - } - - // Find bracketed subexpressions and recurse on them - std::vector::iterator itBracket = std::find(tokens.begin(), tokens.end(), "("); - std::vector::iterator itEndBracket = std::find(tokens.begin(), tokens.end(), ")"); - while ((itBracket != tokens.end()) && (itEndBracket != tokens.end()) && (itEndBracket > itBracket)) { - std::vector inBracket(itBracket + 1, itEndBracket); - EvaluateTokens(inBracket); - - // The insertion is done before the removal because there were failures with the opposite approach - tokens.insert(itBracket, inBracket.begin(), inBracket.end()); - itBracket = std::find(tokens.begin(), tokens.end(), "("); - itEndBracket = std::find(tokens.begin(), tokens.end(), ")"); - tokens.erase(itBracket, itEndBracket + 1); - - itBracket = std::find(tokens.begin(), tokens.end(), "("); - itEndBracket = std::find(tokens.begin(), tokens.end(), ")"); - } - - // Evaluate logical negations - for (size_t j=0; (j+1)::iterator itInsert = - tokens.erase(tokens.begin() + j, tokens.begin() + j + 2); - tokens.insert(itInsert, isTrue ? "1" : "0"); - } else { - j++; - } - } - - // Evaluate expressions in precedence order - enum precedence { precArithmetic, precRelative, precLogical }; - for (int prec=precArithmetic; prec <= precLogical; prec++) { - // Looking at 3 tokens at a time so end at 2 before end - for (size_t k=0; (k+2)") - result = valA > valB; - else if (tokens[k+1] == ">=") - result = valA >= valB; - else if (tokens[k+1] == "==") - result = valA == valB; - else if (tokens[k+1] == "!=") - result = valA != valB; - else if (tokens[k+1] == "||") - result = valA || valB; - else if (tokens[k+1] == "&&") - result = valA && valB; - char sResult[30]; - sprintf(sResult, "%d", result); - std::vector::iterator itInsert = - tokens.erase(tokens.begin() + k, tokens.begin() + k + 3); - tokens.insert(itInsert, sResult); - } else { - k++; - } - } - } -} - -bool LexerCPP::EvaluateExpression(const std::string &expr, const std::map &preprocessorDefinitions) { - // Break into tokens, replacing with definitions - std::string word; - std::vector tokens; - const char *cp = expr.c_str(); - for (;;) { - if (setWord.Contains(*cp)) { - word += *cp; - } else { - std::map::const_iterator it = preprocessorDefinitions.find(word); - if (it != preprocessorDefinitions.end()) { - tokens.push_back(it->second); - } else if (!word.empty() && ((word[0] >= '0' && word[0] <= '9') || (word == "defined"))) { - tokens.push_back(word); - } - word = ""; - if (!*cp) { - break; - } - if ((*cp != ' ') && (*cp != '\t')) { - std::string op(cp, 1); - if (setRelOp.Contains(*cp)) { - if (setRelOp.Contains(cp[1])) { - op += cp[1]; - cp++; - } - } else if (setLogicalOp.Contains(*cp)) { - if (setLogicalOp.Contains(cp[1])) { - op += cp[1]; - cp++; - } - } - tokens.push_back(op); - } - } - cp++; - } - - EvaluateTokens(tokens); - - // "0" or "" -> false else true - bool isFalse = tokens.empty() || - ((tokens.size() == 1) && ((tokens[0] == "") || tokens[0] == "0")); - return !isFalse; -} - -LexerModule lmCPP(SCLEX_CPP, LexerCPP::LexerFactoryCPP, "cpp", cppWordLists); -LexerModule lmCPPNoCase(SCLEX_CPPNOCASE, LexerCPP::LexerFactoryCPPInsensitive, "cppnocase", cppWordLists); +// Scintilla source code edit control +/** @file LexCPP.cxx + ** Lexer for C++, C, Java, and JavaScript. + ** Further folding features and configuration properties added by "Udo Lechner" + **/ +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "SparseState.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static bool IsSpaceEquiv(int state) { + return (state <= SCE_C_COMMENTDOC) || + // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE + (state == SCE_C_COMMENTLINEDOC) || (state == SCE_C_COMMENTDOCKEYWORD) || + (state == SCE_C_COMMENTDOCKEYWORDERROR); +} + +// Preconditions: sc.currentPos points to a character after '+' or '-'. +// The test for pos reaching 0 should be redundant, +// and is in only for safety measures. +// Limitation: this code will give the incorrect answer for code like +// a = b+++/ptn/... +// Putting a space between the '++' post-inc operator and the '+' binary op +// fixes this, and is highly recommended for readability anyway. +static bool FollowsPostfixOperator(StyleContext &sc, LexAccessor &styler) { + int pos = (int) sc.currentPos; + while (--pos > 0) { + char ch = styler[pos]; + if (ch == '+' || ch == '-') { + return styler[pos - 1] == ch; + } + } + return false; +} + +static bool followsReturnKeyword(StyleContext &sc, LexAccessor &styler) { + // Don't look at styles, so no need to flush. + int pos = (int) sc.currentPos; + int currentLine = styler.GetLine(pos); + int lineStartPos = styler.LineStart(currentLine); + char ch; + while (--pos > lineStartPos) { + ch = styler.SafeGetCharAt(pos); + if (ch != ' ' && ch != '\t') { + break; + } + } + const char *retBack = "nruter"; + const char *s = retBack; + while (*s + && pos >= lineStartPos + && styler.SafeGetCharAt(pos) == *s) { + s++; + pos--; + } + return !*s; +} + +static std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace) { + std::string restOfLine; + int i =0; + char ch = styler.SafeGetCharAt(start, '\n'); + while ((ch != '\r') && (ch != '\n')) { + if (allowSpace || (ch != ' ')) + restOfLine += ch; + i++; + ch = styler.SafeGetCharAt(start + i, '\n'); + } + return restOfLine; +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_C_COMMENT || + style == SCE_C_COMMENTDOC || + style == SCE_C_COMMENTDOCKEYWORD || + style == SCE_C_COMMENTDOCKEYWORDERROR; +} + +static std::vector Tokenize(const std::string &s) { + // Break into space separated tokens + std::string word; + std::vector tokens; + for (const char *cp = s.c_str(); *cp; cp++) { + if ((*cp == ' ') || (*cp == '\t')) { + if (!word.empty()) { + tokens.push_back(word); + word = ""; + } + } else { + word += *cp; + } + } + if (!word.empty()) { + tokens.push_back(word); + } + return tokens; +} + +struct PPDefinition { + int line; + std::string key; + std::string value; + PPDefinition(int line_, const std::string &key_, const std::string &value_) : + line(line_), key(key_), value(value_) { + } +}; + +class LinePPState { + int state; + int ifTaken; + int level; + bool ValidLevel() const { + return level >= 0 && level < 32; + } + int maskLevel() const { + return 1 << level; + } +public: + LinePPState() : state(0), ifTaken(0), level(-1) { + } + bool IsInactive() const { + return state != 0; + } + bool CurrentIfTaken() { + return (ifTaken & maskLevel()) != 0; + } + void StartSection(bool on) { + level++; + if (ValidLevel()) { + if (on) { + state &= ~maskLevel(); + ifTaken |= maskLevel(); + } else { + state |= maskLevel(); + ifTaken &= ~maskLevel(); + } + } + } + void EndSection() { + if (ValidLevel()) { + state &= ~maskLevel(); + ifTaken &= ~maskLevel(); + } + level--; + } + void InvertCurrentLevel() { + if (ValidLevel()) { + state ^= maskLevel(); + ifTaken |= maskLevel(); + } + } +}; + +// Hold the preprocessor state for each line seen. +// Currently one entry per line but could become sparse with just one entry per preprocessor line. +class PPStates { + std::vector vlls; +public: + LinePPState ForLine(int line) { + if ((line > 0) && (vlls.size() > static_cast(line))) { + return vlls[line]; + } else { + return LinePPState(); + } + } + void Add(int line, LinePPState lls) { + vlls.resize(line+1); + vlls[line] = lls; + } +}; + +// An individual named option for use in an OptionSet + +// Options used for LexerCPP +struct OptionsCPP { + bool stylingWithinPreprocessor; + bool identifiersAllowDollars; + bool trackPreprocessor; + bool updatePreprocessor; + bool triplequotedStrings; + bool hashquotedStrings; + bool fold; + bool foldSyntaxBased; + bool foldComment; + bool foldCommentMultiline; + bool foldCommentExplicit; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere; + bool foldPreprocessor; + bool foldCompact; + bool foldAtElse; + OptionsCPP() { + stylingWithinPreprocessor = false; + identifiersAllowDollars = true; + trackPreprocessor = true; + updatePreprocessor = true; + triplequotedStrings = false; + hashquotedStrings = false; + fold = false; + foldSyntaxBased = true; + foldComment = false; + foldCommentMultiline = true; + foldCommentExplicit = true; + foldExplicitStart = ""; + foldExplicitEnd = ""; + foldExplicitAnywhere = false; + foldPreprocessor = false; + foldCompact = false; + foldAtElse = false; + } +}; + +static const char *const cppWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + "Documentation comment keywords", + "Global classes and typedefs", + "Preprocessor definitions", + 0, +}; + +struct OptionSetCPP : public OptionSet { + OptionSetCPP() { + DefineProperty("styling.within.preprocessor", &OptionsCPP::stylingWithinPreprocessor, + "For C++ code, determines whether all preprocessor code is styled in the " + "preprocessor style (0, the default) or only from the initial # to the end " + "of the command word(1)."); + + DefineProperty("lexer.cpp.allow.dollars", &OptionsCPP::identifiersAllowDollars, + "Set to 0 to disallow the '$' character in identifiers with the cpp lexer."); + + DefineProperty("lexer.cpp.track.preprocessor", &OptionsCPP::trackPreprocessor, + "Set to 1 to interpret #if/#else/#endif to grey out code that is not active."); + + DefineProperty("lexer.cpp.update.preprocessor", &OptionsCPP::updatePreprocessor, + "Set to 1 to update preprocessor definitions when #define found."); + + DefineProperty("lexer.cpp.triplequoted.strings", &OptionsCPP::triplequotedStrings, + "Set to 1 to enable highlighting of triple-quoted strings."); + + DefineProperty("lexer.cpp.hashquoted.strings", &OptionsCPP::hashquotedStrings, + "Set to 1 to enable highlighting of hash-quoted strings."); + + DefineProperty("fold", &OptionsCPP::fold); + + DefineProperty("fold.cpp.syntax.based", &OptionsCPP::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("fold.comment", &OptionsCPP::foldComment, + "This option enables folding multi-line comments and explicit fold points when using the C++ lexer. " + "Explicit fold points allows adding extra folding by placing a //{ comment at the start and a //} " + "at the end of a section that should fold."); + + DefineProperty("fold.cpp.comment.multiline", &OptionsCPP::foldCommentMultiline, + "Set this property to 0 to disable folding multi-line comments when fold.comment=1."); + + DefineProperty("fold.cpp.comment.explicit", &OptionsCPP::foldCommentExplicit, + "Set this property to 0 to disable folding explicit fold points when fold.comment=1."); + + DefineProperty("fold.cpp.explicit.start", &OptionsCPP::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard //{."); + + DefineProperty("fold.cpp.explicit.end", &OptionsCPP::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard //}."); + + DefineProperty("fold.cpp.explicit.anywhere", &OptionsCPP::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + + DefineProperty("fold.preprocessor", &OptionsCPP::foldPreprocessor, + "This option enables folding preprocessor directives when using the C++ lexer. " + "Includes C#'s explicit #region and #endregion folding directives."); + + DefineProperty("fold.compact", &OptionsCPP::foldCompact); + + DefineProperty("fold.at.else", &OptionsCPP::foldAtElse, + "This option enables C++ folding on a \"} else {\" line of an if statement."); + + DefineWordListSets(cppWordLists); + } +}; + +class LexerCPP : public ILexer { + bool caseSensitive; + CharacterSet setWord; + CharacterSet setNegationOp; + CharacterSet setArithmethicOp; + CharacterSet setRelOp; + CharacterSet setLogicalOp; + PPStates vlls; + std::vector ppDefineHistory; + WordList keywords; + WordList keywords2; + WordList keywords3; + WordList keywords4; + WordList ppDefinitions; + std::map preprocessorDefinitionsStart; + OptionsCPP options; + OptionSetCPP osCPP; + SparseState rawStringTerminators; + enum { activeFlag = 0x40 }; +public: + LexerCPP(bool caseSensitive_) : + caseSensitive(caseSensitive_), + setWord(CharacterSet::setAlphaNum, "._", 0x80, true), + setNegationOp(CharacterSet::setNone, "!"), + setArithmethicOp(CharacterSet::setNone, "+-/*%"), + setRelOp(CharacterSet::setNone, "=!<>"), + setLogicalOp(CharacterSet::setNone, "|&") { + } + ~LexerCPP() { + } + void SCI_METHOD Release() { + delete this; + } + int SCI_METHOD Version() const { + return lvOriginal; + } + const char * SCI_METHOD PropertyNames() { + return osCPP.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) { + return osCPP.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) { + return osCPP.DescribeProperty(name); + } + int SCI_METHOD PropertySet(const char *key, const char *val); + const char * SCI_METHOD DescribeWordListSets() { + return osCPP.DescribeWordListSets(); + } + int SCI_METHOD WordListSet(int n, const char *wl); + void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + + void * SCI_METHOD PrivateCall(int, void *) { + return 0; + } + + static ILexer *LexerFactoryCPP() { + return new LexerCPP(true); + } + static ILexer *LexerFactoryCPPInsensitive() { + return new LexerCPP(false); + } + static int MaskActive(int style) { + return style & ~activeFlag; + } + void EvaluateTokens(std::vector &tokens); + bool EvaluateExpression(const std::string &expr, const std::map &preprocessorDefinitions); +}; + +int SCI_METHOD LexerCPP::PropertySet(const char *key, const char *val) { + if (osCPP.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +int SCI_METHOD LexerCPP::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywords; + break; + case 1: + wordListN = &keywords2; + break; + case 2: + wordListN = &keywords3; + break; + case 3: + wordListN = &keywords4; + break; + case 4: + wordListN = &ppDefinitions; + break; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + if (n == 4) { + // Rebuild preprocessorDefinitions + preprocessorDefinitionsStart.clear(); + for (int nDefinition = 0; nDefinition < ppDefinitions.len; nDefinition++) { + char *cpDefinition = ppDefinitions.words[nDefinition]; + char *cpEquals = strchr(cpDefinition, '='); + if (cpEquals) { + std::string name(cpDefinition, cpEquals - cpDefinition); + std::string val(cpEquals+1); + preprocessorDefinitionsStart[name] = val; + } else { + std::string name(cpDefinition); + std::string val("1"); + preprocessorDefinitionsStart[name] = val; + } + } + } + } + } + return firstModification; +} + +// Functor used to truncate history +struct After { + int line; + After(int line_) : line(line_) {} + bool operator()(PPDefinition &p) const { + return p.line > line; + } +}; + +void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + + CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-"); + CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-"); + + CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); + + CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + + if (options.identifiersAllowDollars) { + setWordStart.Add('$'); + setWord.Add('$'); + } + + int chPrevNonWhite = ' '; + int visibleChars = 0; + bool lastWordWasUUID = false; + int styleBeforeDCKeyword = SCE_C_DEFAULT; + bool continuationLine = false; + bool isIncludePreprocessor = false; + + int lineCurrent = styler.GetLine(startPos); + if ((initStyle == SCE_C_PREPROCESSOR) || + (initStyle == SCE_C_COMMENTLINE) || + (initStyle == SCE_C_COMMENTLINEDOC)) { + // Set continuationLine if last character of previous line is '\' + if (lineCurrent > 0) { + int chBack = styler.SafeGetCharAt(startPos-1, 0); + int chBack2 = styler.SafeGetCharAt(startPos-2, 0); + int lineEndChar = '!'; + if (chBack2 == '\r' && chBack == '\n') { + lineEndChar = styler.SafeGetCharAt(startPos-3, 0); + } else if (chBack == '\n' || chBack == '\r') { + lineEndChar = chBack2; + } + continuationLine = lineEndChar == '\\'; + } + } + + // look back to set chPrevNonWhite properly for better regex colouring + if (startPos > 0) { + int back = startPos; + while (--back && IsSpaceEquiv(styler.StyleAt(back))) + ; + if (styler.StyleAt(back) == SCE_C_OPERATOR) { + chPrevNonWhite = styler.SafeGetCharAt(back); + } + } + + StyleContext sc(startPos, length, initStyle, styler, 0x7f); + LinePPState preproc = vlls.ForLine(lineCurrent); + + bool definitionsChanged = false; + + // Truncate ppDefineHistory before current line + + if (!options.updatePreprocessor) + ppDefineHistory.clear(); + + std::vector::iterator itInvalid = std::find_if(ppDefineHistory.begin(), ppDefineHistory.end(), After(lineCurrent-1)); + if (itInvalid != ppDefineHistory.end()) { + ppDefineHistory.erase(itInvalid, ppDefineHistory.end()); + definitionsChanged = true; + } + + std::map preprocessorDefinitions = preprocessorDefinitionsStart; + for (std::vector::iterator itDef = ppDefineHistory.begin(); itDef != ppDefineHistory.end(); ++itDef) { + preprocessorDefinitions[itDef->key] = itDef->value; + } + + std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1); + SparseState rawSTNew(lineCurrent); + + int activitySet = preproc.IsInactive() ? activeFlag : 0; + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart) { + if ((sc.state == SCE_C_STRING) || (sc.state == SCE_C_CHARACTER)) { + // Prevent SCE_C_STRINGEOL from leaking back to previous line which + // ends with a line continuation by locking in the state upto this position. + sc.SetState(sc.state); + } + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + lastWordWasUUID = false; + isIncludePreprocessor = false; + if (preproc.IsInactive()) { + activitySet = activeFlag; + sc.SetState(sc.state | activitySet); + } + if (activitySet) { + if (sc.ch == '#') { + if (sc.Match("#else") || sc.Match("#end") || sc.Match("#if")) { + //activitySet = 0; + } + } + } + } + + if (sc.atLineEnd) { + lineCurrent++; + vlls.Add(lineCurrent, preproc); + if (rawStringTerminator != "") { + rawSTNew.Set(lineCurrent-1, rawStringTerminator); + } + } + + // Handle line continuation generically. + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + lineCurrent++; + vlls.Add(lineCurrent, preproc); + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continuationLine = true; + continue; + } + } + + const bool atLineEndBeforeSwitch = sc.atLineEnd; + + // Determine if the current state should terminate. + switch (MaskActive(sc.state)) { + case SCE_C_OPERATOR: + sc.SetState(SCE_C_DEFAULT|activitySet); + break; + case SCE_C_NUMBER: + // We accept almost anything because of hex. and number suffixes + if (!(setWord.Contains(sc.ch) || ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_IDENTIFIER: + if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { + char s[1000]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (keywords.InList(s)) { + lastWordWasUUID = strcmp(s, "uuid") == 0; + sc.ChangeState(SCE_C_WORD|activitySet); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_C_WORD2|activitySet); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_C_GLOBALCLASS|activitySet); + } + const bool literalString = sc.ch == '\"'; + if (literalString || sc.ch == '\'') { + size_t lenS = strlen(s); + const bool raw = literalString && sc.chPrev == 'R'; + if (raw) + s[lenS--] = '\0'; + bool valid = + (lenS == 0) || + ((lenS == 1) && ((s[0] == 'L') || (s[0] == 'u') || (s[0] == 'U'))) || + ((lenS == 2) && literalString && (s[0] == 'u') && (s[1] == '8')); + if (valid) { + if (literalString) + sc.ChangeState((raw ? SCE_C_STRINGRAW : SCE_C_STRING)|activitySet); + else + sc.ChangeState(SCE_C_CHARACTER|activitySet); + } + } + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_PREPROCESSOR: + if (sc.atLineStart && !continuationLine) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } else if (options.stylingWithinPreprocessor) { + if (IsASpace(sc.ch)) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + } else { + if (sc.Match('/', '*') || sc.Match('/', '/')) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + } + break; + case SCE_C_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_COMMENTDOC: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_C_COMMENTDOC; + sc.SetState(SCE_C_COMMENTDOCKEYWORD|activitySet); + } + } + break; + case SCE_C_COMMENTLINE: + if (sc.atLineStart && !continuationLine) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_COMMENTLINEDOC: + if (sc.atLineStart && !continuationLine) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC; + sc.SetState(SCE_C_COMMENTDOCKEYWORD|activitySet); + } + } + break; + case SCE_C_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } else if (!setDoxygen.Contains(sc.ch)) { + char s[100]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR|activitySet); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_C_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_C_STRINGEOL|activitySet); + } else if (isIncludePreprocessor) { + if (sc.ch == '>') { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + isIncludePreprocessor = false; + } + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_HASHQUOTEDSTRING: + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_STRINGRAW: + if (sc.Match(rawStringTerminator.c_str())) { + for (size_t termPos=rawStringTerminator.size(); termPos; termPos--) + sc.Forward(); + sc.SetState(SCE_C_DEFAULT|activitySet); + rawStringTerminator = ""; + } + break; + case SCE_C_CHARACTER: + if (sc.atLineEnd) { + sc.ChangeState(SCE_C_STRINGEOL|activitySet); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_REGEX: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } else if (sc.ch == '/') { + sc.Forward(); + while ((sc.ch < 0x80) && islower(sc.ch)) + sc.Forward(); // gobble regex flags + sc.SetState(SCE_C_DEFAULT|activitySet); + } else if (sc.ch == '\\') { + // Gobble up the quoted character + if (sc.chNext == '\\' || sc.chNext == '/') { + sc.Forward(); + } + } + break; + case SCE_C_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_VERBATIM: + if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } + } + break; + case SCE_C_TRIPLEVERBATIM: + if (sc.Match("\"\"\"")) { + while (sc.Match('"')) { + sc.Forward(); + } + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_UUID: + if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + } + + if (sc.atLineEnd && !atLineEndBeforeSwitch) { + // State exit processing consumed characters up to end of line. + lineCurrent++; + vlls.Add(lineCurrent, preproc); + } + + // Determine if a new state should be entered. + if (MaskActive(sc.state) == SCE_C_DEFAULT) { + if (sc.Match('@', '\"')) { + sc.SetState(SCE_C_VERBATIM|activitySet); + sc.Forward(); + } else if (options.triplequotedStrings && sc.Match("\"\"\"")) { + sc.SetState(SCE_C_TRIPLEVERBATIM|activitySet); + sc.Forward(2); + } else if (options.hashquotedStrings && sc.Match('#', '\"')) { + sc.SetState(SCE_C_HASHQUOTEDSTRING|activitySet); + sc.Forward(); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + if (lastWordWasUUID) { + sc.SetState(SCE_C_UUID|activitySet); + lastWordWasUUID = false; + } else { + sc.SetState(SCE_C_NUMBER|activitySet); + } + } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { + if (lastWordWasUUID) { + sc.SetState(SCE_C_UUID|activitySet); + lastWordWasUUID = false; + } else { + sc.SetState(SCE_C_IDENTIFIER|activitySet); + } + } else if (sc.Match('/', '*')) { + if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style + sc.SetState(SCE_C_COMMENTDOC|activitySet); + } else { + sc.SetState(SCE_C_COMMENT|activitySet); + } + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) + // Support of Qt/Doxygen doc. style + sc.SetState(SCE_C_COMMENTLINEDOC|activitySet); + else + sc.SetState(SCE_C_COMMENTLINE|activitySet); + } else if (sc.ch == '/' + && (setOKBeforeRE.Contains(chPrevNonWhite) + || followsReturnKeyword(sc, styler)) + && (!setCouldBePostOp.Contains(chPrevNonWhite) + || !FollowsPostfixOperator(sc, styler))) { + sc.SetState(SCE_C_REGEX|activitySet); // JavaScript's RegEx + } else if (sc.ch == '\"') { + if (sc.chPrev == 'R') { + styler.Flush(); + if (MaskActive(styler.StyleAt(sc.currentPos - 1)) == SCE_C_STRINGRAW) { + sc.SetState(SCE_C_STRINGRAW|activitySet); + rawStringTerminator = ")"; + for (int termPos = sc.currentPos + 1;; termPos++) { + char chTerminator = styler.SafeGetCharAt(termPos, '('); + if (chTerminator == '(') + break; + rawStringTerminator += chTerminator; + } + rawStringTerminator += '\"'; + } else { + sc.SetState(SCE_C_STRING|activitySet); + } + } else { + sc.SetState(SCE_C_STRING|activitySet); + } + isIncludePreprocessor = false; // ensure that '>' won't end the string + } else if (isIncludePreprocessor && sc.ch == '<') { + sc.SetState(SCE_C_STRING|activitySet); + } else if (sc.ch == '\'') { + sc.SetState(SCE_C_CHARACTER|activitySet); + } else if (sc.ch == '#' && visibleChars == 0) { + // Preprocessor commands are alone on their line + sc.SetState(SCE_C_PREPROCESSOR|activitySet); + // Skip whitespace between # and preprocessor word + do { + sc.Forward(); + } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); + if (sc.atLineEnd) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } else if (sc.Match("include")) { + isIncludePreprocessor = true; + } else { + if (options.trackPreprocessor) { + if (sc.Match("ifdef") || sc.Match("ifndef")) { + bool isIfDef = sc.Match("ifdef"); + int i = isIfDef ? 5 : 6; + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + i + 1, false); + bool foundDef = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end(); + preproc.StartSection(isIfDef == foundDef); + } else if (sc.Match("if")) { + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 2, true); + bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions); + preproc.StartSection(ifGood); + } else if (sc.Match("else")) { + if (!preproc.CurrentIfTaken()) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) + sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); + } else if (!preproc.IsInactive()) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) + sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); + } + } else if (sc.Match("elif")) { + // Ensure only one chosen out of #if .. #elif .. #elif .. #else .. #endif + if (!preproc.CurrentIfTaken()) { + // Similar to #if + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 2, true); + bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions); + if (ifGood) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) + sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); + } + } else if (!preproc.IsInactive()) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) + sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); + } + } else if (sc.Match("endif")) { + preproc.EndSection(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); + } else if (sc.Match("define")) { + if (options.updatePreprocessor && !preproc.IsInactive()) { + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true); + if (restOfLine.find(")") == std::string::npos) { // Don't handle macros with arguments + std::vector tokens = Tokenize(restOfLine); + std::string key; + std::string value("1"); + if (tokens.size() >= 1) { + key = tokens[0]; + if (tokens.size() >= 2) { + value = tokens[1]; + } + preprocessorDefinitions[key] = value; + ppDefineHistory.push_back(PPDefinition(lineCurrent, key, value)); + definitionsChanged = true; + } + } + } + } + } + } + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_C_OPERATOR|activitySet); + } + } + + if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) { + chPrevNonWhite = sc.ch; + visibleChars++; + } + continuationLine = false; + } + const bool rawStringsChanged = rawStringTerminators.Merge(rawSTNew, lineCurrent); + if (definitionsChanged || rawStringsChanged) + styler.ChangeLexerState(startPos, startPos + length); + sc.Complete(); +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". + +void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = MaskActive(styler.StyleAt(startPos)); + int style = MaskActive(initStyle); + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = MaskActive(styler.StyleAt(i + 1)); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_C_COMMENTLINEDOC)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_C_COMMENTLINEDOC) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (options.foldComment && options.foldCommentExplicit && ((style == SCE_C_COMMENTLINE) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { + levelNext++; + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + levelNext--; + } + } else { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelNext++; + } else if (chNext2 == '}') { + levelNext--; + } + } + } + } + if (options.foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { + if (ch == '#') { + unsigned int j = i + 1; + while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (styler.Match(j, "region") || styler.Match(j, "if")) { + levelNext++; + } else if (styler.Match(j, "end")) { + levelNext--; + } + } + } + if (options.foldSyntaxBased && (style == SCE_C_OPERATOR)) { + if (ch == '{') { + // Measure the minimum before a '{' to allow + // folding on "} else {" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + if (!IsASpace(ch)) + visibleChars++; + if (atEOL || (i == endPos-1)) { + int levelUse = levelCurrent; + if (options.foldSyntaxBased && options.foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && options.foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + if (atEOL && (i == static_cast(styler.Length()-1))) { + // There is an empty line at end of file so give it same level and empty + styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); + } + visibleChars = 0; + } + } +} + +void LexerCPP::EvaluateTokens(std::vector &tokens) { + + // Evaluate defined() statements to either 0 or 1 + for (size_t i=0; (i+2)) + tokens.erase(tokens.begin() + i + 1, tokens.begin() + i + 4); + val = "1"; + } + tokens[i] = val; + } else { + i++; + } + } + + // Find bracketed subexpressions and recurse on them + std::vector::iterator itBracket = std::find(tokens.begin(), tokens.end(), "("); + std::vector::iterator itEndBracket = std::find(tokens.begin(), tokens.end(), ")"); + while ((itBracket != tokens.end()) && (itEndBracket != tokens.end()) && (itEndBracket > itBracket)) { + std::vector inBracket(itBracket + 1, itEndBracket); + EvaluateTokens(inBracket); + + // The insertion is done before the removal because there were failures with the opposite approach + tokens.insert(itBracket, inBracket.begin(), inBracket.end()); + itBracket = std::find(tokens.begin(), tokens.end(), "("); + itEndBracket = std::find(tokens.begin(), tokens.end(), ")"); + tokens.erase(itBracket, itEndBracket + 1); + + itBracket = std::find(tokens.begin(), tokens.end(), "("); + itEndBracket = std::find(tokens.begin(), tokens.end(), ")"); + } + + // Evaluate logical negations + for (size_t j=0; (j+1)::iterator itInsert = + tokens.erase(tokens.begin() + j, tokens.begin() + j + 2); + tokens.insert(itInsert, isTrue ? "1" : "0"); + } else { + j++; + } + } + + // Evaluate expressions in precedence order + enum precedence { precArithmetic, precRelative, precLogical }; + for (int prec=precArithmetic; prec <= precLogical; prec++) { + // Looking at 3 tokens at a time so end at 2 before end + for (size_t k=0; (k+2)") + result = valA > valB; + else if (tokens[k+1] == ">=") + result = valA >= valB; + else if (tokens[k+1] == "==") + result = valA == valB; + else if (tokens[k+1] == "!=") + result = valA != valB; + else if (tokens[k+1] == "||") + result = valA || valB; + else if (tokens[k+1] == "&&") + result = valA && valB; + char sResult[30]; + sprintf(sResult, "%d", result); + std::vector::iterator itInsert = + tokens.erase(tokens.begin() + k, tokens.begin() + k + 3); + tokens.insert(itInsert, sResult); + } else { + k++; + } + } + } +} + +bool LexerCPP::EvaluateExpression(const std::string &expr, const std::map &preprocessorDefinitions) { + // Break into tokens, replacing with definitions + std::string word; + std::vector tokens; + const char *cp = expr.c_str(); + for (;;) { + if (setWord.Contains(*cp)) { + word += *cp; + } else { + std::map::const_iterator it = preprocessorDefinitions.find(word); + if (it != preprocessorDefinitions.end()) { + tokens.push_back(it->second); + } else if (!word.empty() && ((word[0] >= '0' && word[0] <= '9') || (word == "defined"))) { + tokens.push_back(word); + } + word = ""; + if (!*cp) { + break; + } + if ((*cp != ' ') && (*cp != '\t')) { + std::string op(cp, 1); + if (setRelOp.Contains(*cp)) { + if (setRelOp.Contains(cp[1])) { + op += cp[1]; + cp++; + } + } else if (setLogicalOp.Contains(*cp)) { + if (setLogicalOp.Contains(cp[1])) { + op += cp[1]; + cp++; + } + } + tokens.push_back(op); + } + } + cp++; + } + + EvaluateTokens(tokens); + + // "0" or "" -> false else true + bool isFalse = tokens.empty() || + ((tokens.size() == 1) && ((tokens[0] == "") || tokens[0] == "0")); + return !isFalse; +} + +LexerModule lmCPP(SCLEX_CPP, LexerCPP::LexerFactoryCPP, "cpp", cppWordLists); +LexerModule lmCPPNoCase(SCLEX_CPPNOCASE, LexerCPP::LexerFactoryCPPInsensitive, "cppnocase", cppWordLists); diff --git a/scintilla/lexers/LexCSS.cxx b/ThirdLibs/scintilla/lexers/LexCSS.cxx similarity index 96% rename from scintilla/lexers/LexCSS.cxx rename to ThirdLibs/scintilla/lexers/LexCSS.cxx index f5bd78fd..305a1dd7 100644 --- a/scintilla/lexers/LexCSS.cxx +++ b/ThirdLibs/scintilla/lexers/LexCSS.cxx @@ -1,554 +1,554 @@ -// Scintilla source code edit control -/** @file LexCSS.cxx - ** Lexer for Cascading Style Sheets - ** Written by Jakub Vrna - ** Improved by Philippe Lhoste (CSS2) - ** Improved by Ross McKay (SCSS mode; see http://sass-lang.com/ ) - **/ -// Copyright 1998-2002 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -// TODO: handle SCSS nested properties like font: { weight: bold; size: 1em; } -// TODO: handle SCSS interpolation: #{} -// TODO: add features for Less if somebody feels like contributing; http://lesscss.org/ -// TODO: refactor this monster so that the next poor slob can read it! - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - - -static inline bool IsAWordChar(const unsigned int ch) { - /* FIXME: - * The CSS spec allows "ISO 10646 characters U+00A1 and higher" to be treated as word chars. - * Unfortunately, we are only getting string bytes here, and not full unicode characters. We cannot guarantee - * that our byte is between U+0080 - U+00A0 (to return false), so we have to allow all characters U+0080 and higher - */ - return ch >= 0x80 || isalnum(ch) || ch == '-' || ch == '_'; -} - -inline bool IsCssOperator(const int ch) { - if (!((ch < 0x80) && isalnum(ch)) && - (ch == '{' || ch == '}' || ch == ':' || ch == ',' || ch == ';' || - ch == '.' || ch == '#' || ch == '!' || ch == '@' || - /* CSS2 */ - ch == '*' || ch == '>' || ch == '+' || ch == '=' || ch == '~' || ch == '|' || - ch == '[' || ch == ']' || ch == '(' || ch == ')')) { - return true; - } - return false; -} - -// look behind (from start of document to our start position) to determine current nesting level -inline int NestingLevelLookBehind(unsigned int startPos, Accessor &styler) { - int ch; - int nestingLevel = 0; - - for (unsigned int i = 0; i < startPos; i++) { - ch = styler.SafeGetCharAt(i); - if (ch == '{') - nestingLevel++; - else if (ch == '}') - nestingLevel--; - } - - return nestingLevel; -} - -static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { - WordList &css1Props = *keywordlists[0]; - WordList &pseudoClasses = *keywordlists[1]; - WordList &css2Props = *keywordlists[2]; - WordList &css3Props = *keywordlists[3]; - WordList &pseudoElements = *keywordlists[4]; - WordList &exProps = *keywordlists[5]; - WordList &exPseudoClasses = *keywordlists[6]; - WordList &exPseudoElements = *keywordlists[7]; - - StyleContext sc(startPos, length, initStyle, styler); - - int lastState = -1; // before operator - int lastStateC = -1; // before comment - int lastStateS = -1; // before single-quoted/double-quoted string - int lastStateVar = -1; // before variable (SCSS) - int lastStateVal = -1; // before value (SCSS) - int op = ' '; // last operator - int opPrev = ' '; // last operator - bool insideParentheses = false; // true if currently in a CSS url() or similar construct - - // property lexer.css.scss.language - // Set to 1 for Sassy CSS (.scss) - bool isScssDocument = styler.GetPropertyInt("lexer.css.scss.language") != 0; - - // TODO: implement Less support - bool isLessDocument = false; - - // SCSS and Less both support single-line comments - typedef enum _CommentModes { eCommentBlock = 0, eCommentLine = 1} CommentMode; - CommentMode comment_mode = eCommentBlock; - bool hasSingleLineComments = isScssDocument || isLessDocument; - - // must keep track of nesting level in document types that support it (SCSS, Less) - bool hasNesting = false; - int nestingLevel = 0; - if (isScssDocument || isLessDocument) { - hasNesting = true; - nestingLevel = NestingLevelLookBehind(startPos, styler); - } - - // "the loop" - for (; sc.More(); sc.Forward()) { - if (sc.state == SCE_CSS_COMMENT && ((comment_mode == eCommentBlock && sc.Match('*', '/')) || (comment_mode == eCommentLine && sc.atLineEnd))) { - if (lastStateC == -1) { - // backtrack to get last state: - // comments are like whitespace, so we must return to the previous state - unsigned int i = startPos; - for (; i > 0; i--) { - if ((lastStateC = styler.StyleAt(i-1)) != SCE_CSS_COMMENT) { - if (lastStateC == SCE_CSS_OPERATOR) { - op = styler.SafeGetCharAt(i-1); - opPrev = styler.SafeGetCharAt(i-2); - while (--i) { - lastState = styler.StyleAt(i-1); - if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT) - break; - } - if (i == 0) - lastState = SCE_CSS_DEFAULT; - } - break; - } - } - if (i == 0) - lastStateC = SCE_CSS_DEFAULT; - } - if (comment_mode == eCommentBlock) { - sc.Forward(); - sc.ForwardSetState(lastStateC); - } else /* eCommentLine */ { - sc.SetState(lastStateC); - } - } - - if (sc.state == SCE_CSS_COMMENT) - continue; - - if (sc.state == SCE_CSS_DOUBLESTRING || sc.state == SCE_CSS_SINGLESTRING) { - if (sc.ch != (sc.state == SCE_CSS_DOUBLESTRING ? '\"' : '\'')) - continue; - unsigned int i = sc.currentPos; - while (i && styler[i-1] == '\\') - i--; - if ((sc.currentPos - i) % 2 == 1) - continue; - sc.ForwardSetState(lastStateS); - } - - if (sc.state == SCE_CSS_OPERATOR) { - if (op == ' ') { - unsigned int i = startPos; - op = styler.SafeGetCharAt(i-1); - opPrev = styler.SafeGetCharAt(i-2); - while (--i) { - lastState = styler.StyleAt(i-1); - if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT) - break; - } - } - switch (op) { - case '@': - if (lastState == SCE_CSS_DEFAULT || hasNesting) - sc.SetState(SCE_CSS_DIRECTIVE); - break; - case '>': - case '+': - if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || - lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) - sc.SetState(SCE_CSS_DEFAULT); - break; - case '[': - if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || - lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) - sc.SetState(SCE_CSS_ATTRIBUTE); - break; - case ']': - if (lastState == SCE_CSS_ATTRIBUTE) - sc.SetState(SCE_CSS_TAG); - break; - case '{': - nestingLevel++; - switch (lastState) { - case SCE_CSS_MEDIA: - sc.SetState(SCE_CSS_DEFAULT); - break; - case SCE_CSS_TAG: - case SCE_CSS_DIRECTIVE: - sc.SetState(SCE_CSS_IDENTIFIER); - break; - } - break; - case '}': - if (--nestingLevel < 0) - nestingLevel = 0; - switch (lastState) { - case SCE_CSS_DEFAULT: - case SCE_CSS_VALUE: - case SCE_CSS_IMPORTANT: - case SCE_CSS_IDENTIFIER: - case SCE_CSS_IDENTIFIER2: - case SCE_CSS_IDENTIFIER3: - if (hasNesting) - sc.SetState(nestingLevel > 0 ? SCE_CSS_IDENTIFIER : SCE_CSS_DEFAULT); - else - sc.SetState(SCE_CSS_DEFAULT); - break; - } - break; - case '(': - if (lastState == SCE_CSS_PSEUDOCLASS) - sc.SetState(SCE_CSS_TAG); - else if (lastState == SCE_CSS_EXTENDED_PSEUDOCLASS) - sc.SetState(SCE_CSS_EXTENDED_PSEUDOCLASS); - break; - case ')': - if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || - lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS || - lastState == SCE_CSS_PSEUDOELEMENT || lastState == SCE_CSS_EXTENDED_PSEUDOELEMENT) - sc.SetState(SCE_CSS_TAG); - break; - case ':': - switch (lastState) { - case SCE_CSS_TAG: - case SCE_CSS_DEFAULT: - case SCE_CSS_CLASS: - case SCE_CSS_ID: - case SCE_CSS_PSEUDOCLASS: - case SCE_CSS_EXTENDED_PSEUDOCLASS: - case SCE_CSS_UNKNOWN_PSEUDOCLASS: - case SCE_CSS_PSEUDOELEMENT: - case SCE_CSS_EXTENDED_PSEUDOELEMENT: - sc.SetState(SCE_CSS_PSEUDOCLASS); - break; - case SCE_CSS_IDENTIFIER: - case SCE_CSS_IDENTIFIER2: - case SCE_CSS_IDENTIFIER3: - case SCE_CSS_EXTENDED_IDENTIFIER: - case SCE_CSS_UNKNOWN_IDENTIFIER: - case SCE_CSS_VARIABLE: - sc.SetState(SCE_CSS_VALUE); - lastStateVal = lastState; - break; - } - break; - case '.': - if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || - lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) - sc.SetState(SCE_CSS_CLASS); - break; - case '#': - if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || - lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) - sc.SetState(SCE_CSS_ID); - break; - case ',': - case '|': - case '~': - if (lastState == SCE_CSS_TAG) - sc.SetState(SCE_CSS_DEFAULT); - break; - case ';': - switch (lastState) { - case SCE_CSS_DIRECTIVE: - if (hasNesting) { - sc.SetState(nestingLevel > 0 ? SCE_CSS_IDENTIFIER : SCE_CSS_DEFAULT); - } else { - sc.SetState(SCE_CSS_DEFAULT); - } - break; - case SCE_CSS_VALUE: - case SCE_CSS_IMPORTANT: - // data URLs can have semicolons; simplistically check for wrapping parentheses and move along - if (insideParentheses) { - sc.SetState(lastState); - } else { - if (lastStateVal == SCE_CSS_VARIABLE) { - sc.SetState(SCE_CSS_DEFAULT); - } else { - sc.SetState(SCE_CSS_IDENTIFIER); - } - } - break; - case SCE_CSS_VARIABLE: - if (lastStateVar == SCE_CSS_VALUE) { - // data URLs can have semicolons; simplistically check for wrapping parentheses and move along - if (insideParentheses) { - sc.SetState(SCE_CSS_VALUE); - } else { - sc.SetState(SCE_CSS_IDENTIFIER); - } - } else { - sc.SetState(SCE_CSS_DEFAULT); - } - break; - } - break; - case '!': - if (lastState == SCE_CSS_VALUE) - sc.SetState(SCE_CSS_IMPORTANT); - break; - } - } - - if (sc.ch == '*' && sc.state == SCE_CSS_DEFAULT) { - sc.SetState(SCE_CSS_TAG); - continue; - } - - // check for inside parentheses (whether part of an "operator" or not) - if (sc.ch == '(') - insideParentheses = true; - else if (sc.ch == ')') - insideParentheses = false; - - // SCSS special modes - if (isScssDocument) { - // variable name - if (sc.ch == '$') { - switch (sc.state) { - case SCE_CSS_DEFAULT: - case SCE_CSS_VALUE: - lastStateVar = sc.state; - sc.SetState(SCE_CSS_VARIABLE); - continue; - } - } - if (sc.state == SCE_CSS_VARIABLE) { - if (IsAWordChar(sc.ch)) { - // still looking at the variable name - continue; - } - if (lastStateVar == SCE_CSS_VALUE) { - // not looking at the variable name any more, and it was part of a value - sc.SetState(SCE_CSS_VALUE); - } - } - - // nested rule parent selector - if (sc.ch == '&') { - switch (sc.state) { - case SCE_CSS_DEFAULT: - case SCE_CSS_IDENTIFIER: - sc.SetState(SCE_CSS_TAG); - continue; - } - } - } - - // nesting rules that apply to SCSS and Less - if (hasNesting) { - // check for nested rule selector - if (sc.state == SCE_CSS_IDENTIFIER && (IsAWordChar(sc.ch) || sc.ch == ':' || sc.ch == '.' || sc.ch == '#')) { - // look ahead to see whether { comes before next ; and } - unsigned int endPos = startPos + length; - int ch; - - for (unsigned int i = sc.currentPos; i < endPos; i++) { - ch = styler.SafeGetCharAt(i); - if (ch == ';' || ch == '}') - break; - if (ch == '{') { - sc.SetState(SCE_CSS_DEFAULT); - continue; - } - } - } - - } - - if (IsAWordChar(sc.ch)) { - if (sc.state == SCE_CSS_DEFAULT) - sc.SetState(SCE_CSS_TAG); - continue; - } - - if (IsAWordChar(sc.chPrev) && ( - sc.state == SCE_CSS_IDENTIFIER || sc.state == SCE_CSS_IDENTIFIER2 || - sc.state == SCE_CSS_IDENTIFIER3 || sc.state == SCE_CSS_EXTENDED_IDENTIFIER || - sc.state == SCE_CSS_UNKNOWN_IDENTIFIER || - sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT || - sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT || - sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS || - sc.state == SCE_CSS_IMPORTANT || - sc.state == SCE_CSS_DIRECTIVE - )) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - char *s2 = s; - while (*s2 && !IsAWordChar(*s2)) - s2++; - switch (sc.state) { - case SCE_CSS_IDENTIFIER: - case SCE_CSS_IDENTIFIER2: - case SCE_CSS_IDENTIFIER3: - case SCE_CSS_EXTENDED_IDENTIFIER: - case SCE_CSS_UNKNOWN_IDENTIFIER: - if (css1Props.InList(s2)) - sc.ChangeState(SCE_CSS_IDENTIFIER); - else if (css2Props.InList(s2)) - sc.ChangeState(SCE_CSS_IDENTIFIER2); - else if (css3Props.InList(s2)) - sc.ChangeState(SCE_CSS_IDENTIFIER3); - else if (exProps.InList(s2)) - sc.ChangeState(SCE_CSS_EXTENDED_IDENTIFIER); - else - sc.ChangeState(SCE_CSS_UNKNOWN_IDENTIFIER); - break; - case SCE_CSS_PSEUDOCLASS: - case SCE_CSS_PSEUDOELEMENT: - case SCE_CSS_EXTENDED_PSEUDOCLASS: - case SCE_CSS_EXTENDED_PSEUDOELEMENT: - case SCE_CSS_UNKNOWN_PSEUDOCLASS: - if (op == ':' && opPrev != ':' && pseudoClasses.InList(s2)) - sc.ChangeState(SCE_CSS_PSEUDOCLASS); - else if (opPrev == ':' && pseudoElements.InList(s2)) - sc.ChangeState(SCE_CSS_PSEUDOELEMENT); - else if ((op == ':' || (op == '(' && lastState == SCE_CSS_EXTENDED_PSEUDOCLASS)) && opPrev != ':' && exPseudoClasses.InList(s2)) - sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOCLASS); - else if (opPrev == ':' && exPseudoElements.InList(s2)) - sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOELEMENT); - else - sc.ChangeState(SCE_CSS_UNKNOWN_PSEUDOCLASS); - break; - case SCE_CSS_IMPORTANT: - if (strcmp(s2, "important") != 0) - sc.ChangeState(SCE_CSS_VALUE); - break; - case SCE_CSS_DIRECTIVE: - if (op == '@' && strcmp(s2, "media") == 0) - sc.ChangeState(SCE_CSS_MEDIA); - break; - } - } - - if (sc.ch != '.' && sc.ch != ':' && sc.ch != '#' && ( - sc.state == SCE_CSS_CLASS || sc.state == SCE_CSS_ID || - (sc.ch != '(' && sc.ch != ')' && ( /* This line of the condition makes it possible to extend pseudo-classes with parentheses */ - sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT || - sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT || - sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS - )) - )) - sc.SetState(SCE_CSS_TAG); - - if (sc.Match('/', '*')) { - lastStateC = sc.state; - comment_mode = eCommentBlock; - sc.SetState(SCE_CSS_COMMENT); - sc.Forward(); - } else if (hasSingleLineComments && sc.Match('/', '/') && !insideParentheses) { - // note that we've had to treat ([...]// as the start of a URL not a comment, e.g. url(http://example.com), url(//example.com) - lastStateC = sc.state; - comment_mode = eCommentLine; - sc.SetState(SCE_CSS_COMMENT); - sc.Forward(); - } else if ((sc.state == SCE_CSS_VALUE || sc.state == SCE_CSS_ATTRIBUTE) - && (sc.ch == '\"' || sc.ch == '\'')) { - lastStateS = sc.state; - sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING)); - } else if (IsCssOperator(sc.ch) - && (sc.state != SCE_CSS_ATTRIBUTE || sc.ch == ']') - && (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!') - && ((sc.state != SCE_CSS_DIRECTIVE && sc.state != SCE_CSS_MEDIA) || sc.ch == ';' || sc.ch == '{') - ) { - if (sc.state != SCE_CSS_OPERATOR) - lastState = sc.state; - sc.SetState(SCE_CSS_OPERATOR); - op = sc.ch; - opPrev = sc.chPrev; - } - } - - sc.Complete(); -} - -static void FoldCSSDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - bool inComment = (styler.StyleAt(startPos-1) == SCE_CSS_COMMENT); - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styler.StyleAt(i); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment) { - if (!inComment && (style == SCE_CSS_COMMENT)) - levelCurrent++; - else if (inComment && (style != SCE_CSS_COMMENT)) - levelCurrent--; - inComment = (style == SCE_CSS_COMMENT); - } - if (style == SCE_CSS_OPERATOR) { - if (ch == '{') { - levelCurrent++; - } else if (ch == '}') { - levelCurrent--; - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const cssWordListDesc[] = { - "CSS1 Properties", - "Pseudo-classes", - "CSS2 Properties", - "CSS3 Properties", - "Pseudo-elements", - "Browser-Specific CSS Properties", - "Browser-Specific Pseudo-classes", - "Browser-Specific Pseudo-elements", - 0 -}; - -LexerModule lmCss(SCLEX_CSS, ColouriseCssDoc, "css", FoldCSSDoc, cssWordListDesc); +// Scintilla source code edit control +/** @file LexCSS.cxx + ** Lexer for Cascading Style Sheets + ** Written by Jakub Vrna + ** Improved by Philippe Lhoste (CSS2) + ** Improved by Ross McKay (SCSS mode; see http://sass-lang.com/ ) + **/ +// Copyright 1998-2002 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +// TODO: handle SCSS nested properties like font: { weight: bold; size: 1em; } +// TODO: handle SCSS interpolation: #{} +// TODO: add features for Less if somebody feels like contributing; http://lesscss.org/ +// TODO: refactor this monster so that the next poor slob can read it! + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + + +static inline bool IsAWordChar(const unsigned int ch) { + /* FIXME: + * The CSS spec allows "ISO 10646 characters U+00A1 and higher" to be treated as word chars. + * Unfortunately, we are only getting string bytes here, and not full unicode characters. We cannot guarantee + * that our byte is between U+0080 - U+00A0 (to return false), so we have to allow all characters U+0080 and higher + */ + return ch >= 0x80 || isalnum(ch) || ch == '-' || ch == '_'; +} + +inline bool IsCssOperator(const int ch) { + if (!((ch < 0x80) && isalnum(ch)) && + (ch == '{' || ch == '}' || ch == ':' || ch == ',' || ch == ';' || + ch == '.' || ch == '#' || ch == '!' || ch == '@' || + /* CSS2 */ + ch == '*' || ch == '>' || ch == '+' || ch == '=' || ch == '~' || ch == '|' || + ch == '[' || ch == ']' || ch == '(' || ch == ')')) { + return true; + } + return false; +} + +// look behind (from start of document to our start position) to determine current nesting level +inline int NestingLevelLookBehind(unsigned int startPos, Accessor &styler) { + int ch; + int nestingLevel = 0; + + for (unsigned int i = 0; i < startPos; i++) { + ch = styler.SafeGetCharAt(i); + if (ch == '{') + nestingLevel++; + else if (ch == '}') + nestingLevel--; + } + + return nestingLevel; +} + +static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { + WordList &css1Props = *keywordlists[0]; + WordList &pseudoClasses = *keywordlists[1]; + WordList &css2Props = *keywordlists[2]; + WordList &css3Props = *keywordlists[3]; + WordList &pseudoElements = *keywordlists[4]; + WordList &exProps = *keywordlists[5]; + WordList &exPseudoClasses = *keywordlists[6]; + WordList &exPseudoElements = *keywordlists[7]; + + StyleContext sc(startPos, length, initStyle, styler); + + int lastState = -1; // before operator + int lastStateC = -1; // before comment + int lastStateS = -1; // before single-quoted/double-quoted string + int lastStateVar = -1; // before variable (SCSS) + int lastStateVal = -1; // before value (SCSS) + int op = ' '; // last operator + int opPrev = ' '; // last operator + bool insideParentheses = false; // true if currently in a CSS url() or similar construct + + // property lexer.css.scss.language + // Set to 1 for Sassy CSS (.scss) + bool isScssDocument = styler.GetPropertyInt("lexer.css.scss.language") != 0; + + // TODO: implement Less support + bool isLessDocument = false; + + // SCSS and Less both support single-line comments + typedef enum _CommentModes { eCommentBlock = 0, eCommentLine = 1} CommentMode; + CommentMode comment_mode = eCommentBlock; + bool hasSingleLineComments = isScssDocument || isLessDocument; + + // must keep track of nesting level in document types that support it (SCSS, Less) + bool hasNesting = false; + int nestingLevel = 0; + if (isScssDocument || isLessDocument) { + hasNesting = true; + nestingLevel = NestingLevelLookBehind(startPos, styler); + } + + // "the loop" + for (; sc.More(); sc.Forward()) { + if (sc.state == SCE_CSS_COMMENT && ((comment_mode == eCommentBlock && sc.Match('*', '/')) || (comment_mode == eCommentLine && sc.atLineEnd))) { + if (lastStateC == -1) { + // backtrack to get last state: + // comments are like whitespace, so we must return to the previous state + unsigned int i = startPos; + for (; i > 0; i--) { + if ((lastStateC = styler.StyleAt(i-1)) != SCE_CSS_COMMENT) { + if (lastStateC == SCE_CSS_OPERATOR) { + op = styler.SafeGetCharAt(i-1); + opPrev = styler.SafeGetCharAt(i-2); + while (--i) { + lastState = styler.StyleAt(i-1); + if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT) + break; + } + if (i == 0) + lastState = SCE_CSS_DEFAULT; + } + break; + } + } + if (i == 0) + lastStateC = SCE_CSS_DEFAULT; + } + if (comment_mode == eCommentBlock) { + sc.Forward(); + sc.ForwardSetState(lastStateC); + } else /* eCommentLine */ { + sc.SetState(lastStateC); + } + } + + if (sc.state == SCE_CSS_COMMENT) + continue; + + if (sc.state == SCE_CSS_DOUBLESTRING || sc.state == SCE_CSS_SINGLESTRING) { + if (sc.ch != (sc.state == SCE_CSS_DOUBLESTRING ? '\"' : '\'')) + continue; + unsigned int i = sc.currentPos; + while (i && styler[i-1] == '\\') + i--; + if ((sc.currentPos - i) % 2 == 1) + continue; + sc.ForwardSetState(lastStateS); + } + + if (sc.state == SCE_CSS_OPERATOR) { + if (op == ' ') { + unsigned int i = startPos; + op = styler.SafeGetCharAt(i-1); + opPrev = styler.SafeGetCharAt(i-2); + while (--i) { + lastState = styler.StyleAt(i-1); + if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT) + break; + } + } + switch (op) { + case '@': + if (lastState == SCE_CSS_DEFAULT || hasNesting) + sc.SetState(SCE_CSS_DIRECTIVE); + break; + case '>': + case '+': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) + sc.SetState(SCE_CSS_DEFAULT); + break; + case '[': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) + sc.SetState(SCE_CSS_ATTRIBUTE); + break; + case ']': + if (lastState == SCE_CSS_ATTRIBUTE) + sc.SetState(SCE_CSS_TAG); + break; + case '{': + nestingLevel++; + switch (lastState) { + case SCE_CSS_MEDIA: + sc.SetState(SCE_CSS_DEFAULT); + break; + case SCE_CSS_TAG: + case SCE_CSS_DIRECTIVE: + sc.SetState(SCE_CSS_IDENTIFIER); + break; + } + break; + case '}': + if (--nestingLevel < 0) + nestingLevel = 0; + switch (lastState) { + case SCE_CSS_DEFAULT: + case SCE_CSS_VALUE: + case SCE_CSS_IMPORTANT: + case SCE_CSS_IDENTIFIER: + case SCE_CSS_IDENTIFIER2: + case SCE_CSS_IDENTIFIER3: + if (hasNesting) + sc.SetState(nestingLevel > 0 ? SCE_CSS_IDENTIFIER : SCE_CSS_DEFAULT); + else + sc.SetState(SCE_CSS_DEFAULT); + break; + } + break; + case '(': + if (lastState == SCE_CSS_PSEUDOCLASS) + sc.SetState(SCE_CSS_TAG); + else if (lastState == SCE_CSS_EXTENDED_PSEUDOCLASS) + sc.SetState(SCE_CSS_EXTENDED_PSEUDOCLASS); + break; + case ')': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS || + lastState == SCE_CSS_PSEUDOELEMENT || lastState == SCE_CSS_EXTENDED_PSEUDOELEMENT) + sc.SetState(SCE_CSS_TAG); + break; + case ':': + switch (lastState) { + case SCE_CSS_TAG: + case SCE_CSS_DEFAULT: + case SCE_CSS_CLASS: + case SCE_CSS_ID: + case SCE_CSS_PSEUDOCLASS: + case SCE_CSS_EXTENDED_PSEUDOCLASS: + case SCE_CSS_UNKNOWN_PSEUDOCLASS: + case SCE_CSS_PSEUDOELEMENT: + case SCE_CSS_EXTENDED_PSEUDOELEMENT: + sc.SetState(SCE_CSS_PSEUDOCLASS); + break; + case SCE_CSS_IDENTIFIER: + case SCE_CSS_IDENTIFIER2: + case SCE_CSS_IDENTIFIER3: + case SCE_CSS_EXTENDED_IDENTIFIER: + case SCE_CSS_UNKNOWN_IDENTIFIER: + case SCE_CSS_VARIABLE: + sc.SetState(SCE_CSS_VALUE); + lastStateVal = lastState; + break; + } + break; + case '.': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) + sc.SetState(SCE_CSS_CLASS); + break; + case '#': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) + sc.SetState(SCE_CSS_ID); + break; + case ',': + case '|': + case '~': + if (lastState == SCE_CSS_TAG) + sc.SetState(SCE_CSS_DEFAULT); + break; + case ';': + switch (lastState) { + case SCE_CSS_DIRECTIVE: + if (hasNesting) { + sc.SetState(nestingLevel > 0 ? SCE_CSS_IDENTIFIER : SCE_CSS_DEFAULT); + } else { + sc.SetState(SCE_CSS_DEFAULT); + } + break; + case SCE_CSS_VALUE: + case SCE_CSS_IMPORTANT: + // data URLs can have semicolons; simplistically check for wrapping parentheses and move along + if (insideParentheses) { + sc.SetState(lastState); + } else { + if (lastStateVal == SCE_CSS_VARIABLE) { + sc.SetState(SCE_CSS_DEFAULT); + } else { + sc.SetState(SCE_CSS_IDENTIFIER); + } + } + break; + case SCE_CSS_VARIABLE: + if (lastStateVar == SCE_CSS_VALUE) { + // data URLs can have semicolons; simplistically check for wrapping parentheses and move along + if (insideParentheses) { + sc.SetState(SCE_CSS_VALUE); + } else { + sc.SetState(SCE_CSS_IDENTIFIER); + } + } else { + sc.SetState(SCE_CSS_DEFAULT); + } + break; + } + break; + case '!': + if (lastState == SCE_CSS_VALUE) + sc.SetState(SCE_CSS_IMPORTANT); + break; + } + } + + if (sc.ch == '*' && sc.state == SCE_CSS_DEFAULT) { + sc.SetState(SCE_CSS_TAG); + continue; + } + + // check for inside parentheses (whether part of an "operator" or not) + if (sc.ch == '(') + insideParentheses = true; + else if (sc.ch == ')') + insideParentheses = false; + + // SCSS special modes + if (isScssDocument) { + // variable name + if (sc.ch == '$') { + switch (sc.state) { + case SCE_CSS_DEFAULT: + case SCE_CSS_VALUE: + lastStateVar = sc.state; + sc.SetState(SCE_CSS_VARIABLE); + continue; + } + } + if (sc.state == SCE_CSS_VARIABLE) { + if (IsAWordChar(sc.ch)) { + // still looking at the variable name + continue; + } + if (lastStateVar == SCE_CSS_VALUE) { + // not looking at the variable name any more, and it was part of a value + sc.SetState(SCE_CSS_VALUE); + } + } + + // nested rule parent selector + if (sc.ch == '&') { + switch (sc.state) { + case SCE_CSS_DEFAULT: + case SCE_CSS_IDENTIFIER: + sc.SetState(SCE_CSS_TAG); + continue; + } + } + } + + // nesting rules that apply to SCSS and Less + if (hasNesting) { + // check for nested rule selector + if (sc.state == SCE_CSS_IDENTIFIER && (IsAWordChar(sc.ch) || sc.ch == ':' || sc.ch == '.' || sc.ch == '#')) { + // look ahead to see whether { comes before next ; and } + unsigned int endPos = startPos + length; + int ch; + + for (unsigned int i = sc.currentPos; i < endPos; i++) { + ch = styler.SafeGetCharAt(i); + if (ch == ';' || ch == '}') + break; + if (ch == '{') { + sc.SetState(SCE_CSS_DEFAULT); + continue; + } + } + } + + } + + if (IsAWordChar(sc.ch)) { + if (sc.state == SCE_CSS_DEFAULT) + sc.SetState(SCE_CSS_TAG); + continue; + } + + if (IsAWordChar(sc.chPrev) && ( + sc.state == SCE_CSS_IDENTIFIER || sc.state == SCE_CSS_IDENTIFIER2 || + sc.state == SCE_CSS_IDENTIFIER3 || sc.state == SCE_CSS_EXTENDED_IDENTIFIER || + sc.state == SCE_CSS_UNKNOWN_IDENTIFIER || + sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT || + sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT || + sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS || + sc.state == SCE_CSS_IMPORTANT || + sc.state == SCE_CSS_DIRECTIVE + )) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + char *s2 = s; + while (*s2 && !IsAWordChar(*s2)) + s2++; + switch (sc.state) { + case SCE_CSS_IDENTIFIER: + case SCE_CSS_IDENTIFIER2: + case SCE_CSS_IDENTIFIER3: + case SCE_CSS_EXTENDED_IDENTIFIER: + case SCE_CSS_UNKNOWN_IDENTIFIER: + if (css1Props.InList(s2)) + sc.ChangeState(SCE_CSS_IDENTIFIER); + else if (css2Props.InList(s2)) + sc.ChangeState(SCE_CSS_IDENTIFIER2); + else if (css3Props.InList(s2)) + sc.ChangeState(SCE_CSS_IDENTIFIER3); + else if (exProps.InList(s2)) + sc.ChangeState(SCE_CSS_EXTENDED_IDENTIFIER); + else + sc.ChangeState(SCE_CSS_UNKNOWN_IDENTIFIER); + break; + case SCE_CSS_PSEUDOCLASS: + case SCE_CSS_PSEUDOELEMENT: + case SCE_CSS_EXTENDED_PSEUDOCLASS: + case SCE_CSS_EXTENDED_PSEUDOELEMENT: + case SCE_CSS_UNKNOWN_PSEUDOCLASS: + if (op == ':' && opPrev != ':' && pseudoClasses.InList(s2)) + sc.ChangeState(SCE_CSS_PSEUDOCLASS); + else if (opPrev == ':' && pseudoElements.InList(s2)) + sc.ChangeState(SCE_CSS_PSEUDOELEMENT); + else if ((op == ':' || (op == '(' && lastState == SCE_CSS_EXTENDED_PSEUDOCLASS)) && opPrev != ':' && exPseudoClasses.InList(s2)) + sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOCLASS); + else if (opPrev == ':' && exPseudoElements.InList(s2)) + sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOELEMENT); + else + sc.ChangeState(SCE_CSS_UNKNOWN_PSEUDOCLASS); + break; + case SCE_CSS_IMPORTANT: + if (strcmp(s2, "important") != 0) + sc.ChangeState(SCE_CSS_VALUE); + break; + case SCE_CSS_DIRECTIVE: + if (op == '@' && strcmp(s2, "media") == 0) + sc.ChangeState(SCE_CSS_MEDIA); + break; + } + } + + if (sc.ch != '.' && sc.ch != ':' && sc.ch != '#' && ( + sc.state == SCE_CSS_CLASS || sc.state == SCE_CSS_ID || + (sc.ch != '(' && sc.ch != ')' && ( /* This line of the condition makes it possible to extend pseudo-classes with parentheses */ + sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT || + sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT || + sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS + )) + )) + sc.SetState(SCE_CSS_TAG); + + if (sc.Match('/', '*')) { + lastStateC = sc.state; + comment_mode = eCommentBlock; + sc.SetState(SCE_CSS_COMMENT); + sc.Forward(); + } else if (hasSingleLineComments && sc.Match('/', '/') && !insideParentheses) { + // note that we've had to treat ([...]// as the start of a URL not a comment, e.g. url(http://example.com), url(//example.com) + lastStateC = sc.state; + comment_mode = eCommentLine; + sc.SetState(SCE_CSS_COMMENT); + sc.Forward(); + } else if ((sc.state == SCE_CSS_VALUE || sc.state == SCE_CSS_ATTRIBUTE) + && (sc.ch == '\"' || sc.ch == '\'')) { + lastStateS = sc.state; + sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING)); + } else if (IsCssOperator(sc.ch) + && (sc.state != SCE_CSS_ATTRIBUTE || sc.ch == ']') + && (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!') + && ((sc.state != SCE_CSS_DIRECTIVE && sc.state != SCE_CSS_MEDIA) || sc.ch == ';' || sc.ch == '{') + ) { + if (sc.state != SCE_CSS_OPERATOR) + lastState = sc.state; + sc.SetState(SCE_CSS_OPERATOR); + op = sc.ch; + opPrev = sc.chPrev; + } + } + + sc.Complete(); +} + +static void FoldCSSDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + bool inComment = (styler.StyleAt(startPos-1) == SCE_CSS_COMMENT); + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styler.StyleAt(i); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment) { + if (!inComment && (style == SCE_CSS_COMMENT)) + levelCurrent++; + else if (inComment && (style != SCE_CSS_COMMENT)) + levelCurrent--; + inComment = (style == SCE_CSS_COMMENT); + } + if (style == SCE_CSS_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const cssWordListDesc[] = { + "CSS1 Properties", + "Pseudo-classes", + "CSS2 Properties", + "CSS3 Properties", + "Pseudo-elements", + "Browser-Specific CSS Properties", + "Browser-Specific Pseudo-classes", + "Browser-Specific Pseudo-elements", + 0 +}; + +LexerModule lmCss(SCLEX_CSS, ColouriseCssDoc, "css", FoldCSSDoc, cssWordListDesc); diff --git a/scintilla/lexers/LexCaml.cxx b/ThirdLibs/scintilla/lexers/LexCaml.cxx similarity index 96% rename from scintilla/lexers/LexCaml.cxx rename to ThirdLibs/scintilla/lexers/LexCaml.cxx index 982384f7..f576e3e2 100644 --- a/scintilla/lexers/LexCaml.cxx +++ b/ThirdLibs/scintilla/lexers/LexCaml.cxx @@ -1,456 +1,456 @@ -// Scintilla source code edit control -/** @file LexCaml.cxx - ** Lexer for Objective Caml. - **/ -// Copyright 2005-2009 by Robert Roessler -// The License.txt file describes the conditions under which this software may be distributed. -/* Release History - 20050204 Initial release. - 20050205 Quick compiler standards/"cleanliness" adjustment. - 20050206 Added cast for IsLeadByte(). - 20050209 Changes to "external" build support. - 20050306 Fix for 1st-char-in-doc "corner" case. - 20050502 Fix for [harmless] one-past-the-end coloring. - 20050515 Refined numeric token recognition logic. - 20051125 Added 2nd "optional" keywords class. - 20051129 Support "magic" (read-only) comments for RCaml. - 20051204 Swtich to using StyleContext infrastructure. - 20090629 Add full Standard ML '97 support. -*/ - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "PropSetSimple.h" -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -// Since the Microsoft __iscsym[f] funcs are not ANSI... -inline int iscaml(int c) {return isalnum(c) || c == '_';} -inline int iscamlf(int c) {return isalpha(c) || c == '_';} - -static const int baseT[24] = { - 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A - L */ - 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,16 /* M - X */ -}; - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#ifdef BUILD_AS_EXTERNAL_LEXER -/* - (actually seems to work!) -*/ -#include -#include "WindowAccessor.h" -#include "ExternalLexer.h" - -#undef EXT_LEXER_DECL -#define EXT_LEXER_DECL __declspec( dllexport ) __stdcall - -#if PLAT_WIN -#include -#endif - -static void ColouriseCamlDoc( - unsigned int startPos, int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler); - -static void FoldCamlDoc( - unsigned int startPos, int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler); - -static void InternalLexOrFold(int lexOrFold, unsigned int startPos, int length, - int initStyle, char *words[], WindowID window, char *props); - -static const char* LexerName = "caml"; - -#ifdef TRACE -void Platform::DebugPrintf(const char *format, ...) { - char buffer[2000]; - va_list pArguments; - va_start(pArguments, format); - vsprintf(buffer,format,pArguments); - va_end(pArguments); - Platform::DebugDisplay(buffer); -} -#else -void Platform::DebugPrintf(const char *, ...) { -} -#endif - -bool Platform::IsDBCSLeadByte(int codePage, char ch) { - return ::IsDBCSLeadByteEx(codePage, ch) != 0; -} - -long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam) { - return ::SendMessage(reinterpret_cast(w), msg, wParam, lParam); -} - -long Platform::SendScintillaPointer(WindowID w, unsigned int msg, unsigned long wParam, void *lParam) { - return ::SendMessage(reinterpret_cast(w), msg, wParam, - reinterpret_cast(lParam)); -} - -void EXT_LEXER_DECL Fold(unsigned int lexer, unsigned int startPos, int length, - int initStyle, char *words[], WindowID window, char *props) -{ - // below useless evaluation(s) to supress "not used" warnings - lexer; - // build expected data structures and do the Fold - InternalLexOrFold(1, startPos, length, initStyle, words, window, props); - -} - -int EXT_LEXER_DECL GetLexerCount() -{ - return 1; // just us [Objective] Caml lexers here! -} - -void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength) -{ - // below useless evaluation(s) to supress "not used" warnings - Index; - // return as much of our lexer name as will fit (what's up with Index?) - if (buflength > 0) { - buflength--; - int n = strlen(LexerName); - if (n > buflength) - n = buflength; - memcpy(name, LexerName, n), name[n] = '\0'; - } -} - -void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, - int initStyle, char *words[], WindowID window, char *props) -{ - // below useless evaluation(s) to supress "not used" warnings - lexer; - // build expected data structures and do the Lex - InternalLexOrFold(0, startPos, length, initStyle, words, window, props); -} - -static void InternalLexOrFold(int foldOrLex, unsigned int startPos, int length, - int initStyle, char *words[], WindowID window, char *props) -{ - // create and initialize a WindowAccessor (including contained PropSet) - PropSetSimple ps; - ps.SetMultiple(props); - WindowAccessor wa(window, ps); - // create and initialize WordList(s) - int nWL = 0; - for (; words[nWL]; nWL++) ; // count # of WordList PTRs needed - WordList** wl = new WordList* [nWL + 1];// alloc WordList PTRs - int i = 0; - for (; i < nWL; i++) { - wl[i] = new WordList(); // (works or THROWS bad_alloc EXCEPTION) - wl[i]->Set(words[i]); - } - wl[i] = 0; - // call our "internal" folder/lexer (... then do Flush!) - if (foldOrLex) - FoldCamlDoc(startPos, length, initStyle, wl, wa); - else - ColouriseCamlDoc(startPos, length, initStyle, wl, wa); - wa.Flush(); - // clean up before leaving - for (i = nWL - 1; i >= 0; i--) - delete wl[i]; - delete [] wl; -} - -static -#endif /* BUILD_AS_EXTERNAL_LEXER */ - -void ColouriseCamlDoc( - unsigned int startPos, int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) -{ - // initialize styler - StyleContext sc(startPos, length, initStyle, styler); - - int chBase = 0, chToken = 0, chLit = 0; - WordList& keywords = *keywordlists[0]; - WordList& keywords2 = *keywordlists[1]; - WordList& keywords3 = *keywordlists[2]; - const bool isSML = keywords.InList("andalso"); - const int useMagic = styler.GetPropertyInt("lexer.caml.magic", 0); - - // set up [initial] state info (terminating states that shouldn't "bleed") - const int state_ = sc.state & 0x0f; - if (state_ <= SCE_CAML_CHAR - || (isSML && state_ == SCE_CAML_STRING)) - sc.state = SCE_CAML_DEFAULT; - int nesting = (state_ >= SCE_CAML_COMMENT)? (state_ - SCE_CAML_COMMENT): 0; - - // foreach char in range... - while (sc.More()) { - // set up [per-char] state info - int state2 = -1; // (ASSUME no state change) - int chColor = sc.currentPos - 1;// (ASSUME standard coloring range) - bool advance = true; // (ASSUME scanner "eats" 1 char) - - // step state machine - switch (sc.state & 0x0f) { - case SCE_CAML_DEFAULT: - chToken = sc.currentPos; // save [possible] token start (JIC) - // it's wide open; what do we have? - if (iscamlf(sc.ch)) - state2 = SCE_CAML_IDENTIFIER; - else if (!isSML && sc.Match('`') && iscamlf(sc.chNext)) - state2 = SCE_CAML_TAGNAME; - else if (!isSML && sc.Match('#') && isdigit(sc.chNext)) - state2 = SCE_CAML_LINENUM; - else if (isdigit(sc.ch)) { - // it's a number, assume base 10 - state2 = SCE_CAML_NUMBER, chBase = 10; - if (sc.Match('0')) { - // there MAY be a base specified... - const char* baseC = "bBoOxX"; - if (isSML) { - if (sc.chNext == 'w') - sc.Forward(); // (consume SML "word" indicator) - baseC = "x"; - } - // ... change to specified base AS REQUIRED - if (strchr(baseC, sc.chNext)) - chBase = baseT[tolower(sc.chNext) - 'a'], sc.Forward(); - } - } else if (!isSML && sc.Match('\'')) // (Caml char literal?) - state2 = SCE_CAML_CHAR, chLit = 0; - else if (isSML && sc.Match('#', '"')) // (SML char literal?) - state2 = SCE_CAML_CHAR, sc.Forward(); - else if (sc.Match('"')) - state2 = SCE_CAML_STRING; - else if (sc.Match('(', '*')) - state2 = SCE_CAML_COMMENT, sc.Forward(), sc.ch = ' '; // (*)... - else if (strchr("!?~" /* Caml "prefix-symbol" */ - "=<>@^|&+-*/$%" /* Caml "infix-symbol" */ - "()[]{};,:.#", sc.ch) // Caml "bracket" or ;,:.# - // SML "extra" ident chars - || (isSML && (sc.Match('\\') || sc.Match('`')))) - state2 = SCE_CAML_OPERATOR; - break; - - case SCE_CAML_IDENTIFIER: - // [try to] interpret as [additional] identifier char - if (!(iscaml(sc.ch) || sc.Match('\''))) { - const int n = sc.currentPos - chToken; - if (n < 24) { - // length is believable as keyword, [re-]construct token - char t[24]; - for (int i = -n; i < 0; i++) - t[n + i] = static_cast(sc.GetRelative(i)); - t[n] = '\0'; - // special-case "_" token as KEYWORD - if ((n == 1 && sc.chPrev == '_') || keywords.InList(t)) - sc.ChangeState(SCE_CAML_KEYWORD); - else if (keywords2.InList(t)) - sc.ChangeState(SCE_CAML_KEYWORD2); - else if (keywords3.InList(t)) - sc.ChangeState(SCE_CAML_KEYWORD3); - } - state2 = SCE_CAML_DEFAULT, advance = false; - } - break; - - case SCE_CAML_TAGNAME: - // [try to] interpret as [additional] tagname char - if (!(iscaml(sc.ch) || sc.Match('\''))) - state2 = SCE_CAML_DEFAULT, advance = false; - break; - - /*case SCE_CAML_KEYWORD: - case SCE_CAML_KEYWORD2: - case SCE_CAML_KEYWORD3: - // [try to] interpret as [additional] keyword char - if (!iscaml(ch)) - state2 = SCE_CAML_DEFAULT, advance = false; - break;*/ - - case SCE_CAML_LINENUM: - // [try to] interpret as [additional] linenum directive char - if (!isdigit(sc.ch)) - state2 = SCE_CAML_DEFAULT, advance = false; - break; - - case SCE_CAML_OPERATOR: { - // [try to] interpret as [additional] operator char - const char* o = 0; - if (iscaml(sc.ch) || isspace(sc.ch) // ident or whitespace - || (o = strchr(")]};,\'\"#", sc.ch),o) // "termination" chars - || (!isSML && sc.Match('`')) // Caml extra term char - || (!strchr("!$%&*+-./:<=>?@^|~", sc.ch)// "operator" chars - // SML extra ident chars - && !(isSML && (sc.Match('\\') || sc.Match('`'))))) { - // check for INCLUSIVE termination - if (o && strchr(")]};,", sc.ch)) { - if ((sc.Match(')') && sc.chPrev == '(') - || (sc.Match(']') && sc.chPrev == '[')) - // special-case "()" and "[]" tokens as KEYWORDS - sc.ChangeState(SCE_CAML_KEYWORD); - chColor++; - } else - advance = false; - state2 = SCE_CAML_DEFAULT; - } - break; - } - - case SCE_CAML_NUMBER: - // [try to] interpret as [additional] numeric literal char - if ((!isSML && sc.Match('_')) || IsADigit(sc.ch, chBase)) - break; - // how about an integer suffix? - if (!isSML && (sc.Match('l') || sc.Match('L') || sc.Match('n')) - && (sc.chPrev == '_' || IsADigit(sc.chPrev, chBase))) - break; - // or a floating-point literal? - if (chBase == 10) { - // with a decimal point? - if (sc.Match('.') - && ((!isSML && sc.chPrev == '_') - || IsADigit(sc.chPrev, chBase))) - break; - // with an exponent? (I) - if ((sc.Match('e') || sc.Match('E')) - && ((!isSML && (sc.chPrev == '.' || sc.chPrev == '_')) - || IsADigit(sc.chPrev, chBase))) - break; - // with an exponent? (II) - if (((!isSML && (sc.Match('+') || sc.Match('-'))) - || (isSML && sc.Match('~'))) - && (sc.chPrev == 'e' || sc.chPrev == 'E')) - break; - } - // it looks like we have run out of number - state2 = SCE_CAML_DEFAULT, advance = false; - break; - - case SCE_CAML_CHAR: - if (!isSML) { - // [try to] interpret as [additional] char literal char - if (sc.Match('\\')) { - chLit = 1; // (definitely IS a char literal) - if (sc.chPrev == '\\') - sc.ch = ' '; // (...\\') - // should we be terminating - one way or another? - } else if ((sc.Match('\'') && sc.chPrev != '\\') - || sc.atLineEnd) { - state2 = SCE_CAML_DEFAULT; - if (sc.Match('\'')) - chColor++; - else - sc.ChangeState(SCE_CAML_IDENTIFIER); - // ... maybe a char literal, maybe not - } else if (chLit < 1 && sc.currentPos - chToken >= 2) - sc.ChangeState(SCE_CAML_IDENTIFIER), advance = false; - break; - }/* else - // fall through for SML char literal (handle like string) */ - - case SCE_CAML_STRING: - // [try to] interpret as [additional] [SML char/] string literal char - if (isSML && sc.Match('\\') && sc.chPrev != '\\' && isspace(sc.chNext)) - state2 = SCE_CAML_WHITE; - else if (sc.Match('\\') && sc.chPrev == '\\') - sc.ch = ' '; // (...\\") - // should we be terminating - one way or another? - else if ((sc.Match('"') && sc.chPrev != '\\') - || (isSML && sc.atLineEnd)) { - state2 = SCE_CAML_DEFAULT; - if (sc.Match('"')) - chColor++; - } - break; - - case SCE_CAML_WHITE: - // [try to] interpret as [additional] SML embedded whitespace char - if (sc.Match('\\')) { - // style this puppy NOW... - state2 = SCE_CAML_STRING, sc.ch = ' ' /* (...\") */, chColor++, - styler.ColourTo(chColor, SCE_CAML_WHITE), styler.Flush(); - // ... then backtrack to determine original SML literal type - int p = chColor - 2; - for (; p >= 0 && styler.StyleAt(p) == SCE_CAML_WHITE; p--) ; - if (p >= 0) - state2 = static_cast(styler.StyleAt(p)); - // take care of state change NOW - sc.ChangeState(state2), state2 = -1; - } - break; - - case SCE_CAML_COMMENT: - case SCE_CAML_COMMENT1: - case SCE_CAML_COMMENT2: - case SCE_CAML_COMMENT3: - // we're IN a comment - does this start a NESTED comment? - if (sc.Match('(', '*')) - state2 = sc.state + 1, chToken = sc.currentPos, - sc.Forward(), sc.ch = ' ' /* (*)... */, nesting++; - // [try to] interpret as [additional] comment char - else if (sc.Match(')') && sc.chPrev == '*') { - if (nesting) - state2 = (sc.state & 0x0f) - 1, chToken = 0, nesting--; - else - state2 = SCE_CAML_DEFAULT; - chColor++; - // enable "magic" (read-only) comment AS REQUIRED - } else if (useMagic && sc.currentPos - chToken == 4 - && sc.Match('c') && sc.chPrev == 'r' && sc.GetRelative(-2) == '@') - sc.state |= 0x10; // (switch to read-only comment style) - break; - } - - // handle state change and char coloring AS REQUIRED - if (state2 >= 0) - styler.ColourTo(chColor, sc.state), sc.ChangeState(state2); - // move to next char UNLESS re-scanning current char - if (advance) - sc.Forward(); - } - - // do any required terminal char coloring (JIC) - sc.Complete(); -} - -#ifdef BUILD_AS_EXTERNAL_LEXER -static -#endif /* BUILD_AS_EXTERNAL_LEXER */ -void FoldCamlDoc( - unsigned int, int, - int, - WordList *[], - Accessor &) -{ -} - -static const char * const camlWordListDesc[] = { - "Keywords", // primary Objective Caml keywords - "Keywords2", // "optional" keywords (typically from Pervasives) - "Keywords3", // "optional" keywords (typically typenames) - 0 -}; - -#ifndef BUILD_AS_EXTERNAL_LEXER -LexerModule lmCaml(SCLEX_CAML, ColouriseCamlDoc, "caml", FoldCamlDoc, camlWordListDesc); -#endif /* BUILD_AS_EXTERNAL_LEXER */ +// Scintilla source code edit control +/** @file LexCaml.cxx + ** Lexer for Objective Caml. + **/ +// Copyright 2005-2009 by Robert Roessler +// The License.txt file describes the conditions under which this software may be distributed. +/* Release History + 20050204 Initial release. + 20050205 Quick compiler standards/"cleanliness" adjustment. + 20050206 Added cast for IsLeadByte(). + 20050209 Changes to "external" build support. + 20050306 Fix for 1st-char-in-doc "corner" case. + 20050502 Fix for [harmless] one-past-the-end coloring. + 20050515 Refined numeric token recognition logic. + 20051125 Added 2nd "optional" keywords class. + 20051129 Support "magic" (read-only) comments for RCaml. + 20051204 Swtich to using StyleContext infrastructure. + 20090629 Add full Standard ML '97 support. +*/ + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +// Since the Microsoft __iscsym[f] funcs are not ANSI... +inline int iscaml(int c) {return isalnum(c) || c == '_';} +inline int iscamlf(int c) {return isalpha(c) || c == '_';} + +static const int baseT[24] = { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A - L */ + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,16 /* M - X */ +}; + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#ifdef BUILD_AS_EXTERNAL_LEXER +/* + (actually seems to work!) +*/ +#include +#include "WindowAccessor.h" +#include "ExternalLexer.h" + +#undef EXT_LEXER_DECL +#define EXT_LEXER_DECL __declspec( dllexport ) __stdcall + +#if PLAT_WIN +#include +#endif + +static void ColouriseCamlDoc( + unsigned int startPos, int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler); + +static void FoldCamlDoc( + unsigned int startPos, int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler); + +static void InternalLexOrFold(int lexOrFold, unsigned int startPos, int length, + int initStyle, char *words[], WindowID window, char *props); + +static const char* LexerName = "caml"; + +#ifdef TRACE +void Platform::DebugPrintf(const char *format, ...) { + char buffer[2000]; + va_list pArguments; + va_start(pArguments, format); + vsprintf(buffer,format,pArguments); + va_end(pArguments); + Platform::DebugDisplay(buffer); +} +#else +void Platform::DebugPrintf(const char *, ...) { +} +#endif + +bool Platform::IsDBCSLeadByte(int codePage, char ch) { + return ::IsDBCSLeadByteEx(codePage, ch) != 0; +} + +long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam) { + return ::SendMessage(reinterpret_cast(w), msg, wParam, lParam); +} + +long Platform::SendScintillaPointer(WindowID w, unsigned int msg, unsigned long wParam, void *lParam) { + return ::SendMessage(reinterpret_cast(w), msg, wParam, + reinterpret_cast(lParam)); +} + +void EXT_LEXER_DECL Fold(unsigned int lexer, unsigned int startPos, int length, + int initStyle, char *words[], WindowID window, char *props) +{ + // below useless evaluation(s) to supress "not used" warnings + lexer; + // build expected data structures and do the Fold + InternalLexOrFold(1, startPos, length, initStyle, words, window, props); + +} + +int EXT_LEXER_DECL GetLexerCount() +{ + return 1; // just us [Objective] Caml lexers here! +} + +void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength) +{ + // below useless evaluation(s) to supress "not used" warnings + Index; + // return as much of our lexer name as will fit (what's up with Index?) + if (buflength > 0) { + buflength--; + int n = strlen(LexerName); + if (n > buflength) + n = buflength; + memcpy(name, LexerName, n), name[n] = '\0'; + } +} + +void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, + int initStyle, char *words[], WindowID window, char *props) +{ + // below useless evaluation(s) to supress "not used" warnings + lexer; + // build expected data structures and do the Lex + InternalLexOrFold(0, startPos, length, initStyle, words, window, props); +} + +static void InternalLexOrFold(int foldOrLex, unsigned int startPos, int length, + int initStyle, char *words[], WindowID window, char *props) +{ + // create and initialize a WindowAccessor (including contained PropSet) + PropSetSimple ps; + ps.SetMultiple(props); + WindowAccessor wa(window, ps); + // create and initialize WordList(s) + int nWL = 0; + for (; words[nWL]; nWL++) ; // count # of WordList PTRs needed + WordList** wl = new WordList* [nWL + 1];// alloc WordList PTRs + int i = 0; + for (; i < nWL; i++) { + wl[i] = new WordList(); // (works or THROWS bad_alloc EXCEPTION) + wl[i]->Set(words[i]); + } + wl[i] = 0; + // call our "internal" folder/lexer (... then do Flush!) + if (foldOrLex) + FoldCamlDoc(startPos, length, initStyle, wl, wa); + else + ColouriseCamlDoc(startPos, length, initStyle, wl, wa); + wa.Flush(); + // clean up before leaving + for (i = nWL - 1; i >= 0; i--) + delete wl[i]; + delete [] wl; +} + +static +#endif /* BUILD_AS_EXTERNAL_LEXER */ + +void ColouriseCamlDoc( + unsigned int startPos, int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) +{ + // initialize styler + StyleContext sc(startPos, length, initStyle, styler); + + int chBase = 0, chToken = 0, chLit = 0; + WordList& keywords = *keywordlists[0]; + WordList& keywords2 = *keywordlists[1]; + WordList& keywords3 = *keywordlists[2]; + const bool isSML = keywords.InList("andalso"); + const int useMagic = styler.GetPropertyInt("lexer.caml.magic", 0); + + // set up [initial] state info (terminating states that shouldn't "bleed") + const int state_ = sc.state & 0x0f; + if (state_ <= SCE_CAML_CHAR + || (isSML && state_ == SCE_CAML_STRING)) + sc.state = SCE_CAML_DEFAULT; + int nesting = (state_ >= SCE_CAML_COMMENT)? (state_ - SCE_CAML_COMMENT): 0; + + // foreach char in range... + while (sc.More()) { + // set up [per-char] state info + int state2 = -1; // (ASSUME no state change) + int chColor = sc.currentPos - 1;// (ASSUME standard coloring range) + bool advance = true; // (ASSUME scanner "eats" 1 char) + + // step state machine + switch (sc.state & 0x0f) { + case SCE_CAML_DEFAULT: + chToken = sc.currentPos; // save [possible] token start (JIC) + // it's wide open; what do we have? + if (iscamlf(sc.ch)) + state2 = SCE_CAML_IDENTIFIER; + else if (!isSML && sc.Match('`') && iscamlf(sc.chNext)) + state2 = SCE_CAML_TAGNAME; + else if (!isSML && sc.Match('#') && isdigit(sc.chNext)) + state2 = SCE_CAML_LINENUM; + else if (isdigit(sc.ch)) { + // it's a number, assume base 10 + state2 = SCE_CAML_NUMBER, chBase = 10; + if (sc.Match('0')) { + // there MAY be a base specified... + const char* baseC = "bBoOxX"; + if (isSML) { + if (sc.chNext == 'w') + sc.Forward(); // (consume SML "word" indicator) + baseC = "x"; + } + // ... change to specified base AS REQUIRED + if (strchr(baseC, sc.chNext)) + chBase = baseT[tolower(sc.chNext) - 'a'], sc.Forward(); + } + } else if (!isSML && sc.Match('\'')) // (Caml char literal?) + state2 = SCE_CAML_CHAR, chLit = 0; + else if (isSML && sc.Match('#', '"')) // (SML char literal?) + state2 = SCE_CAML_CHAR, sc.Forward(); + else if (sc.Match('"')) + state2 = SCE_CAML_STRING; + else if (sc.Match('(', '*')) + state2 = SCE_CAML_COMMENT, sc.Forward(), sc.ch = ' '; // (*)... + else if (strchr("!?~" /* Caml "prefix-symbol" */ + "=<>@^|&+-*/$%" /* Caml "infix-symbol" */ + "()[]{};,:.#", sc.ch) // Caml "bracket" or ;,:.# + // SML "extra" ident chars + || (isSML && (sc.Match('\\') || sc.Match('`')))) + state2 = SCE_CAML_OPERATOR; + break; + + case SCE_CAML_IDENTIFIER: + // [try to] interpret as [additional] identifier char + if (!(iscaml(sc.ch) || sc.Match('\''))) { + const int n = sc.currentPos - chToken; + if (n < 24) { + // length is believable as keyword, [re-]construct token + char t[24]; + for (int i = -n; i < 0; i++) + t[n + i] = static_cast(sc.GetRelative(i)); + t[n] = '\0'; + // special-case "_" token as KEYWORD + if ((n == 1 && sc.chPrev == '_') || keywords.InList(t)) + sc.ChangeState(SCE_CAML_KEYWORD); + else if (keywords2.InList(t)) + sc.ChangeState(SCE_CAML_KEYWORD2); + else if (keywords3.InList(t)) + sc.ChangeState(SCE_CAML_KEYWORD3); + } + state2 = SCE_CAML_DEFAULT, advance = false; + } + break; + + case SCE_CAML_TAGNAME: + // [try to] interpret as [additional] tagname char + if (!(iscaml(sc.ch) || sc.Match('\''))) + state2 = SCE_CAML_DEFAULT, advance = false; + break; + + /*case SCE_CAML_KEYWORD: + case SCE_CAML_KEYWORD2: + case SCE_CAML_KEYWORD3: + // [try to] interpret as [additional] keyword char + if (!iscaml(ch)) + state2 = SCE_CAML_DEFAULT, advance = false; + break;*/ + + case SCE_CAML_LINENUM: + // [try to] interpret as [additional] linenum directive char + if (!isdigit(sc.ch)) + state2 = SCE_CAML_DEFAULT, advance = false; + break; + + case SCE_CAML_OPERATOR: { + // [try to] interpret as [additional] operator char + const char* o = 0; + if (iscaml(sc.ch) || isspace(sc.ch) // ident or whitespace + || (o = strchr(")]};,\'\"#", sc.ch),o) // "termination" chars + || (!isSML && sc.Match('`')) // Caml extra term char + || (!strchr("!$%&*+-./:<=>?@^|~", sc.ch)// "operator" chars + // SML extra ident chars + && !(isSML && (sc.Match('\\') || sc.Match('`'))))) { + // check for INCLUSIVE termination + if (o && strchr(")]};,", sc.ch)) { + if ((sc.Match(')') && sc.chPrev == '(') + || (sc.Match(']') && sc.chPrev == '[')) + // special-case "()" and "[]" tokens as KEYWORDS + sc.ChangeState(SCE_CAML_KEYWORD); + chColor++; + } else + advance = false; + state2 = SCE_CAML_DEFAULT; + } + break; + } + + case SCE_CAML_NUMBER: + // [try to] interpret as [additional] numeric literal char + if ((!isSML && sc.Match('_')) || IsADigit(sc.ch, chBase)) + break; + // how about an integer suffix? + if (!isSML && (sc.Match('l') || sc.Match('L') || sc.Match('n')) + && (sc.chPrev == '_' || IsADigit(sc.chPrev, chBase))) + break; + // or a floating-point literal? + if (chBase == 10) { + // with a decimal point? + if (sc.Match('.') + && ((!isSML && sc.chPrev == '_') + || IsADigit(sc.chPrev, chBase))) + break; + // with an exponent? (I) + if ((sc.Match('e') || sc.Match('E')) + && ((!isSML && (sc.chPrev == '.' || sc.chPrev == '_')) + || IsADigit(sc.chPrev, chBase))) + break; + // with an exponent? (II) + if (((!isSML && (sc.Match('+') || sc.Match('-'))) + || (isSML && sc.Match('~'))) + && (sc.chPrev == 'e' || sc.chPrev == 'E')) + break; + } + // it looks like we have run out of number + state2 = SCE_CAML_DEFAULT, advance = false; + break; + + case SCE_CAML_CHAR: + if (!isSML) { + // [try to] interpret as [additional] char literal char + if (sc.Match('\\')) { + chLit = 1; // (definitely IS a char literal) + if (sc.chPrev == '\\') + sc.ch = ' '; // (...\\') + // should we be terminating - one way or another? + } else if ((sc.Match('\'') && sc.chPrev != '\\') + || sc.atLineEnd) { + state2 = SCE_CAML_DEFAULT; + if (sc.Match('\'')) + chColor++; + else + sc.ChangeState(SCE_CAML_IDENTIFIER); + // ... maybe a char literal, maybe not + } else if (chLit < 1 && sc.currentPos - chToken >= 2) + sc.ChangeState(SCE_CAML_IDENTIFIER), advance = false; + break; + }/* else + // fall through for SML char literal (handle like string) */ + + case SCE_CAML_STRING: + // [try to] interpret as [additional] [SML char/] string literal char + if (isSML && sc.Match('\\') && sc.chPrev != '\\' && isspace(sc.chNext)) + state2 = SCE_CAML_WHITE; + else if (sc.Match('\\') && sc.chPrev == '\\') + sc.ch = ' '; // (...\\") + // should we be terminating - one way or another? + else if ((sc.Match('"') && sc.chPrev != '\\') + || (isSML && sc.atLineEnd)) { + state2 = SCE_CAML_DEFAULT; + if (sc.Match('"')) + chColor++; + } + break; + + case SCE_CAML_WHITE: + // [try to] interpret as [additional] SML embedded whitespace char + if (sc.Match('\\')) { + // style this puppy NOW... + state2 = SCE_CAML_STRING, sc.ch = ' ' /* (...\") */, chColor++, + styler.ColourTo(chColor, SCE_CAML_WHITE), styler.Flush(); + // ... then backtrack to determine original SML literal type + int p = chColor - 2; + for (; p >= 0 && styler.StyleAt(p) == SCE_CAML_WHITE; p--) ; + if (p >= 0) + state2 = static_cast(styler.StyleAt(p)); + // take care of state change NOW + sc.ChangeState(state2), state2 = -1; + } + break; + + case SCE_CAML_COMMENT: + case SCE_CAML_COMMENT1: + case SCE_CAML_COMMENT2: + case SCE_CAML_COMMENT3: + // we're IN a comment - does this start a NESTED comment? + if (sc.Match('(', '*')) + state2 = sc.state + 1, chToken = sc.currentPos, + sc.Forward(), sc.ch = ' ' /* (*)... */, nesting++; + // [try to] interpret as [additional] comment char + else if (sc.Match(')') && sc.chPrev == '*') { + if (nesting) + state2 = (sc.state & 0x0f) - 1, chToken = 0, nesting--; + else + state2 = SCE_CAML_DEFAULT; + chColor++; + // enable "magic" (read-only) comment AS REQUIRED + } else if (useMagic && sc.currentPos - chToken == 4 + && sc.Match('c') && sc.chPrev == 'r' && sc.GetRelative(-2) == '@') + sc.state |= 0x10; // (switch to read-only comment style) + break; + } + + // handle state change and char coloring AS REQUIRED + if (state2 >= 0) + styler.ColourTo(chColor, sc.state), sc.ChangeState(state2); + // move to next char UNLESS re-scanning current char + if (advance) + sc.Forward(); + } + + // do any required terminal char coloring (JIC) + sc.Complete(); +} + +#ifdef BUILD_AS_EXTERNAL_LEXER +static +#endif /* BUILD_AS_EXTERNAL_LEXER */ +void FoldCamlDoc( + unsigned int, int, + int, + WordList *[], + Accessor &) +{ +} + +static const char * const camlWordListDesc[] = { + "Keywords", // primary Objective Caml keywords + "Keywords2", // "optional" keywords (typically from Pervasives) + "Keywords3", // "optional" keywords (typically typenames) + 0 +}; + +#ifndef BUILD_AS_EXTERNAL_LEXER +LexerModule lmCaml(SCLEX_CAML, ColouriseCamlDoc, "caml", FoldCamlDoc, camlWordListDesc); +#endif /* BUILD_AS_EXTERNAL_LEXER */ diff --git a/scintilla/lexers/LexCmake.cxx b/ThirdLibs/scintilla/lexers/LexCmake.cxx similarity index 97% rename from scintilla/lexers/LexCmake.cxx rename to ThirdLibs/scintilla/lexers/LexCmake.cxx index 7242cfec..70e9dee9 100644 --- a/scintilla/lexers/LexCmake.cxx +++ b/ThirdLibs/scintilla/lexers/LexCmake.cxx @@ -1,461 +1,461 @@ -// Scintilla source code edit control -/** @file LexCmake.cxx - ** Lexer for Cmake - **/ -// Copyright 2007 by Cristian Adam -// based on the NSIS lexer -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static bool isCmakeNumber(char ch) -{ - return(ch >= '0' && ch <= '9'); -} - -static bool isCmakeChar(char ch) -{ - return(ch == '.' ) || (ch == '_' ) || isCmakeNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); -} - -static bool isCmakeLetter(char ch) -{ - return(ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); -} - -static bool CmakeNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler) -{ - int nNextLine = -1; - for ( unsigned int i = start; i < end; i++ ) { - char cNext = styler.SafeGetCharAt( i ); - if ( cNext == '\n' ) { - nNextLine = i+1; - break; - } - } - - if ( nNextLine == -1 ) // We never foudn the next line... - return false; - - for ( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ ) { - char cNext = styler.SafeGetCharAt( firstChar ); - if ( cNext == ' ' ) - continue; - if ( cNext == '\t' ) - continue; - if ( styler.Match(firstChar, "ELSE") || styler.Match(firstChar, "else")) - return true; - break; - } - - return false; -} - -static int calculateFoldCmake(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse) -{ - // If the word is too long, it is not what we are looking for - if ( end - start > 20 ) - return foldlevel; - - int newFoldlevel = foldlevel; - - char s[20]; // The key word we are looking for has atmost 13 characters - for (unsigned int i = 0; i < end - start + 1 && i < 19; i++) { - s[i] = static_cast( styler[ start + i ] ); - s[i + 1] = '\0'; - } - - if ( CompareCaseInsensitive(s, "IF") == 0 || CompareCaseInsensitive(s, "WHILE") == 0 - || CompareCaseInsensitive(s, "MACRO") == 0 || CompareCaseInsensitive(s, "FOREACH") == 0 - || CompareCaseInsensitive(s, "ELSEIF") == 0 ) - newFoldlevel++; - else if ( CompareCaseInsensitive(s, "ENDIF") == 0 || CompareCaseInsensitive(s, "ENDWHILE") == 0 - || CompareCaseInsensitive(s, "ENDMACRO") == 0 || CompareCaseInsensitive(s, "ENDFOREACH") == 0) - newFoldlevel--; - else if ( bElse && CompareCaseInsensitive(s, "ELSEIF") == 0 ) - newFoldlevel++; - else if ( bElse && CompareCaseInsensitive(s, "ELSE") == 0 ) - newFoldlevel++; - - return newFoldlevel; -} - -static int classifyWordCmake(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler ) -{ - char word[100] = {0}; - char lowercaseWord[100] = {0}; - - WordList &Commands = *keywordLists[0]; - WordList &Parameters = *keywordLists[1]; - WordList &UserDefined = *keywordLists[2]; - - for (unsigned int i = 0; i < end - start + 1 && i < 99; i++) { - word[i] = static_cast( styler[ start + i ] ); - lowercaseWord[i] = static_cast(tolower(word[i])); - } - - // Check for special words... - if ( CompareCaseInsensitive(word, "MACRO") == 0 || CompareCaseInsensitive(word, "ENDMACRO") == 0 ) - return SCE_CMAKE_MACRODEF; - - if ( CompareCaseInsensitive(word, "IF") == 0 || CompareCaseInsensitive(word, "ENDIF") == 0 ) - return SCE_CMAKE_IFDEFINEDEF; - - if ( CompareCaseInsensitive(word, "ELSEIF") == 0 || CompareCaseInsensitive(word, "ELSE") == 0 ) - return SCE_CMAKE_IFDEFINEDEF; - - if ( CompareCaseInsensitive(word, "WHILE") == 0 || CompareCaseInsensitive(word, "ENDWHILE") == 0) - return SCE_CMAKE_WHILEDEF; - - if ( CompareCaseInsensitive(word, "FOREACH") == 0 || CompareCaseInsensitive(word, "ENDFOREACH") == 0) - return SCE_CMAKE_FOREACHDEF; - - if ( Commands.InList(lowercaseWord) ) - return SCE_CMAKE_COMMANDS; - - if ( Parameters.InList(word) ) - return SCE_CMAKE_PARAMETERS; - - - if ( UserDefined.InList(word) ) - return SCE_CMAKE_USERDEFINED; - - if ( strlen(word) > 3 ) { - if ( word[1] == '{' && word[strlen(word)-1] == '}' ) - return SCE_CMAKE_VARIABLE; - } - - // To check for numbers - if ( isCmakeNumber( word[0] ) ) { - bool bHasSimpleCmakeNumber = true; - for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) { - if ( !isCmakeNumber( word[j] ) ) { - bHasSimpleCmakeNumber = false; - break; - } - } - - if ( bHasSimpleCmakeNumber ) - return SCE_CMAKE_NUMBER; - } - - return SCE_CMAKE_DEFAULT; -} - -static void ColouriseCmakeDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) -{ - int state = SCE_CMAKE_DEFAULT; - if ( startPos > 0 ) - state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox - - styler.StartAt( startPos ); - styler.GetLine( startPos ); - - unsigned int nLengthDoc = startPos + length; - styler.StartSegment( startPos ); - - char cCurrChar; - bool bVarInString = false; - bool bClassicVarInString = false; - - unsigned int i; - for ( i = startPos; i < nLengthDoc; i++ ) { - cCurrChar = styler.SafeGetCharAt( i ); - char cNextChar = styler.SafeGetCharAt(i+1); - - switch (state) { - case SCE_CMAKE_DEFAULT: - if ( cCurrChar == '#' ) { // we have a comment line - styler.ColourTo(i-1, state ); - state = SCE_CMAKE_COMMENT; - break; - } - if ( cCurrChar == '"' ) { - styler.ColourTo(i-1, state ); - state = SCE_CMAKE_STRINGDQ; - bVarInString = false; - bClassicVarInString = false; - break; - } - if ( cCurrChar == '\'' ) { - styler.ColourTo(i-1, state ); - state = SCE_CMAKE_STRINGRQ; - bVarInString = false; - bClassicVarInString = false; - break; - } - if ( cCurrChar == '`' ) { - styler.ColourTo(i-1, state ); - state = SCE_CMAKE_STRINGLQ; - bVarInString = false; - bClassicVarInString = false; - break; - } - - // CMake Variable - if ( cCurrChar == '$' || isCmakeChar(cCurrChar)) { - styler.ColourTo(i-1,state); - state = SCE_CMAKE_VARIABLE; - - // If it is a number, we must check and set style here first... - if ( isCmakeNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) ) - styler.ColourTo( i, SCE_CMAKE_NUMBER); - - break; - } - - break; - case SCE_CMAKE_COMMENT: - if ( cNextChar == '\n' || cNextChar == '\r' ) { - // Special case: - if ( cCurrChar == '\\' ) { - styler.ColourTo(i-2,state); - styler.ColourTo(i,SCE_CMAKE_DEFAULT); - } - else { - styler.ColourTo(i,state); - state = SCE_CMAKE_DEFAULT; - } - } - break; - case SCE_CMAKE_STRINGDQ: - case SCE_CMAKE_STRINGLQ: - case SCE_CMAKE_STRINGRQ: - - if ( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' ) - break; // Ignore the next character, even if it is a quote of some sort - - if ( cCurrChar == '"' && state == SCE_CMAKE_STRINGDQ ) { - styler.ColourTo(i,state); - state = SCE_CMAKE_DEFAULT; - break; - } - - if ( cCurrChar == '`' && state == SCE_CMAKE_STRINGLQ ) { - styler.ColourTo(i,state); - state = SCE_CMAKE_DEFAULT; - break; - } - - if ( cCurrChar == '\'' && state == SCE_CMAKE_STRINGRQ ) { - styler.ColourTo(i,state); - state = SCE_CMAKE_DEFAULT; - break; - } - - if ( cNextChar == '\r' || cNextChar == '\n' ) { - int nCurLine = styler.GetLine(i+1); - int nBack = i; - // We need to check if the previous line has a \ in it... - bool bNextLine = false; - - while ( nBack > 0 ) { - if ( styler.GetLine(nBack) != nCurLine ) - break; - - char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here - - if ( cTemp == '\\' ) { - bNextLine = true; - break; - } - if ( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' ) - break; - - nBack--; - } - - if ( bNextLine ) { - styler.ColourTo(i+1,state); - } - if ( bNextLine == false ) { - styler.ColourTo(i,state); - state = SCE_CMAKE_DEFAULT; - } - } - break; - - case SCE_CMAKE_VARIABLE: - - // CMake Variable: - if ( cCurrChar == '$' ) - state = SCE_CMAKE_DEFAULT; - else if ( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) ) - state = SCE_CMAKE_DEFAULT; - else if ( (isCmakeChar(cCurrChar) && !isCmakeChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' ) { - state = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler ); - styler.ColourTo( i, state); - state = SCE_CMAKE_DEFAULT; - } - else if ( !isCmakeChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' ) { - if ( classifyWordCmake( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_CMAKE_NUMBER ) - styler.ColourTo( i-1, SCE_CMAKE_NUMBER ); - - state = SCE_CMAKE_DEFAULT; - - if ( cCurrChar == '"' ) { - state = SCE_CMAKE_STRINGDQ; - bVarInString = false; - bClassicVarInString = false; - } - else if ( cCurrChar == '`' ) { - state = SCE_CMAKE_STRINGLQ; - bVarInString = false; - bClassicVarInString = false; - } - else if ( cCurrChar == '\'' ) { - state = SCE_CMAKE_STRINGRQ; - bVarInString = false; - bClassicVarInString = false; - } - else if ( cCurrChar == '#' ) { - state = SCE_CMAKE_COMMENT; - } - } - break; - } - - if ( state == SCE_CMAKE_COMMENT) { - styler.ColourTo(i,state); - } - else if ( state == SCE_CMAKE_STRINGDQ || state == SCE_CMAKE_STRINGLQ || state == SCE_CMAKE_STRINGRQ ) { - bool bIngoreNextDollarSign = false; - - if ( bVarInString && cCurrChar == '$' ) { - bVarInString = false; - bIngoreNextDollarSign = true; - } - else if ( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) ) { - styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR); - bVarInString = false; - bIngoreNextDollarSign = false; - } - - else if ( bVarInString && !isCmakeChar(cNextChar) ) { - int nWordState = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler); - if ( nWordState == SCE_CMAKE_VARIABLE ) - styler.ColourTo( i, SCE_CMAKE_STRINGVAR); - bVarInString = false; - } - // Covers "${TEST}..." - else if ( bClassicVarInString && cNextChar == '}' ) { - styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR); - bClassicVarInString = false; - } - - // Start of var in string - if ( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' ) { - styler.ColourTo( i-1, state); - bClassicVarInString = true; - bVarInString = false; - } - else if ( !bIngoreNextDollarSign && cCurrChar == '$' ) { - styler.ColourTo( i-1, state); - bVarInString = true; - bClassicVarInString = false; - } - } - } - - // Colourise remaining document - styler.ColourTo(nLengthDoc-1,state); -} - -static void FoldCmakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) -{ - // No folding enabled, no reason to continue... - if ( styler.GetPropertyInt("fold") == 0 ) - return; - - bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1; - - int lineCurrent = styler.GetLine(startPos); - unsigned int safeStartPos = styler.LineStart( lineCurrent ); - - bool bArg1 = true; - int nWordStart = -1; - - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelNext = levelCurrent; - - for (unsigned int i = safeStartPos; i < startPos + length; i++) { - char chCurr = styler.SafeGetCharAt(i); - - if ( bArg1 ) { - if ( nWordStart == -1 && (isCmakeLetter(chCurr)) ) { - nWordStart = i; - } - else if ( isCmakeLetter(chCurr) == false && nWordStart > -1 ) { - int newLevel = calculateFoldCmake( nWordStart, i-1, levelNext, styler, foldAtElse); - - if ( newLevel == levelNext ) { - if ( foldAtElse ) { - if ( CmakeNextLineHasElse(i, startPos + length, styler) ) - levelNext--; - } - } - else - levelNext = newLevel; - bArg1 = false; - } - } - - if ( chCurr == '\n' ) { - if ( bArg1 && foldAtElse) { - if ( CmakeNextLineHasElse(i, startPos + length, styler) ) - levelNext--; - } - - // If we are on a new line... - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - if (levelUse < levelNext ) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) - styler.SetLevel(lineCurrent, lev); - - lineCurrent++; - levelCurrent = levelNext; - bArg1 = true; // New line, lets look at first argument again - nWordStart = -1; - } - } - - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) - styler.SetLevel(lineCurrent, lev); -} - -static const char * const cmakeWordLists[] = { - "Commands", - "Parameters", - "UserDefined", - 0, - 0,}; - -LexerModule lmCmake(SCLEX_CMAKE, ColouriseCmakeDoc, "cmake", FoldCmakeDoc, cmakeWordLists); +// Scintilla source code edit control +/** @file LexCmake.cxx + ** Lexer for Cmake + **/ +// Copyright 2007 by Cristian Adam +// based on the NSIS lexer +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static bool isCmakeNumber(char ch) +{ + return(ch >= '0' && ch <= '9'); +} + +static bool isCmakeChar(char ch) +{ + return(ch == '.' ) || (ch == '_' ) || isCmakeNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); +} + +static bool isCmakeLetter(char ch) +{ + return(ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); +} + +static bool CmakeNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler) +{ + int nNextLine = -1; + for ( unsigned int i = start; i < end; i++ ) { + char cNext = styler.SafeGetCharAt( i ); + if ( cNext == '\n' ) { + nNextLine = i+1; + break; + } + } + + if ( nNextLine == -1 ) // We never foudn the next line... + return false; + + for ( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ ) { + char cNext = styler.SafeGetCharAt( firstChar ); + if ( cNext == ' ' ) + continue; + if ( cNext == '\t' ) + continue; + if ( styler.Match(firstChar, "ELSE") || styler.Match(firstChar, "else")) + return true; + break; + } + + return false; +} + +static int calculateFoldCmake(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse) +{ + // If the word is too long, it is not what we are looking for + if ( end - start > 20 ) + return foldlevel; + + int newFoldlevel = foldlevel; + + char s[20]; // The key word we are looking for has atmost 13 characters + for (unsigned int i = 0; i < end - start + 1 && i < 19; i++) { + s[i] = static_cast( styler[ start + i ] ); + s[i + 1] = '\0'; + } + + if ( CompareCaseInsensitive(s, "IF") == 0 || CompareCaseInsensitive(s, "WHILE") == 0 + || CompareCaseInsensitive(s, "MACRO") == 0 || CompareCaseInsensitive(s, "FOREACH") == 0 + || CompareCaseInsensitive(s, "ELSEIF") == 0 ) + newFoldlevel++; + else if ( CompareCaseInsensitive(s, "ENDIF") == 0 || CompareCaseInsensitive(s, "ENDWHILE") == 0 + || CompareCaseInsensitive(s, "ENDMACRO") == 0 || CompareCaseInsensitive(s, "ENDFOREACH") == 0) + newFoldlevel--; + else if ( bElse && CompareCaseInsensitive(s, "ELSEIF") == 0 ) + newFoldlevel++; + else if ( bElse && CompareCaseInsensitive(s, "ELSE") == 0 ) + newFoldlevel++; + + return newFoldlevel; +} + +static int classifyWordCmake(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler ) +{ + char word[100] = {0}; + char lowercaseWord[100] = {0}; + + WordList &Commands = *keywordLists[0]; + WordList &Parameters = *keywordLists[1]; + WordList &UserDefined = *keywordLists[2]; + + for (unsigned int i = 0; i < end - start + 1 && i < 99; i++) { + word[i] = static_cast( styler[ start + i ] ); + lowercaseWord[i] = static_cast(tolower(word[i])); + } + + // Check for special words... + if ( CompareCaseInsensitive(word, "MACRO") == 0 || CompareCaseInsensitive(word, "ENDMACRO") == 0 ) + return SCE_CMAKE_MACRODEF; + + if ( CompareCaseInsensitive(word, "IF") == 0 || CompareCaseInsensitive(word, "ENDIF") == 0 ) + return SCE_CMAKE_IFDEFINEDEF; + + if ( CompareCaseInsensitive(word, "ELSEIF") == 0 || CompareCaseInsensitive(word, "ELSE") == 0 ) + return SCE_CMAKE_IFDEFINEDEF; + + if ( CompareCaseInsensitive(word, "WHILE") == 0 || CompareCaseInsensitive(word, "ENDWHILE") == 0) + return SCE_CMAKE_WHILEDEF; + + if ( CompareCaseInsensitive(word, "FOREACH") == 0 || CompareCaseInsensitive(word, "ENDFOREACH") == 0) + return SCE_CMAKE_FOREACHDEF; + + if ( Commands.InList(lowercaseWord) ) + return SCE_CMAKE_COMMANDS; + + if ( Parameters.InList(word) ) + return SCE_CMAKE_PARAMETERS; + + + if ( UserDefined.InList(word) ) + return SCE_CMAKE_USERDEFINED; + + if ( strlen(word) > 3 ) { + if ( word[1] == '{' && word[strlen(word)-1] == '}' ) + return SCE_CMAKE_VARIABLE; + } + + // To check for numbers + if ( isCmakeNumber( word[0] ) ) { + bool bHasSimpleCmakeNumber = true; + for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) { + if ( !isCmakeNumber( word[j] ) ) { + bHasSimpleCmakeNumber = false; + break; + } + } + + if ( bHasSimpleCmakeNumber ) + return SCE_CMAKE_NUMBER; + } + + return SCE_CMAKE_DEFAULT; +} + +static void ColouriseCmakeDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) +{ + int state = SCE_CMAKE_DEFAULT; + if ( startPos > 0 ) + state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox + + styler.StartAt( startPos ); + styler.GetLine( startPos ); + + unsigned int nLengthDoc = startPos + length; + styler.StartSegment( startPos ); + + char cCurrChar; + bool bVarInString = false; + bool bClassicVarInString = false; + + unsigned int i; + for ( i = startPos; i < nLengthDoc; i++ ) { + cCurrChar = styler.SafeGetCharAt( i ); + char cNextChar = styler.SafeGetCharAt(i+1); + + switch (state) { + case SCE_CMAKE_DEFAULT: + if ( cCurrChar == '#' ) { // we have a comment line + styler.ColourTo(i-1, state ); + state = SCE_CMAKE_COMMENT; + break; + } + if ( cCurrChar == '"' ) { + styler.ColourTo(i-1, state ); + state = SCE_CMAKE_STRINGDQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + if ( cCurrChar == '\'' ) { + styler.ColourTo(i-1, state ); + state = SCE_CMAKE_STRINGRQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + if ( cCurrChar == '`' ) { + styler.ColourTo(i-1, state ); + state = SCE_CMAKE_STRINGLQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + + // CMake Variable + if ( cCurrChar == '$' || isCmakeChar(cCurrChar)) { + styler.ColourTo(i-1,state); + state = SCE_CMAKE_VARIABLE; + + // If it is a number, we must check and set style here first... + if ( isCmakeNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) ) + styler.ColourTo( i, SCE_CMAKE_NUMBER); + + break; + } + + break; + case SCE_CMAKE_COMMENT: + if ( cNextChar == '\n' || cNextChar == '\r' ) { + // Special case: + if ( cCurrChar == '\\' ) { + styler.ColourTo(i-2,state); + styler.ColourTo(i,SCE_CMAKE_DEFAULT); + } + else { + styler.ColourTo(i,state); + state = SCE_CMAKE_DEFAULT; + } + } + break; + case SCE_CMAKE_STRINGDQ: + case SCE_CMAKE_STRINGLQ: + case SCE_CMAKE_STRINGRQ: + + if ( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' ) + break; // Ignore the next character, even if it is a quote of some sort + + if ( cCurrChar == '"' && state == SCE_CMAKE_STRINGDQ ) { + styler.ColourTo(i,state); + state = SCE_CMAKE_DEFAULT; + break; + } + + if ( cCurrChar == '`' && state == SCE_CMAKE_STRINGLQ ) { + styler.ColourTo(i,state); + state = SCE_CMAKE_DEFAULT; + break; + } + + if ( cCurrChar == '\'' && state == SCE_CMAKE_STRINGRQ ) { + styler.ColourTo(i,state); + state = SCE_CMAKE_DEFAULT; + break; + } + + if ( cNextChar == '\r' || cNextChar == '\n' ) { + int nCurLine = styler.GetLine(i+1); + int nBack = i; + // We need to check if the previous line has a \ in it... + bool bNextLine = false; + + while ( nBack > 0 ) { + if ( styler.GetLine(nBack) != nCurLine ) + break; + + char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here + + if ( cTemp == '\\' ) { + bNextLine = true; + break; + } + if ( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' ) + break; + + nBack--; + } + + if ( bNextLine ) { + styler.ColourTo(i+1,state); + } + if ( bNextLine == false ) { + styler.ColourTo(i,state); + state = SCE_CMAKE_DEFAULT; + } + } + break; + + case SCE_CMAKE_VARIABLE: + + // CMake Variable: + if ( cCurrChar == '$' ) + state = SCE_CMAKE_DEFAULT; + else if ( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) ) + state = SCE_CMAKE_DEFAULT; + else if ( (isCmakeChar(cCurrChar) && !isCmakeChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' ) { + state = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler ); + styler.ColourTo( i, state); + state = SCE_CMAKE_DEFAULT; + } + else if ( !isCmakeChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' ) { + if ( classifyWordCmake( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_CMAKE_NUMBER ) + styler.ColourTo( i-1, SCE_CMAKE_NUMBER ); + + state = SCE_CMAKE_DEFAULT; + + if ( cCurrChar == '"' ) { + state = SCE_CMAKE_STRINGDQ; + bVarInString = false; + bClassicVarInString = false; + } + else if ( cCurrChar == '`' ) { + state = SCE_CMAKE_STRINGLQ; + bVarInString = false; + bClassicVarInString = false; + } + else if ( cCurrChar == '\'' ) { + state = SCE_CMAKE_STRINGRQ; + bVarInString = false; + bClassicVarInString = false; + } + else if ( cCurrChar == '#' ) { + state = SCE_CMAKE_COMMENT; + } + } + break; + } + + if ( state == SCE_CMAKE_COMMENT) { + styler.ColourTo(i,state); + } + else if ( state == SCE_CMAKE_STRINGDQ || state == SCE_CMAKE_STRINGLQ || state == SCE_CMAKE_STRINGRQ ) { + bool bIngoreNextDollarSign = false; + + if ( bVarInString && cCurrChar == '$' ) { + bVarInString = false; + bIngoreNextDollarSign = true; + } + else if ( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) ) { + styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR); + bVarInString = false; + bIngoreNextDollarSign = false; + } + + else if ( bVarInString && !isCmakeChar(cNextChar) ) { + int nWordState = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler); + if ( nWordState == SCE_CMAKE_VARIABLE ) + styler.ColourTo( i, SCE_CMAKE_STRINGVAR); + bVarInString = false; + } + // Covers "${TEST}..." + else if ( bClassicVarInString && cNextChar == '}' ) { + styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR); + bClassicVarInString = false; + } + + // Start of var in string + if ( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' ) { + styler.ColourTo( i-1, state); + bClassicVarInString = true; + bVarInString = false; + } + else if ( !bIngoreNextDollarSign && cCurrChar == '$' ) { + styler.ColourTo( i-1, state); + bVarInString = true; + bClassicVarInString = false; + } + } + } + + // Colourise remaining document + styler.ColourTo(nLengthDoc-1,state); +} + +static void FoldCmakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) +{ + // No folding enabled, no reason to continue... + if ( styler.GetPropertyInt("fold") == 0 ) + return; + + bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1; + + int lineCurrent = styler.GetLine(startPos); + unsigned int safeStartPos = styler.LineStart( lineCurrent ); + + bool bArg1 = true; + int nWordStart = -1; + + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelNext = levelCurrent; + + for (unsigned int i = safeStartPos; i < startPos + length; i++) { + char chCurr = styler.SafeGetCharAt(i); + + if ( bArg1 ) { + if ( nWordStart == -1 && (isCmakeLetter(chCurr)) ) { + nWordStart = i; + } + else if ( isCmakeLetter(chCurr) == false && nWordStart > -1 ) { + int newLevel = calculateFoldCmake( nWordStart, i-1, levelNext, styler, foldAtElse); + + if ( newLevel == levelNext ) { + if ( foldAtElse ) { + if ( CmakeNextLineHasElse(i, startPos + length, styler) ) + levelNext--; + } + } + else + levelNext = newLevel; + bArg1 = false; + } + } + + if ( chCurr == '\n' ) { + if ( bArg1 && foldAtElse) { + if ( CmakeNextLineHasElse(i, startPos + length, styler) ) + levelNext--; + } + + // If we are on a new line... + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (levelUse < levelNext ) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) + styler.SetLevel(lineCurrent, lev); + + lineCurrent++; + levelCurrent = levelNext; + bArg1 = true; // New line, lets look at first argument again + nWordStart = -1; + } + } + + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) + styler.SetLevel(lineCurrent, lev); +} + +static const char * const cmakeWordLists[] = { + "Commands", + "Parameters", + "UserDefined", + 0, + 0,}; + +LexerModule lmCmake(SCLEX_CMAKE, ColouriseCmakeDoc, "cmake", FoldCmakeDoc, cmakeWordLists); diff --git a/scintilla/lexers/LexCoffeeScript.cxx b/ThirdLibs/scintilla/lexers/LexCoffeeScript.cxx similarity index 96% rename from scintilla/lexers/LexCoffeeScript.cxx rename to ThirdLibs/scintilla/lexers/LexCoffeeScript.cxx index 3e517092..96d5d2d9 100644 --- a/scintilla/lexers/LexCoffeeScript.cxx +++ b/ThirdLibs/scintilla/lexers/LexCoffeeScript.cxx @@ -1,571 +1,571 @@ -// Scintilla source code edit control -/** @file LexCoffeeScript.cxx - ** Lexer for CoffeeScript. - **/ -// Copyright 1998-2011 by Neil Hodgson -// Based on the Scintilla C++ Lexer -// Written by Eric Promislow in 2011 for the Komodo IDE -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "Platform.h" -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static bool IsSpaceEquiv(int state) { - return (state <= SCE_C_COMMENTDOC - // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE - || state == SCE_C_COMMENTLINEDOC - || state == SCE_C_COMMENTDOCKEYWORD - || state == SCE_C_COMMENTDOCKEYWORDERROR - || state == SCE_COFFEESCRIPT_COMMENTBLOCK - || state == SCE_COFFEESCRIPT_VERBOSE_REGEX - || state == SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT - || state == SCE_C_WORD - || state == SCE_C_REGEX); -} - -// Preconditions: sc.currentPos points to a character after '+' or '-'. -// The test for pos reaching 0 should be redundant, -// and is in only for safety measures. -// Limitation: this code will give the incorrect answer for code like -// a = b+++/ptn/... -// Putting a space between the '++' post-inc operator and the '+' binary op -// fixes this, and is highly recommended for readability anyway. -static bool FollowsPostfixOperator(StyleContext &sc, Accessor &styler) { - int pos = (int) sc.currentPos; - while (--pos > 0) { - char ch = styler[pos]; - if (ch == '+' || ch == '-') { - return styler[pos - 1] == ch; - } - } - return false; -} - -static bool followsReturnKeyword(StyleContext &sc, Accessor &styler) { - // Don't look at styles, so no need to flush. - int pos = (int) sc.currentPos; - int currentLine = styler.GetLine(pos); - int lineStartPos = styler.LineStart(currentLine); - char ch; - while (--pos > lineStartPos) { - ch = styler.SafeGetCharAt(pos); - if (ch != ' ' && ch != '\t') { - break; - } - } - const char *retBack = "nruter"; - const char *s = retBack; - while (*s - && pos >= lineStartPos - && styler.SafeGetCharAt(pos) == *s) { - s++; - pos--; - } - return !*s; -} - -static void ColouriseCoffeeScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - - // property styling.within.preprocessor - // For C++ code, determines whether all preprocessor code is styled in the preprocessor style (0, the default) - // or only from the initial # to the end of the command word(1). - bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; - - CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-"); - CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-"); - - CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); - - CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); - - // property lexer.cpp.allow.dollars - // Set to 0 to disallow the '$' character in identifiers with the cpp lexer. - if (styler.GetPropertyInt("lexer.cpp.allow.dollars", 1) != 0) { - setWordStart.Add('$'); - setWord.Add('$'); - } - - int chPrevNonWhite = ' '; - int visibleChars = 0; - bool lastWordWasUUID = false; - int styleBeforeDCKeyword = SCE_C_DEFAULT; - bool continuationLine = false; - bool isIncludePreprocessor = false; - - if (initStyle == SCE_C_PREPROCESSOR) { - // Set continuationLine if last character of previous line is '\' - int lineCurrent = styler.GetLine(startPos); - if (lineCurrent > 0) { - int chBack = styler.SafeGetCharAt(startPos-1, 0); - int chBack2 = styler.SafeGetCharAt(startPos-2, 0); - int lineEndChar = '!'; - if (chBack2 == '\r' && chBack == '\n') { - lineEndChar = styler.SafeGetCharAt(startPos-3, 0); - } else if (chBack == '\n' || chBack == '\r') { - lineEndChar = chBack2; - } - continuationLine = lineEndChar == '\\'; - } - } - - // look back to set chPrevNonWhite properly for better regex colouring - int endPos = startPos + length; - if (startPos > 0) { - unsigned int back = startPos; - styler.Flush(); - while (back > 0 && IsSpaceEquiv(styler.StyleAt(--back))) - ; - if (styler.StyleAt(back) == SCE_C_OPERATOR) { - chPrevNonWhite = styler.SafeGetCharAt(back); - } - if (startPos != back) { - initStyle = styler.StyleAt(back); - } - startPos = back; - } - - StyleContext sc(startPos, endPos - startPos, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.atLineStart) { - // Reset states to begining of colourise so no surprises - // if different sets of lines lexed. - visibleChars = 0; - lastWordWasUUID = false; - isIncludePreprocessor = false; - } - - // Handle line continuation generically. - if (sc.ch == '\\') { - if (sc.chNext == '\n' || sc.chNext == '\r') { - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - sc.Forward(); - } - continuationLine = true; - continue; - } - } - - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_C_OPERATOR: - sc.SetState(SCE_C_DEFAULT); - break; - case SCE_C_NUMBER: - // We accept almost anything because of hex. and number suffixes - if (!setWord.Contains(sc.ch)) { - sc.SetState(SCE_C_DEFAULT); - } - break; - case SCE_C_IDENTIFIER: - if (!setWord.Contains(sc.ch) || (sc.ch == '.') || (sc.ch == '$')) { - char s[1000]; - sc.GetCurrent(s, sizeof(s)); - if (keywords.InList(s)) { - lastWordWasUUID = strcmp(s, "uuid") == 0; - sc.ChangeState(SCE_C_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_C_WORD2); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_C_GLOBALCLASS); - } - sc.SetState(SCE_C_DEFAULT); - } - break; - case SCE_C_PREPROCESSOR: - if (sc.atLineStart && !continuationLine) { - sc.SetState(SCE_C_DEFAULT); - } else if (stylingWithinPreprocessor) { - if (IsASpace(sc.ch)) { - sc.SetState(SCE_C_DEFAULT); - } - } else { - if (sc.Match('/', '*') || sc.Match('/', '/')) { - sc.SetState(SCE_C_DEFAULT); - } - } - break; - case SCE_C_COMMENT: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT); - } - break; - case SCE_C_COMMENTDOC: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_C_COMMENTDOC; - sc.SetState(SCE_C_COMMENTDOCKEYWORD); - } - } - break; - case SCE_C_COMMENTLINE: - if (sc.atLineStart) { - sc.SetState(SCE_C_DEFAULT); - } - break; - case SCE_C_COMMENTLINEDOC: - if (sc.atLineStart) { - sc.SetState(SCE_C_DEFAULT); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC; - sc.SetState(SCE_C_COMMENTDOCKEYWORD); - } - } - break; - case SCE_C_COMMENTDOCKEYWORD: - if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) { - sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); - sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT); - } else if (!setDoxygen.Contains(sc.ch)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { - sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); - } - sc.SetState(styleBeforeDCKeyword); - } - break; - case SCE_C_STRING: - if (isIncludePreprocessor) { - if (sc.ch == '>') { - sc.ForwardSetState(SCE_C_DEFAULT); - isIncludePreprocessor = false; - } - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_C_DEFAULT); - } - break; - case SCE_C_CHARACTER: - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_C_DEFAULT); - } - break; - case SCE_C_REGEX: - if (sc.atLineStart) { - sc.SetState(SCE_C_DEFAULT); - } else if (sc.ch == '/') { - sc.Forward(); - while ((sc.ch < 0x80) && islower(sc.ch)) - sc.Forward(); // gobble regex flags - sc.SetState(SCE_C_DEFAULT); - } else if (sc.ch == '\\') { - // Gobble up the quoted character - if (sc.chNext == '\\' || sc.chNext == '/') { - sc.Forward(); - } - } - break; - case SCE_C_STRINGEOL: - if (sc.atLineStart) { - sc.SetState(SCE_C_DEFAULT); - } - break; - case SCE_C_VERBATIM: - if (sc.ch == '\"') { - if (sc.chNext == '\"') { - sc.Forward(); - } else { - sc.ForwardSetState(SCE_C_DEFAULT); - } - } - break; - case SCE_C_UUID: - if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { - sc.SetState(SCE_C_DEFAULT); - } - break; - case SCE_COFFEESCRIPT_COMMENTBLOCK: - if (sc.Match("###")) { - sc.ChangeState(SCE_C_COMMENT); - sc.Forward(); - sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT); - } else if (sc.ch == '\\') { - sc.Forward(); - } - break; - case SCE_COFFEESCRIPT_VERBOSE_REGEX: - if (sc.Match("///")) { - sc.Forward(); - sc.Forward(); - sc.ChangeState(SCE_C_REGEX); - sc.ForwardSetState(SCE_C_DEFAULT); - } else if (sc.Match('#')) { - sc.ChangeState(SCE_C_REGEX); - sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT); - } else if (sc.ch == '\\') { - sc.Forward(); - } - break; - case SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT: - if (sc.atLineStart) { - sc.ChangeState(SCE_C_COMMENT); - sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX); - } - break; - } - - // Determine if a new state should be entered. - if (sc.state == SCE_C_DEFAULT) { - if (sc.Match('@', '\"')) { - sc.SetState(SCE_C_VERBATIM); - sc.Forward(); - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - if (lastWordWasUUID) { - sc.SetState(SCE_C_UUID); - lastWordWasUUID = false; - } else { - sc.SetState(SCE_C_NUMBER); - } - } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@') || (sc.ch == '$')) { - if (lastWordWasUUID) { - sc.SetState(SCE_C_UUID); - lastWordWasUUID = false; - } else { - sc.SetState(SCE_C_IDENTIFIER); - } - } else if (sc.Match('/', '*')) { - if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style - sc.SetState(SCE_C_COMMENTDOC); - } else { - sc.SetState(SCE_C_COMMENT); - } - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match("///")) { - sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX); - } else if (sc.ch == '/' - && (setOKBeforeRE.Contains(chPrevNonWhite) - || followsReturnKeyword(sc, styler)) - && (!setCouldBePostOp.Contains(chPrevNonWhite) - || !FollowsPostfixOperator(sc, styler))) { - sc.SetState(SCE_C_REGEX); // JavaScript's RegEx - } else if (sc.ch == '\"') { - sc.SetState(SCE_C_STRING); - isIncludePreprocessor = false; // ensure that '>' won't end the string - } else if (isIncludePreprocessor && sc.ch == '<') { - sc.SetState(SCE_C_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_C_CHARACTER); - } else if (sc.ch == '#') { - if (sc.Match("###")) { - sc.SetState(SCE_COFFEESCRIPT_COMMENTBLOCK); - } else { - sc.SetState(SCE_C_COMMENTLINE); - } - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_C_OPERATOR); - } - } - - if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) { - chPrevNonWhite = sc.ch; - visibleChars++; - } - continuationLine = false; - } - // Change temporary coffeescript states into standard C ones. - switch (sc.state) { - case SCE_COFFEESCRIPT_COMMENTBLOCK: - sc.ChangeState(SCE_C_COMMENT); - break; - case SCE_COFFEESCRIPT_VERBOSE_REGEX: - sc.ChangeState(SCE_C_REGEX); - break; - case SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT: - sc.ChangeState(SCE_C_COMMENTLINE); - break; - } - sc.Complete(); -} - -static bool IsCommentLine(int line, Accessor &styler) { - int pos = styler.LineStart(line); - int eol_pos = styler.LineStart(line + 1) - 1; - for (int i = pos; i < eol_pos; i++) { - char ch = styler[i]; - if (ch == '#') - return true; - else if (ch == '/' - && i < eol_pos - 1 - && styler[i + 1] == '*') - return true; - else if (ch != ' ' && ch != '\t') - return false; - } - return false; -} - -static void FoldCoffeeScriptDoc(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) { - // A simplified version of FoldPyDoc - const int maxPos = startPos + length; - const int maxLines = styler.GetLine(maxPos - 1); // Requested last line - const int docLines = styler.GetLine(styler.Length() - 1); // Available last line - - // property fold.coffeescript.comment - const bool foldComment = styler.GetPropertyInt("fold.coffeescript.comment") != 0; - - const bool foldCompact = styler.GetPropertyInt("fold.compact") != 0; - - // Backtrack to previous non-blank line so we can determine indent level - // for any white space lines - // and so we can fix any preceding fold level (which is why we go back - // at least one line in all cases) - int spaceFlags = 0; - int lineCurrent = styler.GetLine(startPos); - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); - while (lineCurrent > 0) { - lineCurrent--; - indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); - if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) - && !IsCommentLine(lineCurrent, styler)) - break; - } - int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; - - // Set up initial loop state - int prevComment = 0; - if (lineCurrent >= 1) - prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler); - - // Process all characters to end of requested range - // or comment that hangs over the end of the range. Cap processing in all cases - // to end of document (in case of comment at end). - while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevComment)) { - - // Gather info - int lev = indentCurrent; - int lineNext = lineCurrent + 1; - int indentNext = indentCurrent; - if (lineNext <= docLines) { - // Information about next line is only available if not at end of document - indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); - } - const int comment = foldComment && IsCommentLine(lineCurrent, styler); - const int comment_start = (comment && !prevComment && (lineNext <= docLines) && - IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE)); - const int comment_continue = (comment && prevComment); - if (!comment) - indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; - if (indentNext & SC_FOLDLEVELWHITEFLAG) - indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; - - if (comment_start) { - // Place fold point at start of a block of comments - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (comment_continue) { - // Add level to rest of lines in the block - lev = lev + 1; - } - - // Skip past any blank lines for next indent level info; we skip also - // comments (all comments, not just those starting in column 0) - // which effectively folds them into surrounding code rather - // than screwing up folding. - - while ((lineNext < docLines) && - ((indentNext & SC_FOLDLEVELWHITEFLAG) || - (lineNext <= docLines && IsCommentLine(lineNext, styler)))) { - - lineNext++; - indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); - } - - const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK; - const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments); - - // Now set all the indent levels on the lines we skipped - // Do this from end to start. Once we encounter one line - // which is indented more than the line after the end of - // the comment-block, use the level of the block before - - int skipLine = lineNext; - int skipLevel = levelAfterComments; - - while (--skipLine > lineCurrent) { - int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL); - - if (foldCompact) { - if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments) - skipLevel = levelBeforeComments; - - int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; - - styler.SetLevel(skipLine, skipLevel | whiteFlag); - } else { - if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments && - !(skipLineIndent & SC_FOLDLEVELWHITEFLAG) && - !IsCommentLine(skipLine, styler)) - skipLevel = levelBeforeComments; - - styler.SetLevel(skipLine, skipLevel); - } - } - - // Set fold header on non-comment line - if (!comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) - lev |= SC_FOLDLEVELHEADERFLAG; - } - - // Keep track of block comment state of previous line - prevComment = comment_start || comment_continue; - - // Set fold level for this line and move to next line - styler.SetLevel(lineCurrent, lev); - indentCurrent = indentNext; - lineCurrent = lineNext; - } -} - -static const char *const csWordLists[] = { - "Keywords", - 0, -}; - -LexerModule lmCoffeeScript(SCLEX_COFFEESCRIPT, ColouriseCoffeeScriptDoc, "coffeescript", FoldCoffeeScriptDoc, csWordLists); +// Scintilla source code edit control +/** @file LexCoffeeScript.cxx + ** Lexer for CoffeeScript. + **/ +// Copyright 1998-2011 by Neil Hodgson +// Based on the Scintilla C++ Lexer +// Written by Eric Promislow in 2011 for the Komodo IDE +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static bool IsSpaceEquiv(int state) { + return (state <= SCE_C_COMMENTDOC + // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE + || state == SCE_C_COMMENTLINEDOC + || state == SCE_C_COMMENTDOCKEYWORD + || state == SCE_C_COMMENTDOCKEYWORDERROR + || state == SCE_COFFEESCRIPT_COMMENTBLOCK + || state == SCE_COFFEESCRIPT_VERBOSE_REGEX + || state == SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT + || state == SCE_C_WORD + || state == SCE_C_REGEX); +} + +// Preconditions: sc.currentPos points to a character after '+' or '-'. +// The test for pos reaching 0 should be redundant, +// and is in only for safety measures. +// Limitation: this code will give the incorrect answer for code like +// a = b+++/ptn/... +// Putting a space between the '++' post-inc operator and the '+' binary op +// fixes this, and is highly recommended for readability anyway. +static bool FollowsPostfixOperator(StyleContext &sc, Accessor &styler) { + int pos = (int) sc.currentPos; + while (--pos > 0) { + char ch = styler[pos]; + if (ch == '+' || ch == '-') { + return styler[pos - 1] == ch; + } + } + return false; +} + +static bool followsReturnKeyword(StyleContext &sc, Accessor &styler) { + // Don't look at styles, so no need to flush. + int pos = (int) sc.currentPos; + int currentLine = styler.GetLine(pos); + int lineStartPos = styler.LineStart(currentLine); + char ch; + while (--pos > lineStartPos) { + ch = styler.SafeGetCharAt(pos); + if (ch != ' ' && ch != '\t') { + break; + } + } + const char *retBack = "nruter"; + const char *s = retBack; + while (*s + && pos >= lineStartPos + && styler.SafeGetCharAt(pos) == *s) { + s++; + pos--; + } + return !*s; +} + +static void ColouriseCoffeeScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + + // property styling.within.preprocessor + // For C++ code, determines whether all preprocessor code is styled in the preprocessor style (0, the default) + // or only from the initial # to the end of the command word(1). + bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; + + CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-"); + CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-"); + + CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); + + CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); + + // property lexer.cpp.allow.dollars + // Set to 0 to disallow the '$' character in identifiers with the cpp lexer. + if (styler.GetPropertyInt("lexer.cpp.allow.dollars", 1) != 0) { + setWordStart.Add('$'); + setWord.Add('$'); + } + + int chPrevNonWhite = ' '; + int visibleChars = 0; + bool lastWordWasUUID = false; + int styleBeforeDCKeyword = SCE_C_DEFAULT; + bool continuationLine = false; + bool isIncludePreprocessor = false; + + if (initStyle == SCE_C_PREPROCESSOR) { + // Set continuationLine if last character of previous line is '\' + int lineCurrent = styler.GetLine(startPos); + if (lineCurrent > 0) { + int chBack = styler.SafeGetCharAt(startPos-1, 0); + int chBack2 = styler.SafeGetCharAt(startPos-2, 0); + int lineEndChar = '!'; + if (chBack2 == '\r' && chBack == '\n') { + lineEndChar = styler.SafeGetCharAt(startPos-3, 0); + } else if (chBack == '\n' || chBack == '\r') { + lineEndChar = chBack2; + } + continuationLine = lineEndChar == '\\'; + } + } + + // look back to set chPrevNonWhite properly for better regex colouring + int endPos = startPos + length; + if (startPos > 0) { + unsigned int back = startPos; + styler.Flush(); + while (back > 0 && IsSpaceEquiv(styler.StyleAt(--back))) + ; + if (styler.StyleAt(back) == SCE_C_OPERATOR) { + chPrevNonWhite = styler.SafeGetCharAt(back); + } + if (startPos != back) { + initStyle = styler.StyleAt(back); + } + startPos = back; + } + + StyleContext sc(startPos, endPos - startPos, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart) { + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + lastWordWasUUID = false; + isIncludePreprocessor = false; + } + + // Handle line continuation generically. + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continuationLine = true; + continue; + } + } + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_C_OPERATOR: + sc.SetState(SCE_C_DEFAULT); + break; + case SCE_C_NUMBER: + // We accept almost anything because of hex. and number suffixes + if (!setWord.Contains(sc.ch)) { + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_C_IDENTIFIER: + if (!setWord.Contains(sc.ch) || (sc.ch == '.') || (sc.ch == '$')) { + char s[1000]; + sc.GetCurrent(s, sizeof(s)); + if (keywords.InList(s)) { + lastWordWasUUID = strcmp(s, "uuid") == 0; + sc.ChangeState(SCE_C_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_C_WORD2); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_C_GLOBALCLASS); + } + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_C_PREPROCESSOR: + if (sc.atLineStart && !continuationLine) { + sc.SetState(SCE_C_DEFAULT); + } else if (stylingWithinPreprocessor) { + if (IsASpace(sc.ch)) { + sc.SetState(SCE_C_DEFAULT); + } + } else { + if (sc.Match('/', '*') || sc.Match('/', '/')) { + sc.SetState(SCE_C_DEFAULT); + } + } + break; + case SCE_C_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT); + } + break; + case SCE_C_COMMENTDOC: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_C_COMMENTDOC; + sc.SetState(SCE_C_COMMENTDOCKEYWORD); + } + } + break; + case SCE_C_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_C_COMMENTLINEDOC: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC; + sc.SetState(SCE_C_COMMENTDOCKEYWORD); + } + } + break; + case SCE_C_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT); + } else if (!setDoxygen.Contains(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_C_STRING: + if (isIncludePreprocessor) { + if (sc.ch == '>') { + sc.ForwardSetState(SCE_C_DEFAULT); + isIncludePreprocessor = false; + } + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_C_DEFAULT); + } + break; + case SCE_C_CHARACTER: + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_C_DEFAULT); + } + break; + case SCE_C_REGEX: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } else if (sc.ch == '/') { + sc.Forward(); + while ((sc.ch < 0x80) && islower(sc.ch)) + sc.Forward(); // gobble regex flags + sc.SetState(SCE_C_DEFAULT); + } else if (sc.ch == '\\') { + // Gobble up the quoted character + if (sc.chNext == '\\' || sc.chNext == '/') { + sc.Forward(); + } + } + break; + case SCE_C_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_C_VERBATIM: + if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_C_DEFAULT); + } + } + break; + case SCE_C_UUID: + if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_COFFEESCRIPT_COMMENTBLOCK: + if (sc.Match("###")) { + sc.ChangeState(SCE_C_COMMENT); + sc.Forward(); + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT); + } else if (sc.ch == '\\') { + sc.Forward(); + } + break; + case SCE_COFFEESCRIPT_VERBOSE_REGEX: + if (sc.Match("///")) { + sc.Forward(); + sc.Forward(); + sc.ChangeState(SCE_C_REGEX); + sc.ForwardSetState(SCE_C_DEFAULT); + } else if (sc.Match('#')) { + sc.ChangeState(SCE_C_REGEX); + sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT); + } else if (sc.ch == '\\') { + sc.Forward(); + } + break; + case SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT: + if (sc.atLineStart) { + sc.ChangeState(SCE_C_COMMENT); + sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX); + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_C_DEFAULT) { + if (sc.Match('@', '\"')) { + sc.SetState(SCE_C_VERBATIM); + sc.Forward(); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + if (lastWordWasUUID) { + sc.SetState(SCE_C_UUID); + lastWordWasUUID = false; + } else { + sc.SetState(SCE_C_NUMBER); + } + } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@') || (sc.ch == '$')) { + if (lastWordWasUUID) { + sc.SetState(SCE_C_UUID); + lastWordWasUUID = false; + } else { + sc.SetState(SCE_C_IDENTIFIER); + } + } else if (sc.Match('/', '*')) { + if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style + sc.SetState(SCE_C_COMMENTDOC); + } else { + sc.SetState(SCE_C_COMMENT); + } + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match("///")) { + sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX); + } else if (sc.ch == '/' + && (setOKBeforeRE.Contains(chPrevNonWhite) + || followsReturnKeyword(sc, styler)) + && (!setCouldBePostOp.Contains(chPrevNonWhite) + || !FollowsPostfixOperator(sc, styler))) { + sc.SetState(SCE_C_REGEX); // JavaScript's RegEx + } else if (sc.ch == '\"') { + sc.SetState(SCE_C_STRING); + isIncludePreprocessor = false; // ensure that '>' won't end the string + } else if (isIncludePreprocessor && sc.ch == '<') { + sc.SetState(SCE_C_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_C_CHARACTER); + } else if (sc.ch == '#') { + if (sc.Match("###")) { + sc.SetState(SCE_COFFEESCRIPT_COMMENTBLOCK); + } else { + sc.SetState(SCE_C_COMMENTLINE); + } + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_C_OPERATOR); + } + } + + if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) { + chPrevNonWhite = sc.ch; + visibleChars++; + } + continuationLine = false; + } + // Change temporary coffeescript states into standard C ones. + switch (sc.state) { + case SCE_COFFEESCRIPT_COMMENTBLOCK: + sc.ChangeState(SCE_C_COMMENT); + break; + case SCE_COFFEESCRIPT_VERBOSE_REGEX: + sc.ChangeState(SCE_C_REGEX); + break; + case SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT: + sc.ChangeState(SCE_C_COMMENTLINE); + break; + } + sc.Complete(); +} + +static bool IsCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eol_pos; i++) { + char ch = styler[i]; + if (ch == '#') + return true; + else if (ch == '/' + && i < eol_pos - 1 + && styler[i + 1] == '*') + return true; + else if (ch != ' ' && ch != '\t') + return false; + } + return false; +} + +static void FoldCoffeeScriptDoc(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) { + // A simplified version of FoldPyDoc + const int maxPos = startPos + length; + const int maxLines = styler.GetLine(maxPos - 1); // Requested last line + const int docLines = styler.GetLine(styler.Length() - 1); // Available last line + + // property fold.coffeescript.comment + const bool foldComment = styler.GetPropertyInt("fold.coffeescript.comment") != 0; + + const bool foldCompact = styler.GetPropertyInt("fold.compact") != 0; + + // Backtrack to previous non-blank line so we can determine indent level + // for any white space lines + // and so we can fix any preceding fold level (which is why we go back + // at least one line in all cases) + int spaceFlags = 0; + int lineCurrent = styler.GetLine(startPos); + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + while (lineCurrent > 0) { + lineCurrent--; + indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) + && !IsCommentLine(lineCurrent, styler)) + break; + } + int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + + // Set up initial loop state + int prevComment = 0; + if (lineCurrent >= 1) + prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler); + + // Process all characters to end of requested range + // or comment that hangs over the end of the range. Cap processing in all cases + // to end of document (in case of comment at end). + while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevComment)) { + + // Gather info + int lev = indentCurrent; + int lineNext = lineCurrent + 1; + int indentNext = indentCurrent; + if (lineNext <= docLines) { + // Information about next line is only available if not at end of document + indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); + } + const int comment = foldComment && IsCommentLine(lineCurrent, styler); + const int comment_start = (comment && !prevComment && (lineNext <= docLines) && + IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE)); + const int comment_continue = (comment && prevComment); + if (!comment) + indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + if (indentNext & SC_FOLDLEVELWHITEFLAG) + indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; + + if (comment_start) { + // Place fold point at start of a block of comments + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (comment_continue) { + // Add level to rest of lines in the block + lev = lev + 1; + } + + // Skip past any blank lines for next indent level info; we skip also + // comments (all comments, not just those starting in column 0) + // which effectively folds them into surrounding code rather + // than screwing up folding. + + while ((lineNext < docLines) && + ((indentNext & SC_FOLDLEVELWHITEFLAG) || + (lineNext <= docLines && IsCommentLine(lineNext, styler)))) { + + lineNext++; + indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); + } + + const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK; + const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments); + + // Now set all the indent levels on the lines we skipped + // Do this from end to start. Once we encounter one line + // which is indented more than the line after the end of + // the comment-block, use the level of the block before + + int skipLine = lineNext; + int skipLevel = levelAfterComments; + + while (--skipLine > lineCurrent) { + int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL); + + if (foldCompact) { + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments) + skipLevel = levelBeforeComments; + + int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; + + styler.SetLevel(skipLine, skipLevel | whiteFlag); + } else { + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments && + !(skipLineIndent & SC_FOLDLEVELWHITEFLAG) && + !IsCommentLine(skipLine, styler)) + skipLevel = levelBeforeComments; + + styler.SetLevel(skipLine, skipLevel); + } + } + + // Set fold header on non-comment line + if (!comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) + lev |= SC_FOLDLEVELHEADERFLAG; + } + + // Keep track of block comment state of previous line + prevComment = comment_start || comment_continue; + + // Set fold level for this line and move to next line + styler.SetLevel(lineCurrent, lev); + indentCurrent = indentNext; + lineCurrent = lineNext; + } +} + +static const char *const csWordLists[] = { + "Keywords", + 0, +}; + +LexerModule lmCoffeeScript(SCLEX_COFFEESCRIPT, ColouriseCoffeeScriptDoc, "coffeescript", FoldCoffeeScriptDoc, csWordLists); diff --git a/scintilla/lexers/LexConf.cxx b/ThirdLibs/scintilla/lexers/LexConf.cxx similarity index 96% rename from scintilla/lexers/LexConf.cxx rename to ThirdLibs/scintilla/lexers/LexConf.cxx index f26458bf..23ed5a6c 100644 --- a/scintilla/lexers/LexConf.cxx +++ b/ThirdLibs/scintilla/lexers/LexConf.cxx @@ -1,192 +1,192 @@ -// Scintilla source code edit control -/** @file LexConf.cxx - ** Lexer for Apache Configuration Files. - ** - ** First working version contributed by Ahmad Zawawi on October 28, 2000. - ** i created this lexer because i needed something pretty when dealing - ** when Apache Configuration files... - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static void ColouriseConfDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) -{ - int state = SCE_CONF_DEFAULT; - char chNext = styler[startPos]; - int lengthDoc = startPos + length; - // create a buffer large enough to take the largest chunk... - char *buffer = new char[length]; - int bufferCount = 0; - - // this assumes that we have 2 keyword list in conf.properties - WordList &directives = *keywordLists[0]; - WordList ¶ms = *keywordLists[1]; - - // go through all provided text segment - // using the hand-written state machine shown below - styler.StartAt(startPos); - styler.StartSegment(startPos); - for (int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - i++; - continue; - } - switch(state) { - case SCE_CONF_DEFAULT: - if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') { - // whitespace is simply ignored here... - styler.ColourTo(i,SCE_CONF_DEFAULT); - break; - } else if( ch == '#' ) { - // signals the start of a comment... - state = SCE_CONF_COMMENT; - styler.ColourTo(i,SCE_CONF_COMMENT); - } else if( ch == '.' /*|| ch == '/'*/) { - // signals the start of a file... - state = SCE_CONF_EXTENSION; - styler.ColourTo(i,SCE_CONF_EXTENSION); - } else if( ch == '"') { - state = SCE_CONF_STRING; - styler.ColourTo(i,SCE_CONF_STRING); - } else if( isascii(ch) && ispunct(ch) ) { - // signals an operator... - // no state jump necessary for this - // simple case... - styler.ColourTo(i,SCE_CONF_OPERATOR); - } else if( isascii(ch) && isalpha(ch) ) { - // signals the start of an identifier - bufferCount = 0; - buffer[bufferCount++] = static_cast(tolower(ch)); - state = SCE_CONF_IDENTIFIER; - } else if( isascii(ch) && isdigit(ch) ) { - // signals the start of a number - bufferCount = 0; - buffer[bufferCount++] = ch; - //styler.ColourTo(i,SCE_CONF_NUMBER); - state = SCE_CONF_NUMBER; - } else { - // style it the default style.. - styler.ColourTo(i,SCE_CONF_DEFAULT); - } - break; - - case SCE_CONF_COMMENT: - // if we find a newline here, - // we simply go to default state - // else continue to work on it... - if( ch == '\n' || ch == '\r' ) { - state = SCE_CONF_DEFAULT; - } else { - styler.ColourTo(i,SCE_CONF_COMMENT); - } - break; - - case SCE_CONF_EXTENSION: - // if we find a non-alphanumeric char, - // we simply go to default state - // else we're still dealing with an extension... - if( (isascii(ch) && isalnum(ch)) || (ch == '_') || - (ch == '-') || (ch == '$') || - (ch == '/') || (ch == '.') || (ch == '*') ) - { - styler.ColourTo(i,SCE_CONF_EXTENSION); - } else { - state = SCE_CONF_DEFAULT; - chNext = styler[i--]; - } - break; - - case SCE_CONF_STRING: - // if we find the end of a string char, we simply go to default state - // else we're still dealing with an string... - if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || (ch == '\n') || (ch == '\r') ) { - state = SCE_CONF_DEFAULT; - } - styler.ColourTo(i,SCE_CONF_STRING); - break; - - case SCE_CONF_IDENTIFIER: - // stay in CONF_IDENTIFIER state until we find a non-alphanumeric - if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || (ch == '$') || (ch == '.') || (ch == '*')) { - buffer[bufferCount++] = static_cast(tolower(ch)); - } else { - state = SCE_CONF_DEFAULT; - buffer[bufferCount] = '\0'; - - // check if the buffer contains a keyword, and highlight it if it is a keyword... - if(directives.InList(buffer)) { - styler.ColourTo(i-1,SCE_CONF_DIRECTIVE ); - } else if(params.InList(buffer)) { - styler.ColourTo(i-1,SCE_CONF_PARAMETER ); - } else if(strchr(buffer,'/') || strchr(buffer,'.')) { - styler.ColourTo(i-1,SCE_CONF_EXTENSION); - } else { - styler.ColourTo(i-1,SCE_CONF_DEFAULT); - } - - // push back the faulty character - chNext = styler[i--]; - - } - break; - - case SCE_CONF_NUMBER: - // stay in CONF_NUMBER state until we find a non-numeric - if( (isascii(ch) && isdigit(ch)) || ch == '.') { - buffer[bufferCount++] = ch; - } else { - state = SCE_CONF_DEFAULT; - buffer[bufferCount] = '\0'; - - // Colourize here... - if( strchr(buffer,'.') ) { - // it is an IP address... - styler.ColourTo(i-1,SCE_CONF_IP); - } else { - // normal number - styler.ColourTo(i-1,SCE_CONF_NUMBER); - } - - // push back a character - chNext = styler[i--]; - } - break; - - } - } - delete []buffer; -} - -static const char * const confWordListDesc[] = { - "Directives", - "Parameters", - 0 -}; - -LexerModule lmConf(SCLEX_CONF, ColouriseConfDoc, "conf", 0, confWordListDesc); +// Scintilla source code edit control +/** @file LexConf.cxx + ** Lexer for Apache Configuration Files. + ** + ** First working version contributed by Ahmad Zawawi on October 28, 2000. + ** i created this lexer because i needed something pretty when dealing + ** when Apache Configuration files... + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static void ColouriseConfDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) +{ + int state = SCE_CONF_DEFAULT; + char chNext = styler[startPos]; + int lengthDoc = startPos + length; + // create a buffer large enough to take the largest chunk... + char *buffer = new char[length]; + int bufferCount = 0; + + // this assumes that we have 2 keyword list in conf.properties + WordList &directives = *keywordLists[0]; + WordList ¶ms = *keywordLists[1]; + + // go through all provided text segment + // using the hand-written state machine shown below + styler.StartAt(startPos); + styler.StartSegment(startPos); + for (int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + i++; + continue; + } + switch(state) { + case SCE_CONF_DEFAULT: + if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') { + // whitespace is simply ignored here... + styler.ColourTo(i,SCE_CONF_DEFAULT); + break; + } else if( ch == '#' ) { + // signals the start of a comment... + state = SCE_CONF_COMMENT; + styler.ColourTo(i,SCE_CONF_COMMENT); + } else if( ch == '.' /*|| ch == '/'*/) { + // signals the start of a file... + state = SCE_CONF_EXTENSION; + styler.ColourTo(i,SCE_CONF_EXTENSION); + } else if( ch == '"') { + state = SCE_CONF_STRING; + styler.ColourTo(i,SCE_CONF_STRING); + } else if( isascii(ch) && ispunct(ch) ) { + // signals an operator... + // no state jump necessary for this + // simple case... + styler.ColourTo(i,SCE_CONF_OPERATOR); + } else if( isascii(ch) && isalpha(ch) ) { + // signals the start of an identifier + bufferCount = 0; + buffer[bufferCount++] = static_cast(tolower(ch)); + state = SCE_CONF_IDENTIFIER; + } else if( isascii(ch) && isdigit(ch) ) { + // signals the start of a number + bufferCount = 0; + buffer[bufferCount++] = ch; + //styler.ColourTo(i,SCE_CONF_NUMBER); + state = SCE_CONF_NUMBER; + } else { + // style it the default style.. + styler.ColourTo(i,SCE_CONF_DEFAULT); + } + break; + + case SCE_CONF_COMMENT: + // if we find a newline here, + // we simply go to default state + // else continue to work on it... + if( ch == '\n' || ch == '\r' ) { + state = SCE_CONF_DEFAULT; + } else { + styler.ColourTo(i,SCE_CONF_COMMENT); + } + break; + + case SCE_CONF_EXTENSION: + // if we find a non-alphanumeric char, + // we simply go to default state + // else we're still dealing with an extension... + if( (isascii(ch) && isalnum(ch)) || (ch == '_') || + (ch == '-') || (ch == '$') || + (ch == '/') || (ch == '.') || (ch == '*') ) + { + styler.ColourTo(i,SCE_CONF_EXTENSION); + } else { + state = SCE_CONF_DEFAULT; + chNext = styler[i--]; + } + break; + + case SCE_CONF_STRING: + // if we find the end of a string char, we simply go to default state + // else we're still dealing with an string... + if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || (ch == '\n') || (ch == '\r') ) { + state = SCE_CONF_DEFAULT; + } + styler.ColourTo(i,SCE_CONF_STRING); + break; + + case SCE_CONF_IDENTIFIER: + // stay in CONF_IDENTIFIER state until we find a non-alphanumeric + if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || (ch == '$') || (ch == '.') || (ch == '*')) { + buffer[bufferCount++] = static_cast(tolower(ch)); + } else { + state = SCE_CONF_DEFAULT; + buffer[bufferCount] = '\0'; + + // check if the buffer contains a keyword, and highlight it if it is a keyword... + if(directives.InList(buffer)) { + styler.ColourTo(i-1,SCE_CONF_DIRECTIVE ); + } else if(params.InList(buffer)) { + styler.ColourTo(i-1,SCE_CONF_PARAMETER ); + } else if(strchr(buffer,'/') || strchr(buffer,'.')) { + styler.ColourTo(i-1,SCE_CONF_EXTENSION); + } else { + styler.ColourTo(i-1,SCE_CONF_DEFAULT); + } + + // push back the faulty character + chNext = styler[i--]; + + } + break; + + case SCE_CONF_NUMBER: + // stay in CONF_NUMBER state until we find a non-numeric + if( (isascii(ch) && isdigit(ch)) || ch == '.') { + buffer[bufferCount++] = ch; + } else { + state = SCE_CONF_DEFAULT; + buffer[bufferCount] = '\0'; + + // Colourize here... + if( strchr(buffer,'.') ) { + // it is an IP address... + styler.ColourTo(i-1,SCE_CONF_IP); + } else { + // normal number + styler.ColourTo(i-1,SCE_CONF_NUMBER); + } + + // push back a character + chNext = styler[i--]; + } + break; + + } + } + delete []buffer; +} + +static const char * const confWordListDesc[] = { + "Directives", + "Parameters", + 0 +}; + +LexerModule lmConf(SCLEX_CONF, ColouriseConfDoc, "conf", 0, confWordListDesc); diff --git a/scintilla/lexers/LexCrontab.cxx b/ThirdLibs/scintilla/lexers/LexCrontab.cxx similarity index 96% rename from scintilla/lexers/LexCrontab.cxx rename to ThirdLibs/scintilla/lexers/LexCrontab.cxx index ea748356..08abc719 100644 --- a/scintilla/lexers/LexCrontab.cxx +++ b/ThirdLibs/scintilla/lexers/LexCrontab.cxx @@ -1,226 +1,226 @@ -// Scintilla source code edit control -/** @file LexCrontab.cxx - ** Lexer to use with extended crontab files used by a powerful - ** Windows scheduler/event monitor/automation manager nnCron. - ** (http://nemtsev.eserv.ru/) - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static void ColouriseNncrontabDoc(unsigned int startPos, int length, int, WordList -*keywordLists[], Accessor &styler) -{ - int state = SCE_NNCRONTAB_DEFAULT; - char chNext = styler[startPos]; - int lengthDoc = startPos + length; - // create a buffer large enough to take the largest chunk... - char *buffer = new char[length]; - int bufferCount = 0; - // used when highliting environment variables inside quoted string: - bool insideString = false; - - // this assumes that we have 3 keyword list in conf.properties - WordList §ion = *keywordLists[0]; - WordList &keyword = *keywordLists[1]; - WordList &modifier = *keywordLists[2]; - - // go through all provided text segment - // using the hand-written state machine shown below - styler.StartAt(startPos); - styler.StartSegment(startPos); - for (int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - i++; - continue; - } - switch(state) { - case SCE_NNCRONTAB_DEFAULT: - if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') { - // whitespace is simply ignored here... - styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT); - break; - } else if( ch == '#' && styler.SafeGetCharAt(i+1) == '(') { - // signals the start of a task... - state = SCE_NNCRONTAB_TASK; - styler.ColourTo(i,SCE_NNCRONTAB_TASK); - } - else if( ch == '\\' && (styler.SafeGetCharAt(i+1) == ' ' || - styler.SafeGetCharAt(i+1) == '\t')) { - // signals the start of an extended comment... - state = SCE_NNCRONTAB_COMMENT; - styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); - } else if( ch == '#' ) { - // signals the start of a plain comment... - state = SCE_NNCRONTAB_COMMENT; - styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); - } else if( ch == ')' && styler.SafeGetCharAt(i+1) == '#') { - // signals the end of a task... - state = SCE_NNCRONTAB_TASK; - styler.ColourTo(i,SCE_NNCRONTAB_TASK); - } else if( ch == '"') { - state = SCE_NNCRONTAB_STRING; - styler.ColourTo(i,SCE_NNCRONTAB_STRING); - } else if( ch == '%') { - // signals environment variables - state = SCE_NNCRONTAB_ENVIRONMENT; - styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); - } else if( ch == '<' && styler.SafeGetCharAt(i+1) == '%') { - // signals environment variables - state = SCE_NNCRONTAB_ENVIRONMENT; - styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); - } else if( ch == '*' ) { - // signals an asterisk - // no state jump necessary for this simple case... - styler.ColourTo(i,SCE_NNCRONTAB_ASTERISK); - } else if( (isascii(ch) && isalpha(ch)) || ch == '<' ) { - // signals the start of an identifier - bufferCount = 0; - buffer[bufferCount++] = ch; - state = SCE_NNCRONTAB_IDENTIFIER; - } else if( isascii(ch) && isdigit(ch) ) { - // signals the start of a number - bufferCount = 0; - buffer[bufferCount++] = ch; - state = SCE_NNCRONTAB_NUMBER; - } else { - // style it the default style.. - styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT); - } - break; - - case SCE_NNCRONTAB_COMMENT: - // if we find a newline here, - // we simply go to default state - // else continue to work on it... - if( ch == '\n' || ch == '\r' ) { - state = SCE_NNCRONTAB_DEFAULT; - } else { - styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); - } - break; - - case SCE_NNCRONTAB_TASK: - // if we find a newline here, - // we simply go to default state - // else continue to work on it... - if( ch == '\n' || ch == '\r' ) { - state = SCE_NNCRONTAB_DEFAULT; - } else { - styler.ColourTo(i,SCE_NNCRONTAB_TASK); - } - break; - - case SCE_NNCRONTAB_STRING: - if( ch == '%' ) { - state = SCE_NNCRONTAB_ENVIRONMENT; - insideString = true; - styler.ColourTo(i-1,SCE_NNCRONTAB_STRING); - break; - } - // if we find the end of a string char, we simply go to default state - // else we're still dealing with an string... - if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || - (ch == '\n') || (ch == '\r') ) { - state = SCE_NNCRONTAB_DEFAULT; - } - styler.ColourTo(i,SCE_NNCRONTAB_STRING); - break; - - case SCE_NNCRONTAB_ENVIRONMENT: - // if we find the end of a string char, we simply go to default state - // else we're still dealing with an string... - if( ch == '%' && insideString ) { - state = SCE_NNCRONTAB_STRING; - insideString = false; - break; - } - if( (ch == '%' && styler.SafeGetCharAt(i-1)!='\\') - || (ch == '\n') || (ch == '\r') || (ch == '>') ) { - state = SCE_NNCRONTAB_DEFAULT; - styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); - break; - } - styler.ColourTo(i+1,SCE_NNCRONTAB_ENVIRONMENT); - break; - - case SCE_NNCRONTAB_IDENTIFIER: - // stay in CONF_IDENTIFIER state until we find a non-alphanumeric - if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || - (ch == '$') || (ch == '.') || (ch == '<') || (ch == '>') || - (ch == '@') ) { - buffer[bufferCount++] = ch; - } else { - state = SCE_NNCRONTAB_DEFAULT; - buffer[bufferCount] = '\0'; - - // check if the buffer contains a keyword, - // and highlight it if it is a keyword... - if(section.InList(buffer)) { - styler.ColourTo(i,SCE_NNCRONTAB_SECTION ); - } else if(keyword.InList(buffer)) { - styler.ColourTo(i-1,SCE_NNCRONTAB_KEYWORD ); - } // else if(strchr(buffer,'/') || strchr(buffer,'.')) { - // styler.ColourTo(i-1,SCE_NNCRONTAB_EXTENSION); - // } - else if(modifier.InList(buffer)) { - styler.ColourTo(i-1,SCE_NNCRONTAB_MODIFIER ); - } else { - styler.ColourTo(i-1,SCE_NNCRONTAB_DEFAULT); - } - // push back the faulty character - chNext = styler[i--]; - } - break; - - case SCE_NNCRONTAB_NUMBER: - // stay in CONF_NUMBER state until we find a non-numeric - if( isascii(ch) && isdigit(ch) /* || ch == '.' */ ) { - buffer[bufferCount++] = ch; - } else { - state = SCE_NNCRONTAB_DEFAULT; - buffer[bufferCount] = '\0'; - // Colourize here... (normal number) - styler.ColourTo(i-1,SCE_NNCRONTAB_NUMBER); - // push back a character - chNext = styler[i--]; - } - break; - } - } - delete []buffer; -} - -static const char * const cronWordListDesc[] = { - "Section keywords and Forth words", - "nnCrontab keywords", - "Modifiers", - 0 -}; - -LexerModule lmNncrontab(SCLEX_NNCRONTAB, ColouriseNncrontabDoc, "nncrontab", 0, cronWordListDesc); +// Scintilla source code edit control +/** @file LexCrontab.cxx + ** Lexer to use with extended crontab files used by a powerful + ** Windows scheduler/event monitor/automation manager nnCron. + ** (http://nemtsev.eserv.ru/) + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static void ColouriseNncrontabDoc(unsigned int startPos, int length, int, WordList +*keywordLists[], Accessor &styler) +{ + int state = SCE_NNCRONTAB_DEFAULT; + char chNext = styler[startPos]; + int lengthDoc = startPos + length; + // create a buffer large enough to take the largest chunk... + char *buffer = new char[length]; + int bufferCount = 0; + // used when highliting environment variables inside quoted string: + bool insideString = false; + + // this assumes that we have 3 keyword list in conf.properties + WordList §ion = *keywordLists[0]; + WordList &keyword = *keywordLists[1]; + WordList &modifier = *keywordLists[2]; + + // go through all provided text segment + // using the hand-written state machine shown below + styler.StartAt(startPos); + styler.StartSegment(startPos); + for (int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + i++; + continue; + } + switch(state) { + case SCE_NNCRONTAB_DEFAULT: + if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') { + // whitespace is simply ignored here... + styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT); + break; + } else if( ch == '#' && styler.SafeGetCharAt(i+1) == '(') { + // signals the start of a task... + state = SCE_NNCRONTAB_TASK; + styler.ColourTo(i,SCE_NNCRONTAB_TASK); + } + else if( ch == '\\' && (styler.SafeGetCharAt(i+1) == ' ' || + styler.SafeGetCharAt(i+1) == '\t')) { + // signals the start of an extended comment... + state = SCE_NNCRONTAB_COMMENT; + styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); + } else if( ch == '#' ) { + // signals the start of a plain comment... + state = SCE_NNCRONTAB_COMMENT; + styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); + } else if( ch == ')' && styler.SafeGetCharAt(i+1) == '#') { + // signals the end of a task... + state = SCE_NNCRONTAB_TASK; + styler.ColourTo(i,SCE_NNCRONTAB_TASK); + } else if( ch == '"') { + state = SCE_NNCRONTAB_STRING; + styler.ColourTo(i,SCE_NNCRONTAB_STRING); + } else if( ch == '%') { + // signals environment variables + state = SCE_NNCRONTAB_ENVIRONMENT; + styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); + } else if( ch == '<' && styler.SafeGetCharAt(i+1) == '%') { + // signals environment variables + state = SCE_NNCRONTAB_ENVIRONMENT; + styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); + } else if( ch == '*' ) { + // signals an asterisk + // no state jump necessary for this simple case... + styler.ColourTo(i,SCE_NNCRONTAB_ASTERISK); + } else if( (isascii(ch) && isalpha(ch)) || ch == '<' ) { + // signals the start of an identifier + bufferCount = 0; + buffer[bufferCount++] = ch; + state = SCE_NNCRONTAB_IDENTIFIER; + } else if( isascii(ch) && isdigit(ch) ) { + // signals the start of a number + bufferCount = 0; + buffer[bufferCount++] = ch; + state = SCE_NNCRONTAB_NUMBER; + } else { + // style it the default style.. + styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT); + } + break; + + case SCE_NNCRONTAB_COMMENT: + // if we find a newline here, + // we simply go to default state + // else continue to work on it... + if( ch == '\n' || ch == '\r' ) { + state = SCE_NNCRONTAB_DEFAULT; + } else { + styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); + } + break; + + case SCE_NNCRONTAB_TASK: + // if we find a newline here, + // we simply go to default state + // else continue to work on it... + if( ch == '\n' || ch == '\r' ) { + state = SCE_NNCRONTAB_DEFAULT; + } else { + styler.ColourTo(i,SCE_NNCRONTAB_TASK); + } + break; + + case SCE_NNCRONTAB_STRING: + if( ch == '%' ) { + state = SCE_NNCRONTAB_ENVIRONMENT; + insideString = true; + styler.ColourTo(i-1,SCE_NNCRONTAB_STRING); + break; + } + // if we find the end of a string char, we simply go to default state + // else we're still dealing with an string... + if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || + (ch == '\n') || (ch == '\r') ) { + state = SCE_NNCRONTAB_DEFAULT; + } + styler.ColourTo(i,SCE_NNCRONTAB_STRING); + break; + + case SCE_NNCRONTAB_ENVIRONMENT: + // if we find the end of a string char, we simply go to default state + // else we're still dealing with an string... + if( ch == '%' && insideString ) { + state = SCE_NNCRONTAB_STRING; + insideString = false; + break; + } + if( (ch == '%' && styler.SafeGetCharAt(i-1)!='\\') + || (ch == '\n') || (ch == '\r') || (ch == '>') ) { + state = SCE_NNCRONTAB_DEFAULT; + styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); + break; + } + styler.ColourTo(i+1,SCE_NNCRONTAB_ENVIRONMENT); + break; + + case SCE_NNCRONTAB_IDENTIFIER: + // stay in CONF_IDENTIFIER state until we find a non-alphanumeric + if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || + (ch == '$') || (ch == '.') || (ch == '<') || (ch == '>') || + (ch == '@') ) { + buffer[bufferCount++] = ch; + } else { + state = SCE_NNCRONTAB_DEFAULT; + buffer[bufferCount] = '\0'; + + // check if the buffer contains a keyword, + // and highlight it if it is a keyword... + if(section.InList(buffer)) { + styler.ColourTo(i,SCE_NNCRONTAB_SECTION ); + } else if(keyword.InList(buffer)) { + styler.ColourTo(i-1,SCE_NNCRONTAB_KEYWORD ); + } // else if(strchr(buffer,'/') || strchr(buffer,'.')) { + // styler.ColourTo(i-1,SCE_NNCRONTAB_EXTENSION); + // } + else if(modifier.InList(buffer)) { + styler.ColourTo(i-1,SCE_NNCRONTAB_MODIFIER ); + } else { + styler.ColourTo(i-1,SCE_NNCRONTAB_DEFAULT); + } + // push back the faulty character + chNext = styler[i--]; + } + break; + + case SCE_NNCRONTAB_NUMBER: + // stay in CONF_NUMBER state until we find a non-numeric + if( isascii(ch) && isdigit(ch) /* || ch == '.' */ ) { + buffer[bufferCount++] = ch; + } else { + state = SCE_NNCRONTAB_DEFAULT; + buffer[bufferCount] = '\0'; + // Colourize here... (normal number) + styler.ColourTo(i-1,SCE_NNCRONTAB_NUMBER); + // push back a character + chNext = styler[i--]; + } + break; + } + } + delete []buffer; +} + +static const char * const cronWordListDesc[] = { + "Section keywords and Forth words", + "nnCrontab keywords", + "Modifiers", + 0 +}; + +LexerModule lmNncrontab(SCLEX_NNCRONTAB, ColouriseNncrontabDoc, "nncrontab", 0, cronWordListDesc); diff --git a/scintilla/lexers/LexCsound.cxx b/ThirdLibs/scintilla/lexers/LexCsound.cxx similarity index 96% rename from scintilla/lexers/LexCsound.cxx rename to ThirdLibs/scintilla/lexers/LexCsound.cxx index c31ad939..8e5880c9 100644 --- a/scintilla/lexers/LexCsound.cxx +++ b/ThirdLibs/scintilla/lexers/LexCsound.cxx @@ -1,214 +1,214 @@ -// Scintilla source code edit control -/** @file LexCsound.cxx - ** Lexer for Csound (Orchestra & Score) - ** Written by Georg Ritter - - **/ -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || - ch == '_' || ch == '?'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' || - ch == '%' || ch == '@' || ch == '$' || ch == '?'); -} - -static inline bool IsCsoundOperator(char ch) { - if (isascii(ch) && isalnum(ch)) - return false; - // '.' left out as it is used to make up numbers - if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || ch == '^' || - ch == '[' || ch == ']' || ch == '<' || ch == '&' || - ch == '>' || ch == ',' || ch == '|' || ch == '~' || - ch == '%' || ch == ':') - return true; - return false; -} - -static void ColouriseCsoundDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &opcode = *keywordlists[0]; - WordList &headerStmt = *keywordlists[1]; - WordList &otherKeyword = *keywordlists[2]; - - // Do not leak onto next line - if (initStyle == SCE_CSOUND_STRINGEOL) - initStyle = SCE_CSOUND_DEFAULT; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) - { - // Handle line continuation generically. - if (sc.ch == '\\') { - if (sc.chNext == '\n' || sc.chNext == '\r') { - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - sc.Forward(); - } - continue; - } - } - - // Determine if the current state should terminate. - if (sc.state == SCE_CSOUND_OPERATOR) { - if (!IsCsoundOperator(static_cast(sc.ch))) { - sc.SetState(SCE_CSOUND_DEFAULT); - } - }else if (sc.state == SCE_CSOUND_NUMBER) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_CSOUND_DEFAULT); - } - } else if (sc.state == SCE_CSOUND_IDENTIFIER) { - if (!IsAWordChar(sc.ch) ) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - - if (opcode.InList(s)) { - sc.ChangeState(SCE_CSOUND_OPCODE); - } else if (headerStmt.InList(s)) { - sc.ChangeState(SCE_CSOUND_HEADERSTMT); - } else if (otherKeyword.InList(s)) { - sc.ChangeState(SCE_CSOUND_USERKEYWORD); - } else if (s[0] == 'p') { - sc.ChangeState(SCE_CSOUND_PARAM); - } else if (s[0] == 'a') { - sc.ChangeState(SCE_CSOUND_ARATE_VAR); - } else if (s[0] == 'k') { - sc.ChangeState(SCE_CSOUND_KRATE_VAR); - } else if (s[0] == 'i') { // covers both i-rate variables and i-statements - sc.ChangeState(SCE_CSOUND_IRATE_VAR); - } else if (s[0] == 'g') { - sc.ChangeState(SCE_CSOUND_GLOBAL_VAR); - } - sc.SetState(SCE_CSOUND_DEFAULT); - } - } - else if (sc.state == SCE_CSOUND_COMMENT ) { - if (sc.atLineEnd) { - sc.SetState(SCE_CSOUND_DEFAULT); - } - } - else if ((sc.state == SCE_CSOUND_ARATE_VAR) || - (sc.state == SCE_CSOUND_KRATE_VAR) || - (sc.state == SCE_CSOUND_IRATE_VAR)) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_CSOUND_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_CSOUND_DEFAULT) { - if (sc.ch == ';'){ - sc.SetState(SCE_CSOUND_COMMENT); - } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) { - sc.SetState(SCE_CSOUND_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_CSOUND_IDENTIFIER); - } else if (IsCsoundOperator(static_cast(sc.ch))) { - sc.SetState(SCE_CSOUND_OPERATOR); - } else if (sc.ch == 'p') { - sc.SetState(SCE_CSOUND_PARAM); - } else if (sc.ch == 'a') { - sc.SetState(SCE_CSOUND_ARATE_VAR); - } else if (sc.ch == 'k') { - sc.SetState(SCE_CSOUND_KRATE_VAR); - } else if (sc.ch == 'i') { // covers both i-rate variables and i-statements - sc.SetState(SCE_CSOUND_IRATE_VAR); - } else if (sc.ch == 'g') { - sc.SetState(SCE_CSOUND_GLOBAL_VAR); - } - } - } - sc.Complete(); -} - -static void FoldCsoundInstruments(unsigned int startPos, int length, int /* initStyle */, WordList *[], - Accessor &styler) { - unsigned int lengthDoc = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int stylePrev = 0; - int styleNext = styler.StyleAt(startPos); - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if ((stylePrev != SCE_CSOUND_OPCODE) && (style == SCE_CSOUND_OPCODE)) { - char s[20]; - unsigned int j = 0; - while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) { - s[j] = styler[i + j]; - j++; - } - s[j] = '\0'; - - if (strcmp(s, "instr") == 0) - levelCurrent++; - if (strcmp(s, "endin") == 0) - levelCurrent--; - } - - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - stylePrev = style; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - - -static const char * const csoundWordListDesc[] = { - "Opcodes", - "Header Statements", - "User keywords", - 0 -}; - -LexerModule lmCsound(SCLEX_CSOUND, ColouriseCsoundDoc, "csound", FoldCsoundInstruments, csoundWordListDesc); +// Scintilla source code edit control +/** @file LexCsound.cxx + ** Lexer for Csound (Orchestra & Score) + ** Written by Georg Ritter - + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || + ch == '_' || ch == '?'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' || + ch == '%' || ch == '@' || ch == '$' || ch == '?'); +} + +static inline bool IsCsoundOperator(char ch) { + if (isascii(ch) && isalnum(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '^' || + ch == '[' || ch == ']' || ch == '<' || ch == '&' || + ch == '>' || ch == ',' || ch == '|' || ch == '~' || + ch == '%' || ch == ':') + return true; + return false; +} + +static void ColouriseCsoundDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &opcode = *keywordlists[0]; + WordList &headerStmt = *keywordlists[1]; + WordList &otherKeyword = *keywordlists[2]; + + // Do not leak onto next line + if (initStyle == SCE_CSOUND_STRINGEOL) + initStyle = SCE_CSOUND_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) + { + // Handle line continuation generically. + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continue; + } + } + + // Determine if the current state should terminate. + if (sc.state == SCE_CSOUND_OPERATOR) { + if (!IsCsoundOperator(static_cast(sc.ch))) { + sc.SetState(SCE_CSOUND_DEFAULT); + } + }else if (sc.state == SCE_CSOUND_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_CSOUND_DEFAULT); + } + } else if (sc.state == SCE_CSOUND_IDENTIFIER) { + if (!IsAWordChar(sc.ch) ) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + + if (opcode.InList(s)) { + sc.ChangeState(SCE_CSOUND_OPCODE); + } else if (headerStmt.InList(s)) { + sc.ChangeState(SCE_CSOUND_HEADERSTMT); + } else if (otherKeyword.InList(s)) { + sc.ChangeState(SCE_CSOUND_USERKEYWORD); + } else if (s[0] == 'p') { + sc.ChangeState(SCE_CSOUND_PARAM); + } else if (s[0] == 'a') { + sc.ChangeState(SCE_CSOUND_ARATE_VAR); + } else if (s[0] == 'k') { + sc.ChangeState(SCE_CSOUND_KRATE_VAR); + } else if (s[0] == 'i') { // covers both i-rate variables and i-statements + sc.ChangeState(SCE_CSOUND_IRATE_VAR); + } else if (s[0] == 'g') { + sc.ChangeState(SCE_CSOUND_GLOBAL_VAR); + } + sc.SetState(SCE_CSOUND_DEFAULT); + } + } + else if (sc.state == SCE_CSOUND_COMMENT ) { + if (sc.atLineEnd) { + sc.SetState(SCE_CSOUND_DEFAULT); + } + } + else if ((sc.state == SCE_CSOUND_ARATE_VAR) || + (sc.state == SCE_CSOUND_KRATE_VAR) || + (sc.state == SCE_CSOUND_IRATE_VAR)) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_CSOUND_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_CSOUND_DEFAULT) { + if (sc.ch == ';'){ + sc.SetState(SCE_CSOUND_COMMENT); + } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) { + sc.SetState(SCE_CSOUND_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_CSOUND_IDENTIFIER); + } else if (IsCsoundOperator(static_cast(sc.ch))) { + sc.SetState(SCE_CSOUND_OPERATOR); + } else if (sc.ch == 'p') { + sc.SetState(SCE_CSOUND_PARAM); + } else if (sc.ch == 'a') { + sc.SetState(SCE_CSOUND_ARATE_VAR); + } else if (sc.ch == 'k') { + sc.SetState(SCE_CSOUND_KRATE_VAR); + } else if (sc.ch == 'i') { // covers both i-rate variables and i-statements + sc.SetState(SCE_CSOUND_IRATE_VAR); + } else if (sc.ch == 'g') { + sc.SetState(SCE_CSOUND_GLOBAL_VAR); + } + } + } + sc.Complete(); +} + +static void FoldCsoundInstruments(unsigned int startPos, int length, int /* initStyle */, WordList *[], + Accessor &styler) { + unsigned int lengthDoc = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int stylePrev = 0; + int styleNext = styler.StyleAt(startPos); + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if ((stylePrev != SCE_CSOUND_OPCODE) && (style == SCE_CSOUND_OPCODE)) { + char s[20]; + unsigned int j = 0; + while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) { + s[j] = styler[i + j]; + j++; + } + s[j] = '\0'; + + if (strcmp(s, "instr") == 0) + levelCurrent++; + if (strcmp(s, "endin") == 0) + levelCurrent--; + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + stylePrev = style; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + + +static const char * const csoundWordListDesc[] = { + "Opcodes", + "Header Statements", + "User keywords", + 0 +}; + +LexerModule lmCsound(SCLEX_CSOUND, ColouriseCsoundDoc, "csound", FoldCsoundInstruments, csoundWordListDesc); diff --git a/scintilla/lexers/LexD.cxx b/ThirdLibs/scintilla/lexers/LexD.cxx similarity index 96% rename from scintilla/lexers/LexD.cxx rename to ThirdLibs/scintilla/lexers/LexD.cxx index f8851a06..eb76be3e 100644 --- a/scintilla/lexers/LexD.cxx +++ b/ThirdLibs/scintilla/lexers/LexD.cxx @@ -1,568 +1,568 @@ -/** @file LexD.cxx - ** Lexer for D. - ** - ** Copyright (c) 2006 by Waldemar Augustyn - ** Converted to lexer object and added further folding features/properties by "Udo Lechner" - **/ -// Copyright 1998-2005 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" -#include "OptionSet.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/* Nested comments require keeping the value of the nesting level for every - position in the document. But since scintilla always styles line by line, - we only need to store one value per line. The non-negative number indicates - nesting level at the end of the line. -*/ - -// Underscore, letter, digit and universal alphas from C99 Appendix D. - -static bool IsWordStart(int ch) { - return (isascii(ch) && (isalpha(ch) || ch == '_')) || !isascii(ch); -} - -static bool IsWord(int ch) { - return (isascii(ch) && (isalnum(ch) || ch == '_')) || !isascii(ch); -} - -static bool IsDoxygen(int ch) { - if (isascii(ch) && islower(ch)) - return true; - if (ch == '$' || ch == '@' || ch == '\\' || - ch == '&' || ch == '#' || ch == '<' || ch == '>' || - ch == '{' || ch == '}' || ch == '[' || ch == ']') - return true; - return false; -} - -static bool IsStringSuffix(int ch) { - return ch == 'c' || ch == 'w' || ch == 'd'; -} - -static bool IsStreamCommentStyle(int style) { - return style == SCE_D_COMMENT || - style == SCE_D_COMMENTDOC || - style == SCE_D_COMMENTDOCKEYWORD || - style == SCE_D_COMMENTDOCKEYWORDERROR; -} - -// An individual named option for use in an OptionSet - -// Options used for LexerD -struct OptionsD { - bool fold; - bool foldSyntaxBased; - bool foldComment; - bool foldCommentMultiline; - bool foldCommentExplicit; - std::string foldExplicitStart; - std::string foldExplicitEnd; - bool foldExplicitAnywhere; - bool foldCompact; - int foldAtElseInt; - bool foldAtElse; - OptionsD() { - fold = false; - foldSyntaxBased = true; - foldComment = false; - foldCommentMultiline = true; - foldCommentExplicit = true; - foldExplicitStart = ""; - foldExplicitEnd = ""; - foldExplicitAnywhere = false; - foldCompact = true; - foldAtElseInt = -1; - foldAtElse = false; - } -}; - -static const char * const dWordLists[] = { - "Primary keywords and identifiers", - "Secondary keywords and identifiers", - "Documentation comment keywords", - "Type definitions and aliases", - "Keywords 5", - "Keywords 6", - "Keywords 7", - 0, - }; - -struct OptionSetD : public OptionSet { - OptionSetD() { - DefineProperty("fold", &OptionsD::fold); - - DefineProperty("fold.d.syntax.based", &OptionsD::foldSyntaxBased, - "Set this property to 0 to disable syntax based folding."); - - DefineProperty("fold.comment", &OptionsD::foldComment); - - DefineProperty("fold.d.comment.multiline", &OptionsD::foldCommentMultiline, - "Set this property to 0 to disable folding multi-line comments when fold.comment=1."); - - DefineProperty("fold.d.comment.explicit", &OptionsD::foldCommentExplicit, - "Set this property to 0 to disable folding explicit fold points when fold.comment=1."); - - DefineProperty("fold.d.explicit.start", &OptionsD::foldExplicitStart, - "The string to use for explicit fold start points, replacing the standard //{."); - - DefineProperty("fold.d.explicit.end", &OptionsD::foldExplicitEnd, - "The string to use for explicit fold end points, replacing the standard //}."); - - DefineProperty("fold.d.explicit.anywhere", &OptionsD::foldExplicitAnywhere, - "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); - - DefineProperty("fold.compact", &OptionsD::foldCompact); - - DefineProperty("lexer.d.fold.at.else", &OptionsD::foldAtElseInt, - "This option enables D folding on a \"} else {\" line of an if statement."); - - DefineProperty("fold.at.else", &OptionsD::foldAtElse); - - DefineWordListSets(dWordLists); - } -}; - -class LexerD : public ILexer { - bool caseSensitive; - WordList keywords; - WordList keywords2; - WordList keywords3; - WordList keywords4; - WordList keywords5; - WordList keywords6; - WordList keywords7; - OptionsD options; - OptionSetD osD; -public: - LexerD(bool caseSensitive_) : - caseSensitive(caseSensitive_) { - } - ~LexerD() { - } - void SCI_METHOD Release() { - delete this; - } - int SCI_METHOD Version() const { - return lvOriginal; - } - const char * SCI_METHOD PropertyNames() { - return osD.PropertyNames(); - } - int SCI_METHOD PropertyType(const char *name) { - return osD.PropertyType(name); - } - const char * SCI_METHOD DescribeProperty(const char *name) { - return osD.DescribeProperty(name); - } - int SCI_METHOD PropertySet(const char *key, const char *val); - const char * SCI_METHOD DescribeWordListSets() { - return osD.DescribeWordListSets(); - } - int SCI_METHOD WordListSet(int n, const char *wl); - void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); - void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); - - void * SCI_METHOD PrivateCall(int, void *) { - return 0; - } - - static ILexer *LexerFactoryD() { - return new LexerD(true); - } - static ILexer *LexerFactoryDInsensitive() { - return new LexerD(false); - } -}; - -int SCI_METHOD LexerD::PropertySet(const char *key, const char *val) { - if (osD.PropertySet(&options, key, val)) { - return 0; - } - return -1; -} - -int SCI_METHOD LexerD::WordListSet(int n, const char *wl) { - WordList *wordListN = 0; - switch (n) { - case 0: - wordListN = &keywords; - break; - case 1: - wordListN = &keywords2; - break; - case 2: - wordListN = &keywords3; - break; - case 3: - wordListN = &keywords4; - break; - case 4: - wordListN = &keywords5; - break; - case 5: - wordListN = &keywords6; - break; - case 6: - wordListN = &keywords7; - break; - } - int firstModification = -1; - if (wordListN) { - WordList wlNew; - wlNew.Set(wl); - if (*wordListN != wlNew) { - wordListN->Set(wl); - firstModification = 0; - } - } - return firstModification; -} - -void SCI_METHOD LexerD::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { - LexAccessor styler(pAccess); - - int styleBeforeDCKeyword = SCE_D_DEFAULT; - - StyleContext sc(startPos, length, initStyle, styler); - - int curLine = styler.GetLine(startPos); - int curNcLevel = curLine > 0? styler.GetLineState(curLine-1): 0; - bool numFloat = false; // Float literals have '+' and '-' signs - bool numHex = false; - - for (; sc.More(); sc.Forward()) { - - if (sc.atLineStart) { - curLine = styler.GetLine(sc.currentPos); - styler.SetLineState(curLine, curNcLevel); - } - - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_D_OPERATOR: - sc.SetState(SCE_D_DEFAULT); - break; - case SCE_D_NUMBER: - // We accept almost anything because of hex. and number suffixes - if (isascii(sc.ch) && (isalnum(sc.ch) || sc.ch == '_')) { - continue; - } else if (sc.ch == '.' && sc.chNext != '.' && !numFloat) { - // Don't parse 0..2 as number. - numFloat=true; - continue; - } else if ( ( sc.ch == '-' || sc.ch == '+' ) && ( /*sign and*/ - ( !numHex && ( sc.chPrev == 'e' || sc.chPrev == 'E' ) ) || /*decimal or*/ - ( sc.chPrev == 'p' || sc.chPrev == 'P' ) ) ) { /*hex*/ - // Parse exponent sign in float literals: 2e+10 0x2e+10 - continue; - } else { - sc.SetState(SCE_D_DEFAULT); - } - break; - case SCE_D_IDENTIFIER: - if (!IsWord(sc.ch)) { - char s[1000]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - if (keywords.InList(s)) { - sc.ChangeState(SCE_D_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_D_WORD2); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_D_TYPEDEF); - } else if (keywords5.InList(s)) { - sc.ChangeState(SCE_D_WORD5); - } else if (keywords6.InList(s)) { - sc.ChangeState(SCE_D_WORD6); - } else if (keywords7.InList(s)) { - sc.ChangeState(SCE_D_WORD7); - } - sc.SetState(SCE_D_DEFAULT); - } - break; - case SCE_D_COMMENT: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_D_DEFAULT); - } - break; - case SCE_D_COMMENTDOC: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_D_DEFAULT); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_D_COMMENTDOC; - sc.SetState(SCE_D_COMMENTDOCKEYWORD); - } - } - break; - case SCE_D_COMMENTLINE: - if (sc.atLineStart) { - sc.SetState(SCE_D_DEFAULT); - } - break; - case SCE_D_COMMENTLINEDOC: - if (sc.atLineStart) { - sc.SetState(SCE_D_DEFAULT); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_D_COMMENTLINEDOC; - sc.SetState(SCE_D_COMMENTDOCKEYWORD); - } - } - break; - case SCE_D_COMMENTDOCKEYWORD: - if ((styleBeforeDCKeyword == SCE_D_COMMENTDOC) && sc.Match('*', '/')) { - sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR); - sc.Forward(); - sc.ForwardSetState(SCE_D_DEFAULT); - } else if (!IsDoxygen(sc.ch)) { - char s[100]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { - sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR); - } - sc.SetState(styleBeforeDCKeyword); - } - break; - case SCE_D_COMMENTNESTED: - if (sc.Match('+', '/')) { - if (curNcLevel > 0) - curNcLevel -= 1; - curLine = styler.GetLine(sc.currentPos); - styler.SetLineState(curLine, curNcLevel); - sc.Forward(); - if (curNcLevel == 0) { - sc.ForwardSetState(SCE_D_DEFAULT); - } - } else if (sc.Match('/','+')) { - curNcLevel += 1; - curLine = styler.GetLine(sc.currentPos); - styler.SetLineState(curLine, curNcLevel); - sc.Forward(); - } - break; - case SCE_D_STRING: - if (sc.ch == '\\') { - if (sc.chNext == '"' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '"') { - if(IsStringSuffix(sc.chNext)) - sc.Forward(); - sc.ForwardSetState(SCE_D_DEFAULT); - } - break; - case SCE_D_CHARACTER: - if (sc.atLineEnd) { - sc.ChangeState(SCE_D_STRINGEOL); - } else if (sc.ch == '\\') { - if (sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - // Char has no suffixes - sc.ForwardSetState(SCE_D_DEFAULT); - } - break; - case SCE_D_STRINGEOL: - if (sc.atLineStart) { - sc.SetState(SCE_D_DEFAULT); - } - break; - case SCE_D_STRINGB: - if (sc.ch == '`') { - if(IsStringSuffix(sc.chNext)) - sc.Forward(); - sc.ForwardSetState(SCE_D_DEFAULT); - } - break; - case SCE_D_STRINGR: - if (sc.ch == '"') { - if(IsStringSuffix(sc.chNext)) - sc.Forward(); - sc.ForwardSetState(SCE_D_DEFAULT); - } - break; - } - - // Determine if a new state should be entered. - if (sc.state == SCE_D_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_D_NUMBER); - numFloat = sc.ch == '.'; - // Remember hex literal - numHex = sc.ch == '0' && ( sc.chNext == 'x' || sc.chNext == 'X' ); - } else if ( (sc.ch == 'r' || sc.ch == 'x' || sc.ch == 'q') - && sc.chNext == '"' ) { - // Limited support for hex and delimited strings: parse as r"" - sc.SetState(SCE_D_STRINGR); - sc.Forward(); - } else if (IsWordStart(sc.ch) || sc.ch == '$') { - sc.SetState(SCE_D_IDENTIFIER); - } else if (sc.Match('/','+')) { - curNcLevel += 1; - curLine = styler.GetLine(sc.currentPos); - styler.SetLineState(curLine, curNcLevel); - sc.SetState(SCE_D_COMMENTNESTED); - sc.Forward(); - } else if (sc.Match('/', '*')) { - if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style - sc.SetState(SCE_D_COMMENTDOC); - } else { - sc.SetState(SCE_D_COMMENT); - } - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('/', '/')) { - if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) - // Support of Qt/Doxygen doc. style - sc.SetState(SCE_D_COMMENTLINEDOC); - else - sc.SetState(SCE_D_COMMENTLINE); - } else if (sc.ch == '"') { - sc.SetState(SCE_D_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_D_CHARACTER); - } else if (sc.ch == '`') { - sc.SetState(SCE_D_STRINGB); - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_D_OPERATOR); - if (sc.ch == '.' && sc.chNext == '.') sc.Forward(); // Range operator - } - } - } - sc.Complete(); -} - -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment -// and to make it possible to fiddle the current level for "} else {". - -void SCI_METHOD LexerD::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { - - if (!options.fold) - return; - - LexAccessor styler(pAccess); - - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelMinCurrent = levelCurrent; - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - bool foldAtElse = options.foldAtElseInt >= 0 ? options.foldAtElseInt != 0 : options.foldAtElse; - const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev)) { - levelNext++; - } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelNext--; - } - } - if (options.foldComment && options.foldCommentExplicit && ((style == SCE_D_COMMENTLINE) || options.foldExplicitAnywhere)) { - if (userDefinedFoldMarkers) { - if (styler.Match(i, options.foldExplicitStart.c_str())) { - levelNext++; - } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { - levelNext--; - } - } else { - if ((ch == '/') && (chNext == '/')) { - char chNext2 = styler.SafeGetCharAt(i + 2); - if (chNext2 == '{') { - levelNext++; - } else if (chNext2 == '}') { - levelNext--; - } - } - } - } - if (options.foldSyntaxBased && (style == SCE_D_OPERATOR)) { - if (ch == '{') { - // Measure the minimum before a '{' to allow - // folding on "} else {" - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (ch == '}') { - levelNext--; - } - } - if (atEOL || (i == endPos-1)) { - if (options.foldComment && options.foldCommentMultiline) { // Handle nested comments - int nc; - nc = styler.GetLineState(lineCurrent); - nc -= lineCurrent>0? styler.GetLineState(lineCurrent-1): 0; - levelNext += nc; - } - int levelUse = levelCurrent; - if (options.foldSyntaxBased && foldAtElse) { - levelUse = levelMinCurrent; - } - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && options.foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - levelMinCurrent = levelCurrent; - visibleChars = 0; - } - if (!IsASpace(ch)) - visibleChars++; - } -} - -LexerModule lmD(SCLEX_D, LexerD::LexerFactoryD, "d", dWordLists); +/** @file LexD.cxx + ** Lexer for D. + ** + ** Copyright (c) 2006 by Waldemar Augustyn + ** Converted to lexer object and added further folding features/properties by "Udo Lechner" + **/ +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +/* Nested comments require keeping the value of the nesting level for every + position in the document. But since scintilla always styles line by line, + we only need to store one value per line. The non-negative number indicates + nesting level at the end of the line. +*/ + +// Underscore, letter, digit and universal alphas from C99 Appendix D. + +static bool IsWordStart(int ch) { + return (isascii(ch) && (isalpha(ch) || ch == '_')) || !isascii(ch); +} + +static bool IsWord(int ch) { + return (isascii(ch) && (isalnum(ch) || ch == '_')) || !isascii(ch); +} + +static bool IsDoxygen(int ch) { + if (isascii(ch) && islower(ch)) + return true; + if (ch == '$' || ch == '@' || ch == '\\' || + ch == '&' || ch == '#' || ch == '<' || ch == '>' || + ch == '{' || ch == '}' || ch == '[' || ch == ']') + return true; + return false; +} + +static bool IsStringSuffix(int ch) { + return ch == 'c' || ch == 'w' || ch == 'd'; +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_D_COMMENT || + style == SCE_D_COMMENTDOC || + style == SCE_D_COMMENTDOCKEYWORD || + style == SCE_D_COMMENTDOCKEYWORDERROR; +} + +// An individual named option for use in an OptionSet + +// Options used for LexerD +struct OptionsD { + bool fold; + bool foldSyntaxBased; + bool foldComment; + bool foldCommentMultiline; + bool foldCommentExplicit; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere; + bool foldCompact; + int foldAtElseInt; + bool foldAtElse; + OptionsD() { + fold = false; + foldSyntaxBased = true; + foldComment = false; + foldCommentMultiline = true; + foldCommentExplicit = true; + foldExplicitStart = ""; + foldExplicitEnd = ""; + foldExplicitAnywhere = false; + foldCompact = true; + foldAtElseInt = -1; + foldAtElse = false; + } +}; + +static const char * const dWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + "Documentation comment keywords", + "Type definitions and aliases", + "Keywords 5", + "Keywords 6", + "Keywords 7", + 0, + }; + +struct OptionSetD : public OptionSet { + OptionSetD() { + DefineProperty("fold", &OptionsD::fold); + + DefineProperty("fold.d.syntax.based", &OptionsD::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("fold.comment", &OptionsD::foldComment); + + DefineProperty("fold.d.comment.multiline", &OptionsD::foldCommentMultiline, + "Set this property to 0 to disable folding multi-line comments when fold.comment=1."); + + DefineProperty("fold.d.comment.explicit", &OptionsD::foldCommentExplicit, + "Set this property to 0 to disable folding explicit fold points when fold.comment=1."); + + DefineProperty("fold.d.explicit.start", &OptionsD::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard //{."); + + DefineProperty("fold.d.explicit.end", &OptionsD::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard //}."); + + DefineProperty("fold.d.explicit.anywhere", &OptionsD::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + + DefineProperty("fold.compact", &OptionsD::foldCompact); + + DefineProperty("lexer.d.fold.at.else", &OptionsD::foldAtElseInt, + "This option enables D folding on a \"} else {\" line of an if statement."); + + DefineProperty("fold.at.else", &OptionsD::foldAtElse); + + DefineWordListSets(dWordLists); + } +}; + +class LexerD : public ILexer { + bool caseSensitive; + WordList keywords; + WordList keywords2; + WordList keywords3; + WordList keywords4; + WordList keywords5; + WordList keywords6; + WordList keywords7; + OptionsD options; + OptionSetD osD; +public: + LexerD(bool caseSensitive_) : + caseSensitive(caseSensitive_) { + } + ~LexerD() { + } + void SCI_METHOD Release() { + delete this; + } + int SCI_METHOD Version() const { + return lvOriginal; + } + const char * SCI_METHOD PropertyNames() { + return osD.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) { + return osD.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) { + return osD.DescribeProperty(name); + } + int SCI_METHOD PropertySet(const char *key, const char *val); + const char * SCI_METHOD DescribeWordListSets() { + return osD.DescribeWordListSets(); + } + int SCI_METHOD WordListSet(int n, const char *wl); + void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + + void * SCI_METHOD PrivateCall(int, void *) { + return 0; + } + + static ILexer *LexerFactoryD() { + return new LexerD(true); + } + static ILexer *LexerFactoryDInsensitive() { + return new LexerD(false); + } +}; + +int SCI_METHOD LexerD::PropertySet(const char *key, const char *val) { + if (osD.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +int SCI_METHOD LexerD::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywords; + break; + case 1: + wordListN = &keywords2; + break; + case 2: + wordListN = &keywords3; + break; + case 3: + wordListN = &keywords4; + break; + case 4: + wordListN = &keywords5; + break; + case 5: + wordListN = &keywords6; + break; + case 6: + wordListN = &keywords7; + break; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerD::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + + int styleBeforeDCKeyword = SCE_D_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + int curLine = styler.GetLine(startPos); + int curNcLevel = curLine > 0? styler.GetLineState(curLine-1): 0; + bool numFloat = false; // Float literals have '+' and '-' signs + bool numHex = false; + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart) { + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curNcLevel); + } + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_D_OPERATOR: + sc.SetState(SCE_D_DEFAULT); + break; + case SCE_D_NUMBER: + // We accept almost anything because of hex. and number suffixes + if (isascii(sc.ch) && (isalnum(sc.ch) || sc.ch == '_')) { + continue; + } else if (sc.ch == '.' && sc.chNext != '.' && !numFloat) { + // Don't parse 0..2 as number. + numFloat=true; + continue; + } else if ( ( sc.ch == '-' || sc.ch == '+' ) && ( /*sign and*/ + ( !numHex && ( sc.chPrev == 'e' || sc.chPrev == 'E' ) ) || /*decimal or*/ + ( sc.chPrev == 'p' || sc.chPrev == 'P' ) ) ) { /*hex*/ + // Parse exponent sign in float literals: 2e+10 0x2e+10 + continue; + } else { + sc.SetState(SCE_D_DEFAULT); + } + break; + case SCE_D_IDENTIFIER: + if (!IsWord(sc.ch)) { + char s[1000]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (keywords.InList(s)) { + sc.ChangeState(SCE_D_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_D_WORD2); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_D_TYPEDEF); + } else if (keywords5.InList(s)) { + sc.ChangeState(SCE_D_WORD5); + } else if (keywords6.InList(s)) { + sc.ChangeState(SCE_D_WORD6); + } else if (keywords7.InList(s)) { + sc.ChangeState(SCE_D_WORD7); + } + sc.SetState(SCE_D_DEFAULT); + } + break; + case SCE_D_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + case SCE_D_COMMENTDOC: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_D_COMMENTDOC; + sc.SetState(SCE_D_COMMENTDOCKEYWORD); + } + } + break; + case SCE_D_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_D_DEFAULT); + } + break; + case SCE_D_COMMENTLINEDOC: + if (sc.atLineStart) { + sc.SetState(SCE_D_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_D_COMMENTLINEDOC; + sc.SetState(SCE_D_COMMENTDOCKEYWORD); + } + } + break; + case SCE_D_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_D_COMMENTDOC) && sc.Match('*', '/')) { + sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } else if (!IsDoxygen(sc.ch)) { + char s[100]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { + sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_D_COMMENTNESTED: + if (sc.Match('+', '/')) { + if (curNcLevel > 0) + curNcLevel -= 1; + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curNcLevel); + sc.Forward(); + if (curNcLevel == 0) { + sc.ForwardSetState(SCE_D_DEFAULT); + } + } else if (sc.Match('/','+')) { + curNcLevel += 1; + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curNcLevel); + sc.Forward(); + } + break; + case SCE_D_STRING: + if (sc.ch == '\\') { + if (sc.chNext == '"' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '"') { + if(IsStringSuffix(sc.chNext)) + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + case SCE_D_CHARACTER: + if (sc.atLineEnd) { + sc.ChangeState(SCE_D_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + // Char has no suffixes + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + case SCE_D_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_D_DEFAULT); + } + break; + case SCE_D_STRINGB: + if (sc.ch == '`') { + if(IsStringSuffix(sc.chNext)) + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + case SCE_D_STRINGR: + if (sc.ch == '"') { + if(IsStringSuffix(sc.chNext)) + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_D_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_D_NUMBER); + numFloat = sc.ch == '.'; + // Remember hex literal + numHex = sc.ch == '0' && ( sc.chNext == 'x' || sc.chNext == 'X' ); + } else if ( (sc.ch == 'r' || sc.ch == 'x' || sc.ch == 'q') + && sc.chNext == '"' ) { + // Limited support for hex and delimited strings: parse as r"" + sc.SetState(SCE_D_STRINGR); + sc.Forward(); + } else if (IsWordStart(sc.ch) || sc.ch == '$') { + sc.SetState(SCE_D_IDENTIFIER); + } else if (sc.Match('/','+')) { + curNcLevel += 1; + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curNcLevel); + sc.SetState(SCE_D_COMMENTNESTED); + sc.Forward(); + } else if (sc.Match('/', '*')) { + if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style + sc.SetState(SCE_D_COMMENTDOC); + } else { + sc.SetState(SCE_D_COMMENT); + } + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) + // Support of Qt/Doxygen doc. style + sc.SetState(SCE_D_COMMENTLINEDOC); + else + sc.SetState(SCE_D_COMMENTLINE); + } else if (sc.ch == '"') { + sc.SetState(SCE_D_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_D_CHARACTER); + } else if (sc.ch == '`') { + sc.SetState(SCE_D_STRINGB); + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_D_OPERATOR); + if (sc.ch == '.' && sc.chNext == '.') sc.Forward(); // Range operator + } + } + } + sc.Complete(); +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". + +void SCI_METHOD LexerD::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + bool foldAtElse = options.foldAtElseInt >= 0 ? options.foldAtElseInt != 0 : options.foldAtElse; + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (options.foldComment && options.foldCommentExplicit && ((style == SCE_D_COMMENTLINE) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { + levelNext++; + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + levelNext--; + } + } else { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelNext++; + } else if (chNext2 == '}') { + levelNext--; + } + } + } + } + if (options.foldSyntaxBased && (style == SCE_D_OPERATOR)) { + if (ch == '{') { + // Measure the minimum before a '{' to allow + // folding on "} else {" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + if (atEOL || (i == endPos-1)) { + if (options.foldComment && options.foldCommentMultiline) { // Handle nested comments + int nc; + nc = styler.GetLineState(lineCurrent); + nc -= lineCurrent>0? styler.GetLineState(lineCurrent-1): 0; + levelNext += nc; + } + int levelUse = levelCurrent; + if (options.foldSyntaxBased && foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && options.foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + visibleChars = 0; + } + if (!IsASpace(ch)) + visibleChars++; + } +} + +LexerModule lmD(SCLEX_D, LexerD::LexerFactoryD, "d", dWordLists); diff --git a/scintilla/lexers/LexEScript.cxx b/ThirdLibs/scintilla/lexers/LexEScript.cxx similarity index 96% rename from scintilla/lexers/LexEScript.cxx rename to ThirdLibs/scintilla/lexers/LexEScript.cxx index d11d4215..9a7560e1 100644 --- a/scintilla/lexers/LexEScript.cxx +++ b/ThirdLibs/scintilla/lexers/LexEScript.cxx @@ -1,276 +1,276 @@ -// Scintilla source code edit control -/** @file LexESCRIPT.cxx - ** Lexer for ESCRIPT - **/ -// Copyright 2003 by Patrizio Bekerle (patrizio@bekerle.com) - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - - - -static void ColouriseESCRIPTDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - - // Do not leak onto next line - /*if (initStyle == SCE_ESCRIPT_STRINGEOL) - initStyle = SCE_ESCRIPT_DEFAULT;*/ - - StyleContext sc(startPos, length, initStyle, styler); - - bool caseSensitive = styler.GetPropertyInt("escript.case.sensitive", 0) != 0; - - for (; sc.More(); sc.Forward()) { - - /*if (sc.atLineStart && (sc.state == SCE_ESCRIPT_STRING)) { - // Prevent SCE_ESCRIPT_STRINGEOL from leaking back to previous line - sc.SetState(SCE_ESCRIPT_STRING); - }*/ - - // Handle line continuation generically. - if (sc.ch == '\\') { - if (sc.chNext == '\n' || sc.chNext == '\r') { - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - sc.Forward(); - } - continue; - } - } - - // Determine if the current state should terminate. - if (sc.state == SCE_ESCRIPT_OPERATOR || sc.state == SCE_ESCRIPT_BRACE) { - sc.SetState(SCE_ESCRIPT_DEFAULT); - } else if (sc.state == SCE_ESCRIPT_NUMBER) { - if (!IsADigit(sc.ch) || sc.ch != '.') { - sc.SetState(SCE_ESCRIPT_DEFAULT); - } - } else if (sc.state == SCE_ESCRIPT_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { - char s[100]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - -// sc.GetCurrentLowered(s, sizeof(s)); - - if (keywords.InList(s)) { - sc.ChangeState(SCE_ESCRIPT_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_ESCRIPT_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_ESCRIPT_WORD3); - // sc.state = SCE_ESCRIPT_IDENTIFIER; - } - sc.SetState(SCE_ESCRIPT_DEFAULT); - } - } else if (sc.state == SCE_ESCRIPT_COMMENT) { - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); - } - } else if (sc.state == SCE_ESCRIPT_COMMENTDOC) { - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); - } - } else if (sc.state == SCE_ESCRIPT_COMMENTLINE) { - if (sc.atLineEnd) { - sc.SetState(SCE_ESCRIPT_DEFAULT); - } - } else if (sc.state == SCE_ESCRIPT_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_ESCRIPT_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_ESCRIPT_NUMBER); - } else if (IsAWordStart(sc.ch) || (sc.ch == '#')) { - sc.SetState(SCE_ESCRIPT_IDENTIFIER); - } else if (sc.Match('/', '*')) { - sc.SetState(SCE_ESCRIPT_COMMENT); - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('/', '/')) { - sc.SetState(SCE_ESCRIPT_COMMENTLINE); - } else if (sc.ch == '\"') { - sc.SetState(SCE_ESCRIPT_STRING); - //} else if (isoperator(static_cast(sc.ch))) { - } else if (sc.ch == '+' || sc.ch == '-' || sc.ch == '*' || sc.ch == '/' || sc.ch == '=' || sc.ch == '<' || sc.ch == '>' || sc.ch == '&' || sc.ch == '|' || sc.ch == '!' || sc.ch == '?' || sc.ch == ':') { - sc.SetState(SCE_ESCRIPT_OPERATOR); - } else if (sc.ch == '{' || sc.ch == '}') { - sc.SetState(SCE_ESCRIPT_BRACE); - } - } - - } - sc.Complete(); -} - - -static int classifyFoldPointESCRIPT(const char* s, const char* prevWord) { - int lev = 0; - if (strcmp(prevWord, "end") == 0) return lev; - if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "elseif") == 0) - return -1; - - if (strcmp(s, "for") == 0 || strcmp(s, "foreach") == 0 - || strcmp(s, "program") == 0 || strcmp(s, "function") == 0 - || strcmp(s, "while") == 0 || strcmp(s, "case") == 0 - || strcmp(s, "if") == 0 ) { - lev = 1; - } else if ( strcmp(s, "endfor") == 0 || strcmp(s, "endforeach") == 0 - || strcmp(s, "endprogram") == 0 || strcmp(s, "endfunction") == 0 - || strcmp(s, "endwhile") == 0 || strcmp(s, "endcase") == 0 - || strcmp(s, "endif") == 0 ) { - lev = -1; - } - - return lev; -} - - -static bool IsStreamCommentStyle(int style) { - return style == SCE_ESCRIPT_COMMENT || - style == SCE_ESCRIPT_COMMENTDOC || - style == SCE_ESCRIPT_COMMENTLINE; -} - -static void FoldESCRIPTDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { - //~ bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - // Do not know how to fold the comment at the moment. - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldComment = true; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - - int lastStart = 0; - char prevWord[32] = ""; - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - - if (foldComment && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev)) { - levelCurrent++; - } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelCurrent--; - } - } - - if (foldComment && (style == SCE_ESCRIPT_COMMENTLINE)) { - if ((ch == '/') && (chNext == '/')) { - char chNext2 = styler.SafeGetCharAt(i + 2); - if (chNext2 == '{') { - levelCurrent++; - } else if (chNext2 == '}') { - levelCurrent--; - } - } - } - - if (stylePrev == SCE_ESCRIPT_DEFAULT && style == SCE_ESCRIPT_WORD3) - { - // Store last word start point. - lastStart = i; - } - - if (style == SCE_ESCRIPT_WORD3) { - if(iswordchar(ch) && !iswordchar(chNext)) { - char s[32]; - unsigned int j; - for(j = 0; ( j < 31 ) && ( j < i-lastStart+1 ); j++) { - s[j] = static_cast(tolower(styler[lastStart + j])); - } - s[j] = '\0'; - levelCurrent += classifyFoldPointESCRIPT(s, prevWord); - strcpy(prevWord, s); - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - strcpy(prevWord, ""); - } - - if (!isspacechar(ch)) - visibleChars++; - } - - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - - - -static const char * const ESCRIPTWordLists[] = { - "Primary keywords and identifiers", - "Intrinsic functions", - "Extended and user defined functions", - 0, -}; - -LexerModule lmESCRIPT(SCLEX_ESCRIPT, ColouriseESCRIPTDoc, "escript", FoldESCRIPTDoc, ESCRIPTWordLists); +// Scintilla source code edit control +/** @file LexESCRIPT.cxx + ** Lexer for ESCRIPT + **/ +// Copyright 2003 by Patrizio Bekerle (patrizio@bekerle.com) + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + + + +static void ColouriseESCRIPTDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + + // Do not leak onto next line + /*if (initStyle == SCE_ESCRIPT_STRINGEOL) + initStyle = SCE_ESCRIPT_DEFAULT;*/ + + StyleContext sc(startPos, length, initStyle, styler); + + bool caseSensitive = styler.GetPropertyInt("escript.case.sensitive", 0) != 0; + + for (; sc.More(); sc.Forward()) { + + /*if (sc.atLineStart && (sc.state == SCE_ESCRIPT_STRING)) { + // Prevent SCE_ESCRIPT_STRINGEOL from leaking back to previous line + sc.SetState(SCE_ESCRIPT_STRING); + }*/ + + // Handle line continuation generically. + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continue; + } + } + + // Determine if the current state should terminate. + if (sc.state == SCE_ESCRIPT_OPERATOR || sc.state == SCE_ESCRIPT_BRACE) { + sc.SetState(SCE_ESCRIPT_DEFAULT); + } else if (sc.state == SCE_ESCRIPT_NUMBER) { + if (!IsADigit(sc.ch) || sc.ch != '.') { + sc.SetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_IDENTIFIER) { + if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { + char s[100]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + +// sc.GetCurrentLowered(s, sizeof(s)); + + if (keywords.InList(s)) { + sc.ChangeState(SCE_ESCRIPT_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_ESCRIPT_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_ESCRIPT_WORD3); + // sc.state = SCE_ESCRIPT_IDENTIFIER; + } + sc.SetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_COMMENT) { + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_COMMENTDOC) { + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_COMMENTLINE) { + if (sc.atLineEnd) { + sc.SetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_ESCRIPT_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_ESCRIPT_NUMBER); + } else if (IsAWordStart(sc.ch) || (sc.ch == '#')) { + sc.SetState(SCE_ESCRIPT_IDENTIFIER); + } else if (sc.Match('/', '*')) { + sc.SetState(SCE_ESCRIPT_COMMENT); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + sc.SetState(SCE_ESCRIPT_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_ESCRIPT_STRING); + //} else if (isoperator(static_cast(sc.ch))) { + } else if (sc.ch == '+' || sc.ch == '-' || sc.ch == '*' || sc.ch == '/' || sc.ch == '=' || sc.ch == '<' || sc.ch == '>' || sc.ch == '&' || sc.ch == '|' || sc.ch == '!' || sc.ch == '?' || sc.ch == ':') { + sc.SetState(SCE_ESCRIPT_OPERATOR); + } else if (sc.ch == '{' || sc.ch == '}') { + sc.SetState(SCE_ESCRIPT_BRACE); + } + } + + } + sc.Complete(); +} + + +static int classifyFoldPointESCRIPT(const char* s, const char* prevWord) { + int lev = 0; + if (strcmp(prevWord, "end") == 0) return lev; + if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "elseif") == 0) + return -1; + + if (strcmp(s, "for") == 0 || strcmp(s, "foreach") == 0 + || strcmp(s, "program") == 0 || strcmp(s, "function") == 0 + || strcmp(s, "while") == 0 || strcmp(s, "case") == 0 + || strcmp(s, "if") == 0 ) { + lev = 1; + } else if ( strcmp(s, "endfor") == 0 || strcmp(s, "endforeach") == 0 + || strcmp(s, "endprogram") == 0 || strcmp(s, "endfunction") == 0 + || strcmp(s, "endwhile") == 0 || strcmp(s, "endcase") == 0 + || strcmp(s, "endif") == 0 ) { + lev = -1; + } + + return lev; +} + + +static bool IsStreamCommentStyle(int style) { + return style == SCE_ESCRIPT_COMMENT || + style == SCE_ESCRIPT_COMMENTDOC || + style == SCE_ESCRIPT_COMMENTLINE; +} + +static void FoldESCRIPTDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { + //~ bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + // Do not know how to fold the comment at the moment. + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldComment = true; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + + int lastStart = 0; + char prevWord[32] = ""; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + + if (foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelCurrent++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + + if (foldComment && (style == SCE_ESCRIPT_COMMENTLINE)) { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelCurrent++; + } else if (chNext2 == '}') { + levelCurrent--; + } + } + } + + if (stylePrev == SCE_ESCRIPT_DEFAULT && style == SCE_ESCRIPT_WORD3) + { + // Store last word start point. + lastStart = i; + } + + if (style == SCE_ESCRIPT_WORD3) { + if(iswordchar(ch) && !iswordchar(chNext)) { + char s[32]; + unsigned int j; + for(j = 0; ( j < 31 ) && ( j < i-lastStart+1 ); j++) { + s[j] = static_cast(tolower(styler[lastStart + j])); + } + s[j] = '\0'; + levelCurrent += classifyFoldPointESCRIPT(s, prevWord); + strcpy(prevWord, s); + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + strcpy(prevWord, ""); + } + + if (!isspacechar(ch)) + visibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + + + +static const char * const ESCRIPTWordLists[] = { + "Primary keywords and identifiers", + "Intrinsic functions", + "Extended and user defined functions", + 0, +}; + +LexerModule lmESCRIPT(SCLEX_ESCRIPT, ColouriseESCRIPTDoc, "escript", FoldESCRIPTDoc, ESCRIPTWordLists); diff --git a/scintilla/lexers/LexEiffel.cxx b/ThirdLibs/scintilla/lexers/LexEiffel.cxx similarity index 96% rename from scintilla/lexers/LexEiffel.cxx rename to ThirdLibs/scintilla/lexers/LexEiffel.cxx index 204d4580..067801ca 100644 --- a/scintilla/lexers/LexEiffel.cxx +++ b/ThirdLibs/scintilla/lexers/LexEiffel.cxx @@ -1,241 +1,241 @@ -// Scintilla source code edit control -/** @file LexEiffel.cxx - ** Lexer for Eiffel. - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool isEiffelOperator(unsigned int ch) { - // '.' left out as it is used to make up numbers - return ch == '*' || ch == '/' || ch == '\\' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || - ch == '{' || ch == '}' || ch == '~' || - ch == '[' || ch == ']' || ch == ';' || - ch == '<' || ch == '>' || ch == ',' || - ch == '.' || ch == '^' || ch == '%' || ch == ':' || - ch == '!' || ch == '@' || ch == '?'; -} - -static inline bool IsAWordChar(unsigned int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAWordStart(unsigned int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static void ColouriseEiffelDoc(unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.state == SCE_EIFFEL_STRINGEOL) { - if (sc.ch != '\r' && sc.ch != '\n') { - sc.SetState(SCE_EIFFEL_DEFAULT); - } - } else if (sc.state == SCE_EIFFEL_OPERATOR) { - sc.SetState(SCE_EIFFEL_DEFAULT); - } else if (sc.state == SCE_EIFFEL_WORD) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (!keywords.InList(s)) { - sc.ChangeState(SCE_EIFFEL_IDENTIFIER); - } - sc.SetState(SCE_EIFFEL_DEFAULT); - } - } else if (sc.state == SCE_EIFFEL_NUMBER) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_EIFFEL_DEFAULT); - } - } else if (sc.state == SCE_EIFFEL_COMMENTLINE) { - if (sc.ch == '\r' || sc.ch == '\n') { - sc.SetState(SCE_EIFFEL_DEFAULT); - } - } else if (sc.state == SCE_EIFFEL_STRING) { - if (sc.ch == '%') { - sc.Forward(); - } else if (sc.ch == '\"') { - sc.Forward(); - sc.SetState(SCE_EIFFEL_DEFAULT); - } - } else if (sc.state == SCE_EIFFEL_CHARACTER) { - if (sc.ch == '\r' || sc.ch == '\n') { - sc.SetState(SCE_EIFFEL_STRINGEOL); - } else if (sc.ch == '%') { - sc.Forward(); - } else if (sc.ch == '\'') { - sc.Forward(); - sc.SetState(SCE_EIFFEL_DEFAULT); - } - } - - if (sc.state == SCE_EIFFEL_DEFAULT) { - if (sc.ch == '-' && sc.chNext == '-') { - sc.SetState(SCE_EIFFEL_COMMENTLINE); - } else if (sc.ch == '\"') { - sc.SetState(SCE_EIFFEL_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_EIFFEL_CHARACTER); - } else if (IsADigit(sc.ch) || (sc.ch == '.')) { - sc.SetState(SCE_EIFFEL_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_EIFFEL_WORD); - } else if (isEiffelOperator(sc.ch)) { - sc.SetState(SCE_EIFFEL_OPERATOR); - } - } - } - sc.Complete(); -} - -static bool IsEiffelComment(Accessor &styler, int pos, int len) { - return len>1 && styler[pos]=='-' && styler[pos+1]=='-'; -} - -static void FoldEiffelDocIndent(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) { - int lengthDoc = startPos + length; - - // Backtrack to previous line in case need to fix its fold status - int lineCurrent = styler.GetLine(startPos); - if (startPos > 0) { - if (lineCurrent > 0) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); - } - } - int spaceFlags = 0; - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsEiffelComment); - char chNext = styler[startPos]; - for (int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) { - int lev = indentCurrent; - int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsEiffelComment); - if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { - // Only non whitespace lines can be headers - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { - // Line after is blank so check the next - maybe should continue further? - int spaceFlags2 = 0; - int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsEiffelComment); - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - } - } - indentCurrent = indentNext; - styler.SetLevel(lineCurrent, lev); - lineCurrent++; - } - } -} - -static void FoldEiffelDocKeyWords(unsigned int startPos, int length, int /* initStyle */, WordList *[], - Accessor &styler) { - unsigned int lengthDoc = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int stylePrev = 0; - int styleNext = styler.StyleAt(startPos); - // lastDeferred should be determined by looking back to last keyword in case - // the "deferred" is on a line before "class" - bool lastDeferred = false; - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if ((stylePrev != SCE_EIFFEL_WORD) && (style == SCE_EIFFEL_WORD)) { - char s[20]; - unsigned int j = 0; - while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) { - s[j] = styler[i + j]; - j++; - } - s[j] = '\0'; - - if ( - (strcmp(s, "check") == 0) || - (strcmp(s, "debug") == 0) || - (strcmp(s, "deferred") == 0) || - (strcmp(s, "do") == 0) || - (strcmp(s, "from") == 0) || - (strcmp(s, "if") == 0) || - (strcmp(s, "inspect") == 0) || - (strcmp(s, "once") == 0) - ) - levelCurrent++; - if (!lastDeferred && (strcmp(s, "class") == 0)) - levelCurrent++; - if (strcmp(s, "end") == 0) - levelCurrent--; - lastDeferred = strcmp(s, "deferred") == 0; - } - - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - stylePrev = style; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const eiffelWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmEiffel(SCLEX_EIFFEL, ColouriseEiffelDoc, "eiffel", FoldEiffelDocIndent, eiffelWordListDesc); -LexerModule lmEiffelkw(SCLEX_EIFFELKW, ColouriseEiffelDoc, "eiffelkw", FoldEiffelDocKeyWords, eiffelWordListDesc); +// Scintilla source code edit control +/** @file LexEiffel.cxx + ** Lexer for Eiffel. + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool isEiffelOperator(unsigned int ch) { + // '.' left out as it is used to make up numbers + return ch == '*' || ch == '/' || ch == '\\' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || + ch == '{' || ch == '}' || ch == '~' || + ch == '[' || ch == ']' || ch == ';' || + ch == '<' || ch == '>' || ch == ',' || + ch == '.' || ch == '^' || ch == '%' || ch == ':' || + ch == '!' || ch == '@' || ch == '?'; +} + +static inline bool IsAWordChar(unsigned int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(unsigned int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static void ColouriseEiffelDoc(unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.state == SCE_EIFFEL_STRINGEOL) { + if (sc.ch != '\r' && sc.ch != '\n') { + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_OPERATOR) { + sc.SetState(SCE_EIFFEL_DEFAULT); + } else if (sc.state == SCE_EIFFEL_WORD) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (!keywords.InList(s)) { + sc.ChangeState(SCE_EIFFEL_IDENTIFIER); + } + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_COMMENTLINE) { + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_STRING) { + if (sc.ch == '%') { + sc.Forward(); + } else if (sc.ch == '\"') { + sc.Forward(); + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_CHARACTER) { + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_EIFFEL_STRINGEOL); + } else if (sc.ch == '%') { + sc.Forward(); + } else if (sc.ch == '\'') { + sc.Forward(); + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } + + if (sc.state == SCE_EIFFEL_DEFAULT) { + if (sc.ch == '-' && sc.chNext == '-') { + sc.SetState(SCE_EIFFEL_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_EIFFEL_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_EIFFEL_CHARACTER); + } else if (IsADigit(sc.ch) || (sc.ch == '.')) { + sc.SetState(SCE_EIFFEL_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_EIFFEL_WORD); + } else if (isEiffelOperator(sc.ch)) { + sc.SetState(SCE_EIFFEL_OPERATOR); + } + } + } + sc.Complete(); +} + +static bool IsEiffelComment(Accessor &styler, int pos, int len) { + return len>1 && styler[pos]=='-' && styler[pos+1]=='-'; +} + +static void FoldEiffelDocIndent(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) { + int lengthDoc = startPos + length; + + // Backtrack to previous line in case need to fix its fold status + int lineCurrent = styler.GetLine(startPos); + if (startPos > 0) { + if (lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + } + int spaceFlags = 0; + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsEiffelComment); + char chNext = styler[startPos]; + for (int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) { + int lev = indentCurrent; + int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsEiffelComment); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + // Only non whitespace lines can be headers + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { + // Line after is blank so check the next - maybe should continue further? + int spaceFlags2 = 0; + int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsEiffelComment); + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + } + } + indentCurrent = indentNext; + styler.SetLevel(lineCurrent, lev); + lineCurrent++; + } + } +} + +static void FoldEiffelDocKeyWords(unsigned int startPos, int length, int /* initStyle */, WordList *[], + Accessor &styler) { + unsigned int lengthDoc = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int stylePrev = 0; + int styleNext = styler.StyleAt(startPos); + // lastDeferred should be determined by looking back to last keyword in case + // the "deferred" is on a line before "class" + bool lastDeferred = false; + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if ((stylePrev != SCE_EIFFEL_WORD) && (style == SCE_EIFFEL_WORD)) { + char s[20]; + unsigned int j = 0; + while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) { + s[j] = styler[i + j]; + j++; + } + s[j] = '\0'; + + if ( + (strcmp(s, "check") == 0) || + (strcmp(s, "debug") == 0) || + (strcmp(s, "deferred") == 0) || + (strcmp(s, "do") == 0) || + (strcmp(s, "from") == 0) || + (strcmp(s, "if") == 0) || + (strcmp(s, "inspect") == 0) || + (strcmp(s, "once") == 0) + ) + levelCurrent++; + if (!lastDeferred && (strcmp(s, "class") == 0)) + levelCurrent++; + if (strcmp(s, "end") == 0) + levelCurrent--; + lastDeferred = strcmp(s, "deferred") == 0; + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + stylePrev = style; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const eiffelWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmEiffel(SCLEX_EIFFEL, ColouriseEiffelDoc, "eiffel", FoldEiffelDocIndent, eiffelWordListDesc); +LexerModule lmEiffelkw(SCLEX_EIFFELKW, ColouriseEiffelDoc, "eiffelkw", FoldEiffelDocKeyWords, eiffelWordListDesc); diff --git a/scintilla/lexers/LexErlang.cxx b/ThirdLibs/scintilla/lexers/LexErlang.cxx similarity index 96% rename from scintilla/lexers/LexErlang.cxx rename to ThirdLibs/scintilla/lexers/LexErlang.cxx index d8e15ccd..5f522585 100644 --- a/scintilla/lexers/LexErlang.cxx +++ b/ThirdLibs/scintilla/lexers/LexErlang.cxx @@ -1,623 +1,623 @@ -// Scintilla source code edit control -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. -/** @file LexErlang.cxx - ** Lexer for Erlang. - ** Enhanced by Etienne 'Lenain' Girondel (lenaing@gmail.com) - ** Originally wrote by Peter-Henry Mander, - ** based on Matlab lexer by Jos Fonseca. - **/ - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static int is_radix(int radix, int ch) { - int digit; - - if (36 < radix || 2 > radix) - return 0; - - if (isdigit(ch)) { - digit = ch - '0'; - } else if (isalnum(ch)) { - digit = toupper(ch) - 'A' + 10; - } else { - return 0; - } - - return (digit < radix); -} - -typedef enum { - STATE_NULL, - COMMENT, - COMMENT_FUNCTION, - COMMENT_MODULE, - COMMENT_DOC, - COMMENT_DOC_MACRO, - ATOM_UNQUOTED, - ATOM_QUOTED, - NODE_NAME_UNQUOTED, - NODE_NAME_QUOTED, - MACRO_START, - MACRO_UNQUOTED, - MACRO_QUOTED, - RECORD_START, - RECORD_UNQUOTED, - RECORD_QUOTED, - NUMERAL_START, - NUMERAL_BASE_VALUE, - NUMERAL_FLOAT, - NUMERAL_EXPONENT, - PREPROCESSOR -} atom_parse_state_t; - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (ch != ' ') && (isalnum(ch) || ch == '_'); -} - -static void ColouriseErlangDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - StyleContext sc(startPos, length, initStyle, styler); - WordList &reservedWords = *keywordlists[0]; - WordList &erlangBIFs = *keywordlists[1]; - WordList &erlangPreproc = *keywordlists[2]; - WordList &erlangModulesAtt = *keywordlists[3]; - WordList &erlangDoc = *keywordlists[4]; - WordList &erlangDocMacro = *keywordlists[5]; - int radix_digits = 0; - int exponent_digits = 0; - atom_parse_state_t parse_state = STATE_NULL; - atom_parse_state_t old_parse_state = STATE_NULL; - bool to_late_to_comment = false; - char cur[100]; - int old_style = SCE_ERLANG_DEFAULT; - - styler.StartAt(startPos); - - for (; sc.More(); sc.Forward()) { - int style = SCE_ERLANG_DEFAULT; - if (STATE_NULL != parse_state) { - - switch (parse_state) { - - case STATE_NULL : sc.SetState(SCE_ERLANG_DEFAULT); break; - - /* COMMENTS ------------------------------------------------------*/ - case COMMENT : { - if (sc.ch != '%') { - to_late_to_comment = true; - } else if (!to_late_to_comment && sc.ch == '%') { - // Switch to comment level 2 (Function) - sc.ChangeState(SCE_ERLANG_COMMENT_FUNCTION); - old_style = SCE_ERLANG_COMMENT_FUNCTION; - parse_state = COMMENT_FUNCTION; - sc.Forward(); - } - } - // V--- Falling through! - case COMMENT_FUNCTION : { - if (sc.ch != '%') { - to_late_to_comment = true; - } else if (!to_late_to_comment && sc.ch == '%') { - // Switch to comment level 3 (Module) - sc.ChangeState(SCE_ERLANG_COMMENT_MODULE); - old_style = SCE_ERLANG_COMMENT_MODULE; - parse_state = COMMENT_MODULE; - sc.Forward(); - } - } - // V--- Falling through! - case COMMENT_MODULE : { - if (parse_state != COMMENT) { - // Search for comment documentation - if (sc.chNext == '@') { - old_parse_state = parse_state; - parse_state = ('{' == sc.ch) - ? COMMENT_DOC_MACRO - : COMMENT_DOC; - sc.ForwardSetState(sc.state); - } - } - - // All comments types fall here. - if (sc.atLineEnd) { - to_late_to_comment = false; - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - case COMMENT_DOC : - // V--- Falling through! - case COMMENT_DOC_MACRO : { - - if (!isalnum(sc.ch)) { - // Try to match documentation comment - sc.GetCurrent(cur, sizeof(cur)); - - if (parse_state == COMMENT_DOC_MACRO - && erlangDocMacro.InList(cur)) { - sc.ChangeState(SCE_ERLANG_COMMENT_DOC_MACRO); - while (sc.ch != '}' && !sc.atLineEnd) - sc.Forward(); - } else if (erlangDoc.InList(cur)) { - sc.ChangeState(SCE_ERLANG_COMMENT_DOC); - } else { - sc.ChangeState(old_style); - } - - // Switch back to old state - sc.SetState(old_style); - parse_state = old_parse_state; - } - - if (sc.atLineEnd) { - to_late_to_comment = false; - sc.ChangeState(old_style); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* -------------------------------------------------------------- */ - /* Atoms ---------------------------------------------------------*/ - case ATOM_UNQUOTED : { - if ('@' == sc.ch){ - parse_state = NODE_NAME_UNQUOTED; - } else if (sc.ch == ':') { - // Searching for module name - if (sc.chNext == ' ') { - // error - sc.ChangeState(SCE_ERLANG_UNKNOWN); - parse_state = STATE_NULL; - } else { - sc.Forward(); - if (isalnum(sc.ch)) { - sc.GetCurrent(cur, sizeof(cur)); - sc.ChangeState(SCE_ERLANG_MODULES); - sc.SetState(SCE_ERLANG_MODULES); - } - } - } else if (!IsAWordChar(sc.ch)) { - - sc.GetCurrent(cur, sizeof(cur)); - if (reservedWords.InList(cur)) { - style = SCE_ERLANG_KEYWORD; - } else if (erlangBIFs.InList(cur) - && strcmp(cur,"erlang:")){ - style = SCE_ERLANG_BIFS; - } else if (sc.ch == '(' || '/' == sc.ch){ - style = SCE_ERLANG_FUNCTION_NAME; - } else { - style = SCE_ERLANG_ATOM; - } - - sc.ChangeState(style); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - - } break; - - case ATOM_QUOTED : { - if ( '@' == sc.ch ){ - parse_state = NODE_NAME_QUOTED; - } else if ('\'' == sc.ch && '\\' != sc.chPrev) { - sc.ChangeState(SCE_ERLANG_ATOM); - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* -------------------------------------------------------------- */ - /* Node names ----------------------------------------------------*/ - case NODE_NAME_UNQUOTED : { - if ('@' == sc.ch) { - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } else if (!IsAWordChar(sc.ch)) { - sc.ChangeState(SCE_ERLANG_NODE_NAME); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - case NODE_NAME_QUOTED : { - if ('@' == sc.ch) { - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } else if ('\'' == sc.ch && '\\' != sc.chPrev) { - sc.ChangeState(SCE_ERLANG_NODE_NAME_QUOTED); - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* -------------------------------------------------------------- */ - /* Records -------------------------------------------------------*/ - case RECORD_START : { - if ('\'' == sc.ch) { - parse_state = RECORD_QUOTED; - } else if (isalpha(sc.ch) && islower(sc.ch)) { - parse_state = RECORD_UNQUOTED; - } else { // error - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - case RECORD_UNQUOTED : { - if (!IsAWordChar(sc.ch)) { - sc.ChangeState(SCE_ERLANG_RECORD); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - case RECORD_QUOTED : { - if ('\'' == sc.ch && '\\' != sc.chPrev) { - sc.ChangeState(SCE_ERLANG_RECORD_QUOTED); - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* -------------------------------------------------------------- */ - /* Macros --------------------------------------------------------*/ - case MACRO_START : { - if ('\'' == sc.ch) { - parse_state = MACRO_QUOTED; - } else if (isalpha(sc.ch)) { - parse_state = MACRO_UNQUOTED; - } else { // error - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - case MACRO_UNQUOTED : { - if (!IsAWordChar(sc.ch)) { - sc.ChangeState(SCE_ERLANG_MACRO); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - case MACRO_QUOTED : { - if ('\'' == sc.ch && '\\' != sc.chPrev) { - sc.ChangeState(SCE_ERLANG_MACRO_QUOTED); - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* -------------------------------------------------------------- */ - /* Numerics ------------------------------------------------------*/ - /* Simple integer */ - case NUMERAL_START : { - if (isdigit(sc.ch)) { - radix_digits *= 10; - radix_digits += sc.ch - '0'; // Assuming ASCII here! - } else if ('#' == sc.ch) { - if (2 > radix_digits || 36 < radix_digits) { - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } else { - parse_state = NUMERAL_BASE_VALUE; - } - } else if ('.' == sc.ch && isdigit(sc.chNext)) { - radix_digits = 0; - parse_state = NUMERAL_FLOAT; - } else if ('e' == sc.ch || 'E' == sc.ch) { - exponent_digits = 0; - parse_state = NUMERAL_EXPONENT; - } else { - radix_digits = 0; - sc.ChangeState(SCE_ERLANG_NUMBER); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* Integer in other base than 10 (x#yyy) */ - case NUMERAL_BASE_VALUE : { - if (!is_radix(radix_digits,sc.ch)) { - radix_digits = 0; - - if (!isalnum(sc.ch)) - sc.ChangeState(SCE_ERLANG_NUMBER); - - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* Float (x.yyy) */ - case NUMERAL_FLOAT : { - if ('e' == sc.ch || 'E' == sc.ch) { - exponent_digits = 0; - parse_state = NUMERAL_EXPONENT; - } else if (!isdigit(sc.ch)) { - sc.ChangeState(SCE_ERLANG_NUMBER); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* Exponent, either integer or float (xEyy, x.yyEzzz) */ - case NUMERAL_EXPONENT : { - if (('-' == sc.ch || '+' == sc.ch) - && (isdigit(sc.chNext))) { - sc.Forward(); - } else if (!isdigit(sc.ch)) { - if (0 < exponent_digits) - sc.ChangeState(SCE_ERLANG_NUMBER); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } else { - ++exponent_digits; - } - } break; - - /* -------------------------------------------------------------- */ - /* Preprocessor --------------------------------------------------*/ - case PREPROCESSOR : { - if (!IsAWordChar(sc.ch)) { - - sc.GetCurrent(cur, sizeof(cur)); - if (erlangPreproc.InList(cur)) { - style = SCE_ERLANG_PREPROC; - } else if (erlangModulesAtt.InList(cur)) { - style = SCE_ERLANG_MODULES_ATT; - } - - sc.ChangeState(style); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - } - - } /* End of : STATE_NULL != parse_state */ - else - { - switch (sc.state) { - case SCE_ERLANG_VARIABLE : { - if (!IsAWordChar(sc.ch)) - sc.SetState(SCE_ERLANG_DEFAULT); - } break; - case SCE_ERLANG_STRING : { - if (sc.ch == '\"' && sc.chPrev != '\\') - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - } break; - case SCE_ERLANG_COMMENT : { - if (sc.atLineEnd) - sc.SetState(SCE_ERLANG_DEFAULT); - } break; - case SCE_ERLANG_CHARACTER : { - if (sc.chPrev == '\\') { - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - } else if (sc.ch != '\\') { - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - } - } break; - case SCE_ERLANG_OPERATOR : { - if (sc.chPrev == '.') { - if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' - || sc.ch == '^') { - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - } else { - sc.SetState(SCE_ERLANG_DEFAULT); - } - } else { - sc.SetState(SCE_ERLANG_DEFAULT); - } - } break; - } - } - - if (sc.state == SCE_ERLANG_DEFAULT) { - bool no_new_state = false; - - switch (sc.ch) { - case '\"' : sc.SetState(SCE_ERLANG_STRING); break; - case '$' : sc.SetState(SCE_ERLANG_CHARACTER); break; - case '%' : { - parse_state = COMMENT; - sc.SetState(SCE_ERLANG_COMMENT); - } break; - case '#' : { - parse_state = RECORD_START; - sc.SetState(SCE_ERLANG_UNKNOWN); - } break; - case '?' : { - parse_state = MACRO_START; - sc.SetState(SCE_ERLANG_UNKNOWN); - } break; - case '\'' : { - parse_state = ATOM_QUOTED; - sc.SetState(SCE_ERLANG_UNKNOWN); - } break; - case '+' : - case '-' : { - if (IsADigit(sc.chNext)) { - parse_state = NUMERAL_START; - radix_digits = 0; - sc.SetState(SCE_ERLANG_UNKNOWN); - } else if (sc.ch != '+') { - parse_state = PREPROCESSOR; - sc.SetState(SCE_ERLANG_UNKNOWN); - } - } break; - default : no_new_state = true; - } - - if (no_new_state) { - if (isdigit(sc.ch)) { - parse_state = NUMERAL_START; - radix_digits = sc.ch - '0'; - sc.SetState(SCE_ERLANG_UNKNOWN); - } else if (isupper(sc.ch) || '_' == sc.ch) { - sc.SetState(SCE_ERLANG_VARIABLE); - } else if (isalpha(sc.ch)) { - parse_state = ATOM_UNQUOTED; - sc.SetState(SCE_ERLANG_UNKNOWN); - } else if (isoperator(static_cast(sc.ch)) - || sc.ch == '\\') { - sc.SetState(SCE_ERLANG_OPERATOR); - } - } - } - - } - sc.Complete(); -} - -static int ClassifyErlangFoldPoint( - Accessor &styler, - int styleNext, - int keyword_start -) { - int lev = 0; - if (styler.Match(keyword_start,"case") - || ( - styler.Match(keyword_start,"fun") - && (SCE_ERLANG_FUNCTION_NAME != styleNext) - ) - || styler.Match(keyword_start,"if") - || styler.Match(keyword_start,"query") - || styler.Match(keyword_start,"receive") - ) { - ++lev; - } else if (styler.Match(keyword_start,"end")) { - --lev; - } - - return lev; -} - -static void FoldErlangDoc( - unsigned int startPos, int length, int initStyle, - WordList** /*keywordlists*/, Accessor &styler -) { - unsigned int endPos = startPos + length; - int currentLine = styler.GetLine(startPos); - int lev; - int previousLevel = styler.LevelAt(currentLine) & SC_FOLDLEVELNUMBERMASK; - int currentLevel = previousLevel; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - int stylePrev; - int keyword_start = 0; - char ch; - char chNext = styler.SafeGetCharAt(startPos); - bool atEOL; - - for (unsigned int i = startPos; i < endPos; i++) { - ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - // Get styles - stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - atEOL = ((ch == '\r') && (chNext != '\n')) || (ch == '\n'); - - if (stylePrev != SCE_ERLANG_KEYWORD - && style == SCE_ERLANG_KEYWORD) { - keyword_start = i; - } - - // Fold on keywords - if (stylePrev == SCE_ERLANG_KEYWORD - && style != SCE_ERLANG_KEYWORD - && style != SCE_ERLANG_ATOM - ) { - currentLevel += ClassifyErlangFoldPoint(styler, - styleNext, - keyword_start); - } - - // Fold on comments - if (style == SCE_ERLANG_COMMENT - || style == SCE_ERLANG_COMMENT_MODULE - || style == SCE_ERLANG_COMMENT_FUNCTION) { - - if (ch == '%' && chNext == '{') { - currentLevel++; - } else if (ch == '%' && chNext == '}') { - currentLevel--; - } - } - - // Fold on braces - if (style == SCE_ERLANG_OPERATOR) { - if (ch == '{' || ch == '(' || ch == '[') { - currentLevel++; - } else if (ch == '}' || ch == ')' || ch == ']') { - currentLevel--; - } - } - - - if (atEOL) { - lev = previousLevel; - - if (currentLevel > previousLevel) - lev |= SC_FOLDLEVELHEADERFLAG; - - if (lev != styler.LevelAt(currentLine)) - styler.SetLevel(currentLine, lev); - - currentLine++; - previousLevel = currentLevel; - } - - } - - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - styler.SetLevel(currentLine, - previousLevel - | (styler.LevelAt(currentLine) & ~SC_FOLDLEVELNUMBERMASK)); -} - -static const char * const erlangWordListDesc[] = { - "Erlang Reserved words", - "Erlang BIFs", - "Erlang Preprocessor", - "Erlang Module Attributes", - "Erlang Documentation", - "Erlang Documentation Macro", - 0 -}; - -LexerModule lmErlang( - SCLEX_ERLANG, - ColouriseErlangDoc, - "erlang", - FoldErlangDoc, - erlangWordListDesc); +// Scintilla source code edit control +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. +/** @file LexErlang.cxx + ** Lexer for Erlang. + ** Enhanced by Etienne 'Lenain' Girondel (lenaing@gmail.com) + ** Originally wrote by Peter-Henry Mander, + ** based on Matlab lexer by Jos Fonseca. + **/ + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static int is_radix(int radix, int ch) { + int digit; + + if (36 < radix || 2 > radix) + return 0; + + if (isdigit(ch)) { + digit = ch - '0'; + } else if (isalnum(ch)) { + digit = toupper(ch) - 'A' + 10; + } else { + return 0; + } + + return (digit < radix); +} + +typedef enum { + STATE_NULL, + COMMENT, + COMMENT_FUNCTION, + COMMENT_MODULE, + COMMENT_DOC, + COMMENT_DOC_MACRO, + ATOM_UNQUOTED, + ATOM_QUOTED, + NODE_NAME_UNQUOTED, + NODE_NAME_QUOTED, + MACRO_START, + MACRO_UNQUOTED, + MACRO_QUOTED, + RECORD_START, + RECORD_UNQUOTED, + RECORD_QUOTED, + NUMERAL_START, + NUMERAL_BASE_VALUE, + NUMERAL_FLOAT, + NUMERAL_EXPONENT, + PREPROCESSOR +} atom_parse_state_t; + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (ch != ' ') && (isalnum(ch) || ch == '_'); +} + +static void ColouriseErlangDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + StyleContext sc(startPos, length, initStyle, styler); + WordList &reservedWords = *keywordlists[0]; + WordList &erlangBIFs = *keywordlists[1]; + WordList &erlangPreproc = *keywordlists[2]; + WordList &erlangModulesAtt = *keywordlists[3]; + WordList &erlangDoc = *keywordlists[4]; + WordList &erlangDocMacro = *keywordlists[5]; + int radix_digits = 0; + int exponent_digits = 0; + atom_parse_state_t parse_state = STATE_NULL; + atom_parse_state_t old_parse_state = STATE_NULL; + bool to_late_to_comment = false; + char cur[100]; + int old_style = SCE_ERLANG_DEFAULT; + + styler.StartAt(startPos); + + for (; sc.More(); sc.Forward()) { + int style = SCE_ERLANG_DEFAULT; + if (STATE_NULL != parse_state) { + + switch (parse_state) { + + case STATE_NULL : sc.SetState(SCE_ERLANG_DEFAULT); break; + + /* COMMENTS ------------------------------------------------------*/ + case COMMENT : { + if (sc.ch != '%') { + to_late_to_comment = true; + } else if (!to_late_to_comment && sc.ch == '%') { + // Switch to comment level 2 (Function) + sc.ChangeState(SCE_ERLANG_COMMENT_FUNCTION); + old_style = SCE_ERLANG_COMMENT_FUNCTION; + parse_state = COMMENT_FUNCTION; + sc.Forward(); + } + } + // V--- Falling through! + case COMMENT_FUNCTION : { + if (sc.ch != '%') { + to_late_to_comment = true; + } else if (!to_late_to_comment && sc.ch == '%') { + // Switch to comment level 3 (Module) + sc.ChangeState(SCE_ERLANG_COMMENT_MODULE); + old_style = SCE_ERLANG_COMMENT_MODULE; + parse_state = COMMENT_MODULE; + sc.Forward(); + } + } + // V--- Falling through! + case COMMENT_MODULE : { + if (parse_state != COMMENT) { + // Search for comment documentation + if (sc.chNext == '@') { + old_parse_state = parse_state; + parse_state = ('{' == sc.ch) + ? COMMENT_DOC_MACRO + : COMMENT_DOC; + sc.ForwardSetState(sc.state); + } + } + + // All comments types fall here. + if (sc.atLineEnd) { + to_late_to_comment = false; + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case COMMENT_DOC : + // V--- Falling through! + case COMMENT_DOC_MACRO : { + + if (!isalnum(sc.ch)) { + // Try to match documentation comment + sc.GetCurrent(cur, sizeof(cur)); + + if (parse_state == COMMENT_DOC_MACRO + && erlangDocMacro.InList(cur)) { + sc.ChangeState(SCE_ERLANG_COMMENT_DOC_MACRO); + while (sc.ch != '}' && !sc.atLineEnd) + sc.Forward(); + } else if (erlangDoc.InList(cur)) { + sc.ChangeState(SCE_ERLANG_COMMENT_DOC); + } else { + sc.ChangeState(old_style); + } + + // Switch back to old state + sc.SetState(old_style); + parse_state = old_parse_state; + } + + if (sc.atLineEnd) { + to_late_to_comment = false; + sc.ChangeState(old_style); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Atoms ---------------------------------------------------------*/ + case ATOM_UNQUOTED : { + if ('@' == sc.ch){ + parse_state = NODE_NAME_UNQUOTED; + } else if (sc.ch == ':') { + // Searching for module name + if (sc.chNext == ' ') { + // error + sc.ChangeState(SCE_ERLANG_UNKNOWN); + parse_state = STATE_NULL; + } else { + sc.Forward(); + if (isalnum(sc.ch)) { + sc.GetCurrent(cur, sizeof(cur)); + sc.ChangeState(SCE_ERLANG_MODULES); + sc.SetState(SCE_ERLANG_MODULES); + } + } + } else if (!IsAWordChar(sc.ch)) { + + sc.GetCurrent(cur, sizeof(cur)); + if (reservedWords.InList(cur)) { + style = SCE_ERLANG_KEYWORD; + } else if (erlangBIFs.InList(cur) + && strcmp(cur,"erlang:")){ + style = SCE_ERLANG_BIFS; + } else if (sc.ch == '(' || '/' == sc.ch){ + style = SCE_ERLANG_FUNCTION_NAME; + } else { + style = SCE_ERLANG_ATOM; + } + + sc.ChangeState(style); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + + } break; + + case ATOM_QUOTED : { + if ( '@' == sc.ch ){ + parse_state = NODE_NAME_QUOTED; + } else if ('\'' == sc.ch && '\\' != sc.chPrev) { + sc.ChangeState(SCE_ERLANG_ATOM); + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Node names ----------------------------------------------------*/ + case NODE_NAME_UNQUOTED : { + if ('@' == sc.ch) { + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } else if (!IsAWordChar(sc.ch)) { + sc.ChangeState(SCE_ERLANG_NODE_NAME); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case NODE_NAME_QUOTED : { + if ('@' == sc.ch) { + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } else if ('\'' == sc.ch && '\\' != sc.chPrev) { + sc.ChangeState(SCE_ERLANG_NODE_NAME_QUOTED); + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Records -------------------------------------------------------*/ + case RECORD_START : { + if ('\'' == sc.ch) { + parse_state = RECORD_QUOTED; + } else if (isalpha(sc.ch) && islower(sc.ch)) { + parse_state = RECORD_UNQUOTED; + } else { // error + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case RECORD_UNQUOTED : { + if (!IsAWordChar(sc.ch)) { + sc.ChangeState(SCE_ERLANG_RECORD); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case RECORD_QUOTED : { + if ('\'' == sc.ch && '\\' != sc.chPrev) { + sc.ChangeState(SCE_ERLANG_RECORD_QUOTED); + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Macros --------------------------------------------------------*/ + case MACRO_START : { + if ('\'' == sc.ch) { + parse_state = MACRO_QUOTED; + } else if (isalpha(sc.ch)) { + parse_state = MACRO_UNQUOTED; + } else { // error + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case MACRO_UNQUOTED : { + if (!IsAWordChar(sc.ch)) { + sc.ChangeState(SCE_ERLANG_MACRO); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case MACRO_QUOTED : { + if ('\'' == sc.ch && '\\' != sc.chPrev) { + sc.ChangeState(SCE_ERLANG_MACRO_QUOTED); + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Numerics ------------------------------------------------------*/ + /* Simple integer */ + case NUMERAL_START : { + if (isdigit(sc.ch)) { + radix_digits *= 10; + radix_digits += sc.ch - '0'; // Assuming ASCII here! + } else if ('#' == sc.ch) { + if (2 > radix_digits || 36 < radix_digits) { + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } else { + parse_state = NUMERAL_BASE_VALUE; + } + } else if ('.' == sc.ch && isdigit(sc.chNext)) { + radix_digits = 0; + parse_state = NUMERAL_FLOAT; + } else if ('e' == sc.ch || 'E' == sc.ch) { + exponent_digits = 0; + parse_state = NUMERAL_EXPONENT; + } else { + radix_digits = 0; + sc.ChangeState(SCE_ERLANG_NUMBER); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* Integer in other base than 10 (x#yyy) */ + case NUMERAL_BASE_VALUE : { + if (!is_radix(radix_digits,sc.ch)) { + radix_digits = 0; + + if (!isalnum(sc.ch)) + sc.ChangeState(SCE_ERLANG_NUMBER); + + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* Float (x.yyy) */ + case NUMERAL_FLOAT : { + if ('e' == sc.ch || 'E' == sc.ch) { + exponent_digits = 0; + parse_state = NUMERAL_EXPONENT; + } else if (!isdigit(sc.ch)) { + sc.ChangeState(SCE_ERLANG_NUMBER); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* Exponent, either integer or float (xEyy, x.yyEzzz) */ + case NUMERAL_EXPONENT : { + if (('-' == sc.ch || '+' == sc.ch) + && (isdigit(sc.chNext))) { + sc.Forward(); + } else if (!isdigit(sc.ch)) { + if (0 < exponent_digits) + sc.ChangeState(SCE_ERLANG_NUMBER); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } else { + ++exponent_digits; + } + } break; + + /* -------------------------------------------------------------- */ + /* Preprocessor --------------------------------------------------*/ + case PREPROCESSOR : { + if (!IsAWordChar(sc.ch)) { + + sc.GetCurrent(cur, sizeof(cur)); + if (erlangPreproc.InList(cur)) { + style = SCE_ERLANG_PREPROC; + } else if (erlangModulesAtt.InList(cur)) { + style = SCE_ERLANG_MODULES_ATT; + } + + sc.ChangeState(style); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + } + + } /* End of : STATE_NULL != parse_state */ + else + { + switch (sc.state) { + case SCE_ERLANG_VARIABLE : { + if (!IsAWordChar(sc.ch)) + sc.SetState(SCE_ERLANG_DEFAULT); + } break; + case SCE_ERLANG_STRING : { + if (sc.ch == '\"' && sc.chPrev != '\\') + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } break; + case SCE_ERLANG_COMMENT : { + if (sc.atLineEnd) + sc.SetState(SCE_ERLANG_DEFAULT); + } break; + case SCE_ERLANG_CHARACTER : { + if (sc.chPrev == '\\') { + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } else if (sc.ch != '\\') { + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } + } break; + case SCE_ERLANG_OPERATOR : { + if (sc.chPrev == '.') { + if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' + || sc.ch == '^') { + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } else { + sc.SetState(SCE_ERLANG_DEFAULT); + } + } else { + sc.SetState(SCE_ERLANG_DEFAULT); + } + } break; + } + } + + if (sc.state == SCE_ERLANG_DEFAULT) { + bool no_new_state = false; + + switch (sc.ch) { + case '\"' : sc.SetState(SCE_ERLANG_STRING); break; + case '$' : sc.SetState(SCE_ERLANG_CHARACTER); break; + case '%' : { + parse_state = COMMENT; + sc.SetState(SCE_ERLANG_COMMENT); + } break; + case '#' : { + parse_state = RECORD_START; + sc.SetState(SCE_ERLANG_UNKNOWN); + } break; + case '?' : { + parse_state = MACRO_START; + sc.SetState(SCE_ERLANG_UNKNOWN); + } break; + case '\'' : { + parse_state = ATOM_QUOTED; + sc.SetState(SCE_ERLANG_UNKNOWN); + } break; + case '+' : + case '-' : { + if (IsADigit(sc.chNext)) { + parse_state = NUMERAL_START; + radix_digits = 0; + sc.SetState(SCE_ERLANG_UNKNOWN); + } else if (sc.ch != '+') { + parse_state = PREPROCESSOR; + sc.SetState(SCE_ERLANG_UNKNOWN); + } + } break; + default : no_new_state = true; + } + + if (no_new_state) { + if (isdigit(sc.ch)) { + parse_state = NUMERAL_START; + radix_digits = sc.ch - '0'; + sc.SetState(SCE_ERLANG_UNKNOWN); + } else if (isupper(sc.ch) || '_' == sc.ch) { + sc.SetState(SCE_ERLANG_VARIABLE); + } else if (isalpha(sc.ch)) { + parse_state = ATOM_UNQUOTED; + sc.SetState(SCE_ERLANG_UNKNOWN); + } else if (isoperator(static_cast(sc.ch)) + || sc.ch == '\\') { + sc.SetState(SCE_ERLANG_OPERATOR); + } + } + } + + } + sc.Complete(); +} + +static int ClassifyErlangFoldPoint( + Accessor &styler, + int styleNext, + int keyword_start +) { + int lev = 0; + if (styler.Match(keyword_start,"case") + || ( + styler.Match(keyword_start,"fun") + && (SCE_ERLANG_FUNCTION_NAME != styleNext) + ) + || styler.Match(keyword_start,"if") + || styler.Match(keyword_start,"query") + || styler.Match(keyword_start,"receive") + ) { + ++lev; + } else if (styler.Match(keyword_start,"end")) { + --lev; + } + + return lev; +} + +static void FoldErlangDoc( + unsigned int startPos, int length, int initStyle, + WordList** /*keywordlists*/, Accessor &styler +) { + unsigned int endPos = startPos + length; + int currentLine = styler.GetLine(startPos); + int lev; + int previousLevel = styler.LevelAt(currentLine) & SC_FOLDLEVELNUMBERMASK; + int currentLevel = previousLevel; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + int stylePrev; + int keyword_start = 0; + char ch; + char chNext = styler.SafeGetCharAt(startPos); + bool atEOL; + + for (unsigned int i = startPos; i < endPos; i++) { + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + // Get styles + stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + atEOL = ((ch == '\r') && (chNext != '\n')) || (ch == '\n'); + + if (stylePrev != SCE_ERLANG_KEYWORD + && style == SCE_ERLANG_KEYWORD) { + keyword_start = i; + } + + // Fold on keywords + if (stylePrev == SCE_ERLANG_KEYWORD + && style != SCE_ERLANG_KEYWORD + && style != SCE_ERLANG_ATOM + ) { + currentLevel += ClassifyErlangFoldPoint(styler, + styleNext, + keyword_start); + } + + // Fold on comments + if (style == SCE_ERLANG_COMMENT + || style == SCE_ERLANG_COMMENT_MODULE + || style == SCE_ERLANG_COMMENT_FUNCTION) { + + if (ch == '%' && chNext == '{') { + currentLevel++; + } else if (ch == '%' && chNext == '}') { + currentLevel--; + } + } + + // Fold on braces + if (style == SCE_ERLANG_OPERATOR) { + if (ch == '{' || ch == '(' || ch == '[') { + currentLevel++; + } else if (ch == '}' || ch == ')' || ch == ']') { + currentLevel--; + } + } + + + if (atEOL) { + lev = previousLevel; + + if (currentLevel > previousLevel) + lev |= SC_FOLDLEVELHEADERFLAG; + + if (lev != styler.LevelAt(currentLine)) + styler.SetLevel(currentLine, lev); + + currentLine++; + previousLevel = currentLevel; + } + + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + styler.SetLevel(currentLine, + previousLevel + | (styler.LevelAt(currentLine) & ~SC_FOLDLEVELNUMBERMASK)); +} + +static const char * const erlangWordListDesc[] = { + "Erlang Reserved words", + "Erlang BIFs", + "Erlang Preprocessor", + "Erlang Module Attributes", + "Erlang Documentation", + "Erlang Documentation Macro", + 0 +}; + +LexerModule lmErlang( + SCLEX_ERLANG, + ColouriseErlangDoc, + "erlang", + FoldErlangDoc, + erlangWordListDesc); diff --git a/scintilla/lexers/LexFlagship.cxx b/ThirdLibs/scintilla/lexers/LexFlagship.cxx similarity index 97% rename from scintilla/lexers/LexFlagship.cxx rename to ThirdLibs/scintilla/lexers/LexFlagship.cxx index 013521bc..b8568b05 100644 --- a/scintilla/lexers/LexFlagship.cxx +++ b/ThirdLibs/scintilla/lexers/LexFlagship.cxx @@ -1,354 +1,354 @@ -// Scintilla source code edit control -/** @file LexFlagShip.cxx - ** Lexer for Harbour and FlagShip. - ** (Syntactically compatible to other xBase dialects, like Clipper, dBase, Clip, FoxPro etc.) - **/ -// Copyright 2005 by Randy Butler -// Copyright 2010 by Xavi (Harbour) -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// Extended to accept accented characters -static inline bool IsAWordChar(int ch) -{ - return ch >= 0x80 || - (isalnum(ch) || ch == '_'); -} - -static void ColouriseFlagShipDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) -{ - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - - // property lexer.flagship.styling.within.preprocessor - // For Harbour code, determines whether all preprocessor code is styled in the preprocessor style (0) or only from the - // initial # to the end of the command word(1, the default). It also determines how to present text, dump, and disabled code. - bool stylingWithinPreprocessor = styler.GetPropertyInt("lexer.flagship.styling.within.preprocessor", 1) != 0; - - CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); - - int visibleChars = 0; - int closeStringChar = 0; - int styleBeforeDCKeyword = SCE_FS_DEFAULT; - bool bEnableCode = initStyle < SCE_FS_DISABLEDCODE; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_FS_OPERATOR: - case SCE_FS_OPERATOR_C: - case SCE_FS_WORDOPERATOR: - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - break; - case SCE_FS_IDENTIFIER: - case SCE_FS_IDENTIFIER_C: - if (!IsAWordChar(sc.ch)) { - char s[64]; - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD : SCE_FS_KEYWORD_C); - } else if (keywords2.InList(s)) { - sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD2 : SCE_FS_KEYWORD2_C); - } else if (bEnableCode && keywords3.InList(s)) { - sc.ChangeState(SCE_FS_KEYWORD3); - } else if (bEnableCode && keywords4.InList(s)) { - sc.ChangeState(SCE_FS_KEYWORD4); - }// Else, it is really an identifier... - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } - break; - case SCE_FS_NUMBER: - if (!IsAWordChar(sc.ch) && !(sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_FS_DEFAULT); - } - break; - case SCE_FS_NUMBER_C: - if (!IsAWordChar(sc.ch) && sc.ch != '.') { - sc.SetState(SCE_FS_DEFAULT_C); - } - break; - case SCE_FS_CONSTANT: - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_FS_DEFAULT); - } - break; - case SCE_FS_STRING: - case SCE_FS_STRING_C: - if (sc.ch == closeStringChar) { - sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } else if (sc.atLineEnd) { - sc.ChangeState(bEnableCode ? SCE_FS_STRINGEOL : SCE_FS_STRINGEOL_C); - } - break; - case SCE_FS_STRINGEOL: - case SCE_FS_STRINGEOL_C: - if (sc.atLineStart) { - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } - break; - case SCE_FS_COMMENTDOC: - case SCE_FS_COMMENTDOC_C: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C; - sc.SetState(SCE_FS_COMMENTDOCKEYWORD); - } - } - break; - case SCE_FS_COMMENT: - case SCE_FS_COMMENTLINE: - if (sc.atLineStart) { - sc.SetState(SCE_FS_DEFAULT); - } - break; - case SCE_FS_COMMENTLINEDOC: - case SCE_FS_COMMENTLINEDOC_C: - if (sc.atLineStart) { - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C; - sc.SetState(SCE_FS_COMMENTDOCKEYWORD); - } - } - break; - case SCE_FS_COMMENTDOCKEYWORD: - if ((styleBeforeDCKeyword == SCE_FS_COMMENTDOC || styleBeforeDCKeyword == SCE_FS_COMMENTDOC_C) && - sc.Match('*', '/')) { - sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR); - sc.Forward(); - sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } else if (!setDoxygen.Contains(sc.ch)) { - char s[64]; - sc.GetCurrentLowered(s, sizeof(s)); - if (!IsASpace(sc.ch) || !keywords5.InList(s + 1)) { - sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR); - } - sc.SetState(styleBeforeDCKeyword); - } - break; - case SCE_FS_PREPROCESSOR: - case SCE_FS_PREPROCESSOR_C: - if (sc.atLineEnd) { - if (!(sc.chPrev == ';' || sc.GetRelative(-2) == ';')) { - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } - } else if (stylingWithinPreprocessor) { - if (IsASpaceOrTab(sc.ch)) { - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } - } else if (sc.Match('/', '*') || sc.Match('/', '/') || sc.Match('&', '&')) { - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } - break; - case SCE_FS_DISABLEDCODE: - if (sc.ch == '#' && visibleChars == 0) { - sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C); - do { // Skip whitespace between # and preprocessor word - sc.Forward(); - } while (IsASpaceOrTab(sc.ch) && sc.More()); - if (sc.MatchIgnoreCase("pragma")) { - sc.Forward(6); - do { // Skip more whitespace until keyword - sc.Forward(); - } while (IsASpaceOrTab(sc.ch) && sc.More()); - if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) { - bEnableCode = true; - sc.SetState(SCE_FS_DISABLEDCODE); - sc.Forward(sc.ch == '_' ? 8 : 6); - sc.ForwardSetState(SCE_FS_DEFAULT); - } else { - sc.ChangeState(SCE_FS_DISABLEDCODE); - } - } else { - sc.ChangeState(SCE_FS_DISABLEDCODE); - } - } - break; - case SCE_FS_DATE: - if (sc.ch == '}') { - sc.ForwardSetState(SCE_FS_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_FS_STRINGEOL); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_FS_DEFAULT || sc.state == SCE_FS_DEFAULT_C) { - if (bEnableCode && - (sc.MatchIgnoreCase(".and.") || sc.MatchIgnoreCase(".not."))) { - sc.SetState(SCE_FS_WORDOPERATOR); - sc.Forward(4); - } else if (bEnableCode && sc.MatchIgnoreCase(".or.")) { - sc.SetState(SCE_FS_WORDOPERATOR); - sc.Forward(3); - } else if (bEnableCode && - (sc.MatchIgnoreCase(".t.") || sc.MatchIgnoreCase(".f.") || - (!IsAWordChar(sc.GetRelative(3)) && sc.MatchIgnoreCase("nil")))) { - sc.SetState(SCE_FS_CONSTANT); - sc.Forward(2); - } else if (sc.Match('/', '*')) { - sc.SetState(bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C); - sc.Forward(); - } else if (bEnableCode && sc.Match('&', '&')) { - sc.SetState(SCE_FS_COMMENTLINE); - sc.Forward(); - } else if (sc.Match('/', '/')) { - sc.SetState(bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C); - sc.Forward(); - } else if (bEnableCode && sc.ch == '*' && visibleChars == 0) { - sc.SetState(SCE_FS_COMMENT); - } else if (sc.ch == '\"' || sc.ch == '\'') { - sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C); - closeStringChar = sc.ch; - } else if (closeStringChar == '>' && sc.ch == '<') { - sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C); - } else if (sc.ch == '#' && visibleChars == 0) { - sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C); - do { // Skip whitespace between # and preprocessor word - sc.Forward(); - } while (IsASpaceOrTab(sc.ch) && sc.More()); - if (sc.atLineEnd) { - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } else if (sc.MatchIgnoreCase("include")) { - if (stylingWithinPreprocessor) { - closeStringChar = '>'; - } - } else if (sc.MatchIgnoreCase("pragma")) { - sc.Forward(6); - do { // Skip more whitespace until keyword - sc.Forward(); - } while (IsASpaceOrTab(sc.ch) && sc.More()); - if (sc.MatchIgnoreCase("begindump") || sc.MatchIgnoreCase("__cstream")) { - bEnableCode = false; - if (stylingWithinPreprocessor) { - sc.SetState(SCE_FS_DISABLEDCODE); - sc.Forward(8); - sc.ForwardSetState(SCE_FS_DEFAULT_C); - } else { - sc.SetState(SCE_FS_DISABLEDCODE); - } - } else if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) { - bEnableCode = true; - sc.SetState(SCE_FS_DISABLEDCODE); - sc.Forward(sc.ch == '_' ? 8 : 6); - sc.ForwardSetState(SCE_FS_DEFAULT); - } - } - } else if (bEnableCode && sc.ch == '{') { - int p = 0; - int chSeek; - unsigned int endPos(startPos + length); - do { // Skip whitespace - chSeek = sc.GetRelative(++p); - } while (IsASpaceOrTab(chSeek) && (sc.currentPos + p < endPos)); - if (chSeek == '^') { - sc.SetState(SCE_FS_DATE); - } else { - sc.SetState(SCE_FS_OPERATOR); - } - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(bEnableCode ? SCE_FS_NUMBER : SCE_FS_NUMBER_C); - } else if (IsAWordChar(sc.ch)) { - sc.SetState(bEnableCode ? SCE_FS_IDENTIFIER : SCE_FS_IDENTIFIER_C); - } else if (isoperator(static_cast(sc.ch)) || (bEnableCode && sc.ch == '@')) { - sc.SetState(bEnableCode ? SCE_FS_OPERATOR : SCE_FS_OPERATOR_C); - } - } - - if (sc.atLineEnd) { - visibleChars = 0; - closeStringChar = 0; - } - if (!IsASpace(sc.ch)) { - visibleChars++; - } - } - sc.Complete(); -} - -static void FoldFlagShipDoc(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) -{ - - int endPos = startPos + length; - - // Backtrack to previous line in case need to fix its fold status - int lineCurrent = styler.GetLine(startPos); - if (startPos > 0 && lineCurrent > 0) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); - } - int spaceFlags = 0; - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags); - char chNext = styler[startPos]; - for (int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos-1)) { - int lev = indentCurrent; - int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags); - if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { - int spaceFlags2 = 0; - int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2); - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - } - } - indentCurrent = indentNext; - styler.SetLevel(lineCurrent, lev); - lineCurrent++; - } - } -} - -static const char * const FSWordListDesc[] = { - "Keywords Commands", - "Std Library Functions", - "Procedure, return, exit", - "Class (oop)", - "Doxygen keywords", - 0 -}; - -LexerModule lmFlagShip(SCLEX_FLAGSHIP, ColouriseFlagShipDoc, "flagship", FoldFlagShipDoc, FSWordListDesc); +// Scintilla source code edit control +/** @file LexFlagShip.cxx + ** Lexer for Harbour and FlagShip. + ** (Syntactically compatible to other xBase dialects, like Clipper, dBase, Clip, FoxPro etc.) + **/ +// Copyright 2005 by Randy Butler +// Copyright 2010 by Xavi (Harbour) +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// Extended to accept accented characters +static inline bool IsAWordChar(int ch) +{ + return ch >= 0x80 || + (isalnum(ch) || ch == '_'); +} + +static void ColouriseFlagShipDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) +{ + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + + // property lexer.flagship.styling.within.preprocessor + // For Harbour code, determines whether all preprocessor code is styled in the preprocessor style (0) or only from the + // initial # to the end of the command word(1, the default). It also determines how to present text, dump, and disabled code. + bool stylingWithinPreprocessor = styler.GetPropertyInt("lexer.flagship.styling.within.preprocessor", 1) != 0; + + CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); + + int visibleChars = 0; + int closeStringChar = 0; + int styleBeforeDCKeyword = SCE_FS_DEFAULT; + bool bEnableCode = initStyle < SCE_FS_DISABLEDCODE; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_FS_OPERATOR: + case SCE_FS_OPERATOR_C: + case SCE_FS_WORDOPERATOR: + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + break; + case SCE_FS_IDENTIFIER: + case SCE_FS_IDENTIFIER_C: + if (!IsAWordChar(sc.ch)) { + char s[64]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD : SCE_FS_KEYWORD_C); + } else if (keywords2.InList(s)) { + sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD2 : SCE_FS_KEYWORD2_C); + } else if (bEnableCode && keywords3.InList(s)) { + sc.ChangeState(SCE_FS_KEYWORD3); + } else if (bEnableCode && keywords4.InList(s)) { + sc.ChangeState(SCE_FS_KEYWORD4); + }// Else, it is really an identifier... + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_NUMBER: + if (!IsAWordChar(sc.ch) && !(sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_FS_DEFAULT); + } + break; + case SCE_FS_NUMBER_C: + if (!IsAWordChar(sc.ch) && sc.ch != '.') { + sc.SetState(SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_CONSTANT: + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_FS_DEFAULT); + } + break; + case SCE_FS_STRING: + case SCE_FS_STRING_C: + if (sc.ch == closeStringChar) { + sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.atLineEnd) { + sc.ChangeState(bEnableCode ? SCE_FS_STRINGEOL : SCE_FS_STRINGEOL_C); + } + break; + case SCE_FS_STRINGEOL: + case SCE_FS_STRINGEOL_C: + if (sc.atLineStart) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_COMMENTDOC: + case SCE_FS_COMMENTDOC_C: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C; + sc.SetState(SCE_FS_COMMENTDOCKEYWORD); + } + } + break; + case SCE_FS_COMMENT: + case SCE_FS_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_FS_DEFAULT); + } + break; + case SCE_FS_COMMENTLINEDOC: + case SCE_FS_COMMENTLINEDOC_C: + if (sc.atLineStart) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C; + sc.SetState(SCE_FS_COMMENTDOCKEYWORD); + } + } + break; + case SCE_FS_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_FS_COMMENTDOC || styleBeforeDCKeyword == SCE_FS_COMMENTDOC_C) && + sc.Match('*', '/')) { + sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (!setDoxygen.Contains(sc.ch)) { + char s[64]; + sc.GetCurrentLowered(s, sizeof(s)); + if (!IsASpace(sc.ch) || !keywords5.InList(s + 1)) { + sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_FS_PREPROCESSOR: + case SCE_FS_PREPROCESSOR_C: + if (sc.atLineEnd) { + if (!(sc.chPrev == ';' || sc.GetRelative(-2) == ';')) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + } else if (stylingWithinPreprocessor) { + if (IsASpaceOrTab(sc.ch)) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + } else if (sc.Match('/', '*') || sc.Match('/', '/') || sc.Match('&', '&')) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_DISABLEDCODE: + if (sc.ch == '#' && visibleChars == 0) { + sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C); + do { // Skip whitespace between # and preprocessor word + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.MatchIgnoreCase("pragma")) { + sc.Forward(6); + do { // Skip more whitespace until keyword + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) { + bEnableCode = true; + sc.SetState(SCE_FS_DISABLEDCODE); + sc.Forward(sc.ch == '_' ? 8 : 6); + sc.ForwardSetState(SCE_FS_DEFAULT); + } else { + sc.ChangeState(SCE_FS_DISABLEDCODE); + } + } else { + sc.ChangeState(SCE_FS_DISABLEDCODE); + } + } + break; + case SCE_FS_DATE: + if (sc.ch == '}') { + sc.ForwardSetState(SCE_FS_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_FS_STRINGEOL); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_FS_DEFAULT || sc.state == SCE_FS_DEFAULT_C) { + if (bEnableCode && + (sc.MatchIgnoreCase(".and.") || sc.MatchIgnoreCase(".not."))) { + sc.SetState(SCE_FS_WORDOPERATOR); + sc.Forward(4); + } else if (bEnableCode && sc.MatchIgnoreCase(".or.")) { + sc.SetState(SCE_FS_WORDOPERATOR); + sc.Forward(3); + } else if (bEnableCode && + (sc.MatchIgnoreCase(".t.") || sc.MatchIgnoreCase(".f.") || + (!IsAWordChar(sc.GetRelative(3)) && sc.MatchIgnoreCase("nil")))) { + sc.SetState(SCE_FS_CONSTANT); + sc.Forward(2); + } else if (sc.Match('/', '*')) { + sc.SetState(bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C); + sc.Forward(); + } else if (bEnableCode && sc.Match('&', '&')) { + sc.SetState(SCE_FS_COMMENTLINE); + sc.Forward(); + } else if (sc.Match('/', '/')) { + sc.SetState(bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C); + sc.Forward(); + } else if (bEnableCode && sc.ch == '*' && visibleChars == 0) { + sc.SetState(SCE_FS_COMMENT); + } else if (sc.ch == '\"' || sc.ch == '\'') { + sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C); + closeStringChar = sc.ch; + } else if (closeStringChar == '>' && sc.ch == '<') { + sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C); + } else if (sc.ch == '#' && visibleChars == 0) { + sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C); + do { // Skip whitespace between # and preprocessor word + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.atLineEnd) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.MatchIgnoreCase("include")) { + if (stylingWithinPreprocessor) { + closeStringChar = '>'; + } + } else if (sc.MatchIgnoreCase("pragma")) { + sc.Forward(6); + do { // Skip more whitespace until keyword + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.MatchIgnoreCase("begindump") || sc.MatchIgnoreCase("__cstream")) { + bEnableCode = false; + if (stylingWithinPreprocessor) { + sc.SetState(SCE_FS_DISABLEDCODE); + sc.Forward(8); + sc.ForwardSetState(SCE_FS_DEFAULT_C); + } else { + sc.SetState(SCE_FS_DISABLEDCODE); + } + } else if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) { + bEnableCode = true; + sc.SetState(SCE_FS_DISABLEDCODE); + sc.Forward(sc.ch == '_' ? 8 : 6); + sc.ForwardSetState(SCE_FS_DEFAULT); + } + } + } else if (bEnableCode && sc.ch == '{') { + int p = 0; + int chSeek; + unsigned int endPos(startPos + length); + do { // Skip whitespace + chSeek = sc.GetRelative(++p); + } while (IsASpaceOrTab(chSeek) && (sc.currentPos + p < endPos)); + if (chSeek == '^') { + sc.SetState(SCE_FS_DATE); + } else { + sc.SetState(SCE_FS_OPERATOR); + } + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(bEnableCode ? SCE_FS_NUMBER : SCE_FS_NUMBER_C); + } else if (IsAWordChar(sc.ch)) { + sc.SetState(bEnableCode ? SCE_FS_IDENTIFIER : SCE_FS_IDENTIFIER_C); + } else if (isoperator(static_cast(sc.ch)) || (bEnableCode && sc.ch == '@')) { + sc.SetState(bEnableCode ? SCE_FS_OPERATOR : SCE_FS_OPERATOR_C); + } + } + + if (sc.atLineEnd) { + visibleChars = 0; + closeStringChar = 0; + } + if (!IsASpace(sc.ch)) { + visibleChars++; + } + } + sc.Complete(); +} + +static void FoldFlagShipDoc(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) +{ + + int endPos = startPos + length; + + // Backtrack to previous line in case need to fix its fold status + int lineCurrent = styler.GetLine(startPos); + if (startPos > 0 && lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + int spaceFlags = 0; + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags); + char chNext = styler[startPos]; + for (int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos-1)) { + int lev = indentCurrent; + int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { + int spaceFlags2 = 0; + int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2); + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + } + } + indentCurrent = indentNext; + styler.SetLevel(lineCurrent, lev); + lineCurrent++; + } + } +} + +static const char * const FSWordListDesc[] = { + "Keywords Commands", + "Std Library Functions", + "Procedure, return, exit", + "Class (oop)", + "Doxygen keywords", + 0 +}; + +LexerModule lmFlagShip(SCLEX_FLAGSHIP, ColouriseFlagShipDoc, "flagship", FoldFlagShipDoc, FSWordListDesc); diff --git a/scintilla/lexers/LexForth.cxx b/ThirdLibs/scintilla/lexers/LexForth.cxx similarity index 96% rename from scintilla/lexers/LexForth.cxx rename to ThirdLibs/scintilla/lexers/LexForth.cxx index ee95e317..0e9875ce 100644 --- a/scintilla/lexers/LexForth.cxx +++ b/ThirdLibs/scintilla/lexers/LexForth.cxx @@ -1,179 +1,179 @@ -// Scintilla source code edit control -/** @file LexForth.cxx - ** Lexer for FORTH - **/ -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || - ch == '_' || ch == '?' || ch == '"' || ch == '@' || - ch == '!' || ch == '[' || ch == ']' || ch == '/' || - ch == '+' || ch == '-' || ch == '*' || ch == '<' || - ch == '>' || ch == '=' || ch == ';' || ch == '(' || - ch == ')' ); -} - -static inline bool IsAWordStart(int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.'); -} - -static inline bool IsANumChar(int ch) { - return (ch < 0x80) && (isxdigit(ch) || ch == '.' || ch == 'e' || ch == 'E' ); -} - -static inline bool IsASpaceChar(int ch) { - return (ch < 0x80) && isspace(ch); -} - -static void ColouriseForthDoc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[], - Accessor &styler) { - - WordList &control = *keywordLists[0]; - WordList &keyword = *keywordLists[1]; - WordList &defword = *keywordLists[2]; - WordList &preword1 = *keywordLists[3]; - WordList &preword2 = *keywordLists[4]; - WordList &strings = *keywordLists[5]; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) - { - // Determine if the current state should terminate. - if (sc.state == SCE_FORTH_COMMENT) { - if (sc.atLineEnd) { - sc.SetState(SCE_FORTH_DEFAULT); - } - }else if (sc.state == SCE_FORTH_COMMENT_ML) { - if (sc.ch == ')') { - sc.ForwardSetState(SCE_FORTH_DEFAULT); - } - }else if (sc.state == SCE_FORTH_IDENTIFIER || sc.state == SCE_FORTH_NUMBER) { - // handle numbers here too, because what we thought was a number might - // turn out to be a keyword e.g. 2DUP - if (IsASpaceChar(sc.ch) ) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - int newState = sc.state == SCE_FORTH_NUMBER ? SCE_FORTH_NUMBER : SCE_FORTH_DEFAULT; - if (control.InList(s)) { - sc.ChangeState(SCE_FORTH_CONTROL); - } else if (keyword.InList(s)) { - sc.ChangeState(SCE_FORTH_KEYWORD); - } else if (defword.InList(s)) { - sc.ChangeState(SCE_FORTH_DEFWORD); - } else if (preword1.InList(s)) { - sc.ChangeState(SCE_FORTH_PREWORD1); - } else if (preword2.InList(s)) { - sc.ChangeState(SCE_FORTH_PREWORD2); - } else if (strings.InList(s)) { - sc.ChangeState(SCE_FORTH_STRING); - newState = SCE_FORTH_STRING; - } - sc.SetState(newState); - } - if (sc.state == SCE_FORTH_NUMBER) { - if (IsASpaceChar(sc.ch)) { - sc.SetState(SCE_FORTH_DEFAULT); - } else if (!IsANumChar(sc.ch)) { - sc.ChangeState(SCE_FORTH_IDENTIFIER); - } - } - }else if (sc.state == SCE_FORTH_STRING) { - if (sc.ch == '\"') { - sc.ForwardSetState(SCE_FORTH_DEFAULT); - } - }else if (sc.state == SCE_FORTH_LOCALE) { - if (sc.ch == '}') { - sc.ForwardSetState(SCE_FORTH_DEFAULT); - } - }else if (sc.state == SCE_FORTH_DEFWORD) { - if (IsASpaceChar(sc.ch)) { - sc.SetState(SCE_FORTH_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_FORTH_DEFAULT) { - if (sc.ch == '\\'){ - sc.SetState(SCE_FORTH_COMMENT); - } else if (sc.ch == '(' && - (sc.atLineStart || IsASpaceChar(sc.chPrev)) && - (sc.atLineEnd || IsASpaceChar(sc.chNext))) { - sc.SetState(SCE_FORTH_COMMENT_ML); - } else if ( (sc.ch == '$' && (isascii(sc.chNext) && isxdigit(sc.chNext))) ) { - // number starting with $ is a hex number - sc.SetState(SCE_FORTH_NUMBER); - while(sc.More() && isascii(sc.chNext) && isxdigit(sc.chNext)) - sc.Forward(); - } else if ( (sc.ch == '%' && (isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))) ) { - // number starting with % is binary - sc.SetState(SCE_FORTH_NUMBER); - while(sc.More() && isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1')) - sc.Forward(); - } else if ( isascii(sc.ch) && - (isxdigit(sc.ch) || ((sc.ch == '.' || sc.ch == '-') && isascii(sc.chNext) && isxdigit(sc.chNext)) ) - ){ - sc.SetState(SCE_FORTH_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_FORTH_IDENTIFIER); - } else if (sc.ch == '{') { - sc.SetState(SCE_FORTH_LOCALE); - } else if (sc.ch == ':' && isascii(sc.chNext) && isspace(sc.chNext)) { - // highlight word definitions e.g. : GCD ( n n -- n ) ..... ; - // ^ ^^^ - sc.SetState(SCE_FORTH_DEFWORD); - while(sc.More() && isascii(sc.chNext) && isspace(sc.chNext)) - sc.Forward(); - } else if (sc.ch == ';' && - (sc.atLineStart || IsASpaceChar(sc.chPrev)) && - (sc.atLineEnd || IsASpaceChar(sc.chNext)) ) { - // mark the ';' that ends a word - sc.SetState(SCE_FORTH_DEFWORD); - sc.ForwardSetState(SCE_FORTH_DEFAULT); - } - } - - } - sc.Complete(); -} - -static void FoldForthDoc(unsigned int, int, int, WordList *[], - Accessor &) { -} - -static const char * const forthWordLists[] = { - "control keywords", - "keywords", - "definition words", - "prewords with one argument", - "prewords with two arguments", - "string definition keywords", - 0, - }; - -LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth", FoldForthDoc, forthWordLists); - - +// Scintilla source code edit control +/** @file LexForth.cxx + ** Lexer for FORTH + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || + ch == '_' || ch == '?' || ch == '"' || ch == '@' || + ch == '!' || ch == '[' || ch == ']' || ch == '/' || + ch == '+' || ch == '-' || ch == '*' || ch == '<' || + ch == '>' || ch == '=' || ch == ';' || ch == '(' || + ch == ')' ); +} + +static inline bool IsAWordStart(int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.'); +} + +static inline bool IsANumChar(int ch) { + return (ch < 0x80) && (isxdigit(ch) || ch == '.' || ch == 'e' || ch == 'E' ); +} + +static inline bool IsASpaceChar(int ch) { + return (ch < 0x80) && isspace(ch); +} + +static void ColouriseForthDoc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[], + Accessor &styler) { + + WordList &control = *keywordLists[0]; + WordList &keyword = *keywordLists[1]; + WordList &defword = *keywordLists[2]; + WordList &preword1 = *keywordLists[3]; + WordList &preword2 = *keywordLists[4]; + WordList &strings = *keywordLists[5]; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) + { + // Determine if the current state should terminate. + if (sc.state == SCE_FORTH_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_FORTH_DEFAULT); + } + }else if (sc.state == SCE_FORTH_COMMENT_ML) { + if (sc.ch == ')') { + sc.ForwardSetState(SCE_FORTH_DEFAULT); + } + }else if (sc.state == SCE_FORTH_IDENTIFIER || sc.state == SCE_FORTH_NUMBER) { + // handle numbers here too, because what we thought was a number might + // turn out to be a keyword e.g. 2DUP + if (IsASpaceChar(sc.ch) ) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + int newState = sc.state == SCE_FORTH_NUMBER ? SCE_FORTH_NUMBER : SCE_FORTH_DEFAULT; + if (control.InList(s)) { + sc.ChangeState(SCE_FORTH_CONTROL); + } else if (keyword.InList(s)) { + sc.ChangeState(SCE_FORTH_KEYWORD); + } else if (defword.InList(s)) { + sc.ChangeState(SCE_FORTH_DEFWORD); + } else if (preword1.InList(s)) { + sc.ChangeState(SCE_FORTH_PREWORD1); + } else if (preword2.InList(s)) { + sc.ChangeState(SCE_FORTH_PREWORD2); + } else if (strings.InList(s)) { + sc.ChangeState(SCE_FORTH_STRING); + newState = SCE_FORTH_STRING; + } + sc.SetState(newState); + } + if (sc.state == SCE_FORTH_NUMBER) { + if (IsASpaceChar(sc.ch)) { + sc.SetState(SCE_FORTH_DEFAULT); + } else if (!IsANumChar(sc.ch)) { + sc.ChangeState(SCE_FORTH_IDENTIFIER); + } + } + }else if (sc.state == SCE_FORTH_STRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_FORTH_DEFAULT); + } + }else if (sc.state == SCE_FORTH_LOCALE) { + if (sc.ch == '}') { + sc.ForwardSetState(SCE_FORTH_DEFAULT); + } + }else if (sc.state == SCE_FORTH_DEFWORD) { + if (IsASpaceChar(sc.ch)) { + sc.SetState(SCE_FORTH_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_FORTH_DEFAULT) { + if (sc.ch == '\\'){ + sc.SetState(SCE_FORTH_COMMENT); + } else if (sc.ch == '(' && + (sc.atLineStart || IsASpaceChar(sc.chPrev)) && + (sc.atLineEnd || IsASpaceChar(sc.chNext))) { + sc.SetState(SCE_FORTH_COMMENT_ML); + } else if ( (sc.ch == '$' && (isascii(sc.chNext) && isxdigit(sc.chNext))) ) { + // number starting with $ is a hex number + sc.SetState(SCE_FORTH_NUMBER); + while(sc.More() && isascii(sc.chNext) && isxdigit(sc.chNext)) + sc.Forward(); + } else if ( (sc.ch == '%' && (isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))) ) { + // number starting with % is binary + sc.SetState(SCE_FORTH_NUMBER); + while(sc.More() && isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1')) + sc.Forward(); + } else if ( isascii(sc.ch) && + (isxdigit(sc.ch) || ((sc.ch == '.' || sc.ch == '-') && isascii(sc.chNext) && isxdigit(sc.chNext)) ) + ){ + sc.SetState(SCE_FORTH_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_FORTH_IDENTIFIER); + } else if (sc.ch == '{') { + sc.SetState(SCE_FORTH_LOCALE); + } else if (sc.ch == ':' && isascii(sc.chNext) && isspace(sc.chNext)) { + // highlight word definitions e.g. : GCD ( n n -- n ) ..... ; + // ^ ^^^ + sc.SetState(SCE_FORTH_DEFWORD); + while(sc.More() && isascii(sc.chNext) && isspace(sc.chNext)) + sc.Forward(); + } else if (sc.ch == ';' && + (sc.atLineStart || IsASpaceChar(sc.chPrev)) && + (sc.atLineEnd || IsASpaceChar(sc.chNext)) ) { + // mark the ';' that ends a word + sc.SetState(SCE_FORTH_DEFWORD); + sc.ForwardSetState(SCE_FORTH_DEFAULT); + } + } + + } + sc.Complete(); +} + +static void FoldForthDoc(unsigned int, int, int, WordList *[], + Accessor &) { +} + +static const char * const forthWordLists[] = { + "control keywords", + "keywords", + "definition words", + "prewords with one argument", + "prewords with two arguments", + "string definition keywords", + 0, + }; + +LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth", FoldForthDoc, forthWordLists); + + diff --git a/scintilla/lexers/LexFortran.cxx b/ThirdLibs/scintilla/lexers/LexFortran.cxx similarity index 97% rename from scintilla/lexers/LexFortran.cxx rename to ThirdLibs/scintilla/lexers/LexFortran.cxx index 66986050..6c61c540 100644 --- a/scintilla/lexers/LexFortran.cxx +++ b/ThirdLibs/scintilla/lexers/LexFortran.cxx @@ -1,471 +1,471 @@ -// Scintilla source code edit control -/** @file LexFortran.cxx - ** Lexer for Fortran. - ** Writen by Chuan-jian Shen, Last changed Sep. 2003 - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. -/***************************************/ -#include -#include -#include -#include -#include -#include -/***************************************/ -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" -/***************************************/ - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/***********************************************/ -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '%'); -} -/**********************************************/ -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch)); -} -/***************************************/ -inline bool IsABlank(unsigned int ch) { - return (ch == ' ') || (ch == 0x09) || (ch == 0x0b) ; -} -/***************************************/ -inline bool IsALineEnd(char ch) { - return ((ch == '\n') || (ch == '\r')) ; -} -/***************************************/ -unsigned int GetContinuedPos(unsigned int pos, Accessor &styler) { - while (!IsALineEnd(styler.SafeGetCharAt(pos++))) continue; - if (styler.SafeGetCharAt(pos) == '\n') pos++; - while (IsABlank(styler.SafeGetCharAt(pos++))) continue; - char chCur = styler.SafeGetCharAt(pos); - if (chCur == '&') { - while (IsABlank(styler.SafeGetCharAt(++pos))) continue; - return pos; - } else { - return pos; - } -} -/***************************************/ -static void ColouriseFortranDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler, bool isFixFormat) { - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - /***************************************/ - int posLineStart = 0, numNonBlank = 0, prevState = 0; - int endPos = startPos + length; - /***************************************/ - // backtrack to the nearest keyword - while ((startPos > 1) && (styler.StyleAt(startPos) != SCE_F_WORD)) { - startPos--; - } - startPos = styler.LineStart(styler.GetLine(startPos)); - initStyle = styler.StyleAt(startPos - 1); - StyleContext sc(startPos, endPos-startPos, initStyle, styler); - /***************************************/ - for (; sc.More(); sc.Forward()) { - // remember the start position of the line - if (sc.atLineStart) { - posLineStart = sc.currentPos; - numNonBlank = 0; - sc.SetState(SCE_F_DEFAULT); - } - if (!IsASpaceOrTab(sc.ch)) numNonBlank ++; - /***********************************************/ - // Handle the fix format generically - int toLineStart = sc.currentPos - posLineStart; - if (isFixFormat && (toLineStart < 6 || toLineStart > 72)) { - if ((toLineStart == 0 && (tolower(sc.ch) == 'c' || sc.ch == '*')) || sc.ch == '!') { - if (sc.MatchIgnoreCase("cdec$") || sc.MatchIgnoreCase("*dec$") || sc.MatchIgnoreCase("!dec$") || - sc.MatchIgnoreCase("cdir$") || sc.MatchIgnoreCase("*dir$") || sc.MatchIgnoreCase("!dir$") || - sc.MatchIgnoreCase("cms$") || sc.MatchIgnoreCase("*ms$") || sc.MatchIgnoreCase("!ms$") || - sc.chNext == '$') { - sc.SetState(SCE_F_PREPROCESSOR); - } else { - sc.SetState(SCE_F_COMMENT); - } - - while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end - } else if (toLineStart > 72) { - sc.SetState(SCE_F_COMMENT); - while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end - } else if (toLineStart < 5) { - if (IsADigit(sc.ch)) - sc.SetState(SCE_F_LABEL); - else - sc.SetState(SCE_F_DEFAULT); - } else if (toLineStart == 5) { - if (!IsASpace(sc.ch) && sc.ch != '0') { - sc.SetState(SCE_F_CONTINUATION); - sc.ForwardSetState(prevState); - } else - sc.SetState(SCE_F_DEFAULT); - } - continue; - } - /***************************************/ - // Handle line continuation generically. - if (!isFixFormat && sc.ch == '&') { - char chTemp = ' '; - int j = 1; - while (IsABlank(chTemp) && j<132) { - chTemp = static_cast(sc.GetRelative(j)); - j++; - } - if (chTemp == '!') { - sc.SetState(SCE_F_CONTINUATION); - if (sc.chNext == '!') sc.ForwardSetState(SCE_F_COMMENT); - } else if (chTemp == '\r' || chTemp == '\n') { - int currentState = sc.state; - sc.SetState(SCE_F_CONTINUATION); - sc.ForwardSetState(SCE_F_DEFAULT); - while (IsASpace(sc.ch) && sc.More()) sc.Forward(); - if (sc.ch == '&') { - sc.SetState(SCE_F_CONTINUATION); - sc.Forward(); - } - sc.SetState(currentState); - } - } - /***************************************/ - // Determine if the current state should terminate. - if (sc.state == SCE_F_OPERATOR) { - sc.SetState(SCE_F_DEFAULT); - } else if (sc.state == SCE_F_NUMBER) { - if (!(IsAWordChar(sc.ch) || sc.ch=='\'' || sc.ch=='\"' || sc.ch=='.')) { - sc.SetState(SCE_F_DEFAULT); - } - } else if (sc.state == SCE_F_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '%')) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_F_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_F_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_F_WORD3); - } - sc.SetState(SCE_F_DEFAULT); - } - } else if (sc.state == SCE_F_COMMENT || sc.state == SCE_F_PREPROCESSOR) { - if (sc.ch == '\r' || sc.ch == '\n') { - sc.SetState(SCE_F_DEFAULT); - } - } else if (sc.state == SCE_F_STRING1) { - prevState = sc.state; - if (sc.ch == '\'') { - if (sc.chNext == '\'') { - sc.Forward(); - } else { - sc.ForwardSetState(SCE_F_DEFAULT); - prevState = SCE_F_DEFAULT; - } - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_F_STRINGEOL); - sc.ForwardSetState(SCE_F_DEFAULT); - } - } else if (sc.state == SCE_F_STRING2) { - prevState = sc.state; - if (sc.atLineEnd) { - sc.ChangeState(SCE_F_STRINGEOL); - sc.ForwardSetState(SCE_F_DEFAULT); - } else if (sc.ch == '\"') { - if (sc.chNext == '\"') { - sc.Forward(); - } else { - sc.ForwardSetState(SCE_F_DEFAULT); - prevState = SCE_F_DEFAULT; - } - } - } else if (sc.state == SCE_F_OPERATOR2) { - if (sc.ch == '.') { - sc.ForwardSetState(SCE_F_DEFAULT); - } - } else if (sc.state == SCE_F_CONTINUATION) { - sc.SetState(SCE_F_DEFAULT); - } else if (sc.state == SCE_F_LABEL) { - if (!IsADigit(sc.ch)) { - sc.SetState(SCE_F_DEFAULT); - } else { - if (isFixFormat && sc.currentPos-posLineStart > 4) - sc.SetState(SCE_F_DEFAULT); - else if (numNonBlank > 5) - sc.SetState(SCE_F_DEFAULT); - } - } - /***************************************/ - // Determine if a new state should be entered. - if (sc.state == SCE_F_DEFAULT) { - if (sc.ch == '!') { - if (sc.MatchIgnoreCase("!dec$") || sc.MatchIgnoreCase("!dir$") || - sc.MatchIgnoreCase("!ms$") || sc.chNext == '$') { - sc.SetState(SCE_F_PREPROCESSOR); - } else { - sc.SetState(SCE_F_COMMENT); - } - } else if ((!isFixFormat) && IsADigit(sc.ch) && numNonBlank == 1) { - sc.SetState(SCE_F_LABEL); - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_F_NUMBER); - } else if ((tolower(sc.ch) == 'b' || tolower(sc.ch) == 'o' || - tolower(sc.ch) == 'z') && (sc.chNext == '\"' || sc.chNext == '\'')) { - sc.SetState(SCE_F_NUMBER); - sc.Forward(); - } else if (sc.ch == '.' && isalpha(sc.chNext)) { - sc.SetState(SCE_F_OPERATOR2); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_F_IDENTIFIER); - } else if (sc.ch == '\"') { - sc.SetState(SCE_F_STRING2); - } else if (sc.ch == '\'') { - sc.SetState(SCE_F_STRING1); - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_F_OPERATOR); - } - } - } - sc.Complete(); -} -/***************************************/ -// To determine the folding level depending on keywords -static int classifyFoldPointFortran(const char* s, const char* prevWord, const char chNextNonBlank) { - int lev = 0; - if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "elseif") == 0) - return -1; - if (strcmp(s, "associate") == 0 || strcmp(s, "block") == 0 - || strcmp(s, "blockdata") == 0 || strcmp(s, "select") == 0 - || strcmp(s, "do") == 0 || strcmp(s, "enum") ==0 - || strcmp(s, "function") == 0 || strcmp(s, "interface") == 0 - || strcmp(s, "module") == 0 || strcmp(s, "program") == 0 - || strcmp(s, "subroutine") == 0 || strcmp(s, "then") == 0 - || (strcmp(s, "type") == 0 && chNextNonBlank != '(') ){ - if (strcmp(prevWord, "end") == 0) - lev = 0; - else - lev = 1; - } else if ((strcmp(s, "end") == 0 && chNextNonBlank != '=') - || strcmp(s, "endassociate") == 0 || strcmp(s, "endblock") == 0 - || strcmp(s, "endblockdata") == 0 || strcmp(s, "endselect") == 0 - || strcmp(s, "enddo") == 0 || strcmp(s, "endenum") ==0 - || strcmp(s, "endif") == 0 || strcmp(s, "endforall") == 0 - || strcmp(s, "endfunction") == 0 || strcmp(s, "endinterface") == 0 - || strcmp(s, "endmodule") == 0 || strcmp(s, "endprogram") == 0 - || strcmp(s, "endsubroutine") == 0 || strcmp(s, "endtype") == 0 - || strcmp(s, "endwhere") == 0 - || (strcmp(s, "procedure") == 0 && strcmp(prevWord,"module")==0) ) { // Take care of the module procedure statement - lev = -1; - } else if (strcmp(prevWord, "end") == 0 && strcmp(s, "if") == 0){ // end if - lev = 0; - } - return lev; -} -// Folding the code -static void FoldFortranDoc(unsigned int startPos, int length, int initStyle, - Accessor &styler, bool isFixFormat) { - // - // bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - // Do not know how to fold the comment at the moment. - // - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - char chNextNonBlank; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - /***************************************/ - int lastStart = 0; - char prevWord[32] = ""; - char Label[6] = ""; - // Variables for do label folding. - static int doLabels[100]; - static int posLabel=-1; - /***************************************/ - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - chNextNonBlank = chNext; - unsigned int j=i+1; - while(IsABlank(chNextNonBlank) && j(tolower(styler[lastStart+k])); - } - s[k] = '\0'; - // Handle the forall and where statement and structure. - if (strcmp(s, "forall") == 0 || strcmp(s, "where") == 0) { - if (strcmp(prevWord, "end") != 0) { - j = i + 1; - char chBrace = '(', chSeek = ')', ch1 = styler.SafeGetCharAt(j); - // Find the position of the first ( - while (ch1 != chBrace && j -1) { - levelCurrent--; - posLabel--; - } - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - strcpy(prevWord, ""); - } - /***************************************/ - if (!isspacechar(ch)) visibleChars++; - } - /***************************************/ - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} -/***************************************/ -static const char * const FortranWordLists[] = { - "Primary keywords and identifiers", - "Intrinsic functions", - "Extended and user defined functions", - 0, -}; -/***************************************/ -static void ColouriseFortranDocFreeFormat(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - ColouriseFortranDoc(startPos, length, initStyle, keywordlists, styler, false); -} -/***************************************/ -static void ColouriseFortranDocFixFormat(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - ColouriseFortranDoc(startPos, length, initStyle, keywordlists, styler, true); -} -/***************************************/ -static void FoldFortranDocFreeFormat(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - FoldFortranDoc(startPos, length, initStyle,styler, false); -} -/***************************************/ -static void FoldFortranDocFixFormat(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - FoldFortranDoc(startPos, length, initStyle,styler, true); -} -/***************************************/ -LexerModule lmFortran(SCLEX_FORTRAN, ColouriseFortranDocFreeFormat, "fortran", FoldFortranDocFreeFormat, FortranWordLists); -LexerModule lmF77(SCLEX_F77, ColouriseFortranDocFixFormat, "f77", FoldFortranDocFixFormat, FortranWordLists); +// Scintilla source code edit control +/** @file LexFortran.cxx + ** Lexer for Fortran. + ** Writen by Chuan-jian Shen, Last changed Sep. 2003 + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. +/***************************************/ +#include +#include +#include +#include +#include +#include +/***************************************/ +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +/***************************************/ + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +/***********************************************/ +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '%'); +} +/**********************************************/ +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch)); +} +/***************************************/ +inline bool IsABlank(unsigned int ch) { + return (ch == ' ') || (ch == 0x09) || (ch == 0x0b) ; +} +/***************************************/ +inline bool IsALineEnd(char ch) { + return ((ch == '\n') || (ch == '\r')) ; +} +/***************************************/ +unsigned int GetContinuedPos(unsigned int pos, Accessor &styler) { + while (!IsALineEnd(styler.SafeGetCharAt(pos++))) continue; + if (styler.SafeGetCharAt(pos) == '\n') pos++; + while (IsABlank(styler.SafeGetCharAt(pos++))) continue; + char chCur = styler.SafeGetCharAt(pos); + if (chCur == '&') { + while (IsABlank(styler.SafeGetCharAt(++pos))) continue; + return pos; + } else { + return pos; + } +} +/***************************************/ +static void ColouriseFortranDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler, bool isFixFormat) { + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + /***************************************/ + int posLineStart = 0, numNonBlank = 0, prevState = 0; + int endPos = startPos + length; + /***************************************/ + // backtrack to the nearest keyword + while ((startPos > 1) && (styler.StyleAt(startPos) != SCE_F_WORD)) { + startPos--; + } + startPos = styler.LineStart(styler.GetLine(startPos)); + initStyle = styler.StyleAt(startPos - 1); + StyleContext sc(startPos, endPos-startPos, initStyle, styler); + /***************************************/ + for (; sc.More(); sc.Forward()) { + // remember the start position of the line + if (sc.atLineStart) { + posLineStart = sc.currentPos; + numNonBlank = 0; + sc.SetState(SCE_F_DEFAULT); + } + if (!IsASpaceOrTab(sc.ch)) numNonBlank ++; + /***********************************************/ + // Handle the fix format generically + int toLineStart = sc.currentPos - posLineStart; + if (isFixFormat && (toLineStart < 6 || toLineStart > 72)) { + if ((toLineStart == 0 && (tolower(sc.ch) == 'c' || sc.ch == '*')) || sc.ch == '!') { + if (sc.MatchIgnoreCase("cdec$") || sc.MatchIgnoreCase("*dec$") || sc.MatchIgnoreCase("!dec$") || + sc.MatchIgnoreCase("cdir$") || sc.MatchIgnoreCase("*dir$") || sc.MatchIgnoreCase("!dir$") || + sc.MatchIgnoreCase("cms$") || sc.MatchIgnoreCase("*ms$") || sc.MatchIgnoreCase("!ms$") || + sc.chNext == '$') { + sc.SetState(SCE_F_PREPROCESSOR); + } else { + sc.SetState(SCE_F_COMMENT); + } + + while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end + } else if (toLineStart > 72) { + sc.SetState(SCE_F_COMMENT); + while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end + } else if (toLineStart < 5) { + if (IsADigit(sc.ch)) + sc.SetState(SCE_F_LABEL); + else + sc.SetState(SCE_F_DEFAULT); + } else if (toLineStart == 5) { + if (!IsASpace(sc.ch) && sc.ch != '0') { + sc.SetState(SCE_F_CONTINUATION); + sc.ForwardSetState(prevState); + } else + sc.SetState(SCE_F_DEFAULT); + } + continue; + } + /***************************************/ + // Handle line continuation generically. + if (!isFixFormat && sc.ch == '&') { + char chTemp = ' '; + int j = 1; + while (IsABlank(chTemp) && j<132) { + chTemp = static_cast(sc.GetRelative(j)); + j++; + } + if (chTemp == '!') { + sc.SetState(SCE_F_CONTINUATION); + if (sc.chNext == '!') sc.ForwardSetState(SCE_F_COMMENT); + } else if (chTemp == '\r' || chTemp == '\n') { + int currentState = sc.state; + sc.SetState(SCE_F_CONTINUATION); + sc.ForwardSetState(SCE_F_DEFAULT); + while (IsASpace(sc.ch) && sc.More()) sc.Forward(); + if (sc.ch == '&') { + sc.SetState(SCE_F_CONTINUATION); + sc.Forward(); + } + sc.SetState(currentState); + } + } + /***************************************/ + // Determine if the current state should terminate. + if (sc.state == SCE_F_OPERATOR) { + sc.SetState(SCE_F_DEFAULT); + } else if (sc.state == SCE_F_NUMBER) { + if (!(IsAWordChar(sc.ch) || sc.ch=='\'' || sc.ch=='\"' || sc.ch=='.')) { + sc.SetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_IDENTIFIER) { + if (!IsAWordChar(sc.ch) || (sc.ch == '%')) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_F_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_F_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_F_WORD3); + } + sc.SetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_COMMENT || sc.state == SCE_F_PREPROCESSOR) { + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_STRING1) { + prevState = sc.state; + if (sc.ch == '\'') { + if (sc.chNext == '\'') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_F_DEFAULT); + prevState = SCE_F_DEFAULT; + } + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_F_STRINGEOL); + sc.ForwardSetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_STRING2) { + prevState = sc.state; + if (sc.atLineEnd) { + sc.ChangeState(SCE_F_STRINGEOL); + sc.ForwardSetState(SCE_F_DEFAULT); + } else if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_F_DEFAULT); + prevState = SCE_F_DEFAULT; + } + } + } else if (sc.state == SCE_F_OPERATOR2) { + if (sc.ch == '.') { + sc.ForwardSetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_CONTINUATION) { + sc.SetState(SCE_F_DEFAULT); + } else if (sc.state == SCE_F_LABEL) { + if (!IsADigit(sc.ch)) { + sc.SetState(SCE_F_DEFAULT); + } else { + if (isFixFormat && sc.currentPos-posLineStart > 4) + sc.SetState(SCE_F_DEFAULT); + else if (numNonBlank > 5) + sc.SetState(SCE_F_DEFAULT); + } + } + /***************************************/ + // Determine if a new state should be entered. + if (sc.state == SCE_F_DEFAULT) { + if (sc.ch == '!') { + if (sc.MatchIgnoreCase("!dec$") || sc.MatchIgnoreCase("!dir$") || + sc.MatchIgnoreCase("!ms$") || sc.chNext == '$') { + sc.SetState(SCE_F_PREPROCESSOR); + } else { + sc.SetState(SCE_F_COMMENT); + } + } else if ((!isFixFormat) && IsADigit(sc.ch) && numNonBlank == 1) { + sc.SetState(SCE_F_LABEL); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_F_NUMBER); + } else if ((tolower(sc.ch) == 'b' || tolower(sc.ch) == 'o' || + tolower(sc.ch) == 'z') && (sc.chNext == '\"' || sc.chNext == '\'')) { + sc.SetState(SCE_F_NUMBER); + sc.Forward(); + } else if (sc.ch == '.' && isalpha(sc.chNext)) { + sc.SetState(SCE_F_OPERATOR2); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_F_IDENTIFIER); + } else if (sc.ch == '\"') { + sc.SetState(SCE_F_STRING2); + } else if (sc.ch == '\'') { + sc.SetState(SCE_F_STRING1); + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_F_OPERATOR); + } + } + } + sc.Complete(); +} +/***************************************/ +// To determine the folding level depending on keywords +static int classifyFoldPointFortran(const char* s, const char* prevWord, const char chNextNonBlank) { + int lev = 0; + if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "elseif") == 0) + return -1; + if (strcmp(s, "associate") == 0 || strcmp(s, "block") == 0 + || strcmp(s, "blockdata") == 0 || strcmp(s, "select") == 0 + || strcmp(s, "do") == 0 || strcmp(s, "enum") ==0 + || strcmp(s, "function") == 0 || strcmp(s, "interface") == 0 + || strcmp(s, "module") == 0 || strcmp(s, "program") == 0 + || strcmp(s, "subroutine") == 0 || strcmp(s, "then") == 0 + || (strcmp(s, "type") == 0 && chNextNonBlank != '(') ){ + if (strcmp(prevWord, "end") == 0) + lev = 0; + else + lev = 1; + } else if ((strcmp(s, "end") == 0 && chNextNonBlank != '=') + || strcmp(s, "endassociate") == 0 || strcmp(s, "endblock") == 0 + || strcmp(s, "endblockdata") == 0 || strcmp(s, "endselect") == 0 + || strcmp(s, "enddo") == 0 || strcmp(s, "endenum") ==0 + || strcmp(s, "endif") == 0 || strcmp(s, "endforall") == 0 + || strcmp(s, "endfunction") == 0 || strcmp(s, "endinterface") == 0 + || strcmp(s, "endmodule") == 0 || strcmp(s, "endprogram") == 0 + || strcmp(s, "endsubroutine") == 0 || strcmp(s, "endtype") == 0 + || strcmp(s, "endwhere") == 0 + || (strcmp(s, "procedure") == 0 && strcmp(prevWord,"module")==0) ) { // Take care of the module procedure statement + lev = -1; + } else if (strcmp(prevWord, "end") == 0 && strcmp(s, "if") == 0){ // end if + lev = 0; + } + return lev; +} +// Folding the code +static void FoldFortranDoc(unsigned int startPos, int length, int initStyle, + Accessor &styler, bool isFixFormat) { + // + // bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + // Do not know how to fold the comment at the moment. + // + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + char chNextNonBlank; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + /***************************************/ + int lastStart = 0; + char prevWord[32] = ""; + char Label[6] = ""; + // Variables for do label folding. + static int doLabels[100]; + static int posLabel=-1; + /***************************************/ + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + chNextNonBlank = chNext; + unsigned int j=i+1; + while(IsABlank(chNextNonBlank) && j(tolower(styler[lastStart+k])); + } + s[k] = '\0'; + // Handle the forall and where statement and structure. + if (strcmp(s, "forall") == 0 || strcmp(s, "where") == 0) { + if (strcmp(prevWord, "end") != 0) { + j = i + 1; + char chBrace = '(', chSeek = ')', ch1 = styler.SafeGetCharAt(j); + // Find the position of the first ( + while (ch1 != chBrace && j -1) { + levelCurrent--; + posLabel--; + } + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + strcpy(prevWord, ""); + } + /***************************************/ + if (!isspacechar(ch)) visibleChars++; + } + /***************************************/ + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} +/***************************************/ +static const char * const FortranWordLists[] = { + "Primary keywords and identifiers", + "Intrinsic functions", + "Extended and user defined functions", + 0, +}; +/***************************************/ +static void ColouriseFortranDocFreeFormat(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + ColouriseFortranDoc(startPos, length, initStyle, keywordlists, styler, false); +} +/***************************************/ +static void ColouriseFortranDocFixFormat(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + ColouriseFortranDoc(startPos, length, initStyle, keywordlists, styler, true); +} +/***************************************/ +static void FoldFortranDocFreeFormat(unsigned int startPos, int length, int initStyle, + WordList *[], Accessor &styler) { + FoldFortranDoc(startPos, length, initStyle,styler, false); +} +/***************************************/ +static void FoldFortranDocFixFormat(unsigned int startPos, int length, int initStyle, + WordList *[], Accessor &styler) { + FoldFortranDoc(startPos, length, initStyle,styler, true); +} +/***************************************/ +LexerModule lmFortran(SCLEX_FORTRAN, ColouriseFortranDocFreeFormat, "fortran", FoldFortranDocFreeFormat, FortranWordLists); +LexerModule lmF77(SCLEX_F77, ColouriseFortranDocFixFormat, "f77", FoldFortranDocFixFormat, FortranWordLists); diff --git a/scintilla/lexers/LexGAP.cxx b/ThirdLibs/scintilla/lexers/LexGAP.cxx similarity index 96% rename from scintilla/lexers/LexGAP.cxx rename to ThirdLibs/scintilla/lexers/LexGAP.cxx index f37884e5..fb306609 100644 --- a/scintilla/lexers/LexGAP.cxx +++ b/ThirdLibs/scintilla/lexers/LexGAP.cxx @@ -1,266 +1,266 @@ -// Scintilla source code edit control -/** @file LexGAP.cxx - ** Lexer for the GAP language. (The GAP System for Computational Discrete Algebra) - ** http://www.gap-system.org - **/ -// Copyright 2007 by Istvan Szollosi ( szteven gmail com ) -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsGAPOperator(char ch) { - if (isascii(ch) && isalnum(ch)) return false; - if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || - ch == '^' || ch == ',' || ch == '!' || ch == '.' || - ch == '=' || ch == '<' || ch == '>' || ch == '(' || - ch == ')' || ch == ';' || ch == '[' || ch == ']' || - ch == '{' || ch == '}' || ch == ':' ) - return true; - return false; -} - -static void GetRange(unsigned int start, unsigned int end, Accessor &styler, char *s, unsigned int len) { - unsigned int i = 0; - while ((i < end - start + 1) && (i < len-1)) { - s[i] = static_cast(styler[start + i]); - i++; - } - s[i] = '\0'; -} - -static void ColouriseGAPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { - - WordList &keywords1 = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - - // Do not leak onto next line - if (initStyle == SCE_GAP_STRINGEOL) initStyle = SCE_GAP_DEFAULT; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - // Prevent SCE_GAP_STRINGEOL from leaking back to previous line - if ( sc.atLineStart ) { - if (sc.state == SCE_GAP_STRING) sc.SetState(SCE_GAP_STRING); - if (sc.state == SCE_GAP_CHAR) sc.SetState(SCE_GAP_CHAR); - } - - // Handle line continuation generically - if (sc.ch == '\\' ) { - if (sc.chNext == '\n' || sc.chNext == '\r') { - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - sc.Forward(); - } - continue; - } - } - - // Determine if the current state should terminate - switch (sc.state) { - case SCE_GAP_OPERATOR : - sc.SetState(SCE_GAP_DEFAULT); - break; - - case SCE_GAP_NUMBER : - if (!IsADigit(sc.ch)) { - if (sc.ch == '\\') { - if (!sc.atLineEnd) { - if (!IsADigit(sc.chNext)) { - sc.Forward(); - sc.ChangeState(SCE_GAP_IDENTIFIER); - } - } - } else if (isalpha(sc.ch) || sc.ch == '_') { - sc.ChangeState(SCE_GAP_IDENTIFIER); - } - else sc.SetState(SCE_GAP_DEFAULT); - } - break; - - case SCE_GAP_IDENTIFIER : - if (!(iswordstart(static_cast(sc.ch)) || sc.ch == '$')) { - if (sc.ch == '\\') sc.Forward(); - else { - char s[1000]; - sc.GetCurrent(s, sizeof(s)); - if (keywords1.InList(s)) { - sc.ChangeState(SCE_GAP_KEYWORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_GAP_KEYWORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_GAP_KEYWORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_GAP_KEYWORD4); - } - sc.SetState(SCE_GAP_DEFAULT); - } - } - break; - - case SCE_GAP_COMMENT : - if (sc.atLineEnd) { - sc.SetState(SCE_GAP_DEFAULT); - } - break; - - case SCE_GAP_STRING: - if (sc.atLineEnd) { - sc.ChangeState(SCE_GAP_STRINGEOL); - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_GAP_DEFAULT); - } - break; - - case SCE_GAP_CHAR: - if (sc.atLineEnd) { - sc.ChangeState(SCE_GAP_STRINGEOL); - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_GAP_DEFAULT); - } - break; - - case SCE_GAP_STRINGEOL: - if (sc.atLineStart) { - sc.SetState(SCE_GAP_DEFAULT); - } - break; - } - - // Determine if a new state should be entered - if (sc.state == SCE_GAP_DEFAULT) { - if (IsGAPOperator(static_cast(sc.ch))) { - sc.SetState(SCE_GAP_OPERATOR); - } - else if (IsADigit(sc.ch)) { - sc.SetState(SCE_GAP_NUMBER); - } else if (isalpha(sc.ch) || sc.ch == '_' || sc.ch == '\\' || sc.ch == '$' || sc.ch == '~') { - sc.SetState(SCE_GAP_IDENTIFIER); - if (sc.ch == '\\') sc.Forward(); - } else if (sc.ch == '#') { - sc.SetState(SCE_GAP_COMMENT); - } else if (sc.ch == '\"') { - sc.SetState(SCE_GAP_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_GAP_CHAR); - } - } - - } - sc.Complete(); -} - -static int ClassifyFoldPointGAP(const char* s) { - int level = 0; - if (strcmp(s, "function") == 0 || - strcmp(s, "do") == 0 || - strcmp(s, "if") == 0 || - strcmp(s, "repeat") == 0 ) { - level = 1; - } else if (strcmp(s, "end") == 0 || - strcmp(s, "od") == 0 || - strcmp(s, "fi") == 0 || - strcmp(s, "until") == 0 ) { - level = -1; - } - return level; -} - -static void FoldGAPDoc( unsigned int startPos, int length, int initStyle, WordList** , Accessor &styler) { - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - - int lastStart = 0; - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if (stylePrev != SCE_GAP_KEYWORD && style == SCE_GAP_KEYWORD) { - // Store last word start point. - lastStart = i; - } - - if (stylePrev == SCE_GAP_KEYWORD) { - if(iswordchar(ch) && !iswordchar(chNext)) { - char s[100]; - GetRange(lastStart, i, styler, s, sizeof(s)); - levelCurrent += ClassifyFoldPointGAP(s); - } - } - - if (atEOL) { - int lev = levelPrev; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - - if (!isspacechar(ch)) - visibleChars++; - } - - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const GAPWordListDesc[] = { - "Keywords 1", - "Keywords 2", - "Keywords 3 (unused)", - "Keywords 4 (unused)", - 0 -}; - -LexerModule lmGAP( - SCLEX_GAP, - ColouriseGAPDoc, - "gap", - FoldGAPDoc, - GAPWordListDesc); +// Scintilla source code edit control +/** @file LexGAP.cxx + ** Lexer for the GAP language. (The GAP System for Computational Discrete Algebra) + ** http://www.gap-system.org + **/ +// Copyright 2007 by Istvan Szollosi ( szteven gmail com ) +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsGAPOperator(char ch) { + if (isascii(ch) && isalnum(ch)) return false; + if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || + ch == '^' || ch == ',' || ch == '!' || ch == '.' || + ch == '=' || ch == '<' || ch == '>' || ch == '(' || + ch == ')' || ch == ';' || ch == '[' || ch == ']' || + ch == '{' || ch == '}' || ch == ':' ) + return true; + return false; +} + +static void GetRange(unsigned int start, unsigned int end, Accessor &styler, char *s, unsigned int len) { + unsigned int i = 0; + while ((i < end - start + 1) && (i < len-1)) { + s[i] = static_cast(styler[start + i]); + i++; + } + s[i] = '\0'; +} + +static void ColouriseGAPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { + + WordList &keywords1 = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + + // Do not leak onto next line + if (initStyle == SCE_GAP_STRINGEOL) initStyle = SCE_GAP_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + // Prevent SCE_GAP_STRINGEOL from leaking back to previous line + if ( sc.atLineStart ) { + if (sc.state == SCE_GAP_STRING) sc.SetState(SCE_GAP_STRING); + if (sc.state == SCE_GAP_CHAR) sc.SetState(SCE_GAP_CHAR); + } + + // Handle line continuation generically + if (sc.ch == '\\' ) { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continue; + } + } + + // Determine if the current state should terminate + switch (sc.state) { + case SCE_GAP_OPERATOR : + sc.SetState(SCE_GAP_DEFAULT); + break; + + case SCE_GAP_NUMBER : + if (!IsADigit(sc.ch)) { + if (sc.ch == '\\') { + if (!sc.atLineEnd) { + if (!IsADigit(sc.chNext)) { + sc.Forward(); + sc.ChangeState(SCE_GAP_IDENTIFIER); + } + } + } else if (isalpha(sc.ch) || sc.ch == '_') { + sc.ChangeState(SCE_GAP_IDENTIFIER); + } + else sc.SetState(SCE_GAP_DEFAULT); + } + break; + + case SCE_GAP_IDENTIFIER : + if (!(iswordstart(static_cast(sc.ch)) || sc.ch == '$')) { + if (sc.ch == '\\') sc.Forward(); + else { + char s[1000]; + sc.GetCurrent(s, sizeof(s)); + if (keywords1.InList(s)) { + sc.ChangeState(SCE_GAP_KEYWORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_GAP_KEYWORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_GAP_KEYWORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_GAP_KEYWORD4); + } + sc.SetState(SCE_GAP_DEFAULT); + } + } + break; + + case SCE_GAP_COMMENT : + if (sc.atLineEnd) { + sc.SetState(SCE_GAP_DEFAULT); + } + break; + + case SCE_GAP_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_GAP_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_GAP_DEFAULT); + } + break; + + case SCE_GAP_CHAR: + if (sc.atLineEnd) { + sc.ChangeState(SCE_GAP_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_GAP_DEFAULT); + } + break; + + case SCE_GAP_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_GAP_DEFAULT); + } + break; + } + + // Determine if a new state should be entered + if (sc.state == SCE_GAP_DEFAULT) { + if (IsGAPOperator(static_cast(sc.ch))) { + sc.SetState(SCE_GAP_OPERATOR); + } + else if (IsADigit(sc.ch)) { + sc.SetState(SCE_GAP_NUMBER); + } else if (isalpha(sc.ch) || sc.ch == '_' || sc.ch == '\\' || sc.ch == '$' || sc.ch == '~') { + sc.SetState(SCE_GAP_IDENTIFIER); + if (sc.ch == '\\') sc.Forward(); + } else if (sc.ch == '#') { + sc.SetState(SCE_GAP_COMMENT); + } else if (sc.ch == '\"') { + sc.SetState(SCE_GAP_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_GAP_CHAR); + } + } + + } + sc.Complete(); +} + +static int ClassifyFoldPointGAP(const char* s) { + int level = 0; + if (strcmp(s, "function") == 0 || + strcmp(s, "do") == 0 || + strcmp(s, "if") == 0 || + strcmp(s, "repeat") == 0 ) { + level = 1; + } else if (strcmp(s, "end") == 0 || + strcmp(s, "od") == 0 || + strcmp(s, "fi") == 0 || + strcmp(s, "until") == 0 ) { + level = -1; + } + return level; +} + +static void FoldGAPDoc( unsigned int startPos, int length, int initStyle, WordList** , Accessor &styler) { + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + + int lastStart = 0; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (stylePrev != SCE_GAP_KEYWORD && style == SCE_GAP_KEYWORD) { + // Store last word start point. + lastStart = i; + } + + if (stylePrev == SCE_GAP_KEYWORD) { + if(iswordchar(ch) && !iswordchar(chNext)) { + char s[100]; + GetRange(lastStart, i, styler, s, sizeof(s)); + levelCurrent += ClassifyFoldPointGAP(s); + } + } + + if (atEOL) { + int lev = levelPrev; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + + if (!isspacechar(ch)) + visibleChars++; + } + + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const GAPWordListDesc[] = { + "Keywords 1", + "Keywords 2", + "Keywords 3 (unused)", + "Keywords 4 (unused)", + 0 +}; + +LexerModule lmGAP( + SCLEX_GAP, + ColouriseGAPDoc, + "gap", + FoldGAPDoc, + GAPWordListDesc); diff --git a/scintilla/lexers/LexGui4Cli.cxx b/ThirdLibs/scintilla/lexers/LexGui4Cli.cxx similarity index 96% rename from scintilla/lexers/LexGui4Cli.cxx rename to ThirdLibs/scintilla/lexers/LexGui4Cli.cxx index 8136425e..13cf9ea8 100644 --- a/scintilla/lexers/LexGui4Cli.cxx +++ b/ThirdLibs/scintilla/lexers/LexGui4Cli.cxx @@ -1,316 +1,316 @@ -// Scintilla source code edit control -// Copyright 1998-2002 by Neil Hodgson -/* -This is the Lexer for Gui4Cli, included in SciLexer.dll -- by d. Keletsekis, 2/10/2003 - -To add to SciLexer.dll: -1. Add the values below to INCLUDE\Scintilla.iface -2. Run the include/HFacer.py script -3. Run the src/lexGen.py script - -val SCE_GC_DEFAULT=0 -val SCE_GC_COMMENTLINE=1 -val SCE_GC_COMMENTBLOCK=2 -val SCE_GC_GLOBAL=3 -val SCE_GC_EVENT=4 -val SCE_GC_ATTRIBUTE=5 -val SCE_GC_CONTROL=6 -val SCE_GC_COMMAND=7 -val SCE_GC_STRING=8 -val SCE_GC_OPERATOR=9 -*/ - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#define debug Platform::DebugPrintf - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch =='\\'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.'); -} - -inline bool isGCOperator(int ch) -{ if (isalnum(ch)) - return false; - // '.' left out as it is used to make up numbers - if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || ch == '%' || - ch == '[' || ch == ']' || ch == '<' || ch == '>' || - ch == ',' || ch == ';' || ch == ':') - return true; - return false; -} - -#define isSpace(x) ((x)==' ' || (x)=='\t') -#define isNL(x) ((x)=='\n' || (x)=='\r') -#define isSpaceOrNL(x) (isSpace(x) || isNL(x)) -#define BUFFSIZE 500 -#define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024) - -static void colorFirstWord(WordList *keywordlists[], Accessor &styler, - StyleContext *sc, char *buff, int length, int) -{ - int c = 0; - while (sc->More() && isSpaceOrNL(sc->ch)) - { sc->Forward(); - } - styler.ColourTo(sc->currentPos - 1, sc->state); - - if (!IsAWordChar(sc->ch)) // comment, marker, etc.. - return; - - while (sc->More() && !isSpaceOrNL(sc->ch) && (c < length-1) && !isGCOperator(sc->ch)) - { buff[c] = static_cast(sc->ch); - ++c; sc->Forward(); - } - buff[c] = '\0'; - char *p = buff; - while (*p) // capitalize.. - { if (islower(*p)) *p = static_cast(toupper(*p)); - ++p; - } - - WordList &kGlobal = *keywordlists[0]; // keyword lists set by the user - WordList &kEvent = *keywordlists[1]; - WordList &kAttribute = *keywordlists[2]; - WordList &kControl = *keywordlists[3]; - WordList &kCommand = *keywordlists[4]; - - int state = 0; - // int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK; - // debug ("line = %d, level = %d", line, level); - - if (kGlobal.InList(buff)) state = SCE_GC_GLOBAL; - else if (kAttribute.InList(buff)) state = SCE_GC_ATTRIBUTE; - else if (kControl.InList(buff)) state = SCE_GC_CONTROL; - else if (kCommand.InList(buff)) state = SCE_GC_COMMAND; - else if (kEvent.InList(buff)) state = SCE_GC_EVENT; - - if (state) - { sc->ChangeState(state); - styler.ColourTo(sc->currentPos - 1, sc->state); - sc->ChangeState(SCE_GC_DEFAULT); - } - else - { sc->ChangeState(SCE_GC_DEFAULT); - styler.ColourTo(sc->currentPos - 1, sc->state); - } -} - -// Main colorizing function called by Scintilla -static void -ColouriseGui4CliDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) -{ - styler.StartAt(startPos); - - int quotestart = 0, oldstate, currentline = styler.GetLine(startPos); - styler.StartSegment(startPos); - bool noforward; - char buff[BUFFSIZE+1]; // buffer for command name - - StyleContext sc(startPos, length, initStyle, styler); - buff[0] = '\0'; // cbuff = 0; - - if (sc.state != SCE_GC_COMMENTBLOCK) // colorize 1st word.. - colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); - - while (sc.More()) - { noforward = 0; - - switch (sc.ch) - { - case '/': - if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING) - break; - if (sc.chNext == '/') // line comment - { sc.SetState (SCE_GC_COMMENTLINE); - sc.Forward(); - styler.ColourTo(sc.currentPos, sc.state); - } - else if (sc.chNext == '*') // block comment - { sc.SetState(SCE_GC_COMMENTBLOCK); - sc.Forward(); - styler.ColourTo(sc.currentPos, sc.state); - } - else - styler.ColourTo(sc.currentPos, sc.state); - break; - - case '*': // end of comment block, or operator.. - if (sc.state == SCE_GC_STRING) - break; - if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/') - { sc.Forward(); - styler.ColourTo(sc.currentPos, sc.state); - sc.ChangeState (SCE_GC_DEFAULT); - } - else - styler.ColourTo(sc.currentPos, sc.state); - break; - - case '\'': case '\"': // strings.. - if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE) - break; - if (sc.state == SCE_GC_STRING) - { if (sc.ch == quotestart) // match same quote char.. - { styler.ColourTo(sc.currentPos, sc.state); - sc.ChangeState(SCE_GC_DEFAULT); - quotestart = 0; - } } - else - { styler.ColourTo(sc.currentPos - 1, sc.state); - sc.ChangeState(SCE_GC_STRING); - quotestart = sc.ch; - } - break; - - case ';': // end of commandline character - if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE && - sc.state != SCE_GC_STRING) - { - styler.ColourTo(sc.currentPos - 1, sc.state); - styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); - sc.ChangeState(SCE_GC_DEFAULT); - sc.Forward(); - colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); - noforward = 1; // don't move forward - already positioned at next char.. - } - break; - - case '+': case '-': case '=': case '!': // operators.. - case '<': case '>': case '&': case '|': case '$': - if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE && - sc.state != SCE_GC_STRING) - { - styler.ColourTo(sc.currentPos - 1, sc.state); - styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); - sc.ChangeState(SCE_GC_DEFAULT); - } - break; - - case '\\': // escape - same as operator, but also mark in strings.. - if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE) - { - oldstate = sc.state; - styler.ColourTo(sc.currentPos - 1, sc.state); - sc.Forward(); // mark also the next char.. - styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); - sc.ChangeState(oldstate); - } - break; - - case '\n': case '\r': - ++currentline; - if (sc.state == SCE_GC_COMMENTLINE) - { styler.ColourTo(sc.currentPos, sc.state); - sc.ChangeState (SCE_GC_DEFAULT); - } - else if (sc.state != SCE_GC_COMMENTBLOCK) - { colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); - noforward = 1; // don't move forward - already positioned at next char.. - } - break; - -// case ' ': case '\t': -// default : - } - - if (!noforward) sc.Forward(); - - } - sc.Complete(); -} - -// Main folding function called by Scintilla - (based on props (.ini) files function) -static void FoldGui4Cli(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) -{ - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - bool headerPoint = false; - - for (unsigned int i = startPos; i < endPos; i++) - { - char ch = chNext; - chNext = styler[i+1]; - - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if (style == SCE_GC_EVENT || style == SCE_GC_GLOBAL) - { headerPoint = true; // fold at events and globals - } - - if (atEOL) - { int lev = SC_FOLDLEVELBASE+1; - - if (headerPoint) - lev = SC_FOLDLEVELBASE; - - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - - if (headerPoint) - lev |= SC_FOLDLEVELHEADERFLAG; - - if (lev != styler.LevelAt(lineCurrent)) // set level, if not already correct - { styler.SetLevel(lineCurrent, lev); - } - - lineCurrent++; // re-initialize our flags - visibleChars = 0; - headerPoint = false; - } - - if (!(isspacechar(ch))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK))) - visibleChars++; - } - - int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1; - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, lev | flagsNext); -} - -// I have no idea what these are for.. probably accessible by some message. -static const char * const gui4cliWordListDesc[] = { - "Globals", "Events", "Attributes", "Control", "Commands", - 0 -}; - -// Declare language & pass our function pointers to Scintilla -LexerModule lmGui4Cli(SCLEX_GUI4CLI, ColouriseGui4CliDoc, "gui4cli", FoldGui4Cli, gui4cliWordListDesc); - -#undef debug - +// Scintilla source code edit control +// Copyright 1998-2002 by Neil Hodgson +/* +This is the Lexer for Gui4Cli, included in SciLexer.dll +- by d. Keletsekis, 2/10/2003 + +To add to SciLexer.dll: +1. Add the values below to INCLUDE\Scintilla.iface +2. Run the include/HFacer.py script +3. Run the src/lexGen.py script + +val SCE_GC_DEFAULT=0 +val SCE_GC_COMMENTLINE=1 +val SCE_GC_COMMENTBLOCK=2 +val SCE_GC_GLOBAL=3 +val SCE_GC_EVENT=4 +val SCE_GC_ATTRIBUTE=5 +val SCE_GC_CONTROL=6 +val SCE_GC_COMMAND=7 +val SCE_GC_STRING=8 +val SCE_GC_OPERATOR=9 +*/ + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#define debug Platform::DebugPrintf + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch =='\\'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.'); +} + +inline bool isGCOperator(int ch) +{ if (isalnum(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '%' || + ch == '[' || ch == ']' || ch == '<' || ch == '>' || + ch == ',' || ch == ';' || ch == ':') + return true; + return false; +} + +#define isSpace(x) ((x)==' ' || (x)=='\t') +#define isNL(x) ((x)=='\n' || (x)=='\r') +#define isSpaceOrNL(x) (isSpace(x) || isNL(x)) +#define BUFFSIZE 500 +#define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024) + +static void colorFirstWord(WordList *keywordlists[], Accessor &styler, + StyleContext *sc, char *buff, int length, int) +{ + int c = 0; + while (sc->More() && isSpaceOrNL(sc->ch)) + { sc->Forward(); + } + styler.ColourTo(sc->currentPos - 1, sc->state); + + if (!IsAWordChar(sc->ch)) // comment, marker, etc.. + return; + + while (sc->More() && !isSpaceOrNL(sc->ch) && (c < length-1) && !isGCOperator(sc->ch)) + { buff[c] = static_cast(sc->ch); + ++c; sc->Forward(); + } + buff[c] = '\0'; + char *p = buff; + while (*p) // capitalize.. + { if (islower(*p)) *p = static_cast(toupper(*p)); + ++p; + } + + WordList &kGlobal = *keywordlists[0]; // keyword lists set by the user + WordList &kEvent = *keywordlists[1]; + WordList &kAttribute = *keywordlists[2]; + WordList &kControl = *keywordlists[3]; + WordList &kCommand = *keywordlists[4]; + + int state = 0; + // int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK; + // debug ("line = %d, level = %d", line, level); + + if (kGlobal.InList(buff)) state = SCE_GC_GLOBAL; + else if (kAttribute.InList(buff)) state = SCE_GC_ATTRIBUTE; + else if (kControl.InList(buff)) state = SCE_GC_CONTROL; + else if (kCommand.InList(buff)) state = SCE_GC_COMMAND; + else if (kEvent.InList(buff)) state = SCE_GC_EVENT; + + if (state) + { sc->ChangeState(state); + styler.ColourTo(sc->currentPos - 1, sc->state); + sc->ChangeState(SCE_GC_DEFAULT); + } + else + { sc->ChangeState(SCE_GC_DEFAULT); + styler.ColourTo(sc->currentPos - 1, sc->state); + } +} + +// Main colorizing function called by Scintilla +static void +ColouriseGui4CliDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) +{ + styler.StartAt(startPos); + + int quotestart = 0, oldstate, currentline = styler.GetLine(startPos); + styler.StartSegment(startPos); + bool noforward; + char buff[BUFFSIZE+1]; // buffer for command name + + StyleContext sc(startPos, length, initStyle, styler); + buff[0] = '\0'; // cbuff = 0; + + if (sc.state != SCE_GC_COMMENTBLOCK) // colorize 1st word.. + colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); + + while (sc.More()) + { noforward = 0; + + switch (sc.ch) + { + case '/': + if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING) + break; + if (sc.chNext == '/') // line comment + { sc.SetState (SCE_GC_COMMENTLINE); + sc.Forward(); + styler.ColourTo(sc.currentPos, sc.state); + } + else if (sc.chNext == '*') // block comment + { sc.SetState(SCE_GC_COMMENTBLOCK); + sc.Forward(); + styler.ColourTo(sc.currentPos, sc.state); + } + else + styler.ColourTo(sc.currentPos, sc.state); + break; + + case '*': // end of comment block, or operator.. + if (sc.state == SCE_GC_STRING) + break; + if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/') + { sc.Forward(); + styler.ColourTo(sc.currentPos, sc.state); + sc.ChangeState (SCE_GC_DEFAULT); + } + else + styler.ColourTo(sc.currentPos, sc.state); + break; + + case '\'': case '\"': // strings.. + if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE) + break; + if (sc.state == SCE_GC_STRING) + { if (sc.ch == quotestart) // match same quote char.. + { styler.ColourTo(sc.currentPos, sc.state); + sc.ChangeState(SCE_GC_DEFAULT); + quotestart = 0; + } } + else + { styler.ColourTo(sc.currentPos - 1, sc.state); + sc.ChangeState(SCE_GC_STRING); + quotestart = sc.ch; + } + break; + + case ';': // end of commandline character + if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE && + sc.state != SCE_GC_STRING) + { + styler.ColourTo(sc.currentPos - 1, sc.state); + styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); + sc.ChangeState(SCE_GC_DEFAULT); + sc.Forward(); + colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); + noforward = 1; // don't move forward - already positioned at next char.. + } + break; + + case '+': case '-': case '=': case '!': // operators.. + case '<': case '>': case '&': case '|': case '$': + if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE && + sc.state != SCE_GC_STRING) + { + styler.ColourTo(sc.currentPos - 1, sc.state); + styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); + sc.ChangeState(SCE_GC_DEFAULT); + } + break; + + case '\\': // escape - same as operator, but also mark in strings.. + if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE) + { + oldstate = sc.state; + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(); // mark also the next char.. + styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); + sc.ChangeState(oldstate); + } + break; + + case '\n': case '\r': + ++currentline; + if (sc.state == SCE_GC_COMMENTLINE) + { styler.ColourTo(sc.currentPos, sc.state); + sc.ChangeState (SCE_GC_DEFAULT); + } + else if (sc.state != SCE_GC_COMMENTBLOCK) + { colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); + noforward = 1; // don't move forward - already positioned at next char.. + } + break; + +// case ' ': case '\t': +// default : + } + + if (!noforward) sc.Forward(); + + } + sc.Complete(); +} + +// Main folding function called by Scintilla - (based on props (.ini) files function) +static void FoldGui4Cli(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) +{ + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + bool headerPoint = false; + + for (unsigned int i = startPos; i < endPos; i++) + { + char ch = chNext; + chNext = styler[i+1]; + + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (style == SCE_GC_EVENT || style == SCE_GC_GLOBAL) + { headerPoint = true; // fold at events and globals + } + + if (atEOL) + { int lev = SC_FOLDLEVELBASE+1; + + if (headerPoint) + lev = SC_FOLDLEVELBASE; + + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + + if (headerPoint) + lev |= SC_FOLDLEVELHEADERFLAG; + + if (lev != styler.LevelAt(lineCurrent)) // set level, if not already correct + { styler.SetLevel(lineCurrent, lev); + } + + lineCurrent++; // re-initialize our flags + visibleChars = 0; + headerPoint = false; + } + + if (!(isspacechar(ch))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK))) + visibleChars++; + } + + int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1; + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, lev | flagsNext); +} + +// I have no idea what these are for.. probably accessible by some message. +static const char * const gui4cliWordListDesc[] = { + "Globals", "Events", "Attributes", "Control", "Commands", + 0 +}; + +// Declare language & pass our function pointers to Scintilla +LexerModule lmGui4Cli(SCLEX_GUI4CLI, ColouriseGui4CliDoc, "gui4cli", FoldGui4Cli, gui4cliWordListDesc); + +#undef debug + diff --git a/scintilla/lexers/LexHTML.cxx b/ThirdLibs/scintilla/lexers/LexHTML.cxx similarity index 96% rename from scintilla/lexers/LexHTML.cxx rename to ThirdLibs/scintilla/lexers/LexHTML.cxx index 5fe4746d..d8d4d2e9 100644 --- a/scintilla/lexers/LexHTML.cxx +++ b/ThirdLibs/scintilla/lexers/LexHTML.cxx @@ -1,2184 +1,2184 @@ -// Scintilla source code edit control -/** @file LexHTML.cxx - ** Lexer for HTML. - **/ -// Copyright 1998-2005 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#define SCE_HA_JS (SCE_HJA_START - SCE_HJ_START) -#define SCE_HA_VBS (SCE_HBA_START - SCE_HB_START) -#define SCE_HA_PYTHON (SCE_HPA_START - SCE_HP_START) - -enum script_type { eScriptNone = 0, eScriptJS, eScriptVBS, eScriptPython, eScriptPHP, eScriptXML, eScriptSGML, eScriptSGMLblock, eScriptComment }; -enum script_mode { eHtml = 0, eNonHtmlScript, eNonHtmlPreProc, eNonHtmlScriptPreProc }; - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -inline bool IsOperator(int ch) { - if (isascii(ch) && isalnum(ch)) - return false; - // '.' left out as it is used to make up numbers - if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || - ch == '(' || ch == ')' || ch == '-' || ch == '+' || - ch == '=' || ch == '|' || ch == '{' || ch == '}' || - ch == '[' || ch == ']' || ch == ':' || ch == ';' || - ch == '<' || ch == '>' || ch == ',' || ch == '/' || - ch == '?' || ch == '!' || ch == '.' || ch == '~') - return true; - return false; -} - -static void GetTextSegment(Accessor &styler, unsigned int start, unsigned int end, char *s, size_t len) { - unsigned int i = 0; - for (; (i < end - start + 1) && (i < len-1); i++) { - s[i] = static_cast(MakeLowerCase(styler[start + i])); - } - s[i] = '\0'; -} - -static const char *GetNextWord(Accessor &styler, unsigned int start, char *s, size_t sLen) { - - unsigned int i = 0; - for (; i < sLen-1; i++) { - char ch = static_cast(styler.SafeGetCharAt(start + i)); - if ((i == 0) && !IsAWordStart(ch)) - break; - if ((i > 0) && !IsAWordChar(ch)) - break; - s[i] = ch; - } - s[i] = '\0'; - - return s; -} - -static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, script_type prevValue) { - char s[100]; - GetTextSegment(styler, start, end, s, sizeof(s)); - //Platform::DebugPrintf("Scripting indicator [%s]\n", s); - if (strstr(s, "src")) // External script - return eScriptNone; - if (strstr(s, "vbs")) - return eScriptVBS; - if (strstr(s, "pyth")) - return eScriptPython; - if (strstr(s, "javas")) - return eScriptJS; - if (strstr(s, "jscr")) - return eScriptJS; - if (strstr(s, "php")) - return eScriptPHP; - if (strstr(s, "xml")) { - const char *xml = strstr(s, "xml"); - for (const char *t=s; t= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) { - return eScriptPython; - } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) { - return eScriptVBS; - } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) { - return eScriptJS; - } else if ((state >= SCE_HPHP_DEFAULT) && (state <= SCE_HPHP_COMMENTLINE)) { - return eScriptPHP; - } else if ((state >= SCE_H_SGML_DEFAULT) && (state < SCE_H_SGML_BLOCK_DEFAULT)) { - return eScriptSGML; - } else if (state == SCE_H_SGML_BLOCK_DEFAULT) { - return eScriptSGMLblock; - } else { - return eScriptNone; - } -} - -static int statePrintForState(int state, script_mode inScriptType) { - int StateToPrint = state; - - if (state >= SCE_HJ_START) { - if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) { - StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_PYTHON); - } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) { - StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_VBS); - } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) { - StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_JS); - } - } - - return StateToPrint; -} - -static int stateForPrintState(int StateToPrint) { - int state; - - if ((StateToPrint >= SCE_HPA_START) && (StateToPrint <= SCE_HPA_IDENTIFIER)) { - state = StateToPrint - SCE_HA_PYTHON; - } else if ((StateToPrint >= SCE_HBA_START) && (StateToPrint <= SCE_HBA_STRINGEOL)) { - state = StateToPrint - SCE_HA_VBS; - } else if ((StateToPrint >= SCE_HJA_START) && (StateToPrint <= SCE_HJA_REGEX)) { - state = StateToPrint - SCE_HA_JS; - } else { - state = StateToPrint; - } - - return state; -} - -static inline bool IsNumber(unsigned int start, Accessor &styler) { - return IsADigit(styler[start]) || (styler[start] == '.') || - (styler[start] == '-') || (styler[start] == '#'); -} - -static inline bool isStringState(int state) { - bool bResult; - - switch (state) { - case SCE_HJ_DOUBLESTRING: - case SCE_HJ_SINGLESTRING: - case SCE_HJA_DOUBLESTRING: - case SCE_HJA_SINGLESTRING: - case SCE_HB_STRING: - case SCE_HBA_STRING: - case SCE_HP_STRING: - case SCE_HP_CHARACTER: - case SCE_HP_TRIPLE: - case SCE_HP_TRIPLEDOUBLE: - case SCE_HPA_STRING: - case SCE_HPA_CHARACTER: - case SCE_HPA_TRIPLE: - case SCE_HPA_TRIPLEDOUBLE: - case SCE_HPHP_HSTRING: - case SCE_HPHP_SIMPLESTRING: - case SCE_HPHP_HSTRING_VARIABLE: - case SCE_HPHP_COMPLEX_VARIABLE: - bResult = true; - break; - default : - bResult = false; - break; - } - return bResult; -} - -static inline bool stateAllowsTermination(int state) { - bool allowTermination = !isStringState(state); - if (allowTermination) { - switch (state) { - case SCE_HB_COMMENTLINE: - case SCE_HPHP_COMMENT: - case SCE_HP_COMMENTLINE: - case SCE_HPA_COMMENTLINE: - allowTermination = false; - } - } - return allowTermination; -} - -// not really well done, since it's only comments that should lex the %> and <% -static inline bool isCommentASPState(int state) { - bool bResult; - - switch (state) { - case SCE_HJ_COMMENT: - case SCE_HJ_COMMENTLINE: - case SCE_HJ_COMMENTDOC: - case SCE_HB_COMMENTLINE: - case SCE_HP_COMMENTLINE: - case SCE_HPHP_COMMENT: - case SCE_HPHP_COMMENTLINE: - bResult = true; - break; - default : - bResult = false; - break; - } - return bResult; -} - -static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { - bool wordIsNumber = IsNumber(start, styler); - char chAttr = SCE_H_ATTRIBUTEUNKNOWN; - if (wordIsNumber) { - chAttr = SCE_H_NUMBER; - } else { - char s[100]; - GetTextSegment(styler, start, end, s, sizeof(s)); - if (keywords.InList(s)) - chAttr = SCE_H_ATTRIBUTE; - } - if ((chAttr == SCE_H_ATTRIBUTEUNKNOWN) && !keywords) - // No keywords -> all are known - chAttr = SCE_H_ATTRIBUTE; - styler.ColourTo(end, chAttr); -} - -static int classifyTagHTML(unsigned int start, unsigned int end, - WordList &keywords, Accessor &styler, bool &tagDontFold, - bool caseSensitive, bool isXml, bool allowScripts) { - char withSpace[30 + 2] = " "; - const char *s = withSpace + 1; - // Copy after the '<' - unsigned int i = 1; - for (unsigned int cPos = start; cPos <= end && i < 30; cPos++) { - char ch = styler[cPos]; - if ((ch != '<') && (ch != '/')) { - withSpace[i++] = caseSensitive ? ch : static_cast(MakeLowerCase(ch)); - } - } - - //The following is only a quick hack, to see if this whole thing would work - //we first need the tagname with a trailing space... - withSpace[i] = ' '; - withSpace[i+1] = '\0'; - - // if the current language is XML, I can fold any tag - // if the current language is HTML, I don't want to fold certain tags (input, meta, etc.) - //...to find it in the list of no-container-tags - tagDontFold = (!isXml) && (NULL != strstr(" area base basefont br col command embed frame hr img input isindex keygen link meta param source track wbr ", withSpace)); - - //now we can remove the trailing space - withSpace[i] = '\0'; - - // No keywords -> all are known - char chAttr = SCE_H_TAGUNKNOWN; - if (s[0] == '!') { - chAttr = SCE_H_SGML_DEFAULT; - } else if (!keywords || keywords.InList(s)) { - chAttr = SCE_H_TAG; - } - styler.ColourTo(end, chAttr); - if (chAttr == SCE_H_TAG) { - if (allowScripts && 0 == strcmp(s, "script")) { - // check to see if this is a self-closing tag by sniffing ahead - bool isSelfClose = false; - for (unsigned int cPos = end; cPos <= end + 100; cPos++) { - char ch = styler.SafeGetCharAt(cPos, '\0'); - if (ch == '\0' || ch == '>') - break; - else if (ch == '/' && styler.SafeGetCharAt(cPos + 1, '\0') == '>') { - isSelfClose = true; - break; - } - } - - // do not enter a script state if the tag self-closed - if (!isSelfClose) - chAttr = SCE_H_SCRIPT; - } else if (!isXml && 0 == strcmp(s, "comment")) { - chAttr = SCE_H_COMMENT; - } - } - return chAttr; -} - -static void classifyWordHTJS(unsigned int start, unsigned int end, - WordList &keywords, Accessor &styler, script_mode inScriptType) { - char s[30 + 1]; - unsigned int i = 0; - for (; i < end - start + 1 && i < 30; i++) { - s[i] = styler[start + i]; - } - s[i] = '\0'; - - char chAttr = SCE_HJ_WORD; - bool wordIsNumber = IsADigit(s[0]) || ((s[0] == '.') && IsADigit(s[1])); - if (wordIsNumber) { - chAttr = SCE_HJ_NUMBER; - } else if (keywords.InList(s)) { - chAttr = SCE_HJ_KEYWORD; - } - styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); -} - -static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, script_mode inScriptType) { - char chAttr = SCE_HB_IDENTIFIER; - bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.'); - if (wordIsNumber) - chAttr = SCE_HB_NUMBER; - else { - char s[100]; - GetTextSegment(styler, start, end, s, sizeof(s)); - if (keywords.InList(s)) { - chAttr = SCE_HB_WORD; - if (strcmp(s, "rem") == 0) - chAttr = SCE_HB_COMMENTLINE; - } - } - styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); - if (chAttr == SCE_HB_COMMENTLINE) - return SCE_HB_COMMENTLINE; - else - return SCE_HB_DEFAULT; -} - -static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord, script_mode inScriptType, bool isMako) { - bool wordIsNumber = IsADigit(styler[start]); - char s[30 + 1]; - unsigned int i = 0; - for (; i < end - start + 1 && i < 30; i++) { - s[i] = styler[start + i]; - } - s[i] = '\0'; - char chAttr = SCE_HP_IDENTIFIER; - if (0 == strcmp(prevWord, "class")) - chAttr = SCE_HP_CLASSNAME; - else if (0 == strcmp(prevWord, "def")) - chAttr = SCE_HP_DEFNAME; - else if (wordIsNumber) - chAttr = SCE_HP_NUMBER; - else if (keywords.InList(s)) - chAttr = SCE_HP_WORD; - else if (isMako && 0 == strcmp(s, "block")) - chAttr = SCE_HP_WORD; - styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); - strcpy(prevWord, s); -} - -// Update the word colour to default or keyword -// Called when in a PHP word -static void classifyWordHTPHP(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { - char chAttr = SCE_HPHP_DEFAULT; - bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.' && start+1 <= end && IsADigit(styler[start+1])); - if (wordIsNumber) - chAttr = SCE_HPHP_NUMBER; - else { - char s[100]; - GetTextSegment(styler, start, end, s, sizeof(s)); - if (keywords.InList(s)) - chAttr = SCE_HPHP_WORD; - } - styler.ColourTo(end, chAttr); -} - -static bool isWordHSGML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { - char s[30 + 1]; - unsigned int i = 0; - for (; i < end - start + 1 && i < 30; i++) { - s[i] = styler[start + i]; - } - s[i] = '\0'; - return keywords.InList(s); -} - -static bool isWordCdata(unsigned int start, unsigned int end, Accessor &styler) { - char s[30 + 1]; - unsigned int i = 0; - for (; i < end - start + 1 && i < 30; i++) { - s[i] = styler[start + i]; - } - s[i] = '\0'; - return (0 == strcmp(s, "[CDATA[")); -} - -// Return the first state to reach when entering a scripting language -static int StateForScript(script_type scriptLanguage) { - int Result; - switch (scriptLanguage) { - case eScriptVBS: - Result = SCE_HB_START; - break; - case eScriptPython: - Result = SCE_HP_START; - break; - case eScriptPHP: - Result = SCE_HPHP_DEFAULT; - break; - case eScriptXML: - Result = SCE_H_TAGUNKNOWN; - break; - case eScriptSGML: - Result = SCE_H_SGML_DEFAULT; - break; - case eScriptComment: - Result = SCE_H_COMMENT; - break; - default : - Result = SCE_HJ_START; - break; - } - return Result; -} - -static inline bool ishtmlwordchar(int ch) { - return !isascii(ch) || - (isalnum(ch) || ch == '.' || ch == '-' || ch == '_' || ch == ':' || ch == '!' || ch == '#'); -} - -static inline bool issgmlwordchar(int ch) { - return !isascii(ch) || - (isalnum(ch) || ch == '.' || ch == '_' || ch == ':' || ch == '!' || ch == '#' || ch == '['); -} - -static inline bool IsPhpWordStart(int ch) { - return (isascii(ch) && (isalpha(ch) || (ch == '_'))) || (ch >= 0x7f); -} - -static inline bool IsPhpWordChar(int ch) { - return IsADigit(ch) || IsPhpWordStart(ch); -} - -static bool InTagState(int state) { - return state == SCE_H_TAG || state == SCE_H_TAGUNKNOWN || - state == SCE_H_SCRIPT || - state == SCE_H_ATTRIBUTE || state == SCE_H_ATTRIBUTEUNKNOWN || - state == SCE_H_NUMBER || state == SCE_H_OTHER || - state == SCE_H_DOUBLESTRING || state == SCE_H_SINGLESTRING; -} - -static bool IsCommentState(const int state) { - return state == SCE_H_COMMENT || state == SCE_H_SGML_COMMENT; -} - -static bool IsScriptCommentState(const int state) { - return state == SCE_HJ_COMMENT || state == SCE_HJ_COMMENTLINE || state == SCE_HJA_COMMENT || - state == SCE_HJA_COMMENTLINE || state == SCE_HB_COMMENTLINE || state == SCE_HBA_COMMENTLINE; -} - -static bool isLineEnd(int ch) { - return ch == '\r' || ch == '\n'; -} - -static bool isOKBeforeRE(int ch) { - return (ch == '(') || (ch == '=') || (ch == ','); -} - -static bool isMakoBlockEnd(const int ch, const int chNext, const char *blockType) { - if (strlen(blockType) == 0) { - return ((ch == '%') && (chNext == '>')); - } else if ((0 == strcmp(blockType, "inherit")) || - (0 == strcmp(blockType, "namespace")) || - (0 == strcmp(blockType, "include")) || - (0 == strcmp(blockType, "page"))) { - return ((ch == '/') && (chNext == '>')); - } else if (0 == strcmp(blockType, "%")) { - if (ch == '/' && isLineEnd(chNext)) - return 1; - else - return isLineEnd(ch); - } else if (0 == strcmp(blockType, "{")) { - return ch == '}'; - } else { - return (ch == '>'); - } -} - -static bool isDjangoBlockEnd(const int ch, const int chNext, const char *blockType) { - if (strlen(blockType) == 0) { - return 0; - } else if (0 == strcmp(blockType, "%")) { - return ((ch == '%') && (chNext == '}')); - } else if (0 == strcmp(blockType, "{")) { - return ((ch == '}') && (chNext == '}')); - } else { - return 0; - } -} - -static bool isPHPStringState(int state) { - return - (state == SCE_HPHP_HSTRING) || - (state == SCE_HPHP_SIMPLESTRING) || - (state == SCE_HPHP_HSTRING_VARIABLE) || - (state == SCE_HPHP_COMPLEX_VARIABLE); -} - -static int FindPhpStringDelimiter(char *phpStringDelimiter, const int phpStringDelimiterSize, int i, const int lengthDoc, Accessor &styler, bool &isSimpleString) { - int j; - const int beginning = i - 1; - bool isValidSimpleString = false; - - while (i < lengthDoc && (styler[i] == ' ' || styler[i] == '\t')) - i++; - - char ch = styler.SafeGetCharAt(i); - const char chNext = styler.SafeGetCharAt(i + 1); - if (!IsPhpWordStart(ch)) { - if (ch == '\'' && IsPhpWordStart(chNext)) { - i++; - ch = chNext; - isSimpleString = true; - } else { - phpStringDelimiter[0] = '\0'; - return beginning; - } - } - phpStringDelimiter[0] = ch; - i++; - - for (j = i; j < lengthDoc && !isLineEnd(styler[j]); j++) { - if (!IsPhpWordChar(styler[j])) { - if (isSimpleString && (styler[j] == '\'') && isLineEnd(styler.SafeGetCharAt(j + 1))) { - isValidSimpleString = true; - j++; - break; - } else { - phpStringDelimiter[0] = '\0'; - return beginning; - } - } - if (j - i < phpStringDelimiterSize - 2) - phpStringDelimiter[j-i+1] = styler[j]; - else - i++; - } - if (isSimpleString && !isValidSimpleString) { - phpStringDelimiter[0] = '\0'; - return beginning; - } - phpStringDelimiter[j-i+1 - (isSimpleString ? 1 : 0)] = '\0'; - return j - 1; -} - -static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler, bool isXml) { - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - WordList &keywords6 = *keywordlists[5]; // SGML (DTD) keywords - - // Lexer for HTML requires more lexical states (8 bits worth) than most lexers - styler.StartAt(startPos, static_cast(STYLE_MAX)); - char prevWord[200]; - prevWord[0] = '\0'; - char phpStringDelimiter[200]; // PHP is not limited in length, we are - phpStringDelimiter[0] = '\0'; - int StateToPrint = initStyle; - int state = stateForPrintState(StateToPrint); - char makoBlockType[200]; - makoBlockType[0] = '\0'; - int makoComment = 0; - char djangoBlockType[2]; - djangoBlockType[0] = '\0'; - - // If inside a tag, it may be a script tag, so reread from the start to ensure any language tags are seen - if (InTagState(state)) { - while ((startPos > 0) && (InTagState(styler.StyleAt(startPos - 1)))) { - startPos--; - length++; - } - state = SCE_H_DEFAULT; - } - // String can be heredoc, must find a delimiter first. Reread from beginning of line containing the string, to get the correct lineState - if (isPHPStringState(state)) { - while (startPos > 0 && (isPHPStringState(state) || !isLineEnd(styler[startPos - 1]))) { - startPos--; - length++; - state = styler.StyleAt(startPos); - } - if (startPos == 0) - state = SCE_H_DEFAULT; - } - styler.StartAt(startPos, static_cast(STYLE_MAX)); - - int lineCurrent = styler.GetLine(startPos); - int lineState; - if (lineCurrent > 0) { - lineState = styler.GetLineState(lineCurrent-1); - } else { - // Default client and ASP scripting language is JavaScript - lineState = eScriptJS << 8; - - // property asp.default.language - // Script in ASP code is initially assumed to be in JavaScript. - // To change this to VBScript set asp.default.language to 2. Python is 3. - lineState |= styler.GetPropertyInt("asp.default.language", eScriptJS) << 4; - } - script_mode inScriptType = script_mode((lineState >> 0) & 0x03); // 2 bits of scripting mode - bool tagOpened = (lineState >> 2) & 0x01; // 1 bit to know if we are in an opened tag - bool tagClosing = (lineState >> 3) & 0x01; // 1 bit to know if we are in a closing tag - bool tagDontFold = false; //some HTML tags should not be folded - script_type aspScript = script_type((lineState >> 4) & 0x0F); // 4 bits of script name - script_type clientScript = script_type((lineState >> 8) & 0x0F); // 4 bits of script name - int beforePreProc = (lineState >> 12) & 0xFF; // 8 bits of state - - script_type scriptLanguage = ScriptOfState(state); - // If eNonHtmlScript coincides with SCE_H_COMMENT, assume eScriptComment - if (inScriptType == eNonHtmlScript && state == SCE_H_COMMENT) { - scriptLanguage = eScriptComment; - } - script_type beforeLanguage = ScriptOfState(beforePreProc); - - // property fold.html - // Folding is turned on or off for HTML and XML files with this option. - // The fold option must also be on for folding to occur. - const bool foldHTML = styler.GetPropertyInt("fold.html", 0) != 0; - - const bool fold = foldHTML && styler.GetPropertyInt("fold", 0); - - // property fold.html.preprocessor - // Folding is turned on or off for scripts embedded in HTML files with this option. - // The default is on. - const bool foldHTMLPreprocessor = foldHTML && styler.GetPropertyInt("fold.html.preprocessor", 1); - - const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - - // property fold.hypertext.comment - // Allow folding for comments in scripts embedded in HTML. - // The default is off. - const bool foldComment = fold && styler.GetPropertyInt("fold.hypertext.comment", 0) != 0; - - // property fold.hypertext.heredoc - // Allow folding for heredocs in scripts embedded in HTML. - // The default is off. - const bool foldHeredoc = fold && styler.GetPropertyInt("fold.hypertext.heredoc", 0) != 0; - - // property html.tags.case.sensitive - // For XML and HTML, setting this property to 1 will make tags match in a case - // sensitive way which is the expected behaviour for XML and XHTML. - const bool caseSensitive = styler.GetPropertyInt("html.tags.case.sensitive", 0) != 0; - - // property lexer.xml.allow.scripts - // Set to 0 to disable scripts in XML. - const bool allowScripts = styler.GetPropertyInt("lexer.xml.allow.scripts", 1) != 0; - - // property lexer.html.mako - // Set to 1 to enable the mako template language. - const bool isMako = styler.GetPropertyInt("lexer.html.mako", 0) != 0; - - // property lexer.html.django - // Set to 1 to enable the django template language. - const bool isDjango = styler.GetPropertyInt("lexer.html.django", 0) != 0; - - const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", 0x80, true); - const CharacterSet setTagContinue(CharacterSet::setAlphaNum, ".-_:!#[", 0x80, true); - const CharacterSet setAttributeContinue(CharacterSet::setAlphaNum, ".-_:!#/", 0x80, true); - - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - int visibleChars = 0; - int lineStartVisibleChars = 0; - - int chPrev = ' '; - int ch = ' '; - int chPrevNonWhite = ' '; - // look back to set chPrevNonWhite properly for better regex colouring - if (scriptLanguage == eScriptJS && startPos > 0) { - int back = startPos; - int style = 0; - while (--back) { - style = styler.StyleAt(back); - if (style < SCE_HJ_DEFAULT || style > SCE_HJ_COMMENTDOC) - // includes SCE_HJ_COMMENT & SCE_HJ_COMMENTLINE - break; - } - if (style == SCE_HJ_SYMBOLS) { - chPrevNonWhite = static_cast(styler.SafeGetCharAt(back)); - } - } - - styler.StartSegment(startPos); - const int lengthDoc = startPos + length; - for (int i = startPos; i < lengthDoc; i++) { - const int chPrev2 = chPrev; - chPrev = ch; - if (!IsASpace(ch) && state != SCE_HJ_COMMENT && - state != SCE_HJ_COMMENTLINE && state != SCE_HJ_COMMENTDOC) - chPrevNonWhite = ch; - ch = static_cast(styler[i]); - int chNext = static_cast(styler.SafeGetCharAt(i + 1)); - const int chNext2 = static_cast(styler.SafeGetCharAt(i + 2)); - - // Handle DBCS codepages - if (styler.IsLeadByte(static_cast(ch))) { - chPrev = ' '; - i += 1; - continue; - } - - if ((!IsASpace(ch) || !foldCompact) && fold) - visibleChars++; - if (!IsASpace(ch)) - lineStartVisibleChars++; - - // decide what is the current state to print (depending of the script tag) - StateToPrint = statePrintForState(state, inScriptType); - - // handle script folding - if (fold) { - switch (scriptLanguage) { - case eScriptJS: - case eScriptPHP: - //not currently supported case eScriptVBS: - - if ((state != SCE_HPHP_COMMENT) && (state != SCE_HPHP_COMMENTLINE) && (state != SCE_HJ_COMMENT) && (state != SCE_HJ_COMMENTLINE) && (state != SCE_HJ_COMMENTDOC) && (!isStringState(state))) { - //Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle); - //if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) { - if (ch == '#') { - int j = i + 1; - while ((j < lengthDoc) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { - j++; - } - if (styler.Match(j, "region") || styler.Match(j, "if")) { - levelCurrent++; - } else if (styler.Match(j, "end")) { - levelCurrent--; - } - } else if ((ch == '{') || (ch == '}') || (foldComment && (ch == '/') && (chNext == '*'))) { - levelCurrent += (((ch == '{') || (ch == '/')) ? 1 : -1); - } - } else if (((state == SCE_HPHP_COMMENT) || (state == SCE_HJ_COMMENT)) && foldComment && (ch == '*') && (chNext == '/')) { - levelCurrent--; - } - break; - case eScriptPython: - if (state != SCE_HP_COMMENTLINE && !isMako) { - if ((ch == ':') && ((chNext == '\n') || (chNext == '\r' && chNext2 == '\n'))) { - levelCurrent++; - } else if ((ch == '\n') && !((chNext == '\r') && (chNext2 == '\n')) && (chNext != '\n')) { - // check if the number of tabs is lower than the level - int Findlevel = (levelCurrent & ~SC_FOLDLEVELBASE) * 8; - for (int j = 0; Findlevel > 0; j++) { - char chTmp = styler.SafeGetCharAt(i + j + 1); - if (chTmp == '\t') { - Findlevel -= 8; - } else if (chTmp == ' ') { - Findlevel--; - } else { - break; - } - } - - if (Findlevel > 0) { - levelCurrent -= Findlevel / 8; - if (Findlevel % 8) - levelCurrent--; - } - } - } - break; - default: - break; - } - } - - if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { - // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) - // Avoid triggering two times on Dos/Win - // New line -> record any line state onto /next/ line - if (fold) { - int lev = levelPrev; - if (visibleChars == 0) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - - styler.SetLevel(lineCurrent, lev); - visibleChars = 0; - levelPrev = levelCurrent; - } - styler.SetLineState(lineCurrent, - ((inScriptType & 0x03) << 0) | - ((tagOpened & 0x01) << 2) | - ((tagClosing & 0x01) << 3) | - ((aspScript & 0x0F) << 4) | - ((clientScript & 0x0F) << 8) | - ((beforePreProc & 0xFF) << 12)); - lineCurrent++; - lineStartVisibleChars = 0; - } - - // handle start of Mako comment line - if (isMako && ch == '#' && chNext == '#') { - makoComment = 1; - } - - // handle end of Mako comment line - else if (isMako && makoComment && (ch == '\r' || ch == '\n')) { - makoComment = 0; - styler.ColourTo(i, SCE_HP_COMMENTLINE); - state = SCE_HP_DEFAULT; - } - - // Allow falling through to mako handling code if newline is going to end a block - if (((ch == '\r' && chNext != '\n') || (ch == '\n')) && - (!isMako || (0 != strcmp(makoBlockType, "%")))) { - } - - // generic end of script processing - else if ((inScriptType == eNonHtmlScript) && (ch == '<') && (chNext == '/')) { - // Check if it's the end of the script tag (or any other HTML tag) - switch (state) { - // in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!) - case SCE_H_DOUBLESTRING: - case SCE_H_SINGLESTRING: - case SCE_HJ_COMMENT: - case SCE_HJ_COMMENTDOC: - //case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide - // the end of script marker from some JS interpreters. - case SCE_HB_COMMENTLINE: - case SCE_HBA_COMMENTLINE: - case SCE_HJ_DOUBLESTRING: - case SCE_HJ_SINGLESTRING: - case SCE_HJ_REGEX: - case SCE_HB_STRING: - case SCE_HBA_STRING: - case SCE_HP_STRING: - case SCE_HP_TRIPLE: - case SCE_HP_TRIPLEDOUBLE: - case SCE_HPHP_HSTRING: - case SCE_HPHP_SIMPLESTRING: - case SCE_HPHP_COMMENT: - case SCE_HPHP_COMMENTLINE: - break; - default : - // check if the closing tag is a script tag - if (const char *tag = - state == SCE_HJ_COMMENTLINE || isXml ? "script" : - state == SCE_H_COMMENT ? "comment" : 0) { - int j = i + 2; - int chr; - do { - chr = static_cast(*tag++); - } while (chr != 0 && chr == MakeLowerCase(styler.SafeGetCharAt(j++))); - if (chr != 0) break; - } - // closing tag of the script (it's a closing HTML tag anyway) - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_TAGUNKNOWN; - inScriptType = eHtml; - scriptLanguage = eScriptNone; - clientScript = eScriptJS; - i += 2; - visibleChars += 2; - tagClosing = true; - continue; - } - } - - ///////////////////////////////////// - // handle the start of PHP pre-processor = Non-HTML - else if ((state != SCE_H_ASPAT) && - !isPHPStringState(state) && - (state != SCE_HPHP_COMMENT) && - (state != SCE_HPHP_COMMENTLINE) && - (ch == '<') && - (chNext == '?') && - !IsScriptCommentState(state)) { - beforeLanguage = scriptLanguage; - scriptLanguage = segIsScriptingIndicator(styler, i + 2, i + 6, eScriptPHP); - if (scriptLanguage != eScriptPHP && isStringState(state)) continue; - styler.ColourTo(i - 1, StateToPrint); - beforePreProc = state; - i++; - visibleChars++; - i += PrintScriptingIndicatorOffset(styler, styler.GetStartSegment() + 2, i + 6); - if (scriptLanguage == eScriptXML) - styler.ColourTo(i, SCE_H_XMLSTART); - else - styler.ColourTo(i, SCE_H_QUESTION); - state = StateForScript(scriptLanguage); - if (inScriptType == eNonHtmlScript) - inScriptType = eNonHtmlScriptPreProc; - else - inScriptType = eNonHtmlPreProc; - // Fold whole script, but not if the XML first tag (all XML-like tags in this case) - if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { - levelCurrent++; - } - // should be better - ch = static_cast(styler.SafeGetCharAt(i)); - continue; - } - - // handle the start Mako template Python code - else if (isMako && scriptLanguage == eScriptNone && ((ch == '<' && chNext == '%') || - (lineStartVisibleChars == 1 && ch == '%') || - (lineStartVisibleChars == 1 && ch == '/' && chNext == '%') || - (ch == '$' && chNext == '{') || - (ch == '<' && chNext == '/' && chNext2 == '%'))) { - if (ch == '%' || ch == '/') - strcpy(makoBlockType, "%"); - else if (ch == '$') - strcpy(makoBlockType, "{"); - else if (chNext == '/') - GetNextWord(styler, i+3, makoBlockType, sizeof(makoBlockType)); - else - GetNextWord(styler, i+2, makoBlockType, sizeof(makoBlockType)); - styler.ColourTo(i - 1, StateToPrint); - beforePreProc = state; - if (inScriptType == eNonHtmlScript) - inScriptType = eNonHtmlScriptPreProc; - else - inScriptType = eNonHtmlPreProc; - - if (chNext == '/') { - i += 2; - visibleChars += 2; - } else if (ch != '%') { - i++; - visibleChars++; - } - state = SCE_HP_START; - scriptLanguage = eScriptPython; - styler.ColourTo(i, SCE_H_ASP); - - if (ch != '%' && ch != '$' && ch != '/') { - i += static_cast(strlen(makoBlockType)); - visibleChars += static_cast(strlen(makoBlockType)); - if (keywords4.InList(makoBlockType)) - styler.ColourTo(i, SCE_HP_WORD); - else - styler.ColourTo(i, SCE_H_TAGUNKNOWN); - } - - ch = static_cast(styler.SafeGetCharAt(i)); - continue; - } - - // handle the start/end of Django comment - else if (isDjango && state != SCE_H_COMMENT && (ch == '{' && chNext == '#')) { - styler.ColourTo(i - 1, StateToPrint); - beforePreProc = state; - beforeLanguage = scriptLanguage; - if (inScriptType == eNonHtmlScript) - inScriptType = eNonHtmlScriptPreProc; - else - inScriptType = eNonHtmlPreProc; - i += 1; - visibleChars += 1; - scriptLanguage = eScriptComment; - state = SCE_H_COMMENT; - styler.ColourTo(i, SCE_H_ASP); - ch = static_cast(styler.SafeGetCharAt(i)); - continue; - } else if (isDjango && state == SCE_H_COMMENT && (ch == '#' && chNext == '}')) { - styler.ColourTo(i - 1, StateToPrint); - i += 1; - visibleChars += 1; - styler.ColourTo(i, SCE_H_ASP); - state = beforePreProc; - if (inScriptType == eNonHtmlScriptPreProc) - inScriptType = eNonHtmlScript; - else - inScriptType = eHtml; - scriptLanguage = beforeLanguage; - continue; - } - - // handle the start Django template code - else if (isDjango && scriptLanguage != eScriptPython && (ch == '{' && (chNext == '%' || chNext == '{'))) { - if (chNext == '%') - strcpy(djangoBlockType, "%"); - else - strcpy(djangoBlockType, "{"); - styler.ColourTo(i - 1, StateToPrint); - beforePreProc = state; - if (inScriptType == eNonHtmlScript) - inScriptType = eNonHtmlScriptPreProc; - else - inScriptType = eNonHtmlPreProc; - - i += 1; - visibleChars += 1; - state = SCE_HP_START; - beforeLanguage = scriptLanguage; - scriptLanguage = eScriptPython; - styler.ColourTo(i, SCE_H_ASP); - - ch = static_cast(styler.SafeGetCharAt(i)); - continue; - } - - // handle the start of ASP pre-processor = Non-HTML - else if (!isMako && !isDjango && !isCommentASPState(state) && (ch == '<') && (chNext == '%') && !isPHPStringState(state)) { - styler.ColourTo(i - 1, StateToPrint); - beforePreProc = state; - if (inScriptType == eNonHtmlScript) - inScriptType = eNonHtmlScriptPreProc; - else - inScriptType = eNonHtmlPreProc; - - if (chNext2 == '@') { - i += 2; // place as if it was the second next char treated - visibleChars += 2; - state = SCE_H_ASPAT; - } else if ((chNext2 == '-') && (styler.SafeGetCharAt(i + 3) == '-')) { - styler.ColourTo(i + 3, SCE_H_ASP); - state = SCE_H_XCCOMMENT; - scriptLanguage = eScriptVBS; - continue; - } else { - if (chNext2 == '=') { - i += 2; // place as if it was the second next char treated - visibleChars += 2; - } else { - i++; // place as if it was the next char treated - visibleChars++; - } - - state = StateForScript(aspScript); - } - scriptLanguage = eScriptVBS; - styler.ColourTo(i, SCE_H_ASP); - // fold whole script - if (foldHTMLPreprocessor) - levelCurrent++; - // should be better - ch = static_cast(styler.SafeGetCharAt(i)); - continue; - } - - ///////////////////////////////////// - // handle the start of SGML language (DTD) - else if (((scriptLanguage == eScriptNone) || (scriptLanguage == eScriptXML)) && - (chPrev == '<') && - (ch == '!') && - (StateToPrint != SCE_H_CDATA) && - (!IsCommentState(StateToPrint)) && - (!IsScriptCommentState(StateToPrint))) { - beforePreProc = state; - styler.ColourTo(i - 2, StateToPrint); - if ((chNext == '-') && (chNext2 == '-')) { - state = SCE_H_COMMENT; // wait for a pending command - styler.ColourTo(i + 2, SCE_H_COMMENT); - i += 2; // follow styling after the -- - } else if (isWordCdata(i + 1, i + 7, styler)) { - state = SCE_H_CDATA; - } else { - styler.ColourTo(i, SCE_H_SGML_DEFAULT); // ') { - i++; - visibleChars++; - } - else if (0 == strcmp(makoBlockType, "%") && ch == '/') { - i++; - visibleChars++; - } - if (0 != strcmp(makoBlockType, "%") || ch == '/') { - styler.ColourTo(i, SCE_H_ASP); - } - state = beforePreProc; - if (inScriptType == eNonHtmlScriptPreProc) - inScriptType = eNonHtmlScript; - else - inScriptType = eHtml; - scriptLanguage = eScriptNone; - continue; - } - - // handle the end of Django template code - else if (isDjango && - ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && - (scriptLanguage != eScriptNone) && stateAllowsTermination(state) && - isDjangoBlockEnd(ch, chNext, djangoBlockType)) { - if (state == SCE_H_ASPAT) { - aspScript = segIsScriptingIndicator(styler, - styler.GetStartSegment(), i - 1, aspScript); - } - if (state == SCE_HP_WORD) { - classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako); - } else { - styler.ColourTo(i - 1, StateToPrint); - } - i += 1; - visibleChars += 1; - styler.ColourTo(i, SCE_H_ASP); - state = beforePreProc; - if (inScriptType == eNonHtmlScriptPreProc) - inScriptType = eNonHtmlScript; - else - inScriptType = eHtml; - scriptLanguage = beforeLanguage; - continue; - } - - // handle the end of a pre-processor = Non-HTML - else if ((!isMako && !isDjango && ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && - (((scriptLanguage != eScriptNone) && stateAllowsTermination(state))) && - (((ch == '%') || (ch == '?')) && (chNext == '>'))) || - ((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) { - if (state == SCE_H_ASPAT) { - aspScript = segIsScriptingIndicator(styler, - styler.GetStartSegment(), i - 1, aspScript); - } - // Bounce out of any ASP mode - switch (state) { - case SCE_HJ_WORD: - classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType); - break; - case SCE_HB_WORD: - classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType); - break; - case SCE_HP_WORD: - classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako); - break; - case SCE_HPHP_WORD: - classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler); - break; - case SCE_H_XCCOMMENT: - styler.ColourTo(i - 1, state); - break; - default : - styler.ColourTo(i - 1, StateToPrint); - break; - } - if (scriptLanguage != eScriptSGML) { - i++; - visibleChars++; - } - if (ch == '%') - styler.ColourTo(i, SCE_H_ASP); - else if (scriptLanguage == eScriptXML) - styler.ColourTo(i, SCE_H_XMLEND); - else if (scriptLanguage == eScriptSGML) - styler.ColourTo(i, SCE_H_SGML_DEFAULT); - else - styler.ColourTo(i, SCE_H_QUESTION); - state = beforePreProc; - if (inScriptType == eNonHtmlScriptPreProc) - inScriptType = eNonHtmlScript; - else - inScriptType = eHtml; - // Unfold all scripting languages, except for XML tag - if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { - levelCurrent--; - } - scriptLanguage = beforeLanguage; - continue; - } - ///////////////////////////////////// - - switch (state) { - case SCE_H_DEFAULT: - if (ch == '<') { - // in HTML, fold on tag open and unfold on tag close - tagOpened = true; - tagClosing = (chNext == '/'); - styler.ColourTo(i - 1, StateToPrint); - if (chNext != '!') - state = SCE_H_TAGUNKNOWN; - } else if (ch == '&') { - styler.ColourTo(i - 1, SCE_H_DEFAULT); - state = SCE_H_ENTITY; - } - break; - case SCE_H_SGML_DEFAULT: - case SCE_H_SGML_BLOCK_DEFAULT: -// if (scriptLanguage == eScriptSGMLblock) -// StateToPrint = SCE_H_SGML_BLOCK_DEFAULT; - - if (ch == '\"') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_SGML_DOUBLESTRING; - } else if (ch == '\'') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_SGML_SIMPLESTRING; - } else if ((ch == '-') && (chPrev == '-')) { - if (static_cast(styler.GetStartSegment()) <= (i - 2)) { - styler.ColourTo(i - 2, StateToPrint); - } - state = SCE_H_SGML_COMMENT; - } else if (isascii(ch) && isalpha(ch) && (chPrev == '%')) { - styler.ColourTo(i - 2, StateToPrint); - state = SCE_H_SGML_ENTITY; - } else if (ch == '#') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_SGML_SPECIAL; - } else if (ch == '[') { - styler.ColourTo(i - 1, StateToPrint); - scriptLanguage = eScriptSGMLblock; - state = SCE_H_SGML_BLOCK_DEFAULT; - } else if (ch == ']') { - if (scriptLanguage == eScriptSGMLblock) { - styler.ColourTo(i, StateToPrint); - scriptLanguage = eScriptSGML; - } else { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i, SCE_H_SGML_ERROR); - } - state = SCE_H_SGML_DEFAULT; - } else if (scriptLanguage == eScriptSGMLblock) { - if ((ch == '!') && (chPrev == '<')) { - styler.ColourTo(i - 2, StateToPrint); - styler.ColourTo(i, SCE_H_SGML_DEFAULT); - state = SCE_H_SGML_COMMAND; - } else if (ch == '>') { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i, SCE_H_SGML_DEFAULT); - } - } - break; - case SCE_H_SGML_COMMAND: - if ((ch == '-') && (chPrev == '-')) { - styler.ColourTo(i - 2, StateToPrint); - state = SCE_H_SGML_COMMENT; - } else if (!issgmlwordchar(ch)) { - if (isWordHSGML(styler.GetStartSegment(), i - 1, keywords6, styler)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_SGML_1ST_PARAM; - } else { - state = SCE_H_SGML_ERROR; - } - } - break; - case SCE_H_SGML_1ST_PARAM: - // wait for the beginning of the word - if ((ch == '-') && (chPrev == '-')) { - if (scriptLanguage == eScriptSGMLblock) { - styler.ColourTo(i - 2, SCE_H_SGML_BLOCK_DEFAULT); - } else { - styler.ColourTo(i - 2, SCE_H_SGML_DEFAULT); - } - state = SCE_H_SGML_1ST_PARAM_COMMENT; - } else if (issgmlwordchar(ch)) { - if (scriptLanguage == eScriptSGMLblock) { - styler.ColourTo(i - 1, SCE_H_SGML_BLOCK_DEFAULT); - } else { - styler.ColourTo(i - 1, SCE_H_SGML_DEFAULT); - } - // find the length of the word - int size = 1; - while (setHTMLWord.Contains(static_cast(styler.SafeGetCharAt(i + size)))) - size++; - styler.ColourTo(i + size - 1, StateToPrint); - i += size - 1; - visibleChars += size - 1; - ch = static_cast(styler.SafeGetCharAt(i)); - if (scriptLanguage == eScriptSGMLblock) { - state = SCE_H_SGML_BLOCK_DEFAULT; - } else { - state = SCE_H_SGML_DEFAULT; - } - continue; - } - break; - case SCE_H_SGML_ERROR: - if ((ch == '-') && (chPrev == '-')) { - styler.ColourTo(i - 2, StateToPrint); - state = SCE_H_SGML_COMMENT; - } - case SCE_H_SGML_DOUBLESTRING: - if (ch == '\"') { - styler.ColourTo(i, StateToPrint); - state = SCE_H_SGML_DEFAULT; - } - break; - case SCE_H_SGML_SIMPLESTRING: - if (ch == '\'') { - styler.ColourTo(i, StateToPrint); - state = SCE_H_SGML_DEFAULT; - } - break; - case SCE_H_SGML_COMMENT: - if ((ch == '-') && (chPrev == '-')) { - styler.ColourTo(i, StateToPrint); - state = SCE_H_SGML_DEFAULT; - } - break; - case SCE_H_CDATA: - if ((chPrev2 == ']') && (chPrev == ']') && (ch == '>')) { - styler.ColourTo(i, StateToPrint); - state = SCE_H_DEFAULT; - levelCurrent--; - } - break; - case SCE_H_COMMENT: - if ((scriptLanguage != eScriptComment) && (chPrev2 == '-') && (chPrev == '-') && (ch == '>')) { - styler.ColourTo(i, StateToPrint); - state = SCE_H_DEFAULT; - levelCurrent--; - } - break; - case SCE_H_SGML_1ST_PARAM_COMMENT: - if ((ch == '-') && (chPrev == '-')) { - styler.ColourTo(i, SCE_H_SGML_COMMENT); - state = SCE_H_SGML_1ST_PARAM; - } - break; - case SCE_H_SGML_SPECIAL: - if (!(isascii(ch) && isupper(ch))) { - styler.ColourTo(i - 1, StateToPrint); - if (isalnum(ch)) { - state = SCE_H_SGML_ERROR; - } else { - state = SCE_H_SGML_DEFAULT; - } - } - break; - case SCE_H_SGML_ENTITY: - if (ch == ';') { - styler.ColourTo(i, StateToPrint); - state = SCE_H_SGML_DEFAULT; - } else if (!(isascii(ch) && isalnum(ch)) && ch != '-' && ch != '.') { - styler.ColourTo(i, SCE_H_SGML_ERROR); - state = SCE_H_SGML_DEFAULT; - } - break; - case SCE_H_ENTITY: - if (ch == ';') { - styler.ColourTo(i, StateToPrint); - state = SCE_H_DEFAULT; - } - if (ch != '#' && !(isascii(ch) && isalnum(ch)) // Should check that '#' follows '&', but it is unlikely anyway... - && ch != '.' && ch != '-' && ch != '_' && ch != ':') { // valid in XML - if (!isascii(ch)) // Possibly start of a multibyte character so don't allow this byte to be in entity style - styler.ColourTo(i-1, SCE_H_TAGUNKNOWN); - else - styler.ColourTo(i, SCE_H_TAGUNKNOWN); - state = SCE_H_DEFAULT; - } - break; - case SCE_H_TAGUNKNOWN: - if (!setTagContinue.Contains(ch) && !((ch == '/') && (chPrev == '<'))) { - int eClass = classifyTagHTML(styler.GetStartSegment(), - i - 1, keywords, styler, tagDontFold, caseSensitive, isXml, allowScripts); - if (eClass == SCE_H_SCRIPT || eClass == SCE_H_COMMENT) { - if (!tagClosing) { - inScriptType = eNonHtmlScript; - scriptLanguage = eClass == SCE_H_SCRIPT ? clientScript : eScriptComment; - } else { - scriptLanguage = eScriptNone; - } - eClass = SCE_H_TAG; - } - if (ch == '>') { - styler.ColourTo(i, eClass); - if (inScriptType == eNonHtmlScript) { - state = StateForScript(scriptLanguage); - } else { - state = SCE_H_DEFAULT; - } - tagOpened = false; - if (!tagDontFold) { - if (tagClosing) { - levelCurrent--; - } else { - levelCurrent++; - } - } - tagClosing = false; - } else if (ch == '/' && chNext == '>') { - if (eClass == SCE_H_TAGUNKNOWN) { - styler.ColourTo(i + 1, SCE_H_TAGUNKNOWN); - } else { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i + 1, SCE_H_TAGEND); - } - i++; - ch = chNext; - state = SCE_H_DEFAULT; - tagOpened = false; - } else { - if (eClass != SCE_H_TAGUNKNOWN) { - if (eClass == SCE_H_SGML_DEFAULT) { - state = SCE_H_SGML_DEFAULT; - } else { - state = SCE_H_OTHER; - } - } - } - } - break; - case SCE_H_ATTRIBUTE: - if (!setAttributeContinue.Contains(ch)) { - if (inScriptType == eNonHtmlScript) { - int scriptLanguagePrev = scriptLanguage; - clientScript = segIsScriptingIndicator(styler, styler.GetStartSegment(), i - 1, scriptLanguage); - scriptLanguage = clientScript; - if ((scriptLanguagePrev != scriptLanguage) && (scriptLanguage == eScriptNone)) - inScriptType = eHtml; - } - classifyAttribHTML(styler.GetStartSegment(), i - 1, keywords, styler); - if (ch == '>') { - styler.ColourTo(i, SCE_H_TAG); - if (inScriptType == eNonHtmlScript) { - state = StateForScript(scriptLanguage); - } else { - state = SCE_H_DEFAULT; - } - tagOpened = false; - if (!tagDontFold) { - if (tagClosing) { - levelCurrent--; - } else { - levelCurrent++; - } - } - tagClosing = false; - } else if (ch == '=') { - styler.ColourTo(i, SCE_H_OTHER); - state = SCE_H_VALUE; - } else { - state = SCE_H_OTHER; - } - } - break; - case SCE_H_OTHER: - if (ch == '>') { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i, SCE_H_TAG); - if (inScriptType == eNonHtmlScript) { - state = StateForScript(scriptLanguage); - } else { - state = SCE_H_DEFAULT; - } - tagOpened = false; - if (!tagDontFold) { - if (tagClosing) { - levelCurrent--; - } else { - levelCurrent++; - } - } - tagClosing = false; - } else if (ch == '\"') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_DOUBLESTRING; - } else if (ch == '\'') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_SINGLESTRING; - } else if (ch == '=') { - styler.ColourTo(i, StateToPrint); - state = SCE_H_VALUE; - } else if (ch == '/' && chNext == '>') { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i + 1, SCE_H_TAGEND); - i++; - ch = chNext; - state = SCE_H_DEFAULT; - tagOpened = false; - } else if (ch == '?' && chNext == '>') { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i + 1, SCE_H_XMLEND); - i++; - ch = chNext; - state = SCE_H_DEFAULT; - } else if (setHTMLWord.Contains(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_ATTRIBUTE; - } - break; - case SCE_H_DOUBLESTRING: - if (ch == '\"') { - if (inScriptType == eNonHtmlScript) { - scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage); - } - styler.ColourTo(i, SCE_H_DOUBLESTRING); - state = SCE_H_OTHER; - } - break; - case SCE_H_SINGLESTRING: - if (ch == '\'') { - if (inScriptType == eNonHtmlScript) { - scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage); - } - styler.ColourTo(i, SCE_H_SINGLESTRING); - state = SCE_H_OTHER; - } - break; - case SCE_H_VALUE: - if (!setHTMLWord.Contains(ch)) { - if (ch == '\"' && chPrev == '=') { - // Should really test for being first character - state = SCE_H_DOUBLESTRING; - } else if (ch == '\'' && chPrev == '=') { - state = SCE_H_SINGLESTRING; - } else { - if (IsNumber(styler.GetStartSegment(), styler)) { - styler.ColourTo(i - 1, SCE_H_NUMBER); - } else { - styler.ColourTo(i - 1, StateToPrint); - } - if (ch == '>') { - styler.ColourTo(i, SCE_H_TAG); - if (inScriptType == eNonHtmlScript) { - state = StateForScript(scriptLanguage); - } else { - state = SCE_H_DEFAULT; - } - tagOpened = false; - if (!tagDontFold) { - if (tagClosing) { - levelCurrent--; - } else { - levelCurrent++; - } - } - tagClosing = false; - } else { - state = SCE_H_OTHER; - } - } - } - break; - case SCE_HJ_DEFAULT: - case SCE_HJ_START: - case SCE_HJ_SYMBOLS: - if (IsAWordStart(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_WORD; - } else if (ch == '/' && chNext == '*') { - styler.ColourTo(i - 1, StateToPrint); - if (chNext2 == '*') - state = SCE_HJ_COMMENTDOC; - else - state = SCE_HJ_COMMENT; - } else if (ch == '/' && chNext == '/') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_COMMENTLINE; - } else if (ch == '/' && isOKBeforeRE(chPrevNonWhite)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_REGEX; - } else if (ch == '\"') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_DOUBLESTRING; - } else if (ch == '\'') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_SINGLESTRING; - } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && - styler.SafeGetCharAt(i + 3) == '-') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_COMMENTLINE; - } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_COMMENTLINE; - i += 2; - } else if (IsOperator(ch)) { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); - state = SCE_HJ_DEFAULT; - } else if ((ch == ' ') || (ch == '\t')) { - if (state == SCE_HJ_START) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_DEFAULT; - } - } - break; - case SCE_HJ_WORD: - if (!IsAWordChar(ch)) { - classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType); - //styler.ColourTo(i - 1, eHTJSKeyword); - state = SCE_HJ_DEFAULT; - if (ch == '/' && chNext == '*') { - if (chNext2 == '*') - state = SCE_HJ_COMMENTDOC; - else - state = SCE_HJ_COMMENT; - } else if (ch == '/' && chNext == '/') { - state = SCE_HJ_COMMENTLINE; - } else if (ch == '\"') { - state = SCE_HJ_DOUBLESTRING; - } else if (ch == '\'') { - state = SCE_HJ_SINGLESTRING; - } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_COMMENTLINE; - i += 2; - } else if (IsOperator(ch)) { - styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); - state = SCE_HJ_DEFAULT; - } - } - break; - case SCE_HJ_COMMENT: - case SCE_HJ_COMMENTDOC: - if (ch == '/' && chPrev == '*') { - styler.ColourTo(i, StateToPrint); - state = SCE_HJ_DEFAULT; - ch = ' '; - } - break; - case SCE_HJ_COMMENTLINE: - if (ch == '\r' || ch == '\n') { - styler.ColourTo(i - 1, statePrintForState(SCE_HJ_COMMENTLINE, inScriptType)); - state = SCE_HJ_DEFAULT; - ch = ' '; - } - break; - case SCE_HJ_DOUBLESTRING: - if (ch == '\\') { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') { - i++; - } - } else if (ch == '\"') { - styler.ColourTo(i, statePrintForState(SCE_HJ_DOUBLESTRING, inScriptType)); - state = SCE_HJ_DEFAULT; - } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_COMMENTLINE; - i += 2; - } else if (isLineEnd(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_STRINGEOL; - } - break; - case SCE_HJ_SINGLESTRING: - if (ch == '\\') { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') { - i++; - } - } else if (ch == '\'') { - styler.ColourTo(i, statePrintForState(SCE_HJ_SINGLESTRING, inScriptType)); - state = SCE_HJ_DEFAULT; - } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_COMMENTLINE; - i += 2; - } else if (isLineEnd(ch)) { - styler.ColourTo(i - 1, StateToPrint); - if (chPrev != '\\' && (chPrev2 != '\\' || chPrev != '\r' || ch != '\n')) { - state = SCE_HJ_STRINGEOL; - } - } - break; - case SCE_HJ_STRINGEOL: - if (!isLineEnd(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_DEFAULT; - } else if (!isLineEnd(chNext)) { - styler.ColourTo(i, StateToPrint); - state = SCE_HJ_DEFAULT; - } - break; - case SCE_HJ_REGEX: - if (ch == '\r' || ch == '\n' || ch == '/') { - if (ch == '/') { - while (isascii(chNext) && islower(chNext)) { // gobble regex flags - i++; - ch = chNext; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } - } - styler.ColourTo(i, StateToPrint); - state = SCE_HJ_DEFAULT; - } else if (ch == '\\') { - // Gobble up the quoted character - if (chNext == '\\' || chNext == '/') { - i++; - ch = chNext; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } - } - break; - case SCE_HB_DEFAULT: - case SCE_HB_START: - if (IsAWordStart(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_WORD; - } else if (ch == '\'') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_COMMENTLINE; - } else if (ch == '\"') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_STRING; - } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && - styler.SafeGetCharAt(i + 3) == '-') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_COMMENTLINE; - } else if (IsOperator(ch)) { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType)); - state = SCE_HB_DEFAULT; - } else if ((ch == ' ') || (ch == '\t')) { - if (state == SCE_HB_START) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_DEFAULT; - } - } - break; - case SCE_HB_WORD: - if (!IsAWordChar(ch)) { - state = classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType); - if (state == SCE_HB_DEFAULT) { - if (ch == '\"') { - state = SCE_HB_STRING; - } else if (ch == '\'') { - state = SCE_HB_COMMENTLINE; - } else if (IsOperator(ch)) { - styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType)); - state = SCE_HB_DEFAULT; - } - } - } - break; - case SCE_HB_STRING: - if (ch == '\"') { - styler.ColourTo(i, StateToPrint); - state = SCE_HB_DEFAULT; - } else if (ch == '\r' || ch == '\n') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_STRINGEOL; - } - break; - case SCE_HB_COMMENTLINE: - if (ch == '\r' || ch == '\n') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_DEFAULT; - } - break; - case SCE_HB_STRINGEOL: - if (!isLineEnd(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_DEFAULT; - } else if (!isLineEnd(chNext)) { - styler.ColourTo(i, StateToPrint); - state = SCE_HB_DEFAULT; - } - break; - case SCE_HP_DEFAULT: - case SCE_HP_START: - if (IsAWordStart(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HP_WORD; - } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && - styler.SafeGetCharAt(i + 3) == '-') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HP_COMMENTLINE; - } else if (ch == '#') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HP_COMMENTLINE; - } else if (ch == '\"') { - styler.ColourTo(i - 1, StateToPrint); - if (chNext == '\"' && chNext2 == '\"') { - i += 2; - state = SCE_HP_TRIPLEDOUBLE; - ch = ' '; - chPrev = ' '; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } else { - // state = statePrintForState(SCE_HP_STRING,inScriptType); - state = SCE_HP_STRING; - } - } else if (ch == '\'') { - styler.ColourTo(i - 1, StateToPrint); - if (chNext == '\'' && chNext2 == '\'') { - i += 2; - state = SCE_HP_TRIPLE; - ch = ' '; - chPrev = ' '; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } else { - state = SCE_HP_CHARACTER; - } - } else if (IsOperator(ch)) { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType)); - } else if ((ch == ' ') || (ch == '\t')) { - if (state == SCE_HP_START) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HP_DEFAULT; - } - } - break; - case SCE_HP_WORD: - if (!IsAWordChar(ch)) { - classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako); - state = SCE_HP_DEFAULT; - if (ch == '#') { - state = SCE_HP_COMMENTLINE; - } else if (ch == '\"') { - if (chNext == '\"' && chNext2 == '\"') { - i += 2; - state = SCE_HP_TRIPLEDOUBLE; - ch = ' '; - chPrev = ' '; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } else { - state = SCE_HP_STRING; - } - } else if (ch == '\'') { - if (chNext == '\'' && chNext2 == '\'') { - i += 2; - state = SCE_HP_TRIPLE; - ch = ' '; - chPrev = ' '; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } else { - state = SCE_HP_CHARACTER; - } - } else if (IsOperator(ch)) { - styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType)); - } - } - break; - case SCE_HP_COMMENTLINE: - if (ch == '\r' || ch == '\n') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HP_DEFAULT; - } - break; - case SCE_HP_STRING: - if (ch == '\\') { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') { - i++; - ch = chNext; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } - } else if (ch == '\"') { - styler.ColourTo(i, StateToPrint); - state = SCE_HP_DEFAULT; - } - break; - case SCE_HP_CHARACTER: - if (ch == '\\') { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') { - i++; - ch = chNext; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } - } else if (ch == '\'') { - styler.ColourTo(i, StateToPrint); - state = SCE_HP_DEFAULT; - } - break; - case SCE_HP_TRIPLE: - if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') { - styler.ColourTo(i, StateToPrint); - state = SCE_HP_DEFAULT; - } - break; - case SCE_HP_TRIPLEDOUBLE: - if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') { - styler.ColourTo(i, StateToPrint); - state = SCE_HP_DEFAULT; - } - break; - ///////////// start - PHP state handling - case SCE_HPHP_WORD: - if (!IsAWordChar(ch)) { - classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler); - if (ch == '/' && chNext == '*') { - i++; - state = SCE_HPHP_COMMENT; - } else if (ch == '/' && chNext == '/') { - i++; - state = SCE_HPHP_COMMENTLINE; - } else if (ch == '#') { - state = SCE_HPHP_COMMENTLINE; - } else if (ch == '\"') { - state = SCE_HPHP_HSTRING; - strcpy(phpStringDelimiter, "\""); - } else if (styler.Match(i, "<<<")) { - bool isSimpleString = false; - i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString); - if (strlen(phpStringDelimiter)) { - state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING); - if (foldHeredoc) levelCurrent++; - } - } else if (ch == '\'') { - state = SCE_HPHP_SIMPLESTRING; - strcpy(phpStringDelimiter, "\'"); - } else if (ch == '$' && IsPhpWordStart(chNext)) { - state = SCE_HPHP_VARIABLE; - } else if (IsOperator(ch)) { - state = SCE_HPHP_OPERATOR; - } else { - state = SCE_HPHP_DEFAULT; - } - } - break; - case SCE_HPHP_NUMBER: - // recognize bases 8,10 or 16 integers OR floating-point numbers - if (!IsADigit(ch) - && strchr(".xXabcdefABCDEF", ch) == NULL - && ((ch != '-' && ch != '+') || (chPrev != 'e' && chPrev != 'E'))) { - styler.ColourTo(i - 1, SCE_HPHP_NUMBER); - if (IsOperator(ch)) - state = SCE_HPHP_OPERATOR; - else - state = SCE_HPHP_DEFAULT; - } - break; - case SCE_HPHP_VARIABLE: - if (!IsPhpWordChar(chNext)) { - styler.ColourTo(i, SCE_HPHP_VARIABLE); - state = SCE_HPHP_DEFAULT; - } - break; - case SCE_HPHP_COMMENT: - if (ch == '/' && chPrev == '*') { - styler.ColourTo(i, StateToPrint); - state = SCE_HPHP_DEFAULT; - } - break; - case SCE_HPHP_COMMENTLINE: - if (ch == '\r' || ch == '\n') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HPHP_DEFAULT; - } - break; - case SCE_HPHP_HSTRING: - if (ch == '\\' && (phpStringDelimiter[0] == '\"' || chNext == '$' || chNext == '{')) { - // skip the next char - i++; - } else if (((ch == '{' && chNext == '$') || (ch == '$' && chNext == '{')) - && IsPhpWordStart(chNext2)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HPHP_COMPLEX_VARIABLE; - } else if (ch == '$' && IsPhpWordStart(chNext)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HPHP_HSTRING_VARIABLE; - } else if (styler.Match(i, phpStringDelimiter)) { - if (phpStringDelimiter[0] == '\"') { - styler.ColourTo(i, StateToPrint); - state = SCE_HPHP_DEFAULT; - } else if (isLineEnd(chPrev)) { - const int psdLength = static_cast(strlen(phpStringDelimiter)); - const char chAfterPsd = styler.SafeGetCharAt(i + psdLength); - const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1); - if (isLineEnd(chAfterPsd) || - (chAfterPsd == ';' && isLineEnd(chAfterPsd2))) { - i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1; - styler.ColourTo(i, StateToPrint); - state = SCE_HPHP_DEFAULT; - if (foldHeredoc) levelCurrent--; - } - } - } - break; - case SCE_HPHP_SIMPLESTRING: - if (phpStringDelimiter[0] == '\'') { - if (ch == '\\') { - // skip the next char - i++; - } else if (ch == '\'') { - styler.ColourTo(i, StateToPrint); - state = SCE_HPHP_DEFAULT; - } - } else if (isLineEnd(chPrev) && styler.Match(i, phpStringDelimiter)) { - const int psdLength = static_cast(strlen(phpStringDelimiter)); - const char chAfterPsd = styler.SafeGetCharAt(i + psdLength); - const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1); - if (isLineEnd(chAfterPsd) || - (chAfterPsd == ';' && isLineEnd(chAfterPsd2))) { - i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1; - styler.ColourTo(i, StateToPrint); - state = SCE_HPHP_DEFAULT; - if (foldHeredoc) levelCurrent--; - } - } - break; - case SCE_HPHP_HSTRING_VARIABLE: - if (!IsPhpWordChar(chNext)) { - styler.ColourTo(i, StateToPrint); - state = SCE_HPHP_HSTRING; - } - break; - case SCE_HPHP_COMPLEX_VARIABLE: - if (ch == '}') { - styler.ColourTo(i, StateToPrint); - state = SCE_HPHP_HSTRING; - } - break; - case SCE_HPHP_OPERATOR: - case SCE_HPHP_DEFAULT: - styler.ColourTo(i - 1, StateToPrint); - if (IsADigit(ch) || (ch == '.' && IsADigit(chNext))) { - state = SCE_HPHP_NUMBER; - } else if (IsAWordStart(ch)) { - state = SCE_HPHP_WORD; - } else if (ch == '/' && chNext == '*') { - i++; - state = SCE_HPHP_COMMENT; - } else if (ch == '/' && chNext == '/') { - i++; - state = SCE_HPHP_COMMENTLINE; - } else if (ch == '#') { - state = SCE_HPHP_COMMENTLINE; - } else if (ch == '\"') { - state = SCE_HPHP_HSTRING; - strcpy(phpStringDelimiter, "\""); - } else if (styler.Match(i, "<<<")) { - bool isSimpleString = false; - i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString); - if (strlen(phpStringDelimiter)) { - state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING); - if (foldHeredoc) levelCurrent++; - } - } else if (ch == '\'') { - state = SCE_HPHP_SIMPLESTRING; - strcpy(phpStringDelimiter, "\'"); - } else if (ch == '$' && IsPhpWordStart(chNext)) { - state = SCE_HPHP_VARIABLE; - } else if (IsOperator(ch)) { - state = SCE_HPHP_OPERATOR; - } else if ((state == SCE_HPHP_OPERATOR) && (IsASpace(ch))) { - state = SCE_HPHP_DEFAULT; - } - break; - ///////////// end - PHP state handling - } - - // Some of the above terminated their lexeme but since the same character starts - // the same class again, only reenter if non empty segment. - - bool nonEmptySegment = i >= static_cast(styler.GetStartSegment()); - if (state == SCE_HB_DEFAULT) { // One of the above succeeded - if ((ch == '\"') && (nonEmptySegment)) { - state = SCE_HB_STRING; - } else if (ch == '\'') { - state = SCE_HB_COMMENTLINE; - } else if (IsAWordStart(ch)) { - state = SCE_HB_WORD; - } else if (IsOperator(ch)) { - styler.ColourTo(i, SCE_HB_DEFAULT); - } - } else if (state == SCE_HBA_DEFAULT) { // One of the above succeeded - if ((ch == '\"') && (nonEmptySegment)) { - state = SCE_HBA_STRING; - } else if (ch == '\'') { - state = SCE_HBA_COMMENTLINE; - } else if (IsAWordStart(ch)) { - state = SCE_HBA_WORD; - } else if (IsOperator(ch)) { - styler.ColourTo(i, SCE_HBA_DEFAULT); - } - } else if (state == SCE_HJ_DEFAULT) { // One of the above succeeded - if (ch == '/' && chNext == '*') { - if (styler.SafeGetCharAt(i + 2) == '*') - state = SCE_HJ_COMMENTDOC; - else - state = SCE_HJ_COMMENT; - } else if (ch == '/' && chNext == '/') { - state = SCE_HJ_COMMENTLINE; - } else if ((ch == '\"') && (nonEmptySegment)) { - state = SCE_HJ_DOUBLESTRING; - } else if ((ch == '\'') && (nonEmptySegment)) { - state = SCE_HJ_SINGLESTRING; - } else if (IsAWordStart(ch)) { - state = SCE_HJ_WORD; - } else if (IsOperator(ch)) { - styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); - } - } - } - - switch (state) { - case SCE_HJ_WORD: - classifyWordHTJS(styler.GetStartSegment(), lengthDoc - 1, keywords2, styler, inScriptType); - break; - case SCE_HB_WORD: - classifyWordHTVB(styler.GetStartSegment(), lengthDoc - 1, keywords3, styler, inScriptType); - break; - case SCE_HP_WORD: - classifyWordHTPy(styler.GetStartSegment(), lengthDoc - 1, keywords4, styler, prevWord, inScriptType, isMako); - break; - case SCE_HPHP_WORD: - classifyWordHTPHP(styler.GetStartSegment(), lengthDoc - 1, keywords5, styler); - break; - default: - StateToPrint = statePrintForState(state, inScriptType); - styler.ColourTo(lengthDoc - 1, StateToPrint); - break; - } - - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - if (fold) { - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); - } -} - -static void ColouriseXMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - // Passing in true because we're lexing XML - ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, true); -} - -static void ColouriseHTMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - // Passing in false because we're notlexing XML - ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, false); -} - -static void ColourisePHPScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - if (startPos == 0) - initStyle = SCE_HPHP_DEFAULT; - ColouriseHTMLDoc(startPos, length, initStyle, keywordlists, styler); -} - -static const char * const htmlWordListDesc[] = { - "HTML elements and attributes", - "JavaScript keywords", - "VBScript keywords", - "Python keywords", - "PHP keywords", - "SGML and DTD keywords", - 0, -}; - -static const char * const phpscriptWordListDesc[] = { - "", //Unused - "", //Unused - "", //Unused - "", //Unused - "PHP keywords", - "", //Unused - 0, -}; - -LexerModule lmHTML(SCLEX_HTML, ColouriseHTMLDoc, "hypertext", 0, htmlWordListDesc, 8); -LexerModule lmXML(SCLEX_XML, ColouriseXMLDoc, "xml", 0, htmlWordListDesc, 8); -LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc, 8); +// Scintilla source code edit control +/** @file LexHTML.cxx + ** Lexer for HTML. + **/ +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#define SCE_HA_JS (SCE_HJA_START - SCE_HJ_START) +#define SCE_HA_VBS (SCE_HBA_START - SCE_HB_START) +#define SCE_HA_PYTHON (SCE_HPA_START - SCE_HP_START) + +enum script_type { eScriptNone = 0, eScriptJS, eScriptVBS, eScriptPython, eScriptPHP, eScriptXML, eScriptSGML, eScriptSGMLblock, eScriptComment }; +enum script_mode { eHtml = 0, eNonHtmlScript, eNonHtmlPreProc, eNonHtmlScriptPreProc }; + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +inline bool IsOperator(int ch) { + if (isascii(ch) && isalnum(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || + ch == '(' || ch == ')' || ch == '-' || ch == '+' || + ch == '=' || ch == '|' || ch == '{' || ch == '}' || + ch == '[' || ch == ']' || ch == ':' || ch == ';' || + ch == '<' || ch == '>' || ch == ',' || ch == '/' || + ch == '?' || ch == '!' || ch == '.' || ch == '~') + return true; + return false; +} + +static void GetTextSegment(Accessor &styler, unsigned int start, unsigned int end, char *s, size_t len) { + unsigned int i = 0; + for (; (i < end - start + 1) && (i < len-1); i++) { + s[i] = static_cast(MakeLowerCase(styler[start + i])); + } + s[i] = '\0'; +} + +static const char *GetNextWord(Accessor &styler, unsigned int start, char *s, size_t sLen) { + + unsigned int i = 0; + for (; i < sLen-1; i++) { + char ch = static_cast(styler.SafeGetCharAt(start + i)); + if ((i == 0) && !IsAWordStart(ch)) + break; + if ((i > 0) && !IsAWordChar(ch)) + break; + s[i] = ch; + } + s[i] = '\0'; + + return s; +} + +static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, script_type prevValue) { + char s[100]; + GetTextSegment(styler, start, end, s, sizeof(s)); + //Platform::DebugPrintf("Scripting indicator [%s]\n", s); + if (strstr(s, "src")) // External script + return eScriptNone; + if (strstr(s, "vbs")) + return eScriptVBS; + if (strstr(s, "pyth")) + return eScriptPython; + if (strstr(s, "javas")) + return eScriptJS; + if (strstr(s, "jscr")) + return eScriptJS; + if (strstr(s, "php")) + return eScriptPHP; + if (strstr(s, "xml")) { + const char *xml = strstr(s, "xml"); + for (const char *t=s; t= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) { + return eScriptPython; + } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) { + return eScriptVBS; + } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) { + return eScriptJS; + } else if ((state >= SCE_HPHP_DEFAULT) && (state <= SCE_HPHP_COMMENTLINE)) { + return eScriptPHP; + } else if ((state >= SCE_H_SGML_DEFAULT) && (state < SCE_H_SGML_BLOCK_DEFAULT)) { + return eScriptSGML; + } else if (state == SCE_H_SGML_BLOCK_DEFAULT) { + return eScriptSGMLblock; + } else { + return eScriptNone; + } +} + +static int statePrintForState(int state, script_mode inScriptType) { + int StateToPrint = state; + + if (state >= SCE_HJ_START) { + if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) { + StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_PYTHON); + } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) { + StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_VBS); + } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) { + StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_JS); + } + } + + return StateToPrint; +} + +static int stateForPrintState(int StateToPrint) { + int state; + + if ((StateToPrint >= SCE_HPA_START) && (StateToPrint <= SCE_HPA_IDENTIFIER)) { + state = StateToPrint - SCE_HA_PYTHON; + } else if ((StateToPrint >= SCE_HBA_START) && (StateToPrint <= SCE_HBA_STRINGEOL)) { + state = StateToPrint - SCE_HA_VBS; + } else if ((StateToPrint >= SCE_HJA_START) && (StateToPrint <= SCE_HJA_REGEX)) { + state = StateToPrint - SCE_HA_JS; + } else { + state = StateToPrint; + } + + return state; +} + +static inline bool IsNumber(unsigned int start, Accessor &styler) { + return IsADigit(styler[start]) || (styler[start] == '.') || + (styler[start] == '-') || (styler[start] == '#'); +} + +static inline bool isStringState(int state) { + bool bResult; + + switch (state) { + case SCE_HJ_DOUBLESTRING: + case SCE_HJ_SINGLESTRING: + case SCE_HJA_DOUBLESTRING: + case SCE_HJA_SINGLESTRING: + case SCE_HB_STRING: + case SCE_HBA_STRING: + case SCE_HP_STRING: + case SCE_HP_CHARACTER: + case SCE_HP_TRIPLE: + case SCE_HP_TRIPLEDOUBLE: + case SCE_HPA_STRING: + case SCE_HPA_CHARACTER: + case SCE_HPA_TRIPLE: + case SCE_HPA_TRIPLEDOUBLE: + case SCE_HPHP_HSTRING: + case SCE_HPHP_SIMPLESTRING: + case SCE_HPHP_HSTRING_VARIABLE: + case SCE_HPHP_COMPLEX_VARIABLE: + bResult = true; + break; + default : + bResult = false; + break; + } + return bResult; +} + +static inline bool stateAllowsTermination(int state) { + bool allowTermination = !isStringState(state); + if (allowTermination) { + switch (state) { + case SCE_HB_COMMENTLINE: + case SCE_HPHP_COMMENT: + case SCE_HP_COMMENTLINE: + case SCE_HPA_COMMENTLINE: + allowTermination = false; + } + } + return allowTermination; +} + +// not really well done, since it's only comments that should lex the %> and <% +static inline bool isCommentASPState(int state) { + bool bResult; + + switch (state) { + case SCE_HJ_COMMENT: + case SCE_HJ_COMMENTLINE: + case SCE_HJ_COMMENTDOC: + case SCE_HB_COMMENTLINE: + case SCE_HP_COMMENTLINE: + case SCE_HPHP_COMMENT: + case SCE_HPHP_COMMENTLINE: + bResult = true; + break; + default : + bResult = false; + break; + } + return bResult; +} + +static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { + bool wordIsNumber = IsNumber(start, styler); + char chAttr = SCE_H_ATTRIBUTEUNKNOWN; + if (wordIsNumber) { + chAttr = SCE_H_NUMBER; + } else { + char s[100]; + GetTextSegment(styler, start, end, s, sizeof(s)); + if (keywords.InList(s)) + chAttr = SCE_H_ATTRIBUTE; + } + if ((chAttr == SCE_H_ATTRIBUTEUNKNOWN) && !keywords) + // No keywords -> all are known + chAttr = SCE_H_ATTRIBUTE; + styler.ColourTo(end, chAttr); +} + +static int classifyTagHTML(unsigned int start, unsigned int end, + WordList &keywords, Accessor &styler, bool &tagDontFold, + bool caseSensitive, bool isXml, bool allowScripts) { + char withSpace[30 + 2] = " "; + const char *s = withSpace + 1; + // Copy after the '<' + unsigned int i = 1; + for (unsigned int cPos = start; cPos <= end && i < 30; cPos++) { + char ch = styler[cPos]; + if ((ch != '<') && (ch != '/')) { + withSpace[i++] = caseSensitive ? ch : static_cast(MakeLowerCase(ch)); + } + } + + //The following is only a quick hack, to see if this whole thing would work + //we first need the tagname with a trailing space... + withSpace[i] = ' '; + withSpace[i+1] = '\0'; + + // if the current language is XML, I can fold any tag + // if the current language is HTML, I don't want to fold certain tags (input, meta, etc.) + //...to find it in the list of no-container-tags + tagDontFold = (!isXml) && (NULL != strstr(" area base basefont br col command embed frame hr img input isindex keygen link meta param source track wbr ", withSpace)); + + //now we can remove the trailing space + withSpace[i] = '\0'; + + // No keywords -> all are known + char chAttr = SCE_H_TAGUNKNOWN; + if (s[0] == '!') { + chAttr = SCE_H_SGML_DEFAULT; + } else if (!keywords || keywords.InList(s)) { + chAttr = SCE_H_TAG; + } + styler.ColourTo(end, chAttr); + if (chAttr == SCE_H_TAG) { + if (allowScripts && 0 == strcmp(s, "script")) { + // check to see if this is a self-closing tag by sniffing ahead + bool isSelfClose = false; + for (unsigned int cPos = end; cPos <= end + 100; cPos++) { + char ch = styler.SafeGetCharAt(cPos, '\0'); + if (ch == '\0' || ch == '>') + break; + else if (ch == '/' && styler.SafeGetCharAt(cPos + 1, '\0') == '>') { + isSelfClose = true; + break; + } + } + + // do not enter a script state if the tag self-closed + if (!isSelfClose) + chAttr = SCE_H_SCRIPT; + } else if (!isXml && 0 == strcmp(s, "comment")) { + chAttr = SCE_H_COMMENT; + } + } + return chAttr; +} + +static void classifyWordHTJS(unsigned int start, unsigned int end, + WordList &keywords, Accessor &styler, script_mode inScriptType) { + char s[30 + 1]; + unsigned int i = 0; + for (; i < end - start + 1 && i < 30; i++) { + s[i] = styler[start + i]; + } + s[i] = '\0'; + + char chAttr = SCE_HJ_WORD; + bool wordIsNumber = IsADigit(s[0]) || ((s[0] == '.') && IsADigit(s[1])); + if (wordIsNumber) { + chAttr = SCE_HJ_NUMBER; + } else if (keywords.InList(s)) { + chAttr = SCE_HJ_KEYWORD; + } + styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); +} + +static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, script_mode inScriptType) { + char chAttr = SCE_HB_IDENTIFIER; + bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.'); + if (wordIsNumber) + chAttr = SCE_HB_NUMBER; + else { + char s[100]; + GetTextSegment(styler, start, end, s, sizeof(s)); + if (keywords.InList(s)) { + chAttr = SCE_HB_WORD; + if (strcmp(s, "rem") == 0) + chAttr = SCE_HB_COMMENTLINE; + } + } + styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); + if (chAttr == SCE_HB_COMMENTLINE) + return SCE_HB_COMMENTLINE; + else + return SCE_HB_DEFAULT; +} + +static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord, script_mode inScriptType, bool isMako) { + bool wordIsNumber = IsADigit(styler[start]); + char s[30 + 1]; + unsigned int i = 0; + for (; i < end - start + 1 && i < 30; i++) { + s[i] = styler[start + i]; + } + s[i] = '\0'; + char chAttr = SCE_HP_IDENTIFIER; + if (0 == strcmp(prevWord, "class")) + chAttr = SCE_HP_CLASSNAME; + else if (0 == strcmp(prevWord, "def")) + chAttr = SCE_HP_DEFNAME; + else if (wordIsNumber) + chAttr = SCE_HP_NUMBER; + else if (keywords.InList(s)) + chAttr = SCE_HP_WORD; + else if (isMako && 0 == strcmp(s, "block")) + chAttr = SCE_HP_WORD; + styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); + strcpy(prevWord, s); +} + +// Update the word colour to default or keyword +// Called when in a PHP word +static void classifyWordHTPHP(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { + char chAttr = SCE_HPHP_DEFAULT; + bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.' && start+1 <= end && IsADigit(styler[start+1])); + if (wordIsNumber) + chAttr = SCE_HPHP_NUMBER; + else { + char s[100]; + GetTextSegment(styler, start, end, s, sizeof(s)); + if (keywords.InList(s)) + chAttr = SCE_HPHP_WORD; + } + styler.ColourTo(end, chAttr); +} + +static bool isWordHSGML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { + char s[30 + 1]; + unsigned int i = 0; + for (; i < end - start + 1 && i < 30; i++) { + s[i] = styler[start + i]; + } + s[i] = '\0'; + return keywords.InList(s); +} + +static bool isWordCdata(unsigned int start, unsigned int end, Accessor &styler) { + char s[30 + 1]; + unsigned int i = 0; + for (; i < end - start + 1 && i < 30; i++) { + s[i] = styler[start + i]; + } + s[i] = '\0'; + return (0 == strcmp(s, "[CDATA[")); +} + +// Return the first state to reach when entering a scripting language +static int StateForScript(script_type scriptLanguage) { + int Result; + switch (scriptLanguage) { + case eScriptVBS: + Result = SCE_HB_START; + break; + case eScriptPython: + Result = SCE_HP_START; + break; + case eScriptPHP: + Result = SCE_HPHP_DEFAULT; + break; + case eScriptXML: + Result = SCE_H_TAGUNKNOWN; + break; + case eScriptSGML: + Result = SCE_H_SGML_DEFAULT; + break; + case eScriptComment: + Result = SCE_H_COMMENT; + break; + default : + Result = SCE_HJ_START; + break; + } + return Result; +} + +static inline bool ishtmlwordchar(int ch) { + return !isascii(ch) || + (isalnum(ch) || ch == '.' || ch == '-' || ch == '_' || ch == ':' || ch == '!' || ch == '#'); +} + +static inline bool issgmlwordchar(int ch) { + return !isascii(ch) || + (isalnum(ch) || ch == '.' || ch == '_' || ch == ':' || ch == '!' || ch == '#' || ch == '['); +} + +static inline bool IsPhpWordStart(int ch) { + return (isascii(ch) && (isalpha(ch) || (ch == '_'))) || (ch >= 0x7f); +} + +static inline bool IsPhpWordChar(int ch) { + return IsADigit(ch) || IsPhpWordStart(ch); +} + +static bool InTagState(int state) { + return state == SCE_H_TAG || state == SCE_H_TAGUNKNOWN || + state == SCE_H_SCRIPT || + state == SCE_H_ATTRIBUTE || state == SCE_H_ATTRIBUTEUNKNOWN || + state == SCE_H_NUMBER || state == SCE_H_OTHER || + state == SCE_H_DOUBLESTRING || state == SCE_H_SINGLESTRING; +} + +static bool IsCommentState(const int state) { + return state == SCE_H_COMMENT || state == SCE_H_SGML_COMMENT; +} + +static bool IsScriptCommentState(const int state) { + return state == SCE_HJ_COMMENT || state == SCE_HJ_COMMENTLINE || state == SCE_HJA_COMMENT || + state == SCE_HJA_COMMENTLINE || state == SCE_HB_COMMENTLINE || state == SCE_HBA_COMMENTLINE; +} + +static bool isLineEnd(int ch) { + return ch == '\r' || ch == '\n'; +} + +static bool isOKBeforeRE(int ch) { + return (ch == '(') || (ch == '=') || (ch == ','); +} + +static bool isMakoBlockEnd(const int ch, const int chNext, const char *blockType) { + if (strlen(blockType) == 0) { + return ((ch == '%') && (chNext == '>')); + } else if ((0 == strcmp(blockType, "inherit")) || + (0 == strcmp(blockType, "namespace")) || + (0 == strcmp(blockType, "include")) || + (0 == strcmp(blockType, "page"))) { + return ((ch == '/') && (chNext == '>')); + } else if (0 == strcmp(blockType, "%")) { + if (ch == '/' && isLineEnd(chNext)) + return 1; + else + return isLineEnd(ch); + } else if (0 == strcmp(blockType, "{")) { + return ch == '}'; + } else { + return (ch == '>'); + } +} + +static bool isDjangoBlockEnd(const int ch, const int chNext, const char *blockType) { + if (strlen(blockType) == 0) { + return 0; + } else if (0 == strcmp(blockType, "%")) { + return ((ch == '%') && (chNext == '}')); + } else if (0 == strcmp(blockType, "{")) { + return ((ch == '}') && (chNext == '}')); + } else { + return 0; + } +} + +static bool isPHPStringState(int state) { + return + (state == SCE_HPHP_HSTRING) || + (state == SCE_HPHP_SIMPLESTRING) || + (state == SCE_HPHP_HSTRING_VARIABLE) || + (state == SCE_HPHP_COMPLEX_VARIABLE); +} + +static int FindPhpStringDelimiter(char *phpStringDelimiter, const int phpStringDelimiterSize, int i, const int lengthDoc, Accessor &styler, bool &isSimpleString) { + int j; + const int beginning = i - 1; + bool isValidSimpleString = false; + + while (i < lengthDoc && (styler[i] == ' ' || styler[i] == '\t')) + i++; + + char ch = styler.SafeGetCharAt(i); + const char chNext = styler.SafeGetCharAt(i + 1); + if (!IsPhpWordStart(ch)) { + if (ch == '\'' && IsPhpWordStart(chNext)) { + i++; + ch = chNext; + isSimpleString = true; + } else { + phpStringDelimiter[0] = '\0'; + return beginning; + } + } + phpStringDelimiter[0] = ch; + i++; + + for (j = i; j < lengthDoc && !isLineEnd(styler[j]); j++) { + if (!IsPhpWordChar(styler[j])) { + if (isSimpleString && (styler[j] == '\'') && isLineEnd(styler.SafeGetCharAt(j + 1))) { + isValidSimpleString = true; + j++; + break; + } else { + phpStringDelimiter[0] = '\0'; + return beginning; + } + } + if (j - i < phpStringDelimiterSize - 2) + phpStringDelimiter[j-i+1] = styler[j]; + else + i++; + } + if (isSimpleString && !isValidSimpleString) { + phpStringDelimiter[0] = '\0'; + return beginning; + } + phpStringDelimiter[j-i+1 - (isSimpleString ? 1 : 0)] = '\0'; + return j - 1; +} + +static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler, bool isXml) { + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; // SGML (DTD) keywords + + // Lexer for HTML requires more lexical states (8 bits worth) than most lexers + styler.StartAt(startPos, static_cast(STYLE_MAX)); + char prevWord[200]; + prevWord[0] = '\0'; + char phpStringDelimiter[200]; // PHP is not limited in length, we are + phpStringDelimiter[0] = '\0'; + int StateToPrint = initStyle; + int state = stateForPrintState(StateToPrint); + char makoBlockType[200]; + makoBlockType[0] = '\0'; + int makoComment = 0; + char djangoBlockType[2]; + djangoBlockType[0] = '\0'; + + // If inside a tag, it may be a script tag, so reread from the start to ensure any language tags are seen + if (InTagState(state)) { + while ((startPos > 0) && (InTagState(styler.StyleAt(startPos - 1)))) { + startPos--; + length++; + } + state = SCE_H_DEFAULT; + } + // String can be heredoc, must find a delimiter first. Reread from beginning of line containing the string, to get the correct lineState + if (isPHPStringState(state)) { + while (startPos > 0 && (isPHPStringState(state) || !isLineEnd(styler[startPos - 1]))) { + startPos--; + length++; + state = styler.StyleAt(startPos); + } + if (startPos == 0) + state = SCE_H_DEFAULT; + } + styler.StartAt(startPos, static_cast(STYLE_MAX)); + + int lineCurrent = styler.GetLine(startPos); + int lineState; + if (lineCurrent > 0) { + lineState = styler.GetLineState(lineCurrent-1); + } else { + // Default client and ASP scripting language is JavaScript + lineState = eScriptJS << 8; + + // property asp.default.language + // Script in ASP code is initially assumed to be in JavaScript. + // To change this to VBScript set asp.default.language to 2. Python is 3. + lineState |= styler.GetPropertyInt("asp.default.language", eScriptJS) << 4; + } + script_mode inScriptType = script_mode((lineState >> 0) & 0x03); // 2 bits of scripting mode + bool tagOpened = (lineState >> 2) & 0x01; // 1 bit to know if we are in an opened tag + bool tagClosing = (lineState >> 3) & 0x01; // 1 bit to know if we are in a closing tag + bool tagDontFold = false; //some HTML tags should not be folded + script_type aspScript = script_type((lineState >> 4) & 0x0F); // 4 bits of script name + script_type clientScript = script_type((lineState >> 8) & 0x0F); // 4 bits of script name + int beforePreProc = (lineState >> 12) & 0xFF; // 8 bits of state + + script_type scriptLanguage = ScriptOfState(state); + // If eNonHtmlScript coincides with SCE_H_COMMENT, assume eScriptComment + if (inScriptType == eNonHtmlScript && state == SCE_H_COMMENT) { + scriptLanguage = eScriptComment; + } + script_type beforeLanguage = ScriptOfState(beforePreProc); + + // property fold.html + // Folding is turned on or off for HTML and XML files with this option. + // The fold option must also be on for folding to occur. + const bool foldHTML = styler.GetPropertyInt("fold.html", 0) != 0; + + const bool fold = foldHTML && styler.GetPropertyInt("fold", 0); + + // property fold.html.preprocessor + // Folding is turned on or off for scripts embedded in HTML files with this option. + // The default is on. + const bool foldHTMLPreprocessor = foldHTML && styler.GetPropertyInt("fold.html.preprocessor", 1); + + const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + + // property fold.hypertext.comment + // Allow folding for comments in scripts embedded in HTML. + // The default is off. + const bool foldComment = fold && styler.GetPropertyInt("fold.hypertext.comment", 0) != 0; + + // property fold.hypertext.heredoc + // Allow folding for heredocs in scripts embedded in HTML. + // The default is off. + const bool foldHeredoc = fold && styler.GetPropertyInt("fold.hypertext.heredoc", 0) != 0; + + // property html.tags.case.sensitive + // For XML and HTML, setting this property to 1 will make tags match in a case + // sensitive way which is the expected behaviour for XML and XHTML. + const bool caseSensitive = styler.GetPropertyInt("html.tags.case.sensitive", 0) != 0; + + // property lexer.xml.allow.scripts + // Set to 0 to disable scripts in XML. + const bool allowScripts = styler.GetPropertyInt("lexer.xml.allow.scripts", 1) != 0; + + // property lexer.html.mako + // Set to 1 to enable the mako template language. + const bool isMako = styler.GetPropertyInt("lexer.html.mako", 0) != 0; + + // property lexer.html.django + // Set to 1 to enable the django template language. + const bool isDjango = styler.GetPropertyInt("lexer.html.django", 0) != 0; + + const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", 0x80, true); + const CharacterSet setTagContinue(CharacterSet::setAlphaNum, ".-_:!#[", 0x80, true); + const CharacterSet setAttributeContinue(CharacterSet::setAlphaNum, ".-_:!#/", 0x80, true); + + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + int visibleChars = 0; + int lineStartVisibleChars = 0; + + int chPrev = ' '; + int ch = ' '; + int chPrevNonWhite = ' '; + // look back to set chPrevNonWhite properly for better regex colouring + if (scriptLanguage == eScriptJS && startPos > 0) { + int back = startPos; + int style = 0; + while (--back) { + style = styler.StyleAt(back); + if (style < SCE_HJ_DEFAULT || style > SCE_HJ_COMMENTDOC) + // includes SCE_HJ_COMMENT & SCE_HJ_COMMENTLINE + break; + } + if (style == SCE_HJ_SYMBOLS) { + chPrevNonWhite = static_cast(styler.SafeGetCharAt(back)); + } + } + + styler.StartSegment(startPos); + const int lengthDoc = startPos + length; + for (int i = startPos; i < lengthDoc; i++) { + const int chPrev2 = chPrev; + chPrev = ch; + if (!IsASpace(ch) && state != SCE_HJ_COMMENT && + state != SCE_HJ_COMMENTLINE && state != SCE_HJ_COMMENTDOC) + chPrevNonWhite = ch; + ch = static_cast(styler[i]); + int chNext = static_cast(styler.SafeGetCharAt(i + 1)); + const int chNext2 = static_cast(styler.SafeGetCharAt(i + 2)); + + // Handle DBCS codepages + if (styler.IsLeadByte(static_cast(ch))) { + chPrev = ' '; + i += 1; + continue; + } + + if ((!IsASpace(ch) || !foldCompact) && fold) + visibleChars++; + if (!IsASpace(ch)) + lineStartVisibleChars++; + + // decide what is the current state to print (depending of the script tag) + StateToPrint = statePrintForState(state, inScriptType); + + // handle script folding + if (fold) { + switch (scriptLanguage) { + case eScriptJS: + case eScriptPHP: + //not currently supported case eScriptVBS: + + if ((state != SCE_HPHP_COMMENT) && (state != SCE_HPHP_COMMENTLINE) && (state != SCE_HJ_COMMENT) && (state != SCE_HJ_COMMENTLINE) && (state != SCE_HJ_COMMENTDOC) && (!isStringState(state))) { + //Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle); + //if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) { + if (ch == '#') { + int j = i + 1; + while ((j < lengthDoc) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (styler.Match(j, "region") || styler.Match(j, "if")) { + levelCurrent++; + } else if (styler.Match(j, "end")) { + levelCurrent--; + } + } else if ((ch == '{') || (ch == '}') || (foldComment && (ch == '/') && (chNext == '*'))) { + levelCurrent += (((ch == '{') || (ch == '/')) ? 1 : -1); + } + } else if (((state == SCE_HPHP_COMMENT) || (state == SCE_HJ_COMMENT)) && foldComment && (ch == '*') && (chNext == '/')) { + levelCurrent--; + } + break; + case eScriptPython: + if (state != SCE_HP_COMMENTLINE && !isMako) { + if ((ch == ':') && ((chNext == '\n') || (chNext == '\r' && chNext2 == '\n'))) { + levelCurrent++; + } else if ((ch == '\n') && !((chNext == '\r') && (chNext2 == '\n')) && (chNext != '\n')) { + // check if the number of tabs is lower than the level + int Findlevel = (levelCurrent & ~SC_FOLDLEVELBASE) * 8; + for (int j = 0; Findlevel > 0; j++) { + char chTmp = styler.SafeGetCharAt(i + j + 1); + if (chTmp == '\t') { + Findlevel -= 8; + } else if (chTmp == ' ') { + Findlevel--; + } else { + break; + } + } + + if (Findlevel > 0) { + levelCurrent -= Findlevel / 8; + if (Findlevel % 8) + levelCurrent--; + } + } + } + break; + default: + break; + } + } + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // New line -> record any line state onto /next/ line + if (fold) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + + styler.SetLevel(lineCurrent, lev); + visibleChars = 0; + levelPrev = levelCurrent; + } + styler.SetLineState(lineCurrent, + ((inScriptType & 0x03) << 0) | + ((tagOpened & 0x01) << 2) | + ((tagClosing & 0x01) << 3) | + ((aspScript & 0x0F) << 4) | + ((clientScript & 0x0F) << 8) | + ((beforePreProc & 0xFF) << 12)); + lineCurrent++; + lineStartVisibleChars = 0; + } + + // handle start of Mako comment line + if (isMako && ch == '#' && chNext == '#') { + makoComment = 1; + } + + // handle end of Mako comment line + else if (isMako && makoComment && (ch == '\r' || ch == '\n')) { + makoComment = 0; + styler.ColourTo(i, SCE_HP_COMMENTLINE); + state = SCE_HP_DEFAULT; + } + + // Allow falling through to mako handling code if newline is going to end a block + if (((ch == '\r' && chNext != '\n') || (ch == '\n')) && + (!isMako || (0 != strcmp(makoBlockType, "%")))) { + } + + // generic end of script processing + else if ((inScriptType == eNonHtmlScript) && (ch == '<') && (chNext == '/')) { + // Check if it's the end of the script tag (or any other HTML tag) + switch (state) { + // in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!) + case SCE_H_DOUBLESTRING: + case SCE_H_SINGLESTRING: + case SCE_HJ_COMMENT: + case SCE_HJ_COMMENTDOC: + //case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide + // the end of script marker from some JS interpreters. + case SCE_HB_COMMENTLINE: + case SCE_HBA_COMMENTLINE: + case SCE_HJ_DOUBLESTRING: + case SCE_HJ_SINGLESTRING: + case SCE_HJ_REGEX: + case SCE_HB_STRING: + case SCE_HBA_STRING: + case SCE_HP_STRING: + case SCE_HP_TRIPLE: + case SCE_HP_TRIPLEDOUBLE: + case SCE_HPHP_HSTRING: + case SCE_HPHP_SIMPLESTRING: + case SCE_HPHP_COMMENT: + case SCE_HPHP_COMMENTLINE: + break; + default : + // check if the closing tag is a script tag + if (const char *tag = + state == SCE_HJ_COMMENTLINE || isXml ? "script" : + state == SCE_H_COMMENT ? "comment" : 0) { + int j = i + 2; + int chr; + do { + chr = static_cast(*tag++); + } while (chr != 0 && chr == MakeLowerCase(styler.SafeGetCharAt(j++))); + if (chr != 0) break; + } + // closing tag of the script (it's a closing HTML tag anyway) + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_TAGUNKNOWN; + inScriptType = eHtml; + scriptLanguage = eScriptNone; + clientScript = eScriptJS; + i += 2; + visibleChars += 2; + tagClosing = true; + continue; + } + } + + ///////////////////////////////////// + // handle the start of PHP pre-processor = Non-HTML + else if ((state != SCE_H_ASPAT) && + !isPHPStringState(state) && + (state != SCE_HPHP_COMMENT) && + (state != SCE_HPHP_COMMENTLINE) && + (ch == '<') && + (chNext == '?') && + !IsScriptCommentState(state)) { + beforeLanguage = scriptLanguage; + scriptLanguage = segIsScriptingIndicator(styler, i + 2, i + 6, eScriptPHP); + if (scriptLanguage != eScriptPHP && isStringState(state)) continue; + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + i++; + visibleChars++; + i += PrintScriptingIndicatorOffset(styler, styler.GetStartSegment() + 2, i + 6); + if (scriptLanguage == eScriptXML) + styler.ColourTo(i, SCE_H_XMLSTART); + else + styler.ColourTo(i, SCE_H_QUESTION); + state = StateForScript(scriptLanguage); + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + // Fold whole script, but not if the XML first tag (all XML-like tags in this case) + if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { + levelCurrent++; + } + // should be better + ch = static_cast(styler.SafeGetCharAt(i)); + continue; + } + + // handle the start Mako template Python code + else if (isMako && scriptLanguage == eScriptNone && ((ch == '<' && chNext == '%') || + (lineStartVisibleChars == 1 && ch == '%') || + (lineStartVisibleChars == 1 && ch == '/' && chNext == '%') || + (ch == '$' && chNext == '{') || + (ch == '<' && chNext == '/' && chNext2 == '%'))) { + if (ch == '%' || ch == '/') + strcpy(makoBlockType, "%"); + else if (ch == '$') + strcpy(makoBlockType, "{"); + else if (chNext == '/') + GetNextWord(styler, i+3, makoBlockType, sizeof(makoBlockType)); + else + GetNextWord(styler, i+2, makoBlockType, sizeof(makoBlockType)); + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + + if (chNext == '/') { + i += 2; + visibleChars += 2; + } else if (ch != '%') { + i++; + visibleChars++; + } + state = SCE_HP_START; + scriptLanguage = eScriptPython; + styler.ColourTo(i, SCE_H_ASP); + + if (ch != '%' && ch != '$' && ch != '/') { + i += static_cast(strlen(makoBlockType)); + visibleChars += static_cast(strlen(makoBlockType)); + if (keywords4.InList(makoBlockType)) + styler.ColourTo(i, SCE_HP_WORD); + else + styler.ColourTo(i, SCE_H_TAGUNKNOWN); + } + + ch = static_cast(styler.SafeGetCharAt(i)); + continue; + } + + // handle the start/end of Django comment + else if (isDjango && state != SCE_H_COMMENT && (ch == '{' && chNext == '#')) { + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + beforeLanguage = scriptLanguage; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + i += 1; + visibleChars += 1; + scriptLanguage = eScriptComment; + state = SCE_H_COMMENT; + styler.ColourTo(i, SCE_H_ASP); + ch = static_cast(styler.SafeGetCharAt(i)); + continue; + } else if (isDjango && state == SCE_H_COMMENT && (ch == '#' && chNext == '}')) { + styler.ColourTo(i - 1, StateToPrint); + i += 1; + visibleChars += 1; + styler.ColourTo(i, SCE_H_ASP); + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + scriptLanguage = beforeLanguage; + continue; + } + + // handle the start Django template code + else if (isDjango && scriptLanguage != eScriptPython && (ch == '{' && (chNext == '%' || chNext == '{'))) { + if (chNext == '%') + strcpy(djangoBlockType, "%"); + else + strcpy(djangoBlockType, "{"); + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + + i += 1; + visibleChars += 1; + state = SCE_HP_START; + beforeLanguage = scriptLanguage; + scriptLanguage = eScriptPython; + styler.ColourTo(i, SCE_H_ASP); + + ch = static_cast(styler.SafeGetCharAt(i)); + continue; + } + + // handle the start of ASP pre-processor = Non-HTML + else if (!isMako && !isDjango && !isCommentASPState(state) && (ch == '<') && (chNext == '%') && !isPHPStringState(state)) { + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + + if (chNext2 == '@') { + i += 2; // place as if it was the second next char treated + visibleChars += 2; + state = SCE_H_ASPAT; + } else if ((chNext2 == '-') && (styler.SafeGetCharAt(i + 3) == '-')) { + styler.ColourTo(i + 3, SCE_H_ASP); + state = SCE_H_XCCOMMENT; + scriptLanguage = eScriptVBS; + continue; + } else { + if (chNext2 == '=') { + i += 2; // place as if it was the second next char treated + visibleChars += 2; + } else { + i++; // place as if it was the next char treated + visibleChars++; + } + + state = StateForScript(aspScript); + } + scriptLanguage = eScriptVBS; + styler.ColourTo(i, SCE_H_ASP); + // fold whole script + if (foldHTMLPreprocessor) + levelCurrent++; + // should be better + ch = static_cast(styler.SafeGetCharAt(i)); + continue; + } + + ///////////////////////////////////// + // handle the start of SGML language (DTD) + else if (((scriptLanguage == eScriptNone) || (scriptLanguage == eScriptXML)) && + (chPrev == '<') && + (ch == '!') && + (StateToPrint != SCE_H_CDATA) && + (!IsCommentState(StateToPrint)) && + (!IsScriptCommentState(StateToPrint))) { + beforePreProc = state; + styler.ColourTo(i - 2, StateToPrint); + if ((chNext == '-') && (chNext2 == '-')) { + state = SCE_H_COMMENT; // wait for a pending command + styler.ColourTo(i + 2, SCE_H_COMMENT); + i += 2; // follow styling after the -- + } else if (isWordCdata(i + 1, i + 7, styler)) { + state = SCE_H_CDATA; + } else { + styler.ColourTo(i, SCE_H_SGML_DEFAULT); // ') { + i++; + visibleChars++; + } + else if (0 == strcmp(makoBlockType, "%") && ch == '/') { + i++; + visibleChars++; + } + if (0 != strcmp(makoBlockType, "%") || ch == '/') { + styler.ColourTo(i, SCE_H_ASP); + } + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + scriptLanguage = eScriptNone; + continue; + } + + // handle the end of Django template code + else if (isDjango && + ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && + (scriptLanguage != eScriptNone) && stateAllowsTermination(state) && + isDjangoBlockEnd(ch, chNext, djangoBlockType)) { + if (state == SCE_H_ASPAT) { + aspScript = segIsScriptingIndicator(styler, + styler.GetStartSegment(), i - 1, aspScript); + } + if (state == SCE_HP_WORD) { + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako); + } else { + styler.ColourTo(i - 1, StateToPrint); + } + i += 1; + visibleChars += 1; + styler.ColourTo(i, SCE_H_ASP); + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + scriptLanguage = beforeLanguage; + continue; + } + + // handle the end of a pre-processor = Non-HTML + else if ((!isMako && !isDjango && ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && + (((scriptLanguage != eScriptNone) && stateAllowsTermination(state))) && + (((ch == '%') || (ch == '?')) && (chNext == '>'))) || + ((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) { + if (state == SCE_H_ASPAT) { + aspScript = segIsScriptingIndicator(styler, + styler.GetStartSegment(), i - 1, aspScript); + } + // Bounce out of any ASP mode + switch (state) { + case SCE_HJ_WORD: + classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType); + break; + case SCE_HB_WORD: + classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType); + break; + case SCE_HP_WORD: + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako); + break; + case SCE_HPHP_WORD: + classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler); + break; + case SCE_H_XCCOMMENT: + styler.ColourTo(i - 1, state); + break; + default : + styler.ColourTo(i - 1, StateToPrint); + break; + } + if (scriptLanguage != eScriptSGML) { + i++; + visibleChars++; + } + if (ch == '%') + styler.ColourTo(i, SCE_H_ASP); + else if (scriptLanguage == eScriptXML) + styler.ColourTo(i, SCE_H_XMLEND); + else if (scriptLanguage == eScriptSGML) + styler.ColourTo(i, SCE_H_SGML_DEFAULT); + else + styler.ColourTo(i, SCE_H_QUESTION); + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + // Unfold all scripting languages, except for XML tag + if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { + levelCurrent--; + } + scriptLanguage = beforeLanguage; + continue; + } + ///////////////////////////////////// + + switch (state) { + case SCE_H_DEFAULT: + if (ch == '<') { + // in HTML, fold on tag open and unfold on tag close + tagOpened = true; + tagClosing = (chNext == '/'); + styler.ColourTo(i - 1, StateToPrint); + if (chNext != '!') + state = SCE_H_TAGUNKNOWN; + } else if (ch == '&') { + styler.ColourTo(i - 1, SCE_H_DEFAULT); + state = SCE_H_ENTITY; + } + break; + case SCE_H_SGML_DEFAULT: + case SCE_H_SGML_BLOCK_DEFAULT: +// if (scriptLanguage == eScriptSGMLblock) +// StateToPrint = SCE_H_SGML_BLOCK_DEFAULT; + + if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_DOUBLESTRING; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_SIMPLESTRING; + } else if ((ch == '-') && (chPrev == '-')) { + if (static_cast(styler.GetStartSegment()) <= (i - 2)) { + styler.ColourTo(i - 2, StateToPrint); + } + state = SCE_H_SGML_COMMENT; + } else if (isascii(ch) && isalpha(ch) && (chPrev == '%')) { + styler.ColourTo(i - 2, StateToPrint); + state = SCE_H_SGML_ENTITY; + } else if (ch == '#') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_SPECIAL; + } else if (ch == '[') { + styler.ColourTo(i - 1, StateToPrint); + scriptLanguage = eScriptSGMLblock; + state = SCE_H_SGML_BLOCK_DEFAULT; + } else if (ch == ']') { + if (scriptLanguage == eScriptSGMLblock) { + styler.ColourTo(i, StateToPrint); + scriptLanguage = eScriptSGML; + } else { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, SCE_H_SGML_ERROR); + } + state = SCE_H_SGML_DEFAULT; + } else if (scriptLanguage == eScriptSGMLblock) { + if ((ch == '!') && (chPrev == '<')) { + styler.ColourTo(i - 2, StateToPrint); + styler.ColourTo(i, SCE_H_SGML_DEFAULT); + state = SCE_H_SGML_COMMAND; + } else if (ch == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, SCE_H_SGML_DEFAULT); + } + } + break; + case SCE_H_SGML_COMMAND: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i - 2, StateToPrint); + state = SCE_H_SGML_COMMENT; + } else if (!issgmlwordchar(ch)) { + if (isWordHSGML(styler.GetStartSegment(), i - 1, keywords6, styler)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_1ST_PARAM; + } else { + state = SCE_H_SGML_ERROR; + } + } + break; + case SCE_H_SGML_1ST_PARAM: + // wait for the beginning of the word + if ((ch == '-') && (chPrev == '-')) { + if (scriptLanguage == eScriptSGMLblock) { + styler.ColourTo(i - 2, SCE_H_SGML_BLOCK_DEFAULT); + } else { + styler.ColourTo(i - 2, SCE_H_SGML_DEFAULT); + } + state = SCE_H_SGML_1ST_PARAM_COMMENT; + } else if (issgmlwordchar(ch)) { + if (scriptLanguage == eScriptSGMLblock) { + styler.ColourTo(i - 1, SCE_H_SGML_BLOCK_DEFAULT); + } else { + styler.ColourTo(i - 1, SCE_H_SGML_DEFAULT); + } + // find the length of the word + int size = 1; + while (setHTMLWord.Contains(static_cast(styler.SafeGetCharAt(i + size)))) + size++; + styler.ColourTo(i + size - 1, StateToPrint); + i += size - 1; + visibleChars += size - 1; + ch = static_cast(styler.SafeGetCharAt(i)); + if (scriptLanguage == eScriptSGMLblock) { + state = SCE_H_SGML_BLOCK_DEFAULT; + } else { + state = SCE_H_SGML_DEFAULT; + } + continue; + } + break; + case SCE_H_SGML_ERROR: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i - 2, StateToPrint); + state = SCE_H_SGML_COMMENT; + } + case SCE_H_SGML_DOUBLESTRING: + if (ch == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_SGML_SIMPLESTRING: + if (ch == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_SGML_COMMENT: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_CDATA: + if ((chPrev2 == ']') && (chPrev == ']') && (ch == '>')) { + styler.ColourTo(i, StateToPrint); + state = SCE_H_DEFAULT; + levelCurrent--; + } + break; + case SCE_H_COMMENT: + if ((scriptLanguage != eScriptComment) && (chPrev2 == '-') && (chPrev == '-') && (ch == '>')) { + styler.ColourTo(i, StateToPrint); + state = SCE_H_DEFAULT; + levelCurrent--; + } + break; + case SCE_H_SGML_1ST_PARAM_COMMENT: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i, SCE_H_SGML_COMMENT); + state = SCE_H_SGML_1ST_PARAM; + } + break; + case SCE_H_SGML_SPECIAL: + if (!(isascii(ch) && isupper(ch))) { + styler.ColourTo(i - 1, StateToPrint); + if (isalnum(ch)) { + state = SCE_H_SGML_ERROR; + } else { + state = SCE_H_SGML_DEFAULT; + } + } + break; + case SCE_H_SGML_ENTITY: + if (ch == ';') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } else if (!(isascii(ch) && isalnum(ch)) && ch != '-' && ch != '.') { + styler.ColourTo(i, SCE_H_SGML_ERROR); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_ENTITY: + if (ch == ';') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_DEFAULT; + } + if (ch != '#' && !(isascii(ch) && isalnum(ch)) // Should check that '#' follows '&', but it is unlikely anyway... + && ch != '.' && ch != '-' && ch != '_' && ch != ':') { // valid in XML + if (!isascii(ch)) // Possibly start of a multibyte character so don't allow this byte to be in entity style + styler.ColourTo(i-1, SCE_H_TAGUNKNOWN); + else + styler.ColourTo(i, SCE_H_TAGUNKNOWN); + state = SCE_H_DEFAULT; + } + break; + case SCE_H_TAGUNKNOWN: + if (!setTagContinue.Contains(ch) && !((ch == '/') && (chPrev == '<'))) { + int eClass = classifyTagHTML(styler.GetStartSegment(), + i - 1, keywords, styler, tagDontFold, caseSensitive, isXml, allowScripts); + if (eClass == SCE_H_SCRIPT || eClass == SCE_H_COMMENT) { + if (!tagClosing) { + inScriptType = eNonHtmlScript; + scriptLanguage = eClass == SCE_H_SCRIPT ? clientScript : eScriptComment; + } else { + scriptLanguage = eScriptNone; + } + eClass = SCE_H_TAG; + } + if (ch == '>') { + styler.ColourTo(i, eClass); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!tagDontFold) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else if (ch == '/' && chNext == '>') { + if (eClass == SCE_H_TAGUNKNOWN) { + styler.ColourTo(i + 1, SCE_H_TAGUNKNOWN); + } else { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i + 1, SCE_H_TAGEND); + } + i++; + ch = chNext; + state = SCE_H_DEFAULT; + tagOpened = false; + } else { + if (eClass != SCE_H_TAGUNKNOWN) { + if (eClass == SCE_H_SGML_DEFAULT) { + state = SCE_H_SGML_DEFAULT; + } else { + state = SCE_H_OTHER; + } + } + } + } + break; + case SCE_H_ATTRIBUTE: + if (!setAttributeContinue.Contains(ch)) { + if (inScriptType == eNonHtmlScript) { + int scriptLanguagePrev = scriptLanguage; + clientScript = segIsScriptingIndicator(styler, styler.GetStartSegment(), i - 1, scriptLanguage); + scriptLanguage = clientScript; + if ((scriptLanguagePrev != scriptLanguage) && (scriptLanguage == eScriptNone)) + inScriptType = eHtml; + } + classifyAttribHTML(styler.GetStartSegment(), i - 1, keywords, styler); + if (ch == '>') { + styler.ColourTo(i, SCE_H_TAG); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!tagDontFold) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else if (ch == '=') { + styler.ColourTo(i, SCE_H_OTHER); + state = SCE_H_VALUE; + } else { + state = SCE_H_OTHER; + } + } + break; + case SCE_H_OTHER: + if (ch == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, SCE_H_TAG); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!tagDontFold) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_DOUBLESTRING; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SINGLESTRING; + } else if (ch == '=') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_VALUE; + } else if (ch == '/' && chNext == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i + 1, SCE_H_TAGEND); + i++; + ch = chNext; + state = SCE_H_DEFAULT; + tagOpened = false; + } else if (ch == '?' && chNext == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i + 1, SCE_H_XMLEND); + i++; + ch = chNext; + state = SCE_H_DEFAULT; + } else if (setHTMLWord.Contains(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_ATTRIBUTE; + } + break; + case SCE_H_DOUBLESTRING: + if (ch == '\"') { + if (inScriptType == eNonHtmlScript) { + scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage); + } + styler.ColourTo(i, SCE_H_DOUBLESTRING); + state = SCE_H_OTHER; + } + break; + case SCE_H_SINGLESTRING: + if (ch == '\'') { + if (inScriptType == eNonHtmlScript) { + scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage); + } + styler.ColourTo(i, SCE_H_SINGLESTRING); + state = SCE_H_OTHER; + } + break; + case SCE_H_VALUE: + if (!setHTMLWord.Contains(ch)) { + if (ch == '\"' && chPrev == '=') { + // Should really test for being first character + state = SCE_H_DOUBLESTRING; + } else if (ch == '\'' && chPrev == '=') { + state = SCE_H_SINGLESTRING; + } else { + if (IsNumber(styler.GetStartSegment(), styler)) { + styler.ColourTo(i - 1, SCE_H_NUMBER); + } else { + styler.ColourTo(i - 1, StateToPrint); + } + if (ch == '>') { + styler.ColourTo(i, SCE_H_TAG); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!tagDontFold) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else { + state = SCE_H_OTHER; + } + } + } + break; + case SCE_HJ_DEFAULT: + case SCE_HJ_START: + case SCE_HJ_SYMBOLS: + if (IsAWordStart(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_WORD; + } else if (ch == '/' && chNext == '*') { + styler.ColourTo(i - 1, StateToPrint); + if (chNext2 == '*') + state = SCE_HJ_COMMENTDOC; + else + state = SCE_HJ_COMMENT; + } else if (ch == '/' && chNext == '/') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + } else if (ch == '/' && isOKBeforeRE(chPrevNonWhite)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_REGEX; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_DOUBLESTRING; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_SINGLESTRING; + } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && + styler.SafeGetCharAt(i + 3) == '-') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + i += 2; + } else if (IsOperator(ch)) { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); + state = SCE_HJ_DEFAULT; + } else if ((ch == ' ') || (ch == '\t')) { + if (state == SCE_HJ_START) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_DEFAULT; + } + } + break; + case SCE_HJ_WORD: + if (!IsAWordChar(ch)) { + classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType); + //styler.ColourTo(i - 1, eHTJSKeyword); + state = SCE_HJ_DEFAULT; + if (ch == '/' && chNext == '*') { + if (chNext2 == '*') + state = SCE_HJ_COMMENTDOC; + else + state = SCE_HJ_COMMENT; + } else if (ch == '/' && chNext == '/') { + state = SCE_HJ_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_HJ_DOUBLESTRING; + } else if (ch == '\'') { + state = SCE_HJ_SINGLESTRING; + } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + i += 2; + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); + state = SCE_HJ_DEFAULT; + } + } + break; + case SCE_HJ_COMMENT: + case SCE_HJ_COMMENTDOC: + if (ch == '/' && chPrev == '*') { + styler.ColourTo(i, StateToPrint); + state = SCE_HJ_DEFAULT; + ch = ' '; + } + break; + case SCE_HJ_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, statePrintForState(SCE_HJ_COMMENTLINE, inScriptType)); + state = SCE_HJ_DEFAULT; + ch = ' '; + } + break; + case SCE_HJ_DOUBLESTRING: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + } + } else if (ch == '\"') { + styler.ColourTo(i, statePrintForState(SCE_HJ_DOUBLESTRING, inScriptType)); + state = SCE_HJ_DEFAULT; + } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + i += 2; + } else if (isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_STRINGEOL; + } + break; + case SCE_HJ_SINGLESTRING: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + } + } else if (ch == '\'') { + styler.ColourTo(i, statePrintForState(SCE_HJ_SINGLESTRING, inScriptType)); + state = SCE_HJ_DEFAULT; + } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + i += 2; + } else if (isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + if (chPrev != '\\' && (chPrev2 != '\\' || chPrev != '\r' || ch != '\n')) { + state = SCE_HJ_STRINGEOL; + } + } + break; + case SCE_HJ_STRINGEOL: + if (!isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_DEFAULT; + } else if (!isLineEnd(chNext)) { + styler.ColourTo(i, StateToPrint); + state = SCE_HJ_DEFAULT; + } + break; + case SCE_HJ_REGEX: + if (ch == '\r' || ch == '\n' || ch == '/') { + if (ch == '/') { + while (isascii(chNext) && islower(chNext)) { // gobble regex flags + i++; + ch = chNext; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } + } + styler.ColourTo(i, StateToPrint); + state = SCE_HJ_DEFAULT; + } else if (ch == '\\') { + // Gobble up the quoted character + if (chNext == '\\' || chNext == '/') { + i++; + ch = chNext; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } + } + break; + case SCE_HB_DEFAULT: + case SCE_HB_START: + if (IsAWordStart(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_WORD; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_COMMENTLINE; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_STRING; + } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && + styler.SafeGetCharAt(i + 3) == '-') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_COMMENTLINE; + } else if (IsOperator(ch)) { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType)); + state = SCE_HB_DEFAULT; + } else if ((ch == ' ') || (ch == '\t')) { + if (state == SCE_HB_START) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_DEFAULT; + } + } + break; + case SCE_HB_WORD: + if (!IsAWordChar(ch)) { + state = classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType); + if (state == SCE_HB_DEFAULT) { + if (ch == '\"') { + state = SCE_HB_STRING; + } else if (ch == '\'') { + state = SCE_HB_COMMENTLINE; + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType)); + state = SCE_HB_DEFAULT; + } + } + } + break; + case SCE_HB_STRING: + if (ch == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HB_DEFAULT; + } else if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_STRINGEOL; + } + break; + case SCE_HB_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_DEFAULT; + } + break; + case SCE_HB_STRINGEOL: + if (!isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_DEFAULT; + } else if (!isLineEnd(chNext)) { + styler.ColourTo(i, StateToPrint); + state = SCE_HB_DEFAULT; + } + break; + case SCE_HP_DEFAULT: + case SCE_HP_START: + if (IsAWordStart(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_WORD; + } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && + styler.SafeGetCharAt(i + 3) == '-') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_COMMENTLINE; + } else if (ch == '#') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_COMMENTLINE; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + if (chNext == '\"' && chNext2 == '\"') { + i += 2; + state = SCE_HP_TRIPLEDOUBLE; + ch = ' '; + chPrev = ' '; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } else { + // state = statePrintForState(SCE_HP_STRING,inScriptType); + state = SCE_HP_STRING; + } + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + if (chNext == '\'' && chNext2 == '\'') { + i += 2; + state = SCE_HP_TRIPLE; + ch = ' '; + chPrev = ' '; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } else { + state = SCE_HP_CHARACTER; + } + } else if (IsOperator(ch)) { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType)); + } else if ((ch == ' ') || (ch == '\t')) { + if (state == SCE_HP_START) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_DEFAULT; + } + } + break; + case SCE_HP_WORD: + if (!IsAWordChar(ch)) { + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako); + state = SCE_HP_DEFAULT; + if (ch == '#') { + state = SCE_HP_COMMENTLINE; + } else if (ch == '\"') { + if (chNext == '\"' && chNext2 == '\"') { + i += 2; + state = SCE_HP_TRIPLEDOUBLE; + ch = ' '; + chPrev = ' '; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } else { + state = SCE_HP_STRING; + } + } else if (ch == '\'') { + if (chNext == '\'' && chNext2 == '\'') { + i += 2; + state = SCE_HP_TRIPLE; + ch = ' '; + chPrev = ' '; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } else { + state = SCE_HP_CHARACTER; + } + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType)); + } + } + break; + case SCE_HP_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_STRING: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } + } else if (ch == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_CHARACTER: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } + } else if (ch == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_TRIPLE: + if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_TRIPLEDOUBLE: + if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + ///////////// start - PHP state handling + case SCE_HPHP_WORD: + if (!IsAWordChar(ch)) { + classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler); + if (ch == '/' && chNext == '*') { + i++; + state = SCE_HPHP_COMMENT; + } else if (ch == '/' && chNext == '/') { + i++; + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '#') { + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_HPHP_HSTRING; + strcpy(phpStringDelimiter, "\""); + } else if (styler.Match(i, "<<<")) { + bool isSimpleString = false; + i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString); + if (strlen(phpStringDelimiter)) { + state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING); + if (foldHeredoc) levelCurrent++; + } + } else if (ch == '\'') { + state = SCE_HPHP_SIMPLESTRING; + strcpy(phpStringDelimiter, "\'"); + } else if (ch == '$' && IsPhpWordStart(chNext)) { + state = SCE_HPHP_VARIABLE; + } else if (IsOperator(ch)) { + state = SCE_HPHP_OPERATOR; + } else { + state = SCE_HPHP_DEFAULT; + } + } + break; + case SCE_HPHP_NUMBER: + // recognize bases 8,10 or 16 integers OR floating-point numbers + if (!IsADigit(ch) + && strchr(".xXabcdefABCDEF", ch) == NULL + && ((ch != '-' && ch != '+') || (chPrev != 'e' && chPrev != 'E'))) { + styler.ColourTo(i - 1, SCE_HPHP_NUMBER); + if (IsOperator(ch)) + state = SCE_HPHP_OPERATOR; + else + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_VARIABLE: + if (!IsPhpWordChar(chNext)) { + styler.ColourTo(i, SCE_HPHP_VARIABLE); + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_COMMENT: + if (ch == '/' && chPrev == '*') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_HSTRING: + if (ch == '\\' && (phpStringDelimiter[0] == '\"' || chNext == '$' || chNext == '{')) { + // skip the next char + i++; + } else if (((ch == '{' && chNext == '$') || (ch == '$' && chNext == '{')) + && IsPhpWordStart(chNext2)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HPHP_COMPLEX_VARIABLE; + } else if (ch == '$' && IsPhpWordStart(chNext)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HPHP_HSTRING_VARIABLE; + } else if (styler.Match(i, phpStringDelimiter)) { + if (phpStringDelimiter[0] == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + } else if (isLineEnd(chPrev)) { + const int psdLength = static_cast(strlen(phpStringDelimiter)); + const char chAfterPsd = styler.SafeGetCharAt(i + psdLength); + const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1); + if (isLineEnd(chAfterPsd) || + (chAfterPsd == ';' && isLineEnd(chAfterPsd2))) { + i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1; + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + if (foldHeredoc) levelCurrent--; + } + } + } + break; + case SCE_HPHP_SIMPLESTRING: + if (phpStringDelimiter[0] == '\'') { + if (ch == '\\') { + // skip the next char + i++; + } else if (ch == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + } + } else if (isLineEnd(chPrev) && styler.Match(i, phpStringDelimiter)) { + const int psdLength = static_cast(strlen(phpStringDelimiter)); + const char chAfterPsd = styler.SafeGetCharAt(i + psdLength); + const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1); + if (isLineEnd(chAfterPsd) || + (chAfterPsd == ';' && isLineEnd(chAfterPsd2))) { + i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1; + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + if (foldHeredoc) levelCurrent--; + } + } + break; + case SCE_HPHP_HSTRING_VARIABLE: + if (!IsPhpWordChar(chNext)) { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_HSTRING; + } + break; + case SCE_HPHP_COMPLEX_VARIABLE: + if (ch == '}') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_HSTRING; + } + break; + case SCE_HPHP_OPERATOR: + case SCE_HPHP_DEFAULT: + styler.ColourTo(i - 1, StateToPrint); + if (IsADigit(ch) || (ch == '.' && IsADigit(chNext))) { + state = SCE_HPHP_NUMBER; + } else if (IsAWordStart(ch)) { + state = SCE_HPHP_WORD; + } else if (ch == '/' && chNext == '*') { + i++; + state = SCE_HPHP_COMMENT; + } else if (ch == '/' && chNext == '/') { + i++; + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '#') { + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_HPHP_HSTRING; + strcpy(phpStringDelimiter, "\""); + } else if (styler.Match(i, "<<<")) { + bool isSimpleString = false; + i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString); + if (strlen(phpStringDelimiter)) { + state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING); + if (foldHeredoc) levelCurrent++; + } + } else if (ch == '\'') { + state = SCE_HPHP_SIMPLESTRING; + strcpy(phpStringDelimiter, "\'"); + } else if (ch == '$' && IsPhpWordStart(chNext)) { + state = SCE_HPHP_VARIABLE; + } else if (IsOperator(ch)) { + state = SCE_HPHP_OPERATOR; + } else if ((state == SCE_HPHP_OPERATOR) && (IsASpace(ch))) { + state = SCE_HPHP_DEFAULT; + } + break; + ///////////// end - PHP state handling + } + + // Some of the above terminated their lexeme but since the same character starts + // the same class again, only reenter if non empty segment. + + bool nonEmptySegment = i >= static_cast(styler.GetStartSegment()); + if (state == SCE_HB_DEFAULT) { // One of the above succeeded + if ((ch == '\"') && (nonEmptySegment)) { + state = SCE_HB_STRING; + } else if (ch == '\'') { + state = SCE_HB_COMMENTLINE; + } else if (IsAWordStart(ch)) { + state = SCE_HB_WORD; + } else if (IsOperator(ch)) { + styler.ColourTo(i, SCE_HB_DEFAULT); + } + } else if (state == SCE_HBA_DEFAULT) { // One of the above succeeded + if ((ch == '\"') && (nonEmptySegment)) { + state = SCE_HBA_STRING; + } else if (ch == '\'') { + state = SCE_HBA_COMMENTLINE; + } else if (IsAWordStart(ch)) { + state = SCE_HBA_WORD; + } else if (IsOperator(ch)) { + styler.ColourTo(i, SCE_HBA_DEFAULT); + } + } else if (state == SCE_HJ_DEFAULT) { // One of the above succeeded + if (ch == '/' && chNext == '*') { + if (styler.SafeGetCharAt(i + 2) == '*') + state = SCE_HJ_COMMENTDOC; + else + state = SCE_HJ_COMMENT; + } else if (ch == '/' && chNext == '/') { + state = SCE_HJ_COMMENTLINE; + } else if ((ch == '\"') && (nonEmptySegment)) { + state = SCE_HJ_DOUBLESTRING; + } else if ((ch == '\'') && (nonEmptySegment)) { + state = SCE_HJ_SINGLESTRING; + } else if (IsAWordStart(ch)) { + state = SCE_HJ_WORD; + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); + } + } + } + + switch (state) { + case SCE_HJ_WORD: + classifyWordHTJS(styler.GetStartSegment(), lengthDoc - 1, keywords2, styler, inScriptType); + break; + case SCE_HB_WORD: + classifyWordHTVB(styler.GetStartSegment(), lengthDoc - 1, keywords3, styler, inScriptType); + break; + case SCE_HP_WORD: + classifyWordHTPy(styler.GetStartSegment(), lengthDoc - 1, keywords4, styler, prevWord, inScriptType, isMako); + break; + case SCE_HPHP_WORD: + classifyWordHTPHP(styler.GetStartSegment(), lengthDoc - 1, keywords5, styler); + break; + default: + StateToPrint = statePrintForState(state, inScriptType); + styler.ColourTo(lengthDoc - 1, StateToPrint); + break; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + if (fold) { + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); + } +} + +static void ColouriseXMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + // Passing in true because we're lexing XML + ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, true); +} + +static void ColouriseHTMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + // Passing in false because we're notlexing XML + ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, false); +} + +static void ColourisePHPScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + if (startPos == 0) + initStyle = SCE_HPHP_DEFAULT; + ColouriseHTMLDoc(startPos, length, initStyle, keywordlists, styler); +} + +static const char * const htmlWordListDesc[] = { + "HTML elements and attributes", + "JavaScript keywords", + "VBScript keywords", + "Python keywords", + "PHP keywords", + "SGML and DTD keywords", + 0, +}; + +static const char * const phpscriptWordListDesc[] = { + "", //Unused + "", //Unused + "", //Unused + "", //Unused + "PHP keywords", + "", //Unused + 0, +}; + +LexerModule lmHTML(SCLEX_HTML, ColouriseHTMLDoc, "hypertext", 0, htmlWordListDesc, 8); +LexerModule lmXML(SCLEX_XML, ColouriseXMLDoc, "xml", 0, htmlWordListDesc, 8); +LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc, 8); diff --git a/scintilla/lexers/LexHaskell.cxx b/ThirdLibs/scintilla/lexers/LexHaskell.cxx similarity index 96% rename from scintilla/lexers/LexHaskell.cxx rename to ThirdLibs/scintilla/lexers/LexHaskell.cxx index a4bc2e11..37d85d0c 100644 --- a/scintilla/lexers/LexHaskell.cxx +++ b/ThirdLibs/scintilla/lexers/LexHaskell.cxx @@ -1,368 +1,368 @@ -/****************************************************************** - * LexHaskell.cxx - * - * A haskell lexer for the scintilla code control. - * Some stuff "lended" from LexPython.cxx and LexCPP.cxx. - * External lexer stuff inspired from the caml external lexer. - * - * Written by Tobias Engvall - tumm at dtek dot chalmers dot se - * - * Several bug fixes by Krasimir Angelov - kr.angelov at gmail.com - * - * TODO: - * * Implement a folder :) - * * Nice Character-lexing (stuff inside '\''), LexPython has - * this. - * - * - *****************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "PropSetSimple.h" -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#ifdef BUILD_AS_EXTERNAL_LEXER - -#include "ExternalLexer.h" -#include "WindowAccessor.h" - -#define BUILD_EXTERNAL_LEXER 0 - -#endif - -#define HA_MODE_DEFAULT 0 -#define HA_MODE_IMPORT1 1 -#define HA_MODE_IMPORT2 2 -#define HA_MODE_IMPORT3 3 -#define HA_MODE_MODULE 4 -#define HA_MODE_FFI 5 -#define HA_MODE_TYPE 6 - -static inline bool IsNewline(const int ch) { - return (ch == '\n' || ch == '\r'); -} - -static inline bool IsWhitespace(const int ch) { - return ( ch == ' ' - || ch == '\t' - || IsNewline(ch) ); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''); -} - -static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &ffi = *keywordlists[1]; - - StyleContext sc(startPos, length, initStyle, styler); - - int lineCurrent = styler.GetLine(startPos); - int state = lineCurrent ? styler.GetLineState(lineCurrent-1) - : HA_MODE_DEFAULT; - int mode = state & 0xF; - int xmode = state >> 4; - - while (sc.More()) { - // Check for state end - - // Operator - if (sc.state == SCE_HA_OPERATOR) { - if (isascii(sc.ch) && isoperator(static_cast(sc.ch))) { - sc.Forward(); - } else { - styler.ColourTo(sc.currentPos - 1, sc.state); - sc.ChangeState(SCE_HA_DEFAULT); - } - } - // String - else if (sc.state == SCE_HA_STRING) { - if (sc.ch == '\"') { - sc.Forward(); - styler.ColourTo(sc.currentPos-1, sc.state); - sc.ChangeState(SCE_HA_DEFAULT); - } else if (sc.ch == '\\') { - sc.Forward(2); - } else if (sc.atLineEnd) { - styler.ColourTo(sc.currentPos-1, sc.state); - sc.ChangeState(SCE_HA_DEFAULT); - } else { - sc.Forward(); - } - } - // Char - else if (sc.state == SCE_HA_CHARACTER) { - if (sc.ch == '\'') { - sc.Forward(); - styler.ColourTo(sc.currentPos-1, sc.state); - sc.ChangeState(SCE_HA_DEFAULT); - } else if (sc.ch == '\\') { - sc.Forward(2); - } else if (sc.atLineEnd) { - styler.ColourTo(sc.currentPos-1, sc.state); - sc.ChangeState(SCE_HA_DEFAULT); - } else { - sc.Forward(); - } - } - // Number - else if (sc.state == SCE_HA_NUMBER) { - if (IsADigit(sc.ch, xmode)) { - sc.Forward(); - } else if ((xmode == 10) && - (sc.ch == 'e' || sc.ch == 'E') && - (IsADigit(sc.chNext) || sc.chNext == '+' || sc.chNext == '-')) { - sc.Forward(); - if (sc.ch == '+' || sc.ch == '-') - sc.Forward(); - } else { - styler.ColourTo(sc.currentPos - 1, sc.state); - sc.ChangeState(SCE_HA_DEFAULT); - } - } - // Identifier - else if (sc.state == SCE_HA_IDENTIFIER) { - if (IsAWordChar(sc.ch)) { - sc.Forward(); - } else { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - int style = sc.state; - int new_mode = 0; - if (keywords.InList(s)) { - style = SCE_HA_KEYWORD; - } else if (isupper(s[0])) { - if (mode >= HA_MODE_IMPORT1 && mode <= HA_MODE_IMPORT3) { - style = SCE_HA_MODULE; - new_mode = HA_MODE_IMPORT2; - } else if (mode == HA_MODE_MODULE) - style = SCE_HA_MODULE; - else - style = SCE_HA_CAPITAL; - } else if (mode == HA_MODE_IMPORT1 && - strcmp(s,"qualified") == 0) { - style = SCE_HA_KEYWORD; - new_mode = HA_MODE_IMPORT1; - } else if (mode == HA_MODE_IMPORT2) { - if (strcmp(s,"as") == 0) { - style = SCE_HA_KEYWORD; - new_mode = HA_MODE_IMPORT3; - } else if (strcmp(s,"hiding") == 0) { - style = SCE_HA_KEYWORD; - } - } else if (mode == HA_MODE_FFI) { - if (ffi.InList(s)) { - style = SCE_HA_KEYWORD; - new_mode = HA_MODE_FFI; - } - } - else if (mode == HA_MODE_TYPE) { - if (strcmp(s,"family") == 0) - style = SCE_HA_KEYWORD; - } - styler.ColourTo(sc.currentPos - 1, style); - if (strcmp(s,"import") == 0 && mode != HA_MODE_FFI) - new_mode = HA_MODE_IMPORT1; - else if (strcmp(s,"module") == 0) - new_mode = HA_MODE_MODULE; - else if (strcmp(s,"foreign") == 0) - new_mode = HA_MODE_FFI; - else if (strcmp(s,"type") == 0) - new_mode = HA_MODE_TYPE; - sc.ChangeState(SCE_HA_DEFAULT); - mode = new_mode; - } - } - - // Comments - // Oneliner - else if (sc.state == SCE_HA_COMMENTLINE) { - if (sc.atLineEnd) { - styler.ColourTo(sc.currentPos - 1, sc.state); - sc.ChangeState(SCE_HA_DEFAULT); - } else { - sc.Forward(); - } - } - // Nested - else if (sc.state == SCE_HA_COMMENTBLOCK) { - if (sc.Match("{-")) { - sc.Forward(2); - xmode++; - } - else if (sc.Match("-}")) { - sc.Forward(2); - xmode--; - if (xmode == 0) { - styler.ColourTo(sc.currentPos - 1, sc.state); - sc.ChangeState(SCE_HA_DEFAULT); - } - } else { - if (sc.atLineEnd) { - // Remember the line state for future incremental lexing - styler.SetLineState(lineCurrent, (xmode << 4) | mode); - lineCurrent++; - } - sc.Forward(); - } - } - // New state? - if (sc.state == SCE_HA_DEFAULT) { - // Digit - if (IsADigit(sc.ch) || - (sc.ch == '.' && IsADigit(sc.chNext)) || - (sc.ch == '-' && IsADigit(sc.chNext))) { - styler.ColourTo(sc.currentPos - 1, sc.state); - sc.ChangeState(SCE_HA_NUMBER); - if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) { - // Match anything starting with "0x" or "0X", too - sc.Forward(2); - xmode = 16; - } else if (sc.ch == '0' && (sc.chNext == 'O' || sc.chNext == 'o')) { - // Match anything starting with "0x" or "0X", too - sc.Forward(2); - xmode = 8; - } else { - sc.Forward(); - xmode = 10; - } - mode = HA_MODE_DEFAULT; - } - // Comment line - else if (sc.Match("--")) { - styler.ColourTo(sc.currentPos - 1, sc.state); - sc.Forward(2); - sc.ChangeState(SCE_HA_COMMENTLINE); - // Comment block - } - else if (sc.Match("{-")) { - styler.ColourTo(sc.currentPos - 1, sc.state); - sc.Forward(2); - sc.ChangeState(SCE_HA_COMMENTBLOCK); - xmode = 1; - } - // String - else if (sc.Match('\"')) { - styler.ColourTo(sc.currentPos - 1, sc.state); - sc.Forward(); - sc.ChangeState(SCE_HA_STRING); - } - // Character - else if (sc.Match('\'')) { - styler.ColourTo(sc.currentPos - 1, sc.state); - sc.Forward(); - sc.ChangeState(SCE_HA_CHARACTER); - } - else if (sc.ch == '(' || sc.ch == ')' || - sc.ch == '{' || sc.ch == '}' || - sc.ch == '[' || sc.ch == ']') { - styler.ColourTo(sc.currentPos - 1, sc.state); - sc.Forward(); - styler.ColourTo(sc.currentPos - 1, SCE_HA_OPERATOR); - mode = HA_MODE_DEFAULT; - } - // Operator - else if (isascii(sc.ch) && isoperator(static_cast(sc.ch))) { - styler.ColourTo(sc.currentPos - 1, sc.state); - sc.Forward(); - sc.ChangeState(SCE_HA_OPERATOR); - mode = HA_MODE_DEFAULT; - } - // Keyword - else if (IsAWordStart(sc.ch)) { - styler.ColourTo(sc.currentPos - 1, sc.state); - sc.Forward(); - sc.ChangeState(SCE_HA_IDENTIFIER); - } else { - if (sc.atLineEnd) { - // Remember the line state for future incremental lexing - styler.SetLineState(lineCurrent, (xmode << 4) | mode); - lineCurrent++; - } - sc.Forward(); - } - } - } - sc.Complete(); -} - -// External stuff - used for dynamic-loading, not implemented in wxStyledTextCtrl yet. -// Inspired by the caml external lexer - Credits to Robert Roessler - http://www.rftp.com -#ifdef BUILD_EXTERNAL_LEXER -static const char* LexerName = "haskell"; - -void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, int initStyle, - char *words[], WindowID window, char *props) -{ - PropSetSimple ps; - ps.SetMultiple(props); - WindowAccessor wa(window, ps); - - int nWL = 0; - for (; words[nWL]; nWL++) ; - WordList** wl = new WordList* [nWL + 1]; - int i = 0; - for (; iSet(words[i]); - } - wl[i] = 0; - - ColorizeHaskellDoc(startPos, length, initStyle, wl, wa); - wa.Flush(); - for (i=nWL-1;i>=0;i--) - delete wl[i]; - delete [] wl; -} - -void EXT_LEXER_DECL Fold (unsigned int lexer, unsigned int startPos, int length, int initStyle, - char *words[], WindowID window, char *props) -{ - -} - -int EXT_LEXER_DECL GetLexerCount() -{ - return 1; -} - -void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength) -{ - if (buflength > 0) { - buflength--; - int n = strlen(LexerName); - if (n > buflength) - n = buflength; - memcpy(name, LexerName, n), name[n] = '\0'; - } -} -#endif - -LexerModule lmHaskell(SCLEX_HASKELL, ColorizeHaskellDoc, "haskell"); +/****************************************************************** + * LexHaskell.cxx + * + * A haskell lexer for the scintilla code control. + * Some stuff "lended" from LexPython.cxx and LexCPP.cxx. + * External lexer stuff inspired from the caml external lexer. + * + * Written by Tobias Engvall - tumm at dtek dot chalmers dot se + * + * Several bug fixes by Krasimir Angelov - kr.angelov at gmail.com + * + * TODO: + * * Implement a folder :) + * * Nice Character-lexing (stuff inside '\''), LexPython has + * this. + * + * + *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#ifdef BUILD_AS_EXTERNAL_LEXER + +#include "ExternalLexer.h" +#include "WindowAccessor.h" + +#define BUILD_EXTERNAL_LEXER 0 + +#endif + +#define HA_MODE_DEFAULT 0 +#define HA_MODE_IMPORT1 1 +#define HA_MODE_IMPORT2 2 +#define HA_MODE_IMPORT3 3 +#define HA_MODE_MODULE 4 +#define HA_MODE_FFI 5 +#define HA_MODE_TYPE 6 + +static inline bool IsNewline(const int ch) { + return (ch == '\n' || ch == '\r'); +} + +static inline bool IsWhitespace(const int ch) { + return ( ch == ' ' + || ch == '\t' + || IsNewline(ch) ); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''); +} + +static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &ffi = *keywordlists[1]; + + StyleContext sc(startPos, length, initStyle, styler); + + int lineCurrent = styler.GetLine(startPos); + int state = lineCurrent ? styler.GetLineState(lineCurrent-1) + : HA_MODE_DEFAULT; + int mode = state & 0xF; + int xmode = state >> 4; + + while (sc.More()) { + // Check for state end + + // Operator + if (sc.state == SCE_HA_OPERATOR) { + if (isascii(sc.ch) && isoperator(static_cast(sc.ch))) { + sc.Forward(); + } else { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } + } + // String + else if (sc.state == SCE_HA_STRING) { + if (sc.ch == '\"') { + sc.Forward(); + styler.ColourTo(sc.currentPos-1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } else if (sc.ch == '\\') { + sc.Forward(2); + } else if (sc.atLineEnd) { + styler.ColourTo(sc.currentPos-1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } else { + sc.Forward(); + } + } + // Char + else if (sc.state == SCE_HA_CHARACTER) { + if (sc.ch == '\'') { + sc.Forward(); + styler.ColourTo(sc.currentPos-1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } else if (sc.ch == '\\') { + sc.Forward(2); + } else if (sc.atLineEnd) { + styler.ColourTo(sc.currentPos-1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } else { + sc.Forward(); + } + } + // Number + else if (sc.state == SCE_HA_NUMBER) { + if (IsADigit(sc.ch, xmode)) { + sc.Forward(); + } else if ((xmode == 10) && + (sc.ch == 'e' || sc.ch == 'E') && + (IsADigit(sc.chNext) || sc.chNext == '+' || sc.chNext == '-')) { + sc.Forward(); + if (sc.ch == '+' || sc.ch == '-') + sc.Forward(); + } else { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } + } + // Identifier + else if (sc.state == SCE_HA_IDENTIFIER) { + if (IsAWordChar(sc.ch)) { + sc.Forward(); + } else { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + int style = sc.state; + int new_mode = 0; + if (keywords.InList(s)) { + style = SCE_HA_KEYWORD; + } else if (isupper(s[0])) { + if (mode >= HA_MODE_IMPORT1 && mode <= HA_MODE_IMPORT3) { + style = SCE_HA_MODULE; + new_mode = HA_MODE_IMPORT2; + } else if (mode == HA_MODE_MODULE) + style = SCE_HA_MODULE; + else + style = SCE_HA_CAPITAL; + } else if (mode == HA_MODE_IMPORT1 && + strcmp(s,"qualified") == 0) { + style = SCE_HA_KEYWORD; + new_mode = HA_MODE_IMPORT1; + } else if (mode == HA_MODE_IMPORT2) { + if (strcmp(s,"as") == 0) { + style = SCE_HA_KEYWORD; + new_mode = HA_MODE_IMPORT3; + } else if (strcmp(s,"hiding") == 0) { + style = SCE_HA_KEYWORD; + } + } else if (mode == HA_MODE_FFI) { + if (ffi.InList(s)) { + style = SCE_HA_KEYWORD; + new_mode = HA_MODE_FFI; + } + } + else if (mode == HA_MODE_TYPE) { + if (strcmp(s,"family") == 0) + style = SCE_HA_KEYWORD; + } + styler.ColourTo(sc.currentPos - 1, style); + if (strcmp(s,"import") == 0 && mode != HA_MODE_FFI) + new_mode = HA_MODE_IMPORT1; + else if (strcmp(s,"module") == 0) + new_mode = HA_MODE_MODULE; + else if (strcmp(s,"foreign") == 0) + new_mode = HA_MODE_FFI; + else if (strcmp(s,"type") == 0) + new_mode = HA_MODE_TYPE; + sc.ChangeState(SCE_HA_DEFAULT); + mode = new_mode; + } + } + + // Comments + // Oneliner + else if (sc.state == SCE_HA_COMMENTLINE) { + if (sc.atLineEnd) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } else { + sc.Forward(); + } + } + // Nested + else if (sc.state == SCE_HA_COMMENTBLOCK) { + if (sc.Match("{-")) { + sc.Forward(2); + xmode++; + } + else if (sc.Match("-}")) { + sc.Forward(2); + xmode--; + if (xmode == 0) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } + } else { + if (sc.atLineEnd) { + // Remember the line state for future incremental lexing + styler.SetLineState(lineCurrent, (xmode << 4) | mode); + lineCurrent++; + } + sc.Forward(); + } + } + // New state? + if (sc.state == SCE_HA_DEFAULT) { + // Digit + if (IsADigit(sc.ch) || + (sc.ch == '.' && IsADigit(sc.chNext)) || + (sc.ch == '-' && IsADigit(sc.chNext))) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.ChangeState(SCE_HA_NUMBER); + if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) { + // Match anything starting with "0x" or "0X", too + sc.Forward(2); + xmode = 16; + } else if (sc.ch == '0' && (sc.chNext == 'O' || sc.chNext == 'o')) { + // Match anything starting with "0x" or "0X", too + sc.Forward(2); + xmode = 8; + } else { + sc.Forward(); + xmode = 10; + } + mode = HA_MODE_DEFAULT; + } + // Comment line + else if (sc.Match("--")) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(2); + sc.ChangeState(SCE_HA_COMMENTLINE); + // Comment block + } + else if (sc.Match("{-")) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(2); + sc.ChangeState(SCE_HA_COMMENTBLOCK); + xmode = 1; + } + // String + else if (sc.Match('\"')) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(); + sc.ChangeState(SCE_HA_STRING); + } + // Character + else if (sc.Match('\'')) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(); + sc.ChangeState(SCE_HA_CHARACTER); + } + else if (sc.ch == '(' || sc.ch == ')' || + sc.ch == '{' || sc.ch == '}' || + sc.ch == '[' || sc.ch == ']') { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(); + styler.ColourTo(sc.currentPos - 1, SCE_HA_OPERATOR); + mode = HA_MODE_DEFAULT; + } + // Operator + else if (isascii(sc.ch) && isoperator(static_cast(sc.ch))) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(); + sc.ChangeState(SCE_HA_OPERATOR); + mode = HA_MODE_DEFAULT; + } + // Keyword + else if (IsAWordStart(sc.ch)) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(); + sc.ChangeState(SCE_HA_IDENTIFIER); + } else { + if (sc.atLineEnd) { + // Remember the line state for future incremental lexing + styler.SetLineState(lineCurrent, (xmode << 4) | mode); + lineCurrent++; + } + sc.Forward(); + } + } + } + sc.Complete(); +} + +// External stuff - used for dynamic-loading, not implemented in wxStyledTextCtrl yet. +// Inspired by the caml external lexer - Credits to Robert Roessler - http://www.rftp.com +#ifdef BUILD_EXTERNAL_LEXER +static const char* LexerName = "haskell"; + +void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, int initStyle, + char *words[], WindowID window, char *props) +{ + PropSetSimple ps; + ps.SetMultiple(props); + WindowAccessor wa(window, ps); + + int nWL = 0; + for (; words[nWL]; nWL++) ; + WordList** wl = new WordList* [nWL + 1]; + int i = 0; + for (; iSet(words[i]); + } + wl[i] = 0; + + ColorizeHaskellDoc(startPos, length, initStyle, wl, wa); + wa.Flush(); + for (i=nWL-1;i>=0;i--) + delete wl[i]; + delete [] wl; +} + +void EXT_LEXER_DECL Fold (unsigned int lexer, unsigned int startPos, int length, int initStyle, + char *words[], WindowID window, char *props) +{ + +} + +int EXT_LEXER_DECL GetLexerCount() +{ + return 1; +} + +void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength) +{ + if (buflength > 0) { + buflength--; + int n = strlen(LexerName); + if (n > buflength) + n = buflength; + memcpy(name, LexerName, n), name[n] = '\0'; + } +} +#endif + +LexerModule lmHaskell(SCLEX_HASKELL, ColorizeHaskellDoc, "haskell"); diff --git a/scintilla/lexers/LexInno.cxx b/ThirdLibs/scintilla/lexers/LexInno.cxx similarity index 96% rename from scintilla/lexers/LexInno.cxx rename to ThirdLibs/scintilla/lexers/LexInno.cxx index 117160d1..a0f5b327 100644 --- a/scintilla/lexers/LexInno.cxx +++ b/ThirdLibs/scintilla/lexers/LexInno.cxx @@ -1,290 +1,290 @@ -// Scintilla source code edit control -/** @file LexInno.cxx - ** Lexer for Inno Setup scripts. - **/ -// Written by Friedrich Vedder , using code from LexOthers.cxx. -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) { - int state = SCE_INNO_DEFAULT; - char chPrev; - char ch = 0; - char chNext = styler[startPos]; - int lengthDoc = startPos + length; - char *buffer = new char[length]; - int bufferCount = 0; - bool isBOL, isEOL, isWS, isBOLWS = 0; - bool isCStyleComment = false; - - WordList §ionKeywords = *keywordLists[0]; - WordList &standardKeywords = *keywordLists[1]; - WordList ¶meterKeywords = *keywordLists[2]; - WordList &preprocessorKeywords = *keywordLists[3]; - WordList &pascalKeywords = *keywordLists[4]; - WordList &userKeywords = *keywordLists[5]; - - int curLine = styler.GetLine(startPos); - int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : 0; - bool isCode = (curLineState == 1); - - // Go through all provided text segment - // using the hand-written state machine shown below - styler.StartAt(startPos); - styler.StartSegment(startPos); - for (int i = startPos; i < lengthDoc; i++) { - chPrev = ch; - ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - i++; - continue; - } - - isBOL = (chPrev == 0) || (chPrev == '\n') || (chPrev == '\r' && ch != '\n'); - isBOLWS = (isBOL) ? 1 : (isBOLWS && (chPrev == ' ' || chPrev == '\t')); - isEOL = (ch == '\n' || ch == '\r'); - isWS = (ch == ' ' || ch == '\t'); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { - // Remember the line state for future incremental lexing - curLine = styler.GetLine(i); - styler.SetLineState(curLine, (isCode ? 1 : 0)); - } - - switch(state) { - case SCE_INNO_DEFAULT: - if (!isCode && ch == ';' && isBOLWS) { - // Start of a comment - state = SCE_INNO_COMMENT; - } else if (ch == '[' && isBOLWS) { - // Start of a section name - bufferCount = 0; - state = SCE_INNO_SECTION; - } else if (ch == '#' && isBOLWS) { - // Start of a preprocessor directive - state = SCE_INNO_PREPROC; - } else if (!isCode && ch == '{' && chNext != '{' && chPrev != '{') { - // Start of an inline expansion - state = SCE_INNO_INLINE_EXPANSION; - } else if (isCode && (ch == '{' || (ch == '(' && chNext == '*'))) { - // Start of a Pascal comment - state = SCE_INNO_COMMENT_PASCAL; - isCStyleComment = false; - } else if (isCode && ch == '/' && chNext == '/') { - // Apparently, C-style comments are legal, too - state = SCE_INNO_COMMENT_PASCAL; - isCStyleComment = true; - } else if (ch == '"') { - // Start of a double-quote string - state = SCE_INNO_STRING_DOUBLE; - } else if (ch == '\'') { - // Start of a single-quote string - state = SCE_INNO_STRING_SINGLE; - } else if (isascii(ch) && (isalpha(ch) || (ch == '_'))) { - // Start of an identifier - bufferCount = 0; - buffer[bufferCount++] = static_cast(tolower(ch)); - state = SCE_INNO_IDENTIFIER; - } else { - // Style it the default style - styler.ColourTo(i,SCE_INNO_DEFAULT); - } - break; - - case SCE_INNO_COMMENT: - if (isEOL) { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_COMMENT); - } - break; - - case SCE_INNO_IDENTIFIER: - if (isascii(ch) && (isalnum(ch) || (ch == '_'))) { - buffer[bufferCount++] = static_cast(tolower(ch)); - } else { - state = SCE_INNO_DEFAULT; - buffer[bufferCount] = '\0'; - - // Check if the buffer contains a keyword - if (!isCode && standardKeywords.InList(buffer)) { - styler.ColourTo(i-1,SCE_INNO_KEYWORD); - } else if (!isCode && parameterKeywords.InList(buffer)) { - styler.ColourTo(i-1,SCE_INNO_PARAMETER); - } else if (isCode && pascalKeywords.InList(buffer)) { - styler.ColourTo(i-1,SCE_INNO_KEYWORD_PASCAL); - } else if (!isCode && userKeywords.InList(buffer)) { - styler.ColourTo(i-1,SCE_INNO_KEYWORD_USER); - } else { - styler.ColourTo(i-1,SCE_INNO_DEFAULT); - } - - // Push back the faulty character - chNext = styler[i--]; - ch = chPrev; - } - break; - - case SCE_INNO_SECTION: - if (ch == ']') { - state = SCE_INNO_DEFAULT; - buffer[bufferCount] = '\0'; - - // Check if the buffer contains a section name - if (sectionKeywords.InList(buffer)) { - styler.ColourTo(i,SCE_INNO_SECTION); - isCode = !CompareCaseInsensitive(buffer, "code"); - } else { - styler.ColourTo(i,SCE_INNO_DEFAULT); - } - } else if (isascii(ch) && (isalnum(ch) || (ch == '_'))) { - buffer[bufferCount++] = static_cast(tolower(ch)); - } else { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_DEFAULT); - } - break; - - case SCE_INNO_PREPROC: - if (isWS || isEOL) { - if (isascii(chPrev) && isalpha(chPrev)) { - state = SCE_INNO_DEFAULT; - buffer[bufferCount] = '\0'; - - // Check if the buffer contains a preprocessor directive - if (preprocessorKeywords.InList(buffer)) { - styler.ColourTo(i-1,SCE_INNO_PREPROC); - } else { - styler.ColourTo(i-1,SCE_INNO_DEFAULT); - } - - // Push back the faulty character - chNext = styler[i--]; - ch = chPrev; - } - } else if (isascii(ch) && isalpha(ch)) { - if (chPrev == '#' || chPrev == ' ' || chPrev == '\t') - bufferCount = 0; - buffer[bufferCount++] = static_cast(tolower(ch)); - } - break; - - case SCE_INNO_STRING_DOUBLE: - if (ch == '"' || isEOL) { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_STRING_DOUBLE); - } - break; - - case SCE_INNO_STRING_SINGLE: - if (ch == '\'' || isEOL) { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_STRING_SINGLE); - } - break; - - case SCE_INNO_INLINE_EXPANSION: - if (ch == '}') { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_INLINE_EXPANSION); - } else if (isEOL) { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_DEFAULT); - } - break; - - case SCE_INNO_COMMENT_PASCAL: - if (isCStyleComment) { - if (isEOL) { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL); - } - } else { - if (ch == '}' || (ch == ')' && chPrev == '*')) { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL); - } else if (isEOL) { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_DEFAULT); - } - } - break; - - } - } - delete []buffer; -} - -static const char * const innoWordListDesc[] = { - "Sections", - "Keywords", - "Parameters", - "Preprocessor directives", - "Pascal keywords", - "User defined keywords", - 0 -}; - -static void FoldInnoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - unsigned int endPos = startPos + length; - char chNext = styler[startPos]; - - int lineCurrent = styler.GetLine(startPos); - - bool sectionFlag = false; - int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) : SC_FOLDLEVELBASE; - int level; - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler[i+1]; - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - int style = styler.StyleAt(i); - - if (style == SCE_INNO_SECTION) - sectionFlag = true; - - if (atEOL || i == endPos - 1) { - if (sectionFlag) { - level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; - if (level == levelPrev) - styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG); - } else { - level = levelPrev & SC_FOLDLEVELNUMBERMASK; - if (levelPrev & SC_FOLDLEVELHEADERFLAG) - level++; - } - - styler.SetLevel(lineCurrent, level); - - levelPrev = level; - lineCurrent++; - sectionFlag = false; - } - } -} - -LexerModule lmInno(SCLEX_INNOSETUP, ColouriseInnoDoc, "inno", FoldInnoDoc, innoWordListDesc); +// Scintilla source code edit control +/** @file LexInno.cxx + ** Lexer for Inno Setup scripts. + **/ +// Written by Friedrich Vedder , using code from LexOthers.cxx. +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) { + int state = SCE_INNO_DEFAULT; + char chPrev; + char ch = 0; + char chNext = styler[startPos]; + int lengthDoc = startPos + length; + char *buffer = new char[length]; + int bufferCount = 0; + bool isBOL, isEOL, isWS, isBOLWS = 0; + bool isCStyleComment = false; + + WordList §ionKeywords = *keywordLists[0]; + WordList &standardKeywords = *keywordLists[1]; + WordList ¶meterKeywords = *keywordLists[2]; + WordList &preprocessorKeywords = *keywordLists[3]; + WordList &pascalKeywords = *keywordLists[4]; + WordList &userKeywords = *keywordLists[5]; + + int curLine = styler.GetLine(startPos); + int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : 0; + bool isCode = (curLineState == 1); + + // Go through all provided text segment + // using the hand-written state machine shown below + styler.StartAt(startPos); + styler.StartSegment(startPos); + for (int i = startPos; i < lengthDoc; i++) { + chPrev = ch; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + i++; + continue; + } + + isBOL = (chPrev == 0) || (chPrev == '\n') || (chPrev == '\r' && ch != '\n'); + isBOLWS = (isBOL) ? 1 : (isBOLWS && (chPrev == ' ' || chPrev == '\t')); + isEOL = (ch == '\n' || ch == '\r'); + isWS = (ch == ' ' || ch == '\t'); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Remember the line state for future incremental lexing + curLine = styler.GetLine(i); + styler.SetLineState(curLine, (isCode ? 1 : 0)); + } + + switch(state) { + case SCE_INNO_DEFAULT: + if (!isCode && ch == ';' && isBOLWS) { + // Start of a comment + state = SCE_INNO_COMMENT; + } else if (ch == '[' && isBOLWS) { + // Start of a section name + bufferCount = 0; + state = SCE_INNO_SECTION; + } else if (ch == '#' && isBOLWS) { + // Start of a preprocessor directive + state = SCE_INNO_PREPROC; + } else if (!isCode && ch == '{' && chNext != '{' && chPrev != '{') { + // Start of an inline expansion + state = SCE_INNO_INLINE_EXPANSION; + } else if (isCode && (ch == '{' || (ch == '(' && chNext == '*'))) { + // Start of a Pascal comment + state = SCE_INNO_COMMENT_PASCAL; + isCStyleComment = false; + } else if (isCode && ch == '/' && chNext == '/') { + // Apparently, C-style comments are legal, too + state = SCE_INNO_COMMENT_PASCAL; + isCStyleComment = true; + } else if (ch == '"') { + // Start of a double-quote string + state = SCE_INNO_STRING_DOUBLE; + } else if (ch == '\'') { + // Start of a single-quote string + state = SCE_INNO_STRING_SINGLE; + } else if (isascii(ch) && (isalpha(ch) || (ch == '_'))) { + // Start of an identifier + bufferCount = 0; + buffer[bufferCount++] = static_cast(tolower(ch)); + state = SCE_INNO_IDENTIFIER; + } else { + // Style it the default style + styler.ColourTo(i,SCE_INNO_DEFAULT); + } + break; + + case SCE_INNO_COMMENT: + if (isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_COMMENT); + } + break; + + case SCE_INNO_IDENTIFIER: + if (isascii(ch) && (isalnum(ch) || (ch == '_'))) { + buffer[bufferCount++] = static_cast(tolower(ch)); + } else { + state = SCE_INNO_DEFAULT; + buffer[bufferCount] = '\0'; + + // Check if the buffer contains a keyword + if (!isCode && standardKeywords.InList(buffer)) { + styler.ColourTo(i-1,SCE_INNO_KEYWORD); + } else if (!isCode && parameterKeywords.InList(buffer)) { + styler.ColourTo(i-1,SCE_INNO_PARAMETER); + } else if (isCode && pascalKeywords.InList(buffer)) { + styler.ColourTo(i-1,SCE_INNO_KEYWORD_PASCAL); + } else if (!isCode && userKeywords.InList(buffer)) { + styler.ColourTo(i-1,SCE_INNO_KEYWORD_USER); + } else { + styler.ColourTo(i-1,SCE_INNO_DEFAULT); + } + + // Push back the faulty character + chNext = styler[i--]; + ch = chPrev; + } + break; + + case SCE_INNO_SECTION: + if (ch == ']') { + state = SCE_INNO_DEFAULT; + buffer[bufferCount] = '\0'; + + // Check if the buffer contains a section name + if (sectionKeywords.InList(buffer)) { + styler.ColourTo(i,SCE_INNO_SECTION); + isCode = !CompareCaseInsensitive(buffer, "code"); + } else { + styler.ColourTo(i,SCE_INNO_DEFAULT); + } + } else if (isascii(ch) && (isalnum(ch) || (ch == '_'))) { + buffer[bufferCount++] = static_cast(tolower(ch)); + } else { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_DEFAULT); + } + break; + + case SCE_INNO_PREPROC: + if (isWS || isEOL) { + if (isascii(chPrev) && isalpha(chPrev)) { + state = SCE_INNO_DEFAULT; + buffer[bufferCount] = '\0'; + + // Check if the buffer contains a preprocessor directive + if (preprocessorKeywords.InList(buffer)) { + styler.ColourTo(i-1,SCE_INNO_PREPROC); + } else { + styler.ColourTo(i-1,SCE_INNO_DEFAULT); + } + + // Push back the faulty character + chNext = styler[i--]; + ch = chPrev; + } + } else if (isascii(ch) && isalpha(ch)) { + if (chPrev == '#' || chPrev == ' ' || chPrev == '\t') + bufferCount = 0; + buffer[bufferCount++] = static_cast(tolower(ch)); + } + break; + + case SCE_INNO_STRING_DOUBLE: + if (ch == '"' || isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_STRING_DOUBLE); + } + break; + + case SCE_INNO_STRING_SINGLE: + if (ch == '\'' || isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_STRING_SINGLE); + } + break; + + case SCE_INNO_INLINE_EXPANSION: + if (ch == '}') { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_INLINE_EXPANSION); + } else if (isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_DEFAULT); + } + break; + + case SCE_INNO_COMMENT_PASCAL: + if (isCStyleComment) { + if (isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL); + } + } else { + if (ch == '}' || (ch == ')' && chPrev == '*')) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL); + } else if (isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_DEFAULT); + } + } + break; + + } + } + delete []buffer; +} + +static const char * const innoWordListDesc[] = { + "Sections", + "Keywords", + "Parameters", + "Preprocessor directives", + "Pascal keywords", + "User defined keywords", + 0 +}; + +static void FoldInnoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + unsigned int endPos = startPos + length; + char chNext = styler[startPos]; + + int lineCurrent = styler.GetLine(startPos); + + bool sectionFlag = false; + int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) : SC_FOLDLEVELBASE; + int level; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler[i+1]; + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + int style = styler.StyleAt(i); + + if (style == SCE_INNO_SECTION) + sectionFlag = true; + + if (atEOL || i == endPos - 1) { + if (sectionFlag) { + level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + if (level == levelPrev) + styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG); + } else { + level = levelPrev & SC_FOLDLEVELNUMBERMASK; + if (levelPrev & SC_FOLDLEVELHEADERFLAG) + level++; + } + + styler.SetLevel(lineCurrent, level); + + levelPrev = level; + lineCurrent++; + sectionFlag = false; + } + } +} + +LexerModule lmInno(SCLEX_INNOSETUP, ColouriseInnoDoc, "inno", FoldInnoDoc, innoWordListDesc); diff --git a/scintilla/lexers/LexKix.cxx b/ThirdLibs/scintilla/lexers/LexKix.cxx similarity index 96% rename from scintilla/lexers/LexKix.cxx rename to ThirdLibs/scintilla/lexers/LexKix.cxx index 2891f68a..32af263f 100644 --- a/scintilla/lexers/LexKix.cxx +++ b/ThirdLibs/scintilla/lexers/LexKix.cxx @@ -1,129 +1,129 @@ -// Scintilla source code edit control -/** @file LexKix.cxx - ** Lexer for KIX-Scripts. - **/ -// Copyright 2004 by Manfred Becker -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// Extended to accept accented characters -static inline bool IsAWordChar(int ch) { - return ch >= 0x80 || isalnum(ch) || ch == '_'; -} - -static inline bool IsOperator(const int ch) { - return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '&' || ch == '|' || ch == '<' || ch == '>' || ch == '='); -} - -static void ColouriseKixDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; -// WordList &keywords4 = *keywordlists[3]; - - styler.StartAt(startPos); - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.state == SCE_KIX_COMMENT) { - if (sc.atLineEnd) { - sc.SetState(SCE_KIX_DEFAULT); - } - } else if (sc.state == SCE_KIX_STRING1) { - // This is a doubles quotes string - if (sc.ch == '\"') { - sc.ForwardSetState(SCE_KIX_DEFAULT); - } - } else if (sc.state == SCE_KIX_STRING2) { - // This is a single quote string - if (sc.ch == '\'') { - sc.ForwardSetState(SCE_KIX_DEFAULT); - } - } else if (sc.state == SCE_KIX_NUMBER) { - if (!IsADigit(sc.ch)) { - sc.SetState(SCE_KIX_DEFAULT); - } - } else if (sc.state == SCE_KIX_VAR) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_KIX_DEFAULT); - } - } else if (sc.state == SCE_KIX_MACRO) { - if (!IsAWordChar(sc.ch) && !IsADigit(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - - if (!keywords3.InList(&s[1])) { - sc.ChangeState(SCE_KIX_DEFAULT); - } - sc.SetState(SCE_KIX_DEFAULT); - } - } else if (sc.state == SCE_KIX_OPERATOR) { - if (!IsOperator(sc.ch)) { - sc.SetState(SCE_KIX_DEFAULT); - } - } else if (sc.state == SCE_KIX_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - - if (keywords.InList(s)) { - sc.ChangeState(SCE_KIX_KEYWORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_KIX_FUNCTIONS); - } - sc.SetState(SCE_KIX_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_KIX_DEFAULT) { - if (sc.ch == ';') { - sc.SetState(SCE_KIX_COMMENT); - } else if (sc.ch == '\"') { - sc.SetState(SCE_KIX_STRING1); - } else if (sc.ch == '\'') { - sc.SetState(SCE_KIX_STRING2); - } else if (sc.ch == '$') { - sc.SetState(SCE_KIX_VAR); - } else if (sc.ch == '@') { - sc.SetState(SCE_KIX_MACRO); - } else if (IsADigit(sc.ch) || ((sc.ch == '.' || sc.ch == '&') && IsADigit(sc.chNext))) { - sc.SetState(SCE_KIX_NUMBER); - } else if (IsOperator(sc.ch)) { - sc.SetState(SCE_KIX_OPERATOR); - } else if (IsAWordChar(sc.ch)) { - sc.SetState(SCE_KIX_IDENTIFIER); - } - } - } - sc.Complete(); -} - - -LexerModule lmKix(SCLEX_KIX, ColouriseKixDoc, "kix"); - +// Scintilla source code edit control +/** @file LexKix.cxx + ** Lexer for KIX-Scripts. + **/ +// Copyright 2004 by Manfred Becker +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// Extended to accept accented characters +static inline bool IsAWordChar(int ch) { + return ch >= 0x80 || isalnum(ch) || ch == '_'; +} + +static inline bool IsOperator(const int ch) { + return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '&' || ch == '|' || ch == '<' || ch == '>' || ch == '='); +} + +static void ColouriseKixDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; +// WordList &keywords4 = *keywordlists[3]; + + styler.StartAt(startPos); + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.state == SCE_KIX_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_STRING1) { + // This is a doubles quotes string + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_STRING2) { + // This is a single quote string + if (sc.ch == '\'') { + sc.ForwardSetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_NUMBER) { + if (!IsADigit(sc.ch)) { + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_VAR) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_MACRO) { + if (!IsAWordChar(sc.ch) && !IsADigit(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if (!keywords3.InList(&s[1])) { + sc.ChangeState(SCE_KIX_DEFAULT); + } + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_OPERATOR) { + if (!IsOperator(sc.ch)) { + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if (keywords.InList(s)) { + sc.ChangeState(SCE_KIX_KEYWORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_KIX_FUNCTIONS); + } + sc.SetState(SCE_KIX_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_KIX_DEFAULT) { + if (sc.ch == ';') { + sc.SetState(SCE_KIX_COMMENT); + } else if (sc.ch == '\"') { + sc.SetState(SCE_KIX_STRING1); + } else if (sc.ch == '\'') { + sc.SetState(SCE_KIX_STRING2); + } else if (sc.ch == '$') { + sc.SetState(SCE_KIX_VAR); + } else if (sc.ch == '@') { + sc.SetState(SCE_KIX_MACRO); + } else if (IsADigit(sc.ch) || ((sc.ch == '.' || sc.ch == '&') && IsADigit(sc.chNext))) { + sc.SetState(SCE_KIX_NUMBER); + } else if (IsOperator(sc.ch)) { + sc.SetState(SCE_KIX_OPERATOR); + } else if (IsAWordChar(sc.ch)) { + sc.SetState(SCE_KIX_IDENTIFIER); + } + } + } + sc.Complete(); +} + + +LexerModule lmKix(SCLEX_KIX, ColouriseKixDoc, "kix"); + diff --git a/scintilla/lexers/LexLisp.cxx b/ThirdLibs/scintilla/lexers/LexLisp.cxx similarity index 96% rename from scintilla/lexers/LexLisp.cxx rename to ThirdLibs/scintilla/lexers/LexLisp.cxx index 884abfab..08f765ad 100644 --- a/scintilla/lexers/LexLisp.cxx +++ b/ThirdLibs/scintilla/lexers/LexLisp.cxx @@ -1,285 +1,285 @@ -// Scintilla source code edit control -/** @file LexLisp.cxx - ** Lexer for Lisp. - ** Written by Alexey Yutkin. - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#define SCE_LISP_CHARACTER 29 -#define SCE_LISP_MACRO 30 -#define SCE_LISP_MACRO_DISPATCH 31 - -static inline bool isLispoperator(char ch) { - if (isascii(ch) && isalnum(ch)) - return false; - if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}') - return true; - return false; -} - -static inline bool isLispwordstart(char ch) { - return isascii(ch) && ch != ';' && !isspacechar(ch) && !isLispoperator(ch) && - ch != '\n' && ch != '\r' && ch != '\"'; -} - - -static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) { - assert(end >= start); - char s[100]; - unsigned int i; - bool digit_flag = true; - for (i = 0; (i < end - start + 1) && (i < 99); i++) { - s[i] = styler[start + i]; - s[i + 1] = '\0'; - if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false; - } - char chAttr = SCE_LISP_IDENTIFIER; - - if(digit_flag) chAttr = SCE_LISP_NUMBER; - else { - if (keywords.InList(s)) { - chAttr = SCE_LISP_KEYWORD; - } else if (keywords_kw.InList(s)) { - chAttr = SCE_LISP_KEYWORD_KW; - } else if ((s[0] == '*' && s[i-1] == '*') || - (s[0] == '+' && s[i-1] == '+')) { - chAttr = SCE_LISP_SPECIAL; - } - } - styler.ColourTo(end, chAttr); - return; -} - - -static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords_kw = *keywordlists[1]; - - styler.StartAt(startPos); - - int state = initStyle, radix = -1; - char chNext = styler[startPos]; - unsigned int lengthDoc = startPos + length; - styler.StartSegment(startPos); - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - i += 1; - continue; - } - - if (state == SCE_LISP_DEFAULT) { - if (ch == '#') { - styler.ColourTo(i - 1, state); - radix = -1; - state = SCE_LISP_MACRO_DISPATCH; - } else if (ch == ':' && isLispwordstart(chNext)) { - styler.ColourTo(i - 1, state); - state = SCE_LISP_SYMBOL; - } else if (isLispwordstart(ch)) { - styler.ColourTo(i - 1, state); - state = SCE_LISP_IDENTIFIER; - } - else if (ch == ';') { - styler.ColourTo(i - 1, state); - state = SCE_LISP_COMMENT; - } - else if (isLispoperator(ch) || ch=='\'') { - styler.ColourTo(i - 1, state); - styler.ColourTo(i, SCE_LISP_OPERATOR); - if (ch=='\'' && isLispwordstart(chNext)) { - state = SCE_LISP_SYMBOL; - } - } - else if (ch == '\"') { - styler.ColourTo(i - 1, state); - state = SCE_LISP_STRING; - } - } else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) { - if (!isLispwordstart(ch)) { - if (state == SCE_LISP_IDENTIFIER) { - classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler); - } else { - styler.ColourTo(i - 1, state); - } - state = SCE_LISP_DEFAULT; - } /*else*/ - if (isLispoperator(ch) || ch=='\'') { - styler.ColourTo(i - 1, state); - styler.ColourTo(i, SCE_LISP_OPERATOR); - if (ch=='\'' && isLispwordstart(chNext)) { - state = SCE_LISP_SYMBOL; - } - } - } else if (state == SCE_LISP_MACRO_DISPATCH) { - if (!(isascii(ch) && isdigit(ch))) { - if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) { - state = SCE_LISP_DEFAULT; - } else { - switch (ch) { - case '|': state = SCE_LISP_MULTI_COMMENT; break; - case 'o': - case 'O': radix = 8; state = SCE_LISP_MACRO; break; - case 'x': - case 'X': radix = 16; state = SCE_LISP_MACRO; break; - case 'b': - case 'B': radix = 2; state = SCE_LISP_MACRO; break; - case '\\': state = SCE_LISP_CHARACTER; break; - case ':': - case '-': - case '+': state = SCE_LISP_MACRO; break; - case '\'': if (isLispwordstart(chNext)) { - state = SCE_LISP_SPECIAL; - } else { - styler.ColourTo(i - 1, SCE_LISP_DEFAULT); - styler.ColourTo(i, SCE_LISP_OPERATOR); - state = SCE_LISP_DEFAULT; - } - break; - default: if (isLispoperator(ch)) { - styler.ColourTo(i - 1, SCE_LISP_DEFAULT); - styler.ColourTo(i, SCE_LISP_OPERATOR); - } - state = SCE_LISP_DEFAULT; - break; - } - } - } - } else if (state == SCE_LISP_MACRO) { - if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) { - state = SCE_LISP_SPECIAL; - } else { - state = SCE_LISP_DEFAULT; - } - } else if (state == SCE_LISP_CHARACTER) { - if (isLispoperator(ch)) { - styler.ColourTo(i, SCE_LISP_SPECIAL); - state = SCE_LISP_DEFAULT; - } else if (isLispwordstart(ch)) { - styler.ColourTo(i, SCE_LISP_SPECIAL); - state = SCE_LISP_SPECIAL; - } else { - state = SCE_LISP_DEFAULT; - } - } else if (state == SCE_LISP_SPECIAL) { - if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) { - styler.ColourTo(i - 1, state); - state = SCE_LISP_DEFAULT; - } - if (isLispoperator(ch) || ch=='\'') { - styler.ColourTo(i - 1, state); - styler.ColourTo(i, SCE_LISP_OPERATOR); - if (ch=='\'' && isLispwordstart(chNext)) { - state = SCE_LISP_SYMBOL; - } - } - } else { - if (state == SCE_LISP_COMMENT) { - if (atEOL) { - styler.ColourTo(i - 1, state); - state = SCE_LISP_DEFAULT; - } - } else if (state == SCE_LISP_MULTI_COMMENT) { - if (ch == '|' && chNext == '#') { - i++; - chNext = styler.SafeGetCharAt(i + 1); - styler.ColourTo(i, state); - state = SCE_LISP_DEFAULT; - } - } else if (state == SCE_LISP_STRING) { - if (ch == '\\') { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') { - i++; - chNext = styler.SafeGetCharAt(i + 1); - } - } else if (ch == '\"') { - styler.ColourTo(i, state); - state = SCE_LISP_DEFAULT; - } - } - } - - } - styler.ColourTo(lengthDoc - 1, state); -} - -static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[], - Accessor &styler) { - unsigned int lengthDoc = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (style == SCE_LISP_OPERATOR) { - if (ch == '(' || ch == '[' || ch == '{') { - levelCurrent++; - } else if (ch == ')' || ch == ']' || ch == '}') { - levelCurrent--; - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const lispWordListDesc[] = { - "Functions and special operators", - "Keywords", - 0 -}; - -LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc); +// Scintilla source code edit control +/** @file LexLisp.cxx + ** Lexer for Lisp. + ** Written by Alexey Yutkin. + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#define SCE_LISP_CHARACTER 29 +#define SCE_LISP_MACRO 30 +#define SCE_LISP_MACRO_DISPATCH 31 + +static inline bool isLispoperator(char ch) { + if (isascii(ch) && isalnum(ch)) + return false; + if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}') + return true; + return false; +} + +static inline bool isLispwordstart(char ch) { + return isascii(ch) && ch != ';' && !isspacechar(ch) && !isLispoperator(ch) && + ch != '\n' && ch != '\r' && ch != '\"'; +} + + +static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) { + assert(end >= start); + char s[100]; + unsigned int i; + bool digit_flag = true; + for (i = 0; (i < end - start + 1) && (i < 99); i++) { + s[i] = styler[start + i]; + s[i + 1] = '\0'; + if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false; + } + char chAttr = SCE_LISP_IDENTIFIER; + + if(digit_flag) chAttr = SCE_LISP_NUMBER; + else { + if (keywords.InList(s)) { + chAttr = SCE_LISP_KEYWORD; + } else if (keywords_kw.InList(s)) { + chAttr = SCE_LISP_KEYWORD_KW; + } else if ((s[0] == '*' && s[i-1] == '*') || + (s[0] == '+' && s[i-1] == '+')) { + chAttr = SCE_LISP_SPECIAL; + } + } + styler.ColourTo(end, chAttr); + return; +} + + +static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords_kw = *keywordlists[1]; + + styler.StartAt(startPos); + + int state = initStyle, radix = -1; + char chNext = styler[startPos]; + unsigned int lengthDoc = startPos + length; + styler.StartSegment(startPos); + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + i += 1; + continue; + } + + if (state == SCE_LISP_DEFAULT) { + if (ch == '#') { + styler.ColourTo(i - 1, state); + radix = -1; + state = SCE_LISP_MACRO_DISPATCH; + } else if (ch == ':' && isLispwordstart(chNext)) { + styler.ColourTo(i - 1, state); + state = SCE_LISP_SYMBOL; + } else if (isLispwordstart(ch)) { + styler.ColourTo(i - 1, state); + state = SCE_LISP_IDENTIFIER; + } + else if (ch == ';') { + styler.ColourTo(i - 1, state); + state = SCE_LISP_COMMENT; + } + else if (isLispoperator(ch) || ch=='\'') { + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_LISP_OPERATOR); + if (ch=='\'' && isLispwordstart(chNext)) { + state = SCE_LISP_SYMBOL; + } + } + else if (ch == '\"') { + styler.ColourTo(i - 1, state); + state = SCE_LISP_STRING; + } + } else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) { + if (!isLispwordstart(ch)) { + if (state == SCE_LISP_IDENTIFIER) { + classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler); + } else { + styler.ColourTo(i - 1, state); + } + state = SCE_LISP_DEFAULT; + } /*else*/ + if (isLispoperator(ch) || ch=='\'') { + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_LISP_OPERATOR); + if (ch=='\'' && isLispwordstart(chNext)) { + state = SCE_LISP_SYMBOL; + } + } + } else if (state == SCE_LISP_MACRO_DISPATCH) { + if (!(isascii(ch) && isdigit(ch))) { + if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) { + state = SCE_LISP_DEFAULT; + } else { + switch (ch) { + case '|': state = SCE_LISP_MULTI_COMMENT; break; + case 'o': + case 'O': radix = 8; state = SCE_LISP_MACRO; break; + case 'x': + case 'X': radix = 16; state = SCE_LISP_MACRO; break; + case 'b': + case 'B': radix = 2; state = SCE_LISP_MACRO; break; + case '\\': state = SCE_LISP_CHARACTER; break; + case ':': + case '-': + case '+': state = SCE_LISP_MACRO; break; + case '\'': if (isLispwordstart(chNext)) { + state = SCE_LISP_SPECIAL; + } else { + styler.ColourTo(i - 1, SCE_LISP_DEFAULT); + styler.ColourTo(i, SCE_LISP_OPERATOR); + state = SCE_LISP_DEFAULT; + } + break; + default: if (isLispoperator(ch)) { + styler.ColourTo(i - 1, SCE_LISP_DEFAULT); + styler.ColourTo(i, SCE_LISP_OPERATOR); + } + state = SCE_LISP_DEFAULT; + break; + } + } + } + } else if (state == SCE_LISP_MACRO) { + if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) { + state = SCE_LISP_SPECIAL; + } else { + state = SCE_LISP_DEFAULT; + } + } else if (state == SCE_LISP_CHARACTER) { + if (isLispoperator(ch)) { + styler.ColourTo(i, SCE_LISP_SPECIAL); + state = SCE_LISP_DEFAULT; + } else if (isLispwordstart(ch)) { + styler.ColourTo(i, SCE_LISP_SPECIAL); + state = SCE_LISP_SPECIAL; + } else { + state = SCE_LISP_DEFAULT; + } + } else if (state == SCE_LISP_SPECIAL) { + if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) { + styler.ColourTo(i - 1, state); + state = SCE_LISP_DEFAULT; + } + if (isLispoperator(ch) || ch=='\'') { + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_LISP_OPERATOR); + if (ch=='\'' && isLispwordstart(chNext)) { + state = SCE_LISP_SYMBOL; + } + } + } else { + if (state == SCE_LISP_COMMENT) { + if (atEOL) { + styler.ColourTo(i - 1, state); + state = SCE_LISP_DEFAULT; + } + } else if (state == SCE_LISP_MULTI_COMMENT) { + if (ch == '|' && chNext == '#') { + i++; + chNext = styler.SafeGetCharAt(i + 1); + styler.ColourTo(i, state); + state = SCE_LISP_DEFAULT; + } + } else if (state == SCE_LISP_STRING) { + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + chNext = styler.SafeGetCharAt(i + 1); + } + } else if (ch == '\"') { + styler.ColourTo(i, state); + state = SCE_LISP_DEFAULT; + } + } + } + + } + styler.ColourTo(lengthDoc - 1, state); +} + +static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[], + Accessor &styler) { + unsigned int lengthDoc = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (style == SCE_LISP_OPERATOR) { + if (ch == '(' || ch == '[' || ch == '{') { + levelCurrent++; + } else if (ch == ')' || ch == ']' || ch == '}') { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const lispWordListDesc[] = { + "Functions and special operators", + "Keywords", + 0 +}; + +LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc); diff --git a/scintilla/lexers/LexLout.cxx b/ThirdLibs/scintilla/lexers/LexLout.cxx similarity index 96% rename from scintilla/lexers/LexLout.cxx rename to ThirdLibs/scintilla/lexers/LexLout.cxx index d81c7287..985b93b4 100644 --- a/scintilla/lexers/LexLout.cxx +++ b/ThirdLibs/scintilla/lexers/LexLout.cxx @@ -1,215 +1,215 @@ -// Scintilla source code edit control -/** @file LexLout.cxx - ** Lexer for the Basser Lout (>= version 3) typesetting language - **/ -// Copyright 2003 by Kein-Hong Man -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalpha(ch) || ch == '@' || ch == '_'); -} - -static inline bool IsAnOther(const int ch) { - return (ch < 0x80) && (ch == '{' || ch == '}' || - ch == '!' || ch == '$' || ch == '%' || ch == '&' || ch == '\'' || - ch == '(' || ch == ')' || ch == '*' || ch == '+' || ch == ',' || - ch == '-' || ch == '.' || ch == '/' || ch == ':' || ch == ';' || - ch == '<' || ch == '=' || ch == '>' || ch == '?' || ch == '[' || - ch == ']' || ch == '^' || ch == '`' || ch == '|' || ch == '~'); -} - -static void ColouriseLoutDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - - int visibleChars = 0; - int firstWordInLine = 0; - int leadingAtSign = 0; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.atLineStart && (sc.state == SCE_LOUT_STRING)) { - // Prevent SCE_LOUT_STRINGEOL from leaking back to previous line - sc.SetState(SCE_LOUT_STRING); - } - - // Determine if the current state should terminate. - if (sc.state == SCE_LOUT_COMMENT) { - if (sc.atLineEnd) { - sc.SetState(SCE_LOUT_DEFAULT); - visibleChars = 0; - } - } else if (sc.state == SCE_LOUT_NUMBER) { - if (!IsADigit(sc.ch) && sc.ch != '.') { - sc.SetState(SCE_LOUT_DEFAULT); - } - } else if (sc.state == SCE_LOUT_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_LOUT_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_LOUT_STRINGEOL); - sc.ForwardSetState(SCE_LOUT_DEFAULT); - visibleChars = 0; - } - } else if (sc.state == SCE_LOUT_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - - if (leadingAtSign) { - if (keywords.InList(s)) { - sc.ChangeState(SCE_LOUT_WORD); - } else { - sc.ChangeState(SCE_LOUT_WORD4); - } - } else if (firstWordInLine && keywords3.InList(s)) { - sc.ChangeState(SCE_LOUT_WORD3); - } - sc.SetState(SCE_LOUT_DEFAULT); - } - } else if (sc.state == SCE_LOUT_OPERATOR) { - if (!IsAnOther(sc.ch)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - - if (keywords2.InList(s)) { - sc.ChangeState(SCE_LOUT_WORD2); - } - sc.SetState(SCE_LOUT_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_LOUT_DEFAULT) { - if (sc.ch == '#') { - sc.SetState(SCE_LOUT_COMMENT); - } else if (sc.ch == '\"') { - sc.SetState(SCE_LOUT_STRING); - } else if (IsADigit(sc.ch) || - (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_LOUT_NUMBER); - } else if (IsAWordChar(sc.ch)) { - firstWordInLine = (visibleChars == 0); - leadingAtSign = (sc.ch == '@'); - sc.SetState(SCE_LOUT_IDENTIFIER); - } else if (IsAnOther(sc.ch)) { - sc.SetState(SCE_LOUT_OPERATOR); - } - } - - if (sc.atLineEnd) { - // Reset states to begining of colourise so no surprises - // if different sets of lines lexed. - visibleChars = 0; - } - if (!IsASpace(sc.ch)) { - visibleChars++; - } - } - sc.Complete(); -} - -static void FoldLoutDoc(unsigned int startPos, int length, int, WordList *[], - Accessor &styler) { - - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - int styleNext = styler.StyleAt(startPos); - char s[10]; - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if (style == SCE_LOUT_WORD) { - if (ch == '@') { - for (unsigned int j = 0; j < 8; j++) { - if (!IsAWordChar(styler[i + j])) { - break; - } - s[j] = styler[i + j]; - s[j + 1] = '\0'; - } - if (strcmp(s, "@Begin") == 0) { - levelCurrent++; - } else if (strcmp(s, "@End") == 0) { - levelCurrent--; - } - } - } else if (style == SCE_LOUT_OPERATOR) { - if (ch == '{') { - levelCurrent++; - } else if (ch == '}') { - levelCurrent--; - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) { - lev |= SC_FOLDLEVELWHITEFLAG; - } - if ((levelCurrent > levelPrev) && (visibleChars > 0)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const loutWordLists[] = { - "Predefined identifiers", - "Predefined delimiters", - "Predefined keywords", - 0, - }; - -LexerModule lmLout(SCLEX_LOUT, ColouriseLoutDoc, "lout", FoldLoutDoc, loutWordLists); +// Scintilla source code edit control +/** @file LexLout.cxx + ** Lexer for the Basser Lout (>= version 3) typesetting language + **/ +// Copyright 2003 by Kein-Hong Man +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalpha(ch) || ch == '@' || ch == '_'); +} + +static inline bool IsAnOther(const int ch) { + return (ch < 0x80) && (ch == '{' || ch == '}' || + ch == '!' || ch == '$' || ch == '%' || ch == '&' || ch == '\'' || + ch == '(' || ch == ')' || ch == '*' || ch == '+' || ch == ',' || + ch == '-' || ch == '.' || ch == '/' || ch == ':' || ch == ';' || + ch == '<' || ch == '=' || ch == '>' || ch == '?' || ch == '[' || + ch == ']' || ch == '^' || ch == '`' || ch == '|' || ch == '~'); +} + +static void ColouriseLoutDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + + int visibleChars = 0; + int firstWordInLine = 0; + int leadingAtSign = 0; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart && (sc.state == SCE_LOUT_STRING)) { + // Prevent SCE_LOUT_STRINGEOL from leaking back to previous line + sc.SetState(SCE_LOUT_STRING); + } + + // Determine if the current state should terminate. + if (sc.state == SCE_LOUT_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_LOUT_DEFAULT); + visibleChars = 0; + } + } else if (sc.state == SCE_LOUT_NUMBER) { + if (!IsADigit(sc.ch) && sc.ch != '.') { + sc.SetState(SCE_LOUT_DEFAULT); + } + } else if (sc.state == SCE_LOUT_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_LOUT_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_LOUT_STRINGEOL); + sc.ForwardSetState(SCE_LOUT_DEFAULT); + visibleChars = 0; + } + } else if (sc.state == SCE_LOUT_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + + if (leadingAtSign) { + if (keywords.InList(s)) { + sc.ChangeState(SCE_LOUT_WORD); + } else { + sc.ChangeState(SCE_LOUT_WORD4); + } + } else if (firstWordInLine && keywords3.InList(s)) { + sc.ChangeState(SCE_LOUT_WORD3); + } + sc.SetState(SCE_LOUT_DEFAULT); + } + } else if (sc.state == SCE_LOUT_OPERATOR) { + if (!IsAnOther(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + + if (keywords2.InList(s)) { + sc.ChangeState(SCE_LOUT_WORD2); + } + sc.SetState(SCE_LOUT_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_LOUT_DEFAULT) { + if (sc.ch == '#') { + sc.SetState(SCE_LOUT_COMMENT); + } else if (sc.ch == '\"') { + sc.SetState(SCE_LOUT_STRING); + } else if (IsADigit(sc.ch) || + (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_LOUT_NUMBER); + } else if (IsAWordChar(sc.ch)) { + firstWordInLine = (visibleChars == 0); + leadingAtSign = (sc.ch == '@'); + sc.SetState(SCE_LOUT_IDENTIFIER); + } else if (IsAnOther(sc.ch)) { + sc.SetState(SCE_LOUT_OPERATOR); + } + } + + if (sc.atLineEnd) { + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + } + if (!IsASpace(sc.ch)) { + visibleChars++; + } + } + sc.Complete(); +} + +static void FoldLoutDoc(unsigned int startPos, int length, int, WordList *[], + Accessor &styler) { + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + int styleNext = styler.StyleAt(startPos); + char s[10]; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (style == SCE_LOUT_WORD) { + if (ch == '@') { + for (unsigned int j = 0; j < 8; j++) { + if (!IsAWordChar(styler[i + j])) { + break; + } + s[j] = styler[i + j]; + s[j + 1] = '\0'; + } + if (strcmp(s, "@Begin") == 0) { + levelCurrent++; + } else if (strcmp(s, "@End") == 0) { + levelCurrent--; + } + } + } else if (style == SCE_LOUT_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) { + lev |= SC_FOLDLEVELWHITEFLAG; + } + if ((levelCurrent > levelPrev) && (visibleChars > 0)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const loutWordLists[] = { + "Predefined identifiers", + "Predefined delimiters", + "Predefined keywords", + 0, + }; + +LexerModule lmLout(SCLEX_LOUT, ColouriseLoutDoc, "lout", FoldLoutDoc, loutWordLists); diff --git a/scintilla/lexers/LexLua.cxx b/ThirdLibs/scintilla/lexers/LexLua.cxx similarity index 96% rename from scintilla/lexers/LexLua.cxx rename to ThirdLibs/scintilla/lexers/LexLua.cxx index 1205725c..9e48efcd 100644 --- a/scintilla/lexers/LexLua.cxx +++ b/ThirdLibs/scintilla/lexers/LexLua.cxx @@ -1,453 +1,453 @@ -// Scintilla source code edit control -/** @file LexLua.cxx - ** Lexer for Lua language. - ** - ** Written by Paul Winwood. - ** Folder by Alexey Yutkin. - ** Modified by Marcos E. Wurzius & Philippe Lhoste - **/ - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ], -// return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on. -// The maximum number of '=' characters allowed is 254. -static int LongDelimCheck(StyleContext &sc) { - int sep = 1; - while (sc.GetRelative(sep) == '=' && sep < 0xFF) - sep++; - if (sc.GetRelative(sep) == sc.ch) - return sep; - return 0; -} - -static void ColouriseLuaDoc( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - WordList &keywords6 = *keywordlists[5]; - WordList &keywords7 = *keywordlists[6]; - WordList &keywords8 = *keywordlists[7]; - - // Accepts accented characters - CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true); - // Not exactly following number definition (several dots are seen as OK, etc.) - // but probably enough in most cases. [pP] is for hex floats. - CharacterSet setNumber(CharacterSet::setDigits, ".-+abcdefpABCDEFP"); - CharacterSet setExponent(CharacterSet::setNone, "eEpP"); - CharacterSet setLuaOperator(CharacterSet::setNone, "*/-+()={}~[];<>,.^%:#"); - CharacterSet setEscapeSkip(CharacterSet::setNone, "\"'\\"); - - int currentLine = styler.GetLine(startPos); - // Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level, - // if we are inside such a string. Block comment was introduced in Lua 5.0, - // blocks with separators [=[ ... ]=] in Lua 5.1. - // Continuation of a string (\z whitespace escaping) is controlled by stringWs. - int nestLevel = 0; - int sepCount = 0; - int stringWs = 0; - if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT || - initStyle == SCE_LUA_STRING || initStyle == SCE_LUA_CHARACTER) { - int lineState = styler.GetLineState(currentLine - 1); - nestLevel = lineState >> 9; - sepCount = lineState & 0xFF; - stringWs = lineState & 0x100; - } - - // Do not leak onto next line - if (initStyle == SCE_LUA_STRINGEOL || initStyle == SCE_LUA_COMMENTLINE || initStyle == SCE_LUA_PREPROCESSOR) { - initStyle = SCE_LUA_DEFAULT; - } - - StyleContext sc(startPos, length, initStyle, styler); - if (startPos == 0 && sc.ch == '#') { - // shbang line: # is a comment only if first char of the script - sc.SetState(SCE_LUA_COMMENTLINE); - } - for (; sc.More(); sc.Forward()) { - if (sc.atLineEnd) { - // Update the line state, so it can be seen by next line - currentLine = styler.GetLine(sc.currentPos); - switch (sc.state) { - case SCE_LUA_LITERALSTRING: - case SCE_LUA_COMMENT: - case SCE_LUA_STRING: - case SCE_LUA_CHARACTER: - // Inside a literal string, block comment or string, we set the line state - styler.SetLineState(currentLine, (nestLevel << 9) | stringWs | sepCount); - break; - default: - // Reset the line state - styler.SetLineState(currentLine, 0); - break; - } - } - if (sc.atLineStart && (sc.state == SCE_LUA_STRING)) { - // Prevent SCE_LUA_STRINGEOL from leaking back to previous line - sc.SetState(SCE_LUA_STRING); - } - - // Handle string line continuation - if ((sc.state == SCE_LUA_STRING || sc.state == SCE_LUA_CHARACTER) && - sc.ch == '\\') { - if (sc.chNext == '\n' || sc.chNext == '\r') { - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - sc.Forward(); - } - continue; - } - } - - // Determine if the current state should terminate. - if (sc.state == SCE_LUA_OPERATOR) { - if (sc.ch == ':' && sc.chPrev == ':') { // ::