From 864081102a5f252415f41950b3039a896b4ae9c5 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Mon, 8 Oct 2012 18:43:29 +0000 Subject: Awkwars's plugins - welcome to our trunk git-svn-id: http://svn.miranda-ng.org/main/trunk@1822 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/QuickSearch/ico/default.ico | Bin 0 -> 2550 bytes plugins/QuickSearch/ico/delete.ico | Bin 0 -> 1406 bytes plugins/QuickSearch/ico/down.ico | Bin 0 -> 2550 bytes plugins/QuickSearch/ico/female.ico | Bin 0 -> 2550 bytes plugins/QuickSearch/ico/item.ico | Bin 0 -> 1406 bytes plugins/QuickSearch/ico/male.ico | Bin 0 -> 2550 bytes plugins/QuickSearch/ico/new.ico | Bin 0 -> 1406 bytes plugins/QuickSearch/ico/qs.ico | Bin 0 -> 1406 bytes plugins/QuickSearch/ico/reload.ico | Bin 0 -> 2550 bytes plugins/QuickSearch/ico/up.ico | Bin 0 -> 2550 bytes plugins/QuickSearch/make.bat | 17 + plugins/QuickSearch/qs.rc | 178 ++ plugins/QuickSearch/qs.res | Bin 0 -> 26276 bytes plugins/QuickSearch/quicksearch.dpr | 244 +++ plugins/QuickSearch/quicksearch_history.txt | 110 + plugins/QuickSearch/resource.inc | 76 + plugins/QuickSearch/sr_frame.pas | 343 ++++ plugins/QuickSearch/sr_global.pas | 750 +++++++ plugins/QuickSearch/sr_optdialog.pas | 1041 ++++++++++ plugins/QuickSearch/sr_window.pas | 2943 +++++++++++++++++++++++++++ 20 files changed, 5702 insertions(+) create mode 100644 plugins/QuickSearch/ico/default.ico create mode 100644 plugins/QuickSearch/ico/delete.ico create mode 100644 plugins/QuickSearch/ico/down.ico create mode 100644 plugins/QuickSearch/ico/female.ico create mode 100644 plugins/QuickSearch/ico/item.ico create mode 100644 plugins/QuickSearch/ico/male.ico create mode 100644 plugins/QuickSearch/ico/new.ico create mode 100644 plugins/QuickSearch/ico/qs.ico create mode 100644 plugins/QuickSearch/ico/reload.ico create mode 100644 plugins/QuickSearch/ico/up.ico create mode 100644 plugins/QuickSearch/make.bat create mode 100644 plugins/QuickSearch/qs.rc create mode 100644 plugins/QuickSearch/qs.res create mode 100644 plugins/QuickSearch/quicksearch.dpr create mode 100644 plugins/QuickSearch/quicksearch_history.txt create mode 100644 plugins/QuickSearch/resource.inc create mode 100644 plugins/QuickSearch/sr_frame.pas create mode 100644 plugins/QuickSearch/sr_global.pas create mode 100644 plugins/QuickSearch/sr_optdialog.pas create mode 100644 plugins/QuickSearch/sr_window.pas (limited to 'plugins/QuickSearch') diff --git a/plugins/QuickSearch/ico/default.ico b/plugins/QuickSearch/ico/default.ico new file mode 100644 index 0000000000..4cd27f0623 Binary files /dev/null and b/plugins/QuickSearch/ico/default.ico differ diff --git a/plugins/QuickSearch/ico/delete.ico b/plugins/QuickSearch/ico/delete.ico new file mode 100644 index 0000000000..07fee6c512 Binary files /dev/null and b/plugins/QuickSearch/ico/delete.ico differ diff --git a/plugins/QuickSearch/ico/down.ico b/plugins/QuickSearch/ico/down.ico new file mode 100644 index 0000000000..d4fdb83bbf Binary files /dev/null and b/plugins/QuickSearch/ico/down.ico differ diff --git a/plugins/QuickSearch/ico/female.ico b/plugins/QuickSearch/ico/female.ico new file mode 100644 index 0000000000..fe1cbd2bce Binary files /dev/null and b/plugins/QuickSearch/ico/female.ico differ diff --git a/plugins/QuickSearch/ico/item.ico b/plugins/QuickSearch/ico/item.ico new file mode 100644 index 0000000000..80c3802c09 Binary files /dev/null and b/plugins/QuickSearch/ico/item.ico differ diff --git a/plugins/QuickSearch/ico/male.ico b/plugins/QuickSearch/ico/male.ico new file mode 100644 index 0000000000..ebd0420554 Binary files /dev/null and b/plugins/QuickSearch/ico/male.ico differ diff --git a/plugins/QuickSearch/ico/new.ico b/plugins/QuickSearch/ico/new.ico new file mode 100644 index 0000000000..ac80adb26e Binary files /dev/null and b/plugins/QuickSearch/ico/new.ico differ diff --git a/plugins/QuickSearch/ico/qs.ico b/plugins/QuickSearch/ico/qs.ico new file mode 100644 index 0000000000..415a0bccd7 Binary files /dev/null and b/plugins/QuickSearch/ico/qs.ico differ diff --git a/plugins/QuickSearch/ico/reload.ico b/plugins/QuickSearch/ico/reload.ico new file mode 100644 index 0000000000..dc070c5083 Binary files /dev/null and b/plugins/QuickSearch/ico/reload.ico differ diff --git a/plugins/QuickSearch/ico/up.ico b/plugins/QuickSearch/ico/up.ico new file mode 100644 index 0000000000..56fde31eda Binary files /dev/null and b/plugins/QuickSearch/ico/up.ico differ diff --git a/plugins/QuickSearch/make.bat b/plugins/QuickSearch/make.bat new file mode 100644 index 0000000000..36de9c338c --- /dev/null +++ b/plugins/QuickSearch/make.bat @@ -0,0 +1,17 @@ +@echo off +set myopts=-dMiranda +set dprname=quicksearch.dpr + +..\delphi\brcc32.exe qs.rc -foqs.res + +if /i '%1' == 'fpc' ( + ..\FPC\bin\fpc.exe %myopts% %dprname% %2 %3 %4 %5 %6 %7 %8 %9 +) else if /i '%1' == 'fpc64' ( + ..\FPC\bin64\ppcrossx64.exe %myopts% %dprname% %2 %3 %4 %5 %6 %7 %8 %9 +) else if /i '%1' == 'xe2' ( + ..\XE2\BIN\dcc32.exe %myopts% %dprname% %2 %3 %4 %5 %6 %7 %8 %9 +) else if /i '%1' == 'xe64' ( + ..\XE2\BIN\dcc64.exe %myopts% %dprname% %2 %3 %4 %5 %6 %7 %8 %9 +) else ( + ..\delphi\dcc32 %myopts% %dprname% %1 %2 %3 %4 %5 %6 %7 %8 %9 +) diff --git a/plugins/QuickSearch/qs.rc b/plugins/QuickSearch/qs.rc new file mode 100644 index 0000000000..d22a32c57d --- /dev/null +++ b/plugins/QuickSearch/qs.rc @@ -0,0 +1,178 @@ +#include "resource.inc" + +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +IDD_FRAME DIALOGEX 0, 0, 114, 16, 0 +STYLE DS_SETFONT | WS_CHILD | DS_FIXEDSYS | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + PUSHBUTTON "*", IDC_FRAME_OPEN, 2, 2, 12, 12 + EDITTEXT IDC_FRAME_EDIT, 16, 2, 62, 12 + PUSHBUTTON "<", IDC_FRAME_PREV, 80, 2, 15, 12 + PUSHBUTTON ">", IDC_FRAME_NEXT, 97, 2, 15, 12 +} + +IDD_SCRIPT DIALOGEX 0, 0, 256, 82, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_VISIBLE | WS_THICKFRAME +CAPTION "Script Editor" +//EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + EDITTEXT IDC_EDIT_SCRIPT , 4, 4, 248, 56, + ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL + PUSHBUTTON "&OK" , IDOK , 106, 64, 46, 14 + PUSHBUTTON "&Help" , IDHELP , 156, 64, 46, 14 + PUSHBUTTON "C&ancel", IDCANCEL , 206, 64, 46, 14 +} + +IDD_DIALOG1 DIALOGEX 40, 40, 314, 240 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_BORDER +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "Ms Shell Dlg",0,0 +{ + CONTROL "New" ,IDC_NEW ,"MButtonClass",WS_TABSTOP,216, 46,16,16,$18000000 + CONTROL "Save" ,IDC_SETITEM,"MButtonClass",WS_TABSTOP,216, 64,16,16,$18000000 + CONTROL "Up" ,IDC_UP ,"MButtonClass",WS_TABSTOP,216, 82,16,16,$18000000 + CONTROL "Down" ,IDC_DN ,"MButtonClass",WS_TABSTOP,216,100,16,16,$18000000 + CONTROL "Delete" ,IDC_DELETE ,"MButtonClass",WS_TABSTOP,216,118,16,16,$18000000 + CONTROL "Default",IDC_DEFAULT,"MButtonClass",WS_TABSTOP,216,136,16,16,$18000000 + CONTROL "Reload" ,IDC_RELOAD ,"MButtonClass",WS_TABSTOP,216, 2,16,16,$18000000 + + CONTROL "List2",IDC_LIST,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | + WS_BORDER | WS_TABSTOP,0,2,213,150 + + CTEXT "Settings",-1 ,234, 2,77,12, SS_CENTERIMAGE + CONTROL "", -1, "STATIC", SS_ETCHEDHORZ, 234, 14, 77, 2 + + LTEXT "Title:",-1 ,236, 16,75,12, SS_CENTERIMAGE + EDITTEXT IDC_E_TITLE ,234, 28,77,14, ES_AUTOHSCROLL | WS_TABSTOP + + LTEXT "Type:",-1 ,236, 44,75,12, SS_CENTERIMAGE + COMBOBOX IDC_C_VARTYPE ,234, 56,77,110, CBS_DROPDOWNLIST | + CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + + LTEXT "InfoType:",IDC_STAT_VARTYPE,236, 72,75,12, SS_CENTERIMAGE + COMBOBOX IDC_C_CNFTYPE ,234, 84,77,150, CBS_DROPDOWNLIST | + CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_C_RESULT ,234, 84,77,80, CBS_DROPDOWNLIST | + CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Script",IDC_SCRIPT, 234, 84, 77, 12 + + LTEXT "Service:",IDC_STAT_SERVICE ,236,100,75,12, SS_CENTERIMAGE + LTEXT "Module:" ,IDC_STAT_MODULE ,236,100,75,12, SS_CENTERIMAGE + EDITTEXT IDC_E_MODULE ,234,112,77,14, ES_AUTOHSCROLL | WS_TABSTOP + + LTEXT "wParam:",IDC_STAT_WPAR ,236,128,75,12, SS_CENTERIMAGE + LTEXT "Setting:",IDC_STAT_SETTING ,236,128,75,12, SS_CENTERIMAGE + EDITTEXT IDC_E_VAR ,234,140,77,14, ES_AUTOHSCROLL | WS_TABSTOP + + LTEXT "wParam type:",-1,236,156,75,12, SS_CENTERIMAGE + COMBOBOX IDC_C_WPAR ,234,168,77,80, CBS_DROPDOWNLIST | + CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + + LTEXT "lParam:",-1,236,184,75,12, SS_CENTERIMAGE + EDITTEXT IDC_E_LPAR ,234,196,77,14, ES_AUTOHSCROLL | WS_TABSTOP + + LTEXT "lParam type:",-1 ,236,212,75,12, SS_CENTERIMAGE + COMBOBOX IDC_C_LPAR ,234,224,77,80, CBS_DROPDOWNLIST | + CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + + CONTROL "Sort by Status",IDC_CH_SORTSTATUS,"Button", + BS_MULTILINE | BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,5,166,109,10 + CONTROL "Only Users in List",IDC_CH_SHOWONLYUSERS,"Button", + BS_MULTILINE | BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,5,178,109,10 + CONTROL "Auto Close mode",IDC_CH_AUTOCLOSE,"Button", + BS_MULTILINE | BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,5,190,109,10 + CONTROL "Draw Grid",IDC_CH_DRAWGRID,"Button", + BS_MULTILINE | BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,5,202,109,10 + CONTROL "Show Client Icons",IDC_CH_SHOWCLIENTICONS,"Button", + BS_MULTILINE | BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,5,214,109,10 + CONTROL "Save search pattern",IDC_CH_SAVEPATTERN,"Button", + BS_MULTILINE | BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,5,226,109,10 + GROUPBOX "",-1,0,154,116,84 + + CONTROL "Item in Main Menu",IDC_CH_SHOWINMENU,"Button", + BS_MULTILINE | BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,121,166,109,10 + CONTROL "Button on TopToolBar",IDC_CH_ADDTOTOPTOOLBAR,"Button", + BS_MULTILINE | BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,121,178,109,10 + CONTROL "Tool Window Style",IDC_CH_USETOOLSTYLE,"Button", + BS_MULTILINE | BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,121,190,109,10 + CONTROL "Copy line to CSV",IDC_CH_SINGLECSV,"Button", + BS_MULTILINE | BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,121,202,109,10 + CONTROL "CSV with headers",IDC_CH_EXPORTHEADERS,"Button", + BS_MULTILINE | BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,121,214,109,10 + CONTROL "Skip minimized columns",IDC_CH_SKIPMINIMIZED,"Button", + BS_MULTILINE | BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,121,226,109,10 + GROUPBOX "",-1,118,154,114,84 + GROUPBOX "Additional Options",-1,0,154,232,84 +} + +IDI_QS ICON DISCARDABLE "ico\qs.ico" + +IDI_NEW ICON DISCARDABLE "ico\new.ico" +IDI_ITEM ICON DISCARDABLE "ico\item.ico" +IDI_UP ICON DISCARDABLE "ico\up.ico" +IDI_DOWN ICON DISCARDABLE "ico\down.ico" +IDI_DELETE ICON DISCARDABLE "ico\delete.ico" +IDI_DEFAULT ICON DISCARDABLE "ico\default.ico" +IDI_RELOAD ICON DISCARDABLE "ico\reload.ico" + +IDI_MALE ICON DISCARDABLE "ico\male.ico" +IDI_FEMALE ICON DISCARDABLE "ico\female.ico" + +IDD_MAIN DIALOGEX 40, 40, 520, 240 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CAPTION | WS_VISIBLE | WS_BORDER | WS_SYSMENU | + WS_DLGFRAME | WS_OVERLAPPED | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "Ms Shell Dlg",0,0 +{ + EDITTEXT IDC_E_SEARCHTEXT, 180,8,276,14, WS_TABSTOP// | ES_LOWERCASE + PUSHBUTTON "Close" , IDCANCEL , 462, 0,52,14, WS_TABSTOP + PUSHBUTTON "Refresh", IDC_REFRESH, 462,16,52,14, WS_TABSTOP + + CONTROL "Show Offline contacts",IDC_CH_SHOWOFFLINE,"Button", + BS_AUTOCHECKBOX | BS_FLAT | BS_MULTILINE | BS_VCENTER | WS_TABSTOP,2,0,96,20 + CONTROL "Colorize",IDC_CH_COLORIZE,"Button", + BS_AUTOCHECKBOX | BS_FLAT | BS_MULTILINE | BS_VCENTER | WS_TABSTOP,2,20,96,10 +// LTEXT "Search for:",-1, 4,4,52,14, SS_CENTERIMAGE + COMBOBOX IDC_CB_PROTOCOLS,100,8,76,80, CBS_DROPDOWNLIST | + CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + CONTROL "", IDC_LIST, "SysListView32", WS_BORDER | WS_TABSTOP | // LVS_SHAREIMAGELISTS | // LVS_EX_SUBITEMIMAGES | + LVS_SHOWSELALWAYS | LVS_REPORT | LVS_NOLABELWRAP, + 2, 32, 516, 194 //, WS_EX_CONTROLPARENT + + CONTROL "", IDC_STATUSBAR, "msctls_statusbar32", + CCS_BOTTOM | 0x0900, // SBT_TOOLTIPS | SBARS_SIZEGRIP + 0,226,520,14 +} + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,4,1,18 + PRODUCTVERSION 0,8,0,0 + FILEFLAGSMASK $3F + FILEOS 4 + FILETYPE 2 + FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName","" + VALUE "Comments", "Plugin to quick search for nickname, firstname, lastname, email, uin in your contact list"0 + VALUE "FileDescription", "Quick info search plugin for Miranda NG"0 + VALUE "FileVersion", "1, 4, 1, 18 "0 + VALUE "InternalName", "QuickSearchMod"0 + VALUE "OriginalFilename", "quicksearch.dll"0 + VALUE "ProductName", "QuickSearchMod Dynamic Link Library (DLL)"0 + VALUE "ProductVersion", "0, 8, 0, 0 "0 + VALUE "SpecialBuild", "2.07.2010 "0 + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation",0,1200 + END +END diff --git a/plugins/QuickSearch/qs.res b/plugins/QuickSearch/qs.res new file mode 100644 index 0000000000..891c078829 Binary files /dev/null and b/plugins/QuickSearch/qs.res differ diff --git a/plugins/QuickSearch/quicksearch.dpr b/plugins/QuickSearch/quicksearch.dpr new file mode 100644 index 0000000000..699472b7b1 --- /dev/null +++ b/plugins/QuickSearch/quicksearch.dpr @@ -0,0 +1,244 @@ +{$include compilers.inc} +{$IFDEF COMPILER_16_UP} + {$WEAKLINKRTTI ON} + {.$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])} +{$ENDIF} +{$IMAGEBASE $13100000} +library quicksearch; + +{$R qs.res} + +uses +// FastMM4, + Windows, + Messages, + m_api, + sr_optdialog, + sr_global, + sr_window, + sr_frame, + mirutils, + common; + +var + opthook:cardinal; + onloadhook:cardinal; + onstatus, + ondelete, +// onaccount, + onadd:cardinal; + servshow:cardinal; + +const + icohook:THANDLE = 0; + +function MirandaPluginInfoEx(mirandaVersion:DWORD):PPLUGININFOEX; cdecl; +begin + result:=@PluginInfo; + PluginInfo.cbSize :=SizeOf(TPLUGININFOEX); + PluginInfo.shortName :='Quick Search Mod'; + PluginInfo.version :=$01040112; + PluginInfo.description:= + 'This Plugin allow you to quick search for nickname,'+ + 'firstname, lastname, email, uin in your contact list.'+ + 'And now you may add any setting to display - for example'+ + 'users version of miranda,group or city.'; + PluginInfo.author :='Awkward, based on Bethoven sources'; + PluginInfo.authorEmail:='panda75@bk.ru; awk1975@ya.ru'; + PluginInfo.copyright :='(c) 2004,2005 Bethoven; 2006-2012 Awkward'; + PluginInfo.homepage :='http://code.google.com/p/delphi-miranda-plugins/'; + PluginInfo.flags :=UNICODE_AWARE; + PluginInfo.uuid :=MIID_QUICKSEARCH; +end; + +function OnTTBLoaded(wParam:WPARAM;lParam:LPARAM):int;cdecl; +begin + addtotoolbar; + result:=0; +end; + +function IconChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + mi:TCListMenuItem; + ttb:TTBButton; +begin + result:=0; + FillChar(mi,SizeOf(mi),0); + mi.cbSize:=sizeof(mi); + mi.flags :=CMIM_ICON; + + mi.hIcon:=CallService(MS_SKIN2_GETICON,0,tlparam(QS_QS)); + CallService(MS_CLIST_MODIFYMENUITEM,MainMenuItem,tlparam(@mi)); + +// toptoolbar + if ServiceExists(MS_TTB_GETBUTTONOPTIONS)<>0 then + begin + CallService(MS_TTB_GETBUTTONOPTIONS,(hTTBButton shl 16)+TTBO_ALLDATA,TLPARAM(@ttb)); + ttb.hIconUp:=CallService(MS_SKIN2_GETICON,0,TLPARAM(QS_QS)); + ttb.hIconDn:=ttb.hIconUp; + CallService(MS_TTB_SETBUTTONOPTIONS,(hTTBButton shl 16)+TTBO_ALLDATA,TLPARAM(@ttb)); + end; + +end; + +procedure RegisterIcons; +var + sid:TSKINICONDESC; +begin + FillChar(sid,SizeOf(TSKINICONDESC),0); + sid.cbSize :=SizeOf(TSKINICONDESC); + sid.cx :=16; + sid.cy :=16; + sid.szSection.a:=qs_module; + + sid.hDefaultIcon :=LoadImage(hInstance,MAKEINTRESOURCE(IDI_QS),IMAGE_ICON,16,16,0); + sid.pszName :=QS_QS; + sid.szDescription.a:=qs_name; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + + sid.hDefaultIcon :=LoadImage(hInstance,MAKEINTRESOURCE(IDI_NEW),IMAGE_ICON,16,16,0); + sid.pszName :=QS_NEW; + sid.szDescription.a:='New Column'; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + + sid.hDefaultIcon :=LoadImage(hInstance,MAKEINTRESOURCE(IDI_ITEM),IMAGE_ICON,16,16,0); + sid.pszName :=QS_ITEM; + sid.szDescription.a:='Save Column'; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + + sid.hDefaultIcon :=LoadImage(hInstance,MAKEINTRESOURCE(IDI_UP),IMAGE_ICON,16,16,0); + sid.pszName :=QS_UP; + sid.szDescription.a:='Column Up'; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + + sid.hDefaultIcon :=LoadImage(hInstance,MAKEINTRESOURCE(IDI_DOWN),IMAGE_ICON,16,16,0); + sid.pszName :=QS_DOWN; + sid.szDescription.a:='Column Down'; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + + sid.hDefaultIcon :=LoadImage(hInstance,MAKEINTRESOURCE(IDI_DELETE),IMAGE_ICON,16,16,0); + sid.pszName :=QS_DELETE; + sid.szDescription.a:='Delete Column'; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + + sid.hDefaultIcon :=LoadImage(hInstance,MAKEINTRESOURCE(IDI_DEFAULT),IMAGE_ICON,16,16,0); + sid.pszName :=QS_DEFAULT; + sid.szDescription.a:='Default'; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + + sid.hDefaultIcon :=LoadImage(hInstance,MAKEINTRESOURCE(IDI_RELOAD),IMAGE_ICON,16,16,0); + sid.pszName :=QS_RELOAD; + sid.szDescription.a:='Reload'; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + + sid.hDefaultIcon :=LoadImage(hInstance,MAKEINTRESOURCE(IDI_MALE),IMAGE_ICON,16,16,0); + sid.pszName :=QS_MALE; + sid.szDescription.a:='Male'; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + + sid.hDefaultIcon :=LoadImage(hInstance,MAKEINTRESOURCE(IDI_FEMALE),IMAGE_ICON,16,16,0); + sid.pszName :=QS_FEMALE; + sid.szDescription.a:='Female'; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + + icohook:=HookEvent(ME_SKIN2_ICONSCHANGED,@IconChanged); +end; + +function OnOptInitialise(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + odp:TOPTIONSDIALOGPAGE; +begin + ZeroMemory(@odp,sizeof(odp)); + odp.cbSize :=SizeOf(odp); //for 0.6+ compatibility + odp.Position :=900003000; + odp.hInstance :=hInstance; + odp.pszTemplate:=PAnsiChar(IDD_DIALOG1); + odp.szTitle.a :=qs_name; + odp.szGroup.a :='Contact List'; + odp.pfnDlgProc :=@sr_optdialog.DlgProcOptions; + odp.flags :=ODPF_BOLDGROUPS; + Options_AddPage(wParam,@odp); +// CallService(MS_OPT_ADDPAGE,wParam,tlparam(@odp)); + Result:=0; +end; + +function OpenSearchWindow(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +begin + result:=0; + if not opened then + OpenSrWindow(pointer(wParam),lParam) + else + BringToFront; +end; + +function OnModulesLoaded(wParam:WPARAM;lParam:LPARAM):int;cdecl; +begin + UnhookEvent(onloadhook); + + CallService(MS_DBEDIT_REGISTERSINGLEMODULE,twparam(qs_module),0); + + RegisterIcons; + RegisterColors; + + servshow:=CreateServiceFunction(QS_SHOWSERVICE,@OpenSearchWindow); + AddRemoveMenuItemToMainMenu; + + reghotkeys; + + onadd :=HookEvent(ME_DB_CONTACT_ADDED ,@OnContactAdded); + ondelete :=HookEvent(ME_DB_CONTACT_DELETED ,@OnContactDeleted); + onstatus :=HookEvent(ME_CLIST_CONTACTICONCHANGED,@OnStatusChanged); +// onaccount:=HookEvent(ME_PROTO_ACCLISTCHANGED ,@OnAccountChanged); + HookEvent(ME_TTB_MODULELOADED,@OnTTBLoaded); + + CreateFrame(0); + Result:=0; +end; + +function Load():Integer;cdecl; +begin + Result:=0; + Langpack_register; + opthook :=HookEvent(ME_OPT_INITIALISE ,@OnOptInitialise); + onloadhook:=HookEvent(ME_SYSTEM_MODULESLOADED,@OnModulesLoaded); + loadopt_db(true); +end; + +function Unload:Integer;cdecl; +begin + result:=0; + removetoolbar; //?? + DestroyFrame; + + DestroyServiceFunction(servshow); + UnhookEvent(opthook); + UnhookEvent(onadd); + UnhookEvent(ondelete); + UnhookEvent(onstatus); +// UnhookEvent(onaccount); + if icohook<>0 then + UnhookEvent(icohook); + +// unreghotkeys; + + CloseSrWindow; + + clear_columns; +end; + +exports + Load, Unload, + MirandaPluginInfoEx; + +begin +end. diff --git a/plugins/QuickSearch/quicksearch_history.txt b/plugins/QuickSearch/quicksearch_history.txt new file mode 100644 index 0000000000..17cfce6852 --- /dev/null +++ b/plugins/QuickSearch/quicksearch_history.txt @@ -0,0 +1,110 @@ +Service: + wParam: 0, or pattern string + lParam: 0 - wParam has unicode string; + 1 - Ansi String (only Unicode plugin version) + 2 - wParam is contact handle to select (not realized) + service:"QuickSearch_PLUGIN/Show" + +History: + +1.4.1.19 () + FastMM4 memory manager used (not native Delphi or miranda) + Fixed some Memory leaks +1.4.1.18 (2 jul 2010) + Doubleclick/Enter on contact set as Clist doubleclick action + Group list sorted now + Fixed main window Refresh action (F5 and button) + Added frame button to open Main QS window +1.4.1.17 (5 may 2010) + Added contact list frame + Fixed columns sort + Added right click on columns header processing + Filter applying just for visible columns now + Added tooltip for hidden columns info + Added several User Info fields + Added button and hotkey F5 to refresh content of main window + Partial code refactoring + Fixed again info showing in window with hidden columns +1.4.0.16 (16 jul 2009) + Fixed info showing in window with hidden columns +1.4.0.15 (13 jul 2009) + Fixed empty line for hidden contacts and contacts of disabled accounts +1.4.0.14 (11 jul 2009) + Added checkbox for hide columns from showing +1.4.0.13 (10 jul 2009) + Added context menu item to combine selected contacts to metacontact + Added new column type for metacontacts + Added colorization for metacontacts +1.4.0.12 (jun 2009) + Fixed fields drawing in options dialog + Added colorisation for not-in-list contacts and on switched off or deleted accounts + Fixes for Statusbar + Fixes for Show/hide offline contacts +1.4.0.11 (13 mar 2009) + Added column type "Variables script" + Added translation to column types + Fixed Show/hide offline contacts behaviour + Fixed one of unicode localization bugs + Fixed contact copying to Clipboard +1.4.0.10 (19 oct 2008) + Some fixes + Some WinAPI/Delphi functions replaced by handmaked + Added support for Miranda core hotkeys (ver 8.0+) + Added:Drag&Drop (realtime) QS list column reordering + In option:list scrolling to newly added items + Added ANSI code part + Fixed: empty LastEvent field was at top of event list +1.4.0.9 (11 sep 2008) + Fixed: Can crashed with content filter + Maked list filling faster + Changed: maximum column amount changing dynamically now + Source changed: AnsiChar replaced by AnsiChar + Removed some codeparts for Miranda v0.5 compatibility + Fixed: wrong QS window width resizing +1.4.0.8 (28 aug 2008) + Fixed crash while adding contact with opened QS window +1.4.0.7 (21 jul 2008) + Added icons for XStatus + Fixed unicode filter + Added internal caching +(29 oct 2007) + Added tooltips for IM-client and gender columns + Changed QS window icon assign code + Changed group of contacts delete code + Added filter groups in "" (start quote must be first AnsiChar or after space) +(19 may 2007) + Added option to save text search pattern +1.4.0.6 (09 mar 2007) + Added: Option to skip 'minimized' columns while copying to Clipboard + Fixed: Abort context menu move contacts to first group in list + Ctrl-C (or &Copy context menu command) copying info with TAB separated fields + Added: new miranda API support +1.4.0.5 (21 jan 2007) + Fixed: Contact menu do not execute action when Auto close mode is ON + Fixed: Gender icon not shown when icolib not installed + Partially solved problem with large system fonts + Fixed: changed menu/toolbar icon was not set at start + Added Gender reading from UserInfo, not only protocol +1.4.0.4 (22 dec 2006) + Added Male/Female icon and special gender processing + Letters and BackSpace works in the list + Ctrl-C in list copying contact info to Clipboard + Added StatusBar + Slightly modified Option page + Added option to disable client icon + Added Updater support + Added IcoLib support +1.4.0.3 (18 dec 2006) + Service was advanced + Fixed: Enter on edit field removes contact from group +1.4.0.2 (17 dec 2006) + Added option to show/hide offline contacts + Added "Stay on top" option to sysmenu + Fixed: context menu shown only one time +1.4.0.1 (17 dec 2006) + Fixed: Options not shown in Miranda before 0.6 version + Small code and interface changes + First item in list now focused automatically + Fixed: search pattern work only with small characters +1.4.0.0 (14 dec 2006) + Initial release \ No newline at end of file diff --git a/plugins/QuickSearch/resource.inc b/plugins/QuickSearch/resource.inc new file mode 100644 index 0000000000..d31773d79e --- /dev/null +++ b/plugins/QuickSearch/resource.inc @@ -0,0 +1,76 @@ +const + IDD_DIALOG1 = 101; + IDD_MAIN = 102; + IDD_SCRIPT = 103; + IDD_FRAME = 104; + + IDI_QS = 107; + + IDI_NEW = 110; + IDI_ITEM = 111; + IDI_UP = 112; + IDI_DOWN = 113; + IDI_DELETE = 114; + IDI_DEFAULT = 115; + IDI_RELOAD = 116; + + IDI_MALE = 120; + IDI_FEMALE = 121; + + IDC_FRAME_EDIT = 1025; + IDC_FRAME_PREV = 1026; + IDC_FRAME_NEXT = 1027; + IDC_FRAME_OPEN = 1028; + + IDC_NEW = 1001; + IDC_DELETE = 1002; + IDC_UP = 1003; + IDC_DN = 1004; + IDC_DEFAULT = 1005; + IDC_SETITEM = 1006; + IDC_RELOAD = 1007; + + IDC_E_TITLE = 1010; + IDC_E_MODULE = 1011; + IDC_E_VAR = 1012; + IDC_E_LPAR = 1013; + IDC_HOTKEYGLOB = 1014; + IDC_HOTKEYLOC = 1015; + IDC_HKGROUP = 1016; + IDC_STAT_GLOBAL = 1017; + IDC_STAT_LOCAL = 1018; + IDC_LIST = 1020; + IDC_C_VARTYPE = 1021; + IDC_C_CNFTYPE = 1022; + IDC_CB_MAIN = 1023; + IDC_C_WPAR = 1024; + IDC_C_LPAR = 1025; + IDC_C_RESULT = 1026; + IDC_CH_SORTSTATUS = 1030; + IDC_CH_SHOWINMENU = 1031; + IDC_CH_SHOWONLYUSERS = 1032; + IDC_CH_ADDTOTOPTOOLBAR = 1033; + IDC_CH_AUTOCLOSE = 1034; + IDC_CH_USETOOLSTYLE = 1035; + IDC_CH_HOOKCHANGES = 1036; + IDC_CH_DRAWGRID = 1037; + IDC_CH_SHOWCLIENTICONS = 1038; + IDC_STAT_SERVICE = 1040; + IDC_STAT_MODULE = 1041; + IDC_STAT_WPAR = 1042; + IDC_STAT_SETTING = 1043; + IDC_CH_SINGLECSV = 1044; + IDC_CH_EXPORTHEADERS = 1045; + IDC_CH_SKIPMINIMIZED = 1046; + IDC_CH_SAVEPATTERN = 1047; + IDC_STAT_VARTYPE = 1048; + IDC_SCRIPT = 1049; + + IDC_E_SEARCHTEXT = 1001; + IDC_CH_SHOWOFFLINE = 1031; + IDC_CH_COLORIZE = 1032; + IDC_REFRESH = 1033; + IDC_STATUSBAR = 1034; + IDC_CB_PROTOCOLS = 1035; + + IDC_EDIT_SCRIPT = 1025; diff --git a/plugins/QuickSearch/sr_frame.pas b/plugins/QuickSearch/sr_frame.pas new file mode 100644 index 0000000000..bf3e576554 --- /dev/null +++ b/plugins/QuickSearch/sr_frame.pas @@ -0,0 +1,343 @@ +unit sr_frame; + +interface + +uses windows; + +procedure CreateFrame(parent:HWND); +procedure DestroyFrame; + +implementation + +uses commctrl,Messages,m_api,common,wrapper,mirutils,sr_global; + +{.$include resource.inc} + +const + frm_back:pAnsiChar = 'Frame background'; +const + FrameWnd:HWND = 0; + FrameId:integer = -1; + OldEditProc:pointer=nil; + pattern:pWideChar=nil; + current: THANDLE = 0; +var + colorhook:THANDLE; + hbr:HBRUSH; + frm_bkg:TCOLORREF; + +function CheckContact(wnd:HWND; hContact:THANDLE):THANDLE; +var + buf:array [0..127] of WideChar; +begin + result:=0; + + SendMessage(wnd,CLM_GETITEMTEXT,hContact,lparam(@buf)); + + if StrPosW(CharLowerW(@buf),pattern)<>nil then + result:=hContact; +end; + +function GetNextContact(wnd:HWND; root,hContact:THANDLE; direction,skip:integer):THANDLE; +var + tmp:THANDLE; +// buf:array [0..127] of WideChar; +begin + result:=0; + repeat + + if skip=0 then + begin + case SendMessage(wnd,CLM_GETITEMTYPE,hContact,0) of + CLCIT_GROUP: begin + if SendMessage(wnd,CLM_GETEXPAND,hContact,0)=CLE_EXPAND then // expanded only + begin + tmp:=SendMessage(wnd,CLM_GETNEXTITEM,CLGN_CHILD,hContact); + if tmp<>0 then + begin + hContact:=tmp; + if direction=CLGN_PREVIOUS then + begin // set on last contact in group + repeat + tmp:=SendMessage(wnd,CLM_GETNEXTITEM,CLGN_NEXT,hContact); + if tmp<>0 then + hContact:=tmp + else + break; + until false; + end; + continue; + end; + end; + end; + CLCIT_CONTACT: begin + result:=CheckContact(wnd,hContact); + if result<>0 then + break; + end; + else // CLCIT_INVALID for example + break; + end; + end + else + skip:=0; + + if hContact=HCONTACT_ISGROUP then +// if (hContact=root) and (direction=CLGN_PREVIOUS) then // 1st group, no need to process "root=clist" + break; + + tmp:=SendMessage(wnd,CLM_GETNEXTITEM,direction,hContact); + if tmp=0 then + begin + hContact:=SendMessage(wnd,CLM_GETNEXTITEM,CLGN_PARENT,hContact); + // not here but where group insert + skip:=1; + continue; + // hContact:=SendMessage(wnd,CLM_GETNEXTITEM,direction,hContact); + if hContact=0 then + break; + end + else + hContact:=tmp; + until false; +end; + +function SearchContact(direction:integer;skip:integer=1):integer; +var + root,hContact:THANDLE; + wnd:HWND; +begin + result:=0; + if (pattern=nil) or (pattern^=#0) then + begin + current:=0; // next seach - from start + exit; // pattern empty + end; + + wnd:=CallService(MS_CLUI_GETHWNDTREE,0,0); + + root:=SendMessage(wnd,CLM_GETNEXTITEM,CLGN_ROOT,0); + if current=0 then + hContact:=root + else + hContact:=current; + + result:=GetNextContact(wnd,root,hContact,direction,skip); + + if result<>0 then + SetCListSelContact(result); +end; + +function NewEditProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +begin +// result:=0; + case hMessage of + WM_CHAR: if wParam=27 then + begin + // clear edit field + SendMessage(Dialog,WM_SETTEXT,0,0); + // go to top? + current:=0; + end; + + WM_KEYDOWN: begin + case wParam of + VK_PRIOR,VK_UP: begin + current:=SearchContact(CLGN_PREVIOUS); + end; + VK_NEXT,VK_DOWN: begin + current:=SearchContact(CLGN_NEXT); + end; + end; + end; + end; + result:=CallWindowProc(OldEditProc,Dialog,hMessage,wParam,lParam); +end; + +function QSDlgResizer(Dialog:HWND;lParam:LPARAM;urc:PUTILRESIZECONTROL):int; cdecl; +begin + case urc^.wId of + IDC_FRAME_OPEN: result:=RD_ANCHORX_LEFT or RD_ANCHORY_CENTRE; + IDC_FRAME_EDIT: result:=RD_ANCHORX_WIDTH or RD_ANCHORY_CENTRE; + IDC_FRAME_PREV: result:=RD_ANCHORX_RIGHT or RD_ANCHORY_CENTRE; + IDC_FRAME_NEXT: result:=RD_ANCHORX_RIGHT or RD_ANCHORY_CENTRE; + else + result:=0; + end; +end; + +function QSFrameProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + urd:TUTILRESIZEDIALOG; + tmp:THANDLE; + rc:TRECT; + ti:TTOOLINFOW; + hwndTooltip:HWND; +begin + result:=0; + case hMessage of + WM_DESTROY: begin + DeleteObject(hbr); + end; + + WM_INITDIALOG: begin + OldEditProc:=pointer(SetWindowLongPtrW(GetDlgItem(Dialog,IDC_FRAME_EDIT), + GWL_WNDPROC,LONG_PTR(@NewEditProc))); + + hwndTooltip:=CreateWindowW(TOOLTIPS_CLASS,nil,TTS_ALWAYSTIP, + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + Dialog,0,hInstance,nil); + + FillChar(ti,SizeOf(ti),0); + ti.cbSize :=sizeof(TOOLINFO); + ti.uFlags :=TTF_IDISHWND or TTF_SUBCLASS; + ti.hwnd :=Dialog; + ti.hinst :=hInstance; + ti.uId :=GetDlgItem(Dialog,IDC_FRAME_PREV); + + ti.lpszText:=pWideChar(TranslateW('Previous item')); + SendMessage(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); + ti.uId :=GetDlgItem(Dialog,IDC_FRAME_NEXT); + ti.lpszText:=pWideChar(TranslateW('Next item')); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); + ti.uId :=GetDlgItem(Dialog,IDC_FRAME_OPEN); + ti.lpszText:=pWideChar(TranslateW('Open main window')); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); + end; + + WM_SIZE: begin + FillChar(urd,SizeOf(TUTILRESIZEDIALOG),0); + urd.cbSize :=SizeOf(urd); + urd.hwndDlg :=Dialog; + urd.hInstance :=hInstance; + urd.lpTemplate:=MAKEINTRESOURCEA(IDD_FRAME); + urd.lParam :=0; + urd.pfnResizer:=@QSDlgResizer; + CallService(MS_UTILS_RESIZEDIALOG,0,tlparam(@urd)); + end; + + WM_ERASEBKGND: begin + GetClientRect(Dialog,rc); + FillRect(wParam,rc,hbr); + result:=1; + end; + + WM_COMMAND: begin + case wParam shr 16 of + EN_CHANGE: begin + mFreeMem(pattern); + pattern:=GetDlgText(Dialog,IDC_FRAME_EDIT); + if pattern<>nil then + CharLowerW(pattern); + + tmp:=SearchContact(CLGN_NEXT,0); + if tmp=0 then + tmp:=SearchContact(CLGN_PREVIOUS,0); + current:=tmp; + end; + + BN_CLICKED: begin + tmp:=0; + case loword(wParam) of + IDC_FRAME_PREV: tmp:=SearchContact(CLGN_PREVIOUS); + IDC_FRAME_NEXT: tmp:=SearchContact(CLGN_NEXT); + IDC_FRAME_OPEN: CallService(QS_SHOWSERVICE,twparam(pattern),0); + end; + if tmp<>0 then current:=tmp; + end; + end; + end; + + else + result:=DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; + +function ColorReload(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + cid:TColourID; +begin + result:=0; + cid.cbSize:=SizeOf(cid); + StrCopy(cid.group,'QuickSearch'); + StrCopy(cid.name ,frm_back); + frm_bkg:=CallService(MS_COLOUR_GETA,twparam(@cid),0); + DeleteObject(hbr); + hbr:=CreateSolidBrush(frm_bkg); + + RedrawWindow(FrameWnd,nil,0,RDW_ERASE); +end; + +procedure CreateFrame(parent:HWND); +var + Frame:TCLISTFrame; + wnd:HWND; + tmp:cardinal; + tr:TRECT; + cid:TColourID; +begin + if ServiceExists(MS_CLIST_FRAMES_ADDFRAME)=0 then + exit; + if parent=0 then + parent:=CallService(MS_CLUI_GETHWND,0,0); + + if FrameWnd=0 then + FrameWnd:=CreateDialog(hInstance,MAKEINTRESOURCE(IDD_FRAME),parent,@QSFrameProc); + + if FrameWnd<>0 then + begin + GetWindowRect(FrameWnd,tr); + FillChar(Frame,SizeOf(Frame),0); + with Frame do + begin + cbSize :=SizeOf(Frame); + hWnd :=FrameWnd; + hIcon :=0; + align :=alTop; + height :=tr.bottom-tr.top+2; + Flags :=F_VISIBLE or F_NOBORDER or F_UNICODE; + name.w :='Quick search'; + TBName.w:='Quick search'; + end; + + FrameId:=CallService(MS_CLIST_FRAMES_ADDFRAME,wparam(@Frame),0); + if FrameId>=0 then + begin + CallService(MS_CLIST_FRAMES_UPDATEFRAME,FrameId, FU_FMPOS); + + wnd:=CallService(MS_CLUI_GETHWND{MS_CLUI_GETHWNDTREE},0,0); + tmp:=SendMessage(wnd,CLM_GETEXSTYLE,0,0); + SendMessage(wnd,CLM_SETEXSTYLE,tmp or CLS_EX_SHOWSELALWAYS,0); + + cid.cbSize:=SizeOf(cid); + cid.flags :=0; + StrCopy(cid.group,'QuickSearch'); + StrCopy(cid.dbSettingsGroup,qs_module); + + StrCopy(cid.name ,frm_back); + StrCopy(cid.setting,'frame_back'); + cid.defcolour:=COLOR_3DFACE; + cid.order :=0; + ColourRegister(@cid); + + colorhook:=HookEvent(ME_COLOUR_RELOAD,@ColorReload); + ColorReload(0,0); + end; + end; +end; + +procedure DestroyFrame; +begin + if FrameId>=0 then + begin + UnhookEvent(colorhook); + CallService(MS_CLIST_FRAMES_REMOVEFRAME,FrameId,0); + FrameId:=-1; + end; + DestroyWindow(FrameWnd); + FrameWnd:=0; + mFreeMem(pattern); +end; + +end. diff --git a/plugins/QuickSearch/sr_global.pas b/plugins/QuickSearch/sr_global.pas new file mode 100644 index 0000000000..cd9e1d826e --- /dev/null +++ b/plugins/QuickSearch/sr_global.pas @@ -0,0 +1,750 @@ +unit sr_global; + +interface +uses windows,messages,commctrl,m_api,dbsettings,mirutils; + +const + // for QS window only + IDM_STAYONTOP = WM_USER+1; + WM_MYADDCONTACT = WM_USER+2; + WM_MYDELETECONTACT = WM_USER+3; + + WM_MYSHOWHIDEITEM = WM_USER + 4; + WM_MYMOVEITEM = WM_USER + 5; +const + wcUp = 1; + wcDown = 2; + wcHide = 3; + wcShow = 4; + wcDelete = 5; + wcInsert = 6; + wcChange = 7; + wcRefresh = 8; + +const + opened:boolean = false; +const + QS_QS :PAnsiChar = 'QS_QS'; + QS_NEW :PAnsiChar = 'QS_New'; + QS_ITEM :PAnsiChar = 'QS_Item'; + QS_UP :PAnsiChar = 'QS_Up'; + QS_DOWN :PAnsiChar = 'QS_Down'; + QS_DELETE :PAnsiChar = 'QS_Delete'; + QS_DEFAULT:PAnsiChar = 'QS_Default'; + QS_RELOAD :PAnsiChar = 'QS_Reload'; + QS_MALE :PAnsiChar = 'QS_Male'; + QS_FEMALE :PAnsiChar = 'QS_Female'; +const + qs_module :PAnsiChar = 'QuickSearch'; + qs_name :PAnsiChar = 'Quick Search'; + QS_SHOWSERVICE:PAnsiChar = 'QuickSearch_PLUGIN/Show'; + +const + StatusSort = 1000; + +const + ptNumber = 0; + ptInteger = 1; + ptString = 2; + ptUnicode = 3; + ptCurrent = 4; + +const //types + ST_BYTE = 0; + ST_WORD = 1; + ST_INT = 2; + ST_STRING = 3; + ST_IP = 4; + ST_LASTSEEN = 5; + ST_CONTACTINFO = 6; + ST_LASTEVENT = 7; + ST_TIMESTAMP = 8; + ST_SERVICE = 9; + ST_SCRIPT = 10; + ST_METACONTACT = 11; + + ST_MAXTYPE = 11; + +const + COL_ON = $0001; // Show column + COL_INIT = $0002; // No need to update + COL_XSTATUS = $0100; + COL_GENDER = $0200; + COL_CLIENT = $0400; + +{$include resource.inc} + +type + tserviceparam = record + case _type:word of + 0: (n:dword); + 1: (i:integer); + 2: (a:PAnsiChar); + 3: (w:PWideChar); + end; +type + tcolumnitem=record + title :PWideChar; + module_name :PAnsiChar; + width :dword; + setting_type :dword; // ST_* constants + setting_cnftype:dword; // pt* constants + wparam :tserviceparam; + lparam :tserviceparam; + flags :dword; // COL_* constants + end; + tcolumnarray = array of tcolumnitem; + tqsopt=record + grrect :TRECT; + columns :tcolumnarray;//array of tcolumnitem; + numcolumns :integer; + columnsort :integer; + ascendsort :boolean; + sortbystatus :boolean; + drawgrid :boolean; + showinmenu :boolean; + showonlyinlist :boolean; + showintoptoolbar:boolean; + usetoolstyle :boolean; + closeafteraction:boolean; + stayontop :boolean; + showoffline :boolean; + showclienticons :boolean; + exportheaders :boolean; + singlecsv :boolean; + skipminimized :boolean; + savepattern :boolean; + colorize :boolean; + end; + +procedure reghotkeys; +procedure unreghotkeys; + +procedure saveopt_wnd; +procedure saveopt_db; +procedure loadopt_db(full:boolean); +procedure clear_columns; +function new_column(after:integer=-1):integer; +procedure delete_column(pos:integer); +procedure loaddefaultcolumns; + +procedure AddRemoveMenuItemToMainMenu; +procedure addtotoolbar; +procedure removetoolbar; + +var + qsopt:tqsopt; + +const + MainMenuItem:integer=0; + hTTBButton :thandle=0; + +implementation + +uses common; + +const + HKN_GLOBAL:PAnsiChar = 'QS_Global'; +const + so_mbottom :PAnsiChar = 'mbottom'; + so_mright :PAnsiChar = 'mright'; + so_mtop :PAnsiChar = 'mtop'; + so_mleft :PAnsiChar = 'mleft'; + so_columnsort :PAnsiChar = 'columnsort'; + so_sortbystatus :PAnsiChar = 'sortbystatus'; + so_ascendsort :PAnsiChar = 'ascendsort'; + so_showonlyinlist :PAnsiChar = 'showonlyinlist'; + so_dontusetoolstyle:PAnsiChar = 'dontusetoolstyle'; + so_showinmenu :PAnsiChar = 'showinmenu'; + so_showintoptoolbar:PAnsiChar = 'showintoptoolbar'; + so_closeafteraction:PAnsiChar = 'closeafteraction'; + so_exportheaders :PAnsiChar = 'exportheaders'; + so_singlecsv :PAnsiChar = 'singlecsv'; + so_savepattern :PAnsiChar = 'savepattern'; + so_numcolumns :PAnsiChar = 'numcolumns'; + so_item :PAnsiChar = 'item'; + so_drawgrid :PAnsiChar = 'drawgrid'; + so_stayontop :PAnsiChar = 'stayontop'; + so_showclienticons :PAnsiChar = 'showclienticons'; + so_skipminimized :PAnsiChar = 'skipminimized'; + so_showoffline :PAnsiChar = 'showoffline'; + so_colorize :PAnsiChar = 'colorize'; + + so__title :PAnsiChar = '_title'; + so__setting_type :PAnsiChar = '_setting_type'; + so__setting_cnftype:PAnsiChar = '_setting_cnftype'; + so__module_name :PAnsiChar = '_module_name'; + so__wparam_type :PAnsiChar = '_wparam_type'; + so__lparam_type :PAnsiChar = '_lparam_type'; + so__wparam :PAnsiChar = '_wparam'; + so__lparam :PAnsiChar = '_lparam'; + so__width :PAnsiChar = '_width'; + so__flags :PAnsiChar = '_flags'; + +procedure reghotkeys; +var + hkrec:HOTKEYDESC; +begin + FillChar(hkrec,SizeOf(hkrec),0); + with hkrec do + begin + cbSize :=HOTKEYDESC_SIZE_V1; + pszName :=HKN_GLOBAL; + pszDescription.a:='QuickSearch window hotkey'; + pszSection.a :=qs_name; + pszService :=QS_SHOWSERVICE; + DefHotKey :=(HOTKEYF_ALT shl 8) or VK_F3; + end; + CallService(MS_HOTKEY_REGISTER,0,lparam(@hkrec)); +end; + +procedure unreghotkeys; +begin + CallService(MS_HOTKEY_UNREGISTER,0,lparam(HKN_GLOBAL)); +end; + +procedure removetoolbar; +begin + if hTTBButton<>0 then + begin + if ServiceExists(MS_TTB_REMOVEBUTTON)>0 then + begin + CallService(MS_TTB_REMOVEBUTTON,WPARAM(hTTBButton),0); + hTTBButton:=0; + end; + end; +end; + +procedure addtotoolbar; +var + ttbopt:TTBButton; +begin + removetoolbar; + + if qsopt.showintoptoolbar then + begin + if ServiceExists(MS_TTB_ADDBUTTON)>0 then + begin + ZeroMemory(@ttbopt,sizeof(ttbopt)); + ttbopt.cbSize :=sizeof(ttbopt); + ttbopt.pszService:=QS_SHOWSERVICE; + ttbopt.hIconUp :=CallService(MS_SKIN2_GETICON,0,lparam(QS_QS)); + ttbopt.hIconDn :=ttbopt.hIconUp; + ttbopt.dwFlags :=TTBBF_VISIBLE; + ttbopt.name :=qs_module; + hTTBButton:=TopToolbar_AddButton(@ttbopt); + if hTTBButton=THANDLE(-1) then + hTTBButton:=0; + end; + end; +end; + +procedure AddRemoveMenuItemToMainMenu; +var + cmi:TCLISTMENUITEM; +begin + if qsopt.showinmenu then + begin + if MainMenuItem<>0 then exit; + ZeroMemory(@cmi,sizeof(cmi)); + cmi.cbSize :=sizeof(cmi) ; + cmi.szName.a :=qs_name; + cmi.position :=500050000; +// cmi.pszPopupName:=nil; +// cmi.flags :=0; + cmi.pszService :=QS_SHOWSERVICE; + cmi.hIcon :=CallService(MS_SKIN2_GETICON,0,lparam(QS_QS)); + MainMenuItem :=Menu_AddMainMenuItem(@cmi); + end + else + begin + if (MainMenuItem<>0) and + (ServiceExists(MS_CLIST_REMOVEMAINMENUITEM)<>0) then + begin + CallService(MS_CLIST_REMOVEMAINMENUITEM,MainMenuItem,0); + MainMenuItem:=0; + end; + end; +end; + +// -------- column functions --------- + +procedure clear_column(num:integer); +begin + with qsopt.columns[num] do + begin + mFreeMem(title); + if setting_type<>ST_CONTACTINFO then + begin + mFreeMem(module_name); + if setting_type<>ST_SERVICE then + mFreeMem(wparam.a) + else + begin + if (wparam._type=ptString) or (wparam._type=ptUnicode) then mFreeMem(wparam.a); + if (lparam._type=ptString) or (lparam._type=ptUnicode) then mFreeMem(lparam.a); + end; + end; + end; +end; + +procedure clear_columns; +var + i:integer; +begin + for i:=0 to qsopt.numcolumns-1 do + clear_column(i); + FillChar(qsopt.columns[0],Length(qsopt.columns),0); + qsopt.numcolumns:=0; +end; + +procedure delete_column(pos:integer); +begin + if (pos>=0) and (qsopt.numcolumns>0) then + begin + dec(qsopt.numcolumns); + clear_column(pos); + move(qsopt.columns[pos+1],qsopt.columns[pos],(qsopt.numcolumns-pos)*sizeof(tcolumnitem)); + SetLength(qsopt.columns,qsopt.numcolumns); + end; +end; + +function new_column(after:integer=-1):integer; +begin + SetLength(qsopt.columns,qsopt.numcolumns+1); + FillChar(qsopt.columns[qsopt.numcolumns],SizeOf(tcolumnitem),0); + with qsopt.columns[qsopt.numcolumns] do + begin + StrDupW(title,'New column'); + width:=64; + flags:=COL_ON; + end; + result:=qsopt.numcolumns; + inc(qsopt.numcolumns); +end; + +procedure MakeTitle(var title; name:pAnsiChar); +begin + FastAnsiToWide(name,pWideChar(title)); +end; + +procedure loaddefaultcolumns; +begin + clear_columns; + qsopt.numcolumns:=15; + SetLength(qsopt.columns ,qsopt.numcolumns); + FillChar(qsopt.columns[0],qsopt.numcolumns*SizeOf(tcolumnitem),0); + + // protocol + with qsopt.columns[0] do + begin + MakeTitle(title,'Protocol'); + StrDup (module_name,MS_PROTO_GETCONTACTBASEPROTO); + width :=82; + setting_type :=ST_SERVICE; + setting_cnftype:=ptString; + wparam._type :=ptCurrent; + lparam._type :=ptNumber; + lparam.n :=0; + flags :=COL_ON; + end; + + with qsopt.columns[1] do + begin + MakeTitle(title,'Real Protocol'); + StrDup(module_name,'Protocol'); + StrDup(wparam.a ,'p'); + width :=82; + setting_type :=ST_STRING; + flags :=0; + end; + + //gender + with qsopt.columns[2] do + begin + MakeTitle(title,'Gender'); + width :=20; + setting_type :=ST_CONTACTINFO; + setting_cnftype:=CNF_GENDER; + flags :=COL_ON; + end; + + //uin + with qsopt.columns[3] do + begin + MakeTitle(title,'UserID'); + width :=80; + setting_type :=ST_CONTACTINFO; + setting_cnftype:=CNF_UNIQUEID; + flags :=COL_ON; + end; + + //username(displayname) + with qsopt.columns[4] do + begin + MakeTitle(title,'Nickname'); + StrDup(module_name,MS_CLIST_GETCONTACTDISPLAYNAME); + width :=76; + setting_type :=ST_SERVICE; + setting_cnftype:=ptUnicode; + wparam._type :=ptCurrent; + lparam._type :=ptNumber; + lparam.n :=2; // 0 for ANSI + flags :=COL_ON; + end; + + //firstname + with qsopt.columns[5] do + begin + MakeTitle(title,'First name'); + width :=68; + setting_type :=ST_CONTACTINFO; + setting_cnftype:=CNF_FIRSTNAME; + flags :=COL_ON; + end; + + //lastname + with qsopt.columns[6] do + begin + MakeTitle(title,'Last name'); + width :=66; + setting_type :=ST_CONTACTINFO; + setting_cnftype:=CNF_LASTNAME; + flags :=COL_ON; + end; + + //group + with qsopt.columns[7] do + begin + MakeTitle(title,'Group'); + width :=80; + StrDup(module_name,'CList'); + StrDup(wparam.a ,'Group'); + setting_type :=ST_STRING; + flags :=COL_ON; + end; + + //email + with qsopt.columns[8] do + begin + MakeTitle(title,'E-mail'); + width :=116; + setting_type :=ST_CONTACTINFO; + setting_cnftype:=CNF_EMAIL; + flags :=COL_ON; + end; + + //miranda version + with qsopt.columns[9] do + begin + MakeTitle(title,'ClientID'); + StrDup(wparam.a,'MirVer'); + width :=60; + setting_type:=ST_STRING; + flags :=COL_ON; + end; + + //IP version + with qsopt.columns[10] do + begin + MakeTitle(title,'Ext IP'); + StrDup(module_name,'ICQ'); + StrDup(wparam.a ,'IP'); + width :=100; + setting_type:=ST_IP; + flags :=0; + end; + + //LastSeen + with qsopt.columns[11] do + begin + MakeTitle(title,'LastSeen'); + StrDup(module_name,'SeenModule'); + width :=116; + setting_type:=ST_LASTSEEN; + flags :=0; + end; + + //last event + with qsopt.columns[12] do + begin + MakeTitle(title,'Last Event'); + width :=100; + setting_type:=ST_LASTEVENT; + flags :=0; + end; + + //online since + with qsopt.columns[13] do + begin + MakeTitle(title,'Online since'); + StrDup(module_name,'ICQ'); + StrDup(wparam.a ,'LogonTS'); + width :=100; + setting_type:=ST_TIMESTAMP; + flags :=0; + end; + + //metacontacts + with qsopt.columns[14] do + begin + MakeTitle(title,'Metacontact'); + width :=50; + setting_type:=ST_METACONTACT; + flags :=0; + end; +end; + +// -------- save/load settings --------- + +procedure WriteInt(setting:PAnsiChar;value:int); +begin + DBWriteDword(0,qs_module,setting,value) +end; +procedure WriteWord(setting:PAnsiChar;value:word); +begin + DBWriteWord(0,qs_module,setting,value) +end; +procedure WriteStr(setting:PAnsiChar;value:PAnsiChar); +begin + DBWriteString(0,qs_module,setting,value) +end; +procedure WriteUnicode(setting:PAnsiChar;value:PWideChar); +begin + DBWriteUnicode(0,qs_module,setting,value) +end; +procedure WriteBool(setting:PAnsiChar;value:bool); +begin + DBWriteByte(0,qs_module,setting,ord(value)) +end; + +procedure saveopt_wnd; +var + i:integer; + buf:array [0..127] of AnsiChar; + p,pp:PAnsiChar; +begin + WriteInt (so_mbottom ,qsopt.grrect.bottom); + WriteInt (so_mright ,qsopt.grrect.right); + WriteInt (so_mtop ,qsopt.grrect.top); + WriteInt (so_mleft ,qsopt.grrect.left); + + WriteBool(so_showoffline,qsopt.showoffline); + WriteBool(so_colorize ,qsopt.colorize); + + WriteInt (so_columnsort ,qsopt.columnsort); + + pp:=StrCopyE(buf,so_item); + for i:=0 to qsopt.numcolumns-1 do + begin + p:=StrEnd(IntToStr(pp,i)); + with qsopt.columns[i] do + begin + StrCopy(p,so__flags); WriteInt (buf,flags); + StrCopy(p,so__width); WriteWord(buf,width); + end; + end; +end; + +{ + "fast" writing" + order array - if column order only changed + column flags - if checkboxes changed only +} +procedure saveopt_db; +var + i:integer; + buf:array [0..127] of AnsiChar; + p,pp:PAnsiChar; +begin + WriteWord(so_numcolumns ,qsopt.numcolumns); + + WriteBool(so_sortbystatus ,qsopt.sortbystatus); + WriteBool(so_showinmenu ,qsopt.showinmenu); +// WriteInt (so_columnsort ,qsopt.columnsort); + WriteBool(so_ascendsort ,qsopt.ascendsort); + WriteBool(so_showonlyinlist ,qsopt.showonlyinlist); + + WriteBool(so_showintoptoolbar,qsopt.showintoptoolbar); + WriteBool(so_dontusetoolstyle,not qsopt.usetoolstyle); + WriteBool(so_closeafteraction,qsopt.closeafteraction); + WriteBool(so_drawgrid ,qsopt.drawgrid); + WriteBool(so_stayontop ,qsopt.stayontop); + WriteBool(so_showclienticons ,qsopt.showclienticons); + WriteBool(so_exportheaders ,qsopt.exportheaders); + WriteBool(so_singlecsv ,qsopt.singlecsv); + WriteBool(so_skipminimized ,qsopt.skipminimized); + WriteBool(so_savepattern ,qsopt.savepattern); + + pp:=StrCopyE(buf,so_item); + for i:=0 to qsopt.numcolumns-1 do + begin + p:=StrEnd(IntToStr(pp,i)); + with qsopt.columns[i] do + begin + StrCopy(p,so__title); + WriteUnicode(buf,title); + case setting_type of + ST_SCRIPT: begin + StrCopy(p,so__wparam); + WriteUnicode(buf,wparam.w); + end; + ST_CONTACTINFO: begin + StrCopy(p,so__setting_cnftype); WriteWord(buf,setting_cnftype); + end; + ST_SERVICE: begin + StrCopy(p,so__module_name ); WriteStr (buf,module_name); + StrCopy(p,so__setting_cnftype); WriteWord(buf,setting_cnftype); + StrCopy(p,so__wparam_type ); WriteWord(buf,wparam._type); + StrCopy(p,so__lparam_type ); WriteWord(buf,lparam._type); + StrCopy(p,so__wparam); + case wparam._type of + ptNumber, + ptInteger: WriteInt (buf,wparam.n); + ptString : WriteStr (buf,wparam.a); + ptUnicode: WriteUnicode(buf,wparam.w); + end; + StrCopy(p,so__lparam); + case lparam._type of + ptNumber, + ptInteger: WriteInt (buf,lparam.n); + ptString : WriteStr (buf,lparam.a); + ptUnicode: WriteUnicode(buf,lparam.w); + end; + end; + else + StrCopy(p,so__module_name); WriteStr(buf,module_name); + StrCopy(p,so__wparam ); WriteStr(buf,wparam.a); + end; + StrCopy(p,so__setting_type); WriteWord(buf,setting_type); + StrCopy(p,so__flags ); WriteInt (buf,flags); + StrCopy(p,so__width ); WriteWord(buf,width); + end; + end; +end; + +function GetInt(setting:PAnsiChar;default:integer):integer; +begin + result:=DBReadDWord(0,qs_module,setting,default); +end; +function GetWord(setting:PAnsiChar;default:word):word; +begin + result:=DBReadWord(0,qs_module,setting,default); +end; +function GetBool(setting:PAnsiChar;default:bool):bool; +begin + result:=bool(DBReadByte(0,qs_module,setting,integer(default))); +end; +function GetStr(setting:PAnsiChar):PAnsiChar; +begin + result:=DBReadString(0,qs_module,setting,nil); +end; +function GetUnicode(setting:PAnsiChar):PWideChar; +begin + result:=DBReadUnicode(0,qs_module,setting,nil); +end; + +{ + if "fast"writing enabled + fill columns accordingly comumn order array +} +procedure loadopt_db(full:boolean); +var + i:integer; + buf:array [0..127] of AnsiChar; + p,pp:PAnsiChar; +begin + if full then + begin + zeromemory(@qsopt,sizeof(qsopt)); + + qsopt.grrect.bottom:=GetInt(so_mbottom,240); + qsopt.grrect.right :=GetInt(so_mright,550); + qsopt.grrect.top :=GetInt(so_mtop,0); + qsopt.grrect.left :=GetInt(so_mleft,0); + + qsopt.columnsort :=GetInt (so_columnsort,StatusSort); + qsopt.sortbystatus :=GetBool(so_sortbystatus,true); + qsopt.ascendsort :=GetBool(so_ascendsort ,true); + + qsopt.showonlyinlist :=GetBool(so_showonlyinlist ,false); + qsopt.usetoolstyle :=not GetBool(so_dontusetoolstyle,false); + qsopt.showinmenu :=GetBool(so_showinmenu ,true); + qsopt.showintoptoolbar:=GetBool(so_showintoptoolbar,true); + qsopt.closeafteraction:=GetBool(so_closeafteraction,false); + qsopt.drawgrid :=GetBool(so_drawgrid ,true); + qsopt.stayontop :=GetBool(so_stayontop ,false); + qsopt.singlecsv :=GetBool(so_singlecsv ,false); + qsopt.exportheaders :=GetBool(so_exportheaders ,false); + qsopt.showoffline :=GetBool(so_showoffline ,true); + qsopt.skipminimized :=GetBool(so_skipminimized ,true); + qsopt.savepattern :=GetBool(so_savepattern ,true); + qsopt.colorize :=GetBool(so_colorize ,true); + + if ServiceExists(MS_FP_GETCLIENTICON)<>0 then + qsopt.showclienticons:=GetBool(so_showclienticons,true) + else + qsopt.showclienticons:=false; + end + else + clear_columns; + + qsopt.numcolumns:=GetWord(so_numcolumns,0); + if qsopt.numcolumns=0 then + begin + loaddefaultcolumns; + saveopt_db; + end + else + begin + pp:=StrCopyE(buf,so_item); + SetLength(qsopt.columns,qsopt.numcolumns); + FillChar(qsopt.columns[0],SizeOf(tcolumnitem)*qsopt.numcolumns,0); + for i:=0 to qsopt.numcolumns-1 do + begin + p:=StrEnd(IntToStr(pp,i)); + with qsopt.columns[i] do + begin + StrCopy(p,so__title); + title:=GetUnicode(buf); + StrCopy(p,so__setting_type); setting_type:=GetWord(buf,0); + case setting_type of + ST_SCRIPT: begin + StrCopy(p,so__wparam); + wparam.w:=GetUnicode(buf); + end; + ST_CONTACTINFO: begin + StrCopy(p,so__setting_cnftype); setting_cnftype:=GetWord(buf,0); + end; + ST_SERVICE: begin + StrCopy(p,so__setting_cnftype); setting_cnftype:=GetWord(buf,0); + StrCopy(p,so__module_name); module_name :=GetStr(buf); + StrCopy(p,so__wparam_type); wparam._type:=GetWord(buf,0); + StrCopy(p,so__lparam_type); lparam._type:=GetWord(buf,0); + StrCopy(p,so__wparam); + case wparam._type of + ptNumber, + ptInteger: wparam.n:=GetInt(buf,0); + ptString : wparam.a:=GetStr(buf); + ptUnicode: wparam.w:=GetUnicode(buf); + end; + StrCopy(p,so__lparam); + case lparam._type of + ptNumber, + ptInteger: lparam.n:=GetInt(buf,0); + ptString : lparam.a:=GetStr(buf); + ptUnicode: lparam.w:=GetUnicode(buf); + end; + end; + else + StrCopy(p,so__module_name); module_name:=GetStr(buf); + StrCopy(p,so__wparam ); wparam.a :=GetStr(buf); + end; + StrCopy(p,so__width); width:=GetWord(buf,20); + StrCopy(p,so__flags); flags:=GetInt (buf,COL_ON); + end; + end; + end; +end; + +end. diff --git a/plugins/QuickSearch/sr_optdialog.pas b/plugins/QuickSearch/sr_optdialog.pas new file mode 100644 index 0000000000..7e7e711532 --- /dev/null +++ b/plugins/QuickSearch/sr_optdialog.pas @@ -0,0 +1,1041 @@ +unit sr_optdialog; + +interface +uses windows; + +{.$include resource.inc} + +procedure OptChangeColumns(code:integer;column,data:integer); +function DlgProcOptions(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; + +const + maindlg:HWND = 0; + +implementation + +uses messages,commctrl,sr_global,m_api,common,mirutils,wrapper,sr_window; + +var + OldListProc:pointer; +const + curscript:pointer=nil; + +const + stByte :PAnsiChar = 'Byte'; + stWord :PAnsiChar = 'Word'; + stInt :PAnsiChar = 'Int'; + stString :PAnsiChar = 'String'; + stLastSeen :PAnsiChar = 'LastSeen'; + stIP :PAnsiChar = 'IP'; + stContactInfo:PAnsiChar = 'ContactInfo'; + stLastEvent :PAnsiChar = 'LastEvent'; + stTimeStamp :PAnsiChar = 'TimeStamp'; + stService :PAnsiChar = 'Service'; + stScript :PAnsiChar = 'Script'; + stMetacontact:PAnsiChar = 'Metacontact'; + +const + cnFirstName = 'FIRSTNAME' ; + cnLastName = 'LASTNAME' ; + cnNick = 'NICK' ; + cnCustomNick = 'CUSTOMNICK'; + cnEmail = 'EMAIL' ; + cnCity = 'CITY' ; + cnState = 'STATE' ; + cnCountry = 'COUNTRY' ; + cnPhone = 'PHONE' ; + cnHomepage = 'HOMEPAGE' ; + cnAbout = 'ABOUT' ; + cnGender = 'GENDER' ; + cnAge = 'AGE' ; + cnFirstLast = 'FIRSTLAST' ; + cnUniqueID = 'UNIQUEID' ; + cnFax = 'FAX' ; + cnCellular = 'CELLULAR' ; + cnTimezone = 'TIMEZONE' ; + cnMyNotes = 'MYNOTES' ; + cnBirthday = 'BIRTHDAY' ; + cnBirthMonth = 'BIRTHMONTH'; + cnBirthYear = 'BIRTHYEAR' ; + cnZIP = 'ZIP' ; + cnStreet = 'STREET' ; + cnLanguage1 = 'LANGUAGE1' ; + cnLanguage2 = 'LANGUAGE2' ; + cnLanguage3 = 'LANGUAGE3' ; + cnCoName = 'CONAME' ; + +const + strNotSelected = 'Not Selected'; + +const + MaxControls = 13; + aIdElement:array [0..MaxControls-1] of integer = ( + IDC_SCRIPT, IDC_STAT_VARTYPE, IDC_C_CNFTYPE, IDC_C_RESULT, + IDC_STAT_SERVICE, IDC_STAT_MODULE, IDC_E_MODULE, + IDC_STAT_WPAR, IDC_STAT_SETTING, IDC_E_VAR, + IDC_C_WPAR, IDC_E_LPAR, IDC_C_LPAR); + + aShowElement:array [0..ST_MAXTYPE,0..MaxControls-1] of byte = ( +{ST_BYTE } ($00, $80, $80, $00, $00, $81, $81, $00, $81, $81, $80, $80, $80), +{ST_WORD } ($00, $80, $80, $00, $00, $81, $81, $00, $81, $81, $80, $80, $80), +{ST_INT } ($00, $80, $80, $00, $00, $81, $81, $00, $81, $81, $80, $80, $80), +{ST_STRING } ($00, $80, $80, $00, $00, $81, $81, $00, $81, $81, $80, $80, $80), +{ST_IP } ($00, $80, $80, $00, $00, $81, $81, $00, $81, $81, $80, $80, $80), +{ST_LASTSEEN } ($00, $80, $80, $00, $00, $81, $81, $00, $81, $81, $80, $80, $80), +{ST_CONTACTINFO} ($00, $81, $81, $00, $00, $80, $80, $00, $80, $80, $80, $80, $80), +{ST_LASTEVENT } ($00, $80, $80, $00, $00, $80, $80, $00, $80, $80, $80, $80, $80), +{ST_TIMESTAMP } ($00, $80, $80, $00, $00, $81, $81, $00, $81, $81, $80, $80, $80), +{ST_SERVICE } ($00, $80, $00, $81, $81, $00, $81, $81, $00, $81, $81, $81, $81), +{ST_SCRIPT } ($81, $00, $00, $00, $00, $80, $80, $00, $80, $80, $80, $80, $80), +{ST_METACONTACT} ($00, $80, $80, $00, $00, $80, $80, $00, $80, $80, $80, $80, $80)); + +procedure SetupControls(Dialog:HWND; aType:integer); +var + i,j: cardinal; + wnd:HWND; +begin + for i:=0 to MaxControls-1 do + begin + j :=aShowElement[aType][i]; + wnd:=GetDlgItem(Dialog,aIdElement[i]); + EnableWindow(wnd,odd(j)); + if shortint(j)<0 then + j:=SW_SHOW + else + j:=SW_HIDE; + ShowWindow(wnd,j); + end; +end; + +function settype2str(settype:integer):pointer; +var + tmp:array [0..127] of WideChar; +begin + case settype of +// ST_BYTE: result:=stByte; + ST_WORD: result:=stWord; + ST_INT: result:=stInt; + ST_STRING: result:=stString; + ST_LASTSEEN: result:=stLastSeen; + ST_IP: result:=stIP; + ST_CONTACTINFO: result:=stContactInfo; + ST_LASTEVENT: result:=stLastEvent; + ST_TIMESTAMP: result:=stTimeStamp; + ST_SERVICE: result:=stService; + ST_SCRIPT: result:=stScript; + ST_METACONTACT: result:=stMetacontact; + else + result:=stByte; + end; + + FastAnsiToWideBuf(result,tmp); + StrDupW(pWideChar(result),TranslateW(tmp)); +end; + +function setcnftype2str(settype:integer):PWideChar; +var + res:pWideChar; +begin + case settype of +// CNF_FIRSTNAME: result:=translate(cnFirstName); + CNF_LASTNAME: res:=cnLastName ; + CNF_NICK: res:=cnNick ; + CNF_CUSTOMNICK: res:=cnCustomNick; + CNF_EMAIL: res:=cnEmail ; + CNF_CITY: res:=cnCity ; + CNF_STATE: res:=cnState ; + CNF_COUNTRY: res:=cnCountry ; + CNF_PHONE: res:=cnPhone ; + CNF_HOMEPAGE: res:=cnHomepage ; + CNF_ABOUT: res:=cnAbout ; + CNF_GENDER: res:=cnGender ; + CNF_AGE: res:=cnAge ; + CNF_FIRSTLAST: res:=cnFirstLast ; + CNF_UNIQUEID: res:=cnUniqueID ; + + CNF_FAX: res:=cnFax ; + CNF_CELLULAR: res:=cnCellular ; + CNF_TIMEZONE: res:=cnTimezone ; + CNF_MYNOTES: res:=cnMyNotes ; + CNF_BIRTHDAY: res:=cnBirthday ; + CNF_BIRTHMONTH: res:=cnBirthMonth; + CNF_BIRTHYEAR: res:=cnBirthYear ; + CNF_STREET: res:=cnStreet ; + CNF_ZIP: res:=cnZIP ; + CNF_LANGUAGE1: res:=cnLanguage1 ; + CNF_LANGUAGE2: res:=cnLanguage2 ; + CNF_LANGUAGE3: res:=cnLanguage3 ; + CNF_CONAME: res:=cnCoName ; + else + res:=cnFirstName; + end; + result:=TranslateW(res); +end; + +procedure addcolumn(handle:hwnd;width:word;title:PAnsiChar); +var + lvcol:LV_COLUMNW; + buf:array [0..127] of WideChar; +begin + lvcol.mask:=LVCF_TEXT or LVCF_WIDTH; + lvcol.cx :=width; + lvcol.pszText:=TranslateW(FastAnsiToWideBuf(title,buf)); + SendMessageW(handle,LVM_INSERTCOLUMNW,0,lparam(@lvcol)); +end; + +function getselecteditem(list:hwnd):integer; +begin + result:=SendMessage(list,LVM_GETNEXTITEM,-1,LVNI_FOCUSED); +end; + +function savecuritem(Dialog:hwnd):integer; +var + listhwnd:hwnd; + selitem:integer; + + procedure GetText(id,subpos:integer;var dst:PAnsiChar); overload; + var + tpc:array [0..1023] of AnsiChar; + begin + GetDlgItemTextA(Dialog,id,tpc,SizeOf(tpc)); + mFreeMem(dst); + StrDup(dst,tpc); + LV_SetItem(listhwnd,dst,selitem,subpos); + end; + + // now for Title only + procedure GetText(id,subpos:integer;var dst:PWideChar); overload; + var + tpc:array [0..1023] of WideChar; + begin + GetDlgItemTextW(Dialog,id,@tpc,SizeOf(tpc) div SizeOf(WideChar)); + mFreeMem(dst); + StrDupW(dst,@tpc); + LV_SetItemW(listhwnd,dst,selitem,subpos); + end; + + procedure setparam(var param:tserviceparam;cb,id:integer); + var + z:bool; + tpc:array [0..1023] of WideChar; + begin + param._type:=SendDlgItemMessage(Dialog,cb,CB_GETCURSEL,0,0); + case param._type of + ptNumber: param.n:=GetDlgItemInt(Dialog,id,z,false); + ptInteger: param.i:=GetDlgItemInt(Dialog,id,z,true); + ptString: begin + GetDlgItemTextA(Dialog,id,@tpc,SizeOf(tpc)); + StrDup(param.a,@tpc); + end; + ptUnicode: begin + GetDlgItemTextW(Dialog,id,@tpc,SizeOf(tpc) div SizeOf(WideChar)); + StrDupW(param.w,@tpc); + end; + end; + end; + +var + tpc :array [0..127] of WideChar; + tmpwnd:HWND; + oldtype,i:integer; + column:integer; +begin + listhwnd:=GetDlgItem(Dialog,IDC_LIST); + selitem:=getselecteditem(listhwnd); +//!! column:=LV_GetLParam(listhwnd,selitem); + column:=selitem; + result:=selitem; + if (selitem>=0) and (selitemptCurrent); + end; + +var + v:PWideChar; + i:int_ptr; + selpos:integer; +begin + CheckDirection(Dialog,column); + + selpos:=column; + if (selpos>=0) and (selpos0); + LV_SetItemW(list,title,i,1); + case setting_type of + ST_METACONTACT: begin + LV_SetItemW(list,TranslateW('Metacontact'),i,2); + end; + + ST_CONTACTINFO: begin + LV_SetItemW(list,setcnftype2str(setting_cnftype),i,2) + end; + + ST_SCRIPT: begin + LV_SetItemW(list,TranslateW('Script'),i,2); + end; + + ST_SERVICE: begin + LV_SetItemW(list,TranslateW('Service'),i,2); + LV_SetItem(list,module_name,i,3); + end; + else + LV_SetItem(list,module_name,i,2); + LV_SetItem(list,wparam.a,i,3); + end; + end; +end; + +procedure update_list(list:hwnd); +var + i:integer; +begin + ListView_DeleteAllItems(list); + ListView_SetItemCount(list,qsopt.numcolumns); + + for i:=0 to qsopt.numcolumns-1 do + begin + add_column(list,i); + end; +//!! SortColumns(list); + ListView_SetItemState(list,0,LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); +end; + +procedure addresulttypes(list:integer); +begin + SendMessageW(list,CB_INSERTSTRING,ptNumber ,lparam(TranslateW('number value' ))); + SendMessageW(list,CB_INSERTSTRING,ptInteger,lparam(TranslateW('integer value' ))); + SendMessageW(list,CB_INSERTSTRING,ptString ,lparam(TranslateW('ANSI string' ))); + SendMessageW(list,CB_INSERTSTRING,ptUnicode,lparam(TranslateW('Unicode string'))); + SendMessage(list,CB_SETCURSEL,0,0); +end; + +procedure addparamtypes(list:integer); +begin + addresulttypes(list); + SendMessageW(list,CB_INSERTSTRING,ptCurrent,lparam(TranslateW('current contact'))); +end; + +procedure AddVal(list:HWND;param:integer); +var + i:integer; + v:pointer; +begin + v:=settype2str(param); + i:=SendMessageW(list,CB_ADDSTRING,0,lparam(v)); + mFreeMem(v); + SendMessage(list,CB_SETITEMDATA,i,param); +end; + +procedure addsettypes(list:hwnd); +begin + AddVal(list,ST_BYTE); + AddVal(list,ST_WORD); + AddVal(list,ST_INT); + AddVal(list,ST_STRING); + AddVal(list,ST_LASTSEEN); + AddVal(list,ST_IP); + AddVal(list,ST_CONTACTINFO); + AddVal(list,ST_LASTEVENT); + AddVal(list,ST_TIMESTAMP); + AddVal(list,ST_SERVICE); + AddVal(list,ST_SCRIPT); + AddVal(list,ST_METACONTACT); + SendMessage(list,CB_SETCURSEL,0,0); +end; + +procedure AddCnf(list:HWND;param:integer); +begin + SendMessage(list,CB_SETITEMDATA, + SendMessageW(list,CB_ADDSTRING,0,lparam(setcnftype2str(param))), + param); +// mFreeMem(str); +end; + +procedure addsetcnftypes(list:hwnd); +begin + AddCnf(list,CNF_FIRSTNAME); + AddCnf(list,CNF_LASTNAME); + AddCnf(list,CNF_NICK); + AddCnf(list,CNF_CUSTOMNICK); + AddCnf(list,CNF_EMAIL); + AddCnf(list,CNF_CITY); + AddCnf(list,CNF_STATE); + AddCnf(list,CNF_COUNTRY); + AddCnf(list,CNF_PHONE); + AddCnf(list,CNF_HOMEPAGE); + AddCnf(list,CNF_ABOUT); + AddCnf(list,CNF_GENDER); + AddCnf(list,CNF_AGE); + AddCnf(list,CNF_FIRSTLAST); + AddCnf(list,CNF_UNIQUEID); + + AddCnf(list,CNF_FAX); + AddCnf(list,CNF_CELLULAR); + AddCnf(list,CNF_TIMEZONE); + AddCnf(list,CNF_MYNOTES); + AddCnf(list,CNF_BIRTHDAY); + AddCnf(list,CNF_BIRTHMONTH); + AddCnf(list,CNF_BIRTHYEAR); + AddCnf(list,CNF_STREET); + AddCnf(list,CNF_ZIP); + AddCnf(list,CNF_LANGUAGE1); + AddCnf(list,CNF_LANGUAGE2); + AddCnf(list,CNF_LANGUAGE3); + AddCnf(list,CNF_CONAME); + + SendMessage(list,CB_SETCURSEL,0,0); +end; + +procedure _GetIcon(idc:integer;ico:PAnsiChar); +begin + SetButtonIcon(GetDlgItem(maindlg,idc),ico); +end; + +function IconChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl; +begin + result:=0; + _GetIcon(IDC_NEW ,QS_NEW); + _GetIcon(IDC_SETITEM,QS_ITEM); + _GetIcon(IDC_UP ,QS_UP); + _GetIcon(IDC_DN ,QS_DOWN); + _GetIcon(IDC_DELETE ,QS_DELETE); + _GetIcon(IDC_DEFAULT,QS_DEFAULT); + _GetIcon(IDC_RELOAD ,QS_RELOAD); +end; + +function ScriptEdit(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + tmp:pointer; + vhi:TVARHELPINFO; +begin + result:=0; + case hMessage of + + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + SetDlgItemTextW(Dialog,IDC_EDIT_SCRIPT,pWideChar(lParam)); + end; + + WM_COMMAND: begin + case wParam shr 16 of + BN_CLICKED: begin + case loword(wParam) of + IDHELP: SendMessage(Dialog,WM_HELP,0,0); + IDOK: begin + tmp:=GetDlgText(Dialog,IDC_EDIT_SCRIPT); + EndDialog(Dialog,tlparam(tmp)); + end; + IDCANCEL: begin // clear result / restore old value + EndDialog(Dialog,0); + end; + end; + end; + end; + end; + + WM_HELP: begin + FillChar(vhi,SizeOf(vhi),0); + with vhi do + begin + cbSize:=SizeOf(vhi); + flags:=VHF_NOINPUTDLG; + end; + CallService(MS_VARS_SHOWHELPEX,Dialog,tlparam(@vhi)); + end; + end; +end; + +function NewListProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):integer; stdcall; +begin + result:=0; + if hMessage=WM_KEYDOWN then + begin + case wParam of + VK_INSERT: begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_NEW,0); + exit; + end; + VK_DELETE: begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_DELETE,0); + exit; + end; + VK_UP: begin + if (GetKeyState(VK_CONTROL) and $8000)<>0 then + begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_UP,0); + exit; + end; + end; + VK_DOWN: begin + if (GetKeyState(VK_CONTROL) and $8000)<>0 then + begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_DN,0); + exit; + end; + end; + end; + end; + result:=CallWindowProc(OldListProc,Dialog,hMessage,wParam,lParam); +end; + +function DlgProcOptions(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +const + InitDlg:bool = true; + hook:THANDLE = 0; +var +// tpc:array [0..255] of AnsiChar; + itemsel:integer; + tmpwnd:HWND; + tmpbool:bool; + i:integer; +// ti:TTOOLINFOW; +// hwndTooltip:HWND; + hNew :hwnd; + hItem :hwnd; + hUp :hwnd; + hDown :hwnd; + hDelete :hwnd; + hDefault:hwnd; + hReload :hwnd; + listhwnd:hwnd; + tmpcol:tcolumnitem; +begin + result:=0; + + case hMessage of + WM_DESTROY: begin + // if closed by Cancel, with changes but without apply + loadopt_db(false); //!!!! + WndChangeColumns(wcRefresh); + + mFreeMem(curscript); + if hook<>0 then + UnhookEvent(hook); + maindlg:=0; + end; + + WM_INITDIALOG: begin + InitDlg:=true; + listhwnd:=GetDlgItem(Dialog,IDC_LIST); + + SendMessageW(listhwnd,LVM_SETEXTENDEDLISTVIEWSTYLE,0, + SendMessageW(listhwnd,LVM_GETEXTENDEDLISTVIEWSTYLE,0,0) or + LVS_EX_FULLROWSELECT or LVS_EX_CHECKBOXES); + + TranslateDialogDefault(Dialog); + + addcolumn(listhwnd,95 ,'Setting'); + addcolumn(listhwnd,105,'Module/InfoType'); + addcolumn(listhwnd,85 ,'Title'); + addcolumn(listhwnd,20 ,'#'); + addsettypes (GetDlgItem(Dialog,IDC_C_VARTYPE)); + addsetcnftypes(GetDlgItem(Dialog,IDC_C_CNFTYPE)); + addparamtypes (GetDlgItem(Dialog,IDC_C_WPAR)); + addparamtypes (GetDlgItem(Dialog,IDC_C_LPAR)); + addresulttypes(GetDlgItem(Dialog,IDC_C_RESULT)); + + CheckDlgButton(Dialog,IDC_CH_SORTSTATUS ,ORD(qsopt.sortbystatus)); + CheckDlgButton(Dialog,IDC_CH_SHOWINMENU ,ORD(qsopt.showinmenu)); + CheckDlgButton(Dialog,IDC_CH_SHOWONLYUSERS ,ORD(qsopt.showonlyinlist)); + CheckDlgButton(Dialog,IDC_CH_AUTOCLOSE ,ORD(qsopt.closeafteraction)); + CheckDlgButton(Dialog,IDC_CH_ADDTOTOPTOOLBAR,ORD(qsopt.showintoptoolbar)); + CheckDlgButton(Dialog,IDC_CH_USETOOLSTYLE ,ORD(qsopt.usetoolstyle)); + CheckDlgButton(Dialog,IDC_CH_DRAWGRID ,ORD(qsopt.drawgrid)); + CheckDlgButton(Dialog,IDC_CH_SINGLECSV ,ORD(qsopt.singlecsv)); + CheckDlgButton(Dialog,IDC_CH_EXPORTHEADERS ,ORD(qsopt.exportheaders)); + CheckDlgButton(Dialog,IDC_CH_SKIPMINIMIZED ,ORD(qsopt.skipminimized)); + CheckDlgButton(Dialog,IDC_CH_SAVEPATTERN ,ORD(qsopt.savepattern)); + if ServiceExists(MS_FP_GETCLIENTICON)<>0 then + CheckDlgButton(Dialog,IDC_CH_SHOWCLIENTICONS,ORD(qsopt.showclienticons)) + else + EnableWindow(GetDlgItem(Dialog,IDC_CH_SHOWCLIENTICONS),false); + + if ServiceExists(MS_TTB_ADDBUTTON)=0 then + EnableWindow(GetDlgItem(Dialog,IDC_CH_ADDTOTOPTOOLBAR),FALSE); +{ + hwndTooltip:=CreateWindowW(TOOLTIPS_CLASS,nil,TTS_ALWAYSTIP, + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + Dialog,0,hInstance,nil); +} + hNew :=GetDlgItem(Dialog,IDC_NEW); + SendMessage(hNew,BUTTONADDTOOLTIP,TWPARAM(TranslateW('New')),BATF_UNICODE); + hItem :=GetDlgItem(Dialog,IDC_SETITEM); + SendMessage(hItem,BUTTONADDTOOLTIP,TWPARAM(TranslateW('Save Item')),BATF_UNICODE); + hUp :=GetDlgItem(Dialog,IDC_UP); + SendMessage(hUp,BUTTONADDTOOLTIP,TWPARAM(TranslateW('Up')),BATF_UNICODE); + hDown :=GetDlgItem(Dialog,IDC_DN); + SendMessage(hDown,BUTTONADDTOOLTIP,TWPARAM(TranslateW('Down')),BATF_UNICODE); + hDelete :=GetDlgItem(Dialog,IDC_DELETE); + SendMessage(hDelete,BUTTONADDTOOLTIP,TWPARAM(TranslateW('Delete')),BATF_UNICODE); + hDefault:=GetDlgItem(Dialog,IDC_DEFAULT); + SendMessage(hDefault,BUTTONADDTOOLTIP,TWPARAM(TranslateW('Default')),BATF_UNICODE); + hReload :=GetDlgItem(Dialog,IDC_RELOAD); + SendMessage(hReload,BUTTONADDTOOLTIP,TWPARAM(TranslateW('Reload')),BATF_UNICODE); +{ + FillChar(ti,SizeOf(ti),0); + ti.cbSize :=sizeof(TOOLINFO); + ti.uFlags :=TTF_IDISHWND or TTF_SUBCLASS; + ti.hwnd :=Dialog; + ti.hinst :=hInstance; + ti.uId :=hNew; + ti.lpszText:=TranslateW('New'); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); + ti.uId :=hItem; + ti.lpszText:=TranslateW('Save Item'); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); + ti.uId :=hUp; + ti.lpszText:=TranslateW('Up'); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); + ti.uId :=hDown; + ti.lpszText:=TranslateW('Down'); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); + ti.uId :=hDelete; + ti.lpszText:=TranslateW('Delete'); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); + ti.uId :=hDefault; + ti.lpszText:=TranslateW('Default'); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); + ti.uId :=hReload; + ti.lpszText:=TranslateW('Reload'); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); +} + SetButtonIcon(hNew ,QS_NEW); + SetButtonIcon(hItem, QS_ITEM); + SetButtonIcon(hUp ,QS_UP); + SetButtonIcon(hDown ,QS_DOWN); + SetButtonIcon(hDelete ,QS_DELETE); + SetButtonIcon(hDefault,QS_DEFAULT); + SetButtonIcon(hReload ,QS_RELOAD); + + update_list(listhwnd); + + maindlg:=Dialog; + hook:=HookEvent(ME_SKIN2_ICONSCHANGED,@IconChanged); + + result:=1; + + OldListProc:=pointer(SetWindowLongPtrW(listhwnd,GWL_WNDPROC,LONG_PTR(@NewListProc))); + + InitDlg:=false; + end; + + WM_NOTIFY: begin + case integer(PNMHdr(lParam)^.code) of + + PSN_APPLY: begin + // checkboxes + listhwnd:=GetDlgItem(Dialog,IDC_LIST); + + for i:=0 to SendMessage(listhwnd,LVM_GETITEMCOUNT,0,0)-1 do + begin + with qsopt.columns[i] do + begin + if ListView_GetCheckSTate(listhwnd,i)=0 then + flags:=flags and not COL_ON + else + flags:=flags or COL_ON; + end; + end; + + disable_elem(Dialog,IDC_SETITEM); + savecuritem(Dialog); + + qsopt.sortbystatus :=IsDlgButtonChecked(Dialog,IDC_CH_SORTSTATUS )<>BST_UNCHECKED; + qsopt.showonlyinlist :=IsDlgButtonChecked(Dialog,IDC_CH_SHOWONLYUSERS )<>BST_UNCHECKED; + qsopt.closeafteraction:=IsDlgButtonChecked(Dialog,IDC_CH_AUTOCLOSE )<>BST_UNCHECKED; + qsopt.usetoolstyle :=IsDlgButtonChecked(Dialog,IDC_CH_USETOOLSTYLE )<>BST_UNCHECKED; + qsopt.drawgrid :=IsDlgButtonChecked(Dialog,IDC_CH_DRAWGRID )<>BST_UNCHECKED; + qsopt.showclienticons :=IsDlgButtonChecked(Dialog,IDC_CH_SHOWCLIENTICONS)<>BST_UNCHECKED; + qsopt.singlecsv :=IsDlgButtonChecked(Dialog,IDC_CH_SINGLECSV )<>BST_UNCHECKED; + qsopt.exportheaders :=IsDlgButtonChecked(Dialog,IDC_CH_EXPORTHEADERS )<>BST_UNCHECKED; + qsopt.skipminimized :=IsDlgButtonChecked(Dialog,IDC_CH_SKIPMINIMIZED )<>BST_UNCHECKED; + qsopt.savepattern :=IsDlgButtonChecked(Dialog,IDC_CH_SAVEPATTERN )<>BST_UNCHECKED; + + tmpbool:=IsDlgButtonChecked(Dialog,IDC_CH_SHOWINMENU)<>BST_UNCHECKED; + if qsopt.showinmenu<>tmpbool then + begin + qsopt.showinmenu:=tmpbool; + AddRemoveMenuItemToMainMenu; + end; + tmpbool:=IsDlgButtonChecked(Dialog,IDC_CH_ADDTOTOPTOOLBAR )<>BST_UNCHECKED; + if qsopt.showintoptoolbar<>tmpbool then + begin + qsopt.showintoptoolbar:=tmpbool; + addtotoolbar; + end; + + saveopt_db; + result:=1; + end; + + LVN_ITEMCHANGED: begin + if wParam=IDC_LIST then + begin + i:=(PNMLISTVIEW(lParam)^.uOldState and LVNI_FOCUSED)- + (PNMLISTVIEW(lParam)^.uNewState and LVNI_FOCUSED); + if i<0 then // new focus + begin + InitDlg:=true; + displcurinfo(Dialog,PNMLISTVIEW(lParam)^.iItem); +{!! + displcurinfo(Dialog, + LV_GetLParam(PNMLISTVIEW(lParam)^.hdr.hwndFrom, + PNMLISTVIEW(lParam)^.iItem)); +} + InitDlg:=false; + result:=1; + end else if (i=0) and not InitDlg then + begin + if (PNMLISTVIEW(lParam)^.uOldState or PNMLISTVIEW(lParam)^.uNewState)=$3000 then + begin + i:=PNMLISTVIEW(lParam)^.uOldState-PNMLISTVIEW(lParam)^.uNewState; + if abs(i)=$1000 then + begin + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + if i<0 then + i:=wcShow + else + i:=wcHide; + WndChangeColumns(i,PNMLISTVIEW(lParam)^.iItem); + result:=1; + end; + end; + end; + end; + end; + + end; + end; + + WM_MYSHOWHIDEITEM: begin + InitDlg:=true; + ListView_SetCheckState(GetDlgItem(Dialog,IDC_LIST),wParam,lParam<>0); + InitDlg:=false; + end; + + WM_MYMOVEITEM: begin + listhwnd:=GetDlgItem(Dialog,IDC_LIST); + LV_MoveItem(listhwnd,lParam,wParam); + itemsel:=wParam+lParam; + i:=SizeOf(tcolumnitem)*abs(integer(lParam)); + move(qsopt.columns[wParam],tmpcol,SizeOf(tcolumnitem)); + + if integer(lParam)>0 then + move(qsopt.columns[wParam+1],qsopt.columns[wParam],i) + else + move(qsopt.columns[itemsel],qsopt.columns[itemsel+1],i); + + move(tmpcol,qsopt.columns[itemsel],SizeOf(tcolumnitem)); + + CheckDirection(Dialog,getselecteditem(listhwnd)); + end; + + WM_COMMAND: begin + if ((wParam shr 16)=CBN_SELCHANGE) then + begin + case loword(wParam) of + IDC_C_VARTYPE: begin + i:=SendMessage(lParam,CB_GETITEMDATA, + SendMessage(lParam,CB_GETCURSEL,0,0),0); + + SetupControls(Dialog,i); + + EnableWindow(GetDlgItem(Dialog,IDC_E_VAR), + SendDlgItemMessage(Dialog,IDC_C_WPAR,CB_GETCURSEL,0,0)<>ptCurrent); + EnableWindow(GetDlgItem(Dialog,IDC_E_LPAR), + SendDlgItemMessage(Dialog,IDC_C_LPAR,CB_GETCURSEL,0,0)<>ptCurrent); + end; + IDC_C_WPAR: begin + EnableWindow(GetDlgItem(Dialog,IDC_E_VAR), + SendMessage(lParam,CB_GETCURSEL,0,0)<>ptCurrent); + end; + IDC_C_LPAR: begin + EnableWindow(GetDlgItem(Dialog,IDC_E_LPAR), + SendMessage(lParam,CB_GETCURSEL,0,0)<>ptCurrent); + end; + end; + end; + + if not InitDlg then + case wParam shr 16 of + CBN_SELCHANGE, + BN_CLICKED, + EN_CHANGE: begin + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + enable_elem(Dialog,IDC_SETITEM); + end; + end; + + listhwnd:=GetDlgItem(Dialog,IDC_LIST); + result:=1; + case loword(wParam) of + IDC_SCRIPT: begin + tmpwnd:=DialogBoxParamW(hInstance,MAKEINTRESOURCEW(IDD_SCRIPT), + Dialog,@ScriptEdit,tlparam(curscript)); + if tmpwnd<>0 then + begin + curscript:=pointer(tmpwnd); + end; + end; + + IDC_NEW: begin + InitDlg:=true; + WndChangeColumns(wcInsert, + add_column(listhwnd,new_column(getselecteditem(listhwnd)))); + + SendMessage(listhwnd,LVM_ENSUREVISIBLE,qsopt.numcolumns-1,0); + ListView_SetItemState(listhwnd,qsopt.numcolumns-1, + LVIS_FOCUSED+LVIS_SELECTED,LVIS_FOCUSED+LVIS_SELECTED); + InitDlg:=false; + end; + + IDC_DELETE: begin + i:=getselecteditem(listhwnd); + SendMessage(listhwnd,LVM_DELETEITEM,i,0); + delete_column(i); + WndChangeColumns(wcDelete,i); +// update_list(listhwnd); + + if i=qsopt.numcolumns then dec(i); + ListView_SetItemState(listhwnd,i, + LVIS_FOCUSED+LVIS_SELECTED,LVIS_FOCUSED+LVIS_SELECTED); + end; + + IDC_UP: begin + itemsel:=getselecteditem(listhwnd); + if itemsel>0 then + begin + LV_MoveItem(listhwnd,-1,itemsel); + move(qsopt.columns[itemsel] ,tmpcol ,SizeOf(tcolumnitem)); + move(qsopt.columns[itemsel-1],qsopt.columns[itemsel] ,SizeOf(tcolumnitem)); + move(tmpcol ,qsopt.columns[itemsel-1],SizeOf(tcolumnitem)); + WndChangeColumns(wcUp,itemsel); + CheckDirection(Dialog,itemsel-1); + end; + end; + + IDC_DN: begin + itemsel:=getselecteditem(listhwnd); + if (itemsel>=0) and (itemsel<(qsopt.numcolumns-1)) then + begin + LV_MoveItem(listhwnd,1,itemsel); + move(qsopt.columns[itemsel] ,tmpcol ,SizeOf(tcolumnitem)); + move(qsopt.columns[itemsel+1],qsopt.columns[itemsel] ,SizeOf(tcolumnitem)); + move(tmpcol ,qsopt.columns[itemsel+1],SizeOf(tcolumnitem)); + WndChangeColumns(wcDown,itemsel); + CheckDirection(Dialog,itemsel+1); + end; + end; + + IDC_SETITEM: begin + WndChangeColumns(wcChange,savecuritem(Dialog)); + end; + + IDC_DEFAULT: begin + InitDlg:=true; + loaddefaultcolumns; + update_list(listhwnd); + WndChangeColumns(wcRefresh); + InitDlg:=false; + end; + + IDC_RELOAD: begin + InitDlg:=true; + loadopt_db(false); + update_list(listhwnd); + WndChangeColumns(wcRefresh); + InitDlg:=false; + end; + else + result:=0; + end; + end; +// else +// result:=DefWindowProc(Dialog,hMessage,wParam,lParam); + end; + DefWindowProc(Dialog,hMessage,wParam,lParam); +end; + +procedure OptChangeColumns(code:integer;column,data:integer); +begin + case code of + wcUp: begin + SendMessage(maindlg,WM_MYSHOWHIDEITEM,column,data); + end; + + wcShow: begin + SendMessage(maindlg,WM_MYSHOWHIDEITEM,column,data); + end; + end; +end; + +end. diff --git a/plugins/QuickSearch/sr_window.pas b/plugins/QuickSearch/sr_window.pas new file mode 100644 index 0000000000..5df340f575 --- /dev/null +++ b/plugins/QuickSearch/sr_window.pas @@ -0,0 +1,2943 @@ +unit sr_window; + +interface + +uses windows,m_api; + +function OpenSrWindow(apattern:PWideChar;flags:LPARAM):boolean; +function BringToFront:integer; +function CloseSrWindow:boolean; +procedure WndChangeColumns(code:integer;column:integer=-1); + +function OnContactAdded (wParam:WPARAM;lParam:LPARAM):int;cdecl; +function OnStatusChanged (wParam:WPARAM;lParam:LPARAM):int;cdecl; +function OnContactDeleted(wParam:WPARAM;lParam:LPARAM):int;cdecl; +function OnAccountChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl; +procedure RegisterColors; + +const + grid:HWND = 0; + +implementation + +uses messages,commctrl,sr_global,common,dbsettings,mirutils, + wrapper,sr_optdialog,protocols; + +const + flt_show_offline = $100; +const + strCListDel:PAnsiChar='CList/DeleteContactCommand'; +const + LVS_EX_LABELTIP = $4000; +const + hIconF :HICON = 0; + hIconM :HICON = 0; + mainwnd :HWND = 0; + StatusBar:HWND = 0; + sortcoldn:THANDLE = 0; + sortcolup:THANDLE = 0; + gridbrush:HBRUSH = 0; +const + OldLVProc :pointer = nil; + OldProc :pointer = nil; + OldEditProc:pointer = nil; +const + pattern:pWideChar = nil; +const + QSF_INLIST = $0001; // in constant list + QSF_ACTIVE = $0002; // contact in listview + QSF_DELETED = $0004; // contact deleted + QSF_PATTERN = $0008; // pattern check passed + QSF_ACCDEL = $0010; // account deleted + QSF_ACCOFF = $0020; // account disabled + QSF_META = $0040; // contact is metacontact + QSF_SUBMETA = $0080; // contact is part of metacontact + +type + pQSRec = ^tQSRec; + tQSRec = record // cell + text:PWideChar; + data:uint_ptr; + end; + pQSFRec = ^tQSFRec; + tQSFRec = record // row + contact:THANDLE; + proto :uint_ptr; + flags :dword; + status :dword; + wparam :WPARAM; + lparam :LPARAM; + end; +var + colorhook:THANDLE; + MainBuf:array of array of tQSRec; + FlagBuf:array of tQSFRec; + LastMeta:integer; + tstrMale, + tstrFemale, + tstrUnknown:PWideChar; + colorder:array of integer; + tablecolumns:integer; + +const + maxpattern = 8; +var + patterns:array [0..maxpattern-1] of record + str:PWideChar; + res:bool; + end; +const + patstr:PWideChar=nil; + numpattern:integer=0; + +const + TIMERID_HOVER = 10; +const + TTShowed:bool=false; + TTInstalled:bool = false; + +const + bkg_norm:pAnsiChar = 'Normal background'; + fgr_norm:pAnsiChar = 'Normal foreground'; + bkg_odd :pAnsiChar = 'Odd background'; + fgr_odd :pAnsiChar = 'Odd foreground'; + bkg_dis :pAnsiChar = 'Disabled account background'; + fgr_dis :pAnsiChar = 'Disabled account foreground'; + bkg_del :pAnsiChar = 'Deleted account background'; + fgr_del :pAnsiChar = 'Deleted account foreground'; + bkg_hid :pAnsiChar = 'Hidden contact background'; + fgr_hid :pAnsiChar = 'Hidden contact foreground'; + bkg_meta:pAnsiChar = 'Metacontact background'; + fgr_meta:pAnsiChar = 'Metacontact foreground'; + bkg_sub :pAnsiChar = 'SubMetacontact background'; + fgr_sub :pAnsiChar = 'SubMetacontact foreground'; + +var + cbkg_norm, + cfgr_norm, + cbkg_odd, + cfgr_odd, + cbkg_dis, + cfgr_dis, + cbkg_del, + cfgr_del, + cbkg_hid, + cfgr_hid, + cbkg_meta, + cfgr_meta, + cbkg_sub, + cfgr_sub:TCOLORREF; + AdvFilter:cardinal; + +function GetQSColumn(item:integer):LPARAM; +var + i:integer; +begin + for i:=0 to qsopt.numcolumns-1 do + begin + if colorder[i]=item then + begin + result:=i; + exit; + end; + end; + result:=-1; +end; +{ +procedure SwitchOrder(var src,dst:array of dword); +var + i:integer; +begin + for i:=0 to HIGH(src) do + begin + dst[src[i]]:=i; + end; +end; +} +procedure ShiftColumns(item,shift:integer); // item - table item, order - new screen order +var + i,col:integer; + buf:tQSRec; + lsize,lshift:integer; +begin + col:=-1; + lshift:=0; + for i:=0 to qsopt.numcolumns-1 do + begin + if (qsopt.columns[i].flags and COL_ON)<>0 then + begin + if shift=0 then + col:=i; // new position + dec(shift); + end; + if colorder[i]=item then + begin + lshift:=i; // column in buffer + end; + end; + item:=lshift; + shift:=col-item; + + col:=colorder[item]; + lsize:=sizeof(tQSRec)*abs(shift); + lshift:=item+shift; + if shift>0 then + begin + for i:=0 to HIGH(MainBuf) do + begin + buf:=MainBuf[i,item]; + move(MainBuf[i,item+1],MainBuf[i,item],lsize); + MainBuf[i,lshift]:=buf; + end; + + move(colorder[item+1],colorder[item],SizeOf(integer)*shift); + end + else // shift<0 + begin + for i:=0 to HIGH(MainBuf) do + begin + buf:=MainBuf[i,item]; + move(MainBuf[i,lshift],MainBuf[i,lshift+1],lsize); + MainBuf[i,lshift]:=buf; + end; + + move(colorder[lshift],colorder[lshift+1],sizeof(integer)*(-shift)); + end; + colorder[lshift]:=col; + OptChangeColumns(wcUp,item,shift); +end; + +function GetColor(name:pAnsiChar):TCOLORREF; +var + cid:TColourID; +begin + cid.cbSize:=SizeOf(cid); + StrCopy(cid.group,'QuickSearch'); + StrCopy(cid.name ,name); + result:=CallService(MS_COLOUR_GETA,lparam(@cid),0); +end; + +procedure RegisterColors; +var + cid:TColourID; +begin + cid.cbSize:=SizeOf(cid); + cid.flags :=0; + StrCopy(cid.group,'QuickSearch'); + StrCopy(cid.dbSettingsGroup,qs_module); + + StrCopy(cid.name ,bkg_norm); + StrCopy(cid.setting,'back_norm'); + cid.defcolour:=$00FFFFFF; + cid.order :=0; + ColourRegister(@cid); + + StrCopy(cid.name ,fgr_norm); + StrCopy(cid.setting,'fore_norm'); + cid.defcolour:=$00000000; + cid.order :=1; + ColourRegister(@cid); + + StrCopy(cid.name ,bkg_odd); + StrCopy(cid.setting,'back_odd'); + cid.defcolour:=$00EBE6DE; + cid.order :=2; + ColourRegister(@cid); + + StrCopy(cid.name ,fgr_odd); + StrCopy(cid.setting,'fore_odd'); + cid.defcolour:=$00000000; + cid.order :=3; + ColourRegister(@cid); + + StrCopy(cid.name ,bkg_dis); + StrCopy(cid.setting,'back_dis'); + cid.defcolour:=$008080FF; + cid.order :=4; + ColourRegister(@cid); + + StrCopy(cid.name ,fgr_dis); + StrCopy(cid.setting,'fore_dis'); + cid.defcolour:=$00000000; + cid.order :=5; + ColourRegister(@cid); + + StrCopy(cid.name ,bkg_del); + StrCopy(cid.setting,'back_del'); + cid.defcolour:=$008000FF; + cid.order :=6; + ColourRegister(@cid); + + StrCopy(cid.name ,fgr_del); + StrCopy(cid.setting,'fore_del'); + cid.defcolour:=$00000000; + cid.order :=7; + ColourRegister(@cid); + + StrCopy(cid.name ,bkg_hid); + StrCopy(cid.setting,'back_hid'); + cid.defcolour:=$0080FFFF; + cid.order :=8; + ColourRegister(@cid); + + StrCopy(cid.name ,fgr_hid); + StrCopy(cid.setting,'fore_hid'); + cid.defcolour:=$00000000; + cid.order :=9; + ColourRegister(@cid); + + StrCopy(cid.name ,bkg_meta); + StrCopy(cid.setting,'back_meta'); + cid.defcolour:=$00BAE699; + cid.order :=10; + ColourRegister(@cid); + + StrCopy(cid.name ,fgr_meta); + StrCopy(cid.setting,'fore_meta'); + cid.defcolour:=$00000000; + cid.order :=11; + ColourRegister(@cid); + + StrCopy(cid.name ,bkg_sub); + StrCopy(cid.setting,'back_sub'); + cid.defcolour:=$00B3CCC1; + cid.order :=12; + ColourRegister(@cid); + + StrCopy(cid.name ,fgr_sub); + StrCopy(cid.setting,'fore_sub'); + cid.defcolour:=$00000000; + cid.order :=13; + ColourRegister(@cid); +end; + +function int2strw(i:integer):PWideChar; +var + buf:array [0..31] of WideChar; +begin + IntToStr(buf,i); + StrDupW(result,buf); +end; + +function int2hexw(i:integer):PWideChar; +var + buf:array [0..31] of WideChar; +begin + IntToHex(buf,i); + StrDupW(result,buf); +end; + +function BuildLastSeenTime(cont:THANDLE;modulename:PAnsiChar):PWideChar; + +var + buf:array [0..19] of WideChar; + pc:pWideChar; + year:integer; +begin + pc:=@buf; + year:=DBReadWord(cont,modulename,'Year',0); + if year<>0 then + begin + IntToStr(pc,DBReadWord(cont,modulename,'Day',0),2); + inc(pc,2); + pc^:='.'; inc(pc); + IntToStr(pc,DBReadWord(cont,modulename,'Month',0),2); + inc(pc,2); + pc^:='.'; inc(pc); + IntToStr(pc,year,4); + inc(pc,4); + pc^:=' '; inc(pc); + pc^:='-'; inc(pc); + pc^:=' '; inc(pc); + IntToStr(pc,DBReadWord(cont,modulename,'Hours',0),2); + inc(pc,2); + pc^:=':'; inc(pc); + IntToStr(pc,DBReadWord(cont,modulename,'Minutes',0),2); + + StrDupW(result,@buf); + end + else + result:=nil; +{ +var + vars:array [0..4] of uint_ptr; +begin + vars[2]:=DBReadWord(cont,modulename,'Year',0); + if vars[2]<>0 then + begin + mGetMem(result,20*SizeOf(WideChar)); + vars[1]:=DBReadWord(cont,modulename,'Month' ,0); + vars[0]:=DBReadWord(cont,modulename,'Day' ,0); + vars[3]:=DBReadWord(cont,modulename,'Hours' ,0); + vars[4]:=DBReadWord(cont,modulename,'Minutes',0); + wvsprintfw(result,'%.2lu.%.2lu.%.4lu - %.2lu:%.2lu',@vars); + end + else + result:=nil; +} +end; + +function BuildLastSeenTimeInt(cont:thandle;modulename:PAnsiChar):cardinal; +var + Day,Month,Year,Hours,Minutes:word; +begin + Year:=DBReadWord(cont,modulename,'Year',0); + if Year<>0 then + begin + Month :=DBReadWord(cont,modulename,'Month' ,0); + Day :=DBReadWord(cont,modulename,'Day' ,0); + Hours :=DBReadWord(cont,modulename,'Hours' ,0); + Minutes:=DBReadWord(cont,modulename,'Minutes',0); + result:=Minutes+Hours*60+Day*60*24+Month*60*24*31+(Year-1980)*60*24*31*356; // was 366 + end + else + result:=0; +end; + +function IPtoStr(ip:dword):PWideChar; +var + buf:array [0..16] of WideChar; + p:PWideChar; +begin + p:=@buf; + IntToStr(buf,ip shr 24); + while p^<>#0 do inc(p); p^:='.'; inc(p); + IntToStr(p,(ip shr 16) and $FF); + while p^<>#0 do inc(p); p^:='.'; inc(p); + IntToStr(p,HIByte(ip)); + while p^<>#0 do inc(p); p^:='.'; inc(p); + IntToStr(p,LOByte(ip)); + StrDupW(result,buf); +end; + +function TimeToStrW(data:dword):PWideChar; +var + strdatetime:array [0..63] of WideChar; + dbtts:TDBTIMETOSTRING; +begin + dbtts.cbDest :=sizeof(strdatetime); + dbtts.szDest.w :=@strdatetime; + dbtts.szFormat.w:='d - t'; + CallService(MS_DB_TIME_TIMESTAMPTOSTRINGT,data,lparam(@dbtts)); + StrDupW(result,strdatetime); +end; + +function FindMeta(hMeta:THANDLE;var MetaNum:WPARAM):LPARAM; +var + i:integer; +begin + result:=0; + for i:=0 to HIGH(FlagBuf) do + begin + with FlagBuf[i] do + begin + if contact=hMeta then + begin + if wparam=0 then // new meta + begin + inc(LastMeta); + wparam :=LastMeta; + lparam :=0; + end; + MetaNum:=wparam; + inc(lparam); + result:=lparam; + break; + end; + end; + end; +end; + +function DoMeta(hContact:THANDLE):pointer; +var + pw:pWideChar; + i:integer; +begin + result:=nil; + for i:=0 to HIGH(FlagBuf) do + begin + with FlagBuf[i] do + begin + if contact=hContact then + begin + if (flags and QSF_META)<>0 then // adding new meta count + begin + if wparam=0 then + begin + inc(LastMeta); + wparam:=LastMeta; +// lparam:=0; + end; + end + else if (flags and QSF_SUBMETA)<>0 then + begin + lparam:=FindMeta(CallService(MS_MC_GETMETACONTACT,hContact,0),wparam); + end; + + if wparam>0 then + begin + mGetMem(result,32); + pw:=result; + pw[0]:='['; + IntToStr(pw+1,wparam,3); + pw[4]:=']'; + if lparam>0 then + begin + pw[5]:=' '; + IntToStr(pw+6,lparam); + end + else + pw[5]:=#0; + end; + break; + end; + end; + end; +end; + +procedure LoadOneItem(hContact:THANDLE;num:integer;proto:integer; var res:tQSRec); +var + cni:TCONTACTINFO; + dbei:TDBEVENTINFO; + hDbEvent:cardinal; + tmp:int_ptr; + protov:PAnsiChar; +begin + FillChar(res,SizeOf(tQSRec),0); + res.data:=dword(-1); + res.text:=nil; + with qsopt.columns[num] do + begin + + if module_name<>nil then + protov:=module_name + else + protov:=GetProtoName(proto); + + case setting_type of + ST_METACONTACT: begin + res.text:=DoMeta(hContact); + end; + + ST_SCRIPT: begin + res.text:=ParseVarString(wparam.w,hContact); + end; + + ST_SERVICE: begin + if wparam._type=ptCurrent then wparam.n:=hContact; + if lparam._type=ptCurrent then lparam.n:=hContact; + tmp:=CallService(protov,wparam.n,lparam.n); + if int_ptr(tmp)=int_ptr(CALLSERVICE_NOTFOUND) then exit; + case setting_cnftype of + ptString: begin + AnsiToWide(PAnsiChar(tmp),res.text); + end; + ptUnicode: begin + StrDupW(res.text,PWideChar(tmp)); + end; + ptNumber,ptInteger:begin + res.data:=tmp; + res.text:=int2strw(tmp); + end; + end; + end; + + ST_CONTACTINFO: begin + FillChar(cni,SizeOf(cni),0); + cni.cbSize :=sizeof(cni); + cni.dwFlag:=setting_cnftype or CNF_UNICODE; + cni.hContact:=hContact; + cni.szProto :=GetProtoName(proto); + if CallService(MS_CONTACT_GETCONTACTINFO,0,tlparam(@cni))=0 then + begin + case cni._type of + CNFT_ASCIIZ: begin + if cni.retval.szVal.w<>nil then + begin + StrDupW(res.text,cni.retval.szVal.w); + mir_free(cni.retval.szVal.w); + end; + exit; + end; + CNFT_BYTE :begin + res.data:=cni.retval.bVal; + if setting_cnftype=CNF_GENDER then + begin + if not (res.data in [70,77]) then + res.data:=DBReadByte(hContact,'UserInfo','Gender',0); + exit; + end + end; + CNFT_WORD :res.data:=cni.retval.wVal; + CNFT_DWORD:res.data:=cni.retval.dVal; + end; + res.text:=int2strw(res.data); + end; + end; + + ST_STRING: begin + res.text:=DBReadUnicode(hContact,protov,wparam.a,nil) + end; + + ST_BYTE: begin + res.data:=DBReadByte(hContact,protov,wparam.a,0); + res.text:=int2strw(res.data); + end; + + ST_WORD: begin + res.data:=DBReadWord(hContact,protov,wparam.a,0); + res.text:=int2strw(res.data); + end; + + ST_INT: begin + if (module_name=nil) and (wparam.a=nil) then + begin + res.data:=hContact; + res.text:=int2hexw(res.data); + end + else + begin + res.data:=DBReadDWord(hContact,protov,wparam.a,0); + res.text:=int2strw(res.data); + end; + end; + + ST_LASTSEEN: begin + res.data:=BuildLastSeenTimeInt(hContact,protov); + res.text:=BuildLastSeenTime (hContact,protov); + end; + + ST_IP: begin + res.data:=DBReadDWord(hContact,protov,wparam.a,0); + res.text:=IPtoStr(res.data); + end; + + ST_TIMESTAMP: begin + res.data:=DBReadDWord(hContact,protov,wparam.a,0); + if res.data<>0 then + res.text:=TimeToStrW(res.data); + end; + + ST_LASTEVENT: begin + hDbEvent:=CallService(MS_DB_EVENT_FINDLAST,hContact,0); + if hDbEvent<>0 then + begin + ZeroMemory(@dbei,sizeof(dbei)); + dbei.cbSize:=SizeOf(dbei); + CallService(MS_DB_EVENT_GET,hDbEvent,tlparam(@dbei)); + res.data:=dbei.timestamp; + res.text:=TimeToStrW(res.data); + end + else + res.data:=0; + end; + end; + end; +end; + +function CompareItem(lParam1,lParam2:LPARAM;SortType:LPARAM):int; stdcall; +var + typ1,typ2:boolean; + res1,res2:pQSRec; + i1,i2:uint_ptr; +begin + result:=0; + if SortType=StatusSort then //sort by status + begin + i1:=FlagBuf[lParam1].status; + i2:=FlagBuf[lParam2].status; + // offline - to the end + if i1=ID_STATUS_OFFLINE then i1:=ID_STATUS_OFFLINE+64; + if i2=ID_STATUS_OFFLINE then i2:=ID_STATUS_OFFLINE+64; + // not string parameters + typ1:=false; + typ2:=false; + end + else + begin + res1:=@MainBuf[lParam1,SortType]; + res2:=@MainBuf[lParam2,SortType]; + i1 := res1^.data; + i2 := res2^.data; + typ1:=i1=uint_ptr(-1); + typ2:=i2=uint_ptr(-1); + + if (typ1 and typ2) then // string & string + begin + if (res2.text=nil) and (res1.text=nil) then // nil + result:=0 + else if res2.text=nil then + result:=1 + else if res1.text=nil then + result:=-1 + else + result:=lstrcmpiw(res1.text,res2.text); + end + else if typ1 or typ2 then // string & num + begin + if typ1 then + result:=1 + else + result:=-1; + end; + end; + if not (typ1 or typ2) then // not strings + begin + if i1>i2 then + result:=1 + else if i1=0 then + begin + FillChar(fi,SizeOf(fi),0); + fi.flags :=LVFI_PARAM; + fi.lParam:=num; + result:=SendMessage(grid,LVM_FINDITEM,wparam(-1),lparam(@fi)); + end + else + result:=num; +end; + +procedure AddContactToList(hContact:THANDLE;num:integer); +var + i:integer; + li:LV_ITEMW; +begin + FillChar(li,SizeOf(li),0); + li.iItem :=100000; //!! need append + li.mask :=LVIF_IMAGE or LVIF_PARAM; + li.iImage:=CallService(MS_CLIST_GETCONTACTICON,hContact,0); + li.lParam:=num; + li.iItem :=SendMessageW(grid,LVM_INSERTITEMW,0,lparam(@li)); + + li.iImage:=0; + for i:=0 to qsopt.numcolumns-1 do + begin + if (qsopt.columns[i].flags and COL_ON)<>0 then + begin + // Client icons preprocess + li.pszText :=MainBuf[num,i].text; + if (((qsopt.columns[i].flags and COL_CLIENT)<>0) and + (li.pszText<>NIL) and qsopt.showclienticons) OR + ((qsopt.columns[i].flags and (COL_XSTATUS or COL_GENDER))<>0) then + li.mask:=LVIF_IMAGE or LVIF_TEXT + else + li.mask:=LVIF_TEXT; + li.iSubItem:=colorder[i]; + SendMessageW(grid,LVM_SETITEMW,0,lparam(@li)); + end; + end; +end; + +type + pSBDataRecord = ^tSBDataRecord; + tSBDataRecord = record + flags :cardinal; + total :cardinal; // in clist + found :cardinal; // by pattern + online:cardinal; // clist online + liston:cardinal; // pattern online + end; + tSBData = array [0..63] of tSBDataRecord; + +procedure DrawSBW(const SBData:tSBData); +var + aPartPos:array [0..63 ] of integer; + buf :array [0..255] of WideChar; + fmtstr :array [0..255] of WideChar; + all:integer; + i,j:integer; + p,pc,po,pd,poff,pa:PWideChar; + rc:TRECT; + dc:HDC; + icon:HICON; + protocnt:integer; +begin + p:=@buf; + p:=StrEndW(IntToStr(p,SBData[0].found)); + p:=StrCopyEW(p,TranslateW(' users found (')); + p:=StrEndW(IntToStr(p,Length(FlagBuf))); + p:=StrCopyEW(p,TranslateW(') Online: ')); + IntToStr(p,SBData[0].online); + + dc:=GetDC(StatusBar); + DrawTextW(dc,pWidechar(@buf),-1,rc,DT_CALCRECT); + ReleaseDC(StatusBar,dc); + all:=rc.right-rc.left; + aPartPos[0]:=all; + protocnt:=GetNumProto; + i:=1; + while i<=protocnt do + begin + inc(all,55); + aPartPos[i]:=all; + inc(i); + end; + aPartPos[i]:=-1; + SendMessageW(StatusBar,SB_SETPARTS,protocnt+2,lparam(@aPartPos)); + SendMessageW(StatusBar,SB_SETTEXTW,0,lparam(@buf)); + + po :=TranslateW('Online'); + pd :=TranslateW('deleted'); + poff:=TranslateW('off'); + pa :=TranslateW('active'); + + for i:=1 to protocnt do + begin + if ((SBData[i].flags and (QSF_ACCDEL or QSF_ACCOFF))<>0) then + begin + icon:=CallService(MS_SKIN_LOADPROTOICON,0,ID_STATUS_OFFLINE); + end + else + begin + icon:=CallService( + MS_SKIN_LOADPROTOICON,wparam(GetProtoName(i)),ID_STATUS_ONLINE); + end; + + FastAnsiToWideBuf(GetProtoName(i),fmtstr); + + SendMessageW(StatusBar,SB_SETICON,i,icon); + + j:=High(buf);//(SizeOf(buf) div SizeOf(WideChar))-1; + buf[j]:=#0; + + // fill by spaces + p:=@buf[0]; + while j>0 do + begin + dec(j); + p^:=' '; + inc(p); + end; + + if (SBData[i].flags and QSF_ACCDEL)<>0 then + begin + buf [0]:='!'; + pc:=pd; + end + else if (SBData[i].flags and QSF_ACCOFF)<>0 then + begin + buf [0]:='?'; + pc:=poff + end + else + pc:=pa; + + IntToStr(pWideChar(@buf[2]),SBData[i].found); + StrEndW(buf)^:=' '; + SendMessageW(StatusBar,SB_SETTEXTW,i,lparam(@buf)); + +// create tooltip + p:=@buf; + p:=StrCopyEW(p,fmtstr); // Protocol + p^:=' '; inc(p); + p^:='('; inc(p); + p:=StrCopyEW(p,pc); // Protocol status + p^:=')'; inc(p); + p^:=':'; inc(p); + p^:=' '; inc(p); + + with SBData[i] do + begin + p:=StrEndW(IntToStr(p,found)); + p^:=' '; inc(p); + p^:='('; inc(p); + p:=StrEndW(IntToStr(p,total)); + p^:=')'; inc(p); + p^:=';'; inc(p); + p^:=' '; inc(p); + p:=StrCopyEW(p,po); + p^:=' '; inc(p); + p:=StrEndW(IntToStr(p,liston)); + p^:=' '; inc(p); + p^:='('; inc(p); + p:=StrEndW(IntToStr(p,online)); + p^:=')'; inc(p); + end; + p^:=#0; + SendMessageW(StatusBar,SB_SETTIPTEXTW,i,lparam(@buf)); + end; + +end; + +procedure UpdateSB; +var + SBData: tSBData; + j:integer; + p:pSBDataRecord; +begin + FillChar(SBData,SizeOf(SBData),0); + + // for all contacts + for j:=0 to HIGH(FlagBuf) do + begin + p:=@SBData[FlagBuf[j].proto]; + p^.flags:=FlagBuf[j].flags; + + inc(p^.total); + + if (p^.flags and QSF_ACTIVE)<>0 then + begin + inc(p^.found); + inc(SBData[0].found); + end; + + if FlagBuf[j].status<>ID_STATUS_OFFLINE then + begin + inc(p^.online); + inc(SBData[0].online); + if (p^.flags and QSF_ACTIVE)<>0 then + begin + inc(p^.liston); + inc(SBData[0].liston); + end; + end; + + end; + + DrawSBW(SBData); +end; + +procedure Sort; +begin + if qsopt.columnsort>=tablecolumns then + qsopt.columnsort:=StatusSort; + + SendMessage(grid,LVM_SORTITEMS,GetQSColumn(qsopt.columnsort),LPARAM(@CompareItem)); +// ListView_SortItems(grid,@CompareItem,GetQSColumn(qsopt.columnsort)); + + if (qsopt.columnsort<>StatusSort) and qsopt.sortbystatus then + SendMessage(grid,LVM_SORTITEMS,StatusSort,LPARAM(@CompareItem)); +// ListView_SortItems(grid,@CompareItem,StatusSort); +end; + +procedure MakePatternW; +var + wasquote:bool; + lpatptr:PWideChar; +begin + numpattern:=0; + mFreeMem(patstr); + if (pattern<>nil) and (pattern^<>#0) then + begin + wasquote:=false; + StrDupW(patstr,pattern); + lpatptr:=patstr; + repeat + while lpatptr^=' ' do inc(lpatptr); + if lpatptr^<>#0 then + begin + if lpatptr^='"' then + begin + inc(lpatptr); + wasquote:=true; + end + else + begin + patterns[numpattern].str:=lpatptr; + inc(numpattern); + while lpatptr^<>#0 do + begin + if wasquote then + begin + if lpatptr^='"' then + begin + wasquote:=false; + break; + end; + end + else if lpatptr^=' ' then + break; + inc(lpatptr); + end; + if lpatptr^<>#0 then + begin + lpatptr^:=#0; + inc(lpatptr); + end; + end; + if numpattern=maxpattern then break; + end; + until lpatptr^=#0; + end; +end; + +function CheckPatternW(cnt:integer):boolean; +var + lstr:array [0..1023] of WideChar; + i,j:integer; +begin + if numpattern>0 then + begin + for i:=0 to numpattern-1 do + patterns[i].res:=false; + + for i:=0 to qsopt.numcolumns-1 do + begin + if ((qsopt.columns[i].flags and COL_ON)<>0) and + (MainBuf[cnt,i].text<>nil) then + begin + StrCopyW(lstr,MainBuf[cnt,i].text,HIGH(lstr)); + CharLowerW(lstr); + for j:=0 to numpattern-1 do + if not patterns[j].res then + begin + if StrPosW(lstr,patterns[j].str)<>nil then //!! + patterns[j].res:=true; + end; + end; + end; + + result:=true; + for i:=0 to numpattern-1 do + result:=result and patterns[i].res; + end + else + result:=true; +end; + +procedure ProcessLine(num:integer;test:boolean=true); +var + p:pQSFRec; + l:boolean; +begin + p:=@FlagBuf[num]; + if (p^.flags and QSF_DELETED)<>0 then + exit; + + if qsopt.showonlyinlist then + begin + if (p^.flags and QSF_INLIST)=0 then + exit; + end; + + if test then + begin + l:=CheckPatternW(num); + if l then + p^.flags:=p^.flags or QSF_PATTERN + else + p^.flags:=p^.flags and not QSF_PATTERN; + end + else + l:=(p^.flags and QSF_PATTERN)<>0;//true; + + if l then + begin + if (p^.flags and QSF_ACTIVE)=0 then + begin + if (qsopt.showoffline) or (p^.status<>ID_STATUS_OFFLINE) then + begin + p^.flags:=p^.flags or QSF_ACTIVE; + AddContactToList(p^.contact,num); + end; + end + end + else + begin + if (p^.flags and QSF_ACTIVE)<>0 then + begin + p^.flags:=p^.flags and not QSF_ACTIVE; + ListView_DeleteItem(grid,FindItem(num)); + end; + end; +end; + +function AdvancedFilter:integer; +var + p:pQSFRec; + i:integer; + show:boolean; +begin + result:=0; + + SendMessage(grid,WM_SETREDRAW,0,0); + + for i:=0 to HIGH(FlagBuf) do + begin + p:=@FlagBuf[i]; + // firstly = proto + show:=(LoByte(AdvFilter)=0) or (p^.proto=LoByte(AdvFilter)); + // secondary = show/hide offline + show:=show and ((p^.status<>ID_STATUS_OFFLINE) or ((AdvFilter and flt_show_offline)<>0)); + + if (p^.flags and QSF_PATTERN)<>0 then + begin + if show then + begin + if (p^.flags and QSF_ACTIVE)=0 then + ProcessLine(i,false); + end + else + begin + p^.flags:=p^.flags and not QSF_ACTIVE; + ListView_DeleteItem(grid,FindItem(i)); + end; + end; + end; + + SendMessage(grid,WM_SETREDRAW,1,0); + InvalidateRect(grid,nil,false); + + Sort; + UpdateSB; +end; + +procedure FillGrid; +var + cnt:integer; +begin + + SendMessage(grid,WM_SETREDRAW,0,0); + + MakePatternW; + + for cnt:=0 to HIGH(FlagBuf) do + ProcessLine(cnt); + + SendMessage(grid,WM_SETREDRAW,1,0); + InvalidateRect(grid,nil,false); + + Sort; + UpdateSB; + + AdvancedFilter; //!! + + ListView_SetItemState(grid,0,LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); +end; + +procedure AddContact(num:integer;hContact:THANDLE); +var + i:integer; + tmpstr:array [0..63] of AnsiChar; +begin + FillChar(FlagBuf[num],SizeOf(tQSFRec),0); + with FlagBuf[num] do + begin + contact:=hContact; + flags :=0; + i:=IsContactActive(hContact,tmpstr); + proto:=FindProto(tmpstr); + + case i of + -2: flags:=flags or QSF_ACCDEL; // deleted account + -1: flags:=flags or QSF_ACCOFF; // disabled account +// 0 : ; // hidden contact + 1 : flags:=flags or QSF_META; // metacontact + 2 : flags:=flags or QSF_SUBMETA; // subMetacontact + end; + if i>0 then + flags:=flags or QSF_INLIST; // normal contact + + if (proto=0) or (i<0) then + status:=ID_STATUS_OFFLINE + else + status:=DBReadWord(contact,GetProtoName(proto),'Status',ID_STATUS_OFFLINE); + + for i:=0 to qsopt.numcolumns-1 do + if (qsopt.columns[i].flags and COL_ON)<>0 then + LoadOneItem(contact,i,proto,MainBuf[num,i]); + end; + +end; + +function PrepareToFill:boolean; +var + cnt,cnt1:integer; + hContact:THANDLE; + i:integer; +begin + result:=false; + if qsopt.numcolumns=0 then + exit; + // calculating contacts + cnt:=CallService(MS_DB_CONTACT_GETCOUNT,0,0); + if cnt=0 then + exit; + + result:=true; + // Allocate mem + SetLength(MainBuf,cnt,qsopt.numcolumns); + SetLength(FlagBuf,cnt); + + // filling buffer + LastMeta:=0; + cnt1:=0; + hContact:=CallService(MS_DB_CONTACT_FINDFIRST,0,0); + while hContact<>0 do + begin + //!! check account + AddContact(cnt1,hContact); + inc(cnt1); + if cnt1=cnt then break; // additional checking + hContact:=CallService(MS_DB_CONTACT_FINDNEXT,hContact,0); + end; + if cnt1<>cnt then + begin + SetLength(MainBuf,cnt1); + SetLength(FlagBuf,cnt1); + end; + + SetLength(colorder,qsopt.numcolumns); + cnt:=0; + for i:=0 to qsopt.numcolumns-1 do + begin + if (qsopt.columns[i].flags and COL_ON)<>0 then + begin + colorder[i]:=cnt; + inc(cnt); + qsopt.columns[i].flags := qsopt.columns[i].flags or COL_INIT; + end + else + colorder[i]:=-1; + end; + +end; + +function GetFocusedhContact:THANDLE; +var + i:integer; +begin + i:=LV_GetLParam(grid); + if i=-1 then + result:=0 + else + result:=FlagBuf[i].contact; +end; + +procedure ShowContactMsgDlg(hContact:THANDLE); +begin + if hContact<>0 then + begin + ShowContactDialog(hContact); + if qsopt.closeafteraction then DestroyWindow(mainwnd); + end; +end; + +procedure DeleteOneContact(hContact:THANDLE); +begin + if ServiceExists(strCListDel)>0 then + CallService(strCListDel,hContact,0) + else + CallService(MS_DB_CONTACT_DELETE,hContact,0); +end; + +procedure DeleteByList; +var + i,j:integer; +begin + j:=ListView_GetItemCount(grid)-1; + + i:=MessageBoxW(0,TranslateW('Do you really want to delete selected contacts?'), + TranslateW('Warning'),MB_OKCANCEL+MB_ICONWARNING); + + if i=IDOK then + begin + SendMessage(grid,WM_SETREDRAW,0,0); + for i:=j downto 0 do + begin + if ListView_GetItemState(grid,i,LVIS_SELECTED)<>0 then + CallService(MS_DB_CONTACT_DELETE,FlagBuf[LV_GetLParam(grid,i)].contact,0); + end; + SendMessage(grid,WM_SETREDRAW,1,0); + end; +end; + +procedure ConvertToMeta; +var + i,j:integer; + hMeta:THANDLE; + tmp:THANDLE; +begin + j:=ListView_GetItemCount(grid)-1; + + hMeta:=0; + for i:=j downto 0 do // check + begin + if ListView_GetItemState(grid,i,LVIS_SELECTED)<>0 then + begin + tmp:=CallService(MS_MC_GETMETACONTACT,FlagBuf[LV_GetLParam(grid,i)].contact,0); + if tmp<>0 then + if hMeta=0 then + hMeta:=tmp + else if tmp<>hMeta then + begin + MessageBoxW(0, + TranslateW('Some of selected contacts in different metacontacts already'), + 'Quick Search',MB_ICONERROR); + exit; + end; + end; + end; + + if hMeta<>0 then + begin + i:=MessageBoxW(0, + TranslateW('One or more contacts in same Meta already. Try to convert anyway?'), + 'Quick Search',MB_YESNO+MB_ICONWARNING); + if i<>IDYES then + exit; + end; + + // convert if needed + for i:=j downto 0 do + begin + if ListView_GetItemState(grid,i,LVIS_SELECTED)<>0 then + begin + if hMeta=0 then + hMeta:=CallService(MS_MC_CONVERTTOMETA,FlagBuf[LV_GetLParam(grid,i)].contact,0) + else + CallService(MS_MC_ADDTOMETA,FlagBuf[LV_GetLParam(grid,i)].contact,hMeta); + end; + end; +end; + +procedure MoveToGroup(group:PWideChar); +var + i,j,grcol:integer; + contact:THANDLE; +begin + j:=ListView_GetItemCount(grid)-1; + grcol:=-1; + for i:=0 to qsopt.numcolumns-1 do + begin + with qsopt.columns[i] do + if (setting_type=ST_STRING) and + (StrCmp(module_name,'CList')=0) and + (StrCmp(wparam.a ,'Group')=0) then + begin + if (flags and COL_ON)=0 then + flags:=flags and not COL_INIT + else + grcol:=i; + break; + end + end; + for i:=0 to j do + begin + if ListView_GetItemState(grid,i,LVIS_SELECTED)<>0 then + begin + contact:=FlagBuf[LV_GetLParam(grid,i)].contact; + DBWriteUnicode(contact,strCList,'Group',group); + if (not qsopt.closeafteraction) and (grcol>=0) then + begin + LoadOneItem(contact,grcol,0,MainBuf[i,grcol]); + end; + end; + end; + if (not qsopt.closeafteraction) and (grcol>=0) then + FillGrid; +end; + +function IsColumnMinimized(num:integer):bool; +begin + result:=ListView_GetColumnWidth(grid,num)<=10; +end; + +procedure CopyMultiLinesW(num:integer); +var + i,j,k:integer; + p,buf:PWideChar; + tmpcnt,cnt:integer; +begin + cnt:=0; + if qsopt.exportheaders then + begin + k:=0; + while k0 then + inc(cnt,2); + end; + j:=ListView_GetItemCount(grid)-1; + tmpcnt:=cnt; + for i:=0 to j do + begin + if ListView_GetItemState(grid,i,LVIS_SELECTED)<>0 then + begin + k:=0; + num:=LV_GetLParam(grid,i); + while kcnt then + inc(cnt,2); + end; + if cnt=0 then + exit; + + inc(cnt); + mGetMem(buf,cnt*SizeOf(WideChar)); + p:=buf; + + if qsopt.exportheaders then + begin + k:=0; + while k0 then + begin + k:=0; + num:=LV_GetLParam(grid,i); + while k1) or qsopt.singlecsv then + begin + CopyMultiLinesW(i); + exit; + end; + + cnt:=0; + num:=LV_GetLParam(grid,ListView_GetNextItem(grid,-1,LVNI_FOCUSED)); + i:=0; + while i':' then + inc(cnt); + + inc(cnt,StrLenW(MainBuf[num,i].text)+2); + end; + end; + if cnt=0 then + exit; + mGetMem(pp,(cnt+1)*SizeOf(WideChar)); + p:=pp; + + i:=0; + while i':' then + begin + p^:=':'; + inc(p); + end; + p^:=' '; inc(p); + StrCopyW(p,MainBuf[num,i].text); + p:=StrEndW(p); + p^:=#13; (p+1)^:=#10; inc(p,2); + end; + end; + p^:=#0; + + CopyToClipboard(pp,false); + mFreeMem(pp); + exit; + end; + // backspace + 8: begin + if pattern<>nil then + begin + StrCopyW(buf,pattern); + p:=StrEndW(buf); + (p-1)^:=#0; + SetDlgItemTextW(mainwnd,IDC_E_SEARCHTEXT,buf); + end; + end; + // letters + 32..127: begin + if pattern<>nil then + StrCopyW(buf,pattern) + else + buf[0]:=#0; + p:=StrEndW(buf); + p^:=WideChar(wParam); + (p+1)^:=#0; + SetDlgItemTextW(mainwnd,IDC_E_SEARCHTEXT,buf); + end; + end + end; + + WM_TIMER: begin + if wParam=TIMERID_HOVER then + begin + KillTimer(Dialog,TIMERID_HOVER); + if GetForegroundWindow<>mainwnd then exit; + i:=LV_GetLParam(grid,OldHItem); + FillChar(info,SizeOf(info),0); + with info do + begin + cbSize :=SizeOf(info); + hItem :=FlagBuf[i].contact; + GetCursorPos(ptCursor); + tmpCursor :=ptCursor; +{ + ptCursor.x:=loword(lParam); + ptCursor.y:=hiword(lParam); +} + SendMessage(grid,LVM_GETITEMRECT,OldHItem,tlparam(@rcItem)); + ScreenToClient(grid,tmpCursor); + if not PtInRect(rcItem,tmpCursor) then exit; + end; +// mGetMem(txt,16384*SizeOf(WideChar)); +{ + p:=txt; + for cnt:=0 to HIGH(MainBuf[0]) do + begin + if (qsopt.columns[cnt].flags and COL_ON)=0 then + begin + LoadOneItem(info.hItem,cnt,FlagBuf[i].proto,qsr); + if qsr.text<>nil then + begin + if qsr.text^<>#0 then + begin +//!! need: buffer free space check here +num:=StrLenW(qsopt.columns[cnt].title)+StrLenW(qsr.text)+4; +if (16384-num)>(p-txt) then +begin + + p:=StrCopyEW(p,qsopt.columns[cnt].title); + p^:=':'; inc(p); p^:=' '; inc(p); + p:=StrCopyEW(p,qsr.text); + p^:=#13; inc(p); p^:=#10; inc(p); +end +else +begin + mFreeMem(qsr.text); + break; +end; + end; + mFreeMem(qsr.text); + end; + end; + end; + p^:=#0; +} + CallService(MS_TIPPER_SHOWTIPW,0{dword(txt)},tlparam(@info)); +// mFreeMem(txt); + TTShowed:=true; + end; + end; + + WM_MOUSEMOVE: begin + pinfo.pt.x:=loword(lParam); + pinfo.pt.y:=hiword(lParam); + pinfo.flags:=0; + if integer(SendMessage(grid,LVM_SUBITEMHITTEST,0,tlparam(@pinfo)))<>-1 then + begin + if (pinfo.iItem<>OldHItem) or (pinfo.iSubItem<>OldHSubItem) then + begin + OldHSubItem:=pinfo.iSubItem; + OldHItem :=pinfo.iItem; + + if TTInstalled then + begin + if TTShowed then + begin + TTShowed:=false; + CallService(MS_TIPPER_HIDETIP,0,0); + end; + KillTimer(Dialog, TIMERID_HOVER); + if OldHSubItem=0 then + begin + SetTimer(Dialog, TIMERID_HOVER, 450, nil); + exit; + end; + end; +//!! + with TI do + begin + cbSize:=SizeOf(TI); + uFlags:=TTF_SUBCLASS+TTF_IDISHWND; + hWnd :=mainwnd; + uId :=Dialog; + hInst :=0; + end; + + OldHSubItem:=GetQSColumn(OldHSubItem); + if (qsopt.columns[OldHSubItem].flags and + (COL_XSTATUS or COL_GENDER))<>0 then + begin + i:=LV_GetLParam(grid,OldHItem); +// TTShowed:=true; + if (qsopt.columns[OldHSubItem].flags and COL_GENDER)<>0 then + begin + case MainBuf[i,OldHSubItem].data of + 77: TI.lpszText:=tstrMale; + 70: TI.lpszText:=tstrFemale; + else + TI.lpszText:=tstrUnknown; + end; + end + else // if (qsopt.columns[OldHSubItem].flags and COL_XSTATUS)<>0 then + begin + StrCopyW(buf,MainBuf[i,OldHSubItem].text); + ics.flags:=CSSF_DEFAULT_NAME or CSSF_MASK_NAME or CSSF_UNICODE; + + StrCopy(StrCopyE(buf1,GetProtoName(FlagBuf[i].proto)),PS_ICQ_GETCUSTOMSTATUSEX); + + i:=StrToInt(buf); + ics.wParam:=@i; + ics.cbSize:=SizeOf(ics); + ics.szName.w:=@buf; + + CallService(buf1,0,tlparam(@ics)); + TI.lpszText:=TranslateW(@buf); + end; + end + else + begin + TI.lpszText:=nil; +// TTShowed:=false; + end; + SendMessageW(HintWnd,TTM_SETTOOLINFOW,0,tlparam(@TI)); + end + end; + end; + + WM_KEYUP: begin + case wParam of + VK_RETURN: begin + if ListView_GetSelectedCount(grid)=1 then + ShowContactMsgDlg(GetFocusedhContact); + exit; + end; + VK_INSERT: begin + CallService(MS_FINDADDFINDADD,0,0); + exit; + end; + VK_DELETE: begin + lParam:=ListView_GetSelectedCount(grid); + if lParam>1 then + DeleteByList + else if lParam=1 then + DeleteOneContact(GetFocusedhContact); + exit; + end; + VK_F5: begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_REFRESH,0); + exit; + end; + end; + end; + + WM_NOTIFY: begin + if integer(PNMHdr(lParam)^.code)=HDN_ENDDRAG then + begin + ShiftColumns(PHDNotify(lParam)^.Item,PHDNotify(lParam)^.pitem^.iOrder); + end; + end; + + end; + result:=CallWindowProc(OldLVProc,Dialog,hMessage,wParam,lParam); +end; + +procedure ColumnClick(wnd:HWND;num:integer); +var + hdi:THDITEM; + header:HWND; +begin + zeromemory(@hdi,sizeof(hdi)); + hdi.mask:=HDI_BITMAP or HDI_FORMAT; + hdi.fmt :=HDF_LEFT or HDF_STRING; + header:=ListView_GetHeader(wnd); + SendMessage(header,HDM_SETITEM,qsopt.columnsort,lparam(@hdi)); + + if qsopt.columnsort<>num then + begin + qsopt.ascendsort:=true; + qsopt.columnsort:=num; + end + else + qsopt.ascendsort:=not qsopt.ascendsort; + + if qsopt.ascendsort then + hdi.hbm:=sortcoldn + else + hdi.hbm:=sortcolup; + hdi.fmt:=HDF_LEFT or HDF_BITMAP or HDF_BITMAP_ON_RIGHT or HDF_STRING; + Header_SetItem(header,num,hdi); + + Sort; +end; + +procedure MakeColumnMenu; +var + menu:HMENU; + flag,id:integer; + pt:TPOINT; +begin + menu:=CreatePopupMenu; + if menu<>0 then + begin + for id:=0 to qsopt.numcolumns-1 do + begin + if (qsopt.columns[id].flags and COL_ON)<>0 then + flag:=MF_CHECKED or MF_STRING + else + flag:=MF_UNCHECKED or MF_STRING; + AppendMenuW(menu,flag,100+id,TranslateW(qsopt.columns[id].title)); + end; + GetCursorPos(pt); + id:=integer(TrackPopupMenu(menu,TPM_RETURNCMD+TPM_NONOTIFY,pt.x,pt.y,0,mainwnd,nil)); + if id>100 then + begin + dec(id,100); + with qsopt.columns[id] do + begin + flags:=flags xor COL_ON; + if (flags and COL_ON)<>0 then + flag:=wcShow + else + flag:=wcHide; + end; + WndChangeColumns(flag,id); + OptChangeColumns(wcShow,id,ord(flag=wcShow)); + end; + DestroyMenu(menu); + end; +end; + +function NewLVHProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +begin + case hMessage of + + WM_RBUTTONUP: begin + result:=0; + exit; + end; + + WM_RBUTTONDOWN: begin + MakeColumnMenu; + end; + end; + result:=CallWindowProc(OldProc,Dialog,hMessage,wParam,lParam); +end; + +procedure SetCellColor(lplvcd:PNMLVCUSTOMDRAW;idx:integer); +begin + if qsopt.colorize then + begin + with FlagBuf[idx] do + begin + if (flags and QSF_ACCDEL)<>0 then + begin + lplvcd^.clrTextBk:=cbkg_del; + lplvcd^.clrText :=cfgr_del; + end + else if (flags and QSF_ACCOFF)<>0 then + begin + lplvcd^.clrTextBk:=cbkg_dis; + lplvcd^.clrText :=cfgr_dis; + end + else if (flags and QSF_META)<>0 then + begin + lplvcd^.clrTextBk:=cbkg_meta; + lplvcd^.clrText :=cfgr_meta; + end + else if (flags and QSF_SUBMETA)<>0 then + begin + lplvcd^.clrTextBk:=cbkg_sub; + lplvcd^.clrText :=cfgr_sub; + end + else if (flags and QSF_INLIST)=0 then + begin + lplvcd^.clrTextBk:=cbkg_hid; + lplvcd^.clrText :=cfgr_hid; + end + else + idx:=-1; + end; + end + else + idx:=-1; + if idx<0 then + begin + if (not qsopt.drawgrid) and odd(lplvcd^.nmcd.dwItemSpec) then + begin + lplvcd^.clrTextBk:=cbkg_odd; + lplvcd^.clrText :=cfgr_odd; + end + else + begin + lplvcd^.clrTextBk:=cbkg_norm; + lplvcd^.clrText :=cfgr_norm; + end; + end; +end; + +function ProcessCustomDraw(lParam:LPARAM):integer; +var + lplvcd:PNMLVCUSTOMDRAW; + rc:TRECT; + h:HICON; + buf:array [0..255] of AnsiChar; + i,j,sub:integer; +begin + lplvcd:=pointer(lParam); + result:=CDRF_DODEFAULT; + case lplvcd^.nmcd.dwDrawStage of + CDDS_PREPAINT: begin + result:=CDRF_NOTIFYITEMDRAW; + exit; + end; + CDDS_ITEMPREPAINT: begin + result:=CDRF_NOTIFYSUBITEMDRAW; + + SetCellColor(lplvcd,LV_GetLParam(grid,lplvcd^.nmcd.dwItemSpec)); + + exit; + end; + CDDS_SUBITEM or CDDS_ITEMPREPAINT: begin + + i:=LV_GetLParam(grid,lplvcd^.nmcd.dwItemSpec); + SetCellColor(lplvcd,i); + sub:=GetQSColumn(lplvcd^.iSubItem); + if (qsopt.columns[sub].flags and COL_GENDER)<>0 then + begin + ListView_GetSubItemRect(grid,lplvcd^.nmcd.dwItemSpec,lplvcd^.iSubItem,LVIR_ICON,@rc); + + case MainBuf[i,sub].data of + 70: h:=hIconF; + 77: h:=hIconM; + else + h:=0; + end; + if h<>0 then + begin + DrawIconEx(lplvcd^.nmcd.hdc,rc.left+1,rc.top,h,16,16,0,0,DI_NORMAL); + end; + result:=CDRF_SKIPDEFAULT; + end + else if (qsopt.columns[sub].flags and COL_XSTATUS)<>0 then + begin + j:=StrToInt(MainBuf[i,sub].text); + if j>0 then + begin + StrCopy(StrCopyE(buf,GetProtoName(FlagBuf[i].proto)),PS_ICQ_GETCUSTOMSTATUSICON); + if ServiceExists(buf)<>0 then + begin + h:=CallService(buf,j,LR_SHARED); + + ListView_GetSubItemRect(grid,lplvcd^.nmcd.dwItemSpec,lplvcd^.iSubItem,LVIR_ICON,@rc); + DrawIconEx(lplvcd^.nmcd.hdc,rc.left+1,rc.top,h,16,16,0,0,DI_NORMAL); + end; + end; + result:=CDRF_SKIPDEFAULT; + end + else if qsopt.showclienticons and + ((qsopt.columns[sub].flags and COL_CLIENT)<>0) then + result:=CDRF_NOTIFYPOSTPAINT; + end; + CDDS_SUBITEM or CDDS_ITEMPOSTPAINT: begin + sub:=GetQSColumn(lplvcd^.iSubItem); + if (qsopt.columns[sub].flags and COL_CLIENT)<>0 then + begin + i:=LV_GetLParam(grid,lplvcd^.nmcd.dwItemSpec); + FastWideToAnsiBuf(MainBuf[i,sub].text,buf); + +// ListView_GetItemTextA(grid,lplvcd^.nmcd.dwItemSpec,lplvcd^.iSubItem,buf,SizeOf(buf)); + if buf[0]<>#0 then + begin + h:=CallService(MS_FP_GETCLIENTICON,tlparam(@buf),0); + ListView_GetSubItemRect(grid,lplvcd^.nmcd.dwItemSpec,lplvcd^.iSubItem,LVIR_ICON,@rc); + DrawIconEx(lplvcd^.nmcd.hdc,rc.left+1,rc.top,h,16,16,0,0,DI_NORMAL); + DestroyIcon(h); + end; + result:=CDRF_SKIPDEFAULT; + end; + end; + end; +end; + +function NewEditProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + count,current,next,perpage:integer; + li:LV_ITEM; +begin + result:=0; + case hMessage of + WM_CHAR: if wParam=27 then + begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDCANCEL,0); + exit; + end; + WM_KEYUP: if wParam=VK_RETURN then + begin + if ListView_GetSelectedCount(grid)=1 then + ShowContactMsgDlg(GetFocusedhContact); + exit; + end; + WM_KEYDOWN: begin + count :=ListView_GetItemCount(grid); + current:=ListView_GetNextItem(grid,-1,LVNI_FOCUSED); + next:=-1; + if count>0 then + case wParam of + VK_NEXT,VK_PRIOR: begin + perpage:=ListView_GetCountPerPage(grid); + if wParam=VK_NEXT then + next:=Min(current+perpage,count) + else + next:=Max(current-perpage,0); + end; + VK_UP: begin + if current>0 then + next:=current-1 + end; + VK_DOWN: begin + if current=0 then + begin + li.statemask:=LVIS_SELECTED; + li.state:=0; + SendMessage(grid,LVM_SETITEMSTATE,twparam(-1),tlparam(@li)); + ListView_SetItemState(grid,next,LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); + // ListView_EnsureVisible(grid,next,false); + SendMessage(grid,LVM_ENSUREVISIBLE,next,0); + result:=0; + exit; + end; + end; + end; + result:=CallWindowProc(OldEditProc,Dialog,hMessage,wParam,lParam); +end; + +function ShowContactMenu(wnd:HWND;hContact:THANDLE):HMENU; +var + pt:tpoint; +begin + if hContact<>0 then + begin + GetCursorPos(pt); + result:=CallService(MS_CLIST_MENUBUILDCONTACT,hContact,0); + if result<>0 then + begin + TrackPopupMenu(result,0,pt.x,pt.y,0,wnd,nil); + DestroyMenu(result); + end; + end + else + result:=0; +end; + +procedure ShowMultiPopup(cnt:integer); +var + mmenu,grpmenu:HMENU; + i:integer; + buf:array [0..255] of WideChar; + p:PWideChar; + pt:TPOINT; +begin + mmenu:=CreatePopupMenu; + if mmenu=0 then + exit; + + StrCopyW(buf,TranslateW('Selected')); + p:=@buf; + while p^<>#0 do inc(p); + p^:=' '; inc(p); + + IntToStr(p,cnt); + + while p^<>#0 do inc(p); + p^:=' '; inc(p); + StrCopyW(p,TranslateW('contacts')); + AppendMenuW(mmenu,MF_DISABLED+MF_STRING,0,buf); + AppendMenuW(mmenu,MF_SEPARATOR,0,nil); + AppendMenuW(mmenu,MF_STRING,101,TranslateW('&Delete')); + AppendMenuW(mmenu,MF_STRING,102,TranslateW('&Copy')); + if ServiceExists(MS_MC_CONVERTTOMETA)<>0 then + AppendMenuW(mmenu,MF_STRING,103,TranslateW('C&onvert to Meta')); + + grpmenu:=MakeGroupMenu(400); + +// grpmenu:=CallService(MS_CLIST_GROUPBUILDMENU,0,0); + AppendMenuW(mmenu,MF_POPUP,grpmenu,TranslateW('&Move to Group')); + + GetCursorPos(pt); + i:=integer(TrackPopupMenu(mmenu,TPM_RETURNCMD+TPM_NONOTIFY,pt.x,pt.y,0,mainwnd,nil)); + case i of + 101: DeleteByList; + 102: begin + CopyMultiLinesW(ListView_GetSelectedCount(grid)) + end; + 103: ConvertToMeta; + else + if i>0 then + begin // move to group + if i=400 then // root group + buf[0]:=#0 + else + begin + GetMenuStringW(grpmenu,i,buf,SizeOf(buf),MF_BYCOMMAND); + end; + MoveToGroup(buf); + end; + end; + DestroyMenu(mmenu); + if qsopt.closeafteraction then + CloseSrWindow; +end; + +procedure addcolumn(handle:hwnd;num,width:integer;title:PWideChar); +var + lvcol:LV_COLUMNW; +begin + zeromemory(@lvcol,sizeof(lvcol)); + lvcol.mask :=LVCF_TEXT or LVCF_WIDTH; + lvcol.pszText :=title; + lvcol.cx :=width; + SendMessageW(handle,LVM_INSERTCOLUMNW,num,lparam(@lvcol)); +end; +{ +// from zero!! +function GetNthByMask(const arr:tcolumnarray; num:cardinal; mask:dword):tcolumnitem; +var + i:cardinal; +begin + for i:=0 to HIGH(arr) do + begin + if (arr[i].flags and mask)<>0 then + begin + if num=0 then + begin + result:=arr[i]; + exit; + end; + dec(num); + end; + end; + result:=arr[0]; +end; +} +function ColorReload(wParam:WPARAM;lParam:LPARAM):int;cdecl; +begin + result:=0; + cbkg_norm:=GetColor(bkg_norm); + cfgr_norm:=GetColor(fgr_norm); + cbkg_odd :=GetColor(bkg_odd); + cfgr_odd :=GetColor(fgr_odd); + cbkg_dis :=GetColor(bkg_dis); + cfgr_dis :=GetColor(fgr_dis); + cbkg_del :=GetColor(bkg_del); + cfgr_del :=GetColor(fgr_del); + cbkg_hid :=GetColor(bkg_hid); + cfgr_hid :=GetColor(fgr_hid); + cbkg_meta:=GetColor(bkg_meta); + cfgr_meta:=GetColor(fgr_meta); + cbkg_sub :=GetColor(bkg_sub); + cfgr_sub :=GetColor(fgr_sub); +end; + +procedure ClearBuffers; +var + w,h:integer; +begin + for w:=0 to HIGH(MainBuf) do + for h:=0 to HIGH(MainBuf[0]) do + mFreeMem(MainBuf[w,h].text); +end; + +procedure SetSpecialColumns(num:integer); +begin + with qsopt.columns[num] do + begin + if (setting_type=ST_BYTE) and + (lstrcmpia(wparam.a,'XStatusId')=0) then + begin + flags:=flags or COL_XSTATUS; + end + + else if (setting_type=ST_CONTACTINFO) and + (setting_cnftype=CNF_GENDER) then + begin + if hIconF=0 then hIconF:=CallService(MS_SKIN2_GETICON,0,tlparam(QS_FEMALE)); + if hIconM=0 then hIconM:=CallService(MS_SKIN2_GETICON,0,tlparam(QS_MALE)); + flags:=flags or COL_GENDER; + tstrMale :=TranslateW('Male'); + tstrFemale :=TranslateW('Female'); + tstrUnknown:=TranslateW('Unknown'); + end + + else if (wparam.a<>NIL) and // FingerPrint preprocess + (setting_type=ST_STRING) and + (lstrcmpia(wparam.a,'MirVer')=0) and + (ServiceExists(MS_FP_GETCLIENTICON)<>0) then + flags:=flags or COL_CLIENT; + end; +end; + +function FindAddDlgResizer(Dialog:HWND;lParam:LPARAM;urc:PUTILRESIZECONTROL):int; cdecl; +begin + case urc^.wId of + IDCANCEL: result:=RD_ANCHORX_RIGHT or RD_ANCHORY_TOP; + IDC_REFRESH: result:=RD_ANCHORX_RIGHT or RD_ANCHORY_TOP; + IDC_CH_SHOWOFFLINE: result:=RD_ANCHORX_LEFT or RD_ANCHORY_TOP; + IDC_CH_COLORIZE: result:=RD_ANCHORX_LEFT or RD_ANCHORY_TOP; + IDC_CB_PROTOCOLS: result:=RD_ANCHORX_LEFT or RD_ANCHORY_TOP; + IDC_E_SEARCHTEXT: result:=RD_ANCHORX_WIDTH or RD_ANCHORY_TOP; + IDC_LIST: result:=RD_ANCHORX_WIDTH or RD_ANCHORY_HEIGHT; + IDC_STATUSBAR: result:=RD_ANCHORX_WIDTH or RD_ANCHORY_BOTTOM; + else + result:=0; + end; +end; + +procedure PrepareTable(reset:boolean=false); +var + i:integer; + old:integer; +begin + old:=tablecolumns; + tablecolumns:=0; + for i:=0 to qsopt.numcolumns-1 do + begin + with qsopt.columns[i] do + begin + if (flags and COL_ON)<>0 then + begin + addcolumn(grid,tablecolumns,width,TranslateW(title)); + inc(tablecolumns); + end; + + SetSpecialColumns(i); + end; + end; + if reset then + begin + for i:=old+tablecolumns-1 downto tablecolumns do + begin + SendMessage(grid,LVM_DELETECOLUMN,i,0); + end; + end; + + ListView_DeleteAllItems(grid); + ListView_SetItemCount(grid,HIGH(FlagBuf)+1); +end; + +procedure FillProtoCombo(cb:HWND); +var + i:integer; + buf:array [0..63] of WideChar; +begin + SendMessage(cb,CB_RESETCONTENT,0,0); + CB_AddStrDataW(cb,TranslateW('All')); + for i:=1 to GetNumProto do + begin + CB_AddStrDataW(cb,FastAnsiToWideBuf(GetProtoName(i),@buf),i); + end; + SendMessage(cb,CB_SETCURSEL,0,0); +end; + +function QSMainWndProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + tmp:LONG_PTR; + tmph:THANDLE; + w,h:uint_ptr; + i:integer; + buf:array [0..255] of WideChar; + rc:TRECT; + pt:TPOINT; + smenu:HMENU; + TI:tToolInfoW; + urd:TUTILRESIZEDIALOG; +begin + result:=0; + case hMessage of + WM_DESTROY: begin + UnhookEvent(colorhook); + + StatusBar:=0; + DeleteObject(gridbrush); + GetWindowRect(Dialog,rc); + + CopyRect(qsopt.grrect,rc); + + // set column width - only for enabled columns + for tmp:=0 to qsopt.numcolumns-1 do + begin + if {(qsopt.columns[tmp].flags and COL_ON)<>0} colorder[tmp]>=0 then + begin + w:=ListView_GetColumnWidth(grid,colorder[tmp]); + if w<>0 then + qsopt.columns[tmp].width:=w; + end; + end; + saveopt_wnd; + + ListView_SetImageList(grid,0,LVSIL_SMALL); + opened:=false; + + tmp:=GetDC(grid); + h:=GetCurrentObject(tmp,OBJ_FONT); + SendMessage(grid,WM_SETFONT,0,1); + DeleteObject(h); + ReleaseDC(grid,tmp); + + grid:=0; + + if qsopt.savepattern then + DBWriteUnicode(0,qs_module,'pattern',pattern); + + mFreeMem(patstr); + mFreeMem(pattern); + + ClearBuffers; + end; + + WM_INITDIALOG: begin + + tmph:=GetModuleHandle(nil); + if sortcoldn=0 then + sortcoldn:=LoadImageA(tmph,PAnsiChar(240),IMAGE_BITMAP,0,0,LR_LOADMAP3DCOLORS); + if sortcolup=0 then + sortcolup:=LoadImageA(tmph,PAnsiChar(239),IMAGE_BITMAP,0,0,LR_LOADMAP3DCOLORS); + + SetWindowTextW(Dialog,'Quick Search'); + + StatusBar:=GetDlgItem(Dialog,IDC_STATUSBAR); + + smenu:=GetSystemMenu(Dialog,false); + InsertMenu (smenu,5,MF_BYPOSITION or MF_SEPARATOR,0,nil); + InsertMenuW(smenu,6,MF_BYPOSITION or MF_STRING, + IDM_STAYONTOP,TranslateW('Stay on Top')); + + if qsopt.stayontop then + begin + CheckMenuItem(smenu,IDM_STAYONTOP,MF_BYCOMMAND or MF_CHECKED); + SetWindowPos(Dialog,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE); + end; + AdvFilter:=0; + if qsopt.showoffline then + begin + CheckDlgButton(Dialog,IDC_CH_SHOWOFFLINE,ORD(qsopt.showoffline)); + AdvFilter:=AdvFilter or flt_show_offline; + end; + + if qsopt.colorize then + CheckDlgButton(Dialog,IDC_CH_COLORIZE,ORD(qsopt.colorize)); + + gridbrush:=CreateSolidBrush(RGB(222,230,235)); + + mainwnd:=Dialog; + tmp:=GetWindowLongPtrW(Dialog,GWL_EXSTYLE); + if qsopt.usetoolstyle then + tmp:=tmp or WS_EX_TOOLWINDOW + else + tmp:=tmp and not WS_EX_TOOLWINDOW; + SetWindowLongPtrW(Dialog,GWL_EXSTYLE,tmp); + + SendMessage(Dialog,WM_SETICON,ICON_SMALL,//LoadIcon(hInstance,PAnsiChar(IDI_QS)) + CallService(MS_SKIN2_GETICON,0,tlparam(QS_QS))); + grid:=GetDlgItem(Dialog,IDC_LIST); + + ListView_SetImageList(grid, + CallService(MS_CLIST_GETICONSIMAGELIST,0,0),LVSIL_SMALL); + + tmp:=LVS_EX_FULLROWSELECT or LVS_EX_SUBITEMIMAGES or LVS_EX_HEADERDRAGDROP or LVS_EX_LABELTIP; + if qsopt.drawgrid then + tmp:=tmp or LVS_EX_GRIDLINES; + SendMessage(grid,LVM_SETEXTENDEDLISTVIEWSTYLE,0,tmp); + + OldLVProc :=pointer(SetWindowLongPtrW(grid,GWL_WNDPROC,LONG_PTR(@NewLVProc))); + OldEditProc:=pointer(SetWindowLongPtrW(GetDlgItem(Dialog,IDC_E_SEARCHTEXT), + GWL_WNDPROC,LONG_PTR(@NewEditProc))); + + OldProc:=pointer(SetWindowLongPtrW( + SendMessage(grid,LVM_GETHEADER,0,0), + GWL_WNDPROC,LONG_PTR(@NewLVHProc))); + + FillProtoCombo(GetDlgItem(Dialog,IDC_CB_PROTOCOLS)); + + PrepareTable; + + if pattern<>nil then + begin + SetDlgItemTextW(Dialog,IDC_E_SEARCHTEXT,pattern) + end + else + begin + buf[0]:=#0; + SetDlgItemTextW(Dialog,IDC_E_SEARCHTEXT,@buf); + FillGrid; + end; + + TranslateDialogDefault(Dialog); + + SnapToScreen(qsopt.grrect); + with qsopt.grrect do + MoveWindow(Dialog,left,top,right-left,bottom-top,false); + + with TI do + begin + cbSize :=SizeOf(TI); + uFlags :=TTF_SUBCLASS+TTF_IDISHWND; + hWnd :=Dialog; + uId :=grid; + hInst :=0; + lpszText :=nil; + end; + HintWnd:=CreateWindowExW(0,TOOLTIPS_CLASS,nil,0, + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + Dialog,0,HInstance,NIL); + + SendMessageW(HintWnd,TTM_ADDTOOLW,0,tlparam(@TI)); +// SetWindowsHookEx(WH_KEYBOARD,@QSKbdHook,0,GetCurrentThreadId); + colorhook:=HookEvent(ME_COLOUR_RELOAD,@ColorReload); + + opened:=true; + end; + + WM_GETMINMAXINFO: begin + with PMINMAXINFO(lParam)^ do + begin + ptMinTrackSize.x:=300; + ptMinTrackSize.y:=160; + end; + end; + + WM_SIZE: begin + SendMessage(StatusBar,WM_SIZE,0,0); + FillChar(urd,SizeOf(TUTILRESIZEDIALOG),0); + urd.cbSize :=SizeOf(urd); + urd.hwndDlg :=Dialog; + urd.hInstance :=hInstance; + urd.lpTemplate:=MAKEINTRESOURCEA(IDD_MAIN); + urd.lParam :=0; + urd.pfnResizer:=@FindAddDlgResizer; + CallService(MS_UTILS_RESIZEDIALOG,0,tlparam(@urd)); + end; + + WM_SYSCOMMAND: begin + if wParam=IDM_STAYONTOP then + begin + if qsopt.stayontop then + begin + h:=MF_BYCOMMAND or MF_UNCHECKED; + w:=HWND_NOTOPMOST; + end + else + begin + h:=MF_BYCOMMAND or MF_CHECKED; + w:=HWND_TOPMOST; + end; + CheckMenuItem(GetSystemMenu(Dialog,false),IDM_STAYONTOP,h); + SetWindowPos(Dialog,w,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE); + qsopt.stayontop:=not qsopt.stayontop; + exit; + end; + end; + + WM_CONTEXTMENU: begin + if wParam=tWPARAM(GetDlgItem(Dialog,IDC_LIST)) then + begin + w:=ListView_GetSelectedCount(grid); + if w>1 then + ShowMultiPopup(w) + else + ShowContactMenu(Dialog,GetFocusedhContact); + end; + end; + + WM_MYADDCONTACT: begin + // refresh table to add contact + i:=Length(MainBuf); + SetLength(MainBuf,i+1); + SetLength(MainBuf[i],qsopt.numcolumns); + SetLength(FlagBuf,i+1); + + AddContact(i,wParam); + ProcessLine(i); + Sort; + UpdateSB; + end; + + WM_MYDELETECONTACT: begin + i:=FindBufNumber(wParam); + if i>=0 then + begin + FlagBuf[i].flags:=(FlagBuf[i].flags or QSF_DELETED) and not QSF_ACTIVE; + for w:=0 to HIGH(MainBuf[0]) do + mFreeMem(MainBuf[i,w].text); + i:=FindItem(i); + if i>=0 then + ListView_DeleteItem(grid,i); + UpdateSB; + end; + end; + + WM_MEASUREITEM: + CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam); + WM_DRAWITEM: + CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam); + + WM_MOUSEMOVE: begin + if TTInstalled then + begin + GetWindowRect(grid,rc); + pt.x:=loword(lParam); + pt.y:=hiword(lParam); + ClientToScreen(Dialog,pt); + if not PtInRect(rc,pt) then + begin + if TTShowed then + begin + TTShowed:=false; + CallService(MS_TIPPER_HIDETIP,0,0); + end; + KillTimer(grid,TIMERID_HOVER); + end; + end; + end; + + WM_KEYDOWN: begin + case wParam of + VK_F5: begin + PostMessage(Dialog,WM_COMMAND,(BN_CLICKED shl 16)+IDC_REFRESH,0); + exit; + end; + end; + end; + + WM_COMMAND: begin + if opened and (CallService(MS_CLIST_MENUPROCESSCOMMAND, + MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU), + GetFocusedhContact)<>0) then + begin + if qsopt.closeafteraction then + CloseSrWindow; + exit; + end; + + case wParam shr 16 of + CBN_SELCHANGE: begin + AdvFilter:=(AdvFilter and not $FF) or cardinal(CB_GetData(lParam)); + AdvancedFilter; + end; + + EN_CHANGE: begin + GetDlgItemTextW(Dialog,IDC_E_SEARCHTEXT,buf,sizeOf(buf)); + mFreeMem(pattern); + StrDupW(pattern,buf); + if pattern<>nil then + CharLowerW(pattern); + FillGrid; //!! + end; + + BN_CLICKED: begin + case loword(wParam) of + IDC_CH_SHOWOFFLINE: begin + qsopt.showoffline:=IsDlgButtonChecked(Dialog,IDC_CH_SHOWOFFLINE)<>BST_UNCHECKED; + if qsopt.showoffline then + AdvFilter:=AdvFilter or flt_show_offline + else + AdvFilter:=AdvFilter and not flt_show_offline; + AdvancedFilter; + end; + + IDC_CH_COLORIZE: begin + qsopt.colorize:=IsDlgButtonChecked(Dialog,IDC_CH_COLORIZE)<>BST_UNCHECKED; + RedrawWindow(grid,nil,0,RDW_INVALIDATE); + end; + + IDC_REFRESH: begin + ClearBuffers; + PrepareToFill; + PrepareTable(true); + FillGrid; + end; + + IDCANCEL: CloseSrWindow(); + end; + end; + end; + end; + + WM_NOTIFY: begin + case integer(PNMHdr(lParam)^.code) of + LVN_COLUMNCLICK: begin + ColumnClick(PNMListView(lParam)^.hdr.hwndFrom,PNMListView(lParam)^.iSubItem); + end; + NM_CUSTOMDRAW: begin + if PNMHdr(lParam)^.hwndFrom=grid then + begin + SetWindowLongPtrW(Dialog,DWL_MSGRESULT,ProcessCustomDraw(lParam)); + result:=1; + end; + end; + end; + end; + +// else +// result:=DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; + +function CloseSrWindow:boolean; +begin + result:=true; + if opened and (mainwnd<>0) then + begin + DestroyWindow(mainwnd); + + opened:=false; + mainwnd:=0; + end; + FreeProtoList; +end; + +function OpenSRWindow(apattern:PWideChar;flags:LPARAM):boolean; +begin + result:=true; + if opened then + exit; + + TTInstalled := ServiceExists(MS_TIPPER_SHOWTIP)<>0; + // too lazy to move pattern and flags to thread + if apattern<>nil then + begin + if flags=0 then + StrDupW(pattern,apattern) + else + AnsiToWide(PAnsiChar(apattern),pattern); + CharLowerW(pattern); + end + else if qsopt.savepattern then + pattern:=DBReadUnicode(0,qs_module,'pattern',nil) + else + pattern:=nil; + + CreateProtoList; + if PrepareToFill then + begin +//!! SetLength(colorder,qsopt.numcolumns); + ColorReload(0,0); + CreateDialogW(hInstance,PWideChar(IDD_MAIN),0,@QSMainWndProc); + end; +end; + +function BringToFront:integer; +var + wp:TWINDOWPLACEMENT; +begin + result:=1; + wp.length:=SizeOf(TWINDOWPLACEMENT); + GetWindowPlacement(mainwnd,@wp); + if wp.showCmd=SW_SHOWMINIMIZED then + ShowWindow(mainwnd,SW_RESTORE); + SetForegroundWindow(mainwnd); +end; + +procedure ChangeStatusPicture(row:integer; hContact:THANDLE;Pic:integer); +var + li:LV_ITEM; +begin + row:=FindItem(row); + if row>=0 then + begin + li.iItem :=row; + li.iSubItem:=0; + li.mask :=LVIF_IMAGE; + li.iImage :=Pic;//CallService(MS_CLIST_GETCONTACTICON,hContact,0); + SendMessage(grid,LVM_SETITEM,0,lparam(@li)); + end; +end; + +function OnStatusChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + j:integer; + oldstat,newstat:integer; +begin + result:=0; + if not opened then exit; + + j:=FindBufNumber(wParam); + if j>=0 then + begin + oldstat:=FlagBuf[j].status; + newstat:=DBReadWord(wParam,GetProtoName(FlagBuf[j].proto),'Status',ID_STATUS_OFFLINE); + FlagBuf[j].status:=newstat; + + if (oldstat<>ID_STATUS_OFFLINE) and (newstat<>ID_STATUS_OFFLINE) then + ChangeStatusPicture(j,wParam,lParam) + else if (oldstat=ID_STATUS_OFFLINE) {and (newstat<>ID_STATUS_OFFLINE)} then + begin + if qsopt.showoffline then + ChangeStatusPicture(j,wParam,lParam) + else + ProcessLine(j,false) // why false? need to filter! + end + else if {(oldstat<>ID_STATUS_OFFLINE) and} (newstat=ID_STATUS_OFFLINE) then + begin + if qsopt.showoffline then + ChangeStatusPicture(j,wParam,lParam) + else + begin + FlagBuf[j].flags:=FlagBuf[j].flags and not QSF_ACTIVE; + ListView_DeleteItem(grid,FindItem(j)); + end; + end; + + // refresh table to new filtering + if qsopt.sortbystatus then + Sort; + UpdateSB; + end; +end; + +function OnContactAdded(wParam:WPARAM;lParam:LPARAM):int;cdecl; +begin + result:=0; + if opened then + PostMessage(mainwnd,WM_MYADDCONTACT,wParam,lParam); +end; + +function OnContactDeleted(wParam:WPARAM;lParam:LPARAM):int;cdecl; +begin + result:=0; + if opened then + PostMessage(mainwnd,WM_MYDELETECONTACT,wParam,lParam); +end; + +function OnAccountChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl; +begin + result:=0; + if not opened then exit; + case wParam of + PRAC_ADDED: begin + end; + PRAC_REMOVED: begin + end; + PRAC_CHECKED: begin + with PPROTOACCOUNT(lParam)^ do + begin + if bIsEnabled<>0 then + begin + end + else + begin + end; + end; + end; + end; +end; + +function ShiftIndex(idx:integer;var order:array of integer):pointer; +var + i,n:integer; +begin + n:=colorder[idx]; + for i:=0 to qsopt.numcolumns-1 do + if order[i]>n then dec(order[i]); + result:=@order; +end; + +procedure FillLVColumn(column,lvcolumn:integer); +var + li:LV_ITEMW; + i:integer; +begin + FillChar(li,SizeOf(li),0); + for i:=0 to ListView_GetItemCount(grid)-1 do + begin + li.iItem :=i; + li.mask :=LVIF_PARAM; + li.iSubItem:=0; + SendMessage(grid,LVM_GETITEM,0,lparam(@li)); + + li.pszText :=MainBuf[li.lParam,column].text; + // Client icons preprocess + if (((qsopt.columns[column].flags and COL_CLIENT)<>0) and + (li.pszText<>NIL) and qsopt.showclienticons) OR + ((qsopt.columns[column].flags and (COL_XSTATUS or COL_GENDER))<>0) then + li.mask:=LVIF_IMAGE or LVIF_TEXT + else + li.mask:=LVIF_TEXT; + li.iSubItem:=lvcolumn; + SendMessageW(grid,LVM_SETITEMW,0,lparam(@li)); + end; +end; + +procedure SetColumnOrder; +var + i,col:integer; + lcol:array [0..99] of integer; +begin + col:=0; + for i:=0 to qsopt.numcolumns-1 do + if colorder[i]>=0 then + begin + lcol[col]:=colorder[i]; + inc(col); + end; + + SendMessageW(grid,LVM_SETCOLUMNORDERARRAY,col,lparam(@lcol[0])); + + InvalidateRect(grid,nil,false); +end; + +procedure WndChangeColumns(code:integer;column:integer=-1); +var + i,col:integer; + coldata:tQSRec; +// lcol:array of integer; + incr:integer; +begin + if (grid<>0) and + ((code=wcRefresh) or ((column>=0) and (column=0 then + begin + lcol[col]:=colorder[i]; + inc(col); + end; + + SendMessageW(grid,LVM_SETCOLUMNORDERARRAY,tablecolumns,dword(@lcol[0])); + + InvalidateRect(grid,nil,false); +} + end; + + wcInsert: begin // add column + // memory + SetLength(MainBuf,Length(MainBuf),qsopt.numcolumns+1); //!!!! + SetSpecialColumns(column); + // index + SetLength(colorder,qsopt.numcolumns+1); + // screen + if (qsopt.columns[column].flags and COL_ON)<>0 then + WndChangeColumns(wcShow,column) + else + colorder[column]:=-1; + end; + + wcChange: begin // change column + for i:=0 to HIGH(MainBuf) do + begin + mFreeMem(MainBuf[i,column].text); + end; + SetSpecialColumns(column); + qsopt.columns[column].flags:=qsopt.columns[column].flags and not COL_INIT; + if (qsopt.columns[column].flags and COL_ON)<>0 then + FillLVColumn(column,colorder[column]); + end; + + wcRefresh: begin // refresh all info + ClearBuffers; + PrepareToFill; + PrepareTable(true); + end; + end; + FillGrid; + SendMessage(grid,WM_SETREDRAW,1,0); + end; +end; + +begin +end. -- cgit v1.2.3