From a0f6fd68a56068a20e7186e2dd2d7daccfbce4aa Mon Sep 17 00:00:00 2001 From: Pavel Perminov Date: Wed, 26 Sep 2012 19:02:53 +0000 Subject: Chess4Net_MI 2010.0 release (106 rev. truncated adjusted copy) git-svn-id: http://svn.miranda-ng.org/main/trunk@1666 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Chess4Net/BitmapResUnit.pas | 193 + plugins/Chess4Net/Build/Chigorin.mov | Bin 0 -> 10188 bytes plugins/Chess4Net/Build/Chigorin.pos | Bin 0 -> 215159 bytes plugins/Chess4Net/Build/Fischer.mov | Bin 0 -> 13311 bytes plugins/Chess4Net/Build/Fischer.pos | Bin 0 -> 300902 bytes plugins/Chess4Net/Build/Tal.mov | Bin 0 -> 3393 bytes plugins/Chess4Net/Build/Tal.pos | Bin 0 -> 73045 bytes plugins/Chess4Net/Build/eco.mov | Bin 0 -> 36414 bytes plugins/Chess4Net/Build/eco.pos | Bin 0 -> 567931 bytes plugins/Chess4Net/Chess4Net.bpg | 36 + plugins/Chess4Net/Chess4Net.ico | Bin 0 -> 766 bytes plugins/Chess4Net/Chess4Net.res | Bin 0 -> 1276 bytes plugins/Chess4Net/Chess4Net_16.ico | Bin 0 -> 318 bytes plugins/Chess4Net/ChessBoardHeaderUnit.pas | 21 + plugins/Chess4Net/ChessBoardUnit.dfm | 186 + plugins/Chess4Net/ChessBoardUnit.pas | 1391 +++++ plugins/Chess4Net/ChessRulesEngine.pas | 1018 ++++ plugins/Chess4Net/ChessSet.res | Bin 0 -> 74268 bytes plugins/Chess4Net/ChessSet_PNG.RES | Bin 0 -> 19720 bytes plugins/Chess4Net/ClientQueueUnit.pas | 159 + plugins/Chess4Net/Connecting.ico | Bin 0 -> 766 bytes plugins/Chess4Net/ConnectingUnit.dfm | 72 + plugins/Chess4Net/ConnectingUnit.pas | 110 + plugins/Chess4Net/ConnectionUnit.dfm | 118 + plugins/Chess4Net/ConnectionUnit.pas | 107 + plugins/Chess4Net/ContinueUnit.dfm | 40 + plugins/Chess4Net/ContinueUnit.pas | 111 + plugins/Chess4Net/DialogUnit.pas | 196 + plugins/Chess4Net/DraggedFigureUnit.dfm | 59 + plugins/Chess4Net/DraggedFigureUnit.pas | 42 + plugins/Chess4Net/Flag.bmp | Bin 0 -> 358 bytes plugins/Chess4Net/GameOptionsUnit.dfm | 317 ++ plugins/Chess4Net/GameOptionsUnit.pas | 185 + plugins/Chess4Net/GlobalsUnit.pas | 10 + plugins/Chess4Net/InfoUnit.dfm | 114 + plugins/Chess4Net/InfoUnit.pas | 92 + plugins/Chess4Net/Lang.ini | Bin 0 -> 12304 bytes plugins/Chess4Net/LocalizerUnit.pas | 404 ++ plugins/Chess4Net/LookFeelOptionsUnit.dfm | 142 + plugins/Chess4Net/LookFeelOptionsUnit.pas | 108 + plugins/Chess4Net/MI/Chess4Net_MI.cfg | 45 + plugins/Chess4Net/MI/Chess4Net_MI.cfg.bak | 47 + plugins/Chess4Net/MI/Chess4Net_MI.dof | 172 + plugins/Chess4Net/MI/Chess4Net_MI.dpr | 70 + plugins/Chess4Net/MI/ConnectorUnit.pas | 838 +++ plugins/Chess4Net/MI/ControlUnit.pas | 171 + plugins/Chess4Net/MI/GlobalsLocalUnit.pas | 31 + plugins/Chess4Net/MI/ManagerUnit.MI.pas | 869 +++ plugins/Chess4Net/MI/MirandaINC/m_addcontact.inc | 54 + plugins/Chess4Net/MI/MirandaINC/m_api.pas | 75 + plugins/Chess4Net/MI/MirandaINC/m_awaymsg.inc | 40 + plugins/Chess4Net/MI/MirandaINC/m_clc.inc | 284 + plugins/Chess4Net/MI/MirandaINC/m_clist.inc | 641 +++ plugins/Chess4Net/MI/MirandaINC/m_clui.inc | 215 + plugins/Chess4Net/MI/MirandaINC/m_contacts.inc | 84 + plugins/Chess4Net/MI/MirandaINC/m_database.inc | 654 +++ plugins/Chess4Net/MI/MirandaINC/m_email.inc | 39 + plugins/Chess4Net/MI/MirandaINC/m_file.inc | 66 + plugins/Chess4Net/MI/MirandaINC/m_findadd.inc | 38 + plugins/Chess4Net/MI/MirandaINC/m_globaldefs.pas | 98 + plugins/Chess4Net/MI/MirandaINC/m_helpers.inc | 622 +++ plugins/Chess4Net/MI/MirandaINC/m_history.inc | 37 + plugins/Chess4Net/MI/MirandaINC/m_icq.inc | 191 + plugins/Chess4Net/MI/MirandaINC/m_ignore.inc | 74 + plugins/Chess4Net/MI/MirandaINC/m_langpack.inc | 82 + plugins/Chess4Net/MI/MirandaINC/m_message.inc | 57 + plugins/Chess4Net/MI/MirandaINC/m_netlib.inc | 713 +++ plugins/Chess4Net/MI/MirandaINC/m_options.inc | 109 + plugins/Chess4Net/MI/MirandaINC/m_plugins.inc | 70 + plugins/Chess4Net/MI/MirandaINC/m_popup.inc | 222 + plugins/Chess4Net/MI/MirandaINC/m_protocols.inc | 180 + plugins/Chess4Net/MI/MirandaINC/m_protomod.inc | 105 + plugins/Chess4Net/MI/MirandaINC/m_protosvc.inc | 753 +++ plugins/Chess4Net/MI/MirandaINC/m_skin.inc | 120 + plugins/Chess4Net/MI/MirandaINC/m_system.inc | 170 + plugins/Chess4Net/MI/MirandaINC/m_url.inc | 39 + plugins/Chess4Net/MI/MirandaINC/m_userinfo.inc | 84 + plugins/Chess4Net/MI/MirandaINC/m_utils.inc | 279 + plugins/Chess4Net/MI/MirandaINC/newpluginapi.h | 282 + plugins/Chess4Net/MI/MirandaINC/newpluginapi.inc | 209 + plugins/Chess4Net/MI/MirandaINC/readme.txt | 1 + plugins/Chess4Net/MI/MirandaINC/statusmodes.inc | 54 + plugins/Chess4Net/MI/PluginCommonUnit.pas | 55 + plugins/Chess4Net/MI/TransmitGameSelectionUnit.dfm | 47 + plugins/Chess4Net/MI/TransmitGameSelectionUnit.pas | 77 + plugins/Chess4Net/MI/make.bat | 36 + plugins/Chess4Net/ManagerUnit.dfm | 131 + plugins/Chess4Net/ManagerUnit.pas | 2478 +++++++++ plugins/Chess4Net/MessageDialogUnit.pas | 267 + plugins/Chess4Net/ModalForm.pas | 491 ++ plugins/Chess4Net/PosBaseChessBoardUnit.pas | 537 ++ plugins/Chess4Net/PosBaseUnit.pas | 360 ++ plugins/Chess4Net/PromotionUnit.dfm | 30 + plugins/Chess4Net/PromotionUnit.pas | 159 + plugins/Chess4Net/Readme.txt | 251 + plugins/Chess4Net/Readme_RU.txt | Bin 0 -> 13846 bytes plugins/Chess4Net/TODO.txt | 44 + plugins/Chess4Net/lib/PNGImage/obj/adler32.obj | Bin 0 -> 977 bytes plugins/Chess4Net/lib/PNGImage/obj/compress.obj | Bin 0 -> 502 bytes plugins/Chess4Net/lib/PNGImage/obj/crc32.obj | Bin 0 -> 10586 bytes plugins/Chess4Net/lib/PNGImage/obj/deflate.obj | Bin 0 -> 8769 bytes plugins/Chess4Net/lib/PNGImage/obj/gzio.obj | Bin 0 -> 5124 bytes plugins/Chess4Net/lib/PNGImage/obj/infback.obj | Bin 0 -> 6913 bytes plugins/Chess4Net/lib/PNGImage/obj/inffast.obj | Bin 0 -> 1568 bytes plugins/Chess4Net/lib/PNGImage/obj/inflate.obj | Bin 0 -> 10546 bytes plugins/Chess4Net/lib/PNGImage/obj/inftrees.obj | Bin 0 -> 1681 bytes plugins/Chess4Net/lib/PNGImage/obj/trees.obj | Bin 0 -> 10932 bytes plugins/Chess4Net/lib/PNGImage/obj/uncompr.obj | Bin 0 -> 440 bytes plugins/Chess4Net/lib/PNGImage/obj/zutil.obj | Bin 0 -> 747 bytes plugins/Chess4Net/lib/PNGImage/pngextra.pas | 353 ++ plugins/Chess4Net/lib/PNGImage/pngimage.pas | 5824 ++++++++++++++++++++ plugins/Chess4Net/lib/PNGImage/pnglang.pas | 355 ++ plugins/Chess4Net/lib/PNGImage/zlibpas.pas | 156 + .../TntUnicodeControls/Source/ActiveIMM_TLB.pas | 1374 +++++ .../lib/TntUnicodeControls/Source/TntActnList.pas | 835 +++ .../lib/TntUnicodeControls/Source/TntAxCtrls.pas | 191 + .../lib/TntUnicodeControls/Source/TntBandActn.pas | 92 + .../lib/TntUnicodeControls/Source/TntButtons.pas | 982 ++++ .../lib/TntUnicodeControls/Source/TntCheckLst.pas | 184 + .../lib/TntUnicodeControls/Source/TntClasses.pas | 1780 ++++++ .../lib/TntUnicodeControls/Source/TntClipBrd.pas | 86 + .../lib/TntUnicodeControls/Source/TntComCtrls.pas | 5058 +++++++++++++++++ .../lib/TntUnicodeControls/Source/TntCompilers.inc | 356 ++ .../lib/TntUnicodeControls/Source/TntControls.pas | 1099 ++++ .../lib/TntUnicodeControls/Source/TntDB.pas | 900 +++ .../lib/TntUnicodeControls/Source/TntDBActns.pas | 594 ++ .../TntUnicodeControls/Source/TntDBClientActns.pas | 197 + .../lib/TntUnicodeControls/Source/TntDBCtrls.pas | 2195 ++++++++ .../lib/TntUnicodeControls/Source/TntDBGrids.pas | 1175 ++++ .../lib/TntUnicodeControls/Source/TntDBLogDlg.dfm | 108 + .../lib/TntUnicodeControls/Source/TntDBLogDlg.pas | 133 + .../lib/TntUnicodeControls/Source/TntDialogs.pas | 981 ++++ .../lib/TntUnicodeControls/Source/TntExtActns.pas | 1400 +++++ .../lib/TntUnicodeControls/Source/TntExtCtrls.pas | 1062 ++++ .../lib/TntUnicodeControls/Source/TntExtDlgs.pas | 317 ++ .../lib/TntUnicodeControls/Source/TntFileCtrl.pas | 118 + .../Source/TntFormatStrUtils.pas | 503 ++ .../lib/TntUnicodeControls/Source/TntForms.pas | 873 +++ .../lib/TntUnicodeControls/Source/TntGraphics.pas | 142 + .../lib/TntUnicodeControls/Source/TntGrids.pas | 675 +++ .../lib/TntUnicodeControls/Source/TntIniFiles.pas | 1011 ++++ .../TntUnicodeControls/Source/TntIniFilesEx.pas | 205 + .../lib/TntUnicodeControls/Source/TntListActns.pas | 207 + .../lib/TntUnicodeControls/Source/TntMenus.pas | 1146 ++++ .../lib/TntUnicodeControls/Source/TntRegistry.pas | 148 + .../lib/TntUnicodeControls/Source/TntStdActns.pas | 1922 +++++++ .../lib/TntUnicodeControls/Source/TntStdCtrls.pas | 3215 +++++++++++ .../lib/TntUnicodeControls/Source/TntSysUtils.pas | 1699 ++++++ .../lib/TntUnicodeControls/Source/TntSystem.pas | 1384 +++++ .../TntUnicodeControls/Source/TntWideStrUtils.pas | 451 ++ .../TntUnicodeControls/Source/TntWideStrings.pas | 831 +++ .../lib/TntUnicodeControls/Source/TntWindows.pas | 1452 +++++ plugins/Chess4Net/res/BITMAPS.zip | Bin 0 -> 24465 bytes plugins/Chess4Net/res/BOARD.bmp | Bin 0 -> 61190 bytes plugins/Chess4Net/res/Delphi/Buttons.res | Bin 0 -> 5124 bytes plugins/Chess4Net/res/Delphi/Controls.res | Bin 0 -> 2776 bytes plugins/Chess4Net/res/Delphi/Extdlgs.res | Bin 0 -> 456 bytes plugins/Chess4Net/res/MakeRes.bat | 1 + plugins/Chess4Net/res/PNG_SET.zip | Bin 0 -> 17348 bytes 159 files changed, 62948 insertions(+) create mode 100644 plugins/Chess4Net/BitmapResUnit.pas create mode 100644 plugins/Chess4Net/Build/Chigorin.mov create mode 100644 plugins/Chess4Net/Build/Chigorin.pos create mode 100644 plugins/Chess4Net/Build/Fischer.mov create mode 100644 plugins/Chess4Net/Build/Fischer.pos create mode 100644 plugins/Chess4Net/Build/Tal.mov create mode 100644 plugins/Chess4Net/Build/Tal.pos create mode 100644 plugins/Chess4Net/Build/eco.mov create mode 100644 plugins/Chess4Net/Build/eco.pos create mode 100644 plugins/Chess4Net/Chess4Net.bpg create mode 100644 plugins/Chess4Net/Chess4Net.ico create mode 100644 plugins/Chess4Net/Chess4Net.res create mode 100644 plugins/Chess4Net/Chess4Net_16.ico create mode 100644 plugins/Chess4Net/ChessBoardHeaderUnit.pas create mode 100644 plugins/Chess4Net/ChessBoardUnit.dfm create mode 100644 plugins/Chess4Net/ChessBoardUnit.pas create mode 100644 plugins/Chess4Net/ChessRulesEngine.pas create mode 100644 plugins/Chess4Net/ChessSet.res create mode 100644 plugins/Chess4Net/ChessSet_PNG.RES create mode 100644 plugins/Chess4Net/ClientQueueUnit.pas create mode 100644 plugins/Chess4Net/Connecting.ico create mode 100644 plugins/Chess4Net/ConnectingUnit.dfm create mode 100644 plugins/Chess4Net/ConnectingUnit.pas create mode 100644 plugins/Chess4Net/ConnectionUnit.dfm create mode 100644 plugins/Chess4Net/ConnectionUnit.pas create mode 100644 plugins/Chess4Net/ContinueUnit.dfm create mode 100644 plugins/Chess4Net/ContinueUnit.pas create mode 100644 plugins/Chess4Net/DialogUnit.pas create mode 100644 plugins/Chess4Net/DraggedFigureUnit.dfm create mode 100644 plugins/Chess4Net/DraggedFigureUnit.pas create mode 100644 plugins/Chess4Net/Flag.bmp create mode 100644 plugins/Chess4Net/GameOptionsUnit.dfm create mode 100644 plugins/Chess4Net/GameOptionsUnit.pas create mode 100644 plugins/Chess4Net/GlobalsUnit.pas create mode 100644 plugins/Chess4Net/InfoUnit.dfm create mode 100644 plugins/Chess4Net/InfoUnit.pas create mode 100644 plugins/Chess4Net/Lang.ini create mode 100644 plugins/Chess4Net/LocalizerUnit.pas create mode 100644 plugins/Chess4Net/LookFeelOptionsUnit.dfm create mode 100644 plugins/Chess4Net/LookFeelOptionsUnit.pas create mode 100644 plugins/Chess4Net/MI/Chess4Net_MI.cfg create mode 100644 plugins/Chess4Net/MI/Chess4Net_MI.cfg.bak create mode 100644 plugins/Chess4Net/MI/Chess4Net_MI.dof create mode 100644 plugins/Chess4Net/MI/Chess4Net_MI.dpr create mode 100644 plugins/Chess4Net/MI/ConnectorUnit.pas create mode 100644 plugins/Chess4Net/MI/ControlUnit.pas create mode 100644 plugins/Chess4Net/MI/GlobalsLocalUnit.pas create mode 100644 plugins/Chess4Net/MI/ManagerUnit.MI.pas create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_addcontact.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_api.pas create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_awaymsg.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_clc.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_clist.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_clui.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_contacts.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_database.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_email.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_file.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_findadd.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_globaldefs.pas create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_helpers.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_history.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_icq.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_ignore.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_langpack.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_message.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_netlib.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_options.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_plugins.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_popup.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_protocols.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_protomod.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_protosvc.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_skin.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_system.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_url.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_userinfo.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/m_utils.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/newpluginapi.h create mode 100644 plugins/Chess4Net/MI/MirandaINC/newpluginapi.inc create mode 100644 plugins/Chess4Net/MI/MirandaINC/readme.txt create mode 100644 plugins/Chess4Net/MI/MirandaINC/statusmodes.inc create mode 100644 plugins/Chess4Net/MI/PluginCommonUnit.pas create mode 100644 plugins/Chess4Net/MI/TransmitGameSelectionUnit.dfm create mode 100644 plugins/Chess4Net/MI/TransmitGameSelectionUnit.pas create mode 100644 plugins/Chess4Net/MI/make.bat create mode 100644 plugins/Chess4Net/ManagerUnit.dfm create mode 100644 plugins/Chess4Net/ManagerUnit.pas create mode 100644 plugins/Chess4Net/MessageDialogUnit.pas create mode 100644 plugins/Chess4Net/ModalForm.pas create mode 100644 plugins/Chess4Net/PosBaseChessBoardUnit.pas create mode 100644 plugins/Chess4Net/PosBaseUnit.pas create mode 100644 plugins/Chess4Net/PromotionUnit.dfm create mode 100644 plugins/Chess4Net/PromotionUnit.pas create mode 100644 plugins/Chess4Net/Readme.txt create mode 100644 plugins/Chess4Net/Readme_RU.txt create mode 100644 plugins/Chess4Net/TODO.txt create mode 100644 plugins/Chess4Net/lib/PNGImage/obj/adler32.obj create mode 100644 plugins/Chess4Net/lib/PNGImage/obj/compress.obj create mode 100644 plugins/Chess4Net/lib/PNGImage/obj/crc32.obj create mode 100644 plugins/Chess4Net/lib/PNGImage/obj/deflate.obj create mode 100644 plugins/Chess4Net/lib/PNGImage/obj/gzio.obj create mode 100644 plugins/Chess4Net/lib/PNGImage/obj/infback.obj create mode 100644 plugins/Chess4Net/lib/PNGImage/obj/inffast.obj create mode 100644 plugins/Chess4Net/lib/PNGImage/obj/inflate.obj create mode 100644 plugins/Chess4Net/lib/PNGImage/obj/inftrees.obj create mode 100644 plugins/Chess4Net/lib/PNGImage/obj/trees.obj create mode 100644 plugins/Chess4Net/lib/PNGImage/obj/uncompr.obj create mode 100644 plugins/Chess4Net/lib/PNGImage/obj/zutil.obj create mode 100644 plugins/Chess4Net/lib/PNGImage/pngextra.pas create mode 100644 plugins/Chess4Net/lib/PNGImage/pngimage.pas create mode 100644 plugins/Chess4Net/lib/PNGImage/pnglang.pas create mode 100644 plugins/Chess4Net/lib/PNGImage/zlibpas.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/ActiveIMM_TLB.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntActnList.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntAxCtrls.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntBandActn.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntButtons.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntCheckLst.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntClasses.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntClipBrd.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntComCtrls.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntCompilers.inc create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntControls.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntDB.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntDBActns.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntDBClientActns.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntDBCtrls.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntDBGrids.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntDBLogDlg.dfm create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntDBLogDlg.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntDialogs.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntExtActns.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntExtCtrls.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntExtDlgs.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntFileCtrl.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntFormatStrUtils.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntForms.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntGraphics.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntGrids.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntIniFiles.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntIniFilesEx.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntListActns.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntMenus.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntRegistry.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntStdActns.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntStdCtrls.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntSysUtils.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntSystem.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntWideStrUtils.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntWideStrings.pas create mode 100644 plugins/Chess4Net/lib/TntUnicodeControls/Source/TntWindows.pas create mode 100644 plugins/Chess4Net/res/BITMAPS.zip create mode 100644 plugins/Chess4Net/res/BOARD.bmp create mode 100644 plugins/Chess4Net/res/Delphi/Buttons.res create mode 100644 plugins/Chess4Net/res/Delphi/Controls.res create mode 100644 plugins/Chess4Net/res/Delphi/Extdlgs.res create mode 100644 plugins/Chess4Net/res/MakeRes.bat create mode 100644 plugins/Chess4Net/res/PNG_SET.zip diff --git a/plugins/Chess4Net/BitmapResUnit.pas b/plugins/Chess4Net/BitmapResUnit.pas new file mode 100644 index 0000000000..bda6d1a1e9 --- /dev/null +++ b/plugins/Chess4Net/BitmapResUnit.pas @@ -0,0 +1,193 @@ +unit BitmapResUnit; + +interface + +uses + Graphics, Types, + // Chess4Net + ChessBoardHeaderUnit, ChessRulesEngine; + +type + // Bitmap resources - introduced for 2009.1 (sizable board feature) + TBitmapRes = class // parametrizable class factory + private + m_ResSet: TBitmap; + m_iSetNumber: integer; + m_iSquareSize: integer; + procedure FCalculateClientBoardSizes(InitialSize: TSize); + public + constructor Create(const ClientBoardSize: TSize); + destructor Destroy; override; + procedure CreateBoardBitmap(ClientBoardSize: TSize; const BackgroundColor: TColor; + out Bitmap: TBitmap); + procedure CreateFigureBitmap(const Figure: TFigure; out Bitmap: TBitmap); + function GetOptimalBoardSize(ClientSize: TSize): TSize; + property SquareSize: integer read m_iSquareSize; + end; + +implementation + +{$R ChessSet_PNG.RES} + +uses + SysUtils, Classes, Math, pngimage; + +{$J+} + +const + CHB_RES_X = 4; CHB_RES_Y = 4; // starting coordinates of A8 field in resources + +var + g_BitmapResInstance: TBitmapRes = nil; + arrClientBoardSizes: array[1..7] of TSize; + bClientBoardSizesCalculated: boolean = FALSE; + +//////////////////////////////////////////////////////////////////////////////// +// TBitmapRes + +constructor TBitmapRes.Create(const ClientBoardSize: TSize); +begin + if (not bClientBoardSizesCalculated) then + FCalculateClientBoardSizes(ClientBoardSize); +end; + + +destructor TBitmapRes.Destroy; +begin + m_ResSet.Free; + inherited; +end; + + +procedure TBitmapRes.CreateBoardBitmap(ClientBoardSize: TSize; const BackgroundColor: TColor; + out Bitmap: TBitmap); +var + Png: TPngObject; + ResBoard: TBitmap; +begin + Png := nil; + ResBoard := nil; + m_iSquareSize := 0; + + GetOptimalBoardSize(ClientBoardSize); // To refresh m_iSetNumber + if (m_iSetNumber = 0) then + exit; + + Bitmap := TBitMap.Create; + with Bitmap do + try + Png := TPngObject.Create; + Png.LoadFromResourceName(HInstance, 'BOARD' + IntToStr(m_iSetNumber)); + ResBoard := TBitmap.Create; + ResBoard.Assign(Png); + + Width := arrClientBoardSizes[m_iSetNumber].cx; + Height := arrClientBoardSizes[m_iSetNumber].cy; + Canvas.Brush.Color := BackgroundColor; + Canvas.FillRect(Bounds(0, 0, Width, Height)); + Canvas.Draw(CHB_X - CHB_RES_X, CHB_Y - CHB_RES_Y, ResBoard); + + // Load appropriate set + FreeAndNil(m_ResSet); + Png.LoadFromResourceName(HInstance, 'SET' + IntToStr(m_iSetNumber)); + m_ResSet := TBitmap.Create; + m_ResSet.Assign(Png); + + m_iSquareSize := m_ResSet.Height; + finally; + ResBoard.Free; + Png.Free; + end; +end; + + +procedure TBitmapRes.CreateFigureBitmap(const Figure: TFigure; out Bitmap: TBitmap); +const + PNG_SET_POS: array[TFigure] of integer = (2, 4, 6, 8, 10, 12, 0, 3, 5, 7, 9, 11, 13); +var + iSquareSize, iWidth: integer; +begin + if (m_iSetNumber = 0) then + exit; + + iSquareSize := m_ResSet.Height; + + iWidth := IfThen((Figure = ES), iSquareSize + iSquareSize, iSquareSize); + + Bitmap := TBitMap.Create; + Bitmap.Width := iWidth; + Bitmap.Height := iSquareSize; + + Bitmap.Canvas.CopyRect(Bounds(0, 0, iWidth, iSquareSize), m_ResSet.Canvas, + Bounds(iSquareSize * PNG_SET_POS[Figure], 0, iWidth, iSquareSize)); + Bitmap.Transparent:= TRUE; +end; + + +function TBitmapRes.GetOptimalBoardSize(ClientSize: TSize): TSize; +var + i: integer; +begin + m_iSetNumber := 0; + + for i := High(arrClientBoardSizes) downto Low(arrClientBoardSizes) do + begin + if ((ClientSize.cx >= arrClientBoardSizes[i].cx) and + (ClientSize.cy >= arrClientBoardSizes[i].cy)) then + begin + Result := arrClientBoardSizes[i]; + m_iSetNumber := i; + exit; + end; + end; { for i } + + Result := Size(0, 0); +end; + + +procedure TBitmapRes.FCalculateClientBoardSizes(InitialSize: TSize); +var + i: integer; + strResName: string; + iOptimal: integer; + iAddX, iAddY: integer; +begin + // Load board sizes from resources + with TPngObject.Create do + try + for i := Low(arrClientBoardSizes) to High(arrClientBoardSizes) do + begin + strResName := 'BOARD' + IntToStr(i); + LoadFromResourceName(HInstance, strResName); + arrClientBoardSizes[i] := Size(Width, Height); + end; + finally + Free; + end; + + // Find optimal board size from resources + iOptimal := 0; + for i := High(arrClientBoardSizes) downto Low(arrClientBoardSizes) do + begin + if ((InitialSize.cx > (arrClientBoardSizes[i].cx + CHB_X - CHB_RES_X)) and + (InitialSize.cy > (arrClientBoardSizes[i].cy + CHB_Y - CHB_RES_Y))) then + begin + iOptimal := i; + break; + end; + end; + Assert(iOptimal > 0); + + // Calculate board sizes for client + iAddX := InitialSize.cx - arrClientBoardSizes[iOptimal].cx; + iAddY := InitialSize.cy - arrClientBoardSizes[iOptimal].cy; + for i := Low(arrClientBoardSizes) to High(arrClientBoardSizes) do + begin + inc(arrClientBoardSizes[i].cx, iAddX); + inc(arrClientBoardSizes[i].cy, iAddY); + end; + + bClientBoardSizesCalculated := TRUE; +end; + +end. diff --git a/plugins/Chess4Net/Build/Chigorin.mov b/plugins/Chess4Net/Build/Chigorin.mov new file mode 100644 index 0000000000..d52fb6b2c4 Binary files /dev/null and b/plugins/Chess4Net/Build/Chigorin.mov differ diff --git a/plugins/Chess4Net/Build/Chigorin.pos b/plugins/Chess4Net/Build/Chigorin.pos new file mode 100644 index 0000000000..ed7f8eb36d Binary files /dev/null and b/plugins/Chess4Net/Build/Chigorin.pos differ diff --git a/plugins/Chess4Net/Build/Fischer.mov b/plugins/Chess4Net/Build/Fischer.mov new file mode 100644 index 0000000000..8000a1934e Binary files /dev/null and b/plugins/Chess4Net/Build/Fischer.mov differ diff --git a/plugins/Chess4Net/Build/Fischer.pos b/plugins/Chess4Net/Build/Fischer.pos new file mode 100644 index 0000000000..9f64528cdc Binary files /dev/null and b/plugins/Chess4Net/Build/Fischer.pos differ diff --git a/plugins/Chess4Net/Build/Tal.mov b/plugins/Chess4Net/Build/Tal.mov new file mode 100644 index 0000000000..db9fcd6798 Binary files /dev/null and b/plugins/Chess4Net/Build/Tal.mov differ diff --git a/plugins/Chess4Net/Build/Tal.pos b/plugins/Chess4Net/Build/Tal.pos new file mode 100644 index 0000000000..6a5199294b Binary files /dev/null and b/plugins/Chess4Net/Build/Tal.pos differ diff --git a/plugins/Chess4Net/Build/eco.mov b/plugins/Chess4Net/Build/eco.mov new file mode 100644 index 0000000000..c041d1a6d0 Binary files /dev/null and b/plugins/Chess4Net/Build/eco.mov differ diff --git a/plugins/Chess4Net/Build/eco.pos b/plugins/Chess4Net/Build/eco.pos new file mode 100644 index 0000000000..361375d6f3 Binary files /dev/null and b/plugins/Chess4Net/Build/eco.pos differ diff --git a/plugins/Chess4Net/Chess4Net.bpg b/plugins/Chess4Net/Chess4Net.bpg new file mode 100644 index 0000000000..a347fd3148 --- /dev/null +++ b/plugins/Chess4Net/Chess4Net.bpg @@ -0,0 +1,36 @@ +#------------------------------------------------------------------------------ +VERSION = BWS.01 +#------------------------------------------------------------------------------ +!ifndef ROOT +ROOT = $(MAKEDIR)\.. +!endif +#------------------------------------------------------------------------------ +MAKE = $(ROOT)\bin\make.exe -$(MAKEFLAGS) -f$** +DCC = $(ROOT)\bin\dcc32.exe $** +BRCC = $(ROOT)\bin\brcc32.exe $** +#------------------------------------------------------------------------------ +PROJECTS = Chess4Net.exe Chess4Net_MI.dll Chess4Net_Trillian.dll \ + Chess4Net_AndRQ.dll Chess4Net_QIP.dll Chess4Net_Skype.exe +#------------------------------------------------------------------------------ +default: $(PROJECTS) +#------------------------------------------------------------------------------ + +Chess4Net.exe: Socket\Chess4Net.dpr + $(DCC) + +Chess4Net_MI.dll: MI\Chess4Net_MI.dpr + $(DCC) + +Chess4Net_Trillian.dll: Trillian\Chess4Net_Trillian.dpr + $(DCC) + +Chess4Net_AndRQ.dll: AndRQ\Chess4Net_AndRQ.dpr + $(DCC) + +Chess4Net_QIP.dll: QIP\Chess4Net_QIP.dpr + $(DCC) + +Chess4Net_Skype.exe: Skype\Chess4Net_Skype.dpr + $(DCC) + + diff --git a/plugins/Chess4Net/Chess4Net.ico b/plugins/Chess4Net/Chess4Net.ico new file mode 100644 index 0000000000..7994197a01 Binary files /dev/null and b/plugins/Chess4Net/Chess4Net.ico differ diff --git a/plugins/Chess4Net/Chess4Net.res b/plugins/Chess4Net/Chess4Net.res new file mode 100644 index 0000000000..a42efffac4 Binary files /dev/null and b/plugins/Chess4Net/Chess4Net.res differ diff --git a/plugins/Chess4Net/Chess4Net_16.ico b/plugins/Chess4Net/Chess4Net_16.ico new file mode 100644 index 0000000000..d76475585f Binary files /dev/null and b/plugins/Chess4Net/Chess4Net_16.ico differ diff --git a/plugins/Chess4Net/ChessBoardHeaderUnit.pas b/plugins/Chess4Net/ChessBoardHeaderUnit.pas new file mode 100644 index 0000000000..26ffb341a7 --- /dev/null +++ b/plugins/Chess4Net/ChessBoardHeaderUnit.pas @@ -0,0 +1,21 @@ +unit ChessBoardHeaderUnit; + +interface + +uses + Types; + +const + CHB_X = 20; CHB_Y = 6; // starting coordinates of A8 field + +function Size(const iX, iY: integer): TSize; + +implementation + +function Size(const iX, iY: integer): TSize; +begin + Result.cx := iX; + Result.cy := iY; +end; + +end. diff --git a/plugins/Chess4Net/ChessBoardUnit.dfm b/plugins/Chess4Net/ChessBoardUnit.dfm new file mode 100644 index 0000000000..b9f17a075d --- /dev/null +++ b/plugins/Chess4Net/ChessBoardUnit.dfm @@ -0,0 +1,186 @@ +object ChessBoard: TChessBoard + Left = 429 + Top = 209 + Width = 364 + Height = 412 + BorderIcons = [biSystemMenu] + Color = clBtnFace + TransparentColorValue = clBackground + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -13 + Font.Name = 'MS Sans Serif' + Font.Style = [fsBold] + KeyPreview = True + OldCreateOrder = False + OnActivate = FormActivate + OnCanResize = FormCanResize + OnClose = FormClose + OnCreate = FormCreate + OnDestroy = FormDestroy + OnKeyDown = FormKeyDown + OnResize = FormResize + PixelsPerInch = 96 + TextHeight = 16 + object PBoxBoard: TPaintBox + Left = 0 + Top = 33 + Width = 356 + Height = 352 + Align = alClient + Color = clSilver + DragCursor = crHandPoint + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -13 + Font.Name = 'MS Sans Serif' + Font.Style = [fsBold] + ParentColor = False + ParentFont = False + OnDragDrop = PBoxBoardDragDrop + OnDragOver = PBoxBoardDragOver + OnEndDrag = PBoxBoardEndDrag + OnMouseDown = PBoxBoardMouseDown + OnMouseMove = PBoxBoardMouseMove + OnMouseUp = PBoxBoardMouseUp + OnPaint = PBoxBoardPaint + OnStartDrag = PBoxBoardStartDrag + end + object TimePanel: TPanel + Left = 0 + Top = 0 + Width = 356 + Height = 33 + Align = alTop + BevelInner = bvLowered + TabOrder = 0 + OnResize = TimePanelResize + object WhitePanel: TPanel + Left = 8 + Top = 4 + Width = 145 + Height = 25 + BevelOuter = bvNone + TabOrder = 0 + DesignSize = ( + 145 + 25) + object WhiteTimeLabel: TLabel + Left = 71 + Top = 0 + Width = 68 + Height = 25 + Align = alLeft + AutoSize = False + Caption = '0:00:00' + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -19 + Font.Name = 'MS Sans Serif' + Font.Style = [fsBold] + ParentFont = False + Layout = tlCenter + end + object WhiteFlagButton: TSpeedButton + Left = 115 + Top = 2 + Width = 23 + Height = 22 + Anchors = [akTop, akRight] + Glyph.Data = { + 66010000424D6601000000000000760000002800000014000000140000000100 + 040000000000F000000000000000000000001000000000000000000000000000 + 8000008000000080800080000000800080008080000080808000C0C0C0000000 + FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00FFFFFFFFFFFF + FFFFFFFF0000FFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF0000FFFF + FFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFF83FFF + 0000FFFF99FFFFFFFFF33FFF0000FFFFF99FFFFFFF83FFFF0000FFFFF999FFFF + FF33FFFF0000F99999999FFFF33FFFFF0000FF99999999FF83FFFFFF0000FFF9 + 9999999F33FFFFFF0000FFFF999999983FFFFFFF0000FFFFFF9999993FFFFFFF + 0000FFFFFF999999FFFFFFFF0000FFFFFFF9999FFFFFFFFF0000FFFFFFF9999F + FFFFFFFF0000FFFFFFFF99FFFFFFFFFF0000FFFFFFFF9FFFFFFFFFFF0000FFFF + FFFFFFFFFFFFFFFF0000} + Visible = False + OnClick = FlagButtonClick + end + object WhiteLabel: TTntLabel + Left = 0 + Top = 0 + Width = 71 + Height = 25 + Align = alLeft + Caption = 'White ' + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -19 + Font.Name = 'Microsoft Sans Serif' + Font.Style = [fsBold] + ParentFont = False + end + end + object BlackPanel: TPanel + Left = 184 + Top = 4 + Width = 145 + Height = 25 + BevelOuter = bvNone + TabOrder = 1 + DesignSize = ( + 145 + 25) + object BlackTimeLabel: TLabel + Left = 68 + Top = 0 + Width = 68 + Height = 25 + Align = alLeft + AutoSize = False + Caption = '0:00:00' + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -19 + Font.Name = 'MS Sans Serif' + Font.Style = [fsBold] + ParentFont = False + Layout = tlCenter + end + object BlackLabel: TTntLabel + Left = 0 + Top = 0 + Width = 68 + Height = 25 + Align = alLeft + Caption = 'Black ' + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -19 + Font.Name = 'Microsoft Sans Serif' + Font.Style = [fsBold] + ParentFont = False + end + object BlackFlagButton: TSpeedButton + Left = 115 + Top = 2 + Width = 23 + Height = 22 + Anchors = [akTop, akRight] + Visible = False + OnClick = FlagButtonClick + end + end + end + object GameTimer: TTimer + Enabled = False + Interval = 100 + OnTimer = GameTimerTimer + Left = 8 + Top = 40 + end + object AnimateTimer: TTimer + Enabled = False + Interval = 1 + OnTimer = AnimateTimerTimer + Left = 40 + Top = 40 + end +end diff --git a/plugins/Chess4Net/ChessBoardUnit.pas b/plugins/Chess4Net/ChessBoardUnit.pas new file mode 100644 index 0000000000..6b655058ad --- /dev/null +++ b/plugins/Chess4Net/ChessBoardUnit.pas @@ -0,0 +1,1391 @@ +unit ChessBoardUnit; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, TntForms, + Dialogs, StdCtrls, TntStdCtrls, ExtCtrls, Buttons, + // Chess4net + ChessBoardHeaderUnit, ChessRulesEngine, BitmapResUnit, LocalizerUnit; + +type + TMode = (mView, mGame); // состояние доски + TChessBoardEvent = + (cbeMoved, cbeMate, cbeStaleMate, cbeInsuffMaterial, cbeKeyPressed, + cbeClockSwitched, cbeTimeOut, cbeExit, cbeMenu, cbeActivate, cbeFormMoving, + cbeRefreshAll); // возможно добавление новых событий + // cbeRefreshAll сигнализирует, что были изменены глобальные опции. + TChessBoardHandler = procedure(e: TChessBoardEvent; + d1: pointer = nil; d2: pointer = nil) of object; + TAnimation = (aNo, aSlow, aQuick); + +{$IFDEF THREADED_CHESSCLOCK} + TChessBoard = class; + TTimeLabelThread = class(TThread) + private + ChessBoard: TChessBoard; + player_time: array[TFigureColor] of TDateTime; + protected + procedure Execute; override; + public + WhiteTime, BlackTime: string; + constructor Create(ChessBoard: TChessBoard); + end; +{$ENDIF} + + TChessBoard = class(TTntForm, ILocalizable, IChessRulesEngineable) + PBoxBoard: TPaintBox; + TimePanel: TPanel; + WhiteLabel: TTntLabel; + WhiteTimeLabel: TLabel; + BlackLabel: TTntLabel; + BlackTimeLabel: TLabel; + GameTimer: TTimer; + AnimateTimer: TTimer; + WhiteFlagButton: TSpeedButton; + BlackFlagButton: TSpeedButton; + WhitePanel: TPanel; + BlackPanel: TPanel; + procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); + procedure PBoxBoardPaint(Sender: TObject); + procedure PBoxBoardDragDrop(Sender, Source: TObject; X, Y: Integer); + procedure PBoxBoardDragOver(Sender, Source: TObject; X, Y: Integer; + State: TDragState; var Accept: Boolean); + procedure PBoxBoardEndDrag(Sender, Target: TObject; X, Y: Integer); + procedure PBoxBoardMouseDown(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); + procedure PBoxBoardMouseMove(Sender: TObject; Shift: TShiftState; X, + Y: Integer); + procedure PBoxBoardMouseUp(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); + procedure PBoxBoardStartDrag(Sender: TObject; + var DragObject: TDragObject); + procedure AnimateTimerTimer(Sender: TObject); + procedure GameTimerTimer(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); + procedure FormActivate(Sender: TObject); + procedure FlagButtonClick(Sender: TObject); + procedure FormCanResize(Sender: TObject; var NewWidth, NewHeight: Integer; + var Resize: Boolean); + procedure FormResize(Sender: TObject); + procedure TimePanelResize(Sender: TObject); + + private + m_ChessRulesEngine: TChessRulesEngine; + + m_i0, m_j0: integer; + m_fig: TFigure; + + mode_var: TMode; + dx, dy: integer; // Расстояние от курсора до верхнего левого угла + x0, y0: integer; // Предыдущие координаты курсора + _flipped: boolean; // Доска перевёрнута или нет + hilighted: boolean; // Подсветка делаемого хода + + m_bmChessBoard: TBitmap; + m_bmFigure: array[TFigure] of TBitmap; + m_bmBuf: TBitmap; + + Handler: TChessBoardHandler; + + m_animation: TAnimation; // скорость анимации + + anim_dx, anim_dy: real; // переменные для анимации перемещения фигуры + anim_step, anim_step_num: integer; // количество шагов в анимации + player_color: TFigureColor; // цвет игрока клиента + dragged_moved: boolean; // индикатор включения перетаскивания + last_hilight: boolean; // флаг подсветки последнего хода + m_bFlash_move: boolean; // flag for flashing on icoming move + coord_show: boolean; // флаг координат + + auto_flag: boolean; // индикатор автофлага + player_time: array[TFigureColor] of TDateTime; // время белых и чёрных + past_time: TDateTime; // время начала обдумывания хода + unlimited_var: array[TFigureColor] of boolean; // партия без временного контроля + clock_color: TFigureColor; // цвет анимируемой фигуры + + shuted: boolean; // индикатор внешнего закрытия окна + + // Resizing + m_ResizingType: (rtNo, rtHoriz, rtVert); + m_iDeltaWidthHeight: integer; + m_BitmapRes: TBitmapRes; // Manager for bitmaps + m_iTimePanelInitialWidth: integer; + m_iWhitePanelInitialLeft, m_iBlackPanelInitialLeft: integer; + m_iWhitePanelInitialWidth, m_iBlackPanelInitialWidth: integer; + m_TimeFont: TFont; + + m_bViewGaming: boolean; + +{$IFDEF THREADED_CHESSCLOCK} + TimeLabelThread: TTimeLabelThread; // нить используется для борьбы с лагом в Миранде +{$ENDIF} + + procedure HilightLastMove; + procedure WhatSquare(const P: TPoint; var i: Integer; var j: Integer); + procedure Animate(const i, j: integer); // Анимирует перемещение фигуры с (i0,j0) до (i,j) + procedure SetMode(const m: TMode); + procedure ShowTime(const c: TFigureColor); + procedure SetPlayerColor(const color: TFigureColor); + procedure SetTime(color: TFigureColor; const tm: TDateTime); + function GetTime(color: TFigureColor): TDateTime; + procedure SetUnlimited(color: TFigureColor; const unl: boolean); + function GetUnlimited(color: TFigureColor): boolean; + procedure Evaluate; + procedure SetHilightLastMove(const yes: boolean); + procedure SetCoordinates(const yes: boolean); + procedure SetFlipped(const f: boolean); // Переварачивает позицию при отображении + function GetStayOnTop: boolean; + procedure SetStayOnTop(onTop: boolean); + procedure FCancelAnimationDragging; // отмена анимации и перетаскивания для удаления грязи при прорисовки + procedure SetAutoFlag(auto_flag: boolean); + procedure FFlashWindow; + // Localization + procedure ILocalizable.Localize = FLocalize; + procedure FLocalize; + + procedure WMMoving(var Msg: TWMMoving); message WM_MOVING; + procedure WMSizing(var Msg: TMessage); message WM_SIZING; + + function FGetPositinoColor: TFigureColor; + function FGetPosition: PChessPosition; + function AskPromotionFigure(FigureColor: TFigureColor): TFigureName; + + function FGetLastMove: PMoveAbs; + + function FGetPositionsList: TList; + + procedure FOnAfterMoveDone; + + property ChessRulesEngine: TChessRulesEngine read m_ChessRulesEngine; + property Position: PChessPosition read FGetPosition; + + property lastMove: PMoveAbs read FGetLastMove; + + protected + iSquareSize: integer; // Size of a chess board field + bmHiddenBoard: TBitmap; + procedure RDrawBoard; + + procedure RDrawHiddenBoard; virtual; + procedure ROnAfterSetPosition; virtual; + function RDoMove(i, j: integer; prom_fig: TFigureName = K): boolean; + procedure ROnAfterMoveDone; virtual; + + property PositionsList: TList read FGetPositionsList; + + public + constructor Create(Owner: TComponent; h: TChessBoardHandler = nil); reintroduce; + + procedure TakeBack; // взятие хода обратно + procedure SwitchClock(clock_color: TFigureColor); + procedure InitPosition; + procedure PPRandom; + procedure StopClock; + + procedure ResetMoveList; + function SetPosition(const posstr: string): boolean; + function GetPosition: string; + function NMoveDone: integer; // количество сделанных ходов + function DoMove(move_str: string): boolean; + procedure Shut; + + property Unlimited[color: TFigureColor]: boolean read GetUnlimited write SetUnlimited; + property Time[color: TFigureColor]: TDateTime read GetTime write SetTime; + property PlayerColor: TFigureColor read player_color write SetPlayerColor; + property PositionColor: TFigureColor read FGetPositinoColor; // чей ход в текущей позиции + property ClockColor: TFigureColor read clock_color; + property Mode: TMode read mode_var write SetMode; + property CoordinatesShown: boolean read coord_show write SetCoordinates; + + property flipped: boolean read _flipped write SetFlipped; + property LastMoveHilighted: boolean read last_hilight write SetHilightLastMove; + property FlashOnMove: boolean read m_bFlash_move write m_bFlash_move; + property StayOnTop: boolean read GetStayOnTop write SetStayOnTop; + property AutoFlag: boolean read auto_flag write SetAutoFlag; + property animation: TAnimation read m_animation write m_animation; + property ViewGaming: boolean read m_bViewGaming write m_bViewGaming; + end; + +implementation + +{$J+} + +{$R *.dfm} + +uses + StrUtils, Math, DateUtils, + // Chess4Net + PromotionUnit; + +const + HILIGHT_WIDTH = 1; + HILIGHT_COLOR: TColor = clRed; + HILIGHT_LAST_MOVE_WIDTH = 1; + HILIGHT_LAST_MOVE_COLOR: TColor = clBlue; + ANIMATION_SLOW = 30; // Время анимации хода в фреймах >= 1 + ANIMATION_QUICK = 9; + CHB_WIDTH = 4; + TIME_COLOR = clBlack; +// FULL_TIME_FORMAT = 'h:n:s"."z'; + HOUR_TIME_FORMAT = 'h:nn:ss'; + MIN_TIME_FORMAT = 'n:ss'; + ZEITNOT_BOARDER = 10; // сек - цетйтнотная граница + ZEITNOT_COLOR = clMaroon; + ZEITNOT_FORMAT = 's"."zzz'; +// CHEAT_TIME_CONST = 1.5; // > 1 + WHITE_LONG_LABEL: WideString = 'White '; + WHITE_MEDIUM_LABEL: WideString = 'White '; + WHITE_SHORT_LABEL: WideString = 'W '; + BLACK_LONG_LABEL: WideString = 'Black '; + BLACK_MEDIUM_LABEL: WideString = 'Black '; + BLACK_SHORT_LABEL: WideString = 'B '; + +//////////////////////////////////////////////////////////////////////////////// +// Globals + +function TChessBoard.DoMove(move_str: string): boolean; +begin + // Отмена анимации + if (AnimateTimer.Enabled) then + begin + AnimateTimer.Enabled := FALSE; + anim_step := anim_step_num; + AnimateTimerTimer(nil); + end; + + Result := ChessRulesEngine.DoMove(move_str); + + if (Result) then + begin + FOnAfterMoveDone; + Animate(lastMove.i, lastMove.j); + SwitchClock(PositionColor); + if (m_bFlash_move and (mode_var = mGame)) then + FFlashWindow; + end; +end; + + +procedure TChessBoard.ShowTime(const c: TFigureColor); +var + time_label: TLabel; +begin + if c = fcWhite then time_label:= WhiteTimeLabel + else time_label:= BlackTimeLabel; + + if unlimited_var[c] then + begin + time_label.Caption:= ''; + exit; + end; + + time_label.Font.Color:= TIME_COLOR; + + LongTimeFormat:= MIN_TIME_FORMAT; + if player_time[c] >= EncodeTime(1, 0, 0, 0) then + LongTimeFormat:= HOUR_TIME_FORMAT + else + if (player_time[c] < EncodeTime(0, 0, ZEITNOT_BOARDER, 0)) and + (player_time[c] > 0) then + begin + LongTimeFormat:= ZEITNOT_FORMAT; + time_label.Font.Color:= ZEITNOT_COLOR; + end; + + time_label.Caption:= TimeToStr(player_time[c]); +end; + + + +procedure TChessBoard.SetFlipped(const f: boolean); +begin + // TODO: ??? + _flipped:= f; + RDrawBoard; +end; + + +procedure TChessBoard.ResetMoveList; +begin + ChessRulesEngine.ResetMoveList; +end; + + +function TChessBoard.SetPosition(const posstr: string): boolean; +begin + Result := ChessRulesEngine.SetPosition(posstr); + if (not Result) then + exit; + + FCancelAnimationDragging; + ROnAfterSetPosition; + clock_color := Position.color; + RDrawBoard; +end; + + +function TChessBoard.GetPosition: string; +begin + Result := ChessRulesEngine.GetPosition; +end; + + +procedure TChessBoard.FormCreate(Sender: TObject); +begin + m_iDeltaWidthHeight := Width - Height; + + m_iTimePanelInitialWidth := TimePanel.Width; + m_iWhitePanelInitialLeft := WhitePanel.Left; + m_iWhitePanelInitialWidth := WhitePanel.Width; + m_iBlackPanelInitialLeft := BlackPanel.Left; + m_iBlackPanelInitialWidth := BlackPanel.Width; + + m_TimeFont := TFont.Create; + m_TimeFont.Assign(WhiteTimeLabel.Font); + + m_BitmapRes := TBitmapRes.Create(Size(PBoxBoard.Width, PBoxBoard.Height)); + + BlackFlagButton.Glyph := WhiteFlagButton.Glyph; // чтоб не тащить лишнего + coord_show:= TRUE; + last_hilight:= FALSE; + m_animation := aQuick; + + TLocalizer.Instance.AddSubscriber(self); + FLocalize; + + m_ChessRulesEngine := TChessRulesEngine.Create(self); + + // Clock initialization + SetUnlimited(fcWhite, TRUE); SetUnlimited(fcBlack, TRUE); + + InitPosition; +end; + + +procedure TChessBoard.RDrawHiddenBoard; +var + i, j: integer; + x, y: integer; +begin + if (not Assigned(bmHiddenBoard)) then + exit; + + // Copy empty board to the hidden one + with bmHiddenBoard do + begin + Canvas.CopyRect(Bounds(0,0, Width,Height), m_bmChessBoard.Canvas, Bounds(0,0, Width,Height)); + end; + + // Draw coordinates + if (coord_show) then + with bmHiddenBoard, bmHiddenBoard.Canvas do + begin + x:= CHB_X + iSquareSize div 2; + y:= (bmHiddenBoard.Height + CHB_Y + 8 * iSquareSize + CHB_WIDTH) div 2; + if _flipped then j := ord('h') + else j:= ord('a'); + for i:= 1 to 8 do // буквы + begin + TextOut(x - TextWidth(chr(j)) div 2, + y + 1 - TextHeight(chr(j)) div 2 , chr(j)); + x := x + iSquareSize; + if _flipped then dec(j) + else inc(j); + end; + x:= (CHB_X - CHB_WIDTH) div 2; + y:= CHB_Y + iSquareSize div 2; + if _flipped then j:= ord('1') + else j := ord('8'); + for i := 1 to 8 do // цифры + begin + TextOut(x - TextWidth(chr(j)) div 2, + y - TextHeight(chr(j)) div 2, chr(j)); + y:= y + iSquareSize; + if _flipped then inc(j) + else dec(j); + end; + end; + + // Draw pieces + for i := 1 to 8 do + for j := 1 to 8 do + begin + if ((Position.board[i,j] = ES)) then + continue; // There's nothing to draw + if not _flipped then // Загрузить нужную фигуру из ресурса и нарисовать + bmHiddenBoard.Canvas.Draw(CHB_X + iSquareSize * (i-1), + CHB_Y + iSquareSize * (8-j), + m_bmFigure[Position.board[i,j]]) + else // Black is below + bmHiddenBoard.Canvas.Draw(CHB_X + iSquareSize * (8-i), + CHB_Y + iSquareSize * (j-1), + m_bmFigure[Position.board[i,j]]); + end; +end; + + +procedure TChessBoard.RDrawBoard; +begin + RDrawHiddenBoard; + PBoxBoardPaint(nil); +end; + + +procedure TChessBoard.PBoxBoardPaint(Sender: TObject); +begin + PBoxBoard.Canvas.Draw(0,0, bmHiddenBoard); // Вывод скрытой доски на форму +// PBoxBoard.Canvas.StretchDraw(Bounds(0, 0, PBoxBoard.Width, PBoxBoard.Height), bmHiddenBoard); +end; + + +constructor TChessBoard.Create(Owner: TComponent; h: TChessBoardHandler); +begin + inherited Create(Owner); + Handler:= h; +end; + + +procedure TChessBoard.FormDestroy(Sender: TObject); +var + _fig: TFigure; +begin + m_ChessRulesEngine.Free; + + bmHiddenBoard.Free; + m_bmBuf.Free; + + for _fig := Low(TFigure) to High(TFigure) do + m_bmFigure[_fig].Free; + m_bmChessBoard.Free; + + m_BitmapRes.Free; + m_TimeFont.Free; + + TLocalizer.Instance.DeleteSubscriber(self); +end; + + +procedure TChessBoard.PBoxBoardDragDrop(Sender, Source: TObject; X, + Y: Integer); +var + i, j: Integer; +begin + WhatSquare(Point(X, Y), i, j); + if (Mode = mGame) then + begin + if (RDoMove(i, j)) then + begin + SwitchClock(PositionColor); + dragged_moved:= TRUE; + end; + end; // if +end; + + +procedure TChessBoard.PBoxBoardDragOver(Sender, Source: TObject; X, + Y: Integer; State: TDragState; var Accept: Boolean); +var + rect: TRect; + i, j: integer; +begin + case State of + dsDragEnter: + hilighted:= FALSE; + dsDragMove: + begin + // Восстановить фрагмент на bmHiddenBoard + bmHiddenBoard.Canvas.Draw(x0 - dx, y0 - dy, m_bmBuf); + // Копировать новый фрагмент в буфер + m_bmBuf.Canvas.CopyRect(Bounds(0, 0, iSquareSize, iSquareSize), + bmHiddenBoard.Canvas, Bounds(X - dx, Y - dy, iSquareSize, iSquareSize)); + // Нарисовать перетаскиваемую фигуру в новой позиции + bmHiddenBoard.Canvas.Draw(X - dx, Y - dy, m_bmFigure[m_fig]); + // Перенести новый фрагмент на экран + rect:= Bounds(Min(x0,X) - dx, Min(y0, Y) - dy, + abs(X - x0) + iSquareSize, abs(Y - y0) + iSquareSize); + PBoxBoard.Canvas.CopyRect(rect, bmHiddenBoard.Canvas, rect); + + x0 := X; + y0 := Y; + + WhatSquare(Point(X,Y), i,j); + + Accept := ((i in [1..8]) and (j in [1..8])); + end; + end; +end; + + +procedure TChessBoard.PBoxBoardEndDrag(Sender, Target: TObject; X, + Y: Integer); +begin + if hilighted then + with bmHiddenBoard.Canvas do + begin + Pen.Color:= HILIGHT_COLOR; + Pen.Width := HILIGHT_WIDTH; + x0:= x0 - dx; + y0:= y0 - dy; + MoveTo(x0,y0); + LineTo(x0 + iSquareSize - 1, y0); + LineTo(x0 + iSquareSize - 1, y0 + iSquareSize - 1); + LineTo(x0, y0 + iSquareSize - 1); + LineTo(x0,y0); + + PBoxBoardPaint(nil); + end + else + begin + RDrawBoard; + if dragged_moved then + begin + HilightLastMove; + Evaluate; + dragged_moved:= FALSE; + end; + end; +end; + + +procedure TChessBoard.WhatSquare(const P: TPoint; + var i: Integer; var j: Integer); +begin + with P do + begin + i := (X - CHB_X + iSquareSize) div iSquareSize; + j := 8 - (Y - CHB_Y) div iSquareSize; + if (_flipped) then + begin + i := 9 - i; + j := 9 - j; + end; + end; +end; + + +procedure TChessBoard.PBoxBoardMouseDown(Sender: TObject; + Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +var + i, j: Integer; + f: TFigure; +begin + WhatSquare(Point(X, Y), i, j); + if (not ((i in [1..8]) and (j in [1..8]))) then + exit; + + f := Position.board[i,j]; + + case Mode of + mGame: + begin + if (ViewGaming) then + exit; + if (Button <> mbLeft) or (Position.color <> player_color) or + (((Position.color <> fcWhite) or (f >= ES)) and + ((Position.color <> fcBlack) or (f <= ES))) then + exit; + end; + else + exit; + end; + + if (anim_step < anim_step_num) then + begin + anim_step:= anim_step_num; + AnimateTimerTimer(nil); + end; + + if ((i = m_i0) and (j = m_j0)) then + hilighted := (hilighted xor TRUE) + else + hilighted:= TRUE; + + m_fig := f; + m_i0 := i; + m_j0 := j; + + dx := (X - CHB_X) mod iSquareSize; + dy := (Y - CHB_Y) mod iSquareSize; + x0 := X; + y0 := Y; + + dragged_moved := TRUE; + PBoxBoard.BeginDrag(FALSE); +end; + + +procedure TChessBoard.PBoxBoardMouseMove(Sender: TObject; + Shift: TShiftState; X, Y: Integer); +var + f: TFigure; + i,j: Integer; +begin + WhatSquare(Point(X,Y), i,j); + if (not ((i in [1..8]) and (j in [1..8]))) then + begin + PBoxBoard.Cursor:= crDefault; + exit; + end; + + f := Position.board[i,j]; + + case Mode of + mGame: + begin + if (ViewGaming) then + exit; + + if (player_color = Position.color) and + (((Position.color = fcWhite) and (f < ES)) or + ((Position.color = fcBlack) and (f > ES))) then + PBoxBoard.Cursor:= crHandPoint + else + PBoxBoard.Cursor:= crDefault; + end; + + else + PBoxBoard.Cursor:= crDefault; + end; +end; + + +procedure TChessBoard.ROnAfterMoveDone; +var + strLastMove: string; +begin + if (Assigned(Handler) and + ((Mode = mGame) and (Position.color <> player_color))) then + begin + strLastMove := ChessRulesEngine.LastMoveStr; + Handler(cbeMoved, @strLastMove, self); + end; +end; + + +procedure TChessBoard.FOnAfterMoveDone; +var + _fig: TFigure; +begin + m_i0 := lastMove.i0; + m_j0 := lastMove.j0; + + _fig := Position.board[lastMove.i, lastMove.j]; + if (lastMove.prom_fig in [Q, R, B, N]) then + begin + if (_fig < ES) then + m_fig := WP + else + m_fig := BP; + end + else + m_fig := _fig; + + ROnAfterMoveDone; +end; + + +function TChessBoard.RDoMove(i, j: integer; prom_fig: TFigureName = K): boolean; +begin + Result := ChessRulesEngine.DoMove(m_i0, m_j0, i, j, prom_fig); + if (Result) then + FOnAfterMoveDone; +end; + + +function TChessBoard.FGetPositionsList: TList; +begin + Result := ChessRulesEngine.PositionsList; +end; + + +procedure TChessBoard.PBoxBoardMouseUp(Sender: TObject; + Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +var + i, j: integer; +begin + case Button of + mbLeft: + case Mode of + mGame: + begin + if (not hilighted) then + exit; + WhatSquare(Point(X, Y), i, j); + if (dragged_moved) then + RDrawBoard + else + begin + hilighted:= FALSE; + if (RDoMove(i, j)) then + begin + Animate(i, j); + SwitchClock(PositionColor); + end + else + RDrawBoard; + end; + end; + end; + + mbRight: + if (Assigned(Handler)) then + Handler(cbeMenu, self); + end; +end; + +procedure TChessBoard.PBoxBoardStartDrag(Sender: TObject; + var DragObject: TDragObject); +begin + // Копировать изображение пустого поля в m_bmBuf + m_bmBuf.Width:= iSquareSize; m_bmBuf.Height:= iSquareSize; + if (((m_i0 + m_j0) and 1) <> 0) then + m_bmBuf.Canvas.CopyRect(Bounds(0,0, iSquareSize, iSquareSize), + m_bmFigure[ES].Canvas, Bounds(0,0, iSquareSize, iSquareSize)) + else + m_bmBuf.Canvas.CopyRect(Bounds(0,0, iSquareSize, iSquareSize), + m_bmFigure[ES].Canvas, Bounds(iSquareSize,0, iSquareSize, iSquareSize)); + + dragged_moved:= FALSE; +end; + + +procedure TChessBoard.Animate(const i, j: integer); +var + x, y: integer; +begin + if not Showing then exit; + + case animation of + aNo: anim_step_num:= 1; + aSlow: anim_step_num:= ANIMATION_SLOW; + aQuick: anim_step_num:= ANIMATION_QUICK; + end; + + if (_flipped) then + begin + x0 := (8 - m_i0) * iSquareSize + CHB_X; + y0 := (m_j0 - 1) * iSquareSize + CHB_Y; + x := (8 - i) * iSquareSize + CHB_X; + y := (j - 1) * iSquareSize + CHB_Y; + end + else + begin + x0:= (m_i0 - 1) * iSquareSize + CHB_X; + y0:= (8 - m_j0) * iSquareSize + CHB_Y; + x:= (i - 1) * iSquareSize + CHB_X; + y:= (8 - j) * iSquareSize + CHB_Y; + end; + + anim_dx:= (x-x0) / anim_step_num; + anim_dy:= (y-y0) / anim_step_num; + + anim_step:= 0; + + // Копировать изображение пустого поля в m_bmBuf + m_bmBuf.Width := iSquareSize; + m_bmBuf.Height := iSquareSize; + if (((m_i0 + m_j0) and 1) <> 0) then + m_bmBuf.Canvas.CopyRect(Bounds(0, 0, iSquareSize, iSquareSize), + m_bmFigure[ES].Canvas, Bounds(0, 0, iSquareSize, iSquareSize)) + else + m_bmBuf.Canvas.CopyRect(Bounds(0, 0, iSquareSize, iSquareSize), + m_bmFigure[ES].Canvas, Bounds(iSquareSize, 0, iSquareSize, iSquareSize)); + + AnimateTimer.Enabled := TRUE; +end; + + +procedure TChessBoard.AnimateTimerTimer(Sender: TObject); +var + X,Y: integer; + rect: TRect; +begin + inc(anim_step); + if (anim_step < anim_step_num) then + begin + X := round(x0 + anim_dx * anim_step); + Y := round(y0 + anim_dy * anim_step); + dx := X - x0 - round(anim_dx * (anim_step - 1)); + dy := Y - y0 - round(anim_dy * (anim_step - 1)); + + // Восстановить фрагмент на bmHiddenBoard + bmHiddenBoard.Canvas.Draw(X - dx, Y - dy, m_bmBuf); + // Копировать новый фрагмент в буфер + m_bmBuf.Canvas.CopyRect(Bounds(0, 0, iSquareSize, iSquareSize), + bmHiddenBoard.Canvas, Bounds(X, Y, iSquareSize, iSquareSize)); + // Нарисовать перетаскиваемую фигуру в новой позиции + bmHiddenBoard.Canvas.Draw(X, Y, m_bmFigure[m_fig]); + // Перенести новый фрагмент на экран + rect := Bounds(Min(X - dx, X), Min(Y - dy, Y), + abs(dx) + iSquareSize, abs(dy) + iSquareSize); + PBoxBoard.Canvas.CopyRect(rect, bmHiddenBoard.Canvas, rect); + end + else + begin + AnimateTimer.Enabled := FALSE; + RDrawBoard; + HilightLastMove; + Evaluate; + end; +end; + + +procedure TChessBoard.InitPosition; +begin + ChessRulesEngine.InitNewGame; + RDrawBoard; +end; + + +procedure TChessBoard.SetMode(const m: TMode); +begin + mode_var := m; + RDrawBoard; + HilightLastMove; + if (mode_var <> mGame) then + begin + WhiteFlagButton.Visible := FALSE; + BlackFlagButton.Visible := FALSE; + end; +end; + + +procedure TChessBoard.SetTime(color: TFigureColor; const tm: TDateTime); +begin + if (not Unlimited[color]) then + begin + if ((not auto_flag) and (not ViewGaming)) then + begin + case color of + fcWhite: + WhiteFlagButton.Visible := ((player_color = fcBlack) and (tm = 0.0)); + fcBlack: + BlackFlagButton.Visible := ((player_color = fcWhite) and (tm = 0.0)); + end; + end; + player_time[color]:= tm; + ShowTime(color); + end; +end; + + +function TChessBoard.GetTime(color: TFigureColor): TDateTime; +begin + Result:= player_time[color]; +end; + + +procedure TChessBoard.GameTimerTimer(Sender: TObject); +begin + if unlimited_var[clock_color] then + begin + GameTimer.Enabled := FALSE; + exit; + end; + // TODO: cheating check + player_time[clock_color] := player_time[clock_color] - (Now - past_time); + if player_time[clock_color] <= 0.0 then + begin + player_time[clock_color] := 0.0; + ShowTime(clock_color); + if ((not auto_flag) and (player_color <> clock_color) and (not ViewGaming)) then + begin + case clock_color of + fcWhite: + WhiteFlagButton.Visible := TRUE; + fcBlack: + BlackFlagButton.Visible := TRUE; + end; + end; + if ((player_color <> clock_color) and Assigned(Handler) and (Mode = mGame) and (auto_flag)) then + Handler(cbeTimeOut, self); + GameTimer.Enabled := FALSE; + end; +{$IFNDEF THREADED_CHESSCLOCK} + ShowTime(clock_color); +{$ENDIF} + + past_time:= Now; +end; + + +procedure TChessBoard.SetUnlimited(color: TFigureColor; const unl: boolean); +begin + unlimited_var[color]:= unl; + ShowTime(color); +end; + + +function TChessBoard.GetUnlimited(color: TFigureColor): boolean; +begin + Result := unlimited_var[color]; +end; + + +procedure TChessBoard.SwitchClock(clock_color: TFigureColor); +begin + self.clock_color := clock_color; + if (not GameTimer.Enabled) then + begin + past_time := Now; + GameTimer.Enabled := TRUE; + end; + if (Assigned(Handler) and (Mode = mGame)) then + Handler(cbeClockSwitched, self); + ShowTime(clock_color); + +{$IFDEF THREADED_CHESSCLOCK} + if (not Assigned(TimeLabelThread)) then + TimeLabelThread := TTimeLabelThread.Create(self); +{$ENDIF} +end; + + +procedure TChessBoard.HilightLastMove; +var + i, j, l, + _i0, _j0, x, y: integer; +begin + // вывод последнего сделанного хода + if (last_hilight and (lastMove.i0 <> 0)) then + begin + if (_flipped) then + begin + _i0 := 9 - lastMove.i0; + _j0 := lastMove.j0; + i := 9 - lastMove.i; + j := lastMove.j; + end + else + begin + _i0 := lastMove.i0; + _j0 := 9 - lastMove.j0; + i := lastMove.i; + j := 9 - lastMove.j; + end; + + x := iSquareSize * (_i0 - 1) + CHB_X; + y := iSquareSize * (_j0 - 1) + CHB_Y; + bmHiddenBoard.Canvas.Pen.Color := HILIGHT_LAST_MOVE_COLOR; + bmHiddenBoard.Canvas.Pen.Width := HILIGHT_LAST_MOVE_WIDTH; + + for l := 1 to 2 do + with bmHiddenBoard.Canvas do + begin + MoveTo(x, y); + LineTo(x + iSquareSize - 1, y); + LineTo(x + iSquareSize - 1, y + iSquareSize - 1); + LineTo(x, y + iSquareSize - 1); + LineTo(x, y); + + x := iSquareSize * (i - 1) + CHB_X; + y := iSquareSize * (j - 1) + CHB_Y; + end; + PBoxBoardPaint(nil); + end; +end; + + +procedure TChessBoard.SetPlayerColor(const color: TFigureColor); +begin + FCancelAnimationDragging; + player_color:= color; + if (player_color = fcWhite) then + SetFlipped(FALSE) + else + SetFlipped(TRUE); // player_color = fcBlack +end; + + +procedure TChessBoard.StopClock; +begin + GameTimer.Enabled := FALSE; + WhiteFlagButton.Visible := FALSE; + BlackFlagButton.Visible := FALSE; +end; + + +procedure TChessBoard.FormCanResize(Sender: TObject; var NewWidth, + NewHeight: Integer; var Resize: Boolean); +var + + NewBoardSize: TSize; +begin + Resize := (m_ResizingType <> rtNo); + if (not Resize) then + exit; + + if (m_ResizingType = rtVert) then + NewWidth := NewHeight + m_iDeltaWidthHeight + else // rtHoriz + NewHeight := NewWidth - m_iDeltaWidthHeight; + + NewBoardSize := m_BitmapRes.GetOptimalBoardSize( + Size(PBoxBoard.Width + (NewWidth - Width), PBoxBoard.Height + (NewHeight - Height))); + + Resize := (NewBoardSize.cx > 0) and (NewBoardSize.cy > 0) and + ((NewBoardSize.cx <> PBoxBoard.Width) or (NewBoardSize.cy <> PBoxBoard.Height)); + if (Resize) then + begin + NewWidth := Width + (NewBoardSize.cx - PBoxBoard.Width); + NewHeight := Height + (NewBoardSize.cy - PBoxBoard.Height); + end; +end; + + +procedure TChessBoard.FormClose(Sender: TObject; var Action: TCloseAction); +begin + if ((not shuted) and Assigned(Handler)) then + begin + Handler(cbeExit, self); + Action:= caNone; + end + else + shuted := FALSE; +end; + + +procedure TChessBoard.Shut; +begin + shuted:= TRUE; + Close; +end; + + +procedure TChessBoard.Evaluate; +begin + if (Assigned(Handler)) then + begin + case ChessRulesEngine.GetEvaluation of + evMate: + Handler(cbeMate, self); + evStaleMate: + Handler(cbeStaleMate, self); + end; + end; +end; + + +procedure TChessBoard.PPRandom; +begin + ChessRulesEngine.InitNewPPRandomGame; + RDrawBoard; +end; + + +procedure TChessBoard.TakeBack; +begin + if (not ChessRulesEngine.TakeBack) then + exit; + ROnAfterSetPosition; + // TODO: animation + RDrawBoard; +end; + + +procedure TChessBoard.SetHilightLastMove(const yes: boolean); +begin + last_hilight := yes; + RDrawBoard; + HilightLastMove; +end; + + +procedure TChessBoard.SetCoordinates(const yes: boolean); +begin + coord_show := yes; + RDrawBoard; + HilightLastMove; +end; + + +function TChessBoard.NMoveDone: integer; +begin + Result := ChessRulesEngine.NMovesDone; +end; + + +procedure TChessBoard.ROnAfterSetPosition; +begin +end; + +{$IFDEF THREADED_CHESSCLOCK} +procedure TTimeLabelThread.Execute; +begin + while ChessBoard.GameTimer.Enabled do + begin + if self.player_time[fcWhite] <> ChessBoard.player_time[fcWhite] then + ChessBoard.ShowTime(fcWhite); + if self.player_time[fcBlack] <> ChessBoard.player_time[fcBlack] then + ChessBoard.ShowTime(fcBlack); + Sleep(ChessBoard.GameTimer.Interval div 2); + end; + ChessBoard.TimeLabelThread := nil; +end; + + +constructor TTimeLabelThread.Create(ChessBoard: TChessBoard); +begin + self.ChessBoard := ChessBoard; + self.player_time[fcWhite] := ChessBoard.player_time[fcWhite]; + self.player_time[fcBlack] := ChessBoard.player_time[fcBlack]; + + inherited Create(TRUE); +//Priority := tpNormal; + FreeOnTerminate := TRUE; + Resume; +end; +{$ENDIF} + +procedure TChessBoard.FormKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); +begin + if Assigned(Handler) then + Handler(cbeKeyPressed, Pointer(Key), self); +end; + + +function TChessBoard.GetStayOnTop: boolean; +begin + Result := (self.FormStyle = fsStayOnTop); +end; + + +procedure TChessBoard.SetStayOnTop(onTop: boolean); +begin + if (onTop) then + self.FormStyle := fsStayOnTop + else + self.FormStyle := fsNormal; +end; + + +procedure TChessBoard.FormActivate(Sender: TObject); +begin + if Assigned(Handler) then + Handler(cbeActivate, self); +end; + + +procedure TChessBoard.WMMoving(var Msg: TWMMoving); +begin + // TODO: it's possible to handle if form is outside of the screen + if Assigned(Handler) then + Handler(cbeFormMoving, Pointer(Msg.DragRect.Left - Left), Pointer(Msg.DragRect.Top - Top)); + inherited; +end; + + +procedure TChessBoard.WMSizing(var Msg: TMessage); +begin + case Msg.WParam of + WMSZ_RIGHT, WMSZ_LEFT, WMSZ_BOTTOMRIGHT, WMSZ_TOPLEFT: + m_ResizingType := rtHoriz; + WMSZ_BOTTOM, WMSZ_TOP: + m_ResizingType := rtVert; + else + begin + m_ResizingType := rtNo; + PRect(Msg.LParam).Left := Left; + PRect(Msg.LParam).Top := Top; + end; + end; { case } +end; + + +function TChessBoard.FGetPositinoColor: TFigureColor; +begin + Result := Position.color; +end; + + +function TChessBoard.FGetPosition: PChessPosition; +begin + Result := ChessRulesEngine.Position; +end; + + +function TChessBoard.AskPromotionFigure(FigureColor: TFigureColor): TFigureName; +begin + if (Showing) then + begin + with TPromotionForm.Create(self, m_BitmapRes) do + try + Result := ShowPromotion(FigureColor); + finally + Free; + end; + end + else + Result := Q; +end; + + +function TChessBoard.FGetLastMove: PMoveAbs; +begin + Result := ChessRulesEngine.lastMove; +end; + + +procedure TChessBoard.FCancelAnimationDragging; +begin + // Отмена анимации и перетаскивания + if (AnimateTimer.Enabled) then + begin + AnimateTimer.Enabled := FALSE; + // anim_step := anim_step_num; + // AnimateTimerTimer(nil); + end; + if (PBoxBoard.Dragging) then + begin + dragged_moved := FALSE; + PBoxBoard.EndDrag(FALSE); + end; +end; + + +procedure TChessBoard.FlagButtonClick(Sender: TObject); +begin + if Assigned(Handler) and (Mode = mGame) then + Handler(cbeTimeOut, self); +end; + + +procedure TChessBoard.SetAutoFlag(auto_flag: boolean); +begin + self.auto_flag := auto_flag; + if (auto_flag) then + begin + WhiteFlagButton.Visible := FALSE; + BlackFlagButton.Visible := FALSE; + end; +end; + + +procedure TChessBoard.FormResize(Sender: TObject); +var + _fig: TFigure; +begin + FreeAndNil(m_bmChessBoard); + m_BitmapRes.CreateBoardBitmap(Size(PBoxBoard.Width, PBoxBoard.Height), self.Color, + m_bmChessBoard); + iSquareSize := m_BitmapRes.SquareSize; + + for _fig := Low(TFigure) to High(TFigure) do + begin + FreeAndNil(m_bmFigure[_fig]); + m_BitmapRes.CreateFigureBitmap(_fig, m_bmFigure[_fig]); + end; + + // Graphics initialization + if (not Assigned(bmHiddenBoard)) then + begin + bmHiddenBoard := TBitmap.Create; + bmHiddenBoard.Palette := m_bmChessBoard.Palette; + bmHiddenBoard.Canvas.Font := PBoxBoard.Font; // Характеристики шрифта координат задаются в инспекторе + bmHiddenBoard.Canvas.Brush.Style := bsClear; + end; + bmHiddenBoard.Width := m_bmChessBoard.Width; + bmHiddenBoard.Height := m_bmChessBoard.Height; + + if (not Assigned(m_bmBuf)) then + begin + m_bmBuf := TBitmap.Create; + m_bmBuf.Palette:= m_bmChessBoard.Palette; + end; + + RDrawBoard; +end; + + +procedure TChessBoard.TimePanelResize(Sender: TObject); +var + rRatio: real; +begin + // Adjust panels on TimePanel + rRatio := TimePanel.Width / m_iTimePanelInitialWidth; + WhitePanel.Left := Round(rRatio * m_iWhitePanelInitialLeft); + WhitePanel.Width := m_iWhitePanelInitialWidth; + BlackPanel.Left := Round(rRatio * m_iBlackPanelInitialLeft); + BlackPanel.Width := m_iBlackPanelInitialWidth; + + + WhiteTimeLabel.Font.Assign(m_TimeFont); + BlackTimeLabel.Font.Assign(m_TimeFont); + if (WhitePanel.Left + WhitePanel.Width < BlackPanel.Left) then + begin + WhiteLabel.Caption := WHITE_LONG_LABEL; + BlackLabel.Caption := BLACK_LONG_LABEL; + end + else + begin + WhitePanel.Left := 4; + WhitePanel.Width := TimePanel.Width div 2; + BlackPanel.Left := TimePanel.Width div 2; + BlackPanel.Width := TimePanel.Width div 2 - 4; + + WhiteLabel.Caption := WHITE_MEDIUM_LABEL; + BlackLabel.Caption := BLACK_MEDIUM_LABEL; + end; + + // Adjust color labels + if ((WhiteTimeLabel.Left + WhiteTimeLabel.Width > WhitePanel.Width) or + (BlackTimeLabel.Left + BlackTimeLabel.Width > BlackPanel.Width)) then + begin + WhiteTimeLabel.Font.Size := WhiteTimeLabel.Font.Size - 4; + BlackTimeLabel.Font.Size := BlackTimeLabel.Font.Size - 4; + WhiteLabel.Caption := WHITE_SHORT_LABEL; + BlackLabel.Caption := BLACK_SHORT_LABEL; + end; +end; + + +procedure TChessBoard.FFlashWindow; +var + flushWindowInfo: TFlashWInfo; +begin + // Flash with taskbar + flushWindowInfo.cbSize := SizeOf(flushWindowInfo); + flushWindowInfo.hwnd := Application.Handle; + flushWindowInfo.dwflags := FLASHW_TRAY; // FLASHW_ALL; //FLASHW_TRAY; + flushWindowInfo.ucount := 3; // Flash times + flushWindowInfo.dwtimeout := 0; // speed in msec, 0 - frequency of cursor flashing + FlashWindowEx(flushWindowInfo); + + if (self.Focused) then + exit; + // Flash window + flushWindowInfo.hwnd := self.Handle; // handle of the flashing window + flushWindowInfo.dwflags := FLASHW_CAPTION; // FLASHW_TRAY; // FLASHW_ALL; //FLASHW_TRAY; + FlashWindowEx(flushWindowInfo); +end; + + +procedure TChessBoard.FLocalize; +begin + with TLocalizer.Instance do + begin + WHITE_LONG_LABEL := GetLabel(13); + WHITE_MEDIUM_LABEL := GetLabel(14); + WHITE_SHORT_LABEL := GetLabel(15); + BLACK_LONG_LABEL := GetLabel(16); + BLACK_MEDIUM_LABEL := GetLabel(17); + BLACK_SHORT_LABEL := GetLabel(18); + end; + + TimePanelResize(nil); +end; + +initialization + +begin + Randomize; // для PP Random +end; + +finalization + +end. diff --git a/plugins/Chess4Net/ChessRulesEngine.pas b/plugins/Chess4Net/ChessRulesEngine.pas new file mode 100644 index 0000000000..feb471b48b --- /dev/null +++ b/plugins/Chess4Net/ChessRulesEngine.pas @@ -0,0 +1,1018 @@ +unit ChessRulesEngine; + +interface + +uses + Classes; + +type + TFigureName = (K, Q, R, B, N, P); + TFigure = (WK, WQ, WR, WB, WN, WP, ES, + BK, BQ, BR, BB, BN, BP); // ES - Empty Square + TFigureColor = (fcWhite, fcBlack); + + PChessPosition = ^TChessPosition; + TChessPosition = record // шахматная позиция + board: array[1..8, 1..8] of TFigure; + color: TFigureColor; // Чей ход + castling: set of (WhiteKingSide, WhiteQueenSide, // Возможность рокировки + BlackKingSide, BlackQueenSide); + en_passant: 0..8; // Вертикаль возможности взятия e.p. 0 - нету e.p. + end; + + PMoveAbs = ^TMoveAbs; + TMoveAbs = record + i0, j0, i, j: byte; + prom_fig: TFigureName; + end; + + IChessRulesEngineable = interface + function AskPromotionFigure(FigureColor: TFigureColor): TFigureName; + end; + + TEvaluation = (evInGame, evMate, evStaleMate); + + TChessRulesEngine = class + private + m_ChessRulesEngineable: IChessRulesEngineable; + m_Position: TChessPosition; + m_i0, m_j0: integer; // Предыдущие координаты фигуры + m_fig: TFigure; // Перетаскиваемая фигура + m_lastMove: TMoveAbs; // Последний сделанный ход + m_strLastMoveStr: string; // last move in algebraic notation + m_lstPosition: TList; + + function FGetPosition: PChessPosition; + function FAskPromotionFigure(FigureColor: TFigureColor): TFigureName; + procedure FAddPosMoveToList; // Добавляет позицию и ход из неё в список + function FMove2Str(const pos: TChessPosition): string; + + function FCheckMove(const chp: TChessPosition; var chp_res: TChessPosition; + i0, j0, i, j: integer; var prom_fig: TFigureName): boolean; + + function FGetLastMove: PMoveAbs; + procedure FDelPosList; // Удаляет текущую позицию из списка + + function FDoMove(i, j: integer; prom_fig: TFigureName = K): boolean; overload; + + class function FFieldUnderAttack(const pos: TChessPosition; i0,j0: integer): boolean; // TODO: -> private ? + class function FCheckCheck(const pos: TChessPosition): boolean; + function FCanMove(pos: TChessPosition): boolean; + + property i0: integer read m_i0 write m_i0; + property j0: integer read m_j0 write m_j0; + property fig: TFigure read m_fig write m_fig; + + public + constructor Create(ChessRulesEngineable: IChessRulesEngineable = nil); + destructor Destroy; override; + + function DoMove(move_str: string): boolean; overload; + function DoMove(i0, j0, i, j: integer; prom_fig: TFigureName = K): boolean; overload; + function TakeBack: boolean; + function SetPosition(const posstr: string): boolean; + function GetPosition: string; + procedure InitNewGame; + procedure InitNewPPRandomGame; + procedure ResetMoveList; // очищает список позиций + function NMovesDone: integer; // amount of moves done + function GetEvaluation: TEvaluation; + + property Position: PChessPosition read FGetPosition; + property lastMove: PMoveAbs read FGetLastMove; + property lastMoveStr: string read m_strLastMoveStr; + property PositionsList: TList read m_lstPosition; + end; + + PPosMove = ^TPosMove; + TPosMove = record + pos: TChessPosition; + move: TMoveAbs; + end; + +const + INITIAL_CHESS_POSITION = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -'; + EMPTY_CHESS_POSITION = '8/8/8/8/8/8/8/8 w - -'; + +implementation + +{$J+} + +uses + SysUtils, StrUtils; + +type + TDeltaMove = array [TFigureName] of + record + longRange: boolean; + dx,dy: array[1..8] of Integer; + end; + +const + DELTA_MOVE: TDeltaMove = ((longRange: FALSE; // Король + dx: (1,0,-1,0, 1,-1,-1,1); dy: (0,1,0,-1, 1,1,-1,-1)), + (longRange: TRUE; // Ферзь + dx: (1,0,-1,0, 1,-1,-1,1); dy: (0,1,0,-1, 1,1,-1,-1)), + (longRange: TRUE; // Ладья + dx: (1,0,-1,0, 0,0,0,0); dy: (0,1,0,-1, 0,0,0,0)), + (longRange: TRUE; // Слон + dx: (1,-1,-1,1, 0,0,0,0); dy: (1,1,-1,-1, 0,0,0,0)), + (longRange: FALSE; // Конь + dx: (2,1,-1,-2, 2,1,-1,-2); dy: (1,2,2,1, -1,-2,-2,-1)), + (longRange: FALSE; // Пешка + dx: (0,0,-1,1, 0,0,0,0); dy: (2,1,1,1, 0,0,0,0))); + +//////////////////////////////////////////////////////////////////////////////// +// TChessRulesEngine + +constructor TChessRulesEngine.Create(ChessRulesEngineable: IChessRulesEngineable = nil); +begin + inherited Create; + m_ChessRulesEngineable := ChessRulesEngineable; + + // Инициализация списка позиций + m_lstPosition := TList.Create; +end; + + +destructor TChessRulesEngine.Destroy; +var + i: integer; +begin + for i := 0 to m_lstPosition.Count - 1 do + Dispose(m_lstPosition[i]); + m_lstPosition.Free; + + inherited; +end; + + +function TChessRulesEngine.FGetPosition: PChessPosition; +begin + Result := @m_Position; +end; + + +function TChessRulesEngine.FAskPromotionFigure(FigureColor: TFigureColor): TFigureName; +begin + if (Assigned(m_ChessRulesEngineable)) then + Result := m_ChessRulesEngineable.AskPromotionFigure(FigureColor) + else + Result := Q; +end; + + +class function TChessRulesEngine.FCheckCheck(const pos: TChessPosition): boolean; +label + l; +const + _i0: integer = 1; // для увеличения скорости обработки + _j0: integer = 1; +var + i, j: integer; +begin + with pos do + begin + if ((color = fcWhite) and (board[_i0, _j0] = WK)) or + ((color = fcBlack) and (board[_i0, _j0] = BK)) then goto l; + // поиск короля на доске + for i:= 1 to 8 do + begin + for j:= 1 to 8 do + begin + if ((color = fcWhite) and (board[i,j] = WK)) or + ((color = fcBlack) and (board[i,j] = BK)) then + begin + _i0 := i; + _j0 := j; + goto l; + end; + end; // for j + end; // for i +l: + Result := FFieldUnderAttack(pos, _i0, _j0); + end; +end; + + +class function TChessRulesEngine.FFieldUnderAttack(const pos: TChessPosition; i0, j0: integer): boolean; +var + f: TFigureName; + ef: TFigure; + l: byte; + ti,tj: Integer; + locLongRange: boolean; +begin + for f:= R to N do + for l:= 1 to 8 do + with DELTA_MOVE[f], pos do + begin + if (dx[l] = 0) and (dy[l] = 0) then break; // Все ходы просмотрены + ti:= i0; tj:= j0; + locLongRange:= FALSE; + repeat + ti:= ti + dx[l]; tj:= tj + dy[l]; + if not(ti in [1..8]) or not(tj in [1..8]) then break; + ef:= board[ti,tj]; + if ((color = fcWhite) and (ef < ES)) or ((color = fcBlack) and (ef > ES)) + then break; + case ef of + WK,BK: + if locLongRange or (f = N) then break; + WQ,BQ: + if f = N then break; + WR,BR: + if f <> R then break; + WB,BB: + if f <> B then break; + WN,BN: + if f <> N then break; + WP,BP: + if locLongRange or (f <> B) or + ((color = fcWhite) and not(tj > j0)) or + ((color = fcBlack) and not(tj < j0)) + then break; + ES: + begin + locLongRange:= TRUE; + continue; + end; + end; + Result:= TRUE; + exit; + until (not longRange); + end; + + Result := FALSE; +end; + + +function TChessRulesEngine.FCheckMove(const chp: TChessPosition; var chp_res: TChessPosition; + i0, j0, i, j: integer; var prom_fig: TFigureName): boolean; +label + here; +var + ti,tj: integer; + l: byte; + f: TFigureName; + _fig: TFigure; + pos: TChessPosition; +begin + Result:= FALSE; + if not ((i0 in [1..8]) and (j0 in [1..8]) and + (i in [1..8]) and (j in [1..8])) then exit; + + _fig := chp.board[i0, j0]; + if ((chp.color = fcWhite) and (_fig > ES)) or + ((chp.color = fcBlack) and (_fig < ES)) then + exit; + + f := TFigureName(ord(_fig) - ord(chp.color) * ord(BK)); + + for l:= 1 to 8 do + with DELTA_MOVE[f], chp do + begin + if (dx[l] = 0) and (dy[l] = 0) then break; // Все ходы просмотрены + ti:= i0; tj:= j0; + case f of + P: + begin + if (l = 1) and + not(((color = fcWhite) and (j0 = 2) and (board[i0,3] = ES)) or + ((color = fcBlack) and (j0 = 7) and (board[i0,6] = ES))) + then continue; // Пешка - не на 2/7 гор. - не делаем длинный ход. + case color of + fcWhite: + begin + ti:= ti + dx[l]; tj:= tj + dy[l]; + end; + fcBlack: + begin + ti:= ti - dx[l]; tj:= tj - dy[l]; + end; + end; + if not(ti in [1..8]) or not(tj in [1..8]) then continue; + if (l <= 2) and (board[ti,tj] <> ES) + then continue; // Перед пешкой фигура - выход + if (l >= 3) and not(((color = fcWhite) and ((board[ti,tj] > ES) or + ((j0 = 5) and (en_passant = ti)))) or + ((color = fcBlack) and ((board[ti,tj] < ES) or + ((j0 = 4) and (en_passant = ti))))) + then continue; + if (ti = i) and (tj = j) then goto here; + end; + else + repeat + ti:= ti + dx[l]; tj:= tj + dy[l]; + if not(ti in [1..8]) or not(tj in [1..8]) or + ((color = fcWhite) and ((board[ti,tj] < ES) or + ((board[ti,tj] > ES) and ((ti <> i) or (tj <> j))))) or + ((color = fcBlack) and ((board[ti,tj] > ES) or + ((board[ti,tj] < ES) and ((ti <> i) or (tj <> j))))) + then break; + if (ti = i) and (tj = j) then goto here; + until not longRange; + end; { case } + end; + + if f = K then // Проверка на возможность рокировки + with chp do + begin + if (i-i0 = 2) and (j = j0) and + (((color = fcWhite) and (WhiteKingSide in castling)) or + ((color = fcBlack) and (BlackKingSide in castling))) then + begin + if ((board[6,j0] <> ES) or (board[7,j0] <> ES) or // 0-0 + FFieldUnderAttack(chp,5,j0) or + FFieldUnderAttack(chp,6,j0)) then exit; + end + else if ((i-i0 = -2) and (j = j0) and + (((color = fcWhite) and (WhiteQueenSide in castling)) or + ((color = fcBlack) and (BlackQueenSide in castling)))) then + begin + if ((board[4,j0] <> ES) or (board[3,j0] <> ES) or // 0-0-0 + (board[2,j0] <> ES) or + FFieldUnderAttack(chp,5,j0) or + FFieldUnderAttack(chp,4,j0)) then + exit; + end + else exit; + + goto here; + end; + exit; // передвижение фигуры не по правилам +here: + // Реализация хода на pos + pos:= chp; + with pos do + begin + case f of + P: + begin + if (((color = fcWhite) and (j0 = 5)) or + ((color = fcBlack) and (j0 = 4))) and (i = en_passant) + then board[i,j0]:= ES; // убрать при e.p. враж. пешку + end; + K: + begin + if i-i0 = 2 then + begin + board[6,j0]:= board[8,j0]; // 0-0 + board[8,j0]:= ES; + end + else + if i0-i = 2 then + begin + board[4,j0]:= board[1,j0]; // 0-0-0 + board[1,j0]:= ES; + end; + case color of + fcWhite: + castling:= castling - [WhiteKingSide, WhiteQueenSide]; + fcBlack: + castling:= castling - [BlackKingSide, BlackQueenSide]; + end; + end; + R: + begin + if ((i0 = 8) and (j0 = 1)) or ((i = 8) and (j = 1)) + then castling:= castling - [WhiteKingSide] + else + if ((i0 = 1) and (j0 = 1)) or ((i = 1) and (j = 1)) + then castling:= castling - [WhiteQueenSide] + else + if ((i0 = 8) and (j0 = 8)) or ((i = 8) and (j = 8)) + then castling:= castling - [BlackKingSide] + else + if ((i0 = 1) and (j0 = 8)) or ((i = 1) and (j = 8)) + then castling:= castling - [BlackQueenSide]; + end; + end; + if (f = P) and (abs(j-j0) = 2) and + (((i > 1) and (((color = fcWhite) and (board[i-1,j] = BP)) or + ((color = fcBlack) and (board[i-1,j] = WP)))) or + ((i < 8) and (((color = fcWhite) and (board[i+1,j] = BP)) or + ((color = fcBlack) and (board[i+1,j] = WP))))) then + en_passant := i0 // вкл. e.p. + else + en_passant := 0; // выкл. e.p. + // Сделать ход + board[i0, j0]:= ES; + board[i, j] := _fig; + if (FCheckCheck(pos)) then + exit; // ход невозможен из-за шаха + if (f = P) and ((j = 1) or (j = 8)) then + begin + case prom_fig of + Q..N: ; + else + prom_fig := FAskPromotionFigure(pos.color); + end; // case + board[i, j] := TFigure(ord(color) * ord(BK) + ord(prom_fig)); + end; + if color = fcWhite then color:= fcBlack + else color:= fcWhite; + end; + + chp_res:= pos; + Result:= TRUE; +end; + + +function TChessRulesEngine.FCanMove(pos: TChessPosition): boolean; +var + i,j: integer; + ti,tj: integer; + l: byte; + f: TFigureName; + prom_fig: TFigureName; +begin + with pos do + for i:= 1 to 8 do + for j:= 1 to 8 do + begin + if ((color = fcWhite) and (board[i,j] >= ES)) or + ((color = fcBlack) and (board[i,j] <= ES)) then continue; + + f:= TFigureName(ord(board[i,j]) - ord(color) * ord(BK)); + for l:= 1 to 8 do + with DELTA_MOVE[f] do + begin + if (dx[l] = 0) and (dy[l] = 0) then break; // Все ходы просмотрены + ti:= i; tj:= j; + repeat + case color of + fcWhite: + begin + ti:= ti + dx[l]; tj:= tj + dy[l]; + end; + fcBlack: + begin + ti:= ti - dx[l]; tj:= tj - dy[l]; + end; + end; + if not ((ti in [1..8]) and (tj in [1..8])) then break; + prom_fig := Q; + if FCheckMove(pos, pos, i, j, ti, tj, prom_fig) then + begin + Result:= TRUE; + exit; + end; + until not longRange; + end; + end; + Result:= FALSE; +end; + + +function TChessRulesEngine.DoMove(move_str: string): boolean; +label + l1, l2; +var + l: byte; + f, prom_f: TFigureName; + i, j, ti,tj: integer; +begin + // Проверка на рокировку + if (move_str = '0-0') then + begin + if (Position.color = fcWhite) then + move_str:= 'Ke1g1' + else + move_str:= 'Ke8g8' + end + else if (move_str = '0-0-0') then + begin + if (Position.color = fcWhite) then + move_str:= 'Ke1c1' + else + move_str:= 'Ke8c8'; + end; + + i0 := 0; + j0 := 0; + i := 0; + j := 0; + + l := length(move_str); + prom_f := K; + case move_str[l] of + 'Q': prom_f := Q; + 'R': prom_f := R; + 'B': prom_f := B; + 'N': prom_f := N; + else goto l1; + end; + dec(l); +l1: + if move_str[l] in ['1'..'8'] then + begin + j:= StrToInt(move_str[l]); + dec(l); + end; + if move_str[l] in ['a'..'h'] then + begin + i:= ord(move_str[l]) - ord('a') + 1; + dec(l); + end; + if (l > 0) and (move_str[l] in ['1'..'8']) then + begin + j0 := StrToInt(move_str[l]); + dec(l); + end; + if (l > 0) and (move_str[l] in ['a'..'h']) then + begin + i0 := ord(move_str[l]) - ord('a') + 1; + dec(l); + end; + + if l = 0 then f:= P + else + case move_str[l] of + 'K': f:= K; + 'Q': f:= Q; + 'R': f:= R; + 'B': f:= B; + 'N': f:= N; + end; + + with Position^ do + begin + fig := TFigure(ord(f) + ord(Position.color) * ord(BK)); + + case f of + K..N: // Ход Кр - К + begin + for l:= 1 to 8 do + with DELTA_MOVE[f] do + begin + if (dx[l] = 0) and (dy[l] = 0) then break; // Все ходы просмотрены + ti:= i; tj:= j; + repeat + ti:= ti + dx[l]; tj:= tj + dy[l]; + if not ((ti in [1..8]) and (tj in [1..8])) or + ((board[ti,tj] <> ES) and (board[ti,tj] <> fig)) then break; + + if ((i0 = 0) or (i0 = ti)) and ((j0 = 0) or (j0 = tj)) and + (board[ti,tj] = fig) then + begin // Ходящая фигура найдена + i0 := ti; + j0 := tj; + goto l2; + end; + until (f = K) or (f = N); // Если Кр или К, то выход + end; + end; + P: // Ход пешкой + begin + if (i0 <> 0) and (i0 <> i) then // взятие пешкой + begin + for l:= 2 to 7 do + if (board[i0, l] = fig) and ((j0 = 0) or (j0 = l)) then + if color = fcWhite then + begin + if ((board[i,l+1] > ES) or + ((l = 5) and (en_passant = i))) and + ((j = 0) or (j = l+1)) and (abs(i - i0) = 1) then + begin + j0 := l; + j := l + 1; + goto l2; + end; + end + else // color = fcBlack + if ((board[i,l-1] < ES) or + ((l = 4) and (en_passant = i))) and + ((j = 0) or (j = l-1)) and (abs(i - i0) = 1) then + begin + j0 := l; + j := l-1; + goto l2; + end; + end + else // Ход прямо + begin + i0 := i; + if color = fcWhite then + begin + if board[i, j - 1] = fig then + j0 := j - 1 + else if (j = 4) and (board[i, 3] = ES) and + (board[i,2] = fig) then + j0 := 2; + end + else // color = fcBlack + if board[i,j+1] = fig then + j0 := j + 1 + else if (j = 5) and (board[i,6] = ES) and + (board[i, 7] = fig) then + j0 := 7; + end; + end; + end; + end; +l2: + Result := FDoMove(i, j, prom_f); +end; + + +function TChessRulesEngine.FDoMove(i, j: integer; prom_fig: TFigureName = K): boolean; +var + newPosition: TChessPosition; +begin + Result := FCheckMove(Position^, newPosition, i0, j0, i, j, prom_fig); + if (Result) then + begin + // запоминание сделанного хода + lastMove.i0 := i0; + lastMove.j0 := j0; + lastMove.i := i; + lastMove.j := j; + lastMove.prom_fig := prom_fig; + + FAddPosMoveToList; + + m_strLastMoveStr := FMove2Str(newPosition); + Position^ := newPosition; + end; +end; + + +function TChessRulesEngine.DoMove(i0, j0, i, j: integer; prom_fig: TFigureName = K): boolean; +begin + self.i0 := i0; + self.j0 := j0; + Result := FDoMove(i, j, prom_fig); +end; + + +function TChessRulesEngine.FGetLastMove: PMoveAbs; +begin + Result := @m_lastMove; +end; + + +procedure TChessRulesEngine.FAddPosMoveToList; +var + pm: PPosMove; +begin + new(pm); + pm.pos := Position^; + pm.move := lastMove^; + PositionsList.Add(pm); +end; + + +function TChessRulesEngine.FMove2Str(const pos: TChessPosition): string; +var + f: TFigureName; + l: byte; + ti, tj: integer; + ambig, hor, ver: boolean; + _fig: TFigure; +begin + if lastMove.i0 = 0 then // Ход не задан + begin + Result:= ''; + exit; + end; + + _fig := Position.board[lastMove.i0, lastMove.j0]; + f := TFigureName(ord(_fig) + (ord(pos.color) - 1) * ord(BK)); + // Ход пешкой + if (f = P) then + begin + with pos do + begin + if ((lastMove.i - lastMove.i0) = 0) then // ход + Result:= chr(ord('a') + lastMove.i - 1) + IntToStr(lastMove.j) + else // взятие + begin + Result:= chr(ord('a') + lastMove.i0 - 1) + chr(ord('a') + lastMove.i - 1); + + for l := 2 to 7 do // Проверка на двусмысленность взятия + if (((board[lastMove.i0, l] = WP) and ((Position.board[lastMove.i, l+1] > ES) or + ((Position.en_passant = lastMove.i) and (l = 5)))) and (color = fcBlack)) or + (((board[lastMove.i0, l] = BP) and ((Position.board[lastMove.i, l-1] < ES) or + ((Position.en_passant = lastMove.i) and (l = 4)))) and (color = fcWhite)) + then Result:= Result + IntToStr(lastMove.j); + end; + + if (lastMove.j = 8) or (lastMove.j = 1) then // Пешка превратилась + case board[lastMove.i,lastMove.j] of + WQ,BQ: Result:= Result + 'Q'; + WR,BR: Result:= Result + 'R'; + WB,BB: Result:= Result + 'B'; + WN,BN: Result:= Result + 'N'; + end; + exit; + end; + end; // if + + // <Фигура> + case f of + K: Result:= 'K'; + Q: Result:= 'Q'; + R: Result:= 'R'; + B: Result:= 'B'; + N: Result:= 'N'; + end; + // [<Вертикаль>][<Горизонталь>] + ambig:= FALSE; + hor:= FALSE; + ver:= FALSE; + for l := 1 to 8 do + with pos, DELTA_MOVE[f] do + begin + if (dx[l] = 0) and (dy[l] = 0) then + break; // Все ходы просмотрены + ti := lastMove.i; + tj := lastMove.j; + repeat + ti:= ti + dx[l]; tj:= tj + dy[l]; + if not (ti in [1..8]) or not (tj in [1..8]) or + ((board[ti,tj] <> ES) and (board[ti,tj] <> _fig)) then + break; + if (board[ti,tj] = _fig) then + begin + ambig:= TRUE; + ver:= ver or (ti = lastMove.i0); hor:= hor or (tj = lastMove.j0); + break; + end; + until (f = K) or (f = N); // Если Кр или К, то выход + end; + + if ambig then + begin + if not ver or hor then + Result:= Result + chr(ord('a') + lastMove.i0 - 1); + if ver then + Result := Result + IntToStr(lastMove.j0); + end; + + // <Конечное поле> + Result := Result + chr(ord('a') + lastMove.i - 1) + IntToStr(lastMove.j); + + // <Короткая рокировка> | <Длинная рокировка> + if f = K then + begin + if lastMove.i - lastMove.i0 = 2 then + Result:= '0-0' + else if lastMove.i0 - lastMove.i = 2 then + Result:= '0-0-0'; + end; +end; + + +function TChessRulesEngine.TakeBack: boolean; +begin + Result := (PositionsList.Count > 0); + if (Result) then + FDelPosList; +end; + + +procedure TChessRulesEngine.FDelPosList; +var + i: integer; +begin + i := PositionsList.Count - 1; + if (i >= 0) then + begin + Position^ := PPosMove(PositionsList[i]).pos; + Dispose(PositionsList[i]); + PositionsList.Delete(i); + end; +end; + + +function TChessRulesEngine.SetPosition(const posstr: string): boolean; +var + i, j, k: integer; + l: byte; + pos: TChessPosition; +begin + Result:= FALSE; + + l := 1; + for j := 8 downto 1 do + begin + i := 1; + repeat + case posstr[l] of + 'K': pos.board[i,j]:= WK; + 'Q': pos.board[i,j]:= WQ; + 'R': pos.board[i,j]:= WR; + 'B': pos.board[i,j]:= WB; + 'N': pos.board[i,j]:= WN; + 'P': pos.board[i,j]:= WP; + + 'k': pos.board[i,j]:= BK; + 'q': pos.board[i,j]:= BQ; + 'r': pos.board[i,j]:= BR; + 'b': pos.board[i,j]:= BB; + 'n': pos.board[i,j]:= BN; + 'p': pos.board[i,j]:= BP; + + '1'..'8': // Вставка пустых полей + begin + k:= StrToInt(posstr[l]); + repeat + pos.board[i,j]:= ES; + dec(k); inc(i); + until k = 0; + dec(i); + end; + + ' ': break; // Позиция прочитана - выход из цикла + + else exit; // ошибка в posstr + end; + inc(i); inc(l); + until (posstr[l] = '/') or (i > 8); // Повтор до появления '/' или пока на горизонтали + inc(l); + end; + + case posstr[l] of + 'w': pos.color:= fcWhite; + 'b': pos.color:= fcBlack; + else exit; + end; + + inc(l,2); + pos.castling:= []; + while posstr[l] <> ' ' do + begin + with pos do + case posstr[l] of + 'K': castling:= castling + [WhiteKingSide]; + 'Q': castling:= castling + [WhiteQueenSide]; + 'k': castling:= castling + [BlackKingSide]; + 'q': castling:= castling + [BlackQueenSide]; + '-': + if castling <> [] then exit + else + begin + inc(l); + break; + end; + else + exit; + end; + inc(l); + end; + + inc(l); + with pos do + case posstr[l] of + 'a'..'h': en_passant:= ord(posstr[l]) - ord('a') + 1; + '-': en_passant:= 0; + else + exit; + end; + + if (Trim(RightStr(posstr, length(posstr) - l)) <> '') then + exit; + + Position^ := pos; + lastMove.i0 := 0; // предыдущего хода ещё не было + + Result := TRUE; +end; + + +procedure TChessRulesEngine.InitNewGame; +begin + SetPosition(INITIAL_CHESS_POSITION); + ResetMoveList; +end; + + +procedure TChessRulesEngine.ResetMoveList; +var + i: integer; +begin + for i := 0 to PositionsList.Count - 1 do + Dispose(PositionsList[i]); + PositionsList.Clear; +end; + + +function TChessRulesEngine.GetPosition: string; +var + i,j: Integer; + k: byte; + chFig: char; +begin + Result:= ''; + + with Position^ do + begin + // Расстановка фигур + for j := 8 downto 1 do + begin + k:= 0; + for i:= 1 to 8 do + begin + case board[i,j] of + WK: chFig := 'K'; + WQ: chFig := 'Q'; + WR: chFig := 'R'; + WB: chFig := 'B'; + WN: chFig := 'N'; + WP: chFig := 'P'; + BK: chFig := 'k'; + BQ: chFig := 'q'; + BR: chFig := 'r'; + BB: chFig := 'b'; + BN: chFig := 'n'; + BP: chFig := 'p'; + ES: + begin + inc(k); + continue; + end; + end; + + if k > 0 then + begin + Result:= Result + IntToStr(k); + k:= 0; + end; + + Result := Result + chFig; + end; + + if k > 0 then Result:= Result + IntToStr(k); + if j = 1 then Result:= Result + ' ' + else Result:= Result + '/'; // i <= 7 + end; + + if color = fcWhite then Result:= Result + 'w ' + else Result:= Result + 'b '; // color = fcBlack + // Рокировка + if castling = [] then Result:= Result + '-' + else + begin + if WhiteKingSide in castling then Result:= Result + 'K'; + if WhiteQueenSide in castling then Result:= Result + 'Q'; + if BlackKingSide in castling then Result:= Result + 'k'; + if BlackQueenSide in castling then Result:= Result + 'q'; + end; + // en-passant + if (en_passant = 0) then + Result := Result + ' -' + else + Result := Result + ' ' + Chr(Ord('a') - 1 + en_passant); + end; +end; + + +procedure TChessRulesEngine.InitNewPPRandomGame; +const + FIG: array[0..5] of TFigureName = (B, B, Q, R, N, N); + SQR: array[0..5] of byte = (2, 3, 4, 6, 7, 0); +var + rnd_sqr: array[0..5] of byte; + i,j: integer; + f: boolean; +begin + InitNewGame; + if (Random(2) = 0) then + SQR[5] := 1 // с какой стороны оставляем ладью + else + SQR[5] := 8; + + for i := 0 to 5 do + begin + repeat + rnd_sqr[i] := SQR[Random(6)]; + f := FALSE; + for j := 0 to i-1 do f := f or (rnd_sqr[i] = rnd_sqr[j]); + until not (f or ((i = 1) and (((rnd_sqr[0] xor rnd_sqr[1]) and 1) = 0))); + Position.board[rnd_sqr[i], 1] := TFigure(ord(FIG[i])); + Position.board[rnd_sqr[i], 8] := TFigure(ord(BK) + ord(FIG[i])); + end; +end; + + +function TChessRulesEngine.NMovesDone: integer; +begin + Result := (PositionsList.Count + 1) shr 1; // div 2 +end; + + +function TChessRulesEngine.GetEvaluation: TEvaluation; +begin + Result := evInGame; + if (not FCanMove(Position^)) then + begin + if (FCheckCheck(Position^)) then + Result := evMate + else + Result := evStaleMate; + end; + // TODO: Evaluate position for possible technical draw +end; + +end. diff --git a/plugins/Chess4Net/ChessSet.res b/plugins/Chess4Net/ChessSet.res new file mode 100644 index 0000000000..869af68809 Binary files /dev/null and b/plugins/Chess4Net/ChessSet.res differ diff --git a/plugins/Chess4Net/ChessSet_PNG.RES b/plugins/Chess4Net/ChessSet_PNG.RES new file mode 100644 index 0000000000..31328ca9fb Binary files /dev/null and b/plugins/Chess4Net/ChessSet_PNG.RES differ diff --git a/plugins/Chess4Net/ClientQueueUnit.pas b/plugins/Chess4Net/ClientQueueUnit.pas new file mode 100644 index 0000000000..68e6b50558 --- /dev/null +++ b/plugins/Chess4Net/ClientQueueUnit.pas @@ -0,0 +1,159 @@ +unit ClientQueueUnit; + +interface + +type + TClientName = string[25]; + + PClientNode = ^TClientNode; + + TClientNode = record + n: word; + name: TClientName; + handler: pointer; + next: PClientNode; + end; + + TClientQueue = object + Number: word; + procedure Add(const handler: pointer; const name: TClientName = ''); + procedure Remove(const handler: pointer); + function GetName(const handler: pointer): TClientName; + function GetNum(const handler: pointer): word; + function GetHandler(const num: word): pointer; +{ + function Contains(const handler: pointer): boolean; +} + constructor Create(const max: word); + destructor Free; + private + first: PClientNode; + MaxClientsNum: word; + end; + +implementation + +function TClientQueue.GetHandler(const num: word): pointer; +var + n: PClientNode; +begin + n:= first; + while n <> nil do + begin + if num = n^.n then + begin + Result:= n^.handler; + exit; + end; + n:= n^.next; + end; + Result:= nil; +end; + +procedure TClientQueue.Add(const handler: pointer; const name: TClientName); +var + n: PClientNode; + p: ^PClientNode; +begin + if Number = MaxClientsNum then exit; + + n:= first; p:= @first; + while n <> nil do + begin + p:= addr(n^.next); + n:= n^.next; + end; + new(n); inc(Number); + n^.name:= name; + n^.handler:= handler; + n^.next:= nil; + n^.n:= Number; + p^:= n; +end; + +procedure TClientQueue.Remove(const handler: pointer); +var + n: PClientNode; + p: ^PClientNode; +begin + n:= first; p:= @first; + while n <> nil do + begin + if n^.handler = handler then + begin + n:= n^.next; + dispose(p^); + p^:= n; + break; + end; + p:= addr(n^.next); + n:= n^.next; + end; + + while n <> nil do + begin + dec(n^.n); + n:= n^.next; + end; + dec(Number); +end; + + +function TClientQueue.GetName(const handler: pointer): TClientName; +var + n: PClientNode; +begin + n:= first; + while n <> nil do + begin + if handler = n^.handler then + begin + Result:= n^.name; + exit; + end; + n:= n^.next; + end; + Result:= ''; +end; + +function TClientQueue.GetNum(const handler: pointer): word; +var + n: PClientNode; +begin + n:= first; + while n <> nil do + begin + if handler = n^.handler then + begin + Result:= n^.n; + exit; + end; + n:= n^.next; + end; + Result:= 0; +end; + +{ +function TClientQueue.Contains(const handler: pointer): boolean; +} + +constructor TClientQueue.Create(const max: word); +begin + MaxClientsNum:= max; +end; + + +destructor TClientQueue.Free; +var + n: PClientNode; +begin + while first <> nil do + begin + n:= first^.next; + dispose(first); + first:= n; + end; + Number:= 0; +end; + +end. diff --git a/plugins/Chess4Net/Connecting.ico b/plugins/Chess4Net/Connecting.ico new file mode 100644 index 0000000000..433a21ee1d Binary files /dev/null and b/plugins/Chess4Net/Connecting.ico differ diff --git a/plugins/Chess4Net/ConnectingUnit.dfm b/plugins/Chess4Net/ConnectingUnit.dfm new file mode 100644 index 0000000000..b741f35ac7 --- /dev/null +++ b/plugins/Chess4Net/ConnectingUnit.dfm @@ -0,0 +1,72 @@ +object ConnectingForm: TConnectingForm + Left = 583 + Top = 234 + BorderStyle = bsDialog + Caption = 'Connecting...' + ClientHeight = 92 + ClientWidth = 300 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Microsoft Sans Serif' + Font.Style = [] + OldCreateOrder = False + OnClose = FormClose + OnCreate = FormCreate + OnShow = FormShow + PixelsPerInch = 96 + TextHeight = 13 + object ConnectingLabel: TTntLabel + Left = 64 + Top = 16 + Width = 233 + Height = 13 + AutoSize = False + Caption = 'Wait until the connection is completed.' + end + object ConnectingImage: TImage + Left = 16 + Top = 16 + Width = 33 + Height = 33 + Picture.Data = { + 055449636F6E0000010001002020100000000000E80200001600000028000000 + 2000000040000000010004000000000080020000000000000000000000000000 + 0000000000000000000080000080000000808000800000008000800080800000 + 80808000C0C0C0000000FF0000FF000000FFFF00FF000000FF00FF00FFFF0000 + FFFFFF00000000000000000000A000000000000000FFFFFFFFFFF0000AA00000 + 00000000000F0F0F0F0F0000AAAAAA2A000000000000FFFFFFF0000AAAAAAAA2 + AA0000000FF800000008FF00AAAAAAAA2A2000000F9FFFFFFFF000000AA00002 + A2A000000FFFFFFFFFFFFF0000A000000A2A0000000000000000004400000000 + 02A20000000000000000444444000000002A20000000FFFFFFF0C4C4C4C40000 + 0002A0000000F00000F0444444444000000620000000F0EEC0F0C4C4C4C4C400 + 0002A0000040F0CEC0F04C444C444C40000620000040F00000F0C4C4C4C4C4C0 + 0002A0000440FFFFFFF04CCC4C4C4C4400062000044000000000C4C4C4C4C4C3 + 0002600044444C4433333CCCCC4CCC433006200044C4C4C4333333C4C4C4C4C3 + 3002600044444C43333333CCCCCCCC43322222224444C4C333333CC4CCC4C4C3 + 3222222244444C433333CCCCCCCC33333E22E22244C4C4C334C4C4CCCCCC3333 + 3E22E222444444433CCCC3CCCCCC33333E22E2220444C4C433C433C4CCC4C333 + 2EEEE22204444343333333CCCCCCCC4C2EEEE2220044C333333333C4C4C433E2 + 2EEEE22E00444333333333CCCCCC33EE2EEEE2EE0004C333333333C4C3C4332E + EEEEEEE200004333333C333CC3433022EEEEEE22000004333334C333C4C30022 + 22EE2222000000044433444C440000222EEEE2220000000004C4C4C400000022 + 22EE22228003DFFF80039FFFC00700FF0000003F0001001F00019E1F0001DF8F + 8000FF8FE0003FC7E0000FE7E00007E7E00003E7C00001E7C00001E7800000E7 + 800000E700000067000000670000000000000000000000000000000000000000 + 8000000080000000C0000000C0000000E0000000F0000400F8000C00FE003C00 + FF80FC00} + end + object AbortButton: TTntButton + Left = 112 + Top = 56 + Width = 75 + Height = 25 + Cancel = True + Caption = '&Abort' + Default = True + ModalResult = 3 + TabOrder = 0 + OnClick = AbortButtonClick + end +end diff --git a/plugins/Chess4Net/ConnectingUnit.pas b/plugins/Chess4Net/ConnectingUnit.pas new file mode 100644 index 0000000000..9b7bae3c05 --- /dev/null +++ b/plugins/Chess4Net/ConnectingUnit.pas @@ -0,0 +1,110 @@ +unit ConnectingUnit; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, TntStdCtrls, + Forms, {Dialogs, }ExtCtrls, StdCtrls, + DialogUnit, ModalForm; + +type + TConnectingHandler = procedure of object; + + TConnectingForm = class(TModalForm) + AbortButton: TTntButton; + ConnectingLabel: TTntLabel; + ConnectingImage: TImage; + procedure AbortButtonClick(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormShow(Sender: TObject); + procedure FormCreate(Sender: TObject); + private +// dlgOwner: TDialogs; + ConnectingHandler: TConnectingHandler; + shuted: boolean; + procedure FLocalize; + protected + function GetModalID : TModalFormID; override; + public + procedure Shut; + constructor Create(Owner: TForm; h: TConnectingHandler = nil); reintroduce; overload; +// constructor Create(dlgOwner: TDialogs; h: TConnectingHandler); reintroduce; overload; + end; + +implementation + +{$R *.dfm} + +uses + LocalizerUnit; + +//////////////////////////////////////////////////////////////////////////////// +// TConnectiongForm + +procedure TConnectingForm.AbortButtonClick(Sender: TObject); +begin + Close; +end; + + +procedure TConnectingForm.FormShow(Sender: TObject); +var + frmOwner: TForm; +begin + frmOwner := (Owner as TForm); + Left:= frmOwner.Left + (frmOwner.Width - Width) div 2; + Top:= frmOwner.Top + (frmOwner.Height - Height) div 2; +end; + +constructor TConnectingForm.Create(Owner: TForm; h: TConnectingHandler = nil); +begin + self.FormStyle := Owner.FormStyle; + inherited Create(Owner); + shuted := FALSE; + ConnectingHandler := h; +end; + + +procedure TConnectingForm.FormClose(Sender: TObject; + var Action: TCloseAction); +begin + if not shuted then + begin + ModalResult := AbortButton.ModalResult; + if Assigned(ConnectingHandler) then + ConnectingHandler; + end + else + ModalResult := mrNone; +end; + + +procedure TConnectingForm.Shut; +begin + shuted:= TRUE; + Close; +end; + +function TConnectingForm.GetModalID: TModalFormID; +begin + Result := mfConnecting; +end; + + +procedure TConnectingForm.FLocalize; +begin + with TLocalizer.Instance do + begin + Caption := GetLabel(19); + ConnectingLabel.Caption := GetLabel(20); + AbortButton.Caption := GetLabel(21); + end; +end; + + +procedure TConnectingForm.FormCreate(Sender: TObject); +begin + FLocalize; +end; + +end. diff --git a/plugins/Chess4Net/ConnectionUnit.dfm b/plugins/Chess4Net/ConnectionUnit.dfm new file mode 100644 index 0000000000..859a295178 --- /dev/null +++ b/plugins/Chess4Net/ConnectionUnit.dfm @@ -0,0 +1,118 @@ +object ConnectionForm: TConnectionForm + Left = 298 + Top = 145 + BorderIcons = [biSystemMenu] + BorderStyle = bsDialog + Caption = 'Connection Setup' + ClientHeight = 171 + ClientWidth = 292 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + KeyPreview = True + OldCreateOrder = False + OnKeyPress = FormKeyPress + OnShow = FormShow + PixelsPerInch = 96 + TextHeight = 13 + object NickLabel: TLabel + Left = 8 + Top = 8 + Width = 50 + Height = 13 + Caption = 'Your Nick:' + end + object IPLabel: TLabel + Left = 8 + Top = 115 + Width = 95 + Height = 13 + Caption = 'IP or Domain Name:' + end + object PortLabel: TLabel + Left = 152 + Top = 115 + Width = 32 + Height = 13 + Caption = 'Port #:' + end + object NickEdit: TEdit + Left = 8 + Top = 24 + Width = 121 + Height = 21 + MaxLength = 15 + TabOrder = 0 + Text = 'NN' + OnExit = NickEditExit + end + object ConnectionRadioGroup: TRadioGroup + Left = 8 + Top = 56 + Width = 185 + Height = 49 + Caption = 'Connect as' + TabOrder = 1 + end + object ServerRadioButton: TRadioButton + Left = 24 + Top = 72 + Width = 57 + Height = 17 + Caption = 'Server' + Checked = True + TabOrder = 2 + TabStop = True + OnClick = ServerRadioButtonClick + end + object ClientRadioButton: TRadioButton + Left = 120 + Top = 72 + Width = 49 + Height = 17 + Caption = 'Client' + TabOrder = 3 + OnClick = ClientRadioButtonClick + end + object OKButton: TButton + Left = 208 + Top = 16 + Width = 75 + Height = 25 + Caption = '&OK' + ModalResult = 1 + TabOrder = 6 + end + object CancelButton: TButton + Left = 208 + Top = 56 + Width = 75 + Height = 25 + Caption = '&Cancel' + ModalResult = 2 + TabOrder = 7 + end + object IPEdit: TEdit + Left = 8 + Top = 131 + Width = 133 + Height = 21 + Enabled = False + TabOrder = 4 + OnChange = IPEditChange + end + object PortEdit: TMaskEdit + Left = 152 + Top = 131 + Width = 42 + Height = 21 + EditMask = '09999;; ' + MaxLength = 5 + TabOrder = 5 + Text = '5555 ' + OnExit = PortEditExit + end +end diff --git a/plugins/Chess4Net/ConnectionUnit.pas b/plugins/Chess4Net/ConnectionUnit.pas new file mode 100644 index 0000000000..482094afe4 --- /dev/null +++ b/plugins/Chess4Net/ConnectionUnit.pas @@ -0,0 +1,107 @@ +unit ConnectionUnit; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, ExtCtrls, Mask; + +type + TConnectionForm = class(TForm) + NickLabel: TLabel; + NickEdit: TEdit; + ConnectionRadioGroup: TRadioGroup; + ServerRadioButton: TRadioButton; + ClientRadioButton: TRadioButton; + OKButton: TButton; + CancelButton: TButton; + IPEdit: TEdit; + IPLabel: TLabel; + PortLabel: TLabel; + PortEdit: TMaskEdit; + procedure FormShow(Sender: TObject); + procedure ServerRadioButtonClick(Sender: TObject); + procedure ClientRadioButtonClick(Sender: TObject); + procedure NickEditExit(Sender: TObject); + procedure FormKeyPress(Sender: TObject; var Key: Char); + procedure IPEditChange(Sender: TObject); + procedure PortEditExit(Sender: TObject); + public + function GetPort: word; + constructor Create(Owner: TComponent); reintroduce; + end; + +implementation + +{$R *.dfm} + +uses + GlobalsLocalUnit; + +procedure TConnectionForm.ServerRadioButtonClick(Sender: TObject); +begin + IPEdit.Enabled := FALSE; + OKButton.Enabled := TRUE; +end; + +procedure TConnectionForm.FormShow(Sender: TObject); +var + frmOwner: TForm; +begin + frmOwner := (Owner as TForm); + Left:= frmOwner.Left + (frmOwner.Width - Width) div 2; + Top:= frmOwner.Top + (frmOwner.Height - Height) div 2; +end; + +procedure TConnectionForm.ClientRadioButtonClick(Sender: TObject); +begin + IPEdit.Enabled:= TRUE; + if IPEdit.Text <> '' then OKButton.Enabled:= TRUE + else OKButton.Enabled:= FALSE; +end; + +procedure TConnectionForm.PortEditExit(Sender: TObject); +begin + PortEdit.Text := IntToStr(GetPort); +end; + +procedure TConnectionForm.NickEditExit(Sender: TObject); +begin + if NickEdit.Text = '' then NickEdit.Text:= 'NN'; +end; + +procedure TConnectionForm.FormKeyPress(Sender: TObject; var Key: Char); +begin + if Key = #13 then ModalResult:= mrOk; +end; + +procedure TConnectionForm.IPEditChange(Sender: TObject); +begin + if IPEdit.Text <> '' then OKButton.Enabled:= TRUE + else OKButton.Enabled:= FALSE; +end; + +constructor TConnectionForm.Create(Owner: TComponent); +begin + FormStyle := (Owner as TForm).FormStyle; + inherited; + PortEdit.Text := IntToStr(DEFAULT_PORT); +end; + +function TConnectionForm.GetPort: word; +var + port: integer; +begin + try + port := StrToInt(Trim(PortEdit.Text)); + if (port > 0) and (port <= $FFFF) then + Result := port + else + Result := DEFAULT_PORT + except + on EConvertError do + Result := DEFAULT_PORT; + end; +end; + +end. diff --git a/plugins/Chess4Net/ContinueUnit.dfm b/plugins/Chess4Net/ContinueUnit.dfm new file mode 100644 index 0000000000..f2e442ef9e --- /dev/null +++ b/plugins/Chess4Net/ContinueUnit.dfm @@ -0,0 +1,40 @@ +object ContinueForm: TContinueForm + Left = 649 + Top = 305 + BorderStyle = bsDialog + ClientHeight = 75 + ClientWidth = 210 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Microsoft Sans Serif' + Font.Style = [] + OldCreateOrder = False + OnClose = FormClose + OnCreate = FormCreate + OnShow = FormShow + PixelsPerInch = 96 + TextHeight = 13 + object ContinueLabel: TTntLabel + Left = 0 + Top = 12 + Width = 209 + Height = 13 + Alignment = taCenter + AutoSize = False + Caption = 'Press button to continue the game.' + end + object ContinueButton: TTntButton + Left = 67 + Top = 38 + Width = 75 + Height = 25 + Cancel = True + Caption = '&Continue' + Default = True + ModalResult = 1 + TabOrder = 0 + OnClick = ContinueButtonClick + end +end diff --git a/plugins/Chess4Net/ContinueUnit.pas b/plugins/Chess4Net/ContinueUnit.pas new file mode 100644 index 0000000000..9e6fd49c34 --- /dev/null +++ b/plugins/Chess4Net/ContinueUnit.pas @@ -0,0 +1,111 @@ +unit ContinueUnit; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, + {Dialogs, }ExtCtrls, StdCtrls, TntStdCtrls, + DialogUnit, ModalForm; + +type + TContinueHandler = procedure of object; + + TContinueForm = class(TModalForm) + ContinueButton: TTntButton; + ContinueLabel: TTntLabel; + procedure ContinueButtonClick(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormShow(Sender: TObject); + procedure FormCreate(Sender: TObject); + private +// dlgOwner: TDialogs; + ContinueHandler: TContinueHandler; + shuted: boolean; + procedure FLocalize; + protected + function GetModalID: TModalFormID; override; + public + procedure Shut; + constructor Create(Owner: TForm; h: TContinueHandler = nil); reintroduce; overload; +// constructor Create(dlgOwner: TDialogs; h: TContinueHandler); reintroduce; overload; + end; + +implementation + +{$R *.dfm} + +uses + GlobalsUnit, LocalizerUnit; + +//////////////////////////////////////////////////////////////////////////////// +// TContinueForm + +procedure TContinueForm.ContinueButtonClick(Sender: TObject); +begin + Close; +end; + + +procedure TContinueForm.FormShow(Sender: TObject); +var + frmOwner: TForm; +begin + frmOwner := (Owner as TForm); + Left:= frmOwner.Left + (frmOwner.Width - Width) div 2; + Top:= frmOwner.Top + (frmOwner.Height - Height) div 2; +end; + + +constructor TContinueForm.Create(Owner: TForm; h: TContinueHandler = nil); +begin + self.FormStyle := Owner.FormStyle; + inherited Create(Owner); + shuted := FALSE; + ContinueHandler := h; +end; + + +procedure TContinueForm.FormClose(Sender: TObject; + var Action: TCloseAction); +begin + if not shuted then + begin + ModalResult := ContinueButton.ModalResult; + if Assigned(ContinueHandler) then + ContinueHandler; + end + else + ModalResult := mrNone; +end; + + +procedure TContinueForm.Shut; +begin + shuted:= TRUE; + Close; +end; + + +function TContinueForm.GetModalID: TModalFormID; +begin + Result := mfContinue; +end; + + +procedure TContinueForm.FormCreate(Sender: TObject); +begin + Caption := DIALOG_CAPTION; + FLocalize; +end; + + +procedure TContinueForm.FLocalize; +begin + with TLocalizer.Instance do + begin + ContinueLabel.Caption := GetLabel(22); + ContinueButton.Caption := GetLabel(23); + end; +end; + +end. diff --git a/plugins/Chess4Net/DialogUnit.pas b/plugins/Chess4Net/DialogUnit.pas new file mode 100644 index 0000000000..921d630dba --- /dev/null +++ b/plugins/Chess4Net/DialogUnit.pas @@ -0,0 +1,196 @@ +unit DialogUnit; + +interface + +uses + Forms, Dialogs, Controls, Classes, Windows, + ModalForm; + +type + TDialogForm = class(TModalForm) + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure ButtonClick(Sender: TObject); + private + m_ModID: TModalFormID; + msgDlg: TForm; + function GetCaption: TCaption; + procedure SetCaption(capt: TCaption); + protected + function GetHandle: hWnd; override; + function GetEnabled_: boolean; override; + procedure SetEnabled_(flag: boolean); override; + function GetLeft_: integer; override; + procedure SetLeft_(x: integer); override; + function GetTop_: integer; override; + procedure SetTop_(y: integer); override; + function GetModalID: TModalFormID; override; + public + constructor Create(frmOwner: TForm; const wstrMsg: WideString; + DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; modID: TModalFormID = mfNone; + msgDlgHandler: TModalFormHandler = nil; bStayOnTopIfNoOwner: boolean = FALSE); overload; + constructor Create(dlgOwner: TDialogs; const wstrMsg: WideString; + DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; modID: TModalFormID; + msgDlgHandler: TModalFormHandler; bStayOnTopIfNoOwner: boolean = FALSE); overload; + destructor Destroy; override; + + procedure Show; override; + procedure Close; override; + function ShowModal: integer; reintroduce; + procedure SetFocus; override; + + property Caption: TCaption read GetCaption write SetCaption; + end; + +implementation + +uses + StdCtrls, SysUtils, MessageDialogUnit; + +constructor TDialogForm.Create(frmOwner: TForm; const wstrMsg: WideString; + DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; modID: TModalFormID = mfNone; + msgDlgHandler: TModalFormHandler = nil; bStayOnTopIfNoOwner: boolean = FALSE); +var + i: integer; +begin + inherited CreateNew(frmOwner); + + m_ModID := modID; + RHandler := msgDlgHandler; + + msgDlg := MessageDialogUnit.CreateMessageDialog(frmOwner, wstrMsg, DlgType, Buttons, + bStayOnTopIfNoOwner); + // msgDlg.FormStyle := frmOwner.FormStyle; + msgDlg.OnShow := FormShow; + msgDlg.OnClose := FormClose; + + for i := 0 to (msgDlg.ComponentCount - 1) do + begin + if (msgDlg.Components[i] is TButton) then + TButton(msgDlg.Components[i]).OnClick := ButtonClick; + end; +end; + + +constructor TDialogForm.Create(dlgOwner: TDialogs; const wstrMsg: WideString; + DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; modID: TModalFormID; + msgDlgHandler: TModalFormHandler; bStayOnTopIfNoOwner: boolean = FALSE); +begin + self.dlgOwner := dlgOwner; + Create((dlgOwner.Owner as TForm), wstrMsg, DlgType, Buttons, modID, msgDlgHandler, bStayOnTopIfNoOwner); +end; + + +procedure TDialogForm.FormShow(Sender: TObject); +begin + inherited FormShow(msgDlg); +end; + + +procedure TDialogForm.FormClose(Sender: TObject; var Action: TCloseAction); +begin + if Assigned(dlgOwner) then + dlgOwner.UnsetShowing(self); + if (fsModal in msgDlg.FormState) then + exit; + if (Assigned(RHandler)) then + RHandler(TModalForm(msgDlg), GetModalID); +// Action := caFree; + Release; +end; + + +procedure TDialogForm.Show; +begin + msgDlg.Show; +end; + + +procedure TDialogForm.Close; +begin + msgDlg.Close; +end; + + +function TDialogForm.ShowModal: integer; +begin + Result := msgDlg.ShowModal; +end; + +procedure TDialogForm.ButtonClick(Sender: TObject); +begin + if not (fsModal in msgDlg.FormState) then + msgDlg.Close; +end; + +destructor TDialogForm.Destroy; +begin + msgDlg.Release; + inherited; +end; + +function TDialogForm.GetCaption: TCaption; +begin + Result := msgDlg.Caption; +end; + +procedure TDialogForm.SetCaption(capt: TCaption); +begin + msgDlg.Caption := capt; +end; + +function TDialogForm.GetHandle: hWnd; +begin + Result := msgDlg.Handle; +end; + + +function TDialogForm.GetEnabled_: boolean; +begin + Result := msgDlg.Enabled; +end; + + +procedure TDialogForm.SetEnabled_(flag: boolean); +begin + msgDlg.Enabled := flag; +end; + + +procedure TDialogForm.SetFocus; +begin + msgDlg.SetFocus; + msgDlg.Show; +end; + + +function TDialogForm.GetLeft_: integer; +begin + Result := msgDlg.Left; +end; + + +procedure TDialogForm.SetLeft_(x: integer); +begin + msgDlg.Left := x; +end; + + +function TDialogForm.GetTop_: integer; +begin + Result := msgDlg.Top; +end; + + +procedure TDialogForm.SetTop_(y: integer); +begin + msgDlg.Top := y; +end; + + +function TDialogForm.GetModalID: TModalFormID; +begin + Result := m_ModID; +end; + +end. diff --git a/plugins/Chess4Net/DraggedFigureUnit.dfm b/plugins/Chess4Net/DraggedFigureUnit.dfm new file mode 100644 index 0000000000..530e34cf18 --- /dev/null +++ b/plugins/Chess4Net/DraggedFigureUnit.dfm @@ -0,0 +1,59 @@ +object DraggedFigure: TDraggedFigure + Left = 347 + Top = 288 + Cursor = crHandPoint + BorderIcons = [] + BorderStyle = bsNone + ClientHeight = 40 + ClientWidth = 104 + Color = clBlack + Ctl3D = False + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + OldCreateOrder = False + OnCreate = FormCreate + PixelsPerInch = 96 + TextHeight = 13 + object Image1: TImage + Left = 0 + Top = 0 + Width = 40 + Height = 40 + Picture.Data = { + 07544269746D617096030000424D960300000000000076000000280000002800 + 0000280000000100040000000000200300000000000000000000100000000000 + 000000000000000080000080000000808000800000008000800080800000C0C0 + C000808080000000FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFF + FF00666666666666666666666666666666666666666666666666666666666666 + 6666666666666666666666666666666666666666666666666666666666666666 + 6666666660000000000000000000000006666666666666666000000000000000 + 000000000666666666666666600FFFFFFFFFFFFFFFFFFFF00666666666666666 + 6600FFFFFFFFFFFFFFFFFFF006666666666666666600FFFFFFFFFFFFFFFFFFF0 + 066666666666666666600FFFFFFFFFFFFFFFFFF00666666666666666666000FF + FFFFFFFFFFFFFFF006666666666660066666000FFFFFFFFFFFFFFFF006666666 + 6600000066666000FFFFFFFFFFFFFFF00666666660000000066666000FFFFFFF + FFFFFFF006666666000F00F0066666600FFFFFFFFFFFFF006666666600FFFFFF + 0066666000FFFFFFFFFFFF006666666600F00FFFF000666600FFFFFFFFFFFF00 + 6666666600F00FFFFF00006600FFFFFFFFFFFF0066666666600FFFFFFFFF0000 + F00FFFFFFFFFFF0066666666600FFFFFFFFFFF00000FFFFFFFFFF00666666666 + 6600FFFFFFFFFFFF000FFFFFFFFFF006666666666600FFFFFFFFFFFFF00FFFFF + FFFF00066666666666600FFFFFFFFFFFF00FFFFFFFFF00666666666666600FFF + FFFFFFFFFF00FFFFFFF0006666666666666600F0FFFFFFFFFF00FFFFFFF00666 + 66666666666600F00FFFFFFFFFFFFFFFFF00066666666666666600F000FFFFFF + FFFFFFFFFF006666666666666666600F000FFFFFFFFFFFFFF000666666666666 + 6666600FFFFFFFFFFFFFFFFF000666666666666666666600F00FFFFFFFFFFFF0 + 006666666666666666666600000FFFFF00FFF000066666666666666666666660 + 0F000FFF000000066666666666666666666666600FF000FF0000066666666666 + 6666666666666660000000F00666666666666666666666666666666000066000 + 0666666666666666666666666666660006666000666666666666666666666666 + 6666660066666606666666666666666666666666666666666666666666666666 + 6666666666666666666666666666666666666666666666666666666666666666 + 6666666666666666666666666666666666666666666666666666666666666666 + 6666} + Transparent = True + OnMouseDown = Image1MouseDown + end +end diff --git a/plugins/Chess4Net/DraggedFigureUnit.pas b/plugins/Chess4Net/DraggedFigureUnit.pas new file mode 100644 index 0000000000..bbf513ae77 --- /dev/null +++ b/plugins/Chess4Net/DraggedFigureUnit.pas @@ -0,0 +1,42 @@ +unit DraggedFigureUnit; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, + Dialogs, ExtCtrls; + +type + TDraggedFigure = class(TForm) + Image1: TImage; + procedure FormCreate(Sender: TObject); + procedure Image1MouseDown(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); + private + { Private declarations } + public + { Public declarations } + end; + +var + DraggedFigure: TDraggedFigure; + +implementation + +{$R *.dfm} + +procedure TDraggedFigure.FormCreate(Sender: TObject); +begin + ClientWidth:= 40; +end; + + + +procedure TDraggedFigure.Image1MouseDown(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +const SC_DRAGMOVE = $F012; +begin ReleaseCapture; + Perform(WM_SYSCOMMAND, SC_DRAGMOVE, 0 ); +end; + +end. diff --git a/plugins/Chess4Net/Flag.bmp b/plugins/Chess4Net/Flag.bmp new file mode 100644 index 0000000000..52360c210b Binary files /dev/null and b/plugins/Chess4Net/Flag.bmp differ diff --git a/plugins/Chess4Net/GameOptionsUnit.dfm b/plugins/Chess4Net/GameOptionsUnit.dfm new file mode 100644 index 0000000000..d1a5804a6f --- /dev/null +++ b/plugins/Chess4Net/GameOptionsUnit.dfm @@ -0,0 +1,317 @@ +object GameOptionsForm: TGameOptionsForm + Left = 565 + Top = 197 + BorderIcons = [biSystemMenu] + BorderStyle = bsDialog + Caption = 'Game Options' + ClientHeight = 503 + ClientWidth = 387 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Microsoft Sans Serif' + Font.Style = [] + OldCreateOrder = False + OnCreate = FormCreate + OnShow = FormShow + PixelsPerInch = 96 + TextHeight = 13 + object OkButton: TTntButton + Left = 304 + Top = 16 + Width = 75 + Height = 25 + Caption = '&OK' + Default = True + ModalResult = 1 + TabOrder = 3 + end + object CancelButton: TTntButton + Left = 304 + Top = 48 + Width = 75 + Height = 25 + Cancel = True + Caption = '&Cancel' + ModalResult = 2 + TabOrder = 4 + end + object TimeControlGroupBox: TTntGroupBox + Left = 8 + Top = 8 + Width = 281 + Height = 265 + Caption = 'Time Control' + TabOrder = 0 + object EqualTimeCheckBox: TTntCheckBox + Left = 16 + Top = 24 + Width = 233 + Height = 17 + Caption = 'Equal time for both players' + Checked = True + State = cbChecked + TabOrder = 0 + OnClick = EqualTimeCheckBoxClick + end + object YouGroupBox: TTntGroupBox + Left = 32 + Top = 48 + Width = 225 + Height = 97 + Caption = 'Your time' + TabOrder = 1 + DesignSize = ( + 225 + 97) + object YouMinLabel: TTntLabel + Left = 16 + Top = 42 + Width = 129 + Height = 14 + AutoSize = False + Caption = 'Minutes per game:' + end + object YouIncLabel: TTntLabel + Left = 16 + Top = 66 + Width = 129 + Height = 14 + AutoSize = False + Caption = 'Increment in seconds:' + end + object YouMinEdit: TEdit + Left = 168 + Top = 40 + Width = 41 + Height = 21 + BiDiMode = bdLeftToRight + MaxLength = 3 + ParentBiDiMode = False + TabOrder = 1 + Text = '5' + OnChange = YouEditChange + end + object YouIncEdit: TEdit + Left = 168 + Top = 64 + Width = 41 + Height = 21 + TabOrder = 2 + Text = '0' + OnChange = YouEditChange + end + object YouUnlimitedCheckBox: TTntCheckBox + Left = 16 + Top = 16 + Width = 193 + Height = 17 + Anchors = [akLeft, akTop, akRight] + Caption = 'Unlimited' + TabOrder = 0 + OnClick = UnlimitedCheckBoxClick + end + object YouMinUpDown: TUpDown + Left = 209 + Top = 40 + Width = 15 + Height = 21 + Associate = YouMinEdit + Min = 1 + Max = 999 + Position = 5 + TabOrder = 3 + end + object YouIncUpDown: TUpDown + Left = 209 + Top = 64 + Width = 15 + Height = 21 + Associate = YouIncEdit + Max = 999 + TabOrder = 4 + end + end + object OpponentGroupBox: TTntGroupBox + Left = 32 + Top = 152 + Width = 225 + Height = 97 + Caption = 'Opponent'#39's time' + TabOrder = 2 + DesignSize = ( + 225 + 97) + object OpponentMinLabel: TTntLabel + Left = 16 + Top = 42 + Width = 129 + Height = 13 + AutoSize = False + Caption = 'Minutes per game:' + end + object OpponentIncLabel: TTntLabel + Left = 16 + Top = 66 + Width = 129 + Height = 13 + AutoSize = False + Caption = 'Increment in seconds:' + end + object OpponentIncEdit: TEdit + Left = 168 + Top = 64 + Width = 41 + Height = 21 + TabOrder = 2 + Text = '0' + OnChange = OpponentEditChange + end + object OpponentMinEdit: TEdit + Left = 168 + Top = 40 + Width = 41 + Height = 21 + BiDiMode = bdLeftToRight + MaxLength = 3 + ParentBiDiMode = False + TabOrder = 1 + Text = '5' + OnChange = OpponentEditChange + end + object OpponentUnlimitedCheckBox: TTntCheckBox + Left = 16 + Top = 16 + Width = 193 + Height = 17 + Anchors = [akLeft, akTop, akRight] + Caption = 'Unlimited' + TabOrder = 0 + OnClick = UnlimitedCheckBoxClick + end + object OpponentMinUpDown: TUpDown + Left = 209 + Top = 40 + Width = 15 + Height = 21 + Associate = OpponentMinEdit + Min = 1 + Max = 999 + Position = 5 + TabOrder = 3 + end + object OpponentIncUpDown: TUpDown + Left = 209 + Top = 64 + Width = 15 + Height = 21 + Associate = OpponentIncEdit + Max = 999 + TabOrder = 4 + end + end + end + object Panel1: TPanel + Left = 8 + Top = 390 + Width = 281 + Height = 105 + BevelInner = bvRaised + BevelOuter = bvLowered + TabOrder = 2 + DesignSize = ( + 281 + 105) + object AutoFlagCheckBox: TTntCheckBox + Left = 8 + Top = 80 + Width = 265 + Height = 17 + Anchors = [akLeft, akTop, akRight] + Caption = 'Auto Flag' + Checked = True + State = cbChecked + TabOrder = 3 + end + object TakeBackCheckBox: TTntCheckBox + Left = 8 + Top = 56 + Width = 265 + Height = 17 + Anchors = [akLeft, akTop, akRight] + Caption = 'Allow takebacks to your partner' + TabOrder = 2 + end + object GamePauseCheckBox: TTntCheckBox + Left = 8 + Top = 8 + Width = 265 + Height = 17 + Anchors = [akLeft, akTop, akRight] + Caption = 'Game can be paused' + TabOrder = 0 + end + object GameAdjournCheckBox: TTntCheckBox + Left = 8 + Top = 32 + Width = 265 + Height = 17 + Anchors = [akLeft, akTop, akRight] + Caption = 'Game can be adjourned' + TabOrder = 1 + end + end + object TrainingModeGroupBox: TTntGroupBox + Left = 8 + Top = 280 + Width = 281 + Height = 97 + Caption = 'Training Mode' + TabOrder = 1 + DesignSize = ( + 281 + 97) + object ExtBaseLabel: TTntLabel + Left = 16 + Top = 38 + Width = 81 + Height = 13 + AutoSize = False + Caption = 'External base:' + end + object TrainingEnabledCheckBox: TTntCheckBox + Left = 16 + Top = 16 + Width = 257 + Height = 17 + Caption = 'Enabled' + TabOrder = 0 + OnClick = TrainingEnabledCheckBoxClick + end + object ExtBaseComboBox: TTntComboBox + Left = 104 + Top = 36 + Width = 145 + Height = 21 + Enabled = False + ItemHeight = 13 + ItemIndex = 0 + TabOrder = 1 + Text = '' + OnChange = ExtBaseComboBoxChange + Items.Strings = ( + '') + end + object UsrBaseCheckBox: TTntCheckBox + Left = 40 + Top = 64 + Width = 233 + Height = 17 + Anchors = [akLeft, akTop, akRight] + Caption = 'Use user base' + Enabled = False + TabOrder = 2 + end + end +end diff --git a/plugins/Chess4Net/GameOptionsUnit.pas b/plugins/Chess4Net/GameOptionsUnit.pas new file mode 100644 index 0000000000..23f2b5db07 --- /dev/null +++ b/plugins/Chess4Net/GameOptionsUnit.pas @@ -0,0 +1,185 @@ +unit GameOptionsUnit; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, + Dialogs, StdCtrls, TntStdCtrls, ExtCtrls, ComCtrls, + ModalForm; + +type + TGameOptionsForm = class(TModalForm) + OkButton: TTntButton; + CancelButton: TTntButton; + TimeControlGroupBox: TTntGroupBox; + EqualTimeCheckBox: TTntCheckBox; + YouGroupBox: TTntGroupBox; + YouMinLabel: TTntLabel; + YouIncLabel: TTntLabel; + YouMinEdit: TEdit; + YouIncEdit: TEdit; + YouUnlimitedCheckBox: TTntCheckBox; + OpponentGroupBox: TTntGroupBox; + OpponentMinLabel: TTntLabel; + OpponentIncLabel: TTntLabel; + OpponentIncEdit: TEdit; + OpponentMinEdit: TEdit; + OpponentUnlimitedCheckBox: TTntCheckBox; + Panel1: TPanel; + AutoFlagCheckBox: TTntCheckBox; + TakeBackCheckBox: TTntCheckBox; + TrainingModeGroupBox: TTntGroupBox; + TrainingEnabledCheckBox: TTntCheckBox; + ExtBaseComboBox: TTntComboBox; + UsrBaseCheckBox: TTntCheckBox; + ExtBaseLabel: TTntLabel; + GamePauseCheckBox: TTntCheckBox; + YouMinUpDown: TUpDown; + YouIncUpDown: TUpDown; + OpponentMinUpDown: TUpDown; + OpponentIncUpDown: TUpDown; + GameAdjournCheckBox: TTntCheckBox; + procedure YouEditChange(Sender: TObject); + procedure OpponentEditChange(Sender: TObject); + procedure EqualTimeCheckBoxClick(Sender: TObject); + procedure UnlimitedCheckBoxClick(Sender: TObject); + procedure TrainingEnabledCheckBoxClick(Sender: TObject); + procedure ExtBaseComboBoxChange(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure FormCreate(Sender: TObject); + private + procedure FLocalize; + protected + function GetModalID: TModalFormID; override; + end; + +implementation + +{$R *.dfm} + +uses + LocalizerUnit; + +procedure TGameOptionsForm.YouEditChange(Sender: TObject); +begin + YouMinEdit.Text := IntToStr(YouMinUpDown.Position); + YouIncEdit.Text := IntToStr(YouIncUpDown.Position); + if EqualTimeCheckBox.Checked then + begin + OpponentMinEdit.Text := YouMinEdit.Text; + OpponentIncEdit.Text := YouIncEdit.Text; + end; +end; + + +procedure TGameOptionsForm.OpponentEditChange(Sender: TObject); +begin + OpponentMinEdit.Text := IntToStr(OpponentMinUpDown.Position); + OpponentIncEdit.Text := IntToStr(OpponentIncUpDown.Position); + if EqualTimeCheckBox.Checked then + begin + YouMinEdit.Text := OpponentMinEdit.Text; + YouIncEdit.Text := OpponentIncEdit.Text; + end; +end; + + +procedure TGameOptionsForm.EqualTimeCheckBoxClick(Sender: TObject); +begin + if EqualTimeCheckBox.Checked then + begin + OpponentMinEdit.Text := YouMinEdit.Text; + OpponentIncEdit.Text := YouIncEdit.Text; + OpponentUnlimitedCheckBox.Checked := YouUnlimitedCheckBox.Checked; + end; +end; + + +procedure TGameOptionsForm.UnlimitedCheckBoxClick(Sender: TObject); +begin + if EqualTimeCheckBox.Checked then + begin + YouUnlimitedCheckBox.Checked := TCheckBox(Sender).Checked; + OpponentUnlimitedCheckBox.Checked := TCheckBox(Sender).Checked; + end; + + YouMinEdit.Enabled := (not YouUnlimitedCheckBox.Checked); + YouMinUpDown.Enabled := (not YouUnlimitedCheckBox.Checked); + YouIncEdit.Enabled := (not YouUnlimitedCheckBox.Checked); + YouIncUpDown.Enabled := (not YouUnlimitedCheckBox.Checked); + + OpponentMinEdit.Enabled := (not OpponentUnlimitedCheckBox.Checked); + OpponentMinUpDown.Enabled := (not OpponentUnlimitedCheckBox.Checked); + OpponentIncEdit.Enabled := (not OpponentUnlimitedCheckBox.Checked); + OpponentIncUpDown.Enabled := (not OpponentUnlimitedCheckBox.Checked); +end; + + +procedure TGameOptionsForm.TrainingEnabledCheckBoxClick(Sender: TObject); +begin + ExtBaseComboBox.Enabled := TrainingEnabledCheckBox.Checked; + UsrBaseCheckBox.Enabled := TrainingEnabledCheckBox.Checked and (ExtBaseComboBox.ItemIndex <> 0); + TakeBackCheckBox.Enabled := not TrainingEnabledCheckBox.Checked; +end; + + +procedure TGameOptionsForm.ExtBaseComboBoxChange(Sender: TObject); +begin + UsrBaseCheckBox.Enabled := (ExtBaseComboBox.ItemIndex <> 0); + if ExtBaseComboBox.ItemIndex = 0 then + UsrBaseCheckBox.Checked := TRUE; +end; + + +procedure TGameOptionsForm.FormShow(Sender: TObject); +begin + ExtBaseComboBoxChange(Sender); +end; + + +function TGameOptionsForm.GetModalID: TModalFormID; +begin + Result := mfGameOptions; +end; + + +procedure TGameOptionsForm.FormCreate(Sender: TObject); +begin + FLocalize; +end; + + +procedure TGameOptionsForm.FLocalize; +begin + with TLocalizer.Instance do + begin + Caption := GetLabel(24); + + TimeControlGroupBox.Caption := GetLabel(25); + EqualTimeCheckBox.Caption := GetLabel(26); + YouGroupBox.Caption := GetLabel(27); + OpponentGroupBox.Caption := GetLabel(28); + YouUnlimitedCheckBox.Caption := GetLabel(29); + OpponentUnlimitedCheckBox.Caption := GetLabel(29); + YouMinLabel.Caption := GetLabel(30); + OpponentMinLabel.Caption := GetLabel(30); + YouIncLabel.Caption := GetLabel(31); + OpponentIncLabel.Caption := GetLabel(31); + + TrainingModeGroupBox.Caption := GetLabel(32); + TrainingEnabledCheckBox.Caption := GetLabel(33); + ExtBaseLabel.Caption := GetLabel(34); + UsrBaseCheckBox.Caption := GetLabel(35); + + GamePauseCheckBox.Caption := GetLabel(36); + GameAdjournCheckBox.Caption := GetLabel(37); + TakeBackCheckBox.Caption := GetLabel(38); + AutoFlagCheckBox.Caption := GetLabel(39); + + OkButton.Caption := GetLabel(11); + CancelButton.Caption := GetLabel(12); + end; +end; + + +end. diff --git a/plugins/Chess4Net/GlobalsUnit.pas b/plugins/Chess4Net/GlobalsUnit.pas new file mode 100644 index 0000000000..435cde0831 --- /dev/null +++ b/plugins/Chess4Net/GlobalsUnit.pas @@ -0,0 +1,10 @@ +unit GlobalsUnit; + +interface + +const + DIALOG_CAPTION = 'Chess4Net'; + +implementation + +end. diff --git a/plugins/Chess4Net/InfoUnit.dfm b/plugins/Chess4Net/InfoUnit.dfm new file mode 100644 index 0000000000..c3e62247cc --- /dev/null +++ b/plugins/Chess4Net/InfoUnit.dfm @@ -0,0 +1,114 @@ +object InfoForm: TInfoForm + Left = 489 + Top = 506 + BorderStyle = bsDialog + ClientHeight = 166 + ClientWidth = 233 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Microsoft Sans Serif' + Font.Style = [] + OldCreateOrder = False + Position = poScreenCenter + OnClose = FormClose + OnCreate = FormCreate + PixelsPerInch = 96 + TextHeight = 13 + object PluginNameLabel: TLabel + Left = 0 + Top = 8 + Width = 233 + Height = 17 + Alignment = taCenter + AutoSize = False + Caption = 'Chess4Net ' + WordWrap = True + end + object PlayingViaLabel: TLabel + Left = 0 + Top = 27 + Width = 233 + Height = 13 + Alignment = taCenter + AutoSize = False + Caption = 'Plugin for playing chess via ' + end + object Label2: TLabel + Left = 0 + Top = 46 + Width = 233 + Height = 13 + Alignment = taCenter + AutoSize = False + Caption = 'Written by Pavel Perminov' + end + object Label3: TLabel + Left = 0 + Top = 65 + Width = 233 + Height = 13 + Alignment = taCenter + AutoSize = False + Caption = #169' 2007-2010 no rights reserved' + end + object Label4: TLabel + Left = 38 + Top = 84 + Width = 25 + Height = 13 + AutoSize = False + Caption = 'URL:' + end + object Label5: TLabel + Left = 38 + Top = 104 + Width = 32 + Height = 13 + AutoSize = False + Caption = 'E-Mail:' + end + object URLLabel: TLabel + Left = 73 + Top = 84 + Width = 65 + Height = 13 + Cursor = crHandPoint + Caption = 'http://' + Font.Charset = DEFAULT_CHARSET + Font.Color = clBlue + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [fsUnderline] + ParentFont = False + OnClick = URLLabelClick + end + object EMailLabel: TLabel + Left = 73 + Top = 104 + Width = 41 + Height = 13 + Cursor = crHandPoint + Caption = '' + Font.Charset = DEFAULT_CHARSET + Font.Color = clBlue + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [fsUnderline] + ParentFont = False + OnClick = EMailLabelClick + end + object OkButton: TButton + Left = 80 + Top = 128 + Width = 75 + Height = 25 + Cancel = True + Caption = '&OK' + Default = True + ModalResult = 1 + TabOrder = 0 + OnClick = OkButtonClick + end +end diff --git a/plugins/Chess4Net/InfoUnit.pas b/plugins/Chess4Net/InfoUnit.pas new file mode 100644 index 0000000000..66dfdc222d --- /dev/null +++ b/plugins/Chess4Net/InfoUnit.pas @@ -0,0 +1,92 @@ +unit InfoUnit; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, ShellAPI; + +type + TInfoForm = class(TForm) + OkButton: TButton; + PluginNameLabel: TLabel; + PlayingViaLabel: TLabel; + Label2: TLabel; + Label3: TLabel; + Label4: TLabel; + Label5: TLabel; + URLLabel: TLabel; + EMailLabel: TLabel; + procedure OkButtonClick(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure EMailLabelClick(Sender: TObject); + procedure URLLabelClick(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + end; + +procedure ShowInfo; + +implementation + +{$R *.dfm} + +uses + GlobalsLocalUnit, ModalForm; + +var + infoForm: TInfoForm = nil; + +procedure ShowInfo; +begin + if (not Assigned(infoForm)) then + begin + infoForm := TInfoForm.Create(nil); + if (TDialogs.HasStayOnTopOwners) then + infoForm.FormStyle := fsStayOnTop; +{$IFDEF SKYPE} + infoForm.Icon := Chess4NetIcon; + infoForm.Caption := DIALOG_CAPTION; +{$ELSE} // MI, TRILLIAN, AND_RQ, QIP + infoForm.Icon := pluginIcon; + infoForm.Caption := PLUGIN_NAME; +{$ENDIF} + end; + if not infoForm.Showing then + infoForm.Show + else + infoForm.SetFocus; +end; + +procedure TInfoForm.OkButtonClick(Sender: TObject); +begin + Close; +end; + +procedure TInfoForm.FormCreate(Sender: TObject); +begin + PlayingViaLabel.Caption := PLUGIN_PLAYING_VIA; + PluginNameLabel.Caption := PLUGIN_INFO_NAME; + URLLabel.Caption := PLUGIN_URL; + EMailLabel.Caption := PLUGIN_EMAIL; +end; + +procedure TInfoForm.URLLabelClick(Sender: TObject); +begin + ShellExecute(Handle, nil, PChar(URLLabel.Caption), nil, nil, SW_SHOWNORMAL); +end; + +procedure TInfoForm.EMailLabelClick(Sender: TObject); +var + shellStr: string; +begin + shellStr := 'mailto:' + EMailLabel.Caption; + ShellExecute(Handle, nil, PChar(shellStr), nil, nil, SW_SHOWNORMAL); +end; + +procedure TInfoForm.FormClose(Sender: TObject; var Action: TCloseAction); +begin + infoForm := nil; + Action := caFree; +end; + +end. diff --git a/plugins/Chess4Net/Lang.ini b/plugins/Chess4Net/Lang.ini new file mode 100644 index 0000000000..8131f9dea4 Binary files /dev/null and b/plugins/Chess4Net/Lang.ini differ diff --git a/plugins/Chess4Net/LocalizerUnit.pas b/plugins/Chess4Net/LocalizerUnit.pas new file mode 100644 index 0000000000..71f63367a7 --- /dev/null +++ b/plugins/Chess4Net/LocalizerUnit.pas @@ -0,0 +1,404 @@ +unit LocalizerUnit; + +interface + +uses + SysUtils, TntSysUtils, Classes, TntClasses; + +type + // A singletone that is used to localize interface + ILocalizable = interface + procedure Localize; + end; + + ELocalizer = class(Exception); + TLocalizer = class + private + m_IniFileName: TFileName; + m_iLangugesCount: integer; + m_wstrarLanguageNames: array of WideString; + m_wstrlLabels, m_wstrlMessages: TTntStringList; + m_iActiveLanguage: integer; + m_Subscribers: TList; + + constructor Create; + procedure FReadLanguages; + function FGetLangaugeName(iIndex: integer): WideString; + procedure FSetActiveLanguage(iIndex: integer); + function FReadLanguageData(iIndex: integer): boolean; + procedure FNotifySubscribers; + + public + destructor Destroy; override; + class function Instance: TLocalizer; + class procedure FreeInstance; reintroduce; + property LanguagesCount: integer read m_iLangugesCount; + // Returns a language name depending on its index + function GetLabel(iIndex: integer): WideString; + function GetMessage(iIndex: integer): WideString; overload; + function GetMessage(iIndex: integer; wstrarParams: array of const): WideString; overload; + procedure AddSubscriber(const Subscriber: ILocalizable); + procedure DeleteSubscriber(const Subscriber: ILocalizable); + property LanguageName[iIndex: integer]: WideString read FGetLangaugeName; + property ActiveLanguage: integer read m_iActiveLanguage write FSetActiveLanguage; + end; + +implementation + +uses + StrUtils, Forms, TntIniFiles, + GlobalsLocalUnit; + +const + LOCALIZER_INI_FILE = 'Lang.ini'; + + // Labels are used to name interface controls s.a. TLabel and the like + DEFAULT_LABELS: array[0..67] of WideString = + ('Look & Feel Options', {0} + 'Animate Move:', + 'No', + 'Slowly', + 'Quickly', + 'Highlight Last Move', + 'Flash on incoming move', + 'Show Coordinates', + 'Stay Always on Top', + 'Extra Exit on ESC', + 'GUI Language:', {10} + '&OK', + '&Cancel', + 'White ', + 'White ', + 'W ', + 'Black ', + 'Black ', + 'B ', + 'Connecting...', + 'Wait until the connection is completed.', {20} + '&Abort', + 'Press button to continue the game.', + '&Continue', + 'Game Options', + 'Time Control', + 'Equal time for both players', + 'Your time', + 'Opponent''s time', + 'Unlimited', + 'Minutes per game:', {30} + 'Increment in seconds:', + 'Training Mode', + 'Enabled', + 'External base:', + 'Use user base', + 'Game can be paused', + 'Game can be adjourned', + 'Allow takebacks to your partner', + 'Auto Flag', + 'Yes', {40} + 'No', + 'OK', + 'Cancel', + 'Abort', + 'Retry', + 'Ignore', + 'All', + 'NoToAll', + 'YesToAll', + 'Help', {50} + 'Start Adjourned Game', + 'Start Standart Game', + 'Start PP Random Game', + 'Change Color', + 'Game Options...', + 'Look && Feel Options...', + 'About...', + 'Abort', + 'Draw', + 'Resign', {60} + 'Adjourn', + 'Pause', + 'Takeback', + 'If you liked plying Chess4Net give your credits at', + '&Close', + 'Don''t show again', + 'Transmit Game' + ); + + // Messages are used in message boxes + DEFAULT_MESSAGES: array[0..37] of WideString = + ('White is checkmated. You win.', {0} + 'White is checkmated. You loose.', + 'Black is checkmated. You win.', + 'Black is checkmated. You loose.', + 'It''s stalemate. No one wins.', + 'Your opponent leaves.', + 'Your opponent leaves. The game is aborted.', + 'An error during connection occured.', + 'Your opponent is using an older version of Chess4Net.' + sLineBreak + + 'Most of functionality will be not available.' + sLineBreak + + 'Please, ask him/her to update the client.', + 'The current version of Chess4Net is incompatible with the one of your partner.' + sLineBreak + + 'Please check the versions.', + 'Draw?', {10} + 'Can we abort the game?', + 'I resign. You win this game. Congratulations!', + 'The game is aborted.', + 'Sorry, but we have to finish this game.', + 'The game is drawn.', + 'No draw, sorry.', + 'You forfeited on time.', + 'Your opponent forfeited on time.', + 'Can we pause the game?', + 'No pause, sorry.', {20} + 'May I take back last move?', + 'Can we adjourn this game?', + 'No adjourns, sorry.', + 'Sorry, no takebacks!', + 'Do you really want to resign?', + 'Do you want to exit?', + 'The game is adjourned.', + 'You are currently playing some games. Do you want to start broadcasting?', + 'Black forfeits on time.', + 'White forfeits on time.', {30} + 'White resigns.', + 'Black resigns.', + 'Game transmition is not supported by this client!', + 'Broadcaster leaves. Transmition will be closed.', + 'Stalemate.', + 'White is checkmated.', + 'Black is checkmated.' + ); + +var + LocalizerInstance: TLocalizer = nil; + +//////////////////////////////////////////////////////////////////////////////// +// TLocalizer + +constructor TLocalizer.Create; +begin + m_IniFileName := Chess4NetPath + LOCALIZER_INI_FILE; + + m_wstrlLabels := TTntStringList.Create; + m_wstrlMessages := TTntStringList.Create; + + m_Subscribers := TList.Create; + + m_iActiveLanguage := -1; + FReadLanguages; + FReadLanguageData(-1); +end; + + +destructor TLocalizer.Destroy; +begin + Finalize(m_wstrarLanguageNames); + + m_Subscribers.Free; + + m_wstrlMessages.Free; + m_wstrlLabels.Free; + + inherited; +end; + + +class function TLocalizer.Instance: TLocalizer; +begin + if (not Assigned(LocalizerInstance)) then + LocalizerInstance := TLocalizer.Create; + Result := LocalizerInstance; +end; + + +class procedure TLocalizer.FreeInstance; +begin + FreeAndNil(LocalizerInstance); +end; + + +procedure TLocalizer.FReadLanguages; +var + IniFile: TTntIniFile; + i: integer; + wstrSection: WideString; +begin + if (not FileExists(m_IniFileName)) then + exit; + + IniFile := TTntIniFile.Create(m_IniFileName); + try + // Count available languages + Finalize(m_wstrarLanguageNames); + i := 0; + repeat + wstrSection := 'Language' + IntToStr(i + 1); + if (not IniFile.SectionExists(wstrSection)) then + break; + SetLength(m_wstrarLanguageNames, length(m_wstrarLanguageNames) + 1); + m_wstrarLanguageNames[i] := IniFile.ReadString(wstrSection, 'Name', ''); + inc(i); + until FALSE; + m_iLangugesCount := i; + + finally + IniFile.Free; + end; +end; + + +function TLocalizer.FGetLangaugeName(iIndex: integer): WideString; +begin + Result := m_wstrarLanguageNames[iIndex]; +end; + + +procedure TLocalizer.FSetActiveLanguage(iIndex: integer); +begin + if (iIndex <> m_iActiveLanguage) then + begin + if (FReadLanguageData(iIndex)) then + begin + m_iActiveLanguage := iIndex; + FNotifySubscribers; + end + else + m_iActiveLanguage := -1; + end; +end; + + +function TLocalizer.FReadLanguageData(iIndex: integer): boolean; + + function NInsertLineFeeds(const wstrSource: WideString): WideString; + var + iPos, iOffset: integer; + begin + Result := ''; + iOffset := 1; + repeat + iPos := PosEx('/n', wstrSource, iOffset); + if (iPos = 0) then + break; + if ((iPos = 1) or (wstrSource[iPos - 1] <> '/')) then + Result := Result + Copy(wstrSource, iOffset, iPos - iOffset) + sLineBreak + else + Result := Result + Copy(wstrSource, iOffset, iPos - iOffset) + 'n'; // '//n' -> '/n' + iOffset := iPos + 2; + until FALSE; + + Result := Result + Copy(wstrSource, iOffset, MaxInt); + end; + +var + IniFile: TTntIniFile; + i: integer; + wstrSection: WideString; + wstrlValues: TTntStringList; + wstrValue: WideString; +begin + Result := FALSE; + + // Copy default values + m_wstrlLabels.Clear; + for i := Low(DEFAULT_LABELS) to High(DEFAULT_LABELS) do + m_wstrlLabels.Add(DEFAULT_LABELS[i]); + + m_wstrlMessages.Clear; + for i := Low(DEFAULT_MESSAGES) to High(DEFAULT_MESSAGES) do + m_wstrlMessages.Add(DEFAULT_MESSAGES[i]); + + if (not FileExists(m_IniFileName)) then + exit; + + wstrlValues := nil; + IniFile := TTntIniFile.Create(m_IniFileName); + try + wstrSection := 'Language' + IntToStr(iIndex + 1); + if (not IniFile.SectionExists(wstrSection)) then + exit; + + wstrlValues := TTntStringList.Create; + IniFile.ReadSectionValues(wstrSection, wstrlValues); + + for i := 0 to m_wstrlLabels.Count - 1 do + begin + wstrValue := wstrlValues.Values['Label' + IntToStr(i)]; + if (wstrValue <> '') then + begin + if (wstrValue[length(wstrValue)] = '|') then // labels with a width + wstrValue := Copy(wstrValue, 1, length(wstrValue) - 1); + m_wstrlLabels[i] := wstrValue; + end; + end; + for i := 0 to m_wstrlMessages.Count - 1 do + begin + wstrValue := wstrlValues.Values['Msg' + IntToStr(i)]; + if (wstrValue <> '') then + m_wstrlMessages[i] := NInsertLineFeeds(wstrValue); + end; + + finally + wstrlValues.Free; + IniFile.Free; + end; + + Result := TRUE; +end; + + +function TLocalizer.GetLabel(iIndex: integer): WideString; +begin + if (iIndex in [0..m_wstrlLabels.Count - 1]) then + Result := m_wstrlLabels[iIndex] + else + ELocalizer.Create('Wrong label index!'); +end; + + +function TLocalizer.GetMessage(iIndex: integer): WideString; +begin + if (iIndex in [0..m_wstrlMessages.Count - 1]) then + Result := m_wstrlMessages[iIndex] + else + ELocalizer.Create('Wrong message index!'); +end; + + +function TLocalizer.GetMessage(iIndex: integer; wstrarParams: array of const): WideString; +begin + Result := WideFormat(GetMessage(iIndex), wstrarParams) +end; + + +procedure TLocalizer.AddSubscriber(const Subscriber: ILocalizable); +begin + if (m_Subscribers.IndexOf(Pointer(Subscriber)) < 0) then + m_Subscribers.Add(Pointer(Subscriber)); +end; + + +procedure TLocalizer.DeleteSubscriber(const Subscriber: ILocalizable); +var + iIndex: integer; +begin + iIndex := m_Subscribers.IndexOf(Pointer(Subscriber)); + if (iIndex >= 0) then + m_Subscribers.Delete(iIndex); +end; + + +procedure TLocalizer.FNotifySubscribers; +var + i: integer; +begin + for i := 0 to m_Subscribers.Count - 1 do + ILocalizable(m_Subscribers[i]).Localize; +end; + +initialization + +finalization + TLocalizer.FreeInstance; + +end. diff --git a/plugins/Chess4Net/LookFeelOptionsUnit.dfm b/plugins/Chess4Net/LookFeelOptionsUnit.dfm new file mode 100644 index 0000000000..c3fda14bce --- /dev/null +++ b/plugins/Chess4Net/LookFeelOptionsUnit.dfm @@ -0,0 +1,142 @@ +object LookFeelOptionsForm: TLookFeelOptionsForm + Left = 702 + Top = 299 + BorderIcons = [biSystemMenu] + BorderStyle = bsDialog + Caption = 'Look & Feel Options' + ClientHeight = 217 + ClientWidth = 321 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Microsoft Sans Serif' + Font.Style = [] + OldCreateOrder = False + OnCreate = FormCreate + OnDestroy = FormDestroy + PixelsPerInch = 96 + TextHeight = 13 + object AnimateLabel: TTntLabel + Left = 8 + Top = 11 + Width = 89 + Height = 13 + AutoSize = False + Caption = 'Animate Move:' + end + object GUILangLabel: TTntLabel + Left = 8 + Top = 187 + Width = 97 + Height = 13 + AutoSize = False + Caption = 'GUI Language:' + end + object OkButton: TTntButton + Left = 240 + Top = 8 + Width = 75 + Height = 25 + Caption = '&OK' + Default = True + ModalResult = 1 + TabOrder = 2 + end + object CancelButton: TTntButton + Left = 240 + Top = 40 + Width = 75 + Height = 25 + Cancel = True + Caption = '&Cancel' + ModalResult = 2 + TabOrder = 3 + end + object AnimationComboBox: TTntComboBox + Left = 104 + Top = 8 + Width = 81 + Height = 21 + Style = csDropDownList + ItemHeight = 13 + ItemIndex = 0 + TabOrder = 0 + Text = 'No' + Items.Strings = ( + 'No' + 'Slowly' + 'Quickly') + end + object BoxPanel: TPanel + Left = 8 + Top = 40 + Width = 217 + Height = 129 + BevelInner = bvRaised + BevelOuter = bvLowered + TabOrder = 1 + DesignSize = ( + 217 + 129) + object HilightLastMoveBox: TTntCheckBox + Left = 8 + Top = 8 + Width = 201 + Height = 17 + Anchors = [akLeft, akTop, akRight] + Caption = 'Highlight Last Move' + TabOrder = 0 + end + object CoordinatesBox: TTntCheckBox + Left = 8 + Top = 56 + Width = 201 + Height = 17 + Anchors = [akLeft, akTop, akRight] + Caption = 'Show Coordinates' + TabOrder = 1 + end + object StayOnTopBox: TTntCheckBox + Left = 8 + Top = 80 + Width = 201 + Height = 17 + Anchors = [akLeft, akTop, akRight] + Caption = 'Stay Always on Top' + TabOrder = 2 + end + object ExtraExitBox: TTntCheckBox + Left = 8 + Top = 104 + Width = 201 + Height = 17 + Anchors = [akLeft, akTop, akRight] + Caption = 'Extra Exit on ESC' + TabOrder = 3 + end + object FlashIncomingMoveBox: TTntCheckBox + Left = 8 + Top = 32 + Width = 201 + Height = 17 + Anchors = [akLeft, akTop, akRight] + Caption = 'Flash on incoming move' + TabOrder = 4 + end + end + object GUILangComboBox: TTntComboBox + Left = 120 + Top = 184 + Width = 129 + Height = 21 + Style = csDropDownList + ItemHeight = 13 + ItemIndex = 0 + TabOrder = 4 + Text = 'English' + OnChange = GUILangComboBoxChange + Items.Strings = ( + 'English') + end +end diff --git a/plugins/Chess4Net/LookFeelOptionsUnit.pas b/plugins/Chess4Net/LookFeelOptionsUnit.pas new file mode 100644 index 0000000000..138ab498ae --- /dev/null +++ b/plugins/Chess4Net/LookFeelOptionsUnit.pas @@ -0,0 +1,108 @@ +unit LookFeelOptionsUnit; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, ExtCtrls, + ModalForm, TntStdCtrls, + // Chess4Net units + LocalizerUnit; + +type + TLookFeelOptionsForm = class(TModalForm, ILocalizable) + OkButton: TTntButton; + CancelButton: TTntButton; + AnimationComboBox: TTntComboBox; + AnimateLabel: TTntLabel; + BoxPanel: TPanel; + HilightLastMoveBox: TTntCheckBox; + FlashIncomingMoveBox: TTntCheckBox; + CoordinatesBox: TTntCheckBox; + StayOnTopBox: TTntCheckBox; + ExtraExitBox: TTntCheckBox; + GUILangLabel: TTntLabel; + GUILangComboBox: TTntComboBox; + procedure FormCreate(Sender: TObject); + procedure GUILangComboBoxChange(Sender: TObject); + procedure FormDestroy(Sender: TObject); + private + procedure ILocalizable.Localize = FLocalize; + procedure FLocalize; + protected + function GetModalID: TModalFormID; override; + end; + +implementation + +{$R *.dfm} + +function TLookFeelOptionsForm. GetModalID: TModalFormID; +begin + Result := mfLookFeel; +end; + + +procedure TLookFeelOptionsForm.FormCreate(Sender: TObject); +var + i: integer; +begin +{$IFDEF SKYPE} + StayOnTopBox.Enabled := FALSE; // TODO: this was done to prevent non-modal dialogs be overlapped by ChessForm. Resolve later +{$ENDIF} + + // Fill GUI Languages combo box + GUILangComboBox.Clear; + with TLocalizer.Instance do + begin + for i := 0 to LanguagesCount - 1 do + GUILangComboBox.Items.Add(LanguageName[i]); + GUILangComboBox.ItemIndex := ActiveLanguage; + end; + + TLocalizer.Instance.AddSubscriber(self); + FLocalize; +end; + + +procedure TLookFeelOptionsForm.FLocalize; +var + iSavedAnimation: integer; +begin + with TLocalizer.Instance do + begin + Caption := GetLabel(0); + AnimateLabel.Caption := GetLabel(1); + with AnimationComboBox do + begin + iSavedAnimation := ItemIndex; + Items[0] := GetLabel(2); + Items[1] := GetLabel(3); + Items[2] := GetLabel(4); + ItemIndex := iSavedAnimation; + end; + HilightLastMoveBox.Caption := GetLabel(5); + FlashIncomingMoveBox.Caption := GetLabel(6); + CoordinatesBox.Caption := GetLabel(7); + StayOnTopBox.Caption := GetLabel(8); + ExtraExitBox.Caption := GetLabel(9); + GUILangLabel.Caption := GetLabel(10); + + OkButton.Caption := GetLabel(11); + CancelButton.Caption := GetLabel(12); + end; +end; + + +procedure TLookFeelOptionsForm.GUILangComboBoxChange(Sender: TObject); +begin + TLocalizer.Instance.ActiveLanguage := GUILangComboBox.ItemIndex; +end; + + +procedure TLookFeelOptionsForm.FormDestroy(Sender: TObject); +begin + TLocalizer.Instance.DeleteSubscriber(self); +end; + +end. diff --git a/plugins/Chess4Net/MI/Chess4Net_MI.cfg b/plugins/Chess4Net/MI/Chess4Net_MI.cfg new file mode 100644 index 0000000000..6d8fdcc3db --- /dev/null +++ b/plugins/Chess4Net/MI/Chess4Net_MI.cfg @@ -0,0 +1,45 @@ +-$A8 +-$B- +-$C- +-$D- +-$E- +-$F- +-$G+ +-$H+ +-$I- +-$J+ +-$K- +-$L- +-$M- +-$N+ +-$O+ +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$Y- +-$Z1 +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$00400000 +-E"..\bin" +-N".\dcu" +-LE"c:\program files\borland\delphi7\Projects\Bpl" +-LN"c:\program files\borland\delphi7\Projects\Bpl" +-U".\MirandaINC;..\res\Delphi;..\lib\FastMM4;..\lib\PNGImage;..\lib\XIE;..\lib\TntUnicodeControls\Source" +-O".\MirandaINC;..\res\Delphi;..\lib\FastMM4;..\lib\PNGImage;..\lib\XIE;..\lib\TntUnicodeControls\Source" +-I".\MirandaINC;..\res\Delphi;..\lib\FastMM4;..\lib\PNGImage;..\lib\XIE;..\lib\TntUnicodeControls\Source" +-R".\MirandaINC;..\res\Delphi;..\lib\FastMM4;..\lib\PNGImage;..\lib\XIE;..\lib\TntUnicodeControls\Source" +-DMIRANDA;xFASTMM4;xDEBUG_LOG +-w-UNSAFE_TYPE +-w-UNSAFE_CODE +-w-UNSAFE_CAST diff --git a/plugins/Chess4Net/MI/Chess4Net_MI.cfg.bak b/plugins/Chess4Net/MI/Chess4Net_MI.cfg.bak new file mode 100644 index 0000000000..c2321660ff --- /dev/null +++ b/plugins/Chess4Net/MI/Chess4Net_MI.cfg.bak @@ -0,0 +1,47 @@ +-$A8 +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I- +-$J+ +-$K- +-$L+ +-$M- +-$N+ +-$O- +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$YD +-$Z1 +-cg +-vn +-vr +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$00400000 +-E"..\..\Testing\IMEServices\IMEClient2\Plugins" +-N".\dcu" +-LE"c:\program files\borland\delphi7\Projects\Bpl" +-LN"c:\program files\borland\delphi7\Projects\Bpl" +-U"c:\program files\borland\delphi7\Lib\Debug;.\MirandaINC;..\lib\FastMM4;..\lib\PNGImage;..\lib\TntUnicodeControls\Source" +-O"c:\program files\borland\delphi7\Lib\Debug;.\MirandaINC;..\lib\FastMM4;..\lib\PNGImage;..\lib\TntUnicodeControls\Source" +-I"c:\program files\borland\delphi7\Lib\Debug;.\MirandaINC;..\lib\FastMM4;..\lib\PNGImage;..\lib\TntUnicodeControls\Source" +-R"c:\program files\borland\delphi7\Lib\Debug;.\MirandaINC;..\lib\FastMM4;..\lib\PNGImage;..\lib\TntUnicodeControls\Source" +-DMIRANDA;xFASTMM4;xDEBUG_LOG +-w-UNSAFE_TYPE +-w-UNSAFE_CODE +-w-UNSAFE_CAST diff --git a/plugins/Chess4Net/MI/Chess4Net_MI.dof b/plugins/Chess4Net/MI/Chess4Net_MI.dof new file mode 100644 index 0000000000..b7ba2c3184 --- /dev/null +++ b/plugins/Chess4Net/MI/Chess4Net_MI.dof @@ -0,0 +1,172 @@ +[FileVersion] +Version=7.0 +[Compiler] +A=8 +B=0 +C=0 +D=0 +E=0 +F=0 +G=1 +H=1 +I=0 +J=1 +K=0 +L=0 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=0 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +NamespacePrefix= +SymbolDeprecated=1 +SymbolLibrary=1 +SymbolPlatform=1 +UnitLibrary=1 +UnitPlatform=1 +UnitDeprecated=1 +HResultCompat=1 +HidingMember=1 +HiddenVirtual=1 +Garbage=1 +BoundsError=1 +ZeroNilCompat=1 +StringConstTruncated=1 +ForLoopVarVarPar=1 +TypedConstVarPar=1 +AsgToTypedConst=1 +CaseLabelRange=1 +ForVariable=1 +ConstructingAbstract=1 +ComparisonFalse=1 +ComparisonTrue=1 +ComparingSignedUnsigned=1 +CombiningSignedUnsigned=1 +UnsupportedConstruct=1 +FileOpen=1 +FileOpenUnitSrc=1 +BadGlobalSymbol=1 +DuplicateConstructorDestructor=1 +InvalidDirective=1 +PackageNoLink=1 +PackageThreadVar=1 +ImplicitImport=1 +HPPEMITIgnored=1 +NoRetVal=1 +UseBeforeDef=1 +ForLoopVarUndef=1 +UnitNameMismatch=1 +NoCFGFileFound=1 +MessageDirective=1 +ImplicitVariants=1 +UnicodeToLocale=1 +LocaleToUnicode=1 +ImagebaseMultiple=1 +SuspiciousTypecast=1 +PrivatePropAccessor=1 +UnsafeType=0 +UnsafeCode=0 +UnsafeCast=0 +[Linker] +MapFile=0 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=4194304 +ExeDescription= +[Directories] +OutputDir=..\bin +UnitOutputDir=.\dcu +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath=.\MirandaINC;..\lib\FastMM4;..\lib\PNGImage;..\lib\TntUnicodeControls\Source +Packages=vcl;rtl;dbrtl;vcldb;vclx;bdertl;delphiclxide;proide;delphivclide;direct;vclie;stride;VclSmp;vclactnband +Conditionals=MIRANDA;xFASTMM4;xDEBUG_LOG +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication=C:\Documents and Settings\Pavel\Мои документы\Programming\Chess4Net\Testing\Client1\TestingHost.exe +Launcher= +UseLauncher=0 +DebugCWD= +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1049 +CodePage=1251 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= +[HistoryLists\hlConditionals] +Count=14 +Item0=MIRANDA;xFASTMM4;xDEBUG_LOG +Item1=SOCKET;xFASTMM4 +Item2=QIP;xFASTMM4; +Item3=AND_RQ;xFASTMM4 +Item4=TRILLIAN;xFASTMM4 +Item5=SOCKET;FASTMM4 +Item6=MIRANDA;FASTMM4 +Item7=MIRANDA;xFASTMM4 +Item8=xFASTMM4;TRILLIAN +Item9=SOCKET +Item10=QIP +Item11=AND_RQ +Item12=TRILLIAN +Item13=MIRANDA +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[HistoryLists\hlSearchPath] +Count=11 +Item0=.\MirandaINC;..\lib\FastMM4;..\lib\PNGImage;..\lib\TntUnicodeControls\Source +Item1=$(DELPHI)\Lib\Debug;.\MirandaINC;..\lib\FastMM4;..\lib\PNGImage;..\lib\TntUnicodeControls\Source +Item2=..\lib\FastMM4;..\lib\PNGImage;..\lib\TntUnicodeControls\Source +Item3=$(DELPHI)\Lib\Debug;..\lib\FastMM4;..\lib\PNGImage;..\lib\TntUnicodeControls\Source +Item4=.\MirandaINC;..\lib\FastMM4;..\lib\PNGImage;..\lib\TntUnicodeControls +Item5=$(DELPHI)\Lib\Debug;..\lib\FastMM4;..\lib\PNGImage;.\MirandaINC +Item6=$(DELPHI)\Lib\Debug;..\lib\FastMM4;..\lib\PNGImage +Item7=..\lib\FastMM4;..\lib\PNGImage;.\MirandaINC +Item8=..\lib\FastMM4;..\lib\PNGImage;.\MI\MirandaINC +Item9=..\lib\FastMM4;..\lib\PNGImage +Item10=..\lib\PNGImage +[HistoryLists\hlUnitOutputDirectory] +Count=2 +Item0=.\dcu +Item1=..\dcu +[HistoryLists\hlOutputDirectorry] +Count=2 +Item0=..\bin +Item1=C:\Documents and Settings\Pavel\Мои документы\Programming\Chess4Net\Testing\Client1\Plugins diff --git a/plugins/Chess4Net/MI/Chess4Net_MI.dpr b/plugins/Chess4Net/MI/Chess4Net_MI.dpr new file mode 100644 index 0000000000..0779b4eb35 --- /dev/null +++ b/plugins/Chess4Net/MI/Chess4Net_MI.dpr @@ -0,0 +1,70 @@ +library Chess4Net_MI; +{******************************* + plugin library for Miranda +********************************} + +(* +{$IFDEF FASTMM4} + FastMM4, +{$ENDIF} +*) + +uses +{$IFDEF FASTMM4} + FastMM4, +{$ENDIF} + Forms, + SysUtils, + Windows, + BitmapResUnit in '..\BitmapResUnit.pas', + ChessBoardHeaderUnit in '..\ChessBoardHeaderUnit.pas', + ChessBoardUnit in '..\ChessBoardUnit.pas' {ChessBoard}, + ConnectingUnit in '..\ConnectingUnit.pas' {ConnectingForm}, + ConnectorUnit in 'ConnectorUnit.pas', + ContinueUnit in '..\ContinueUnit.pas' {ContinueForm}, + ControlUnit in 'ControlUnit.pas', + DialogUnit in '..\DialogUnit.pas', + GameOptionsUnit in '..\GameOptionsUnit.pas' {GameOptionsForm}, + GlobalsLocalUnit in 'GlobalsLocalUnit.pas', + GlobalsUnit in '..\GlobalsUnit.pas', + InfoUnit in '..\InfoUnit.pas' {InfoForm}, + LocalizerUnit in '..\LocalizerUnit.pas', + LookFeelOptionsUnit in '..\LookFeelOptionsUnit.pas' {OptionsForm}, + ManagerUnit in '..\ManagerUnit.pas' {Manager}, + MessageDialogUnit in '..\MessageDialogUnit.pas', + ModalForm in '..\ModalForm.pas', + PluginCommonUnit in 'PluginCommonUnit.pas', + PosBaseChessBoardUnit in '..\PosBaseChessBoardUnit.pas', + PosBaseUnit in '..\PosBaseUnit.pas', + PromotionUnit in '..\PromotionUnit.pas' {PromotionForm}, + ChessRulesEngine in '..\ChessRulesEngine.pas', + ManagerUnit.MI in 'ManagerUnit.MI.pas', + TransmitGameSelectionUnit in 'TransmitGameSelectionUnit.pas' {TransmitGameSelectionForm}; + +{$R ..\Chess4Net.res} + +begin + ControlUnit.PLUGIN_NAME := 'Chess4Net'; + PLUGIN_MENU_NAME := '&Chess4Net'; + + with _PluginInfo^ do + begin + shortName := 'Chess4Net'; + version := MakeMirandaPluginVersion(201,0,0,1); // 2010.0 + description := PLUGIN_PLAYING_VIA; + author := 'Pavel Perminov'; + authorEmail := 'packpaul@mail.ru'; + copyright := '(c) 2007-2010 No Copyrights'; + homepage := 'http://www.chess4net.ru'; + end; + + guidPlugin := StringToGUID('{BF17C6E3-C52C-4CB8-88ED-E0FC5F5D566A}'); + miidPlugin := StringToGUID('{EBB410F6-E9AA-4F1B-8912-8C41E4EC0F90}'); // interface + + MirandaPluginMenuPosition := $7FFFFFFF; // or < $7FFFFFFF + + gCreatePluginInstance := CreatePluginInstance; + gInitializeControls := InitializeControls; + gDeinitializeControls := DeinitializeControls; + gErrorDuringPluginStart := ErrorDuringPluginStart; +end. diff --git a/plugins/Chess4Net/MI/ConnectorUnit.pas b/plugins/Chess4Net/MI/ConnectorUnit.pas new file mode 100644 index 0000000000..5a50610324 --- /dev/null +++ b/plugins/Chess4Net/MI/ConnectorUnit.pas @@ -0,0 +1,838 @@ +unit ConnectorUnit; + +interface + +uses + Classes, ExtCtrls, + m_globaldefs; + +type + TConnectorEvent = (ceConnected, ceDisconnected, ceData, ceError); + + TConnectorHandler = procedure(ce: TConnectorEvent; d1: pointer = nil; + d2: pointer = nil) of object; + + IConnectorable = interface + procedure ConnectorHandler(ce: TConnectorEvent; d1: pointer = nil; d2: pointer = nil); + end; + + TConnector = class + private + _sendTimer, _sendSystemTimer: TTimer; + + _connected, _opened: boolean; + _plugin: IConnectorable; + _hContact, _hFilterMsg: THandle; + _lstId, _contactLstId: integer; + // отсылаемое сообщение + _msg_sending, _unformated_msg_sending: string; + _cntrMsgIn: integer; // счётчик входящих сообщений + _cntrMsgOut: integer; // счётчик исходящих сообщений + _msg_buf: string; // буфер сообщений + // системное сообщение + _systemDataList: TStringList; + m_lwId: Longword; + m_LastSendTime: TDateTime; + +{$IFDEF DEBUG_LOG} + _logFile: Text; + + procedure InitLog; + procedure WriteToLog(const s: string); + procedure CloseLog; +{$ENDIF} + + procedure FsendTimerTimer(Sender: TObject); + procedure FsendSystemTimerTimer(Sender: TObject); + + function FGetOwnerNick: string; + function FGetContactNick: string; + function FFilterMsg(msg: string): boolean; + function FSendMessage(const vMessage: string): boolean; +// function FNotifySender(const vMessage: string): boolean; + procedure FNotifySender; + procedure FSendSystemData(sd: string); + function FDeformatMsg(var msg: string; out lstId, msgCntr: integer): boolean; + function FFormatMsg(const msg: string): string; + function FGetOwnerID: integer; + function FGetMultiSession: boolean; + procedure FSetMultiSession(bValue: boolean); + procedure FPluginConnectorHandler(ce: TConnectorEvent; + d1: pointer = nil; d2: pointer = nil); + + public + constructor Create(hContact: THandle); reintroduce; + destructor Destroy; override; + + procedure Close; + function Open(bMultiSession: boolean = TRUE): boolean; + function SendData(const d: string): boolean; + procedure SetPlugin(plugin: IConnectorable); + + property Connected: boolean read _connected; + property Opened: boolean read _opened; + property OwnerID: integer read FGetOwnerID; + property OwnerNick: string read FGetOwnerNick; + property ContactID: integer read _hContact; + property ContactNick: string read FGetContactNick; + property MultiSession: boolean read FGetMultiSession write FSetMultiSession; + end; + +procedure InitConnectorGlobals(const invitationStr, promtHeadStr, dataSeparator: string; maxMsgSize: integer = 256); + +implementation + +{$J+} {$I-} + +uses + SysUtils, DateUtils, StrUtils, Types, + m_api, + ControlUnit; + +type + TConnectorList = class(TList) + private + _iterator: integer; + _hContact: THandle; + + function FGetLastAddedConnector: TConnector; + + public + procedure AddConnector(Connector: TConnector); + procedure RemoveConnector(Connector: TConnector); + function GetFirstConnector(hContact: THandle): TConnector; + function GetNextConnector: TConnector; + property LastAddedConnector: TConnector read FGetLastAddedConnector; + end; + +var + g_connectorList: TConnectorList = nil; + g_msgBufferSize: integer; + g_bMultiSession: boolean; + + g_hNotifySender: THandle; + + // cntrMsgIn и cntrMsgOut были введены для преодоления бага с зависающими сообщениями + +const + MSG_INVITATION: string = '!&This is a plugin invitation message&!'; + // MSG_RESPOND: string = '!&This is a plugin respond message&!'; + // <сообщение> ::= PROMPT_HEAD [PROMPT_SEPARATOR <ид клиента>] PROMPT_SEPARATOR <номер сообщения> PROMPT_TAIL <сообщение> + PROMPT_HEAD: string = 'Plgn'; + PROMPT_SEPARATOR = ':'; + PROMPT_TAIL = '>'; + + DATA_SEPARATOR: string = '&&'; + + CMD_CLOSE = 'ext'; + CMD_CONTACT_LIST_ID = 'lstid'; + + MAX_MSG_TRYS = 3; // максимальное количество попыток пересыла после ошибки + MAX_RESEND_TRYS = 9; // максимальное количество попыток пересыла в таймере + MIN_TIME_BETWEEN_MSG = 30; // время между отправкой сообщений системе IM в мс + + OWNER_ID = 0; + +(* +function TConnector.FSendMessage(const vMessage: string): boolean; +const + LAST_SEND_TIME: TDateTime = 0.0; +var + _now: TDateTime; +begin + _now := Now; + if (MilliSecondsBetween(_now, LAST_SEND_TIME) < MIN_TIME_BETWEEN_MSG) then + Result := FALSE + else + begin + LAST_SEND_TIME := _now; + CallContactService(_hContact, PSS_MESSAGE, 0, LPARAM(PChar(vMessage))); + Result := TRUE; + end; +end; +*) + +// PP: Let's hope Miranda IM can messages to different contacts at the same time + +function TConnector.FSendMessage(const vMessage: string): boolean; +// const +// LAST_SEND_TIME: TDateTime = 0.0; +var + _now: TDateTime; +begin + _now := Now; + if (MilliSecondsBetween(_now, m_LastSendTime) < MIN_TIME_BETWEEN_MSG) then + Result := FALSE + else + begin + m_LastSendTime := _now; + CallContactService(_hContact, PSS_MESSAGE, 0, LPARAM(PChar(vMessage))); + Result := TRUE; + end; +end; + + +// деформатирование входящих сообщений. TRUE - если декодирование удалось +function TConnector.FDeformatMsg(var msg: string; out lstId, msgCntr: integer): boolean; +var + l: integer; +begin + Result := FALSE; + if LeftStr(msg, length(PROMPT_HEAD + PROMPT_SEPARATOR)) = (PROMPT_HEAD + PROMPT_SEPARATOR) then + begin + msg := RightStr(msg, length(msg) - length(PROMPT_HEAD + PROMPT_SEPARATOR)); + + // contactListId +// if (_contactLstId >= 0) then + if (g_bMultiSession) then + begin + l := pos(PROMPT_SEPARATOR, msg); + if (l > 0) then + begin + if (not TryStrToInt(LeftStr(msg, l - 1), lstId)) then + exit; + msg := RightStr(msg, length(msg) - l); + end + else + lstId := g_connectorList.LastAddedConnector._lstId; + end + else + lstId := -1; // no contactListId specified in message + + // Message counter + l := pos(PROMPT_TAIL, msg); + if ((l = 0) or (not TryStrToInt(LeftStr(msg, l - 1), msgCntr))) then + exit; + + msg := RightStr(msg, length(msg) - l); + // msg := AnsiReplaceStr(msg, '&', '&'); + + Result := TRUE; + end; +end; + + +function TConnector.FFilterMsg(msg: string): boolean; + + procedure NProceedData(msg: string); + + function NProceedSystemCommand(msg: string): boolean; + begin + Result := TRUE; + if (LeftStr(msg, length(CMD_CONTACT_LIST_ID)) = CMD_CONTACT_LIST_ID) then + begin + msg := RightStr(msg, length(msg) - length(CMD_CONTACT_LIST_ID) - 1); + TryStrToInt(msg, _contactLstId); + end + else if (msg = CMD_CLOSE) then + begin + FPluginConnectorHandler(ceDisconnected); + _connected := FALSE; + _opened := FALSE; + end + else + Result := FALSE; + end; + + var + n, l, i: integer; + arrDatas: TStringDynArray; + strCommand: string; + bSystemCommand: boolean; + begin { \NProceedData } + if (RightStr(msg, length(DATA_SEPARATOR)) <> DATA_SEPARATOR) then + msg := msg + DATA_SEPARATOR; + + n := -1; + l := 1; + repeat + inc(n); + l := PosEx(DATA_SEPARATOR, msg, l); + inc(l, length(DATA_SEPARATOR)); + until (l = length(DATA_SEPARATOR)); + + SetLength(arrDatas, n); + + bSystemCommand := TRUE; + i := 0; + while (i < n) do + begin + l := pos(DATA_SEPARATOR, msg); + strCommand := LeftStr(msg, l - 1); + + if (bSystemCommand) then // System commands can go only in the beginning by definition + begin + bSystemCommand := NProceedSystemCommand(strCommand); + if (bSystemCommand) then + begin + dec(n); + SetLength(arrDatas, n); + continue; + end; + end; + + arrDatas[i] := strCommand; + msg := RightStr(msg, length(msg) - length(DATA_SEPARATOR) - l + 1); + + inc(i); + end; { while } + + if (n > 0) then + begin + FPluginConnectorHandler(ceData, arrDatas); + end; + + Finalize(arrDatas); + end; + +var + lstId, cntrMsg: integer; +begin { TConnector.FFilterMsg } +{$IFDEF DEBUG_LOG} + WriteToLog('>> ' + msg); +{$ENDIF} + if (not Connected) then + begin + // if (msg = MSG_INVITATION) or (msg = MSG_RESPOND) then + if (msg = MSG_INVITATION) then + begin + // if msg = MSG_INVITATION then + // FSendMessage(MSG_RESPOND); + FSendSystemData(MSG_INVITATION); + if (g_bMultiSession) then + FSendSystemData(FFormatMsg(CMD_CONTACT_LIST_ID + ' ' + IntToStr(_lstId))); + _connected := TRUE; + FPluginConnectorHandler(ceConnected); + Result := TRUE; + end + else + Result := FALSE; + end + else // Connected + begin +{ + if (_msg_sending <> '') then + begin + _msg_sending := ''; + _unformated_msg_sending := ''; + inc(_cntrMsgOut); + end; +} + + if (FDeformatMsg(msg, lstId, cntrMsg) and ((not g_bMultisession) or (lstId = _lstId))) then + begin + Result := TRUE; + + if cntrMsg > _cntrMsgIn then + begin + inc(_cntrMsgIn); + if (cntrMsg > _cntrMsgIn) then + begin + FPluginConnectorHandler(ceError); // пакет исчез + exit; + end; + end + else + exit; // пропуск пакетов с более низкими номерами + + NProceedData(msg); + end + else + Result := FALSE; + end; +end; + + +procedure TConnector.FNotifySender; +begin +{$IFDEF DEBUG_LOG} + WriteToLog('<< ' + _msg_sending); +{$ENDIF} + if (Connected and (_msg_sending <> MSG_INVITATION)) then + begin + _unformated_msg_sending := ''; + inc(_cntrMsgOut); + end; + _msg_sending := ''; +end; + + +// форматирование исходящих сообщений +function TConnector.FFormatMsg(const msg: string): string; +var + contactLstIdStr: string; +begin + if (_contactLstId >= 0) then + contactLstIdStr := PROMPT_SEPARATOR + IntToStr(_contactLstId) + else // -1 + contactLstIdStr := ''; + Result := PROMPT_HEAD + contactLstIdStr + PROMPT_SEPARATOR + IntToStr(_cntrMsgOut) + PROMPT_TAIL + msg; +end; + + +procedure TConnector.Close; +begin + if (Connected) then + begin + FSendSystemData(FFormatMsg(CMD_CLOSE)); + + _connected := FALSE; + FPluginConnectorHandler(ceDisconnected); + end; + + _sendTimer.Enabled := FALSE; + _opened := FALSE; + +{$IFDEF DEBUG_LOG} + CloseLog; +{$ENDIF} +end; + + +function TConnector.Open(bMultiSession: boolean = TRUE): boolean; +var + AConnector: TConnector; +begin + Result := FALSE; + + if (not g_bMultiSession) then + g_bMultiSession := bMultisession; + + if (Assigned(g_connectorList)) then + begin + AConnector := g_connectorList.GetFirstConnector(_hContact); + while (Assigned(AConnector)) do + begin + if (AConnector.Opened and (AConnector._contactLstId < 0)) then + exit; + AConnector := g_connectorList.GetNextConnector; + end; + end; + + _cntrMsgIn := 0; + _cntrMsgOut := 1; + _msg_sending := ''; + _unformated_msg_sending := ''; + _msg_buf := ''; + _contactLstId := -1; + _opened := TRUE; + + FSendSystemData(MSG_INVITATION); + + Result := TRUE; +end; + + +function TConnector.SendData(const d: string): boolean; +begin + Result := FALSE; + if (d = '') or + (length(_msg_buf) + length(d) + length(DATA_SEPARATOR) > g_msgBufferSize) or + (LeftStr(d, length(CMD_CLOSE)) = CMD_CLOSE) or + (LeftStr(d, length(CMD_CONTACT_LIST_ID)) = CMD_CONTACT_LIST_ID) or + (pos(DATA_SEPARATOR, d) > 0) then + begin + exit; + end + else + begin + _msg_buf := _msg_buf + d + DATA_SEPARATOR; + _sendTimer.Enabled := TRUE; // Отослать сообщение с некоторой оттяжкой -> всё одним пакетом + end; + Result := TRUE; +end; + + +function FilterMsg(wParam: WPARAM; lParam_: LPARAM): int; cdecl; +var + msg: string; + hContact: THandle; + connector: TConnector; + proceeded: boolean; +begin + msg := string(PPROTORECVEVENT(PCCSDATA(lParam_).lParam).szMessage); + hContact := PCCSDATA(lParam_).hContact; + + proceeded := FALSE; + + if Assigned(g_connectorList) then + begin + connector := g_connectorList.GetFirstConnector(hContact); + while (Assigned(connector)) do + begin + if connector.Opened then + proceeded := (connector.FFilterMsg(msg) or proceeded); + connector := g_connectorList.GetNextConnector; + end; + end; + + if proceeded then + Result := 0 + else + Result := CallService(MS_PROTO_CHAINRECV, wParam, lParam_); +end; + + +function NotifySender(wParam: WPARAM; lParam_: LPARAM): int; cdecl; +const + MSG_TRYS: integer = 1; +var + connector: TConnector; + hContact: THandle; +begin + Result := 0; + hContact := PACKDATA(lParam_).hContact; + + if (PACKDATA(lParam_).type_ <> ACKTYPE_MESSAGE) then + exit; + + case PACKDATA(lParam_)^.result_ of + ACKRESULT_SUCCESS: + begin + MSG_TRYS := 1; + + connector := g_connectorList.GetFirstConnector(hContact); + while Assigned(connector) do + begin + if (connector._msg_sending <> '') then + connector.FNotifySender; + connector := g_connectorList.GetNextConnector; + end; + end; + + ACKRESULT_FAILED: + begin + inc(MSG_TRYS); + if (MSG_TRYS <= MAX_MSG_TRYS) then + begin + connector := g_connectorList.GetFirstConnector(hContact); + while (Assigned(connector)) do + begin + if connector._msg_sending <> '' then + with connector do + begin + _msg_buf := _unformated_msg_sending + _msg_buf; + _sendTimer.Enabled := TRUE; + end; + connector := g_connectorList.GetNextConnector; + end; // while + end + else + begin + connector := g_connectorList.GetFirstConnector(hContact); + while (Assigned(connector)) do + begin + if (connector._msg_sending <> '') then + begin + connector.FPluginConnectorHandler(ceError); + end; + connector := g_connectorList.GetNextConnector; + end; + end; // if (MSG_TRYS <= MAX_MSG_TRYS) + end; // ACKRESULT_FAILED + end; // case PACKDATA +end; + + +constructor TConnector.Create(hContact: THandle); +const + ID_COUNTER: Longword = 0; +var + connector: TConnector; +begin +// inherited Create; + _sendTimer := TTimer.Create(nil); + with _sendTimer do + begin + Enabled := FALSE; + Interval := 100; + OnTimer := FsendTimerTimer; + end; + + _sendSystemTimer := TTimer.Create(nil); + with _sendSystemTimer do + begin + Enabled := FALSE; + Interval := 50; + OnTimer := FsendSystemTimerTimer; + end; + + _hContact := hContact; + _systemDataList := TStringList.Create; + + if (not Assigned(g_connectorList)) then + g_connectorList := TConnectorList.Create; + + connector := g_connectorList.GetFirstConnector(_hContact); + if Assigned(connector) then + _hFilterMsg := connector._hFilterMsg + else + begin + _hFilterMsg := CreateProtoServiceFunction(PChar(PLUGIN_NAME), PSR_MESSAGE, FilterMsg); + if CallService(MS_PROTO_ISPROTOONCONTACT, _hContact, LPARAM(PChar(PLUGIN_NAME))) = 0 then + CallService(MS_PROTO_ADDTOCONTACT, _hContact, LPARAM(PChar(PLUGIN_NAME))); + end; + + if (g_connectorList.Count = 0) then + g_hNotifySender := HookEvent(ME_PROTO_ACK, NotifySender); + + inc(ID_COUNTER); + m_lwId := ID_COUNTER; + + g_connectorList.AddConnector(self); + +{$IFDEF DEBUG_LOG} + InitLog; +{$ENDIF} +end; + + +destructor TConnector.Destroy; +begin + if Connected then + while (not FSendMessage(FFormatMsg(CMD_CLOSE))) do + Sleep(1); + + _systemDataList.Free; + + g_connectorList.RemoveConnector(self); + if (g_connectorList.Count = 0) then + g_bMultiSession := FALSE; + + if (not Assigned(g_connectorList.GetFirstConnector(_hContact))) then + begin + if CallService(MS_PROTO_ISPROTOONCONTACT, _hContact, LPARAM(PChar(PLUGIN_NAME))) <> 0 then + CallService(MS_PROTO_REMOVEFROMCONTACT, _hContact, LPARAM(PChar(PLUGIN_NAME))); + PluginLink.DestroyServiceFunction(_hFilterMsg); + end; + + if (g_connectorList.Count = 0) then + begin + if (g_hNotifySender <> 0) then + UnhookEvent(g_hNotifySender); + FreeAndNil(g_connectorList); + end; + + _sendSystemTimer.Free; + _sendTimer.Free; + +{$IFDEF DEBUG_LOG} + CloseLog; +{$ENDIF} + + inherited; +end; + +{$IFDEF DEBUG_LOG} +procedure TConnector.InitLog; +begin + AssignFile(_logFile, MirandaPluginPath + 'Chess4Net_CONNECTORLOG.txt'); + Append(_logFile); + if IOResult <> 0 then + begin + Rewrite(_logFile); + if IOResult <> 0 then + begin + AssignFile(_logFile, MirandaPluginPath + 'Chess4Net_CONNECTORLOG~.txt'); + Append(_logFile); + if IOResult <> 0 then Rewrite(_logFile); + end; + end; + + WriteToLog('[' + DateTimeToStr(Now) + ']'); +end; + + +procedure TConnector.WriteToLog(const s: string); +begin + writeln(_logFile, s); + Flush(_logFile); +end; + + +procedure TConnector.CloseLog; +begin + CloseFile(_logFile); +end; +{$ENDIF} + +procedure TConnector.FsendTimerTimer(Sender: TObject); +const + RESEND_COUNT : integer = 0; +begin + if (_systemDataList.Count > 0) then + exit; // System data goes first + + if (_msg_sending = '') then + begin + _sendTimer.Enabled := FALSE; + if (_msg_buf <> '') then + begin + _unformated_msg_sending := _msg_buf; + _msg_sending := FFormatMsg(_msg_buf); + _msg_buf := ''; + + _sendTimer.Enabled := (not FSendMessage(_msg_sending)); + end; + end + else + begin +{$IFDEF DEBUG_LOG} + WriteToLog('resend: ' + _msg_sending); +{$ENDIF} + inc(RESEND_COUNT); + if (RESEND_COUNT = MAX_RESEND_TRYS) then + begin + RESEND_COUNT := 0; + FSendMessage(_msg_sending); + end; + end; +end; + + +procedure TConnector.SetPlugin(plugin: IConnectorable); +begin + _plugin := plugin; +end; + + +function TConnector.FGetOwnerNick: string; +begin + Result := PChar(CallService(MS_CLIST_GETCONTACTDISPLAYNAME, 0, 0)); +end; + + +function TConnector.FGetContactNick: string; +begin + Result := PChar(CallService(MS_CLIST_GETCONTACTDISPLAYNAME, _hContact, 0)); +end; + + +procedure InitConnectorGlobals(const invitationStr, promtHeadStr, dataSeparator: string; maxMsgSize: integer = 256); +begin + MSG_INVITATION := invitationStr; + PROMPT_HEAD := promtHeadStr; + DATA_SEPARATOR := dataSeparator; + g_msgBufferSize := maxMsgSize; +end; + +{---------------------------- TConnectorList ---------------------------------} + +procedure TConnectorList.AddConnector(Connector: TConnector); +var + i: integer; +begin + for i := 0 to Count - 1 do + begin + if (not Assigned(Items[i])) then + begin + Connector._lstId := i; + Items[i] := Connector; + exit; + end; + end; // for + Add(Connector); + Connector._lstId := Count - 1; +end; + + +procedure TConnectorList.RemoveConnector(Connector: TConnector); +begin + Items[Connector._lstId] := nil; + while ((Count > 0) and (not Assigned(Items[Count - 1]))) do + Delete(Count - 1); +end; + + +function TConnectorList.GetFirstConnector(hContact: THandle): TConnector; +begin + _hContact := hContact; + + _iterator := -1; + Result := GetNextConnector; +end; + + +function TConnectorList.GetNextConnector: TConnector; +begin + Result := nil; + + while (_iterator < (Count - 1)) do + begin + inc(_iterator); + if (Assigned(Items[_iterator]) and + (_hContact = TConnector(Items[_iterator])._hContact)) then + begin + Result := Items[_iterator]; + exit; + end; + end; +end; + + +function TConnectorList.FGetLastAddedConnector: TConnector; +var + i: integer; +begin + Result := nil; + for i := 0 to Count - 1 do + begin + if ((not Assigned(Result)) or (TConnector(Items[i]).m_lwId > Result.m_lwId)) then + Result := Items[i]; + end; +end; + + +procedure TConnector.FsendSystemTimerTimer(Sender: TObject); +begin + if _systemDataList.Count = 0 then + begin + _sendSystemTimer.Enabled := FALSE; + exit; + end; + + _msg_sending := _systemDataList[0]; + if FSendMessage(_msg_sending) then + _systemDataList.Delete(0); + // else: try to resend +end; + + +procedure TConnector.FSendSystemData(sd: string); +begin + if ((sd <> MSG_INVITATION) and (sd <> CMD_CLOSE)) then + sd := sd + DATA_SEPARATOR; + _systemDataList.Add(sd); + _sendSystemTimer.Enabled := TRUE; +end; + + +function TConnector.FGetOwnerID: integer; +begin + Result := OWNER_ID; +end; + + +procedure TConnector.FSetMultiSession(bValue: boolean); +begin + if ((not g_bMultiSession) and bValue) then + begin + FSendSystemData(FFormatMsg(CMD_CONTACT_LIST_ID + ' ' + IntToStr(_lstId))); + g_bMultiSession := TRUE; + end; +end; + +procedure TConnector.FPluginConnectorHandler(ce: TConnectorEvent; + d1: pointer = nil; d2: pointer = nil); +begin + if (Assigned(_plugin)) then + _plugin.ConnectorHandler(ce, d1, d2); +end; + + +function TConnector.FGetMultiSession: boolean; +begin + Result := g_bMultiSession; +end; + +end. diff --git a/plugins/Chess4Net/MI/ControlUnit.pas b/plugins/Chess4Net/MI/ControlUnit.pas new file mode 100644 index 0000000000..f9f8694e86 --- /dev/null +++ b/plugins/Chess4Net/MI/ControlUnit.pas @@ -0,0 +1,171 @@ +unit ControlUnit; + +interface + +uses + Graphics, + SysUtils, //Classes, + m_globaldefs, m_api, + ConnectorUnit; + +type + IMirandaPlugin = interface(IConnectorable) // Implementatation class must be non-referenced + ['{CE794050-DBA2-4D2E-867E-59A873DF7304}'] + procedure Start; + procedure Stop; + end; + +const + PLUGIN_NAME: string = 'MirandaPlugin'; + PLUGIN_MENU_NAME: string = 'Miranda&Plugin'; + +var + _PluginInfo: PPLUGININFO = @PLUGININFO; + guidPlugin, miidPlugin: TGUID; + + MirandaPluginsPath, MirandaPluginPath: string; + + MirandaPluginIcon: TIcon = nil; + MirandaPluginMenuPosition: integer = $7FFFFFFF; + +// gShowPluginOptions: TProcedure = nil; +// gShowWrongSDKVersion: TProcedure = nil; + gCreatePluginInstance: function(Connector: TConnector): IMirandaPlugin = nil; + gInitializeControls: TProcedure = nil; + gDeinitializeControls: TProcedure = nil; +// gStartOnWrongMsgProtocol: function: boolean = nil; + gErrorDuringPluginStart: TProcedure = nil; + +function MirandaPluginInfo(mirandaVersion: DWORD): PPLUGININFO; cdecl; +function MirandaPluginInfoEx(mirandaVersion: DWORD): PPLUGININFO; cdecl; +function MirandaPluginInterfaces: PGUID; cdecl; +function Load(link: PPLUGINLINK): int; cdecl; +function Unload: int; cdecl; + +function MakeMirandaPluginVersion(a, b, c, d: byte): int; + +exports + MirandaPluginInfo, MirandaPluginInfoEx, MirandaPluginInterfaces, Load, Unload; + +implementation + +uses + Dialogs, Controls, Forms, + PluginCommonUnit; + +var + PluginInterfaces: array[0..1] of TGUID; + g_hMenuCommand: THandle; + +function MirandaPluginInfo(mirandaVersion: DWORD): PPLUGININFO; cdecl; +begin + PLUGININFO.cbSize := sizeof(TPLUGININFO); + PLUGININFO.isTransient := 0; + PLUGININFO.replacesDefaultModule := 0; + + Result := @PLUGININFO; +end; + + +function MirandaPluginInfoEx(mirandaVersion: DWORD): PPLUGININFO; cdecl; +begin + MirandaPluginInfo(mirandaVersion); // Initialize PLUGININFO + + Move(PLUGININFO, PLUGININFOEX, sizeof(TPLUGININFO)); + PLUGININFOEX.cbSize := sizeof(TPLUGININFOEX); + PLUGININFOEX.uuid := guidPlugin; + + Result := @PLUGININFOEX; +end; + + +function MirandaPluginInterfaces: PGUID; cdecl; +begin + PluginInterfaces[0] := miidPlugin; + PluginInterfaces[1] := MIID_LAST; + + Result := @PluginInterfaces; +end; + + +function Start(wParam: WPARAM; lParam_: LPARAM): Integer; cdecl; +var + Connector: TConnector; + pluginInstance: IMirandaPlugin; +begin + Connector := nil; + Pointer(pluginInstance) := nil; + + try + Connector := TConnector.Create(wParam); + pluginInstance := gCreatePluginInstance(Connector); + Connector.SetPlugin(pluginInstance); + pluginInstance.Start; + Pointer(pluginInstance) := nil; + Result := 0; + except + if (Assigned(gErrorDuringPluginStart)) then + gErrorDuringPluginStart; + if (Assigned(Connector)) then + Connector.SetPlugin(nil); + if (Assigned(pluginInstance)) then + begin + pluginInstance.Stop; + Pointer(pluginInstance) := nil; + end; + Result := -1; + end; +end; + + +function Load(link: PPLUGINLINK): int; cdecl; +var + mi: TCListMenuItem; + prt: TPROTOCOLDESCRIPTOR; +begin + if Assigned(gInitializeControls) then + gInitializeControls; + + PLUGINLINK := Pointer(link); + g_hMenuCommand := pluginLink^.CreateServiceFunction(PChar(PLUGIN_NAME + '/MenuCommand'), @Start); + FillChar(mi, sizeof(mi), 0); + mi.cbSize := sizeof(mi); + mi.position := MirandaPluginMenuPosition; + mi.flags := 0; // ? +// mi.hIcon := LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); // загрузка родной иконки +// mi.hIcon := LoadIcon(hInstance, 'MAINICON'); // загрузка иконки из ресурса + if Assigned(MirandaPluginIcon) then + mi.hIcon := MirandaPluginIcon.Handle; + mi.pszName := PChar(PLUGIN_MENU_NAME); + mi.pszService := PChar(PLUGIN_NAME + '/MenuCommand'); + CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, LPARAM(@mi)); + + // регистрация фильтра сообщений + prt.cbSize := sizeof(prt); + prt.szName := PChar(PLUGIN_NAME); + prt.type_ := PROTOTYPE_FILTER; + CallService(MS_PROTO_REGISTERMODULE, 0, LPARAM(@prt)); + + Result := 0; +end; + + +function Unload: int; cdecl; +begin + if Assigned(gDeinitializeControls) then + gDeinitializeControls; + pluginLink^.DestroyServiceFunction(g_hMenuCommand); + g_hMenuCommand := 0; + Result := 0; +end; + + +function MakeMirandaPluginVersion(a, b, c, d: byte): int; +begin + Result := PLUGIN_MAKE_VERSION(a,b,c,d); +end; + +initialization + MirandaPluginsPath := ExtractFileDir(Application.ExeName) + '\Plugins\'; + +end. diff --git a/plugins/Chess4Net/MI/GlobalsLocalUnit.pas b/plugins/Chess4Net/MI/GlobalsLocalUnit.pas new file mode 100644 index 0000000000..3e1c6018ff --- /dev/null +++ b/plugins/Chess4Net/MI/GlobalsLocalUnit.pas @@ -0,0 +1,31 @@ +unit GlobalsLocalUnit; + +// Модуль для глобальных переменных и констант версии для Миранды + +interface + +uses + Graphics; + +const + CHESS4NET = 'Chess4Net'; + CHESS4NET_VERSION = 201000; // 2010.0 + CHESS4NET_TITLE = 'Chess4Net 2010.0 (http://chess4net.ru)'; + MSG_INVITATION = 'Wellcome to Chess4Net. If you don''t have it, please download it from http://chess4net.ru'; + PROMPT_HEAD = 'Ch4N'; + MSG_DATA_SEPARATOR = '&&'; + + PLUGIN_NAME = CHESS4NET; + PLUGIN_VERSION = CHESS4NET_VERSION; + PLUGIN_PLAYING_VIA = 'Plugin for playing chess via Miranda'; + PLUGIN_INFO_NAME = 'Chess4Net 2010.0.1'; + PLUGIN_URL = 'http://chess4net.ru'; + PLUGIN_EMAIL = 'packpaul@mail.ru'; + +var + Chess4NetPath: string; + Chess4NetIcon, pluginIcon: TIcon; + +implementation + +end. diff --git a/plugins/Chess4Net/MI/ManagerUnit.MI.pas b/plugins/Chess4Net/MI/ManagerUnit.MI.pas new file mode 100644 index 0000000000..a27ff73463 --- /dev/null +++ b/plugins/Chess4Net/MI/ManagerUnit.MI.pas @@ -0,0 +1,869 @@ +unit ManagerUnit.MI; + +interface + +uses + SysUtils, + // + ControlUnit, ManagerUnit, ConnectorUnit, ModalForm; + +type + TNonRefInterfacedObject = class(TObject, IInterface) + protected + function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; + function _AddRef: Integer; stdcall; + function _Release: Integer; stdcall; + end; + + TManagerMIFactory = class(TNonRefInterfacedObject, IMirandaPlugin) + private + m_Connector: TConnector; + m_Manager: IMirandaPlugin; + m_Dialogs: TDialogs; + m_bOwnExceptionHandler: boolean; + FErrorDuringPluginStart: TProcedure; + procedure FDialogsHandler(modSender: TModalForm; msgDlgID: TModalFormID); + function FGetDialogs: TDialogs; + procedure FStartGaming; + procedure FStartTransmitting; overload; + procedure FStartTransmitting(ManagerForTransmition: TManager); overload; + function FCanStartTransmitting: boolean; + procedure FHandleStartException; + property Dialogs: TDialogs read FGetDialogs; + protected + procedure Start; + procedure Stop; + procedure ConnectorHandler(ce: TConnectorEvent; d1: pointer = nil; d2: pointer = nil); + public + constructor Create(Connector: TConnector; AErrorDuringPluginStart: TProcedure); reintroduce; + destructor Destroy; override; + end; + +procedure StopAllPlugins; + +implementation + +uses + Types, StrUtils, Classes, Dialogs, Controls, + // + LocalizerUnit, TransmitGameSelectionUnit, GlobalsLocalUnit, ChessBoardUnit; + +type + TManagerMI = class(TManager, IMirandaPlugin) // abstract + protected + procedure Start; + procedure Stop; + procedure RSendData(const cmd: string); override; + procedure ROnDestroy; override; + + procedure ConnectorHandler(e: TConnectorEvent; d1: pointer = nil; d2: pointer = nil); override; + procedure RSetOpponentClientVersion(lwVersion: LongWord); override; + + public + constructor Create(Connector: TConnector); reintroduce; + destructor Destroy; override; + end; + + TTransmittingManagerMI = class; + + EGamingManagerMI = class(Exception); + TGamingManagerMI = class(TManagerMI, IMirandaPlugin) + private + m_lstTransmittingManagers: TList; + + procedure FAddTransmitter(ATransmitter: TTransmittingManagerMI); + function FRemoveTransmitter(ATransmitter: TTransmittingManagerMI): boolean; + procedure FSetGameContextToTransmitter(ATransmitter: TTransmittingManagerMI); + function FContainsContactIDInTransmitters(iContactID: integer): boolean; + procedure FUpdateChessBoardCaptions; + + protected + procedure Start; + procedure ROnCreate; override; + procedure ROnDestroy; override; + procedure ConnectorHandler(e: TConnectorEvent; d1: pointer = nil; d2: pointer = nil); override; + procedure RSetConnectionOccured; override; + procedure RHandleConnectorDataCommand(sl: string); override; + procedure RRetransmit(const strCmd: string); override; + function RGetGameName: string; override; + end; + + ETransmittingManagerMI = class(Exception); + TTransmittingManagerMI = class(TManagerMI, IMirandaPlugin) // TODO: move to separate hierarchy + private + m_GamingManager: TGamingManagerMI; + m_bReady: boolean; // ready for transmition + protected + procedure Start; + procedure ROnCreate; override; + procedure ROnDestroy; override; + + procedure ConnectorHandler(e: TConnectorEvent; d1: pointer = nil; d2: pointer = nil); override; + procedure RHandleConnectorDataCommand(sl: string); override; +// procedure RWriteSettings; override; // no need because m_bConnectionOccured is always FALSE + + public + constructor Create(Connector: TConnector; GamingManager: TGamingManagerMI); reintroduce; + end; + +var + g_lstGamingManagers: TList = nil; + g_Plugins: TInterfaceList = nil; + +procedure AddToPlugins(Plugin: IMirandaPlugin); +begin + if (not Assigned(g_Plugins)) then + g_Plugins := TInterfaceList.Create; + g_Plugins.Add(Plugin); +end; + +procedure RemoveFromPlugins(Plugin: IMirandaPlugin); +begin + if (not Assigned(g_Plugins)) then + exit; + g_Plugins.Remove(Plugin); + if (g_Plugins.Count = 0) then + FreeAndNil(g_Plugins); +end; + + +procedure StopAllPlugins; +var + i: integer; + Plugin: IMirandaPlugin; +begin + if (not Assigned(g_Plugins)) then + exit; + i := g_Plugins.Count - 1; + while ((i >= 0) and Assigned(g_Plugins)) do + begin + Plugin := g_Plugins[i] as IMirandaPlugin; + Plugin.Stop; + Pointer(Plugin) := nil; + dec(i); + end; + FreeAndNil(g_Plugins); +end; + +//////////////////////////////////////////////////////////////////////////////// +// TGamingManagerMI + +procedure TGamingManagerMI.FAddTransmitter(ATransmitter: TTransmittingManagerMI); +begin + if (not Assigned(m_lstTransmittingManagers)) then + m_lstTransmittingManagers := TList.Create; + m_lstTransmittingManagers.Add(ATransmitter); +end; + + +function TGamingManagerMI.FRemoveTransmitter(ATransmitter: TTransmittingManagerMI): boolean; +var + i: integer; +begin + Result := FALSE; + + if (not Assigned(m_lstTransmittingManagers)) then + exit; + + for i := 0 to m_lstTransmittingManagers.Count - 1 do + begin + if (m_lstTransmittingManagers[i] = ATransmitter) then + begin + m_lstTransmittingManagers.Delete(i); + if (m_lstTransmittingManagers.Count = 0) then + FreeAndNil(m_lstTransmittingManagers); + + Result := TRUE; + exit; + end; + end; // for +end; + + +procedure TGamingManagerMI.FSetGameContextToTransmitter(ATransmitter: TTransmittingManagerMI); +begin + if (not (Assigned(ATransmitter) and ATransmitter.m_bReady)) then + exit; + + ATransmitter.RSendData(CMD_NICK_ID + ' ' + PlayerNickId + ' ' + OpponentNickId + ' ' + OpponentNick); + ATransmitter.RSendData(CMD_GAME_CONTEXT + ' ' + RGetGameContextStr); + + if (ChessBoard.Mode = mGame) then + ATransmitter.RSendData(CMD_CONTINUE_GAME); +end; + + +function TGamingManagerMI.FContainsContactIDInTransmitters(iContactID: integer): boolean; +var + i: integer; + ATransmitter: TTransmittingManagerMI; +begin + Result := FALSE; + if (not Assigned(m_lstTransmittingManagers)) then + exit; + for i := 0 to m_lstTransmittingManagers.Count - 1 do + begin + ATransmitter := m_lstTransmittingManagers[i]; + if (Assigned(ATransmitter) and (ATransmitter.Connector.ContactID = iContactID)) then + begin + Result := TRUE; + exit; + end; + end; +end; + + +procedure TGamingManagerMI.Start; +begin + if (Assigned(ChessBoard)) then + begin + Show; + exit; + end; + + if (not Connector.Opened) then + begin + if (not Connector.Open(FALSE)) then + raise EGamingManagerMI.Create('ERROR: Cannot open connector!'); + end; + + RCreateChessBoardAndDialogs; + RSetChessBoardToView; + + RReadPrivateSettings; + + RShowConnectingForm; +end; + + +procedure TGamingManagerMI.ROnCreate; +begin + RCreateAndPopulateExtBaseList; + + // Nicks initialization + PlayerNick := Connector.OwnerNick; + OpponentNick := Connector.ContactNick; + OpponentId := IntToStr(Connector.ContactID); + + TLocalizer.Instance.AddSubscriber(self); // TODO: -> TManager.ROnCreate + RLocalize; +end; + + +procedure TGamingManagerMI.ROnDestroy; + + procedure NRemoveFromGamings; + var + lstTmp: TList; + i: integer; + ATransmitter: TTransmittingManagerMI; + begin + if (Assigned(g_lstGamingManagers)) then + g_lstGamingManagers.Remove(self); + + if (not Assigned(m_lstTransmittingManagers)) then + exit; + + lstTmp := m_lstTransmittingManagers; + m_lstTransmittingManagers := nil; + + for i := 0 to lstTmp.Count - 1 do + begin + ATransmitter := lstTmp[i]; + if (Assigned(ATransmitter)) then + begin + lstTmp[i] := nil; + ATransmitter.Stop; + end; + end; + + lstTmp.Free; + end; + +begin // TGamingManagerMI.ROnDestroy + NRemoveFromGamings; + FUpdateChessBoardCaptions; + inherited ROnDestroy; +end; + + +procedure TGamingManagerMI.ConnectorHandler(e: TConnectorEvent; + d1: pointer = nil; d2: pointer = nil); +begin + case e of + ceError: + begin + Connector.Close; + inherited ConnectorHandler(e, d1, d2); + end; + + else + inherited ConnectorHandler(e, d1, d2); + end; // case +end; + + +procedure TGamingManagerMI.RSetConnectionOccured; +var + iIndex: integer; +begin + inherited RSetConnectionOccured; + + if (not Assigned(g_lstGamingManagers)) then + g_lstGamingManagers := TList.Create; + + iIndex := g_lstGamingManagers.IndexOf(self); + if (iIndex < 0) then + g_lstGamingManagers.Add(self); + + FUpdateChessBoardCaptions; +end; + + +procedure TGamingManagerMI.FUpdateChessBoardCaptions; +var + i: integer; + GM: TGamingManagerMI; +begin + if (not Assigned(g_lstGamingManagers)) then + exit; + for i := 0 to g_lstGamingManagers.Count - 1 do + begin + GM := g_lstGamingManagers[i]; + if (Assigned(GM)) then + GM.RUpdateChessBoardCaption; + end; +end; + + +procedure TGamingManagerMI.RRetransmit(const strCmd: string); +var + i: integer; + ATransmitter: TTransmittingManagerMI; +begin + if (Transmittable or (not Assigned(m_lstTransmittingManagers))) then + exit; + + for i := 0 to m_lstTransmittingManagers.Count - 1 do + begin + ATransmitter := m_lstTransmittingManagers[i]; + if (Assigned(ATransmitter) and (ATransmitter.m_bReady)) then + ATransmitter.RSendData(strCmd); + end; +end; + + +function TGamingManagerMI.RGetGameName: string; +var + i: integer; + iIndex: integer; + iWithSameConnectorCount: integer; + GM: TGamingManagerMI; +begin + Result := inherited RGetGameName; + + if (not Assigned(g_lstGamingManagers)) then + exit; + + iWithSameConnectorCount := 0; + iIndex := 0; + + for i := 0 to g_lstGamingManagers.Count - 1 do + begin + GM := g_lstGamingManagers[i]; + if (Assigned(GM) and (GM.Connector.ContactID = self.Connector.ContactID)) then + begin + inc(iWithSameConnectorCount); + if (GM = self) then + iIndex := iWithSameConnectorCount; + end; // if + end; // for + + if (iWithSameConnectorCount > 1) then + Result := Result + ' (' + IntToStr(iIndex) + ')'; +end; + + +procedure TGamingManagerMI.RHandleConnectorDataCommand(sl: string); +var + strCmdSaved, sr: string; +begin + strCmdSaved := sl; + + RSplitStr(sl, sl, sr); + + if (sl = CMD_TRANSMITTING) then + begin + Transmittable := TRUE; + exit; + end; + + if (not Transmittable) then + begin + inherited RHandleConnectorDataCommand(strCmdSaved); + exit; + end; + + if (sl = CMD_WELCOME) then + begin + if (Assigned(ChessBoard)) then + ChessBoard.InitPosition; + RSetConnectionOccured; + end + else if (sl = CMD_NICK_ID) then + begin + // sr ::= + PlayerNick := OpponentNick; // change for transmittion + + RSplitStr(sr, sl, sr); + PlayerNickId := sl; + + RSplitStr(sr, sl, sr); + OpponentNickId := sl; + + RSplitStr(sr, sl, sr); + OpponentNick := sl; + + ChessBoard.Caption := RGetGameName; + end + else if (sl = CMD_GAME_CONTEXT) then + begin + RSetGameContext(sr); + end + else + inherited RHandleConnectorDataCommand(strCmdSaved); +end; + +//////////////////////////////////////////////////////////////////////////////// +// TManagerMIFactory + +constructor TManagerMIFactory.Create(Connector: TConnector; AErrorDuringPluginStart: TProcedure); +begin + inherited Create; + m_Connector := Connector; + FErrorDuringPluginStart := AErrorDuringPluginStart; + AddToPlugins(self); +end; + + +destructor TManagerMIFactory.Destroy; +begin + RemoveFromPlugins(self); + m_Dialogs.Free; + inherited; +end; + + +procedure TManagerMIFactory.Start; +begin + if (FCanStartTransmitting) then + begin + Dialogs.MessageDlg(TLocalizer.Instance.GetMessage(28), mtCustom, + [mbYes, mbNo], mfTransmitting); // You are currently playing some games. Do you want to start broadcasting? + m_bOwnExceptionHandler := TRUE; + exit; + end; + + FStartGaming; +end; + + +function TManagerMIFactory.FCanStartTransmitting: boolean; +var + i: integer; + GM: TGamingManagerMI; +begin + Result := FALSE; + + if (not (Assigned(g_lstGamingManagers) and Assigned(m_Connector))) then + exit; + + for i := 0 to g_lstGamingManagers.Count - 1 do + begin + GM := g_lstGamingManagers[i]; + Result := (Assigned(GM) and (not GM.Transmittable) and + (m_Connector.ContactID <> GM.Connector.ContactID) and + (not GM.FContainsContactIDInTransmitters(m_Connector.ContactID))); + if (Result) then + exit; + end; // for +end; + + +procedure TManagerMIFactory.FStartGaming; +begin + m_Manager := TGamingManagerMI.Create(m_Connector); + m_Connector.SetPlugin(m_Manager); + m_Connector := nil; + + try + m_Manager.Start; + Pointer(m_Manager) := nil; + except + if (m_bOwnExceptionHandler) then + FHandleStartException + else + raise; + end; + + Stop; +end; + + +procedure TManagerMIFactory.FHandleStartException; +begin + if (Assigned(FErrorDuringPluginStart)) then + FErrorDuringPluginStart; +end; + + +procedure TManagerMIFactory.FStartTransmitting(ManagerForTransmition: TManager); +begin + m_Manager := TTransmittingManagerMI.Create(m_Connector, ManagerForTransmition as TGamingManagerMI); + m_Connector.SetPlugin(m_Manager); + m_Connector := nil; + + try + m_Manager.Start; + Pointer(m_Manager) := nil; + except + if (m_bOwnExceptionHandler) then + FHandleStartException + else + raise; + end; + + Stop; +end; + + +procedure TManagerMIFactory.FStartTransmitting; +var + strlGames: TStringList; + i: integer; + GM: TGamingManagerMI; + ATransmitGameSelectionForm: TTransmitGameSelectionForm; +begin + if (not Assigned(g_lstGamingManagers)) then + begin + Stop; // Don't do anything + exit; + end; + + strlGames := TStringList.Create; + try + for i := 0 to g_lstGamingManagers.Count - 1 do + begin + GM := g_lstGamingManagers[i]; + if (Assigned(GM) and (not GM.Transmittable) and + (m_Connector.ContactID <> GM.Connector.ContactID) and + (not GM.FContainsContactIDInTransmitters(m_Connector.ContactID))) then + strlGames.AddObject(GM.RGetGameName, GM); + end; + + if (strlGames.Count > 1) then + begin + ATransmitGameSelectionForm := + Dialogs.CreateDialog(TTransmitGameSelectionForm) as TTransmitGameSelectionForm; + ATransmitGameSelectionForm.SetGames(strlGames); + ATransmitGameSelectionForm.Show; + end + else if (strlGames.Count = 1) then + begin + GM := strlGames.Objects[0] as TGamingManagerMI; + FStartTransmitting(GM); + end + else // = 0 + Stop; + + finally + strlGames.Free; + end; +end; + + +procedure TManagerMIFactory.Stop; +begin + if (Assigned(m_Connector)) then + begin + m_Connector.SetPlugin(nil); + m_Connector.Free; + end; + if (Assigned(m_Manager)) then + begin + m_Manager.Stop; + Pointer(m_Manager) := nil; + end; + Free; +end; + + +procedure TManagerMIFactory.ConnectorHandler(ce: TConnectorEvent; + d1: pointer = nil; d2: pointer = nil); +begin +end; + + +function TManagerMIFactory.FGetDialogs: TDialogs; +begin + if (not Assigned(m_Dialogs)) then + m_Dialogs := TDialogs.Create(nil, FDialogsHandler); + Result := m_Dialogs; +end; + + +procedure TManagerMIFactory.FDialogsHandler(modSender: TModalForm; msgDlgID: TModalFormID); +var + modRes: TModalResult; + GM: TGamingManagerMI; +begin + modRes := modSender.ModalResult; + case msgDlgID of + mfNone: + ; + mfTransmitting: + begin + if (modRes = mrYes) then + FStartTransmitting + else // mrNo + FStartGaming; + end; + + mfTransmitGame: + begin + if (modRes = mrOk) then + begin + with modSender as TTransmitGameSelectionForm do + begin + GM := GetSelected as TGamingManagerMI; + FStartTransmitting(GM); + end; + end + else + Stop; + end; + end; // case +end; + +//////////////////////////////////////////////////////////////////////////////// +// TNonRefInterfacedObject + +function TNonRefInterfacedObject.QueryInterface(const IID: TGUID; out Obj): HResult; +begin + if GetInterface(IID, Obj) then + Result := 0 + else + Result := E_NOINTERFACE; +end; + + +function TNonRefInterfacedObject._AddRef: Integer; +begin + Result := -1; +end; + + +function TNonRefInterfacedObject._Release: Integer; +begin + Result := -1; +end; + +//////////////////////////////////////////////////////////////////////////////// +// TTransmittingManagerMI + +constructor TTransmittingManagerMI.Create(Connector: TConnector; GamingManager: TGamingManagerMI); +begin + inherited Create(Connector); + m_GamingManager := GamingManager; +end; + +procedure TTransmittingManagerMI.Start; +begin + if (not Connector.Opened) then + begin + if (not Connector.Open(FALSE)) then + raise ETransmittingManagerMI.Create('ERROR: Cannot open connector!'); + end; + m_GamingManager.FAddTransmitter(self); +end; + + +procedure TTransmittingManagerMI.ROnDestroy; + + procedure NRemoveFromTransmittings; + var + i: integer; + GM: TGamingManagerMI; + begin + if (not Assigned(g_lstGamingManagers)) then + exit; + + for i := 0 to g_lstGamingManagers.Count - 1 do + begin + GM := g_lstGamingManagers[i]; + if (Assigned(GM) and GM.FRemoveTransmitter(self)) then + break; + end; + end; + +begin // TTransmittingManagerMI.ROnDestroy + NRemoveFromTransmittings; + inherited ROnDestroy; +end; + + +procedure TTransmittingManagerMI.ROnCreate; +begin +// PlayerNick := m_GamingManager.PlayerNick; +// OpponentNick := m_GamingManager.OpponentNick; +// OpponentId := m_GamingManager.OpponentId; +end; + + +procedure TTransmittingManagerMI.ConnectorHandler(e: TConnectorEvent; d1: pointer = nil; d2: pointer = nil); +begin + case e of + ceConnected: + begin + RSendData(CMD_VERSION + ' ' + IntToStr(CHESS4NET_VERSION)); + RSendData(CMD_TRANSMITTING); + end; + + ceError, ceDisconnected: + begin + Connector.Close; + Stop; + end; + + else + inherited ConnectorHandler(e, d1, d2); + end; // case +end; + + +procedure TTransmittingManagerMI.RHandleConnectorDataCommand(sl: string); +var + sr: string; + lwOpponentClientVersion: Longword; +begin + RSplitStr(sl, sl, sr); + if (sl = CMD_VERSION) then + begin + RSplitStr(sr, sl, sr); + lwOpponentClientVersion := StrToIntDef(sl, CHESS4NET_VERSION); + + if (lwOpponentClientVersion < 201000) then + begin + RSendData(CMD_GOODBYE); + RReleaseWithConnectorGracefully; + end; + + RSetOpponentClientVersion(lwOpponentClientVersion); + end + else if (sl = CMD_TRANSMITTING) then + begin + RSendData(CMD_GOODBYE); // TODO: some message or output to log + RReleaseWithConnectorGracefully; + end + else if (sl = CMD_GOODBYE) then + begin + Stop; + end + else if (sl = CMD_WELCOME) then + begin + RSendData(CMD_WELCOME); + m_bReady := TRUE; + m_GamingManager.FSetGameContextToTransmitter(self); + end; +end; + + +//////////////////////////////////////////////////////////////////////////////// +// TManagerMI + +constructor TManagerMI.Create(Connector: TConnector); +begin + self.Connector := Connector; + RCreate; + AddToPlugins(self); +end; + + +destructor TManagerMI.Destroy; +begin + RemoveFromPlugins(self); + inherited; +end; + + +procedure TManagerMI.Start; +begin + Assert(FALSE); +end; + + +procedure TManagerMI.Stop; +begin + Release; +end; + + +procedure TManagerMI.RSendData(const cmd: string); +begin + Connector.SendData(cmd); +end; + + +procedure TManagerMI.ROnDestroy; +begin + if (Assigned(Connector)) then + begin + Connector.Free; + Connector := nil; + end; + + inherited ROnDestroy; +end; + + +procedure TManagerMI.ConnectorHandler(e: TConnectorEvent; d1: pointer = nil; d2: pointer = nil); +var + iData: integer; + strCmd: string; + strLeft: string; +begin + case e of + ceData: + begin + Assert(High(TStringDynArray(d1)) >= 0); + iData := 0; + repeat + strLeft := TStringDynArray(d1)[iData]; + inc(iData); + strCmd := IfThen((iData <= High(TStringDynArray(d1))), '*'); + + RHandleConnectorDataCommand(strLeft); + until (strCmd = ''); + end; // ceData + + else + inherited ConnectorHandler(e, d1, d2); + end; // case +end; + + +procedure TManagerMI.RSetOpponentClientVersion(lwVersion: LongWord); +begin + inherited RSetOpponentClientVersion(lwVersion); + + if (lwVersion >= 200901) then + Connector.MultiSession := TRUE; +end; + + +initialization + +finalization + FreeAndNil(g_lstGamingManagers); + +end. diff --git a/plugins/Chess4Net/MI/MirandaINC/m_addcontact.inc b/plugins/Chess4Net/MI/MirandaINC/m_addcontact.inc new file mode 100644 index 0000000000..6bf08e8208 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_addcontact.inc @@ -0,0 +1,54 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_ADDCONTACT} +{$DEFINE M_ADDCONTACT} + +const + + HANDLE_SEARCHRESULT = 0; + HANDLE_EVENT = 1; + HANDLE_CONTACT = 2; + +type + + PADDCONTACTSTRUCT = ^TADDCONTACTSTRUCT; + TADDCONTACTSTRUCT = record + handleType: Integer; + handle: THandle; // HDBEVENT, HCONTACT, SearchResult + szProto: PChar; // used by search result only + psr: Pointer; // @PROTOSEARCHRESULT + end; + +const + + { + wParam : (HWND) Parent window of the dialog that will be presented + lParam : Pointer to an initialised TADDCONTACTSTRUCT + Affect : Open's the add contact dialog + Version: 0.1.2.2+ + } + MS_ADDCONTACT_SHOW = 'AddContact/Show'; + +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_api.pas b/plugins/Chess4Net/MI/MirandaINC/m_api.pas new file mode 100644 index 0000000000..412d33e517 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_api.pas @@ -0,0 +1,75 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFDEF FPC} + {$PACKRECORDS C} + {$MODE Delphi} +{$ENDIF} + +unit m_api; + +interface + +uses + + m_globaldefs, windows; + + {$include m_plugins.inc} + {$include m_system.inc} + {$include m_database.inc} + {$include m_findadd.inc} + {$include m_awaymsg.inc} + {$include m_email.inc} + {$include m_history.inc} + {$include m_message.inc} + {$include m_url.inc} + {$include newpluginapi.inc} + {$include m_clui.inc} + {$include m_ignore.inc} + {$include m_skin.inc} + {$include m_file.inc} + {$include m_netlib.inc} + {$include m_langpack.inc} + {$include m_clist.inc} + {$include m_clc.inc} + {$include m_userinfo.inc} + {$include m_protosvc.inc} + {$include m_options.inc} + {$include m_icq.inc} + {$include m_protocols.inc} + {$include m_protomod.inc} + {$include m_utils.inc} + {$include m_addcontact.inc} + {$include statusmodes.inc} + {$include m_contacts.inc} + {$define M_API_UNIT} + {$include m_helpers.inc} + +implementation + + {$undef M_API_UNIT} + {$include m_helpers.inc} + +end. + diff --git a/plugins/Chess4Net/MI/MirandaINC/m_awaymsg.inc b/plugins/Chess4Net/MI/MirandaINC/m_awaymsg.inc new file mode 100644 index 0000000000..44be914423 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_awaymsg.inc @@ -0,0 +1,40 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_AWAYMSG} +{$DEFINE M_AWAYMSG} + +const + + { + wParam : HCONTACT + lParam : 0 + Affect : Show the away/na/etc message for a contact + Returns: 0 on success, non zero on failure, see notes + notes : returns without waiting for the message to be shown. + version: v0.1.0.1+ + } + MS_AWAYMSG_SHOWAWAYMSG = 'SRAway/GetMessage'; + +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_clc.inc b/plugins/Chess4Net/MI/MirandaINC/m_clc.inc new file mode 100644 index 0000000000..743d8370aa --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_clc.inc @@ -0,0 +1,284 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_CLC} +{$DEFINE M_CLC} + +const + + CLISTCONTROL_CLASS = 'CListControl'; + + // styles + + CLS_MANUALUPDATE = $0001; // todo + CLS_SHOWHIDDEN = $0002; + CLS_HIDEOFFLINE = $0004; // hides all offline users + CLS_CHECKBOXES = $0008; + CLS_MULTICOLUMN = $0010; // not true multi-column, just for ignore/vis options + CLS_HIDEEMPTYGROUPS = $0020; // note: this flag will be spontaneously removed if the 'new subgroup' menu item is clicked, for obvious reasons + CLS_USEGROUPS = $0040; + CLS_NOHIDEOFFLINE = $0080; // overrides CLS_HIDEOFFLINE and the per-group hideoffline setting + CLS_GREYALTERNATE = $0100; // make every other line slightly grey + CLS_GROUPCHECKBOXES = $0200; // put checkboxes on groups too (managed by CLC) + + CLS_EX_DISABLEDRAGDROP = $00000001; + CLS_EX_EDITLABELS = $00000002; + CLS_EX_SHOWSELALWAYS = $00000004; + CLS_EX_TRACKSELECT = $00000008; + CLS_EX_SHOWGROUPCOUNTS = $00000010; + CLS_EX_DIVIDERONOFF = $00000020; + CLS_EX_HIDECOUNTSWHENEMPTY = $00000040; + CLS_EX_NOTRANSLUCENTSEL = $00000080; + CLS_EX_LINEWITHGROUPS = $00000100; + CLS_EX_QUICKSEARCHVISONLY = $00000200; + CLS_EX_SORTGROUPSALPHA = $00000400; + CLS_EX_NOSMOOTHSCROLLING = $00000800; + + CLM_FIRST = $1000; // this is the same as LVM_FIRST + CLM_LAST = $1100; + +// messages, compare with equivalent TVM_* in the WINAPI + + CLM_ADDCONTACT = (CLM_FIRST+0); // wParam=hContact + CLM_ADDGROUP = (CLM_FIRST+1); // wParam=hGroup + CLM_AUTOREBUILD = (CLM_FIRST+2); + CLM_DELETEITEM = (CLM_FIRST+3); // wParam=hItem + CLM_EDITLABEL = (CLM_FIRST+4); // wParam=hItem + CLM_ENDEDITLABELNOW = (CLM_FIRST+5); // wParam=cancel, 0 to save + CLM_ENSUREVISIBLE = (CLM_FIRST+6); // wParam=hItem, lParam=partialOk + + CLE_TOGGLE = -1; + CLE_COLLAPSE = 0; + CLE_EXPAND = 1; + CLE_INVALID = $FFFF; + + CLM_EXPAND = (CLM_FIRST+7); // wParam=hItem, lParam=CLE_ + CLM_FINDCONTACT = (CLM_FIRST+8); // wParam=hContact, returns an hItem + CLM_FINDGROUP = (CLM_FIRST+9); // wParam=hGroup, returns an hItem + CLM_GETBKCOLOR = (CLM_FIRST+10); // returns a COLORREF + CLM_GETCHECKMARK = (CLM_FIRST+11); // wParam=hItem, returns 1 or 0 + CLM_GETCOUNT = (CLM_FIRST+12); // returns the total number of items + + CLM_GETEDITCONTROL = (CLM_FIRST+13); // returns the HWND, or NULL + CLM_GETEXPAND = (CLM_FIRST+14); // wParam=hItem, returns a CLE_, CLE_INVALID if not a group + CLM_GETEXTRACOLUMNS = (CLM_FIRST+15); // returns number of extra columns + CLM_GETEXTRAIMAGE = (CLM_FIRST+16); // wParam=hItem, lParam=MAKELPARAM(iColumn (0 based),0), returns iImage or $FF + CLM_GETEXTRAIMAGELIST = (CLM_FIRST+17); // returns HIMAGELIST + CLM_GETFONT = (CLM_FIRST+18); // wParam=fontId, see clm_setfont. returns hFont. + CLM_GETINDENT = (CLM_FIRST+19); // wParam=new group indent + CLM_GETISEARCHSTRING = (CLM_FIRST+20); // lParam=(char*)pszStr, max 120 bytes, returns number of chars in string + CLM_GETITEMTEXT = (CLM_FIRST+21); // wParam=hItem, lParam=(char*)pszStr, max 120 bytes + CLM_GETSCROLLTIME = (CLM_FIRST+22); // returns time in ms + CLM_GETSELECTION = (CLM_FIRST+23); // returns hItem + + CLCHT_ABOVE = $0001; // above client area + CLCHT_BELOW = $0002; // below client area + CLCHT_TOLEFT = $0004; // left of client area + CLCHT_TORIGHT = $0008; // right of client area + CLCHT_NOWHERE = $0010; // in client area, not on an item + CLCHT_ONITEMICON = $0020; + CLCHT_ONITEMCHECK = $0040; + CLCHT_ONITEMLABEL = $0080; + CLCHT_ONITEMINDENT = $0100; // to the left of an item icon + CLCHT_ONITEMEXTRA = $0200; // on an extra icon, HIBYTE(HIWORD()) says which + CLCHT_ONITEM = $03E0; + CLCHT_INLEFTMARGIN = $0400; + CLCHT_BELOWITEMS = $0800; // in client area but below last item + + CLM_HITTEST = (CLM_FIRST+25); // lParam=MAKELPARAM(x,y) (relative to control), wParam=(PDWORD)&hitTest (see encoding of HitTest() in clc.h, can be NULL) returns hItem or NULL + CLM_SELECTITEM = (CLM_FIRST+26); // wParam=hItem + + CLB_TOPLEFT = 0; + CLB_STRETCHV = 1; + CLB_STRETCHH = 2; // and tile vertically + CLB_STRETCH = 3; + + CLBM_TYPE = $00FF; + CLBF_TILEH = $1000; + CLBF_TILEV = $2000; + CLBF_PROPORTIONAL = $4000; + CLBF_SCROLL = $8000; + + CLM_SETBKBITMAP = (CLM_FIRST+27); // wParam=mode, lParam=hBitmap (don't delete it), NULL for none + CLM_SETBKCOLOR = (CLM_FIRST+28); // wParam=a COLORREF, default is GetSysColor(COLOR_3DFACE) + CLM_SETCHECKMARK = (CLM_FIRST+29); // wParam=hItem, lParam=1 or 0 + CLM_SETEXTRACOLUMNS = (CLM_FIRST+30); // wParam=number of extra columns (zero to MAXEXTRACOLUMNS from clc.h, currently 16) + CLM_SETEXTRAIMAGE = (CLM_FIRST+31); // wParam=hItem, lParam=MAKELPARAM(iColumn (0 based),iImage). iImage=$FF is a blank + CLM_SETEXTRAIMAGELIST = (CLM_FIRST+32); // lParam=HIMAGELIST + + FONTID_CONTACTS = 0; + FONTID_INVIS = 1; + FONTID_OFFLINE = 2; + FONTID_NOTONLIST = 3; + FONTID_GROUPS = 4; + FONTID_GROUPCOUNTS = 5; + FONTID_DIVIDERS = 6; + FONTID_OFFINVIS = 7; + FONTID_MAX = 7; + + CLM_SETFONT = (CLM_FIRST+33); // wParam=hFont, lParam=MAKELPARAM(fRedraw,fontId) + CLM_SETINDENT = (CLM_FIRST+34); // wParam=new indent, default is 3 pixels + CLM_SETITEMTEXT = (CLM_FIRST+35); // wParam=hItem, lParam=(char*)pszNewText + CLM_SETSCROLLTIME = (CLM_FIRST+36); // wParam=time in ms, default 200 + CLM_SETHIDEEMPTYGROUPS = (CLM_FIRST+38); // wParam=TRUE/FALSE + + GREYF_UNFOCUS = $80000000; + MODEF_OFFLINE = $40000000; + + // and use the PF2_ #defines from m_protosvc.inc + CLM_SETGREYOUTFLAGS = (CLM_FIRST+39); // wParam=new flags + CLM_GETHIDEOFFLINEROOT = (CLM_FIRST+40); // returns TRUE/FALSE + CLM_SETHIDEOFFLINEROOT = (CLM_FIRST+41); // wParam=TRUE/FALSE + CLM_SETUSEGROUPS = (CLM_FIRST+42); // wParam=TRUE/FALSE + CLM_SETOFFLINEMODES = (CLM_FIRST+43); // for 'hide offline', wParam=PF2_ flags and MODEF_OFFLINE + CLM_GETEXSTYLE = (CLM_FIRST+44); // returns CLS_EX_ flags + CLM_SETEXSTYLE = (CLM_FIRST+45); // wParam=CLS_EX_ flags + CLM_GETLEFTMARGIN = (CLM_FIRST+46); // returns count of pixels + CLM_SETLEFTMARGIN = (CLM_FIRST+47); // wParam=pixels + // the order of info items is never changed, so make sure you add them in the + // order you want them to remain + CLM_ADDINFOITEM = (CLM_FIRST+48); // lParam=&TCLCINFOITEM, returns hItem + CLM_GETITEMTYPE = (CLM_FIRST+49); // wParam=hItem, returns a CLCIT_ + CLM_GETNEXTITEM = (CLM_FIRST+50); // wParam=flag, lParam=hItem, returns an hItem + CLM_GETTEXTCOLOR = (CLM_FIRST+51); // wParam=FONTID_, returns COLORREF + CLM_SETTEXTCOLOR = (CLM_FIRST+52); // wParam=FONTID_, lParam=COLORREF + + CLCIIF_BELOWGROUPS = 1; // put it between groups and contacts, default is at top + CLCIIF_BELOWCONTACTS = 2; // put it at the bottom + CLCIIF_CHECKBOX = $40; // give this item a check box + CLCIIF_GROUPFONT = $80; // draw the item using FONTID_GROUPS + + CLCIT_INVALID = -1; + CLCIT_GROUP = 0; + CLCIT_CONTACT = 1; + CLCIT_DIVIDER = 2; + CLCIT_INFO = 3; + + CLGN_ROOT = 0; + CLGN_CHILD = 1; + CLGN_PARENT = 2; + CLGN_NEXT = 3; + CLGN_PREVIOUS = 4; + CLGN_NEXTCONTACT = 5; + CLGN_PREVIOUSCONTACT = 6; + CLGN_NEXTGROUP = 7; + CLGN_PREVIOUSGROUP = 8; + + CLNF_ISGROUP = 1; + CLNF_ISINFO = 2; + + CLN_FIRST = (0-100); + CLN_EXPANDED = (CLN_FIRST-0); // hItem=hGroup, action=CLE_* + CLN_LISTREBUILT = (CLN_FIRST-1); + CLN_ITEMCHECKED = (CLN_FIRST-2); // todo // hItem,action,flags valid + CLN_DRAGGING = (CLN_FIRST-3); // hItem,pt,flags valid. only sent when cursor outside window, return nonzero if processed + CLN_DROPPED = (CLN_FIRST-4); // hItem,pt,flags valid. only sent when cursor outside window, return nonzero if processed + CLN_LISTSIZECHANGE = (CLN_FIRST-5); // pt.y valid. the vertical height of the visible items in the list has changed. + CLN_OPTIONSCHANGED = (CLN_FIRST-6); // nothing valid. If you set some extended options they have been overwritten and should be re-set + CLN_DRAGSTOP = (CLN_FIRST-7); // hItem,flags valid. sent when cursor goes back in to the window having been outside, return nonzero if processed + CLN_NEWCONTACT = (CLN_FIRST-8); // hItem,flags valid. sent when a new contact is added without a full list rebuild + CLN_CONTACTMOVED = (CLN_FIRST-9); // hItem,flags valid. sent when contact is moved without a full list rebuild + CLN_CHECKCHANGED = (CLN_FIRST-10); // hItem,flags valid. sent when any check mark is changed, but only for one change if there are many + +type + + PCLCINFOITEM = ^TCLCINFOITEM; + TCLCINFOITEM = record + cbSize: int; + pszText: PChar; + hParentGroup: THandle; + flags: DWORD; + hIcon: THandle; // todo + end; + + PNMCLISTCONTROL = ^TNMCLISTCONTROL; + TNMCLISTCONTROL = record + hdr: TNMHDR; // depends on Windows.pas + hItem: THandle; + action: int; + iColumn: int; // -1 if not on an extra column + flags: DWORD; + pt: TPoint; // depends on Windows.pas + end; + + PCLCINFOTIP = ^TCLCINFOTIP; + TCLCINFOTIP = record + cbSize: int; + isTreeFocused: int; // so the plugin can provide an option + isGroup: int; // 0 if it's contact, 1 if it's a group + hItem: THandle; // handle to group or contact + ptCursor: TPoint; + rcItem: TRect; + end; + +const + + { + wParam : 0 + lParam : Pointer to a TCLCINFOTIP structure + Affect : An InfoTip for an item should be shown now, see notes + Returns: [non zero] if you process this, because it makes no sense + for more than one module to process this. + Notes : It's upto the module where to put the InfoTip, Normally + it's a few pixels below and to the right of the cursor. + - + This event is called after the mouse ehas been stationary over + a contact for (by default) 200ms + } + ME_CLC_SHOWINFOTIP = 'CLC/ShowInfoTip'; + + { + wParam : 0 + lParam : Pointer to an initialised TCLCINFOTIP + Affect : It's time to destroy an infotip, see notes + Notes : Only cbSize, isGroup, hItem are set + notes : This is sent when the mouse moves off a contact when ME_CLC_SHOWINFOTIP + has previously been called. + - + If you don't want this behaviour, you should have grabbed the mouse + capture yourself -- + } + ME_CLC_HIDEINFOTIP = 'CLC/HideInfoTip'; + + { + wParam : new_time + lParam : 0 + Affect : Set a new hover time before the info tip hooks are called, see notes + Returns: 0 on success, [non zero] on failure + Notes : The value of this setting is applid to all current CLC windows + and saved to b applied to all future windows, it is persistent. + - + Time is in milliseconds, default is 750ms + } + MS_CLC_SETINFOTIPHOVERTIME = 'CLC/SetInfoTipHoverTime'; + + { + wParam : 0 + lParam : 0 + Affect : get the hover time before the infotip hooks are called + returns: the hover time in MS + } + MS_CLC_GETINFOTIPHOVERTIME = 'CLC/GetInfoTipHoverTime'; + +{$ENDIF} \ No newline at end of file diff --git a/plugins/Chess4Net/MI/MirandaINC/m_clist.inc b/plugins/Chess4Net/MI/MirandaINC/m_clist.inc new file mode 100644 index 0000000000..20a3fb0e29 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_clist.inc @@ -0,0 +1,641 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_CLIST} +{$DEFINE M_CLIST} + +{$ifndef STATUSMODES} + {$include statusmodes.inc} +{$endif} + +const + + // for MS_CLIST_GETSTATUSMODEDESCRIPTION + + GSMDF_PREFIXONLINE = 1; // prefix "Online :" for online submodes, e.g. 'away' + + // for MS_CLIST_ADDMAINMENUITEM + + CMIF_GRAYED = 1; + CMIF_CHECKED = 2; + CMIF_HIDDEN = 4; // only works on contact menus + CMIF_NOTOFFLINE = 8; // item won't appear for contacts that are offline + CMIF_NOTONLINE = 16; // " online + CMIF_NOTONLIST = 32; // item won't appear on standard contacts + CMIF_NOTOFFLIST = 64; // item won't appear on contacts that have the 'NotOnList' setting + + // for MS_CLIST_MODIFYMENUITEM + + CMIM_NAME = $80000000; + CMIM_FLAGS = $40000000; + CMIM_ICON = $20000000; + CMIM_HOTKEY = $10000000; + CMIM_ALL = $F0000000; + + // for MS_CLIST_GETCONTACTDISPLAYNAME + + // will never return the user's custom name, even if that's the one to be displayed + GCDNF_NOMYHANDLE = 1; + + // for MS_CLIST_ADDEVENT + + //flashes the icon even if the user is occupied, and puts the event + // at the top of the queue + CLEF_URGENT = 1; + { icon will not flash forever, only a few times, e.g. online alert } + CLEF_ONLYAFEW = 2; + + // for MS_CLIST_GETICONSIMAGELIST + + IMAGE_GROUPOPEN = 11; + IMAGE_GROUPSHUT = 12; + + // for MS_CLIST_MENUPROCESSCOMMAND + + MPCF_CONTACTMENU = 1; // test commands from a contact menu + MPCF_MAINMENU = 2; // test commands from the main menu + + // for MS_CLIST_GROUPGETNAME/2 + + GROUPF_EXPANDED = $04; + GROUPF_HIDEOFFLINE = $08; + + // + + SETTING_TOOLWINDOW_DEFAULT = 1; + SETTING_SHOWMAINMENU_DEFAULT = 1; + SETTING_SHOWCAPTION_DEFAULT = 1; + SETTING_CLIENTDRAG_DEFAULT = 0; + SETTING_ONTOP_DEFAULT = 1; + SETTING_MIN2TRAY_DEFAULT = 1; + SETTING_TRAY1CLICK_DEFAULT = 0; + SETTING_HIDEOFFLINE_DEFAULT = 0; + SETTING_HIDEEMPTYGROUPS_DEFAULT = 0; + SETTING_USEGROUPS_DEFAULT = 1; + SETTING_SORTBYSTATUS_DEFAULT = 0; + SETTING_TRANSPARENT_DEFAULT = 0; + SETTING_ALPHA_DEFAULT = 200; + SETTING_AUTOALPHA_DEFAULT = 150; + SETTING_CONFIRMDELETE_DEFAULT = 1; + SETTING_AUTOHIDE_DEFAULT = 0; + SETTING_HIDETIME_DEFAULT = 30; + SETTING_CYCLETIME_DEFAULT = 4; + SETTING_ALWAYSSTATUS_DEFAULT = 0; + SETTING_ALWAYSMULTI_DEFAULT = 0; + SETTING_TRAYICON_SINGLE = 0; + SETTING_TRAYICON_CYCLE = 1; + SETTING_TRAYICON_MULTI = 2; + SETTING_TRAYICON_DEFAULT = SETTING_TRAYICON_SINGLE; + SETTING_STATE_HIDDEN = 0; + SETTING_STATE_MINIMIZED = 1; + SETTING_STATE_NORMAL = 2; + +type + + PCLISTMENUITEM = ^TCLISTMENUITEM; + TCLISTMENUITEM = record + cbSize: int; // size in bytes of this structure + pszName: PChar; // text of the menu item + flags: DWORD; + position: int; // approx position on the menu, lower numbers go nearer the top + hIcon: THandle; // icon to put by the item, if this was *not* loaded from + // a resource, you can delete it straight after the call + pszService: PChar; // name of the service to call when the service is clicked + pszPopupName: PChar;// name of the popup menu that this item is on, if this + // is NULL the iteem is on the root of the menu + popupPosition: int; // position of the popup menu on the root menu, ignored + // if pszPopupName is NULL(0) or if the popup menu already exists + hotKey: DWORD; // keyboard accelerator, same as lParam of WM_HOTKEY, 0 for none + pszContactOwner: PChar; // contact menus only, the protocol module that owns + // the contacts to which this to which this menu item + // applies, NULL(0) if it applies to all contacts. + // if it applies to multiple but not all protocols + // add multiple menu items or use ME_CLIST_PREBUILDCONTACTMENU + end; + + PCLISTDOUBLECLICKACTION = ^TCLISTDOUBLECLICKACTION; + TCLISTDOUBLECLICKACTION = record + cbSize: int; + pszContactOwner: PChar; // name of the protocol owning the contact or NULL(0) for all + flags: DWORD; // CMIF_NOT flags above + pszService: PChar; // service to call on double click, is called with wParam=hContact, lParam=0 + end; + + PCLISTEVENT = ^TCLISTEVENT; + TCLISTEVENT = record + cbSize: int; // size in bytes + hContact: THandle; // handle to the contact to put the icon by + hIcon: THandle; // icon to flash! + flags: DWORD; + hDBEvent: THandle; // caller defined, but should be unique for hContact + lParam: LPARAM; + pszService: PChar; // name of service to call on activation + pszTooltip: PChar; // short description of the event to display as a tooltip on the systray + end; + +const + + { + wParam : new_status + lParam : 0 + Affect : Sent when the user acks to change their status, see notes + Notes : Also sent due to a MS_CLIST_SETSTATUSMODE + } + ME_CLIST_STATUSMODECHANGE = 'CList/StatusModeChange'; + + { + wParam : new_status + lParam : 0 + Affect : Force a change of status mode, see statusmodes.inc + } + MS_CLIST_SETSTATUSMODE = 'CList/SetStatusMode'; + + { + wParam : 0 + lParam : 0 + Affect : Get the current status mode, see notes + Notes : This is the status, as set by the user, not any protocol specific status + all protocol modules will attempt to conform to this setting at ALL times. + } + MS_CLIST_GETSTATUSMODE = 'CList/GetStatusMode'; + + { + wParam : status_mode + lParam : flags + Affect : Get a textual description of the given status mode + Returns: pointer to a static buffer of the description of the given status mode + or NULL(0) if the mode was unknown. + Version: v0.1.0.1+ + } + MS_CLIST_GETSTATUSMODEDESCRIPTION = 'CList/GetStatusModeDescription'; + + { + wParam : 0 + lParam : Pointer to a initalised TCLISTMENUITEM structure + Affect : Add a new menu item to the main menu, see notes + Returns: A handle to the new MENU item or NULL(0) on failure + Notes : The given TCLISTMENUITEM.pszService in is called when the item + get clicked with : + - + wParam = 0, lParam = hwndContactList + } + MS_CLIST_ADDMAINMENUITEM = 'CList/AddMainMenuItem'; + + { + wParam : 0 + lParam : Pointer to a initalised TCLISTMENUITEM structure + Affect : Add a new item to the user contact menus, see notes + Notes : exactly the same as MS_CLIST_ADDMAINMENUITEM except when an item + is selected, the service gets called with wParam=hContact, + pszContactOwner is obeyed. + - + Popup menus are not supported, pszPopupName and popupPosition + are ignored. If CTRL is held down when right clicking the menu + position numbers will be displayed in brackets afterr the menu item + text, this only works in debug builds! + } + MS_CLIST_ADDCONTACTMENUITEM = 'CList/AddContactMenuItem'; + + { + wParam : HMENUITEM + lParam : Pointer to a initalised TCLISTMENUITEM + Affect : Modify an existing menu item, see notes + Returns: 0 on success, [non zero] on failure + Notes : hMenuItem will have been returned by MS_CLIST_ADD[MAIN]MENUITEM + TCLISTMENUITEM.flags should contain CMIM_* constants (see above) + to mark which fields should be updated, if it's not present, they + can't be updated -- if flags do not exist for a field it can not + be updated. + Version: v0.1.0.1+ + } + MS_CLIST_MODIFYMENUITEM = 'CList/ModifyMenuItem'; + + { + wParam : HCONTACT + lParam : 0 + Affect : the context menu for a contact is about to be built, see notes + Notes : modules should use this to change menu items that are specific + to the contact that has them + Version: v0.1.0.1+ + } + ME_CLIST_PREBUILDCONTACTMENU = 'CList/PreBuildContactMenu'; + + { + wParam : 0 + lParam : Pointer to a initalised TCLISTDOUBLECLICKACTION structure + Affect : Sets the service to call when a contact is double-clicked, see notes + Returns: 0 on success, [non zero] on failure + Notes : in case of conflicts, the first module to have registered + will get the double click, no others will, this service + will return success even for duplicates + - + This service was dropped from development during 0.3.0.0, it is no + longer supported, see ME_CLIST_DOUBLECLICKED + Version: 0.1.2.2+, 0.2.0+ ONLY (not 3.0a) + } + MS_CLIST_SETDOUBLECLICKACTION = 'CList/SetDoubleClickAction'; + + { + wParam : HCONTACT + lParam : + Affect : Register with this event to be notified of a double click on the CList + against a HCONTACT, you will not be notified if there is a pending CList event + that the double click clears, (i.e. flashing icon is presented to be clicked) + Version: 0.3.0.0 + } + ME_CLIST_DOUBLECLICKED = 'CList/DoubleClicked'; + + { + wParam : HCONTACT + lParam : flags + Affect : Gets the string that the contact list will use to represent a contact + Returns: Always a pointer + Notes : Returns a pointer to the name, will always succeed, even if it needs + to return "(Unknown Contact)" + - + this pointer is a statically allocated buffer which will + be overwritten on every call to this service, callers should make + sure that they copy the information before they call it again + Version: v0.1.2.0+, 0.2.0+ ONLY (0.3a supports the contacts module) + } + MS_CLIST_GETCONTACTDISPLAYNAME = 'CList/GetContactDisplayName'; + + { + wParam : 0 + lParam : Pointer to a TCLISTEVENT + Affect : Add's an event to the list + Notes : The service will flash TCLISTEVENT.hIcon, next to the + contact, TCLISTEVENT.hContact + - + pszService is called is called wParam=hwndContactList, + lParam=pointer to a TCLISTEVENT. + - + the TCLISTEVENT data is invalidated after this service returns + so copy anything from it if required. + - + TCLISTEVENT.pszService will also be called if the user + double clicks on the icon, at which point it will be removed + from the contact lists queue automatically. + - + TCLISTEVENT.hContact and TCLISTEVENT.hDBEvent should be unique. + } + MS_CLIST_ADDEVENT = 'CList/AddEvent'; + + { + wParam : HCONTACT + lParam : HDBEVENT + Affect : Remove an event from the contact list queue + Returns: 0 on success, [non zero] on failure + } + MS_CLIST_REMOVEEVENT = 'Clist/RemoveEvent'; + + { + wParam : HCONTACT + lParam : iEvent + Affect : Get the details of an event in the queue, see notes + Returns: A CLISTEVENT* or NULL(0) on failure + Notes : Returns the iEvent'1st/2nd/3rd/nth elemented queried, + e.g. iEvent=0 will get the event that will be returned if the + user double clicks on that HCONTACT + - + Use HCONTACT=NULL, iEvent=0 for example to get the event + the user will get if they double click on the tray. + Version: v0.1.2.1+ + } + MS_CLIST_GETEVENT = 'CList/GetEvent'; + + { + wParam : ControlID + lParam : Pointer to MEASUREITEMSTRUCT struct + Affect : Process a WM_MEASUREITEM message for user context menus, see notes + Notes : just because wParam, lParam is defined here, only pass them + opaquely to this service, as is. + - + This is just to draw icons, if it is not called, the icons + will not be drawn + Version: v0.1.1.0+ + } + MS_CLIST_MENUMEASUREITEM = 'CList/MenuMeasureItem'; + + { + wParam : + lParam : + Affect : Process a WM_DRAWITEM message for user context menus, + wParam, lParam should be passed from such message handler. + Version: v0.1.1.0+ + } + MS_CLIST_MENUDRAWITEM = 'CList/MenuDrawItem'; + + { + wParam : HCONTACT + lParam : 0 + Affect : Built the context menu for a specific contact + Returns: A HMENU handle identifying the menu, thhis should be DestroyMenu()ed + when done. + Version: v0.1.1.0+ + } + MS_CLIST_MENUBUILDCONTACT = 'CList/MenuBuildContact'; + + { + wParam : 0 + lParam : 0 + Affect : Get the image list handle with all the useful icons in it + Version: v0.1.1.0+ + } + MS_CLIST_GETICONSIMAGELIST = 'CList/GetIconsImageList'; + + { + wParam : HCONTACT + lParam : 0 + Affect : Get the icon that should be associated with a contact + Returns: an index into the contact list imagelist, if the icon + is a flashing icon, this service won't return information about it + see below + Version: v0.1.2.0+ + } + MS_CLIST_GETCONTACTICON = 'CList/GetContactIcon'; + + { + wParam : HCONTACT + lParam : ICON_ID + Affect : The icon of a contact in the contact list has changed, + ICON_ID is an index to what image has changed + Version: v0.1.2.1+ + } + ME_CLIST_CONTACTICONCHANGED = 'CList/ContactIconChanged'; + + // ideally only used by a CLIST UI module + + { + wParam : 0 + lParam : 0 + Affect : Get the handle to Miranda's main menu + Version: v0.1.1.0+ + } + MS_CLIST_MENUGETMAIN = 'CList/MenuGetMain'; + + { + wParam : 0 + lParam : 0 + Affect : Get a handle to Miranda's status menu + Version: v0.1.1.0+ + } + MS_CLIST_MENUGETSTATUS = 'CList/MenuGetStatus'; + + { + wParam : MAKEWPARAM(LOWORD(wParam of WM_COMMAND),flags) + lParam : HCONTACT + Affect : Process a mennu selection from a menu, see notes + Returns: True if it processed the command, False otherwise + notes : hContact is the currently selected contact, it is not used + if this is a main menu command, if this is NULL then the command + is a contact menu one, the command is ignored + Version: v0.1.1.0+ + } + MS_CLIST_MENUPROCESSCOMMAND = 'CList/MenuProcessCommand'; + + { + wParam : virtual key code + lParam : MPCF_* flags + Affect : Process a menu hotkey, see notes + Returns: True if it processed the command, False otherwise + Notes : this should be called in WM_KEYDOWN + Version: v0.1.1.0+ + } + MS_CLIST_MENUPROCESSHOTKEY = 'CList/MenuProcessHotkey'; + + { + wParam : Pointer to a MSG structurer + lParam : Pointer to an LRESULT + Affect : Process all the messages required for docking, see notes + Returns: True if the message should NOT be processed anymore, False otherwise + Notes : only msg.hwnd, msg.message, msg.wParam and msg.lParam are used + your WndProc should return the lResult if AND only IF, TRUE is returned + Version: v0.1.1.0+ + } + MS_CLIST_DOCKINGPROCESSMESSAGE = 'CList/DockingProcessMessage'; + + { + wParam : 0 + lParam : 0 + Affect : Determines wheter the contact list docked + Returns: pnon zero] if the contact list is docked, or 0 if it's not + Version: v0.1.1.0+ + } + MS_CLIST_DOCKINGISDOCKED = 'CList/DockingIsDocked'; + + { + wParam : Pointer to a TMSG + lParam : Pointer to an LRESULT + Affect : Process all the messages required for the tray icon, see notes + Returns: TRUE if the message should not be processed anymore, False otherwise + Notes : Only msg.hwnd, msg.message, msg.wparam and msg.lParam are used + your WndProc should return LRESULT if and ONLY if TRUE is returned + Version: v0.1.1.0+ + } + MS_CLIST_TRAYICONPROCESSMESSAGE = 'CList/TrayIconProcessMessage'; + + { + wParam : Pointer to TMSG + lParam : Pointer to an LRESULT + Affect : Process all the messages required for hotkeys, see notes + Returns: True if the message should not be processed anymore or False otherwise + Notes : only msg.hwnd, msg.message, msg.wParam, msg.lParam are used + Version: v0.1.1.0+ + } + MS_CLIST_HOTKEYSPROCESSMESSAGE = 'CList/HotkeysProcessMessage'; + + { + wParam : 0 + lParam : 0 + Affect : Toggles the show/hide status of the contact list + Returns: 0 on success, [non zero] on failure + Version: v0.1.1.0+ + } + MS_CLIST_SHOWHIDE = 'CList/ShowHide'; + + { + wParam : 0 + lParam : 0 + Affect : temporarily disable the autohide feature, see notes + Notes : this service will restart the auto hide timer, so if you need + to keep the window visible you'll have to bee getting user input + or calling this service each time + Version: v0.1.2.1+ + } + MS_CLIST_PAUSEAUTOHIDE = 'CList/PauseAutoHide'; + + { + wParam : HPARENTGROUP + lParam : 0 + Affect : Create a new group and calls CLUI to display it, see notes + Returns: A handle to the new group. + Notes : If HPARENTGROUP is NULL(0) it will create a group at the root. + Version: v0.1.1.0+ + } + MS_CLIST_GROUPCREATE = 'CList/GroupCreate'; + + { + wParam : HGROUP + lParam : 0 + Affect : Delete a group and call CLUI to display the change + Returns: 0 on success, [non zero] on failure + Version: v0.1.1.0+ + } + MS_CLIST_GROUPDELETE = 'CList/GroupDelete'; + + { + wParam : HGROUP + lParam : newState + Affect : Change the expanded state flag for a group internally, see notes + Returns: 0 on success, [non zero] on failure + Notes : if newState is non zero then the group is expanded, 0 it's collapsed + CLUI IS *NOT* called when the change is made. + Version: v0.1.1.0+ + } + MS_CLIST_GROUPSETEXPANDED = 'CList/GroupSetExpanded'; + + { + wParam : HGROUP + lParam : MAKELPARAM(flags, flagsMask) + Affect : Change the flag for a group, see notes + Returns: 0 on success, [non zero] on failure + Notes : only if flags given in flagsmask are altered, + CLUI is called on change to GROUPF_HIDEOFFLINE + Version: v0.1.2.1+ + } + MS_CLIST_GROUPSETFLAGS = 'CList/GroupSetFlags'; + + { + wParam : HGROUP + lParam : Pointer to a integer to be filled with expanded state + Affect : get the name of a group, see notes + Returns: a static buffer pointing to the name of the group + returns NULL(0) if HGROUP is invalid. + Notes : the returned buffer is only valid til the next call + to this service, lParam can be NULL(0) if you don't + want to know if the group is expanded + Version: v0.1.1.0+ + } + MS_CLIST_GROUPGETNAME = 'CList/GroupGetName'; + + { + wParam : HGROUP + lParam : Pointer to flags + Affect : Get the name of the group, see notes + Returns: A static buffer pointing to the name of the group + returns NULL(0) if HGROUP is invalid + Note : this buffer is only valid til the next call to this service + flags can be NULL(0), otherwise it'll return GROUPF_* constants + Version: v0.1.2.1+ + } + MS_CLIST_GROUPGETNAME2 = 'CList/GroupGetName2'; + + { + wParam : HGROUP + lParam : HBEFOREGROUP + Affect : Move a group directly before another group + Returns: the new handle of the group on success, NULL(0) on failure + Notes : the order is represented by the order in which MS_CLUI_GROUPADDED + is called, however UI's are free to ignore this order and sort + if they wish. + Version: v0.1.2.1+ + } + MS_CLIST_GROUPMOVEBEFORE = 'CList/GroupMoveBefore'; + + { + wParam : HGROUP + lParam : Pointer to a null terminated string containing the new name + Affect : Rename a group internally, see notes + Returns: 0 on success, [non zero] on failure + Notes : this will fail if the group name is a duplicate of an existing + a name, CLUI is not called when this change is made. + Version: v0.1.1.0+ + } + MS_CLIST_GROUPRENAME = 'CList/GroupRename'; + + { + wParam : 0 + lParam : 0 + Affect : Build a menu of the group tree, see notes + Returns: Handle to the menu, NULL(0) on failure + Notes : NULL be returned if the user doesn't have any groups + the dwItemData of every menu item is the handle to that group. + Menu item ID's are assigned starting at 100 in no particular order + Version: v0.1.2.1+ + } + MS_CLIST_GROUPBUILDMENU = 'CList/GroupBuildMenu'; + + { + wParam : newValue + lParam : 0 + Affect : Changes the 'hide offline contacts' flag and calls CLUI, see notes + Returns: 0 success, [non zero] on failure + Notes : newValue is 0 to show all contacts, 1 to show only online contacts + -1 to toggle the value + Version: v0.1.1.0+ + } + MS_CLIST_SETHIDEOFFLINE = 'CList/SetHideOffline'; + + { + wParam : HCONTACT + lParam : 0 + Affect : Do the message processing associated with the double clicking a contact + Returns: 0 on success, [non zero] on failure + Version: v0.1.1.0+ + } + MS_CLIST_CONTACTDOUBLECLICKED = 'CList/ContactDoubleClicked'; + + { + wParam : HCONTACT + lParam : Pointer to an array of pchar's containing files/dirs + Affect : Do the processing when some files are droppeed on a contact, see notes + Returns: 0 on success, [non zero] on failure + Notes : the array is terminated when a NULL(0) entry is found + Version: v0.1.2.1+ + } + MS_CLIST_CONTACTFILESDROPPED = 'CList/ContactFilesDropped'; + + { + wParam : HCONTACT + lParam : HGROUP + Affect : Change the group a contact belongs to, see notes + Returns: 0 on success, [non zero] on failure + Notes : use hGroup=NULL(0) to remove any group association with the contact + Version: v0.1.1.0+ + } + MS_CLIST_CONTACTCHANGEGROUP = 'CList/ContactChangeGroup'; + + { + wParam : HCONTACT_1 + lParam : HCONTACT_2 + Affect : Determine the ordering of two given contacts + Returns: 0 if hContact1 is the same as hContact2 + 1 if hContact1 should be displayed before hContact2 + -1 if hContact1 should be displayed after hCotnact2 + Version: v0.1.1.0+ + } + MS_CLIST_CONTACTSCOMPARE = 'CList/ContactsCompare'; + +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_clui.inc b/plugins/Chess4Net/MI/MirandaINC/m_clui.inc new file mode 100644 index 0000000000..c62b40e458 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_clui.inc @@ -0,0 +1,215 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_CLUI} +{$DEFINE M_CLUI} + + {<>} + +const + + { + wParam : 0 + lParam : 0 + Affects: Returns a window handle for the contact list window, see notes + Returns: "" + Notes : This call has a very specific purpose internally Miranda + and shouldn't be used gratuitously, in almost all cases + there's another call to do whatever it is that you're + trying to do. + } + MS_CLUI_GETHWND = 'CLUI/GetHwnd'; + + { + wParam : new status + lParam : null terminated string to a protocol ID + Affects: Change the protocol specific status indicators, see notes! + Returns: 0 on success, [non zero] on failure + Notes : protocol modules don't want to call this, they want + clist/protocolstatuschanged instead + } + MS_CLUI_PROTOCOLSTATUSCHANGED = 'CLUI/ProtocolStatusChanged'; + + { + wParam : Handle to a group + lParam : 1 or 0 + Affect : A new group was created, add it to the list, see notes + Notes : lParam is set to 1 or 0 if the user just created + the group or not. + - + this is also called when the contact list is being rebuilt, + new groups are always created with the name 'New group' + } + MS_CLUI_GROUPADDED = 'CLUI/GroupCreated'; + + { + wParam : HCONTACT + lParam : ICON_ID + Affect : Change the icon for a contact, see notes + Returns: 0 on success, [non zero] on failure + Notes : ICON_ID is an offset in the imagelist, see clist/geticonsimagelist + } + MS_CLUI_CONTACTSETICON = 'CLUI/ContactSetIcon'; + + { + wParam : HCONTACT + lParam : 0 + Affect : Remove a contact from the list, see notes + Returns: 0 on success, [non zereo] on failure + Notes : this contact is NOT actually being deleted, since if + a contact goes offline while 'hide offline' option is sset, + this service will be called then ALSO + } + MS_CLUI_CONTACTDELETED = 'CLUI/ContactDeleted'; + + { + wParam : HCONTACT + lParam : ICON_ID + Affect : Add a contact to the list, see note + returns: 0 on success, [non zero] on failure + Notes : the caller processes the 'hide offline' setting, so the callee + should not do further processing based on the value of this setting + - + WARNING: this will be called to re-add a contact when they come + online if 'hide offline' is on, but it cannot determine if + the contact is already on the list, so you may get requests to + add a contact when it is already on the list, which you should ignore. + - + You'll also get this whenever an event is added for a contact, + since if the contact was offline, it needs to be shown to + display the mesage, even if 'hide offlines' is on. + - + you should not resort the list on this call, a seperate resort + request will be sent. + - + ICON_ID is an offset in the image list, see clist/geticonsimagelist + + } + MS_CLUI_CONTACTADDED = 'CLUI/ContactAdded'; + + { + wParam : HCONTACT + lParam : 0 + Affect : Reename a contact in the lists, see notes + Returns: 0 on success, [non zero] on failure + Notes : You should not re-sort the list on this call, a separate resort + request will be sent, you can get the new name from clist/getcontactdisplayname + } + MS_CLUI_CONTACTRENAMED = 'CLUI/ContactRenamed'; + + { + wParam : 0 + lParam : 0 + Affect : Start a rebuild of the contact list, see notes + Returns: 0 on success, [non zero] on failure + Notes : this is the cue to clear the existing content of the list + expect to get a series of : + + clui/groupadded + clui/contactadded + clui/resortlist + } + MS_CLUI_LISTBEGINREBUILD = 'CLUI/ListBeginRebuild'; + + { + wParam : 0 + lParam : 0 + Affect : End a rebuild of the contact list, see notes + Returns: 0 on success, [non zero] on error + Notes : if you dissplayed an hourglass in beginbuild, set it back + here, you do not need to explicitly sort the list + } + MS_CLUI_LISTENDREBUILD = 'CLUI/ListEndRebuild'; + + { + wParam : 0 + lParam : 0 + Affect : Sort the contact list now, see notes + Returns: 0 success, [non zero] on failure + Notes : Sorts are buffered so you won't get this message lots of times + if the lists needs to be resorted many times rapidly + } + MS_CLUI_SORTLIST = 'CLUI/SortList'; + + { + wParam : CLUICAPS_* + lParam : 0 + Affect : Gets a load of capabilites for the loaded CLUI, see notes + Returns: the requested value, 0 of wParam is unknown -- + if this service is not implemented it is assumed all return + values will be 0. + Version: v0.1.2.1+ + } + + { can only provide this flag to return the following set of caps, the strings + show the database setting/type to store the list option, changing the value + does not reflect what the change is, i.e. ontop can only be affected with + a call to SetWindowPos() } + CLUICAPS_FLAGS1 = 0; + { empty groups aren't shown, 'CList/HideEmptyGroups' (byte) [changes make the list reload] } + CLUIF_HIDEEMPTYGROUPS = 1; + { groups can be disabled, lists can be merged into one seamlessly, (byte) 'CList/UseGroups' } + CLUIF_DISABLEGROUPS = 2; + { list can be displayed 'on top' of all other windows, 4 (byte) 'CList/OnTop' } + CLUIF_HASONTOPOPTION = 4; + { can disappear after a while of inactive use, + (byte) 'CList/AutoHide' (word) 'CList/HideTime' } + CLUIF_HASAUTOHIDEOPTION = 8; + + MS_CLUI_GETCAPS = 'CLUI/GetCaps'; + + { + wParam : HCONTACT + lParam : MAKELPARAM(screenX, screenY) + Affect : A contact is being dragged outside the main window + Return : return [non zero] to show the drag cursor as "accepting" the drag + or zero to show the circle/slash 'not allowed' + Version: v0.1.2.0+ + } + ME_CLUI_CONTACTDRAGGING = 'CLUI/ContactDragging'; + + { + wParam : HCONTACT + lParam : MAKELPARAM(screenX, screenY) + Affect : a contact has just been dropped outside the main window, see notes + Notes : return non zero to stop other hooks processing this event. + Version: v0.1.2.0+ + } + ME_CLUI_CONTACTDROPPED = 'CLUI/ContactDropped'; + + { + wParam : HCONTACT + lParam : 0 + Affect : A contact that *was* being dragged outside the main window + has gone back to the main window + Return : always return 0 + Version: v0.1.2.1+ + } + ME_CLUI_CONTACTDRAGSTOP = 'CLUI/ContactDragStop'; + +{$ENDIF} \ No newline at end of file diff --git a/plugins/Chess4Net/MI/MirandaINC/m_contacts.inc b/plugins/Chess4Net/MI/MirandaINC/m_contacts.inc new file mode 100644 index 0000000000..4ea0d936c3 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_contacts.inc @@ -0,0 +1,84 @@ +(* +Miranda IM + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*) + +type + + PCONTACTINFO = ^TCONTACTINFO; + TCONTACTINFO = record + cbSize: int; + dwFlag: Byte; + hContact: THandle; + szProto: PChar; + type_: Byte; + retval: record (* in C this is a nameless union *) + case longint of + 0: (bVal: Byte); + 1: (wVal: WORD); + 2: (dVal: DWORD); + 3: (pszVal: PChar); + 4: (cchVal: Word); + end; + end; + +const + +// CNF_* Types of information you can retreive by setting the dwFlag in CONTACTINFO + + CNF_FIRSTNAME = 1; // returns first name (string) + CNF_LASTNAME = 2; // returns last name (string) + CNF_NICK = 3; // returns nick name (string) + CNF_CUSTOMNICK = 4; // returns custom nick name, clist name (string) + CNF_EMAIL = 5; // returns email (string) + CNF_CITY = 6; // returns city (string) + CNF_STATE = 7; // returns state (string) + CNF_COUNTRY = 8; // returns country (string) + CNF_PHONE = 9; // returns phone (string) + CNF_HOMEPAGE = 10; // returns homepage (string) + CNF_ABOUT = 11; // returns about info (string) + CNF_GENDER = 12; // returns gender (byte,'M','F' character) + CNF_AGE = 13; // returns age (byte, 0==unspecified) + CNF_FIRSTLAST = 14; // returns first name + last name (string) + CNF_UNIQUEID = 15; // returns uniqueid, protocol username (must check type for type of return) + +// Special types +// Return the custom name using the name order setting +// IMPORTANT: When using CNF_DISPLAY you MUST free the string returned +// You must **NOT** do this from your version of free() you have to use Miranda's free() +// you can get a function pointer to Miranda's free() via MS_SYSTEM_GET_MMI, see m_system.h + CNF_DISPLAY = 16; +// Same as CNF_DISPLAY except the custom handle is not used +// IMPORTANT: When using CNF_DISPLAYNC you MUST free the string returned +// You must **NOT** do this from your version of free() you have to use Miranda's free() +// you can get a function pointer to Miranda's free() via MS_SYSTEM_GET_MMI, see m_system.h + CNF_DISPLAYNC = 17; + +// If MS_CONTACT_GETCONTACTINFO returns 0 (valid), then one of the following +// types is setting telling you what type of info you received + CNFT_BYTE = 1; + CNFT_WORD = 2; + CNFT_DWORD = 3; + CNFT_ASCIIZ = 4; + + { + wParam : not used + lParam : Pointer to an initialised TCONTACTINFO structure + affects: Get contact information + returns: Zero on success, non zero on failure. + notes : If successful, the type is set and the result is put into the associated member of TCONTACTINFO + } + MS_CONTACT_GETCONTACTINFO = 'Miranda/Contact/GetContactInfo'; diff --git a/plugins/Chess4Net/MI/MirandaINC/m_database.inc b/plugins/Chess4Net/MI/MirandaINC/m_database.inc new file mode 100644 index 0000000000..678977979c --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_database.inc @@ -0,0 +1,654 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_DATABASE} +{$DEFINE M_DATABASE} + +const + + DBVT_DELETED = 0; // setting got deleted, no values are valid + DBVT_BYTE = 1; // bVal, cVal are valid + DBVT_WORD = 2; // wVal, sVal are valid + DBVT_DWORD = 4; // dVal, lVal are valid + DBVT_ASCIIZ = 255; // pszVal is valid + DBVT_BLOB = 254; // cpbVal and pbVal are valid + DBVTF_VARIABLELENGTH = $80; // ? + +type + + HCONTACT = Integer; + HDBEVENT = Integer; + + PDBVARIANT = ^TDBVARIANT; + TDBVARIANT = record + type_: Byte; + case LongInt of + 0: (bVal: Byte); + 1: (cVal: Char); + 2: (wVal: Word); + 3: (sVal: SmallInt); + 4: (dVal: LongInt); + 5: (lVal: Integer); + 6: ( + pszVal: PChar; + cchVal: Word; + ); + 7: ( + cpbVal: Word; + pbVal: PByte; + ); + end; + +const + + { + wParam : size of the buffer to be filled + lParam : pointer to the buffer to be filled + affect : Get's the name of the current profile being used by the database + module -- this is the same as the filename of the profile without + the .ext + return : 0 on success, non zero on failure + } + MS_DB_GETPROFILENAME = 'DB/GetProfileName'; + + { + wParam : size of buffer pointed to by lParam + lParam : pointer to a buffer to be filled + affect : Fill a buffer with the current profile path being used, this does not include the trailing backslash. + return : 0 on success, non zero on failure + version: 0.3a only + } + MS_DB_GETPROFILEPATH = 'DB/GetProfilePath'; + +type + + PDBCONTACTGETSETTING = ^TDBCONTACTGETSETTING; + TDBCONTACTGETSETTING = record + { name of the module that wrote the setting to get } + szModule: PChar; + { the name of the setting to get } + szSetting: PChar; + { pointer to DBVARIANT to receive the value -- must be allocated for GETSETTINGSTATIC + calls thou } + pValue: PDBVARIANT; + end; + + PDBCONTACTWRITESETTING = ^TDBCONTACTWRITESETTING; + TDBCONTACTWRITESETTING = record + { module sig to write this setting under } + szModule: PChar; + { setting name to write } + szSetting: PChar; + { variant containing value to set } + value: TDBVARIANT; + end; + +const + + { + wParam : Handle of a contact to get the setting for (see notes) + lParam : pointer to a TDBCONTACTGETSETTING structure to be filled with setting + this structure also has to be initalised (see notes) + affect : Queries the database module for a setting from a contact. + returns: 0 on success, non zero on failure (contact not found, setting doesn't exist) + notes : TDBCONTACTGETSETTING must be filled with the module name that created + /wrote the setting you want to get (e.g. your module name) + and the actual setting to read with TDBCONTACTGETSETTING.szModule and + TDBCONTACTGETSETTING.szSetting -- TDBCONTACTGETSETTING.pValue is + a pointer to a TDBVARIANT with the returned setting, this maybe nil + and MUST be freed after you're done with it with FreeVariant() + + There are helper functions for reading/writing/deleting common types to and + from the database -- see DBGetContactSetting + + the contact handle (hContact) can be returned by FindContact/AddContact + } + MS_DB_CONTACT_GETSETTING = 'DB/Contact/GetSetting'; + + { + wParam : Handle for a contact to query a setting for + lParam : Pointer to a TDBCONTACTGETSETTING structure + affects: This service is almost the same as the one above, but it does + not return a dynamic copy (with malloc()) -- the caller + must do this for datatypes which require it, e.g. a string. + + This means the TDBCONTACTGETSETTING.pValue *has* to exist and be + allocated by the caller (doesn't have to be allocated from the heap) + the DBVARIANT structure has to be initalised with the type wanted + and enough buffer space around to return the info, do not + expect this service to be as fast as the one above. + + returns: 0 on success, non zero on failure. + } + MS_DB_CONTACT_GETSETTINGSTATIC = 'DB/Contact/GetSettingStatic'; + + { + wParam : 0 + lParam : Pointer to a TDBVARIANT structure + affect : Free's the passed DBVARIANT's dynamic memory (if any) see notes + returns: 0 on success, non zero on failure + notes : use the helper function FreeVariant() + } + MS_DB_CONTACT_FREEVARIANT = 'DB/Contact/FreeVariant'; + + { + wParam : Handle to contact to write setting for + lParam : Pointer to TDBCONTACTWRITESETTING which must be initalised + affects: writes a setting under a contact -- TDBCONTACTWRITESETTING structure + must contain the module name writing -- the setting name, and the value + to write (which is NOT a pointer) .szModule, .szSetting, .Value, see notes + returns: 0 on success, non zero on failure + notes : this service triggers 'DB/Contact/SettingChanged' before it returns + as always, there is a helper function to use this service. + } + MS_DB_CONTACT_WRITESETTING = 'DB/Contact/WriteSetting'; + + { + wParam : hContact under which the setting should be deleted + lParam : Pointer to a TDBCONTACTGETSETTING structure + affects: Deletes the given setting for a contact, the TDBCONTACTGETSETTING.pValue + field is ignored -- only .szModule and .szSetting are needed, see notes + returns: 0 on success, non zero on failure + notes : triggers 'DB/Contact/SettingChanged' BEFORE it deletes the given + setting, when the service returns the TDBVARIANT structure .type_ is set + to 0 and no fields are valid, there is a helper function for this + service, see below. + } + MS_DB_CONTACT_DELETESETTING = 'DB/Contact/DeleteSetting'; + + { + wParam : Handle of a contact to enum settings for + lParam : Pointer to a TDBCONTACTENUMSETTINGS structure, must be initalised + affect : Enumerates all settings for a given contact under a module, + TDBCONTACTENUMSETTINGS must be filled with the function pointer to call + the TDBCONTACTENUMSETTINGS.lParam value to pass to it each time, + as well as the .szModule under which the contact is valid + returns: returns the value of the last call to the enum function, or -1 + if no settings could be enumerated + notes : the szSetting argument passed to the enumeration function is only + valid for the duration of that enumeration call, + it must be allocated dynamically if it is required after that call frame + has returned. + Also, deleting settings as they are enumerated has unpredictable results! + but writing a new value for a setting is okay. + it is unclear how you stop the enumeration once it is started, maybe + possible to return -1 to stop it. + vesion : only valid for 0.1.0.1+ + } + +type + + TDBSETTINGENUMPROC = function(const szSetting: PChar; lParam: LPARAM): int; cdecl; + + PDBCONTACTENUMSETTINGS = ^TDBCONTACTENUMSETTINGS; + TDBCONTACTENUMSETTINGS = record + { function pointer to call to start the enum via MS_DB_CONTACT_ENUMSETTINGS } + pfnEnumProc: TDBSETTINGENUMPROC; + { passed to the above function } + lParam: LPARAM; + { name of the module to get settings for } + szModule: PChar; + { not used by us } + ofsSettings: DWORD; + end; + +const + + MS_DB_CONTACT_ENUMSETTINGS = 'DB/Contact/EnumSettings'; + + { + wParam : 0 + lParam : 0 + affect : none + returns: Returns the number of contacts in the database for the loaded profile + not including the profile user, see notes. + notes : the contacts in the database can be read with FindFirst/FindNext + } + MS_DB_CONTACT_GETCOUNT = 'DB/Contact/GetCount'; + + { + wParam : 0 + lParam : 0 + returns: Returns a handle to the first contact in the database, + this handle does not need to be closed, if there are no users + NULL(0) is returned. + } + MS_DB_CONTACT_FINDFIRST = 'DB/Contact/FindFirst'; + + { + wParam : Contact handle + lParam : 0 + returns: Returns a handle to the next contact after the given contact in + wParam, this handle does not neeed to be closed -- may return NULL(0) + if the given contact in wParam was the last in the database, or the + given contact was invalid + } + MS_DB_CONTACT_FINDNEXT = 'DB/Contact/FindNext'; + + { + wParam : Handle of a contact to delete + lParam : 0 + affect : the user by the given handle is deleted from the database, see notes + returns: Returns 0 on success or nonzero if the handle was invalid + notes : this triggers DB/Contact/Deleted BEFORE it actually deletes the contact + all events are also deleted -- other modules may end up with invalid + handles because of this, which they should be prepared for. + } + MS_DB_CONTACT_DELETE = 'DB/Contact/Delete'; + + { + wParam : 0 + lParam : 0 + affects: creates a new contact in the database, they have no settings, + settings must be added with MS_DB_CONTACT_WRITESETTING or + database helper functions for writing, see notes + returns: A handle to a new contact or NULL(0) on failure. + notes : triggers the ME_DB_CONTACT_ADDED event just before the service returns + } + MS_DB_CONTACT_ADD = 'DB/Contact/Add'; + + + { + wParam : (HANDLE) hContact + lParam : 0 + affects: Checks the given handle within the database for valid information, for + a proper internal header. + returns: Returns 1 if the contact handle is valid, 0 if it is not + notes : Due to the nature of multiple threading a contact handle can be deleted + soon after this service has returned a handle as valid, however it will never point + to another contact. + } + MS_DB_CONTACT_IS = 'DB/Contact/Is'; + + + { + wParam : contact handle for events count is needed + lParam : 0 + service: Gets the number of events in the chain belonging to a contact + in the databasee. + returns: the numbef of events owned by hContact or -1 if hContact + is invalid, they can be found with the event/find* servicees + } + MS_DB_EVENT_GETCOUNT = 'DB/Event/GetCount'; + + { + wParam : contact handle to add an event for + lParam : Pointer to TDBEVENTINFO initialised with data + affect : Add's an event to the contact's event list, the TDBEVENTINFO + structure should be filled with the event of message -- see notes + returns: a handle to a DB event (HDBEVENT), or NULL on error + notes : Triggers DB/Event/Added event just before it returns, + Events are sorted chronologically as they are entered, + so you cannot guarantee that the new hEvent is the last event in the chain, + however if a new event is added that has a timestamp less than + 90 seconds *before* the event that should be after it, + it will be added afterwards, to allow for protocols that only + store times to the nearest minute, and slight delays in transports. + There are a few predefined eventTypes below for easier compatibility, but + modules are free to define their own, beginning at 2000 + DBEVENTINFO.timestamp is in GMT, as returned by time() + } + + DBEF_FIRST = 1; // internally only, do not use + DBEF_SENT = 2; // if set, the event was sent by the user, otherwise it was received + DBEF_READ = 4; // event has been read by the user -- only needed for history + + EVENTTYPE_MESSAGE = 0; + EVENTTYPE_URL = 1; + EVENTTYPE_CONTACTS = 2; // v0.1.2.2+ + EVENTTYPE_ADDED = 1000; // v0.1.1.0+: these used to be module- + EVENTTYPE_AUTHREQUEST = 1001; // specific codes, hence the module- + EVENTTYPE_FILE = 1002; // specific limit has been raised to 2000 + +type + + PDBEVENTINFO = ^TDBEVENTINFO; + TDBEVENTINFO = record + { size of the structure } + cbSize: int; + { module that 'owns' this event and controls the data format } + szModule: PChar; + { timestamp in UNIX time } + timestamp: DWORD; + { the DBEF_* flags above } + flags: DWORD; + { event type, such as message, can be module defined } + eventType: WORD; + { size in bytes of pBlob^ } + cbBlob: DWORD; + { pointer to buffer containing the module defined event data } + pBlob: PByte; + end; + +const + + MS_DB_EVENT_ADD = 'DB/Event/Add'; + + + + { + wParam : Handle to the contact + lParam : HDBEVENT handle to delete + affects: Removes a single event from the database for the given contact + returns: 0 on success, nonzero on failure + notes : Triggers DB/Event/Deleted just before the event *is* deleted + } + MS_DB_EVENT_DELETE = 'DB/Event/Delete'; + + { + wParam : Handle to DB event + lParam : 0 + returns: Returns the space in bytes requried to store the blob in HDBEVENT + given by HDBEVENT(wParam) -- or -1 on error + } + MS_DB_EVENT_GETBLOBSIZE = 'DB/Event/GetBlobSize'; + + { + wParam : Handle to a DB event + lParam : Pointer to a TDBEVENTINFO structure which must be initialised + affects: Returns all the information about an DB event handle to a TDBEVENTINFO + structure which must be initalised, DBEI.cbSize, DBEI.pBlob and DBEI.cbSize + before calling this service, the size can be assertained with + GetBlobSize() service, see notes + returns: Returns 0 on success, non zero on failure + notes : The correct value dbe.cbBlob can be got using db/event/getblobsize + If successful, all the fields of dbe are filled. dbe.cbBlob is set to the + actual number of bytes retrieved and put in dbe.pBlob + If dbe.cbBlob is too small, dbe.pBlob is filled up to the size of dbe.cbBlob + and then dbe.cbBlob is set to the required size of data to go in dbe.pBlob + On return, dbe.szModule is a pointer to the database module's + own internal list of modules. Look but don't touch. + } + MS_DB_EVENT_GET = 'DB/Event/Get'; + + { + wParam : HCONTACT + lParam : HDBEVENT + affect : Changes the flag for an event to mark it as read + Returns: Returns the entire flag DWORD for the event after the change, or -1 + if HDBEVENT is invalid, see notes + notes : This iss one of the database write operations that does not trigger + an event, modules should not save flagss states for any length of time. + } + MS_DB_EVENT_MARKREAD = 'DB/Event/MarkRead'; + + { + wParam : HDBEVENT + lParam : 0 + Affect : Returns a handle to a contact that owns the HDBEVENT, + see notes + Returns: Returns a handle if successful or HDBEEVENT(-1) on failure + notes : This service is very slow, only use wheen you have no other choice + at all. + } + MS_DB_EVENT_GETCONTACT = 'DB/Event/GetContact'; + + { + wParam : HCONTACT + lParam : 0 + Affect : Retrieves a handlee to the first event in the chain + for a HCONTACT + returns: Returns a handle, or NULL(0) if HCONTACT is invalid or has + no events, events in a chain are sorted chronologically automatically + } + MS_DB_EVENT_FINDFIRST = 'DB/Event/FindFirst'; + + { + wParam : HCONTACT + lParam : 0 + Affect : Retrieves a handle to the first unreead event in a chain for a HCONTACT + see notes + Returns: Returns a HDBEVENT handle or NULL(0) if the HCONTACT is invalid + or all it's events have beeen read. + Notes : Events in a chain are sorted chronologically automatically, + but this does not necessarily mean that all events after + the first unread are unread too. + They should be checked individually with event/findnext and event/get + This service is designed for startup, reloading all the events that remained + unread from last time + } + MS_DB_EVENT_FINDFIRSTUNREAD = 'DB/Event/FindFirstUnread'; + + { + wParam : HCONTACT + lParam : 0; + Affects: Retrieves a handle to the lasts event in the chain for a HCONTACT + Returns: Returns a handle or NULL(0) if HCONTACT is invalid or has no events + } + MS_DB_EVENT_FINDLAST = 'DB/Event/FindLast'; + + { + wParam : HDBEVENT + lParam : 0 + Affects: Retrieves a handle to the next event in a chain after HDBEVENT + Returns: A handle to the next DB event or NULL(0) if HDBEVENT is invalid + or the last event in the chain. + } + MS_DB_EVENT_FINDNEXT = 'DB/Event/FindNext'; + + { + wParam : HDBEVENT + lParam : 0 + Affects: Retrieves a handle to the previous event in a chain before HDBEVENT + Returns: A handle to the previous HDBEVENT or NULL(0) if HDBEVENT is invalid + or is the first event in the chain + } + MS_DB_EVENT_FINDPREV = 'DB/Event/FindPrev'; + + + + { + wParam : size in bytes of string buffer (including null term) + lParam : pointer to string buffer + Affect : Scrambles the string buffer in place using a strange encryption algorithm, + see notes + Returns: Always returns 0 + notes : this service may be changed at a later date such that it increasess + the length of the string + } + MS_DB_CRYPT_ENCODESTRING = 'DB/Crypt/EncodeString'; + + { + wParam : size in bytes of string buffer, including null term + lParam : pointer to string buffer + Affect : Descrambles pszString in-place using the strange encryption algorithm, + see notes. + Return : Always returns 0 + notes : Reverses the operation done by MS_DB_CRYPT_ENCODINGSTRING + } + MS_DB_CRYPT_DECODESTRING = 'DB/Crypt/DecodeString'; + + + + { + wParam : timestamp (DWORD) + lParam : 0 + Affect : Converts a GMT timestap into local time + Returns: Returns the converted value, see notes + Notes : Timestamps have a zereo at midnight 1/1/1970 GMT, this service + converts such a value to be based at midnight 1/1/1970 local time. + This service does not use a simple conversion based on the current offset + between GMT and local. Rather, it figures out whether daylight savings time + would have been in place at the time of the stamp and gives the local time as + it would have been at the time and date the stamp contains. + } + MS_DB_TIME_TIMESTAMPTOLOCAL = 'DB/Time/TimestampToLocal'; + + { + wParam : timestamp (DWORD) + lParam : pointer to initalised DBTIMETOSTRING structure + Affect : Converts a GMT timestamp to a customisable local time string + see notes + Returns: Always returns 0 + notes : The string is formatted according to thhe current user's locale + language and preference -- + + .szFormat can have the following special chars : + t time without seconds, e.g. hh:mm + s time with seconds, e.g. hh:mm:ss + m time without minutes e.g. hh + d short date, e.g. dd/mm/yyyy + D long date, e.g. d mmmm yyyy + + all other characters are copied as is. + } + +type + + PDBTIMETOSTRING = ^TDBTIMETOSTRING; + TDBTIMETOSTRING = record + { format string, see above } + szFormat: PChar; + { pointer to dest buffer to store the result } + szDest: PChar; + { size of the buffer } + cbDest: int; + end; + +const + + MS_DB_TIME_TIMESTAMPTOSTRING = 'DB/Time/TimestampToString'; + + + + { + wParam : newSetting (BOOLEAN) + lParam : 0 + Affect : Miranda's database is normally protected against corruption by + aggressively flushing data to the disk on writes, if you're doing + alot of writes e.g. an import plugin, it can sometimes be desirable + to switch this feature off to speed up the process, if you do switch + it off, you must remember that crashes are far more likely to be + catastrophic, so switch it back on at the earliest possible opportunity. + if you're doing a lot of setting writes, the flush is already delayed + so you need not use this service for that purpose, see notes. + Returns: Always returns 0 (successful) + notes : This is set to true initally + } + MS_DB_SETSAFETYMODE = 'DB/SetSafetyMode'; + + { + wParam : (caller defined data) will be passed to lParam of the call back + lParam : function pointer to TDBMODULEENUMPROC + Affects: Enumerates the names of all modules that have stored or + requested information from the database, + the modules are returned in no real order -- + Writing to the database while module names are being enumerated will cause + unpredictable results in the enumeration, but the write will work. + + the enumeration will stop if the callback returns a non zero value. + + Returns: the last return value from the enumeration call back. + Notes : This service is only useful for debugging or EnumSettings + version: The service registered to enumerate all modules that have touched + the database module uses wParam as the lParam cookie value and the lParam + value given here is the function pointer -- this is not safe + to use before v0.1.2.1 because I don't know if this was done in v0.1.2.1- + + prior to v0.1.2.1 you can not pass a value to the enumeration because + of a bug -- which is fixed, but hey :) -- [sam] + } +type + TDBMODULEENUMPROC = function(const szModule: PChar; ofsModuleName: DWORD; lParam: LPARAM): int; cdecl; +const + MS_DB_MODULES_ENUM = 'DB/Modules/Enum'; + + + + { + wParam : HCONTACT + lParam : HDBCONTACT + Affect : Called when a new event has been added to the event chain + for a contact, HCONTACT contains the contact who added the event, + HDBCONTACT a handle to what was added. + see notes + notes : since events are sorted chronologically, you can not guarantee + that HDBEVEnT is in any particular position in the chain. + + } + ME_DB_EVENT_ADDED = 'DB/Event/Added'; + + { + wParam : HANDLE (hContact) + lParam : @DBEVENTINFO + Affects: Hook is fired before any DBEVENTS are created within the database for + a contact (or a user, if hContact is NULL(0)) - It allows a module to + query/change DBEVENTINFO before it is created, see notes. + Returns: Hook should return 1 to stop event being added (will stop other hooks seeing the event too) + Or 0 to continue processing (passing the data on as well) + Notes : This hook is fired for all event types, and the BLOBS that the eventypes mark + Maybe changed, therefore be careful about using BLOB formats. + Because the memory pointing within the DBEVENTINFO CAN NOT BE OWNED or free()'d + it is recommended that the hook only be used to stop events. + Version: 0.3.3a+ (2003/12/03) + } + ME_DB_EVENT_FILTER_ADD = 'DB/Event/FilterAdd'; + + { + wParam : HCONTACT + lParam : HDBEVENT + Affect : Called when an event is about to be deleted from the event chain + for a contact, see notes + notes : Returning non zero from your hook will NOT stop the deletion, + but it will as usual stop other hooks being called + } + ME_DB_EVENT_DELETED = 'DB/Event/Deleted'; + + + + { + wParam : HCONTACT + lParam : 0 + Affect : Called when a new contact has been added to the database, + HCONTACT contains a handle to the new contact. + } + ME_DB_CONTACT_ADDED = 'DB/Contact/Added'; + + { + wParam : HCONTACT + lParam : 0 + Affect : Called when a contact is about to be deleted + Returns: Returning nonzero from your hook will not stop the deletion + but it will stop the other hooks from being called + } + ME_DB_CONTACT_DELETED = 'DB/Contact/Deleted'; + + { + wParam : HCONTACT + lParam : Pointer to a TDBCONTACTWRITESETTING + Affect : Calleed when a contact has one of it's settings changed + hContact is a valid handle to the contact that has changed, + see notes. + notes : this event will be triggered many times rapidly when alot of values + are set. + Modules that hook this should be aware of this fact and quickly + return if they are not interested in the value that has changed. + Careful not to get into infinite loops with this event, + + The TDBCONTACTWRITESETTING pointer is the same one as the + original service all, so don't change any of it's fields + } + ME_DB_CONTACT_SETTINGCHANGED = 'DB/Contact/SettingChanged'; + +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_email.inc b/plugins/Chess4Net/MI/MirandaINC/m_email.inc new file mode 100644 index 0000000000..71859ed208 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_email.inc @@ -0,0 +1,39 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) +{$IFNDEF M_EMAIL} +{$DEFINE M_EMAIL} + +const + + { + wParam : HCONTACT + lParam : 0 + Affects: Send an e-mail to the specified contact, see notes + Returns: Returns 0 on success or nonzero on failure + Notes : If an error occurs the service displays a message box + with the error text -- use this service to alter this + } + MS_EMAIL_SENDEMAIL = 'SREMail/SendCommand'; + +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_file.inc b/plugins/Chess4Net/MI/MirandaINC/m_file.inc new file mode 100644 index 0000000000..e1e388fcdc --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_file.inc @@ -0,0 +1,66 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_FILE} +{$DEFINE M_FILE} + +const + + { + wParam : HCONTACT + lParam : 0 + Affects: Brings up the send file dialog for a contact, see notes + Returns: 0 on success [non zero] on failure + Notes : Returns immediately without waiting for the send + } + MS_FILE_SENDFILE = 'SRFile/SendCommand'; + + { + wParam : HCONTACT + lParam : pointer to an array of PChar's the first nil item + terminates the list -- see notes + Affects: Brings up the send file dialog with specifieed files already chosen + the user is not prevented from editing the list -- + Returns: 0 on success [non zero] on failure -- returns immediately without + waiting for the send to finish + Notes : both directories and files can be given + Version: v0.1.2.1+ + } + MS_FILE_SENDSPECIFICFILES = 'SRFile/SendSpecificFiles'; + + { + wParam : HCONTACT + lParam : Pointer to a buffer + Affects: returns the received files folder for a contact, the buffer + should be at least MAX_PATH long (defined with WinAPI), + the returned path may not exist -- see notes + Returns: Returns 0 on success [non zero] on failure + notes : If HCONTACT is NULL(0) the path returned is the path + without the postfix contact name. + Version: v0.1.2.2+ + } + MS_FILE_GETRECEIVEDFILESFOLDER = 'SRFile/GetReceivedFilesFolder'; + + +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_findadd.inc b/plugins/Chess4Net/MI/MirandaINC/m_findadd.inc new file mode 100644 index 0000000000..9952a787c8 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_findadd.inc @@ -0,0 +1,38 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) +{$IFNDEF M_FINDADD} +{$DEFINE M_FINDADD} + +const + + { + wParam : 0 + lParam : 0 + Affects: Openss the find/add users dialog box, or gives it focus if it's + already open. + Returns: Always returns 0 + } + MS_FINDADDFINDADD = 'FindAdd/FindAddCommand'; + +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_globaldefs.pas b/plugins/Chess4Net/MI/MirandaINC/m_globaldefs.pas new file mode 100644 index 0000000000..2eb47e8a90 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_globaldefs.pas @@ -0,0 +1,98 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFDEF FPC} + {$PACKRECORDS C} + {$MODE Delphi} +{$ENDIF} + +unit m_globaldefs; + +interface + +uses + +{$ifdef FPC} + strings; +{$else} + Windows; +{$endif} + +type + + PByte = ^Byte; + int = Integer; + pint = ^int; + WPARAM = Integer; + LPARAM = Integer; + DWORD = Integer; + THandle = Integer; + + // strcpy() + + {$ifdef FPC} + TStrCpy = function(Dst, Src: PChar): PChar; + {$else} + TStrCpy = function(Dst, Src: PChar): PChar; stdcall; + {$endif} + + // strcat() + + {$ifdef FPC} + TStrCat = function(Dst, Src: PChar): PChar; + {$else} + TStrCat = function(Dst, Src: PChar): PChar; stdcall; + {$endif} + +const + + {$ifdef FPC} + strcpy: TStrCpy = strings.strcopy; + {$else} + strcpy: TStrCpy = lstrcpy; + {$endif} + + {$ifdef FPC} + strcat: TStrCat = strings.strcat; + {$else} + strcat: TStrCat = lstrcat; + {$endif} + + {$include newpluginapi.inc} + +var + { this is now a pointer to a record of function pointers to match the C API, + and to break old code and annoy you. } + + PLUGINLINK: PPLUGINLINK; + + { has to be returned via MirandaPluginInfo and has to be statically allocated, + this means only one module can return info, you shouldn't be merging them anyway! } + + PLUGININFO: TPLUGININFO; + PLUGININFOEX: TPLUGININFOEX; + +implementation + +end. diff --git a/plugins/Chess4Net/MI/MirandaINC/m_helpers.inc b/plugins/Chess4Net/MI/MirandaINC/m_helpers.inc new file mode 100644 index 0000000000..d09d66324e --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_helpers.inc @@ -0,0 +1,622 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$ifdef M_API_UNIT} + + function PLUGIN_MAKE_VERSION(a,b,c,d: Cardinal): int; + function PLUGIN_CMP_VERSION(verA: LongInt; verB: LongInt): int; + +{$else} + + function PLUGIN_MAKE_VERSION(a,b,c,d: Cardinal): int; + {$ifdef FPC} + inline; + {$endif} + begin + Result := (a shl 24) or (b shl 16) or (c shl 8) or d; + end; + + function PLUGIN_CMP_VERSION(verA: LongInt; verB: LongInt): int; {$ifdef FPC} + inline; + {$endif} + begin + Result := 0; + { could be used to compare for severity of age for positive values, if a 0 then + Result := ErrorValue + else + Result := dbv.bVal; + end; + + function DBGetContactSettingWord(hContact: THandle; + const szModule: PChar; const szSetting: PChar; errorValue: Integer): Integer; + {$ifdef FPC} + inline; + {$endif} + var + dbv: TDBVARIANT; + cgs: TDBCONTACTGETSETTING; + begin + cgs.szModule := szModule; + cgs.szSetting := szSetting; + cgs.pValue := @dbv; + If PluginLink^.CallService(MS_DB_CONTACT_GETSETTING, hContact, lParam(@cgs)) <> 0 then + Result := ErrorValue + else + Result := dbv.wVal; + end; + + function DBGetContactSettingDword(hContact: THandle; + const szModule: PChar; const szSetting: PChar; errorValue: Integer): Integer; + {$ifdef FPC} + inline; + {$endif} + var + dbv: TDBVARIANT; + cgs: TDBCONTACTGETSETTING; + begin + cgs.szModule := szModule; + cgs.szSetting := szSetting; + cgs.pValue := @dbv; + If PluginLink^.CallService(MS_DB_CONTACT_GETSETTING, hContact, lParam(@cgs)) <> 0 then + Result := ErrorValue + else + Result := dbv.dVal; + end; + + function DBGetContactSetting(hContact: THandle; + const szModule: PChar; const szSetting: PChar; dbv: PDBVARIANT): Integer; + {$ifdef FPC} + inline; + {$endif} + var + cgs: TDBCONTACTGETSETTING; + begin + cgs.szModule := szModule; + cgs.szSetting := szSetting; + cgs.pValue := dbv; + Result := PluginLink^.CallService(MS_DB_CONTACT_GETSETTING, hContact, lParam(@cgs)); + end; + + function DBFreeVariant(dbv: PDBVARIANT): Integer; + {$ifdef FPC} + inline; + {$endif} + begin + Result := PluginLink^.CallService(MS_DB_CONTACT_FREEVARIANT, 0, lParam(dbv)); + end; + + function DBDeleteContactSetting(hContact: THandle; const szModule: PChar; const szSetting: PChar): Integer; + {$ifdef FPC} + inline; + {$endif} + var + cgs: TDBCONTACTGETSETTING; + begin + cgs.szModule := szModule; + cgs.szSetting := szSetting; + Result := PluginLink^.CallService(MS_DB_CONTACT_DELETESETTING, hContact, lParam(@cgs)); + end; + + function DBWriteContactSettingByte(hContact: THandle; const szModule: PChar; const szSetting: PChar; val: Byte): Integer; + {$ifdef FPC} + inline; + {$endif} + var + cws: TDBCONTACTWRITESETTING; + begin + cws.szModule := szModule; + cws.szSetting := szSetting; + cws.value.type_ := DBVT_BYTE; + cws.value.bVal := Val; + Result := PluginLink^.CallService(MS_DB_CONTACT_WRITESETTING, hContact, lParam(@cws)); + end; + + function DBWriteContactSettingWord(hContact: THandle; const szModule: PChar; const szSetting: PChar; val: Word): Integer; + {$ifdef FPC} + inline; + {$endif} + var + cws: TDBCONTACTWRITESETTING; + begin + cws.szModule := szModule; + cws.szSetting := szSetting; + cws.value.type_ := DBVT_WORD; + cws.value.wVal := Val; + Result := PluginLink^.CallService(MS_DB_CONTACT_WRITESETTING, hContact, lParam(@cws)); + end; + + function DBWriteContactSettingDWord(hContact: THandle; const szModule: PChar; const szSetting: PChar; val: LongInt): Integer; + {$ifdef FPC} + inline; + {$endif} + var + cws: TDBCONTACTWRITESETTING; + begin + cws.szModule := szModule; + cws.szSetting := szSetting; + cws.value.type_ := DBVT_DWORD; + cws.value.dVal := Val; + Result := PluginLink^.CallService(MS_DB_CONTACT_WRITESETTING, hContact, lParam(@cws)); + end; + + function DBWriteContactSettingString(hContact: THandle; const szModule: PChar; const szSetting: PChar; const val: PChar): Integer; + {$ifdef FPC} + inline; + {$endif} + var + cws: TDBCONTACTWRITESETTING; + begin + cws.szModule := szModule; + cws.szSetting := szSetting; + cws.value.type_ := DBVT_ASCIIZ; + cws.value.pszVal := Val; + Result := PluginLink^.CallService(MS_DB_CONTACT_WRITESETTING, hContact, lParam(@cws)); + end; + + {$endif} + +{$endif} + +{$ifdef M_NETLIB} + + {$ifdef M_API_UNIT} + + function Netlib_CloseHandle(Handle: THandle): int; + + function Netlib_GetBase64DecodedBufferSize(const cchEncoded: int): int; + + function Netlib_GetBase64EncodedBufferSize(const cbDecoded: int): int; + + function Netlib_Send(hConn: THandle; const buf: PChar; len: int; flags: int): int; + + function Netlib_Recv(hConn: THandle; const buf: PChar; len: int; flags: int): int; + + procedure Netlib_Log(hNetLib: THandle; const sz: PChar); + + {$else} + + function Netlib_CloseHandle(Handle: THandle): int; + {$ifdef FPC} + inline; + {$endif} + begin + Result := PluginLink^.CallService(MS_NETLIB_CLOSEHANDLE, Handle, 0); + end; + + function Netlib_GetBase64DecodedBufferSize(const cchEncoded: int): int; + {$ifdef FPC} + inline; + {$endif} + begin + Result := (cchEncoded shr 2) * 3; + end; + + function Netlib_GetBase64EncodedBufferSize(const cbDecoded: int): int; + {$ifdef FPC} + inline; + {$endif} + begin + Result := (cbDecoded * 4+11) div 12*4+1; + end; + + function Netlib_Send(hConn: THandle; const buf: PChar; len: int; flags: int): int; + {$ifdef FPC} + inline; + {$endif} + var + nlb: TNETLIBBUFFER; + begin + nlb.buf := buf; + nlb.len := len; + nlb.flags := flags; + Result := PluginLink^.CallService(MS_NETLIB_SEND, wParam(hConn), lParam(@nlb)); + end; + + function Netlib_Recv(hConn: THandle; const buf: PChar; len: int; flags: int): int; + {$ifdef FPC} + inline; + {$endif} + var + nlb: TNETLIBBUFFER; + begin + nlb.buf := buf; + nlb.len := len; + nlb.flags := flags; + Result := PluginLink^.CallService(MS_NETLIB_RECV, wParam(hConn), lParam(@nlb)); + end; + + procedure Netlib_Log(hNetLib: THandle; const sz: PChar); + {$ifdef FPC} + inline; + {$endif} + begin + PluginLink^.CallService(MS_NETLIB_LOG, hNetLib, lParam(sz)); + end; + + {$endif} + +{$endif} + +{$ifdef M_UTILS} + + {$ifdef M_API_UNIT} + + function WindowList_Add(hList: THandle; hWnd: HWND; hContact: THandle): int; + + function WindowList_Remove(hList: THandle; hWnd: THandle): int; + + function WindowList_Find(hList: THandle; hContact: THandle): int; + + function WindowList_Broadcast(hList: THandle; message: int; wParam: WPARAM; lParam: LPARAM): int; + + function Utils_SaveWindowPosition(hWnd: THandle; hContact: THandle; const szModule, szNamePrefix: PChar): int; + + function Utils_RestoreWindowPosition(hWnd: THandle; hContact: THandle; Flags: int; const szModule, szNamePrefix: PChar): int; + + {$else} + + function WindowList_Add(hList: THandle; hWnd: hWnd; hContact: THandle): int; + var + wle: TWINDOWLISTENTRY; + begin + wle.hList := hList; + wle.hWnd := hWnd; + wle.hContact := hContact; + Result := PluginLink^.CallService(MS_UTILS_ADDTOWINDOWLIST, 0, lParam(@wle)); + end; + + function WindowList_Remove(hList: THandle; hWnd: THandle): int; + begin + Result := PluginLink^.CallService(MS_UTILS_REMOVEFROMWINDOWLIST, hList, hWnd); + end; + + function WindowList_Find(hList: THandle; hContact: THandle): int; + begin + Result := PluginLink^.CallService(MS_UTILS_FINDWINDOWINLIST, hList, hContact); + end; + + function WindowList_Broadcast(hList: THandle; message: int; wParam: WPARAM; lParam: LPARAM): int; + var + msg: TMSG; + begin + msg.message := message; + msg.wParam := wParam; + msg.lParam := lParam; + Result := PluginLink^.CallService(MS_UTILS_BROADCASTTOWINDOWLIST, hList, Integer(@Msg)); + end; + + function Utils_SaveWindowPosition(hWnd: THandle; hContact: THandle; const szModule, szNamePrefix: PChar): int; + var + swp: TSAVEWINDOWPOS; + begin + swp.hWnd := hWnd; + swp.hContact := hContact; + swp.szModule := szModule; + swp.szNamePrefix := szNamePrefix; + Result := PluginLink^.CallService(MS_UTILS_SAVEWINDOWPOSITION, 0, lParam(@swp)); + end; + + function Utils_RestoreWindowPosition(hWnd: THandle; hContact: THandle; Flags: int; const szModule, szNamePrefix: PChar): int; + var + swp: TSAVEWINDOWPOS; + begin + swp.hWnd := hWnd; + swp.hContact := hContact; + swp.szModule := szModule; + swp.szNamePrefix := szNamePrefix; + Result := PluginLink^.CallService(MS_UTILS_RESTOREWINDOWPOSITION, Flags, lParam(@swp)); + end; + + {$endif} + +{$endif} + +{$ifdef M_LANGPACK} + + {$ifdef M_API_UNIT} + + function Translate(sz: PChar): PChar; + + function TranslateString(sz: string): string; + + function TranslateDialogDefault(hwndDlg: THandle): int; + + {$else} + + function Translate(sz: PChar): PChar; + {$ifdef FPC} + inline; + {$endif} + begin + { the return value maybe NULL(0) -- it's upto the caller to know if the allocated + string has to be removed from the DLL heap, this has little to do with Miranda, + but if a dynamic string is passed and a return string is used -- the dynamic + string is lost -- be careful, lazy? use TranslateString (note it's slower) } + Result := PChar(PluginLink^.CallService(MS_LANGPACK_TRANSLATESTRING, 0, lParam(sz))); + end; + + function TranslateString(sz: string): string; + {$ifdef FPC} + inline; + {$endif} + begin + Result := string(PChar( PluginLink^.CallService(MS_LANGPACK_TRANSLATESTRING, 0, lParam(sz)))); + end; + + function TranslateDialogDefault(hwndDlg: THandle): int; + {$ifdef FPC} + inline; + {$endif} + var + lptd: TLANGPACKTRANSLATEDIALOG; + begin + lptd.cbSize := sizeof(lptd); + lptd.flags := 0; + lptd.hwndDlg := hwndDlg; + lptd.ignoreControls := nil; + Result := PluginLink^.CallService(MS_LANGPACK_TRANSLATEDIALOG, 0, lParam(@lptd)); + end; + + {$endif} + +{$endif} + +{$ifdef M_PROTOCOLS} + {$ifdef M_API_UNIT} + + function CallContactService(hContact: THandle; const szProtoService: PChar; wParam: WPARAM; lParam: LPARAM): int; + + function CallProtoService(const szModule, szService: PChar; wParam: WPARAM; lParam: LPARAM): int; + + {$else} + + function CallContactService(hContact: THandle; const szProtoService: PChar; wParam: WPARAM; lParam: LPARAM): int; + {$ifdef FPC} + inline; + {$endif} + var + css: TCCSDATA; + begin + css.hContact := hContact; + css.szProtoService := szProtoService; + css.wParam := wParam; + css.lParam := lParam; + Result := PluginLink^.CallService(MS_PROTO_CALLCONTACTSERVICE, 0, Integer(@css)); + end; + + function CallProtoService(const szModule, szService: PChar; wParam: WPARAM; lParam: LPARAM): int; + {$ifdef FPC} + inline; + {$endif} + var + szStr: array[0..MAXMODULELABELLENGTH] of Char; + begin + strcpy(szStr, szModule); + strcat(szStr, szService); + Result := PluginLink^.CallService(szStr, wParam, lParam); + end; + + {$endif} +{$endif} + +{$ifdef M_PROTOMOD} + {$ifdef M_API_UNIT} + + function ProtoBroadcastAck(const szModule: PChar; hContact: THandle; type_: int; result_: int; hProcess: THandle; lParam: LPARAM): int; + + function CreateProtoServiceFunction(const szModule, szService: PChar; serviceProc: TMIRANDASERVICE): int; + + {$else} + + function ProtoBroadcastAck(const szModule: PChar; hContact: THandle; type_: int; result_: int; hProcess: THandle; lParam: LPARAM): int; + {$ifdef FPC} + inline; + {$endif} + var + ack: TACKDATA; + begin + ack.cbSize := sizeof(TACKDATA); + ack.szModule := szModule; + ack.hContact := hContact; + ack.type_ := type_; + ack.result_ := result_; + ack.hProcess := hProcess; + ack.lParam := lParam; + Result := PluginLink^.CallService(MS_PROTO_BROADCASTACK, 0, Integer(@ack)); + end; + + function CreateProtoServiceFunction(const szModule, szService: PChar; serviceProc: TMIRANDASERVICE): int; + {$ifdef FPC} + inline; + {$endif} + var + szStr: array[0..MAXMODULELABELLENGTH] of Char; + begin + strcpy(szStr, szModule); + strcat(szStr, szService); + Result := PluginLink^.CreateServiceFunction(szStr, @serviceProc); + end; + + {$endif} + +{$endif} + +{$ifdef M_SKIN} + + {$ifdef M_API_UNIT} + + function LoadSkinnedIcon(id: int): THandle; + + function LoadSkinnedProtoIcon(const szProto: PChar; status: int): THandle; + + function SkinAddNewSound(const name, description, defaultFile: PChar): int; + + function SkinPlaySound (const name: PChar): int; + + {$else} + + function LoadSkinnedIcon(id: int): THandle; + {$ifdef FPC} + inline; + {$endif} + begin + Result := PluginLink^.CallService(MS_SKIN_LOADICON, id, 0); + end; + + function LoadSkinnedProtoIcon(const szProto: PChar; status: int): THandle; + {$ifdef FPC} + inline; + {$endif} + begin + Result := PluginLink^.CallService(MS_SKIN_LOADPROTOICON, wParam(szProto), status); + end; + + function SkinAddNewSound(const name, description, defaultFile: PChar): int; + {$ifdef FPC} + inline; + {$endif} + var + ssd: TSKINSOUNDDESC; + begin + ssd.cbSize := sizeof(ssd); + ssd.pszName := name; + ssd.pszDescription := description; + ssd.pszDefaultFile := defaultFile; + Result := PluginLink^.CallService(MS_SKIN_ADDNEWSOUND, 0, lParam(@ssd)); + end; + + function SkinPlaySound (const name: PChar): int; + {$ifdef FPC} + inline; + {$endif} + begin + Result := PluginLink^.CallService(MS_SKIN_PLAYSOUND, 0, lParam(name)); + end; + + {$endif} + +{$endif} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_history.inc b/plugins/Chess4Net/MI/MirandaINC/m_history.inc new file mode 100644 index 0000000000..af019ee255 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_history.inc @@ -0,0 +1,37 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) +{$IFNDEF M_HISTORY} +{$DEFINE M_HISTORY} + +const + + { + wParam : HCONTACT + lParam : 0 + Affects: Show's the history dialog box for a contact, see notes + Notes : HCONTACT can be NULL(0) to show system messages + } + MS_HISTORY_SHOWCONTACTHISTORY = 'History/ShowContactHistory'; + +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_icq.inc b/plugins/Chess4Net/MI/MirandaINC/m_icq.inc new file mode 100644 index 0000000000..a498513f01 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_icq.inc @@ -0,0 +1,191 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_ICQ} +{$DEFINE M_ICQ} + +const + + // extra database event type + ICQEVENTTYPE_WEBPAGER = 2003; + + // extra flags for PSS_MESSAGE + PIMF_ROUTE_DEFAULT = 0; + PIMF_ROUTE_DIRECT = $10000; + PIMF_ROUTE_THRUSERVER = $20000; + PIMF_ROUTE_BESTWAY = $30000; + PIMF_ROUTE_MASK = $30000; + + // for SMS + + ICQACKTYPE_SMS = 1001; + ICQEVENTTYPE_SMS = 2001; // database event type + + // for e-mail express + + { + BLOB: + text: ASCIIZ usually in the form "Subject: %s\r\n%s" + from-name: ASCIIZ + from-e-mail: ASCIIZ + } + + ICQEVENTTYPE_EMAILEXPRESS = 2002; + + // for server side lists, used internally only + + // hProcess=dwSequence, lParam=server's error code, 0 for success + ICQACKTYPE_SERVERCLIST = 1003; + +{$ifndef m_protosvc} + {$include m_protosvc.inc} +{$endif} + +type + + PICQSEARCHRESULT = ^TICQSEARCHRESULT; + TICQSEARCHRESULT = record + hdr: TPROTOSEARCHRESULT; + uin: DWORD; + auth: Byte; + end; + + PICQDETAILSSEARCH = ^TICQDETAILSSEARCH; + TICQDETAILSSEARCH = record + nick: PChar; + firstName: PChar; + lastNamee: PChar; + end; + +const + + { + wParam : 0 + lParam : null terminated string containing e-mail to search + affects: Start a search for all ICQ users by e-mail -- see notes + returns: Returnss a handle to the search on success, NULL(0) on failure + notes : uses the same scheme as PSS_BASICSEARCH, + *DEPRECATED* in favour of PS_SEARCHBYEMAIL + } + MS_ICQ_SEARCHBYEMAIL = 'ICQ/SearchByEmail'; + + { + wParam : 0 + lParam : POinter to a TICQDETAILSSEARCH structure + Affect : Start a search of all ICQ users by details, see notes + Returns: A handle to the search on success, NULL(0) on failure + Notes : Results are returned in the same scheme as in PSS_BASICSEARCH, + Not recommended, use PS_SEARCHBYNAME + } + MS_ICQ_SEARCHBYDETAILS = 'ICQ/SearchByDetails'; + + { + wParam : Pointer to a null terminated string containing phone number + lParam : Pointer to a null terminated string containing the message + Affect : Send an SMS via the ICQ network, See notes + Returns: Handle to the send on success, NULL(0) on failure + Notes : the phone number should be the full number with internation code + and prefixed by + e.g. +44 + } + MS_ICQ_SENDSMS = 'ICQ/SendSMS'; + + { + wParam : level + lParam : null terminated string containing logging message + Affect : a logging message was sent from ICQLib + } + ME_ICQ_LOG = 'ICQ/Log'; + +{$ENDIF} + + {$ifdef __} +//Changing user info: +//See documentation of PS_CHANGEINFO +//The changing user info stuff built into the protocol is purposely extremely +//thin, to the extent that your data is passed as-is to the server without +//verification. Don't mess up. +//Everything is byte-aligned +//WORD: 2 bytes, little-endian (that's x86 order) +//DWORD: 4 bytes, little-endian +//LNTS: a WORD containing the length of the string, followed by the string +// itself. No zero terminator. +#define ICQCHANGEINFO_MAIN 0xEA03 +/* pInfoData points to: + WORD datalen + LNTS nick + LNTS first + LNTS last + LNTS email + LNTS city + LNTS state + LNTS phone + LNTS fax + LNTS street + LNTS cellular (if SMS-able string contains an ending ' SMS') + LNTS zip + WORD country + BYTE gmt + BYTE unknown, usually 0 +*/ +#define ICQCHANGEINFO_MORE 0xFD03 +/* pInfoData points to: + WORD datalen + BYTE age + BYTE 0 + BYTE sex + LNTS homepage + WORD birth-year + BYTE birth-month + BYTE birth-day + BYTE lang1 + BYTE lang2 + BYTE lang3 +*/ +#define ICQCHANGEINFO_ABOUT 0x0604 +/* pInfoData points to: + WORD datalen + LNTS about +*/ +#define ICQCHANGEINFO_WORK 0xF303 +/* pInfoData points to: + WORD datalen + LNTS city + LNTS state + DWORD 0 + LNTS street + LNTS zip + WORD country + LNTS company-name + LNTS company-dept + LNTS company-position + WORD 0 + LNTS company-web +*/ +#define ICQCHANGEINFO_PASSWORD 0x2E04 +/* pInfoData points to: + WORD datalen + LNTS newpassword +*/ + {$endif} + diff --git a/plugins/Chess4Net/MI/MirandaINC/m_ignore.inc b/plugins/Chess4Net/MI/MirandaINC/m_ignore.inc new file mode 100644 index 0000000000..4dd83c4cee --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_ignore.inc @@ -0,0 +1,74 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) +{$IFNDEF M_IGNORE} +{$DEFINE M_IGNORE} + + { this module only provides UI and storage for blocking only, protocol modules + are responsible for implementing the block } + +const + + IGNOREEVENT_ALL = LPARAM(-1); + IGNOREEVENT_MESSAGE = 1; + IGNOREEVENT_URL = 2; + IGNOREEVENT_FILE = 3; + IGNOREEVENT_USERONLINE = 4; + IGNOREEVENT_AUTHORIZATION=5; + IGNOREEVENT_YOUWEREADDED=6; // 0.3.3a+ + + { + wParam : HCONTACT + lParam : IGNOREEVENT_* + Affects: Determines if a message type to a contact should be ignored, see notes + Returns: 0 if the message type MUST be shown [non zero] if it MUST be ignored + Notes : HCONTACT can be NULL(0) to see what to do with a contact + that isn't on the list (or is unknown in some way) + don't use the IGNOREEVENT_ALL type! + Version: v0.1.0.1+ + } + MS_IGNORE_ISIGNORED = 'Ignore/IsIgnored'; + + { + wParam : HCONTACT + lParam : IGNOREEVENT_* constant + Affects: Ignore future messages from a contact, see notes + Returns: 0 on success, [nonzero] on failure + Notes : wParam: NULL(0) can be used to see if an unknown contact should be ignored + or not - you can't SET unknown contact's ignore types, this is to stop + a plugin allowing certain functions (I guess) + Version: v0.1.0.1+ + } + MS_IGNORE_IGNORE = 'Ignore/Ignore'; + + { + wParam : HCONTACT + lParam : IGNOREEVENT_* + Affects: Receive future messages from a contact -- of the given type, see notes + Returns: 0 on success, non zero on failure + Notes : Use NULL(0) for HCONTACT to retrieve the setting for an unknown contact + Version: v0.1.0.1+ + } + MS_IGNORE_UNIGNORE = 'Ignore/Unignore'; + +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_langpack.inc b/plugins/Chess4Net/MI/MirandaINC/m_langpack.inc new file mode 100644 index 0000000000..2c1f99478c --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_langpack.inc @@ -0,0 +1,82 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_LANGPACK} +{$DEFINE M_LANGPACK} + +const + + { + wParam : 0 + lParam : pointer to a null terminated string + Affects: Returns a pointer to a localised string, if there is no known + translation it will return lParam, the return value does *not* + have to be freed in anyway (if successful) -- see notes + Returns: a pointer to a null terminated string + Notes : No check is done to see if Miranda has the required version + Version: v0.1.1.0+ + } + MS_LANGPACK_TRANSLATESTRING = 'LangPack/TranslateString'; + + { + wParam : 0 + lParam : Pointer to a LANGPACKTRANSLATEDIALOG initialised structure, see notes + Affects: Translates a dialog into the user's local language + Returns: 0 on successs [non zero] on failure + Notes : this service only knows about the following window classes/elements: + Window titles, STATIC, EDIT, Hyperlink, BUTTON. + Version: v0.1.1.0+ + } + +type + + PLANGPACKTRANSLATEDIALOG = ^TLANGPACKTRANSLATEDIALOG; + TLANGPACKTRANSLATEDIALOG = record + cbSize: int; + flags: DWORD; + hwndDlg: THandle; + ignoreControls: ^Integer; // pointer to an array of integers? mebbe? + end; + +const + + { translate all edit controls, by default non-read-only edit controls are not } + LPTDF_NOIGNOREEDIT = 1; + { don't translate the title of the dialog } + LPTDF_NOTITLE = 2; + + MS_LANGPACK_TRANSLATEDIALOG = 'LangPack/TranslateDialog'; + + { + wParam : HMENU handle (WinAPI handle to a menu) + lParam : 0 + Affects: Translates a menu into the user's local language -- see notes + Returns: 0 on success [non zero] on failure + Notes : This doesn't work with owner draw menus that store their + captions in a structure known by the owner -- something to be aware of ;) + version: v0.1.1.0+ + } + MS_LANGPACK_TRANSLATEMENU = 'LangPack/TranslateMenu'; + +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_message.inc b/plugins/Chess4Net/MI/MirandaINC/m_message.inc new file mode 100644 index 0000000000..dec113bb53 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_message.inc @@ -0,0 +1,57 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_MESSAGE} +{$DEFINE M_MESSAGE} + +const + + { + wParam : HCONTACT + lParam : Pointer to a null terminated string + Affects: brings up the send message dialog for a contact, see notes + Returns: 0 on success, non zero on failure + Notes : returns immediately, just after the send dialog is shown, + the lParam is entered into the editbox of the window, + but it's not sent. + Version: v0.1.2.0+ only supports a string, prior NULL(0) is expected + this service was defined as 'SRMsg/LaunchMessageWindow' + use both if compatibility use both, the correct one will work, + but don't rely on the message to be displayed + + } + MS_MSG_SENDMESSAGE = 'SRMsg/SendCommand'; + MS_MSG_SENDMESSAGE_OLD = 'SRMsg/LaunchMessageWindow'; + + { + wParam : 0 + lParam : Pointer to a null termed string + Affects: displays the send message dialog with the 'multiple' option open + and no contacts selected + Returns: Returns 0 on success, nonzero on failure + Version: only present after v0.1.2.1+ + } + MS_MSG_FORWARDMESSAGE = 'SRMsg/ForwardMessage'; + +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_netlib.inc b/plugins/Chess4Net/MI/MirandaINC/m_netlib.inc new file mode 100644 index 0000000000..8c5f37ef9c --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_netlib.inc @@ -0,0 +1,713 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_NETLIB} +{$DEFINE M_NETLIB} + +{>>/ + + NetLib : + + Instead of you writing all the code for working with sockets and supporting + app level protocols such as SOCKS5, it's all done for you. + + NetLib takes care of all that and you can even register a special abstract + nexus, e.g. ICQ direct, the user can configure all this from the options dialog + and you don't have to bother with any of it. + + NetLib wraps up any Winsock calls but you can still get the socket handle + from your netlib handle and do stuff. + + It gives all modules an abstract way of dealing with transport -- mainly sockets + and proxies, Now the but.. + + It's new (mmmm) thus unsupported by any older version of Miranda, and if you + want to be lazy and not write any "wrapper" mini netlib then you'll have + the kudos of "only works with nightly build version of Miranda" :) + +/<<} + + {$ifndef M_SYSTEM} + {$include m_system.inc} + {$endif} + +const + + // for TNETLIBUSER.flags + + { bind incoming ports } + NUF_INCOMING = $01; + { makes outgoing plain connections } + NUF_OUTGOING = $02; + { can use HTTP gateway for plain sockets. ???HttpGateway* are valid, + enables the HTTP proxy option, displayed in options } + NUF_HTTPGATEWAY = $04; + { don't show this as an entry for custom settings to be defined for, + TNETLIB.szDescriptiveName is ignored } + NUF_NOOPTIONS = $08; + { some connections are made for HTTP communication, + enables the HTTP proxy option, displayed in options } + NUF_HTTPCONNS = $10; + { Disables the HTTPS proxy option in options, Use this if all communication + is HTTP } + NUF_NOHTTPSOPTION = $20; + + // for TNETLIBUSERSETTINGS.proxyType + + { SOCKS4 -- No DNS or multi addressing mode (proxy side) -- optional username can + be given, no password } + PROXYTYPE_SOCKS4 = 1; + { SOCKS5 -- DNS names can be given as addresses to connect to, optional + plain text username/password scheme (which may cause failure due to denied access) + IP address maybe returned for DNS addresses -- thus server side DNS } + PROXYTYPE_SOCKS5 = 2; + PROXYTYPE_HTTP = 3; + PROXYTYPE_HTTPS = 4; + + // for TNETLIBOPENCONNECTION.flags + + { this connection will be useed for HTTP communications, + if configured for an HTTP(S) proxy the connection is opened as if there + was no proxy } + + NLOCF_HTTP = $0001; + + // for TNETLIBHTTPPROXYINFO.flags + + { append sequence numbers to GET requests } + NLHPIF_USEGETSEQUENCE = $0001; + { append sequence numbers to POST requests } + NLHPIF_USEPOSTSEQUENCE = $0002; + { GET and POST use the same sequence } + NLHPIF_GETPOSTSAMESEQUENCE = $0004; + + // for TNETLIBHTTPREQUEST.flags, .requestType + + { used by MS_NETLIB_RECVHTTPHEADERS returned structure } + + REQUEST_RESPONSE = 0; + REQUEST_GET = 1; + REQUEST_POST = 2; + REQUEST_CONNECT = 3; + + { auto generate a 'host' header from .szUrl } + NLHRF_GENERATEHOST = $00000001; + { remove any host and/or protocol portion of szUrl before sending it } + NLHRF_REMOVEHOST = $00000002; + { removes host and/or protocol from szUrl unless the connection was + opened through an HTTP or HTTPS proxy. } + NLHRF_SMARTREMOVEHOST = $00000004; + { if the connection was opened through an HTTP or HTTPS proxy then + send a Proxy-Authorization header if required. } + NLHRF_SMARTAUTHHEADER = $00000008; + { never dump this to the log } + NLHRF_NODUMP = $00010000; + { don't dump http headers (only useful for POSTs and MS_NETLIB_HTTPTRANSACTION } + NLHRF_NODUMPHEADERS = $00020000; + { this transaction is a proxy communication. For dump filtering only. } + NLHRF_DUMPPROXY = $00040000; + { dump posted and reply data as text. Headers are always dumped as text. } + NLHRF_DUMPASTEXT = $00080000; + + // for TNETLIBBUFFER.flags + + { don't wrap outgoing packet using TNETLIBUSER.pfnHttpGatewayWrapSend } + MSG_NOHTTPGATEWAYWRAP = $010000; + { don't dump this packet to the log } + MSG_NODUMP = $020000; + { this iss proxy communication, for dump filtering only } + MSG_DUMPPROXY = $040000; + { don't dump as hex, it's text } + MSG_DUMPASTEXT = $080000; + { send as raw, bybpass HTTP proxy stuff } + MSG_RAW = $100000; + + + // all record types structures are declared in their own block because the C header + // file used forward declaration (to get typed parameters for certain function pointers) + // This sort of define-type-pointer-before-type can only be done in the same type block + // in D2 (don't know about later versions) + +type + + { forward typed pointers to records } + + PNETLIBOPENCONNECTION = ^TNETLIBOPENCONNECTION; + PNETLIBHTTPREQUEST = ^TNETLIBHTTPREQUEST; + + { This function pointer is to the CRT realloc() used by Miranda -- it allows reallocation of memory passed + to us (not that we could EVER share the same CRT) but to allow DLLs in general to reallocate memory } + TNetlibRealloc = function(Mem: Pointer; size_t: int): Pointer; cdecl; + TNetlibHTTPGatewayInitProc = function(hConn: THandle; nloc: PNETLIBOPENCONNECTION; nlhr: PNETLIBHTTPREQUEST): int; cdecl; + TNetlibHTTPGatewayBeginProc = function(hConn: THandle; nloc: PNETLIBOPENCONNECTION): int; cdecl; + TNetlibHTTPGatewayWrapSendProc = function(hConn: THandle; buf: PByte; len: int; flags: int; pfnNetLibSend: TMIRANDASERVICE): int; cdecl; + TNetlibHTTPGatewayUnwrapRecvProc = function(nlhr: PNETLIBHTTPREQUEST; buf: PByte; len: int; outBufLen: pInt; NetlibRealloc: TNetlibRealloc): PByte; cdecl; + + PNETLIBUSER = ^TNETLIBUSER; + TNETLIBUSER = record + cbSize: int; + { used for DB settings and log, 'NL' stuff } + szSettingsModule: PChar; + { shows a descriptive name for which different proxy settings can be defined } + szDescriptiveName: PChar; + { see NUF_* constants above } + flags: DWORD; + szHttpGatewayHello: PChar; + { can be NULL(0) to send no User-Agent: also used by HTTPS proxies } + szHttpGatewayUserAgent: PChar; + pfnHttpGatewayInit: TNetlibHTTPGatewayInitProc; + { can be NULL(0) if no begin is required } + pfnHttpGatewayBegin: TNetlibHTTPGatewayBeginProc; + { can be NULL(0) if no wrapping is required } + pfnHttpGatewayWrapSend: TNetlibHTTPGatewayWrapSendProc; + { can be NULL(0) " " } + pfnHttpGatewayUnwrapRecv: TNetlibHTTPGatewayUnwrapRecvProc; + { only if NUF_INCOMING, will be used for validation of user input } + minIncomingPorts: int; + end; + + PNETLIBUSERSETTINGS = ^TNETLIBUSERSETTINGS; + TNETLIBUSERSETTINGS = record + { filled before calling } + cbSize: int; + { 1 or 0 } + useProxy: int; + { PROXYTYPE_* constant, see above } + proxyType: int; + { can be NULL(0) } + szProxyServer: PChar; + { in host byte order } + wProxyPort: int; + { 1 or 0, always 0 for SOCKS4 (doesn't have auth) } + useProxyAuth: int; + { can be NULL(0), always used by SOCKS4 } + szProxyAuthUser: PChar; + { can be NULL(0) } + szProxyAuthPassword: PChar; + { 1 or 0, only used by HTTP, HTTPS } + useProxyAuthNtlm: int; + { 1 or 0 } + dnsThroughProxy: int; + { 1 or 0 } + specifyIncomingPorts: int; + { can be NULL(0), form '1024-1050,1060-1070,2000' } + szIncomingPorts: PChar; + end; + + TNetlibNewConnectionProc = procedure(hNewConnection: THandle; dwRemoveIP: DWORD); cdecl; + + PNETLIBBIND = ^TNETLIBBIND; + TNETLIBBIND = record + cbSize: int; + { function to call when there's a new connection, dwRemoteIP is in host byte + order -- the handle is to the new connection } + pfnNewConnection: TNetlibNewConnectionProc; + { set on return, host byte order } + dwInternalIP: DWORD; + { set on return, host byte order } + wPort: WORD; + end; + + { Pointered type is above } + TNETLIBOPENCONNECTION = record + cbSize: int; + szHost: PChar; // can be an IP in string form + wPort: Word; + flags: DWORD; // see NLOCF_* flags + end; + + PNETLIBHTTPPROXYINFO = ^TNETLIBHTTPPROXYINFO; + TNETLIBHTTPPROXYINFO = record + cbSize: int; + { see NLHPIF_* above } + flags: DWORD; + szHttpPostUrl: PChar; + szHttpGetUrl: PChar; + firstGetSequence: int; + firstPostSequence: int; + end; + + PNETLIBBASE64 = ^TNETLIBBASE64; + TNETLIBBASE64 = record + pszEncoded: PChar; + cchEncoded: int; + pbDecoded: PByte; + cbDecoded: int; + end; + + PNETLIBHTTPHEADER = ^TNETLIBHTTPHEADER; + TNETLIBHTTPHEADER = record + szName: PChar; + szValue: PChar; + end; + + { PNETLIBHTTPREQUEST = ^TNETLIBHTTPREQUEST, defined above because this is + forward referenced from there } + TNETLIBHTTPREQUEST = record + cbSize: int; + requestType: int; // REQUEST_* constant + flags: DWORD; + szUrl: PChar; + { doesn't contain Content-Length, it'll be added automatically } + headers: PNETLIBHTTPHEADER; // pointer to an array of em? + headersCount: int; // yes they do + pData: PChar; // data to be sent on POST request + dataLength: int; // must be 0 for REQUEST_GET/REQUEST_CONNECT + resultCode: int; + szResultDescr: PChar; + end; + + PNETLIBBUFFER = ^TNETLIBBUFFER; + TNETLIBBUFFER = record + buf: PChar; + len: int; + { see MSG_* constants above } + flags: int; + end; + + PNETLIBSELECT = ^TNETLIBSELECT; + TNETLIBSELECT = record + cbSize: int; + dwTimeout: DWORD; // in milliseconds, INFINITE is acceptable + hReadConns: array[0..64+1] of THandle; + hWriteConns: array[0..64+1] of THandle; + hExceptConns: array[0..64+1] of THandle; + end; + + PNETLIBPACKETRECVER = ^TNETLIBPACKETRECVER; + TNETLIBPACKETRECVER = record + cbSize: int; + { infinite is allowed -- initialise before use } + dwTimeout: DWORD; + { this many bytes are removed from the start of the buffer, + set to 0 on return -- initialise before use } + bytesUsed: int; + { equal the returnd value by service, unless the return value is 0 (connection closed) } + bytesAvailable: int; + { same as the parameter given to MS_NETLIB_CREATEPACKETRECVER: wParam } + bufferSize: int; + { contains the read data } + buffer: PByte; + end; + +const + + { + wParam : 0 + lParam : Pointer to an initalised TNETLIBUSER structure + Affects: Initialises the netlib for a set of connections, see notes + Returns: Returns a handle for future netlib calls, NULL on failure. + Notes : Netlib is loaded AFTER all plugins, thus a call to this service + in Load() will fail, hook ME_SYSTEM_MODULESLOADED and call it + from there. + - + Netlib will save settings under .szSettings module, all settings + (being?) begin with 'NL'. + - + Defacto settings are the same as combobox entry option + as seen in Miranda->Options->Network + Version: v0.1.2.2+ + Errors : ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY, ERROR_DUP_NAME + } + MS_NETLIB_REGISTERUSER = 'Netlib/RegisterUser'; + + { + wParam : HANDLE + lParam : Pointer to a initalised TNETLIBUSERSETTINGS structure + Affects: Gets the user configured settings for a Netlib user, see notes + Returns: [non zero] on SUCCESS, NULL(0) on failure + Notes : .cbSize must be filled with sizeof() before calling -- + the returned null terminated strings (in the structure) are valid + as long as HANDLE remains open or proxy options are changed + again, do not rely on them being around forever. + Version: v0.1.2.2+ + Errors : ERROR_INVALID_PARAMETER + } + MS_NETLIB_GETUSERSETTINGS = 'Netlib/GetUserSettings'; + + { + wParam : HANDLE + lParam : Pointer to a initalised NETLIBUSERSETTINGS structure + Affect : Changes the configurable settings for a Netlib user -- see notes + Returns: [non zero] on success, NULL(0) on failure + Notes : This service is only really useful for people that specify NUF_NOOPTIONS + when registering and want to create their own options. + Settings will be stored even if the option to enable it, is it not enabled, + e.g. useProxyAuth is 0, szProxyAuthPassword will still be saved + Errors : ERROR_INVALID_PARAMETER + } + MS_NETLIB_SETUSERSETTINGS = 'Netlib/SetUserSettings'; + + { + wParam : HANDLE / SOCKET + lParam : 0 + Affects: Closes a handle, see notes + Returns: Returns [non zero] on success, NULL(0) on failure + Notes : All netlib handles should be closed once they're finished with, + If a SOCKET type is passed instead of netlib handle type, it is closed + Errors : ERROR_INVALID_PARAMETER + } + MS_NETLIB_CLOSEHANDLE = 'Netlib/CloseHandle'; + + { + wParam : HANDLE + lParam : Pointer to a initialised TNETLIBBIND + Affects: Open a port and wait for connections on it -- see notes + Returns: Returns a handle on success, NULL(0) on failure + Notes : this function does the equivalent of socket(), bind(), getsockname(), + listen(), accept() -- internally this function creates a new thread + which waits around in accept() for new connections. + When one is received, TNETLIBBIND.pfnNewConnection is called, + from the context of the NEW thread and then it + returns to waiting for connections. + - + Close the returned handle to end the thread and close the port. + - + Errors : ERROR_INVALID_PARAMETER, any returned by socket(), bind(), listen() + getsockname() + } + MS_NETLIB_BINDPORT = 'Netlib/BindPort'; + + { + wParam : HANDLE + lParam : Pointer to an initalised TNETLIBOPENCONNECTION structure + Affects: Opens a connection -- see notes + Returns: Returns a Handle to a new connection on success, NULL(0) on failure + Notes : internally this service is the equivalent of socket(), gethostbyname(), + connect() + - + If NLOCF_HTTP is set and HANDLE is configured for HTTP(S) proxy + then this function will connect() to that proxy server ONLY, + without performing any initialisation conversation. + - + If HANDLE is configured for an HTTP proxy and does not support + HTTP gateways and you try to open a connection without NLOCF_HTTP + then this service will first attempt to open an HTTPS connection, + if that fails, it will try a direct connection, if *that* fails + then it will return failure with the error + from connect() during the connection attempt + Errors : ERROR_INVALID_PARAMETER, any returned by socket(), gethostbyname(), + connect(), MS_NETLIB_SEND, MS_NETLIB_RECV, select() + - + ERROR_TIMEOUT (during proxy communication) + ERROR_BAD_FORMAT (very invalid proxy reply) + ERROR_ACCESS_DENIED (by proxy) + ERROR_CONNECTION_UNAVAIL (socks proxy can't connect to identd) + ERROR_INVALID_ACCESS (proxy refused identd auth) + ERROR_INVALID_DATA (proxy returned invalid code) + ERROR_INVALID_ID_AUTHORITY (proxy requires use of auth method that's not supported) + ERROR_GEN_FAILURE (socks5/https general failure) + ERROR_CALL_NOT_IMPLEMENTED (socks5 command not supported) + ERROR_INVALID_ADDRESS (socks5 address type not supported) + - + HTTP: anything from TNETLIBUSER.pfnHttpGatewayInit, TNETLIBUSER.pfnHttpGatewayBegin, + MS_NETLIB_SENDHTTPREQUEST or MS_NETLIB_RECVHTTPHEADERS + } + MS_NETLIB_OPENCONNECTION = 'Netlib/OpenConnection'; + + { + wParam : HANDLE + lParam : Pointer to an initialised NETLIBHTTPPROXYINFO structure + Affects: Sets the required information for an HTTP proxy connection -- see notes + Returns: [non zero] on success, NULL(0) on failure + Notes : This service is designed to be called from + within TNETLIBUSER.pfnHttpGatewayInit (see notes in C header under + MS_NETLIB_REGISTERUSER) + Errors : ERROR_INVALID_PARAMETER + } + MS_NETLIB_SETHTTPPROXYINFO = 'Netlib/SetHttpProxyInfo'; + + { + wParam : HANDLE + lParam : 0 + Affects: Get's the SOCKET associated with a handle -- see notes + Returns: the SOCKET on success, INVALID_SOCKET on failure + Notes : The Netlib handle passed to this service should only be passed + if they were returned with MS_NETLIB_OPENCONNECTION or MS_NETLIB_BINDPORT + - + Be careful how you use this socket because you might be connected via an + HTTP proxy, in which case calling send/recv() will break things + - + Errors : ERROR_INVALID_PARAMETER + } + MS_NETLIB_GETSOCKET = 'Netlib/GetSocket'; + + { + wParam : 0 + lParam : Pointer to a null terminated string + Affects: URL-encodes a string for x-www-form-urlencoded (and other uses) -- see notes + Returns: A pointer to a null terminated string, NULL(0) on failure + Notes : The returned string must be freed after it's no longer needed, + to do this Miranda's process heap must be used (under the WINAPI), e.g. + HeapFree(GetProcessHeap(), 0, the_returned_string) + Errors : ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY + } + MS_NETLIB_URLENCODE = 'Netlib/UrlEncode'; + + { + wParam : 0 + lParam : Pointer to a TNETLIBBASE64 initialised structure + Affects: Decodes a Base64 null terminated string, see notes + Returns: [non zero] on success, NULL(0) on failure + Notes : TNETLIBBASE64.pszEncoded and cchEncoded must contain a pointer to + a buffer to use as input, and it's length, the length + should not include space taken for null termination -- + - + Output is placed in ..pbDecoded and ..cbDecoded for buffer and + length of buffer -- the maxiumum output for a given input can + be worked out with Netlib_GetBase64DecodedBufferSize() function + see below. + - + For more information on Base64 see rfc-1421. + Errors : ERROR_INVALID_PARAMETER, ERROR_INVALID_DATA, ERROR_BUFFER_OVERFLOW + } + MS_NETLIB_BASE64DECODE = 'Netlib/Base64Decode'; + + { + wParam : 0 + lParam : Pointer to an initialised TNETLIBBASE64 structure + Affect : Base64 encode a string, see notes + Returns: [non zero] on success, NULL(0) on failure + Notes : TNETLIBBASE64.pbDecode and TNETLIBBASE64.cbDecoded contain + the input buffer and it's length -- + TNETLIBBASE64.pszEncoded and TNETLIBBASE64.cchEncoded contain the + buffer in which to put the output and it's length. + - + The maximum output size for a given input can be worked + out with the function Netlib_GetBase64EncodedBufferSize() below + .pszEncoded is null terminated, on return TNETLIBBASE64.cchEncoded + is set to the actual length excluding 0. + Errors : ERROR_INVALID_PARAMETER, ERROR_BUFFER_OVERFLOW + } + MS_NETLIB_BASE64ENCODE = 'Netlib/Base64Encode'; + + { + wParam : HANDLE + lParam : Pointer to a initialised TNETLIBHTTPREQUEST structure + Affect : Send an HTTP request over a connection, see notes + Returns: The number of bytes on success, SOCKET_ERROR on failure + Notes : HANDLE must of been returned by MS_NETLIB_OPENCONNECTION,, + If you use NLHRF_SMARTAUTHHEADER and NTLM auth is in use then + full NTLM auth transcation occurs, comprising sending the + domain, getting the challenge, sending the response. + NETLIBHTTPREQUEST.resultCode and NETLIBHTTPREQUEST.szResultDescr are + ignored by this service. + Errors : ERROR_INVALID_PARAMETER, MS_NETLIB_SEND (return codes) + } + MS_NETLIB_SENDHTTPREQUEST = 'Netlib/SendHttpRequest'; + + { + wParam : HANDLE + lParam : 0 + Affect : Receive HTTP headers, see notes + Returns: A pointer to a TNETLIBHTTPREQUEST structure on success, NULL(0) on failure + Notes : The returned pointer must be freed after it's done with + use MS_NETLIB_FREEHTTPREQUESTSTRUCT. + - + HANDLE must be returned by MS_NETLIB_OPENCONNECTION + - + Return^.pData=NIL and Return^.dataLength=0 always + - + The returned data should be retrieved using MS_NETLIB_RECV once + the headers have been parsed. + If headers haven't finished within 60 seconds the function returns + NULL(0) and ERROR_TIMEOUT + Errors : ERROR_INVALID_PARAMETER, any MS_NETLIB_RECV or select() + ERROR_HANDLE_EOF (connection closed bfore headers complete) + ERROR_TIMEOUT (headers still not complete after 60 seconds) + ERROR_BAD_FORMAT (invalid character or line ending in headers, or first line is blank) + ERROR_BUFFER_OVERFLOW (each header line must be less than 4096 chars long) + ERROR_INVALID_DATA (first header line is malformed ("http/[01].[0-9] [0-9]+ .*", or no colon in subsequent line) + + } + MS_NETLIB_RECVHTTPHEADERS = 'Netlib/RecvHttpHeaders'; + + { + wParam : 0 + lParam : Pointer returned by MS_NETLIB_RECVHTTPHEADERS to free + Affect : Free the memory used by a TNETLIBHTTPREQUEST structure, see notes + Returns: [non zero] on success, NULL(0) on failure + Notes : This service should only be used with memory pointers returned + by either MS_NETLIB_RECVHTTPHEADERS or MS_NETLIB_HTTPTRANSACTION!. + Errors : ERROR_INVALID_PARAMETER + + } + MS_NETLIB_FREEHTTPREQUESTSTRUCT = 'Netlib/FreeHttpRequestStruct'; + + { + wParam : HANDLE + lParam : Pointer to a TNETLIBHTTPREQUEST structure + Affect : Carry out an entire HTTP transaction, see notes + Returns: another pointer to a TNETLIBHTTPREQUEST structure or NULL(0) + on failure + Notes : The returned pointer must be freed at some point + with MS_NETLIB_FREEHTTPREQUESTSTRUCT, + - + TNETLIBHTTPREQUEST.szUrl should have a full HTTP URL, if it + does not start with http://, that will be assumed, but do not + take this assumption to stay assumed (heh..) in the future + - + this service equivalent of open(), sendhttp(), getheaders() + netlib_recv(), netlib_closehandle() + - + TNETLIBHTTPREQUEST.headers will be added to with the following + headers if they're not already present : + "Host" (even if it is requested in .flags) + "User-Agent" (in form : 'Miranda/d.d.d.d <(status of release)>') + "Content-Length" (for POSTs only, set to TNETLIBHTTPREQUEST.dataLength) + + If you don't want to send any of these headers -- + set TNETLIBHTTPREQUEST.headers to NULL(0) + - + In the returned pointer, pData[dataLen] is always 0 for 'safety' + also : headers, headersCount, pData, dataLength, resultCode and + szResultDescr are all valid + - + Also take care not to assume that a returned pointer means that + at the HTTP level it all worked out -- refer to the resultCode for + 2xx before doing anything else + - + Errors : ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY + Errors returned by the aforementioned internally used functions + } + MS_NETLIB_HTTPTRANSACTION = 'Netlib/HttpTransaction'; + + { + wParam : HANDLE + lParam : Pointer to an initialised TNETLIBBUFFER structure + Affect : Send data over an open connection see notes + Returns: The number of bytes sent on success, SOCKET_ERROR on failure + Notes : see Netlib_Send() helper function + Errors : ERROR_INVALID_PARAMETER, + anything from socket(), connect() + send(), TNETLIBUSER.pfnHttpGatewayWrapSend(), + (HTTP proxy): ERROR_GEN_FAILURE (http result code wasn't 2xx) + MS_NETLIB_SENDHTTPREQUEST, MS_NETLIB_RECVHTTPHEADERS + } + MS_NETLIB_SEND = 'Netlib/Send'; + + { + wParam : HANDLE + lParam : Pointer to an initialised TNETLIBBUFFER structure + Affect : Receive data over a connection, see notes + Returns: The number of bytes read on success, SOCKET_ERROR on failure + Notes : + This service uses some of the same flags as MS_NETLIB_SEND : + MSG_PEEK, + MSG_NODUMP, + MSG_DUMPPROXY, + MSG_NOHTTPGATEWAYWRAP, + MSG_DUMPASTEXT, + MSG_RAW + - + On using MSG_NOHTTPGATEWAYWRAP: Because packets through an HTTP proxy are + batched and cached and stuff, using this flag is not a guarantee that it + will be obeyed, and if it is it may even be propogated to future calls + even if you don't specify it then. Because of this, the flag should be + considered an all-or-nothing thing: either use it for the entire duration + of a connection, or not at all. + Errors : ERROR_INVALID_PARAMETER, anything from recv() + (HTTP proxy): + ERROR_GEN_FAILURE (http result code wasn't 2xx) + ERROR_INVALID_DATA (no Content-Length header in reply) + ERROR_NOT_ENOUGH_MEMORY (Content-Length very large) + ERROR_HANDLE_EOF (connection closed before Content-Length bytes recved) + anything from select(), + MS_NETLIB_RECVHTTPHEADERS, nlu.pfnHttpGatewayUnwrapRecv, socket(), + connect(), MS_NETLIB_SENDHTTPREQUEST + + } + MS_NETLIB_RECV = 'Netlib/Recv'; + + { + wParam : 0 + lParam : Pointer to an initialised TNETLIBSELECT structure + Affect : Determine the status of one or more connections, see notes + Returns: The numbe of ready connections, SOCKET_ERROR on failure + Notes : All handles passed to this service must have been returned + either by MS_NETLIB_OPENCONNECTION or MS_NETLIB_BINDPORT, + the last handle in each list must be followed by either NULL + or INVALID_HANDLE_VALUE. + Errors : ERROR_INVALID_HANDLE, ERROR_INVALID_DATA, anything from select() + } + MS_NETLIB_SELECT = 'Netlib/Select'; + + { + wParam : HANDLE + lParam : maxPacketSize + Affect : Create a packet receiver, see notes + Returns: A handle on success, NULL(0) on failure + Notes : The packet receiver implements the common situation where + you have a variable length of packets coming thru over a connection + and you want them split up in order to handle them. + - + The major limiation is, that the buffer is created in memory, + so you can't have arbitrarily large packets + Errors : ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY + } + MS_NETLIB_CREATEPACKETRECVER = 'Netlib/CreatePacketRecver'; + + { + wParam : Handle returned by MS_NETLIB_CREATEPACKETRECVER + lParam : Pointer to an initialised TNETLIBPACKETRECVER + Returns: The total number of bytes available in the buffer, NULL(0) + if the connection was closed or SOCKET_ERROR. + - + If TNETLIBPACKETRECVER.bytesUsed is set to zero and the + buffer is already full up to the maxPacketSize, it is assumed + that a too large packet has been received, All data in + the buffer is discarded and receiving has started anew. + - + This will probably cause alignment problem so if you think + that tis iss likely to happen, then you should deal with it + yourself. + - + Closing the packet receiver will not close the associated + connection but will discard any bytes still in the buffer, + so if you intend to carry on reading from that connection, + make sure you have processed the buffer first. + - + This service is equivalent of memmove() to remove + the first bytesUsed from the buffer, select(), if dwTimeOut + is not INFINITE, then MS_NETLIB_RECV + Errors : ERROR_INVALID_PARAMETER, ERROR_TIMEOUT, anything from select(), + MS_NETLIB_RECV + } + MS_NETLIB_GETMOREPACKETS = 'Netlib/GetMorePackets'; + + { + wParam : HANDLE + lParam : Pointer to null terminated string to uh, log. + Affect : Add a message to the log (if it's running) see notes + Returns: non zeror on success, NULL(0) on failure + Notes : Don't include \r\n or #13#10 it's not needed, + - + Doesn't support formatting like the given C code for + Netlib_Logf, just use FmtStr() and then call this service + if you want that. + Errors : ERROR_INVALID_PARAMETER + } + MS_NETLIB_LOG = 'Netlib/Log'; + +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_options.inc b/plugins/Chess4Net/MI/MirandaINC/m_options.inc new file mode 100644 index 0000000000..23d891a81c --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_options.inc @@ -0,0 +1,109 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_OPTIONS} +{$DEFINE M_OPTIONS} + +const + + { + wParam : addinfo + lParam : 0 + Affects: The user opened the options dialog, see notes + Notes : Modules should do whatever initalisation they need and call + MS_OPT_ADDPAGE with the wParam -- MS_OPT_ADDPAGE + can be called one or more times + if more than one page wants to be displayed. + } + ME_OPT_INITIALISE = 'Opt/Initialise'; + + { + wParam : wParam from ME_OPT_INITIALISE + lParam : Pointer to an initialised TOPTIONSDIALOGPAGE + Affects: Adds a page to the options dialog, see notes + Notes : Strings in the structure can be released as soon as the + service returns -- but icons must be kept around, this iss + not a problem if you're loading theem from a resource. + - + This service should only be called within the ME_OPT_INITIALISE + event hook. + - + Pages in the options dialog operate just like pages in property + sheets, See the WinAPI documentation for details on how they operate. + Version: Prior to v0.1.2.1 the options dialog would resize + to fit the largest page, but since then it's a fixed size + The largest page that fits neatly is 314x240 DLU's + - + Some of OPTIONSDIALOGPAGE's fields are version dependant. + } + MS_OPT_ADDPAGE = 'Opt/AddPage'; + + { defacto size } + + OPTIONSDIALOGPAGE_V0100_SIZE = $18; + OPTIONSDIALOGPAGE_V0120_SIZE = $28; + + { page is only shown when in 'simple' mode } + ODPF_SIMPLEONLY = 1; + { page is only shown when in 'expert' mode } + ODPF_EXPERTONLY = 2; + { give group box titles a bold font } + ODPF_BOLDGROUPS = 4; + +type + + POPTIONSDIALOGPAGE = ^TOPTIONSDIALOGPAGE; + TOPTIONSDIALOGPAGE = record + cbSize: int; + position: int; // position number, lower numbers are top most + pszTitle: PChar; + pfnDlgProc: Pointer; // DLGPROC prototype + pszTemplate: PChar; + hInstance: THandle; + hIcon: THandle; // v0.1.0.1+ + pszGroup: PChar; // v0.1.0.1+ + groupPosition: int; // v0.1.0.1+ + hGroupIcon: THandle; // v0.1.0.1+ + flags: DWORD; // v0.1.2.1+ + { if in simple mode the dialog will be cut off AFTER this control ID, 0 + for disable } + nIDBottomSimpleControl: int; // v0.1.2.1+ + { if in simple mode the dialog will cut off AFTER this control ID, 0 to disable } + nIDRightSimpleControl: int; // v0.1.2.1+ + { these controls will be hidden in simple mode, pointer to an array of ID's + must remain valid for the duration of the dialog } + expertOnlyControls: ^int; + nExpertOnlyControls: int; // v0.1.2.1+ + end; + +const + + { sent to pages via WM_NOTIFY when the expert checkbox is clicked, lParam = new state } + PSN_EXPERTCHANGED = 2; + { returns true/false } + PSM_ISEXPERT = ($0400 + 101); + { returns HFONT used for group box titles } + PSM_GETBOLDFONT = ($0400 + 102); + +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_plugins.inc b/plugins/Chess4Net/MI/MirandaINC/m_plugins.inc new file mode 100644 index 0000000000..689b7a39e7 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_plugins.inc @@ -0,0 +1,70 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_PLUGINS} +{$DEFINE M_PLUGINS} + +const + + DEFMOD_PROTOCOLICQ = 1; // removed from v0.3.0.0 alpha + DEFMOD_PROTOCOLMSN = 2; // removed from v0.1.2.0+ + DEFMOD_UIFINDADD = 3; + DEFMOD_UIUSERINFO = 4; + DEFMOD_SRMESSAGE = 5; + DEFMOD_SRURL = 6; + DEFMOD_SREMAIL = 7; + DEFMOD_SRAUTH = 8; + DEFMOD_SRFILE = 9; + DEFMOD_UIHELP = 10; + DEFMOD_UIHISTORY = 11; + DEFMOD_RNDCHECKUPD = 12; + DEFMOD_RNDICQIMPORT = 13; // not built in to v0.1.0.1+ + DEFMOD_RNDAUTOAWAY = 14; + DEFMOD_RNDUSERONLINE = 15; + DEFMOD_RNDCRYPT = 16; // v0.1.0.1-v0.1.2.0 + DEFMOD_SRAWAY = 17; // v0.1.0.1+ + DEFMOD_RNDIGNORE = 18; // v0.1.0.1+ + DEFMOD_UIVISIBILITY = 19; // v0.1.1.0+, options page only + DEFMOD_UICLUI = 20; // v0.1.1.0+ + DEFMOD_UIPLUGINOPTS = 21; // v0.1.2.1+ + DEFMOD_PROTOCOLNETLIB = 22; // v0.1.2.2+ + + DEFMOD_HIGHEST = 22; + + + + { + wParam : 0 + lParam : 0 + Affect : Gets an array of modules that the plugins report they want to replace + Returns: Returns a pointer to an array of ints, with elements 1 or 0, + indexed by the DEFMOD_* constants, 1 is to mark that the default + module shouldn't be loaded, see notes + Notes : this is primarily for use by the core's module initialiser, + but could also be used by modules that are doing + naughty things that are very feature-dependent. + } + MS_PLUGINS_GETDISABLEDEFAULTARRAY = 'Plugins/GetDisableDefaultArray'; + +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_popup.inc b/plugins/Chess4Net/MI/MirandaINC/m_popup.inc new file mode 100644 index 0000000000..f8d2ea9df9 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_popup.inc @@ -0,0 +1,222 @@ +(* +=============================================================================== + PopUp plugin +Plugin Name: PopUp +Plugin author: hrk, Luca Santarelli, hrk@users.sourceforge.net +This file has been created by egodust, Sam, egodust@users.sourceforge.net +=============================================================================== + +The purpose of this plugin is to give developers a common "platform/interface" to show PopUps. It is born from the source code of NewStatusNotify, another plugin I've made. + +Remember that users *must* have this plugin enabled, or they won't get any popup. Write this in the requirements, do whatever you wish ;-)... but tell them! +=============================================================================== + +-- To use this file you need Windows.pas, m_globaldefs.pas (get it from the CVS under the 'inc' module) +-- To include this in the source, use {$include m_popup.h} + +*) + +{$ifndef M_POPUP_H} +{$define M_POPUP_H} + +{$ifdef FPC} + {$PACKRECORDS C} + {$MODE Delphi} +{$endif} + +const + + MAX_CONTACTNAME = 2048; + MAX_SECONDLINE = 2048; + + SM_WARNING = $01; //Triangle icon. + SM_NOTIFY = $02; //Exclamation mark icon. + +type + + // for info on what this stuff is, see m_popup.h + + PPOPUPDATA = ^TPOPUPDATA; + TPOPUPDATA = record + lchContact: HCONTACT; + lchIcon: THandle; + lpszContactName: array[0..MAX_CONTACTNAME-1] of Char; + lpszText: array[0..MAX_SECONDLINE-1] of Char; + colorBack: COLORREF; + colorForeText: COLORREF; + PluginWindowProc: Pointer; // must be a window procedure using stdcall + PluginData: Pointer; + end; + +type + + // for info on what this stuff is, see m_popup.h + + PPOPUPDATAEX = ^TPOPUPDATAEX; + TPOPUPDATAEX = record + lchContact: HCONTACT; + lchIcon: THandle; + lpszContactName: array[0..MAX_CONTACTNAME-1] of Char; + lpszText: array[0..MAX_SECONDLINE-1] of Char; + colorBack: COLORREF; + colorForeText: COLORREF; + PluginWindowProc: Pointer; // must be a window procedure using stdcall + PluginData: Pointer; + iSeconds: int; //Custom delay time in seconds. -1 means "forever", 0 means "default time". + cZero: array[0..15] of Char; //16 unused bytes which may come useful in the future. + end; + +const + +(* + Creates, adds and shows a popup, given a (valid) POPUPDATA structure pointer. + wParam = (WPARAM)(*POPUPDATA)PopUpDataAddress + lParam = 0 + Returns: > 0 on success, 0 if creation went bad, -1 if the PopUpData contained unacceptable values. + NOTE: it returns -1 if the PopUpData was not valid, if there were already too many popups, if the module was disabled. + Otherwise, it can return anything else... +*) + + MS_POPUP_ADDPOPUP = 'PopUp/AddPopUp'; + +(* + The same, but with a POPUPDATAEX structure pointer. + wParam = (WPARAM)(*POPUPDATAEX)PopUpDataExAddress + lParam = 0 +*) + + MS_POPUP_ADDPOPUPEX = 'PopUp/AddPopUpEx'; + +(* + Returns the handle to the contact associated to the specified PopUpWindow. + You will probably need to know this handle inside your WNDPROC. Exampole: you want to open the MessageWindow. :-) + Call MS_POPUP_GETCONTACT on the hWnd you were given in the WNDPROC. + wParam = (WPARAM)(HWND)hPopUpWindow + lParam = 0; + Returns: the HANDLE of the contact. Can return NULL, meaning it's the main contact. -1 means failure. +*) + + MS_POPUP_GETCONTACT = 'PopUp/GetContact'; + +(* + wParam = hPopUpWindow + lParam = PluginDataAddress; + Returns: the address of the PLUGINDATA structure. Can return NULL, meaning nothing was given. -1 means failure. + IMPORTANT NOTE: it doesn't seem to work if you do: + CallService(..., (LPARAM)aPointerToAStruct); + and then use that struct. + Do this, instead: + aPointerToStruct = CallService(..., (LPARAM)aPointerToAStruct); + and it will work. Just look at the example I've written above (PopUpDlgProc). +*) + MS_POPUP_GETPLUGINDATA = 'PopUp/GetPluginData'; + +(* + wParam = 0 + lParam = 0 + Returns: 0 if the user has chosen not to have the second line, 1 if he choose to have the second line. +*) + MS_POPUP_ISSECONDLINESHOWN = 'PopUp/IsSecondLineShown'; + +(* + UM_FREEPLUGINDATA + wParam = lParam = 0. Process this message if you have allocated your own memory. (i.e.: POPUPDATA.PluginData != NULL) +*) + UM_FREEPLUGINDATA = ((*WM_USER*)$400 + $200); + +(* + UM_DESTROYPOPUP + wParam = lParam = 0. Send this message when you want to destroy the popup, or use the function below. +*) + UM_DESTROYPOPUP = ((*WM_USER*)$400 + $201); + +(* + UM_INITPOPUP + wParam = (WPARAM)(HWND)hPopUpWindow (but this is useless, since I'll directly send it to your hPopUpWindow + lParam = 0. + This message is sent to the PopUp when its creation has been finished, so POPUPDATA (and thus your PluginData) is reachable. + Catch it if you needed to catch WM_CREATE or WM_INITDIALOG, which you'll never ever get in your entire popup-life. + Return value: if you process this message, return 0. If you don't process it, return 0. Do whatever you like ;-) +*) + UM_INITPOPUP = ($400(*WM_USER*) + $202); + +(* + wParam = hPopUpWindow + lParam = lpzNewText + returns: > 0 for success, -1 for failure, 0 if the failure is due to second line not being shown. (but you could call PUIsSecondLineShown() before changing the text...) + Changes the text displayed in the second line of the popup. +*) + MS_POPUP_CHANGETEXT = 'PopUp/Changetext'; + +(* + This is mainly for developers. + Shows a warning message in a PopUp. It's useful if you need a "MessageBox" like function, but you don't want a modal window (which will interfere with a DialogProcedure. MessageBox steals focus and control, this one not. + wParam = lpzMessage + lParam = 0; Returns: 0 if the popup was shown, -1 in case of failure. +*) + MS_POPUP_SHOWMESSAGE = 'PopUp/ShowMessage'; + + + (* helper functions, will be inlined on FPC if you have the swithces enabled *) + + function PUAddPopup(ppdp: PPOPUPDATA): int; + {$ifdef FPC} + inline; + {$endif} + begin + Result := CallService(MS_POPUP_ADDPOPUP, WPARAM(ppdp), 0); + end; + + function PUGetContact(hPopUpWindow: THandle): THandle; + {$ifdef FPC} + inline; + {$endif} + begin + Result := CallService(MS_POPUP_GETCONTACT, WPARAM(hPopUpWindow), 0); + end; + + function PUGetPluginData(hPopUpWindow: THandle): Pointer; + {$ifdef FPC} + inline; + {$endif} + var + dummy: pointer; + begin + dummy := nil; + Int(Result) := CallService(MS_POPUP_GETPLUGINDATA, WPARAM(hPopUpWindow), LPARAM(dummy)); + end; + + function PUIsSecondLineShown: BOOL; + {$ifdef FPC} + inline; + {$endif} + begin + Int(Result) := CallService(MS_POPUP_ISSECONDLINESHOWN, 0, 0); + end; + + function PUDeletePopUp(hWndPopUp: THandle): int; + {$ifdef FPC} + inline; + {$endif} + begin + Result := SendMessage(hWndPopUp, UM_DESTROYPOPUP, 0, 0); + end; + + function PUChangeText(hWndPopUp: THandle; lpzNewText: PChar): int; + {$ifdef FPC} + inline; + {$endif} + begin + Result := CallService(MS_POPUP_CHANGETEXT, WPARAM(hWndPopUp), LPARAM(lpzNewText)); + end; + + function PUShowMessage(lpzText: PChar; kind: Byte): int; + {$ifdef FPC} + inline; + {$endif} + begin + Result := CallService(MS_POPUP_SHOWMESSAGE, WPARAM(lpzText), LPARAM(kind)); + end; + +{$endif} + diff --git a/plugins/Chess4Net/MI/MirandaINC/m_protocols.inc b/plugins/Chess4Net/MI/MirandaINC/m_protocols.inc new file mode 100644 index 0000000000..f198d40a8b --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_protocols.inc @@ -0,0 +1,180 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_PROTOCOLS} +{$DEFINE M_PROTOCOLS} + +const + + ACKTYPE_MESSAGE = 0; + ACKTYPE_URL = 1; + ACKTYPE_FILE = 2; + ACKTYPE_CHAT = 3; + ACKTYPE_AWAYMSG = 4; + ACKTYPE_AUTHREQ = 5; + ACKTYPE_ADDED = 6; + ACKTYPE_GETINFO = 7; + ACKTYPE_SETINFO = 8; + ACKTYPE_LOGIN = 9; + ACKTYPE_SEARCH = 10; + ACKTYPE_NEWUSER = 11; + ACKTYPE_STATUS = 12; + ACKTYPE_CONTACTS = 13; //send/recv of contacts + + ACKRESULT_SUCCESS = 0; + ACKRESULT_FAILED = 1; + //'in progress' result codes: + ACKRESULT_CONNECTING = 100; + ACKRESULT_CONNECTED = 101; + ACKRESULT_INITIALISING = 102; + ACKRESULT_SENTREQUEST = 103; // waiting for reply... + ACKRESULT_DATA = 104; // blob of file data sent/recved, or search result + ACKRESULT_NEXTFILE = 105; // file transfer went to next file + ACKRESULT_FILERESUME = 106; // a file is about to be received, see PS_FILERESUME + ACKRESULT_DENIED = 107; // a file send has been denied (0.3a + only) + + // for PROTOCOLDESCRIPTOR.type + + PROTOTYPE_PROTOCOL = 1000; + PROTOTYPE_ENCRYPTION = 2000; + PROTOTYPE_FILTER = 3000; + PROTOTYPE_TRANSLATION = 4000; + PROTOTYPE_OTHER = 10000;//avoid using this if at all possible + +type + + PCCSDATA = ^TCCSDATA; + TCCSDATA = record + hContact: THandle; + szProtoService: PChar; // a PS_* constant + wParam: WPARAM; + lParam: LPARAM; + end; + + PACKDATA = ^TACKDATA; + TACKDATA = record + cbSize: int; + szModule: PChar; // the name of the protocol module which initiated this ack + hContact: THandle; + type_: int; // an ACKTYPE_* constant + result_: int; // an ACKRESULT_* constant + hProcess: THandle; // caller defined seq, I mean process code + lParam: LPARAM; // caller defined data + end; + + // when type=ACKTYPE_FILE and (result=ACKRESULT_DATA or result=ACKRESULT_FILERESUME) + + PPROTOFILETRANSFERSTATUS = ^TPROTOFILETRANSFERSTATUS; + TPROTOFILETRANSFERSTATUS = record + cbSize: int; + hContact: THandle; + sending: int; // true if sending, false if receiving + files: PChar; // pointer to an array of pchar's + totalFiles: int; + currentFileNumber: int; + totalBytes: LongInt; + totalProgress: LongInt; + workingDir: PChar; + currentFile: PChar; + currentFileSize: LongInt; + currentFileProgress: LongInt; + currentFileTime: LongInt; // UNIX time + end; + + // for registering a protocol, enumeration + + PPROTOCOLDESCRIPTOR = ^TPROTOCOLDESCRIPTOR; + TPROTOCOLDESCRIPTOR = record + cbSize: int; + szName: PChar; // unique name of module + type_: int; // a PROTOTYPE_* constant + end; + +const + + { + wParam : 0 + lParam : Pointer to an initalised CSSDATA structure + Affect : Send a general request thru the protocol chain for a contact + Return : the return value documented in the PS_* def (m_protosvc.inc) + } + MS_PROTO_CALLCONTACTSERVICE = 'Proto/CallContactService'; + + { + wParam : 0 + lParam : Pointer to an initalised TACKDATA structure + Affect : a general 'ack', see notes + Notes : Just because defs are here doesn't mean they will be sent + read the docs for the function you are calling to see what + replies you will get. + } + ME_PROTO_ACK = 'Proto/Ack'; + + { + wParam : pointer to an int to store number of protocols + lParam : Pointer to an an array of PPROTOCOLDESCRIPTOR pointers + Affect : Enumerate the currently running protocols, see notes + Returns: 0 on success, [non zero] on failure + Notes : Neither wParam/lParam maybe NULL(0), the list returned by + this service is the protocol modules currently installed + and running, it is not a complete list of protocols that have + ever been installed. + - + A protocol module does not have to be a protocol running thru + the internet, it can be a vast number of things + } + MS_PROTO_ENUMPROTOCOLS = 'Proto/EnumProtocols'; + + { + wParam : 0 + lParam : Pointer to null terminated string containing protocol name + Affect : Determines if a protocol is running or not. + Returns: A pointer to the PPROTOCOLDESCRIPTOR if the protocol is loaded + or NULL(0) if it isn't + } + MS_PROTO_ISPROTOCOLLOADED = 'Proto/IsProtocolLoaded'; + + { + wParam : HCONTACT + lParam : Pointer to a null terminated string containing a name + Affect : Determine whether the given contact has the given protocol + in it's chain. + Returns : 0 if the protocol isn't in the chain, [non zero] if it is + } + MS_PROTO_ISPROTOONCONTACT = 'Proto/IsProtoOnContact'; + + { + wParam : HCONTACT + lParam : 0 + Affect : Gets the network-level protocol associated with a contact + Returns: a PChar pointing to the ASCIIZ name of the protocol or NULL(0) + if the contact has no protocol, There's no need to dispsose + the returned string. + - + This is the name of the module that actually accesses the network + for that contact. + } + MS_PROTO_GETCONTACTBASEPROTO = 'Proto/GetContactBaseProto'; + +{$ENDIF} \ No newline at end of file diff --git a/plugins/Chess4Net/MI/MirandaINC/m_protomod.inc b/plugins/Chess4Net/MI/MirandaINC/m_protomod.inc new file mode 100644 index 0000000000..312e0de687 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_protomod.inc @@ -0,0 +1,105 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_PROTOMOD} +{$DEFINE M_PROTOMOD} + + {$ifndef M_PROTOCOLS} + {$include m_protocols.inc} + {$endif} + +const + + { + wParam : 0 + lParam : Pointer to a initalised TPROTOCOLDESCRIPTOR structure + Affect : Register a protocol module, see notes + Returns: 0 on success, [non zero] on failure + Notes : This service MUST be called from your module's Load() function + TPROTOCOLDESCRIPTOR.type can be a value other than PROTOTYPE_* + which are used to provide a more precise positioning information + for the contact protocol lists. + - + Relative values to the constants can be given, but this MUST NOT + be done for PROTOTYPE_PROTOCOL. + } + MS_PROTO_REGISTERMODULE = 'Proto/RegisterModule'; + + { + wParam : HCONTACT + lParam : protocol_name_string + Affect : Add the given protocol module to the chain for a contact, see notes + Returns: 0 success, [non zero] on failure + Notes : The module is added to the correct positioning according to it's + registered type. + } + MS_PROTO_ADDTOCONTACT = 'Proto/AddToContact'; + + { + wParam : HCONTACT + lParam : protocol_name_string + Affect : Remove the given protocol name from the chain for the given contact + Returns: 0 on success, [non zero] on failure + } + MS_PROTO_REMOVEFROMCONTACT = 'Proto/RemoveFromContact'; + + { see m_helpers.inc for CreateProtoServiceFunction } + + { + wParam : wParam [arg] + lParam : lParam [arg] + Affect : Call the next service in the chain for the send operation, see notes + Return : Return value should be returned by CallService(MS_PROTO_CHAINSEND,wParam,lParam) + Notes : wParam MUST remain untouched, lParam is a pointer to a CCSDATA structure + and can be modified or copid if needed. + wParam and lParam should be the values passed to your service, + typically your service should return ASAP. + } + MS_PROTO_CHAINSEND = 'Proto/ChainSend'; + + { + wParam : wParam [arg] + lParam : lParam [arg] + Affect : Call the next service in the chain in this receive operation, see notes + Return : Return value should be returned by CallService(MS_PROTO_CHAINRECV,wParam,lParam) + Notes : wParam MUST remain untouched, lParam is a pointer to a CCSDATA structure + and can be modified or copied if needed. + wParam and lParam should be the values passed to your service, + typically your service should return ASAP. + - + MS_PROTO_CHAINRECV is thread safe since 0.1.2.0 -- calls + are translated to the main thread and passed from there. + } + MS_PROTO_CHAINRECV = 'Proto/ChainRecv'; + + { + wParam : 0 + lParam : Pointer to an initalised ACKDATA + Affect : Broadcast a ME_PROTO_ACK event, see notes + Returns: The return value of the NotifyEventHooks() call + Notes : ME_PROTO_ACK is completely thread safe since 01.2.0 + see notes in core/modules.h under NotifyEventHooks() + } + MS_PROTO_BROADCASTACK = 'Proto/BroadcastAck'; +{$ENDIF} diff --git a/plugins/Chess4Net/MI/MirandaINC/m_protosvc.inc b/plugins/Chess4Net/MI/MirandaINC/m_protosvc.inc new file mode 100644 index 0000000000..0b52f04600 --- /dev/null +++ b/plugins/Chess4Net/MI/MirandaINC/m_protosvc.inc @@ -0,0 +1,753 @@ +(* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*) + +{$IFNDEF M_PROTOSVC} +{$DEFINE M_PROTOSVC} + +{<>} + +const + + PFLAGNUM_1 = $1; + PF1_IMSEND = $00000001; // supports IM sending + PF1_IMRECV = $00000002; // supports IM receiving + PF1_IM = (PF1_IMSEND or PF1_IMRECV); + PF1_URLSEND = $00000004; // supports separate URL sending + PF1_URLRECV = $00000008; // supports separate URL receiving + PF1_URL = (PF1_URLSEND or PF1_URLRECV); + PF1_FILESEND = $00000010; // supports file sending + PF1_FILERECV = $00000020; // supports file receiving + PF1_FILE = (PF1_FILESEND or PF1_FILERECV); + PF1_MODEMSGSEND = $00000040; // supports broadcasting away messages + PF1_MODEMSGRECV = $00000080; // supports reading others' away messages + PF1_MODEMSG = (PF1_MODEMSGSEND or PF1_MODEMSGRECV); + PF1_SERVERCLIST = $00000100; // contact lists are stored on the server, not locally. See notes below + PF1_AUTHREQ = $00000200; // will get authorisation requests for some or all contacts + PF1_ADDED = $00000400; // will get 'you were added' notifications + PF1_VISLIST = $00000800; // has an invisible list + PF1_INVISLIST = $00001000; // has a visible list for when in invisible mode + PF1_INDIVSTATUS = $00002000; // supports setting different status modes to each contact + PF1_EXTENSIBLE = $00004000; // the protocol is extensible and supports plugin-defined messages + PF1_PEER2PEER = $00008000; // supports direct (not server mediated) communication between clients + PF1_NEWUSER = $00010000; // supports creation of new user IDs + PF1_CHAT = $00020000; // has a realtime chat capability + PF1_INDIVMODEMSG = $00040000; // supports replying to a mode message request with different text depending on the contact requesting + PF1_BASICSEARCH = $00080000; // supports a basic user searching facility + PF1_EXTSEARCH = $00100000; // supports one or more protocol-specific extended search schemes + PF1_CANRENAMEFILE = $00200000; // supports renaming of incoming files as they are transferred + PF1_FILERESUME = $00400000; // can resume broken file transfers, see PS_FILERESUME below + PF1_ADDSEARCHRES = $00800000; // can add search results to the contact list + PF1_CONTACTSEND = $01000000; // can send contacts to other users + PF1_CONTACTRECV = $02000000; // can receive contacts from other users + PF1_CONTACT = (PF1_CONTACTSEND or PF1_CONTACTRECV); + PF1_CHANGEINFO = $04000000; // can change our user information stored on server + PF1_SEARCHBYEMAIL = $08000000; // supports a search by e-mail feature + PF1_USERIDISEMAIL = $10000000; // set if the uniquely identifying field of the network is the e-mail address + PF1_SEARCHBYNAME = $20000000; // supports searching by nick/first/last names + PF1_EXTSEARCHUI = $40000000; // has a dialog box to allow searching all the possible fields + PF1_NUMERICUSERID = $80000000; // the unique user IDs for this protocol are numeric + + PFLAGNUM_2 = 2; // the status modes that the protocol supports + PF2_ONLINE = $00000001; // an unadorned online mode + PF2_INVISIBLE = $00000002; + PF2_SHORTAWAY = $00000004; // Away on ICQ, BRB on MSN + PF2_LONGAWAY = $00000008; // NA on ICQ, Away on MSN + PF2_LIGHTDND = $00000010; // Occupied on ICQ, Busy on MSN + PF2_HEAVYDND = $00000020; // DND on ICQ + PF2_FREECHAT = $00000040; + PF2_OUTTOLUNCH = $00000080; + PF2_ONTHEPHONE = $00000100; + + PFLAGNUM_3 = 3; //the status modes that the protocol supports + //away-style messages for. Uses the PF2_ flags. + PFLAG_UNIQUEIDTEXT = 100; //returns a static buffer of text describing the unique field by which this protocol identifies users (already translated), or NULL + + PFLAG_MAXCONTACTSPERPACKET = 200; //v0.1.2.2+: returns the maximum number of contacts which can be sent in a single PSS_CONTACTS. + + PFLAGNUM_4 = 4; // v0.3+: flag asking a protocol plugin how auths are handled + PF4_FORCEAUTH = $00000001; // protocol has to send auth's for things to work + PF4_FORCEADDED = $00000002; // protocol has to tell people that they were added (otherwise things don't work) + PF4_NOCUSTOMAUTH = $00000004; // protocol can't send a custom message while asking others for auth + + PFLAG_UNIQUEIDSETTING = 300; // v0.3+: returns the DB setting name (e.g. szProto=ICQ, szSetting=UIN) that has the ID which makes this user unique on that system (0.3a ONLY), the string is statically allocated so no need to free() + + // for PS_SETSTATUS + + LOGINERR_WRONGPASSWORD = 1; + LOGINERR_NONETWORK = 2; + LOGINERR_PROXYFAILURE = 3; + LOGINERR_BADUSERID = 4; + LOGINERR_NOSERVER = 5; + LOGINERR_TIMEOUT = 6; + LOGINERR_WRONGPROTOCOL = 7; + + // flag for PS_ADDTOLIST + + PALF_TEMPORARY = 1; // add the contact temporarily and invisibly, just to get user info or something + + // flags for PS_GETINFO + + SGIF_MINIMAL = 1; // get only the most basic information. This should + // contain at least a Nick and e-mail. + + // for PSR_MESSAGE + + PREF_CREATEREAD = 1; // create the database event with the 'read' flag set + + // for PS_FILERESUME + + FILERESUME_OVERWRITE= 1; + FILERESUME_RESUME = 2; + FILERESUME_RENAME = 3; + FILERESUME_SKIP = 4; + +type + + PPROTOSEARCHRESULT = ^TPROTOSEARCHRESULT; + TPROTOSEARCHRESULT = record + cbSize: int; + nick: PChar; + firstName: PChar; + lastName: PChar; + email: PChar; + reserved: array [0..15] of Byte; + // Protocols may extend this structure with extra members at will and supply + // a larger cbSize to reflect the new information, but they must not change + // any elements above this comment + // The 'reserved' field is part of the basic structure, not space to + // overwrite with protocol-specific information. + // If modules do this, they should take steps to ensure that information + // they put there will be retained by anyone trying to save this structure. + end; + + PPROTOSEARCHBYNAME = ^TPROTOSEARCHBYNAME; + TPROTOSEARCHBYNAME = record + pszNick: PChar; + pszFirstName: PChar; + pszLastName: PChar; + end; + + PPROTORECVEVENT = ^TPROTORECVEVENT; + TPROTORECVEVENT = record + flags: DWORD; + timestamp: DWORD; + szMessage: PChar; + lParam: LPARAM; + end; + + PPROTORECVFILE = ^TPROTORECVFILE; + TPROTORECVFILE = record + flags: DWORD; + timestamp: DWORD; // unix time + szDescription: PChar; + pFiles: PChar; // pointer to an array of pchar's + lParam: LPARAM; + end; + + PPROTOFILERESUME = ^TPROTOFILERESUME; + TPROTOFILERESUME = record + action: int; // FILERESUME_* flag + szFilename: PChar; // full path, only valid if action=FILERESUME_RENAME + end; + +const + + { + wParam : PFLAGNUM_* (see above) + lParam : 0 + Affects: Returns a bitfield for settings corresponding to flag number, see notes + Returns: a bitfield of supported features -- or 0 if flag_num is not supported + Notes : this checks what sort of things are actively supported by a protocol + module + } + PS_GETCAPS = '/GetCaps'; + + { + wParam : cchName + lParam : Pointer to a buffer to fill with human-readable name + Affect : Get a human-readable name for the protocol, see notes + Result : 0 on success, [non zero] on failure + Notes : Should be translated before being returned, cchName + has the size of the buffer, example strings: "ICQ", "AIM" + } + PS_GETNAME = '/GetName'; + + { + wParam : whichIcon + lParam : 0 + Affect : Loads one of the protocol-sspecific icons + Returns: the HICON or NULL on failure, the returned icon + must be DestroyIcon()ed, the UI should overlay + the online icon with further UI-specified icon to + repressent the exact status mode. + } + PLI_PROTOCOL = $1; // An icon representing the protocol (eg the multicoloured flower for ICQ) + PLI_ONLINE = $2; // Online state icon for that protocol (eg green flower for ICQ) + PLI_OFFLINE = $3; // Offline state icon for that protocol (eg red flower for ICQ) + PLIF_LARGE = $0; // Or with one of the above to get the large (32x32 by default) icon + PLIF_SMALL = $10000; // Or with one of the above to get the small (16x16 by default) icon + + PS_LOADICON = '/LoadIcon'; + + { + wParam : status_mode + lParam : Pointer to a null terminated string containing message + Affect : Sets the status mode specific message for the user, see notes + Returns: 0 on success, [non zero] on failure + Notes : This service is not available unless PF1_MODEMSGSEND is set, + and PF1_INDIVMODEMSG is *not* set. + If PF1_INDIVMODEMSG is set, then see PSS_AWAYMSSG for details + of operations of away messages. + - + Protocol modules smust support lParam=NULL, it may eithere mean + to use an empty message or (preferably) not to reply at all to + any requests. + } + PS_SETAWAYMSG = '/SetAwayMsg'; + + { + wParam : newMode from statusmodes.inc + lParam : 0 + Affect : Change the protocol's status mode, see notes + Returns: 0 on success, [non zero] on failure + Notes : Will send an ack with : + type=ACKTYPE_SUCCESS, result=ACKRESULT_SUCCESS, hProcess=previousMode, lParam=newMode + - + when the change completes. This ack is sent for all changes, not + just ones caused by calling this function. + - + NewMode can be ID_STATUS_CONNECTING<=newMode