summaryrefslogtreecommitdiff
path: root/plugins/QuickSearch/sr_window.pas
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/QuickSearch/sr_window.pas')
-rw-r--r--plugins/QuickSearch/sr_window.pas2830
1 files changed, 1100 insertions, 1730 deletions
diff --git a/plugins/QuickSearch/sr_window.pas b/plugins/QuickSearch/sr_window.pas
index 361ec3ca4e..dea7113310 100644
--- a/plugins/QuickSearch/sr_window.pas
+++ b/plugins/QuickSearch/sr_window.pas
@@ -5,14 +5,8 @@ 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
@@ -21,29 +15,25 @@ const
implementation
uses messages,commctrl,sr_global,common,dbsettings,mirutils,
- wrapper,sr_optdialog,protocols;
+ wrapper,protocols,sparam,srvblock,editwrapper;
+
+const
+ IDM_STAYONTOP = WM_USER+1;
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;
+ OldLVHProc :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
@@ -60,35 +50,24 @@ type
data:uint_ptr;
end;
pQSFRec = ^tQSFRec;
- tQSFRec = record // row
+ tQSFRec = record // row (contact)
contact:THANDLE;
proto :uint_ptr;
flags :dword;
status :dword;
- wparam :WPARAM;
+//--- Metacontacts only ---
+ wparam :WPARAM;
lparam :LPARAM;
end;
var
- colorhook:THANDLE;
MainBuf:array of array of tQSRec;
FlagBuf:array of tQSFRec;
LastMeta:integer;
+ tablecolumns:integer;
+var
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;
@@ -96,550 +75,134 @@ 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;
+{$i i_ok.inc}
-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;
+function FindItem(num:integer):integer;
var
- Day,Month,Year,Hours,Minutes:word;
+ fi:LV_FINDINFO;
begin
- Year:=DBReadWord(cont,modulename,'Year',0);
- if Year<>0 then
+ if num>=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
+ FillChar(fi,SizeOf(fi),0);
+ fi.flags :=LVFI_PARAM;
+ fi.lParam:=num;
+ result:=SendMessage(grid,LVM_FINDITEM,wparam(-1),lparam(@fi));
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);
+ result:=num;
end;
-function FindMeta(hMeta:THANDLE;var MetaNum:WPARAM):LPARAM;
+function GetLVSubItem(x,y:integer):integer;
var
- i:integer;
+ pinfo:LV_HITTESTINFO;
begin
- result:=0;
- for i:=0 to HIGH(FlagBuf) do
+ pinfo.flags:=0;
+ pinfo.pt.x:=x;
+ pinfo.pt.y:=y;
+ ScreenToClient(grid,pinfo.pt);
+ result:=-1;
+ if integer(SendMessage(grid,LVM_SUBITEMHITTEST,0,tlparam(@pinfo)))<>-1 then
begin
- with FlagBuf[i] do
+ if (pinfo.flags and LVHT_ONITEM)<>0 then
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;
+ result:=pinfo.iSubItem;
end;
end;
end;
-function DoMeta(hContact:THANDLE):pointer;
+procedure AddContactToList(hContact:THANDLE;num:integer);
var
- pw:pWideChar;
+ li:LV_ITEMW;
i:integer;
begin
- result:=nil;
- for i:=0 to HIGH(FlagBuf) do
+ 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;
+ li.iSubItem:=0;
+ for i:=0 to qsopt.numcolumns-1 do
begin
- with FlagBuf[i] do
+ with qsopt.columns[i] do
begin
- if contact=hContact then
+ if (flags and COL_ON)<>0 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;
+ // Client icons preprocess
+ li.pszText :=MainBuf[num,i].text;
+ if (((flags and COL_CLIENT)<>0) and
+ ((qsopt.flags and QSO_CLIENTICONS)<>0) and
+ (li.pszText<>NIL)) OR
+ ((flags and (COL_XSTATUS or COL_GENDER))<>0) then
+ li.mask:=LVIF_IMAGE or LVIF_TEXT
+ else
+ li.mask:=LVIF_TEXT;
+ SendMessageW(grid,LVM_SETITEMW,0,tlparam(@li));
+ inc(li.iSubItem);
end;
end;
end;
end;
-procedure LoadOneItem(hContact:THANDLE;num:integer;proto:integer; var res:tQSRec);
+
+procedure ProcessLine(num:integer;test:boolean=true);
var
- cni:TCONTACTINFO;
- dbei:TDBEVENTINFO;
- hDbEvent:cardinal;
- tmp:int_ptr;
- protov:PAnsiChar;
+ p:pQSFRec;
+ l:boolean;
begin
- FillChar(res,SizeOf(tQSRec),0);
- res.data:=uint_ptr(-1);
- res.text:=nil;
- with qsopt.columns[num] do
- begin
+ p:=@FlagBuf[num];
+ if (p^.flags and QSF_DELETED)<>0 then
+ exit;
- if module_name<>nil then
- protov:=module_name
+ if test then
+ begin
+ l:=CheckPatternW(num);
+ if l then
+ p^.flags:=p^.flags or QSF_PATTERN
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:=int_ptr(CallService(protov,wparam.n,lparam.n));
- if tmp=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;
+ p^.flags:=p^.flags and not QSF_PATTERN;
+ end
+ else
+ l:=(p^.flags and QSF_PATTERN)<>0;//true;
- ST_INT: begin
- if (module_name=nil) and (wparam.a=nil) then
- begin
- res.data:=hContact;
- res.text:=int2hexw(res.data);
- end
- else
+ if l then
+ begin
+ if (p^.flags and QSF_ACTIVE)=0 then
+ begin
+ if ((qsopt.flags and QSO_SHOWOFFLINE)<>0) or (p^.status<>ID_STATUS_OFFLINE) then
+ begin
+ // check for proto in combo
+ if (LoByte(AdvFilter)=0) or (p^.proto=LoByte(AdvFilter)) then
begin
- res.data:=DBReadDWord(hContact,protov,wparam.a,0);
- res.text:=int2strw(res.data);
+ p^.flags:=p^.flags or QSF_ACTIVE;
+ AddContactToList(p^.contact,num);
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:=db_event_last(hContact);
- if hDbEvent<>0 then
- begin
- ZeroMemory(@dbei,sizeof(dbei));
- dbei.cbSize:=SizeOf(dbei);
- db_event_get(hDbEvent, @dbei);
- res.data:=dbei.timestamp;
- res.text:=TimeToStrW(res.data);
- end
- else
- res.data:=0;
- 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 CompareItem(lParam1,lParam2:LPARAM;SortType:LPARAM):int; stdcall;
var
- typ1,typ2:boolean;
res1,res2:pQSRec;
i1,i2:uint_ptr;
+ typ1,typ2:boolean;
begin
result:=0;
if SortType=StatusSort then //sort by status
@@ -690,385 +253,23 @@ begin
else
result:=0;
end;
- if not qsopt.ascendsort then
+ if (qsopt.flags and QSO_SORTASC)=0 then
result:=-result;
end;
-function FindBufNumber(hContact:THANDLE):integer;
-var
- i:integer;
-begin
- for i:=0 to HIGH(FlagBuf) do
- begin
- if FlagBuf[i].contact=hContact then
- begin
- result:=i;
- exit;
- end;
- end;
- result:=-1;
-end;
-
-function FindItem(num:integer):integer;
-var
- fi:LV_FINDINFO;
-begin
- if num>=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));
+ SendMessage(grid,LVM_SORTITEMS,ListViewToColumn(qsopt.columnsort),LPARAM(@CompareItem));
// ListView_SortItems(grid,@CompareItem,GetQSColumn(qsopt.columnsort));
- if (qsopt.columnsort<>StatusSort) and qsopt.sortbystatus then
+ if (qsopt.columnsort<>StatusSort) and ((qsopt.flags and QSO_SORTBYSTATUS)<>0) 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;
@@ -1133,93 +334,8 @@ begin
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:=db_find_first();
- while hContact<>0 do
- begin
- //!! check account
- AddContact(cnt1,hContact);
- inc(cnt1);
- if cnt1=cnt then break; // additional checking
- hContact:=db_find_next(hContact);
- 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;
+//----- contacts actions -----
function GetFocusedhContact:THANDLE;
var
@@ -1237,7 +353,7 @@ begin
if hContact<>0 then
begin
ShowContactDialog(hContact);
- if qsopt.closeafteraction then DestroyWindow(mainwnd);
+ if (qsopt.flags and QSO_AUTOCLOSE)<>0 then DestroyWindow(mainwnd);
end;
end;
@@ -1272,9 +388,9 @@ end;
procedure ConvertToMeta;
var
- i,j:integer;
hMeta:THANDLE;
tmp:THANDLE;
+ i,j:integer;
begin
j:=ListView_GetItemCount(grid)-1;
@@ -1319,19 +435,51 @@ begin
end;
end;
+procedure UpdateLVCell(item,column:integer;text:pWideChar=pWideChar(-1));
+var
+ li:LV_ITEMW;
+ contact:THANDLE;
+ row:integer;
+begin
+ contact:=FlagBuf[LV_GetLParam(grid,item)].contact;
+ // get buffer row from LV item
+ row:=FindBufNumber(contact);
+ // get cell text
+ if text=pWideChar(-1) then
+ begin
+ if (qsopt.columns[column].flags or COL_INIT)<>0 then //??
+ mFreeMem(MainBuf[row,column].text);
+ LoadOneItem(contact,@qsopt.columns[column],0,MainBuf[row,column]);
+ text:=MainBuf[row,column].text;
+ end;
+
+ // rewrite LV cell
+ zeromemory(@li,sizeof(li));
+ li.mask :=LVIF_TEXT;
+ li.iItem :=item;
+ li.iSubItem:=ColumnToListview(column); // buffer column to LV subitem
+ li.pszText :=text;
+ SendMessageW(grid,LVM_SETITEMW,0,tlparam(@li));
+
+ // if need to filter and sort, do it
+ if (qsopt.columns[column].flags and COL_FILTER)<>0 then
+ ProcessLine(row);
+ if qsopt.columnsort=li.iSubItem then
+ Sort;
+end;
+
procedure MoveToGroup(group:PWideChar);
var
- i,j,grcol:integer;
contact:THANDLE;
+ i,j,grcol,row:integer;
begin
j:=ListView_GetItemCount(grid)-1;
+ // search group column in QS window (if presents)
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
+ if (flags and COL_GROUP)<>0 then
begin
if (flags and COL_ON)=0 then
flags:=flags and not COL_INIT
@@ -1340,46 +488,108 @@ begin
break;
end
end;
+ // move to new group and changing in LV if needs
for i:=0 to j do
begin
if ListView_GetItemState(grid,i,LVIS_SELECTED)<>0 then
begin
contact:=FlagBuf[LV_GetLParam(grid,i)].contact;
+ // change settings
DBWriteUnicode(contact,strCList,'Group',group);
- if (not qsopt.closeafteraction) and (grcol>=0) then
+ // update buffer and LV
+ if ((qsopt.flags and QSO_AUTOCLOSE)=0) and (grcol>=0) then
begin
- LoadOneItem(contact,grcol,0,MainBuf[i,grcol]);
+ row:=FindBufNumber(contact);
+
+ mFreeMem(MainBuf[row,grcol].text);
+ StrDupW(MainBuf[row,grcol].text,group);
+
+// LoadOneItem(contact,qsopt.columns[grcol],0,MainBuf[row,grcol]);
+ UpdateLVCell(i,grcol);
end;
end;
end;
- if (not qsopt.closeafteraction) and (grcol>=0) then
- FillGrid;
end;
-function IsColumnMinimized(num:integer):bool;
+procedure MoveToContainer(container:PWideChar);
+var
+ contact:THANDLE;
+ i,j,grcol,row:integer;
begin
- result:=ListView_GetColumnWidth(grid,num)<=10;
+ j:=ListView_GetItemCount(grid)-1;
+ // search container column in QS window (if presents)
+ grcol:=-1;
+
+ for i:=0 to qsopt.numcolumns-1 do
+ begin
+ with qsopt.columns[i] do
+ if (flags and COL_CNTNR)<>0 then
+ begin
+ if (flags and COL_ON)=0 then
+ flags:=flags and not COL_INIT
+ else
+ grcol:=i;
+ break;
+ end
+ end;
+
+ // attach to new container and changing in LV if needs
+ for i:=0 to j do
+ begin
+ if ListView_GetItemState(grid,i,LVIS_SELECTED)<>0 then
+ begin
+ contact:=FlagBuf[LV_GetLParam(grid,i)].contact;
+ if container^=#0 then
+ DBDeleteSetting(contact,'Tab_SRMsg','containerW')
+ else
+ DBWriteUnicode(contact,'Tab_SRMsg','containerW',container);
+ if ((qsopt.flags and QSO_AUTOCLOSE)=0) and (grcol>=0) then
+ begin
+ row:=FindBufNumber(contact);
+
+ mFreeMem(MainBuf[row,grcol].text);
+ StrDupW(MainBuf[row,grcol].text,container);
+
+// LoadOneItem(contact,qsopt.columns[grcol],0,MainBuf[row,grcol]);
+ UpdateLVCell(i,grcol);
+ end;
+ end;
+ end;
end;
-procedure CopyMultiLinesW(num:integer);
+// right now - memory column order, not screen
+procedure CopyMultiLinesW;
var
- i,j,k:integer;
p,buf:PWideChar;
+ idx:integer;
+ i,j,k:integer;
tmpcnt,cnt:integer;
begin
+{
+ lv:LV_COLUMNW;
+ buf:array [0..127] of WideChar;
+
+ lv.mask :=LVCF_TEXT;
+ lv.cchTextMax:=128;
+ lv.pszText :=@buf;
+
+ SendMessageW(LVM_GETCOLUMNW,i,LPARAM(@lv));
+
+ use lv.pszText, not qsopt.columns[i].title
+}
+ // calculate buffer size, column order not important
cnt:=0;
- if qsopt.exportheaders then
+
+ k:=0;
+ while k<qsopt.numcolumns do
begin
- k:=0;
- while k<qsopt.numcolumns do
- begin
- if not (qsopt.skipminimized and IsColumnMinimized(k)) then
- inc(cnt,StrLenW(TranslateW(qsopt.columns[k].title))+1);
- Inc(k);
- end;
- if cnt>0 then
- inc(cnt,2);
+ if not IsColumnMinimized(k) then
+ inc(cnt,StrLenW(TranslateW(qsopt.columns[k].title))+1);
+ Inc(k);
end;
+ if cnt>0 then
+ inc(cnt,2);
+
j:=ListView_GetItemCount(grid)-1;
tmpcnt:=cnt;
for i:=0 to j do
@@ -1387,11 +597,11 @@ begin
if ListView_GetItemState(grid,i,LVIS_SELECTED)<>0 then
begin
k:=0;
- num:=LV_GetLParam(grid,i);
+ idx:=LV_GetLParam(grid,i);
while k<qsopt.numcolumns do
begin
- if not (qsopt.skipminimized and IsColumnMinimized(k)) then
- inc(cnt,StrLenW(MainBuf[num,k].text)+1);
+ if not IsColumnMinimized(k) then
+ inc(cnt,StrLenW(MainBuf[idx,k].text)+1);
Inc(k);
end;
end;
@@ -1405,36 +615,33 @@ begin
mGetMem(buf,cnt*SizeOf(WideChar));
p:=buf;
- if qsopt.exportheaders then
+ // fill info (need visual column order)
+ k:=0;
+ while k<qsopt.numcolumns do
begin
- k:=0;
- while k<qsopt.numcolumns do
+ if not IsColumnMinimized(k) then
begin
- if not (qsopt.skipminimized and IsColumnMinimized(k)) then
- begin
- StrCopyW(p,TranslateW(qsopt.columns[k].title));
- p:=StrEndW(p);
- p^:=#9;
- inc(p);
- end;
- inc(k);
+ p:=StrCopyEW(p,TranslateW(qsopt.columns[k].title));
+ p^:=#9;
+ inc(p);
end;
- (p-1)^:=#13;
- p^ :=#10;
- inc(p);
+ inc(k);
end;
+ (p-1)^:=#13;
+ p^ :=#10;
+ inc(p);
+
for i:=0 to j do
begin
if ListView_GetItemState(grid,i,LVIS_SELECTED)<>0 then
begin
k:=0;
- num:=LV_GetLParam(grid,i);
+ idx:=LV_GetLParam(grid,i);
while k<qsopt.numcolumns do
begin
- if not (qsopt.skipminimized and IsColumnMinimized(k)) then
+ if not IsColumnMinimized(k) then
begin
- StrCopyW(p,MainBuf[num,k].text);
- p:=StrEndW(p);
+ p:=StrCopyEW(p,MainBuf[idx,k].text);
p^:=#9;
inc(p);
end;
@@ -1449,6 +656,443 @@ begin
CopyToClipboard(buf,false);
mFreeMem(buf);
end;
+{
+procedure CopySingleLine;
+var
+ p,pp:pWideChar;
+ cnt,num,i:integer;
+begin
+ // same as multiline - memory column order
+ cnt:=0;
+ num:=LV_GetLParam(grid,ListView_GetNextItem(grid,-1,LVNI_FOCUSED));
+ i:=0;
+ while i<qsopt.numcolumns do
+ begin
+ if not (qsopt.skipminimized and IsColumnMinimized(i)) then
+ begin
+ p:=TranslateW(qsopt.columns[i].title);
+ inc(cnt,StrLenW(p)+1);
+ if (StrEndW(p)-1)^<>':' 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<qsopt.numcolumns do
+ begin
+ if not (qsopt.skipminimized and IsColumnMinimized(i)) then
+ begin
+ p:=StrCopyEW(p,TranslateW(qsopt.columns[i].title));
+ if (p-1)^<>':' then
+ begin
+ p^:=':';
+ inc(p);
+ end;
+ p^:=' '; inc(p);
+ p:=StrCopyEW(p,MainBuf[num,i].text);
+ p^:=#13; (p+1)^:=#10; inc(p,2);
+ end;
+ end;
+ p^:=#0;
+
+ CopyToClipboard(pp,false);
+ mFreeMem(pp);
+end;
+}
+const
+ srvhandle:THANDLE=0;
+ mnuhandle:THANDLE=0;
+ cmcolumn :integer=-1;
+
+function ColChangeFunc(wParam:WPARAM;lParam:LPARAM):int_ptr; cdecl;
+var
+ pc,pc1:pWideChar;
+ p:pAnsiChar;
+ tbuf:array [0..255] of WideChar;
+ lmodule:pAnsiChar;
+ contact:integer;
+ col:pcolumnitem;
+ qsr:pQSRec;
+begin
+ col:=@qsopt.columns[cmcolumn];
+ StrCopyW(StrCopyEW(@tbuf,TranslateW('Editing of column ')),col.title);
+ contact:=FindBufNumber(wParam);
+ qsr:=@MainBuf[contact,cmcolumn];
+ pc:=qsr.text;
+ result:=ShowEditBox(grid,pc,@tbuf);
+ if result=-1 then
+ exit
+ else if result=1 then
+ begin
+ pc1:=pc;
+ pc:=ParseVarString(pc1,wParam);
+ mFreeMem(pc1);
+ end;
+ // change buffer value
+ mFreeMem(qsr.text);
+ qsr.text:=pc;
+ if col.datatype<>QSTS_STRING then
+ begin
+ qsr.data:=NumToInt(qsr.text);
+ end;
+ // change database setting value
+ if col.module<>nil then
+ lmodule:=col.module
+ else
+ begin
+ lmodule:=GetProtoName(FlagBuf[contact].proto);
+ end;
+
+ case col.datatype of
+ QSTS_BYTE: begin
+ DBWriteByte(wParam,lmodule,
+ col.setting,qsr.data);
+ end;
+ QSTS_WORD: begin
+ DBWriteWord(wParam,lmodule,
+ col.setting,qsr.data);
+ end;
+ QSTS_DWORD,QSTS_SIGNED,QSTS_HEXNUM: begin
+ DBWriteDWord(wParam,lmodule,
+ col.setting,dword(qsr.data));
+ end;
+ QSTS_STRING: begin
+ case DBGetSettingType(wParam,lmodule,col.setting) of
+ DBVT_ASCIIZ: begin
+ WideToAnsi(qsr.text,p,MirandaCP);
+ DBWriteString(wParam,lmodule,col.setting,p);
+ mFreeMem(p);
+ end;
+ DBVT_UTF8: begin
+ WidetoUTF8(qsr.text,p);
+ DBWriteUTF8(wParam,lmodule,col.setting,p);
+ mFreeMem(p);
+ end;
+ DBVT_WCHAR: begin
+ DBWriteUnicode(wParam,lmodule,
+ col.setting,qsr.text);
+ end;
+ end;
+ end;
+ end;
+
+ UpdateLVCell(SendMessage(grid,LVM_GETNEXTITEM,-1,LVNI_FOCUSED),cmcolumn,qsr.text);
+end;
+
+function ShowContactMenu(wnd:HWND;hContact:THANDLE;col:integer=-1):HMENU;
+var
+ mi:TCListMenuItem;
+ pt:tpoint;
+ doit:bool;
+begin
+ if hContact<>0 then
+ begin
+ doit:=false;
+ if col>=0 then
+ begin
+ col:=ListViewToColumn(col);
+ if (qsopt.columns[col].setting_type=QST_SETTING) and
+ // right now, not time or IP
+ (qsopt.columns[col].datatype<>QSTS_IP) and
+ (qsopt.columns[col].datatype<>QSTS_TIMESTAMP) then
+ begin
+ doit:=true;
+
+ if srvhandle=0 then
+ srvhandle:=CreateServiceFunction('QS/dummy',@ColChangeFunc);
+
+ cmcolumn:=col;
+
+ FillChar(mi,SizeOf(mi),0);
+ mi.cbSize:=SizeOf(mi);
+ if mnuhandle=0 then
+ begin
+ mi.flags :=CMIF_UNICODE;
+ mi.szName.w :='Change setting through QS';
+ mi.pszService:='QS/dummy';
+ mnuhandle:=Menu_AddContactMenuItem(@mi);
+ end
+ else
+ begin
+ mi.flags :=CMIM_FLAGS;
+ CallService(MS_CLIST_MODIFYMENUITEM,mnuhandle,LPARAM(@mi));
+ end;
+ end;
+ end;
+
+ 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;
+ // Due to stupid miranda logic, we need to clear tails at service processing, not earlier
+ if doit then
+ begin
+ mi.cbSize:=SizeOf(mi);
+ mi.flags :=CMIM_FLAGS or CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM,mnuhandle,LPARAM(@mi));
+ end;
+
+ end
+ else
+ result:=0;
+end;
+
+function MyStrSort(para1:pointer; para2:pointer):int; cdecl;
+begin
+ result:=StrCmpW(pWideChar(para1),pWideChar(para2));
+end;
+
+function MakeContainerMenu(idxfrom:integer=100):HMENU;
+var
+ sl:TSortedList;
+ i:integer;
+ b:array [0..15] of AnsiChar;
+ p:pWideChar;
+begin
+ result:=CreatePopupMenu;
+ AppendMenuW(result,MF_STRING,idxfrom,TranslateW('default'));
+ AppendMenuW(result,MF_SEPARATOR,0,nil);
+ FillChar(sl,SizeOf(sl),0);
+ sl.increment:=16;
+ sl.sortFunc:=@MyStrSort;
+ i:=1;
+ repeat
+ p:=DBReadUnicode(0,'TAB_ContainersW',IntToStr(b,i),nil);
+ if p=nil then break;
+ List_InsertPtr(@sl,p);
+ inc(i);
+ until false;
+ inc(idxfrom);
+ for i:=0 to sl.realCount-1 do
+ begin
+ p:=pWideChar(sl.Items[i]);
+ AppendMenuW(result,MF_STRING,idxfrom+i,p);
+ mFreeMem(p);
+ end;
+ List_Destroy(@sl);
+end;
+
+procedure ShowMultiPopup(cnt:integer);
+var
+ mmenu,grpmenu,cntmenu:HMENU;
+ p:PWideChar;
+ pt:TPOINT;
+ buf:array [0..255] of WideChar;
+ i:integer;
+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'));
+
+ cntmenu:=MakeContainerMenu(300);
+ AppendMenuW(mmenu,MF_POPUP,cntmenu,TranslateW('Attach to &Tab container'));
+
+ grpmenu:=MakeGroupMenu(400);
+ AppendMenuW(mmenu,MF_POPUP,grpmenu,TranslateW('&Move to Group'));
+// grpmenu:=CallService(MS_CLIST_GROUPBUILDMENU,0,0);
+
+ 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;
+ 300..399: begin
+ if i=300 then // default container, just delete setting
+ buf[0]:=#0
+ else
+ begin
+ GetMenuStringW(cntmenu,i,buf,SizeOf(buf),MF_BYCOMMAND);
+ end;
+ MoveToContainer(buf);
+ end;
+ 400..499: begin
+ 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.flags and QSO_AUTOCLOSE)<>0 then
+ CloseSrWindow;
+end;
+
+//----- ListView Columns -----
+
+procedure ColumnClick(wnd:HWND;num:integer);
+var
+ hdi:THDITEM;
+ header:HWND;
+begin
+ header:=ListView_GetHeader(wnd);
+
+ zeromemory(@hdi,sizeof(hdi));
+ // clear sort mark
+ hdi.mask:=HDI_FORMAT;
+ SendMessage(header,HDM_GETITEM,qsopt.columnsort,lparam(@hdi));
+ hdi.fmt:=hdi.fmt and not (HDF_SORTDOWN or HDF_SORTUP);
+ SendMessage(header,HDM_SETITEM,qsopt.columnsort,lparam(@hdi));
+
+ if qsopt.columnsort<>num then
+ begin
+ qsopt.flags:=qsopt.flags or QSO_SORTASC;
+ qsopt.columnsort:=num;
+ end
+ else
+ qsopt.flags:=qsopt.flags xor QSO_SORTASC;
+
+ // set new sort mark
+ SendMessage(header,HDM_GETITEM,qsopt.columnsort,lparam(@hdi));
+ if (qsopt.flags and QSO_SORTASC)<>0 then
+ hdi.fmt:=hdi.fmt or HDF_SORTDOWN
+ else
+ hdi.fmt:=hdi.fmt or HDF_SORTUP;
+ SendMessage(header,HDM_SETITEM,qsopt.columnsort,lparam(@hdi));
+
+ Sort;
+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
+ ((qsopt.flags and QSO_CLIENTICONS)<>0) and
+ (li.pszText<>NIL)) 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 MakeColumnMenu;
+var
+ column:pcolumnitem;
+ menu:HMENU;
+ lvcol:LV_COLUMNW;
+ pt:TPOINT;
+ flag,id,i,j:integer;
+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);
+ column:=@qsopt.columns[id];
+ column.flags:=column.flags xor COL_ON;
+ if (column.flags and COL_ON)<>0 then
+ begin
+ // memory
+ if (column.flags and COL_INIT)=0 then
+ begin
+ for i:=0 to HIGH(MainBuf) do // contacts
+ begin
+ LoadOneItem(FlagBuf[i].contact,column,FlagBuf[i].proto,MainBuf[i,id]);
+ end;
+ column.flags:=column.flags or COL_INIT;
+ end;
+ // screen
+ i:=ColumnToListView(id);
+ zeromemory(@lvcol,sizeof(lvcol));
+ lvcol.mask :=LVCF_TEXT or LVCF_WIDTH;
+ lvcol.pszText :=TranslateW(column.title);
+ lvcol.cx :=column.width;
+ //!!
+ SendMessageW(grid,LVM_INSERTCOLUMNW,i,tlparam(@lvcol));
+
+ // fill new column
+ FillLVColumn(id,i);
+ end
+ else
+ begin
+ j:=0;
+ for i:=0 to qsopt.numcolumns-1 do
+ begin
+ if (qsopt.columns[i].flags and COL_ON)<>0 then
+ inc(j);
+ end;
+ // keep at least one visible column
+ if j>1 then
+ SendMessage(grid,LVM_DELETECOLUMN,ColumnToListView(id),0)
+ else
+ column.flags:=column.flags or COL_ON;
+ end;
+ 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(OldLVHProc,Dialog,hMessage,wParam,lParam);
+end;
var
HintWnd:HWND;
@@ -1458,17 +1102,17 @@ const
OldHItem :integer=0;
OldHSubItem:integer=0;
var
+ p:PWideChar;
buf :array [0..255] of WideChar; //!! for spec columns and patterns now only
buf1:array [0..127] of AnsiChar;
- p,pp:PWideChar;
- i,num,cnt:integer;
+ tmpCursor:TPOINT;
pinfo:LV_HITTESTINFO;
TI:TToolInfoW;
ics:TCUSTOM_STATUS;
info:TCLCINFOTIP;
// qsr:tQSRec;
- tmpCursor:TPOINT;
+ i,num:integer;
begin
result:=0;
case hMessage of
@@ -1495,55 +1139,8 @@ begin
end;
// Ctrl-C
3: begin
- i:=ListView_GetSelectedCount(grid);
- if (i>1) 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<qsopt.numcolumns do
- begin
- if not (qsopt.skipminimized and IsColumnMinimized(i)) then
- begin
- p:=TranslateW(qsopt.columns[i].title);
- inc(cnt,StrLenW(p)+1);
- if (StrEndW(p)-1)^<>':' 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<qsopt.numcolumns do
- begin
- if not (qsopt.skipminimized and IsColumnMinimized(i)) then
- begin
- StrCopyW(p,TranslateW(qsopt.columns[i].title));
- p:=StrEndW(p);
- if (p-1)^<>':' 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);
+// i:=ListView_GetSelectedCount(grid);
+ CopyMultiLinesW();
exit;
end;
// backspace
@@ -1637,7 +1234,8 @@ end;
pinfo.flags:=0;
if integer(SendMessage(grid,LVM_SUBITEMHITTEST,0,tlparam(@pinfo)))<>-1 then
begin
- if (pinfo.iItem<>OldHItem) or (pinfo.iSubItem<>OldHSubItem) then
+ if ((pinfo.flags and LVHT_ONITEM)<>0) and
+ ((pinfo.iItem<>OldHItem) or (pinfo.iSubItem<>OldHSubItem)) then
begin
OldHSubItem:=pinfo.iSubItem;
OldHItem :=pinfo.iItem;
@@ -1666,24 +1264,24 @@ end;
hInst :=0;
end;
- OldHSubItem:=GetQSColumn(OldHSubItem);
- if (qsopt.columns[OldHSubItem].flags and
+ num:=ListViewToColumn(OldHSubItem);
+ if (qsopt.columns[num].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
+ if (qsopt.columns[num].flags and COL_GENDER)<>0 then
begin
- case MainBuf[i,OldHSubItem].data of
+ case MainBuf[i,num].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
+ else // if (qsopt.columns[num].flags and COL_XSTATUS)<>0 then
begin
- StrCopyW(buf,MainBuf[i,OldHSubItem].text);
+ StrCopyW(buf,MainBuf[i,num].text);
ics.flags:=CSSF_DEFAULT_NAME or CSSF_MASK_NAME or CSSF_UNICODE;
StrCopy(StrCopyE(buf1,GetProtoName(FlagBuf[i].proto)),PS_GETCUSTOMSTATUSEX);
@@ -1715,7 +1313,7 @@ end;
exit;
end;
VK_INSERT: begin
- CallService(MS_FINDADDFINDADD,0,0);
+ CallService(MS_FINDADD_FINDADD,0,0);
exit;
end;
VK_DELETE: begin
@@ -1734,128 +1332,71 @@ 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;
+ case integer(PNMHdr(lParam)^.code) of
+ HDN_ITEMSTATEICONCLICK: begin
+ if ((PHDNotify(lParam)^.pitem^.mask and HDI_FORMAT )<>0) and
+ ((PHDNotify(lParam)^.pitem^.fmt and HDF_CHECKBOX)<>0) then
+ begin
+ i:=ListViewToColumn(PHDNotify(lParam)^.Item);
-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;
+ if (PHDNotify(lParam)^.pitem^.fmt and HDF_CHECKED)=0 then // OLD state
+ begin
+ qsopt.columns[i].flags:=qsopt.columns[i].flags or COL_FILTER;
+ PHDNotify(lParam)^.pitem^.fmt:=PHDNotify(lParam)^.pitem^.fmt or HDF_CHECKED
+ end
+ else
+ begin
+ qsopt.columns[i].flags:=qsopt.columns[i].flags and not COL_FILTER;
+ PHDNotify(lParam)^.pitem^.fmt:=PHDNotify(lParam)^.pitem^.fmt and not HDF_CHECKED
+ end;
+ SendMessage(
+ PHDNotify(lParam)^.hdr.hWndFrom,HDM_SETITEM,
+ PHDNotify(lParam)^.Item,tlparam(PHDNotify(lParam)^.pitem));
+// result:=1;
+ FillGrid;
+ exit;
+ end;
+ end;
+ HDN_ENDDRAG: begin
+ end;
end;
- WndChangeColumns(flag,id);
- OptChangeColumns(wcShow,id,ord(flag=wcShow));
end;
- DestroyMenu(menu);
end;
+ result:=CallWindowProc(OldLVProc,Dialog,hMessage,wParam,lParam);
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;
+//----- Single cell painting -----
procedure SetCellColor(lplvcd:PNMLVCUSTOMDRAW;idx:integer);
begin
- if qsopt.colorize then
+ if (qsopt.flags and QSO_COLORIZE)<>0 then
begin
- with FlagBuf[idx] do
+ with FlagBuf[idx] do
begin
if (flags and QSF_ACCDEL)<>0 then
begin
- lplvcd^.clrTextBk:=cbkg_del;
- lplvcd^.clrText :=cfgr_del;
+ lplvcd^.clrTextBk:=QSColors[bkg_del].color;
+ lplvcd^.clrText :=QSColors[fgr_del].color;
end
else if (flags and QSF_ACCOFF)<>0 then
begin
- lplvcd^.clrTextBk:=cbkg_dis;
- lplvcd^.clrText :=cfgr_dis;
+ lplvcd^.clrTextBk:=QSColors[bkg_dis].color;
+ lplvcd^.clrText :=QSColors[fgr_dis].color;
end
else if (flags and QSF_META)<>0 then
begin
- lplvcd^.clrTextBk:=cbkg_meta;
- lplvcd^.clrText :=cfgr_meta;
+ lplvcd^.clrTextBk:=QSColors[bkg_meta].color;
+ lplvcd^.clrText :=QSColors[fgr_meta].color;
end
else if (flags and QSF_SUBMETA)<>0 then
begin
- lplvcd^.clrTextBk:=cbkg_sub;
- lplvcd^.clrText :=cfgr_sub;
+ lplvcd^.clrTextBk:=QSColors[bkg_sub].color;
+ lplvcd^.clrText :=QSColors[fgr_sub].color;
end
else if (flags and QSF_INLIST)=0 then
begin
- lplvcd^.clrTextBk:=cbkg_hid;
- lplvcd^.clrText :=cfgr_hid;
+ lplvcd^.clrTextBk:=QSColors[bkg_hid].color;
+ lplvcd^.clrText :=QSColors[fgr_hid].color;
end
else
idx:=-1;
@@ -1865,15 +1406,15 @@ begin
idx:=-1;
if idx<0 then
begin
- if (not qsopt.drawgrid) and odd(lplvcd^.nmcd.dwItemSpec) then
+ if ((qsopt.flags and QSO_DRAWGRID)=0) and odd(lplvcd^.nmcd.dwItemSpec) then
begin
- lplvcd^.clrTextBk:=cbkg_odd;
- lplvcd^.clrText :=cfgr_odd;
+ lplvcd^.clrTextBk:=QSColors[bkg_odd].color;
+ lplvcd^.clrText :=QSColors[fgr_odd].color;
end
else
begin
- lplvcd^.clrTextBk:=cbkg_norm;
- lplvcd^.clrText :=cfgr_norm;
+ lplvcd^.clrTextBk:=QSColors[bkg_norm].color;
+ lplvcd^.clrText :=QSColors[fgr_norm].color;
end;
end;
end;
@@ -1881,10 +1422,10 @@ end;
function ProcessCustomDraw(lParam:LPARAM):integer;
var
lplvcd:PNMLVCUSTOMDRAW;
- rc:TRECT;
h:HICON;
+ MirVerW:pWideChar;
buf:array [0..255] of AnsiChar;
- MirVerW:PWideChar;
+ rc:TRECT;
i,j,sub:integer;
begin
lplvcd:=pointer(lParam);
@@ -1897,15 +1438,17 @@ begin
CDDS_ITEMPREPAINT: begin
result:=CDRF_NOTIFYSUBITEMDRAW;
- SetCellColor(lplvcd,LV_GetLParam(grid,lplvcd^.nmcd.dwItemSpec));
+ SetCellColor(lplvcd,lplvcd^.nmcd.lItemlParam);
exit;
end;
CDDS_SUBITEM or CDDS_ITEMPREPAINT: begin
- i:=LV_GetLParam(grid,lplvcd^.nmcd.dwItemSpec);
+ i:=lplvcd^.nmcd.lItemlParam;
SetCellColor(lplvcd,i);
- sub:=GetQSColumn(lplvcd^.iSubItem);
+
+ sub:=ListViewToColumn(lplvcd^.iSubItem);
+
if (qsopt.columns[sub].flags and COL_GENDER)<>0 then
begin
ListView_GetSubItemRect(grid,lplvcd^.nmcd.dwItemSpec,lplvcd^.iSubItem,LVIR_ICON,@rc);
@@ -1922,6 +1465,7 @@ begin
end;
result:=CDRF_SKIPDEFAULT;
end
+
else if (qsopt.columns[sub].flags and COL_XSTATUS)<>0 then
begin
j:=StrToInt(MainBuf[i,sub].text);
@@ -1938,17 +1482,20 @@ begin
end;
result:=CDRF_SKIPDEFAULT;
end
- else if qsopt.showclienticons and
+
+ else if ((qsopt.flags and QSO_CLIENTICONS)<>0) and
((qsopt.columns[sub].flags and COL_CLIENT)<>0) then
result:=CDRF_NOTIFYPOSTPAINT;
end;
+
CDDS_SUBITEM or CDDS_ITEMPOSTPAINT: begin
- sub:=GetQSColumn(lplvcd^.iSubItem);
+ sub:=ListViewToColumn(lplvcd^.iSubItem);
if (qsopt.columns[sub].flags and COL_CLIENT)<>0 then
begin
- i:=LV_GetLParam(grid,lplvcd^.nmcd.dwItemSpec);
- MirVerW:=MainBuf[i,sub].text;
- if (lstrlenW(MirVerW)<>0) and (ServiceExists(MS_FP_GETCLIENTICONW)<>0) then
+ MirVerW:=MainBuf[lplvcd^.nmcd.lItemlParam,sub].text;
+
+//!!
+ if (MirVerW<>nil) and (MirVerW[0]<>#0) and (ServiceExists(MS_FP_GETCLIENTICONW)<>0) then
begin
h:=CallService(MS_FP_GETCLIENTICONW,tlparam(MirVerW),0);
ListView_GetSubItemRect(grid,lplvcd^.nmcd.dwItemSpec,lplvcd^.iSubItem,LVIR_ICON,@rc);
@@ -1961,13 +1508,14 @@ begin
end;
end;
+
function NewEditProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall;
var
- count,current,next,perpage:integer;
li:LV_ITEM;
+ count,current,next,perpage:integer;
begin
result:=0;
- case hMessage of
+ case hMessage of
WM_CHAR: if wParam=27 then
begin
PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDCANCEL,0);
@@ -2012,7 +1560,6 @@ begin
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;
@@ -2022,83 +1569,64 @@ begin
result:=CallWindowProc(OldEditProc,Dialog,hMessage,wParam,lParam);
end;
-function ShowContactMenu(wnd:HWND;hContact:THANDLE):HMENU;
+procedure ClearBuffers;
var
- pt:tpoint;
+ w,h:integer;
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;
+ for w:=0 to HIGH(MainBuf) do
+ for h:=0 to HIGH(MainBuf[0]) do
+ mFreeMem(MainBuf[w,h].text);
+
+ SetLength(MainBuf,0);
+ SetLength(FlagBuf,0);
end;
-procedure ShowMultiPopup(cnt:integer);
-var
- mmenu,grpmenu:HMENU;
- i:integer;
- buf:array [0..255] of WideChar;
- p:PWideChar;
- pt:TPOINT;
+procedure SetSpecialColumns(num:integer);
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);
+ with qsopt.columns[num] do
+ begin
+ if setting_type=QST_SETTING then
+ begin
+ if (datatype=QSTS_STRING) and
+ (StrCmp(module ,'CList')=0) and
+ (StrCmp(setting,'Group')=0) then
+ begin
+ flags:=flags or COL_GROUP
+ end
- 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'));
+ else if (datatype=QSTS_STRING) and
+ (StrCmp(module ,'Tab_SRMsg' )=0) and
+ (StrCmp(setting,'containerW')=0) then
+ begin
+ flags:=flags or COL_CNTNR
+ end
- grpmenu:=MakeGroupMenu(400);
+ else if (datatype=QSTS_BYTE) and
+ (lstrcmpia(setting,'XStatusId')=0) then
+ begin
+ flags:=flags or COL_XSTATUS;
+ end
-// grpmenu:=CallService(MS_CLIST_GROUPBUILDMENU,0,0);
- AppendMenuW(mmenu,MF_POPUP,grpmenu,TranslateW('&Move to Group'));
+ else if (datatype=QSTS_STRING) and
+ (StrCmp(setting,'MirVer')=0) and
+ (ServiceExists(MS_FP_GETCLIENTICONW)<>0) then
+ flags:=flags or COL_CLIENT;
- 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
+ else if (setting_type=QST_CONTACTINFO) and (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;
+
+ qsopt.columns[num].flags:=flags;
end;
- DestroyMenu(mmenu);
- if qsopt.closeafteraction then
- CloseSrWindow;
end;
-
+{
procedure addcolumn(handle:hwnd;num,width:integer;title:PWideChar);
var
lvcol:LV_COLUMNW;
@@ -2109,84 +1637,180 @@ begin
lvcol.cx :=width;
SendMessageW(handle,LVM_INSERTCOLUMNW,num,lparam(@lvcol));
end;
-{
-// from zero!!
-function GetNthByMask(const arr:tcolumnarray; num:cardinal; mask:dword):tcolumnitem;
+}
+// Set columns and clear listview
+procedure PrepareTable(reset:boolean=false);
var
- i:cardinal;
+ lvcol:LV_COLUMNW;
+ hdi:THDITEM;
+ header:HWND;
+ i:integer;
+ old:integer;
begin
- for i:=0 to HIGH(arr) do
+ SendMessage(grid,LVM_DELETEALLITEMS,0,0);
+ header:=ListView_GetHeader(grid);
+
+ zeromemory(@hdi,sizeof(hdi));
+ hdi.mask:=HDI_FORMAT;
+
+ old:=tablecolumns;
+ tablecolumns:=0;
+ zeromemory(@lvcol,sizeof(lvcol));
+ lvcol.mask:=LVCF_TEXT or LVCF_WIDTH;
+ for i:=0 to qsopt.numcolumns-1 do
begin
- if (arr[i].flags and mask)<>0 then
+ with qsopt.columns[i] do
begin
- if num=0 then
+ if (flags and COL_ON)<>0 then
begin
- result:=arr[i];
- exit;
+ lvcol.pszText:=TranslateW(title);
+ lvcol.cx :=width;
+ SendMessageW(grid,LVM_INSERTCOLUMNW,tablecolumns,tlparam(@lvcol));
+// addcolumn(grid,tablecolumns,width,TranslateW(title));
+
+ // set checkbox in column header
+ if (flags and COL_FILTER)<>0 then
+ hdi.fmt:=HDF_LEFT or HDF_STRING or HDF_CHECKBOX or HDF_CHECKED
+ else
+ hdi.fmt:=HDF_LEFT or HDF_STRING or HDF_CHECKBOX;
+ SendMessage(header,HDM_SETITEM,tablecolumns,tlparam(@hdi));
+
+ inc(tablecolumns);
end;
- dec(num);
+
+ SetSpecialColumns(i);
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);
+
+ if reset then
+ begin
+ for i:=old+tablecolumns-1 downto tablecolumns do
+ begin
+ SendMessage(grid,LVM_DELETECOLUMN,i,0);
+ end;
+ end;
+
+ ListView_SetItemCount(grid,HIGH(FlagBuf)+1);
end;
-procedure ClearBuffers;
+//----- Miranda Events -----
+
+procedure ChangeStatusPicture(row:integer; hContact:THANDLE; Pic:integer);
var
- w,h:integer;
+ li:LV_ITEMW;
begin
- for w:=0 to HIGH(MainBuf) do
- for h:=0 to HIGH(MainBuf[0]) do
- mFreeMem(MainBuf[w,h].text);
+ 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);
+ SendMessageW(grid,LVM_SETITEMW,0,lparam(@li));
+ end;
end;
-procedure SetSpecialColumns(num:integer);
+function OnStatusChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl;
+var
+ j:integer;
+ oldstat,newstat:integer;
begin
- with qsopt.columns[num] do
+ result:=0;
+
+ j:=FindBufNumber(wParam);
+ if j>=0 then
begin
- if (setting_type=ST_BYTE) and
- (lstrcmpia(wparam.a,'XStatusId')=0) then
- begin
- flags:=flags or COL_XSTATUS;
- end
+ oldstat:=FlagBuf[j].status;
+ newstat:=DBReadWord(wParam,GetProtoName(FlagBuf[j].proto),'Status',ID_STATUS_OFFLINE);
+ FlagBuf[j].status:=newstat;
- else if (setting_type=ST_CONTACTINFO) and
- (setting_cnftype=CNF_GENDER) then
+ 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 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');
+ if (qsopt.flags and QSO_SHOWOFFLINE)<>0 then
+ ChangeStatusPicture(j,wParam,lParam)
+ else
+ ProcessLine(j,true) // why false? need to filter!
end
+ else if {(oldstat<>ID_STATUS_OFFLINE) and} (newstat=ID_STATUS_OFFLINE) then
+ begin
+ if (qsopt.flags and QSO_SHOWOFFLINE)<>0 then
+ ChangeStatusPicture(j,wParam,lParam)
+ else
+ begin
+ FlagBuf[j].flags:=FlagBuf[j].flags and not QSF_ACTIVE;
+ ListView_DeleteItem(grid,FindItem(j));
+ end;
+ end;
- else if (wparam.a<>NIL) and // FingerPrint preprocess
- (setting_type=ST_STRING) and
- (lstrcmpia(wparam.a,'MirVer')=0) and
- (ServiceExists(MS_FP_GETCLIENTICONW)<>0) then
- flags:=flags or COL_CLIENT;
+ // refresh table to new filtering
+ if (qsopt.flags and QSO_SORTBYSTATUS)<>0 then
+ Sort;
+ UpdateSB;
end;
end;
+function OnContactAdded(wParam:WPARAM;lParam:LPARAM):int;cdecl;
+var
+ i:integer;
+begin
+ result:=0;
+ // 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;
+
+function OnContactDeleted(wParam:WPARAM;lParam:LPARAM):int;cdecl;
+var
+ i,j:integer;
+begin
+ result:=0;
+ i:=FindBufNumber(wParam);
+ if i>=0 then
+ begin
+ FlagBuf[i].flags:=(FlagBuf[i].flags or QSF_DELETED) and not QSF_ACTIVE;
+ for j:=0 to HIGH(MainBuf[0]) do
+ mFreeMem(MainBuf[i,j].text);
+ i:=FindItem(i);
+ if i>=0 then
+ ListView_DeleteItem(grid,i);
+ UpdateSB;
+ end;
+end;
+{
+function OnAccountChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl;
+begin
+ result:=0;
+
+ 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;
+}
+//----- Main window procedure with support -----
+
function FindAddDlgResizer(Dialog:HWND;lParam:LPARAM;urc:PUTILRESIZECONTROL):int; cdecl;
begin
case urc^.wId of
@@ -2203,89 +1827,106 @@ begin
end;
end;
-procedure PrepareTable(reset:boolean=false);
+procedure FillProtoCombo(cb:HWND);
var
i:integer;
- old:integer;
begin
- old:=tablecolumns;
- tablecolumns:=0;
+ SendMessage(cb,CB_RESETCONTENT,0,0);
+ CB_AddStrDataW(cb,TranslateW('All'));
+ for i:=1 to GetNumProto do
+ begin
+ CB_AddStrDataW(cb,GetProtoAccName(i),i);
+ end;
+ SendMessage(cb,CB_SETCURSEL,0,0);
+end;
+
+var
+ hAdd,
+ hDelete,
+// hAccount,
+ hChange:THANDLE;
+
+procedure SaveColumnOrder;
+var
+ tmpcolumns:array [0..MaxColumnAmount-1] of integer;
+ lvc:LV_COLUMNW;
+ i,idx,num,cnt:integer;
+begin
+ DBDeleteGroup(0,qs_module,'item*');
+ idx:=0;
+ lvc.mask:=LVCF_ORDER or LVCF_WIDTH;
for i:=0 to qsopt.numcolumns-1 do
begin
- with qsopt.columns[i] do
+ if qsopt.columns[i].setting_type<>0 then
begin
- if (flags and COL_ON)<>0 then
+ if (qsopt.columns[i].flags and COL_ON)<>0 then
begin
- addcolumn(grid,tablecolumns,width,TranslateW(title));
- inc(tablecolumns);
+ SendMessageW(grid,LVM_GETCOLUMN,idx,tlparam(@lvc));
+ qsopt.columns[i].width:=lvc.cx;
+ tmpcolumns[lvc.iOrder]:=i;
+ inc(idx);
end;
-
- SetSpecialColumns(i);
end;
end;
- if reset then
+ idx:=0;
+ cnt:=0;
+ for i:=0 to qsopt.numcolumns-1 do
begin
- for i:=old+tablecolumns-1 downto tablecolumns do
+ if qsopt.columns[i].setting_type<>0 then
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;
-begin
- SendMessage(cb,CB_RESETCONTENT,0,0);
- CB_AddStrDataW(cb,TranslateW('All'));
- for i:=1 to GetNumProto do
- begin
- CB_AddStrDataW(cb,GetProtoAccName(i),i);
+ if (qsopt.columns[i].flags and COL_ON)<>0 then
+ begin
+ num:=tmpcolumns[idx];
+ inc(idx);
+ end
+ else
+ num:=i;
+ savecolumn(cnt,qsopt.columns[num]);
+ inc(cnt);
+ end
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;
+ smenu:HMENU;
+ header:HWND;
+ hdi:THDITEM;
w,h:uint_ptr;
- i:integer;
+ tmp:LONG_PTR;
buf:array [0..255] of WideChar;
+ colarr:array [0..127] of integer absolute buf;
rc:TRECT;
pt:TPOINT;
- smenu:HMENU;
TI:tToolInfoW;
urd:TUTILRESIZEDIALOG;
begin
result:=0;
case hMessage of
WM_DESTROY: begin
+ if srvhandle<>0 then DestroyServiceFunction(srvhandle);
+ if mnuhandle<>0 then CallService(MO_REMOVEMENUITEM,mnuhandle,0);
+
+ UnhookEvent(hAdd);
+ UnhookEvent(hDelete);
+ UnhookEvent(hChange);
+// UnhookEvent(hAccount);
+
UnhookEvent(colorhook);
+ mainwnd:=0;
+
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;
+ // save column width/order
+ SaveColumnOrder;
+
saveopt_wnd;
ListView_SetImageList(grid,0,LVSIL_SMALL);
- opened:=false;
tmp:=GetDC(grid);
h:=GetCurrentObject(tmp,OBJ_FONT);
@@ -2295,22 +1936,21 @@ begin
grid:=0;
- if qsopt.savepattern then
+ if (qsopt.flags and QSO_SAVEPATTERN)<>0 then
+ begin
DBWriteUnicode(0,qs_module,'pattern',pattern);
+ end;
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);
+ srvhandle:=0;
+ mnuhandle:=0;
SetWindowTextW(Dialog,'Quick Search');
@@ -2321,26 +1961,24 @@ begin
InsertMenuW(smenu,6,MF_BYPOSITION or MF_STRING,
IDM_STAYONTOP,TranslateW('Stay on Top'));
- if qsopt.stayontop then
+ if (qsopt.flags and QSO_STAYONTOP)<>0 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
+ CheckDlgButton(Dialog,IDC_CH_SHOWOFFLINE,ORD((qsopt.flags and QSO_SHOWOFFLINE)<>0));
+ if (qsopt.flags and QSO_SHOWOFFLINE)<>0 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));
+ CheckDlgButton(Dialog,IDC_CH_COLORIZE,ORD((qsopt.flags and QSO_COLORIZE)<>0));
+ // Window
mainwnd:=Dialog;
tmp:=GetWindowLongPtrW(Dialog,GWL_EXSTYLE);
- if qsopt.usetoolstyle then
+ if (qsopt.flags and QSO_TOOLSTYLE)<>0 then
tmp:=tmp or WS_EX_TOOLWINDOW
else
tmp:=tmp and not WS_EX_TOOLWINDOW;
@@ -2350,19 +1988,26 @@ begin
CallService(MS_SKIN2_GETICON,0,tlparam(QS_QS)));
grid:=GetDlgItem(Dialog,IDC_LIST);
+ // ListView
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:=LVS_EX_FULLROWSELECT or LVS_EX_SUBITEMIMAGES or LVS_EX_HEADERDRAGDROP or
+ LVS_EX_LABELTIP or LVS_EX_DOUBLEBUFFER;
+ if (qsopt.flags and QSO_DRAWGRID)<>0 then
tmp:=tmp or LVS_EX_GRIDLINES;
SendMessage(grid,LVM_SETEXTENDEDLISTVIEWSTYLE,0,tmp);
+ // ListView header
+ header:=ListView_GetHeader(grid);
+ SetWindowLongPtrW(header,GWL_STYLE,
+ GetWindowLongPtrW(header,GWL_STYLE) or HDS_CHECKBOXES);
+
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(
+ OldLVHProc:=pointer(SetWindowLongPtrW(
SendMessage(grid,LVM_GETHEADER,0,0),
GWL_WNDPROC,LONG_PTR(@NewLVHProc)));
@@ -2381,6 +2026,17 @@ begin
FillGrid;
end;
+ // Show sorting column
+ zeromemory(@hdi,sizeof(hdi));
+ hdi.mask:=HDI_FORMAT;
+ SendMessageW(header,HDM_GETITEM,qsopt.columnsort,tlparam(@hdi));
+ if (qsopt.flags and QSO_SORTASC)<>0 then
+ hdi.fmt:=hdi.fmt or HDF_SORTDOWN
+ else
+ hdi.fmt:=hdi.fmt or HDF_SORTUP;
+ SendMessageW(header,HDM_SETITEM,qsopt.columnsort,tlparam(@hdi));
+
+
TranslateDialogDefault(Dialog);
SnapToScreen(qsopt.grrect);
@@ -2402,10 +2058,12 @@ begin
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;
+ hAdd :=HookEvent(ME_DB_CONTACT_ADDED ,@OnContactAdded);
+ hDelete:=HookEvent(ME_DB_CONTACT_DELETED ,@OnContactDeleted);
+ hChange:=HookEvent(ME_CLIST_CONTACTICONCHANGED,@OnStatusChanged);
+// hAccount:=HookEvent(ME_PROTO_ACCLISTCHANGED ,@OnAccountChanged);
end;
WM_GETMINMAXINFO: begin
@@ -2431,7 +2089,7 @@ begin
WM_SYSCOMMAND: begin
if wParam=IDM_STAYONTOP then
begin
- if qsopt.stayontop then
+ if (qsopt.flags and QSO_STAYONTOP)<>0 then
begin
h:=MF_BYCOMMAND or MF_UNCHECKED;
w:=HWND_NOTOPMOST;
@@ -2443,7 +2101,7 @@ begin
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;
+ qsopt.flags:=qsopt.flags xor QSO_STAYONTOP;
exit;
end;
end;
@@ -2455,34 +2113,10 @@ begin
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;
+ begin
+ ShowContactMenu(Dialog,GetFocusedhContact,
+ GetLVSubItem(loword(lParam),hiword(lParam)));
+ end;
end;
end;
@@ -2520,11 +2154,11 @@ begin
end;
WM_COMMAND: begin
- if opened and (CallService(MS_CLIST_MENUPROCESSCOMMAND,
- MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU),
- GetFocusedhContact)<>0) then
+ if CallService(MS_CLIST_MENUPROCESSCOMMAND,
+ MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU),
+ GetFocusedhContact)<>0 then
begin
- if qsopt.closeafteraction then
+ if (qsopt.flags and QSO_AUTOCLOSE)<>0 then
CloseSrWindow;
exit;
end;
@@ -2547,16 +2181,24 @@ begin
BN_CLICKED: begin
case loword(wParam) of
IDC_CH_SHOWOFFLINE: begin
- qsopt.showoffline:=IsDlgButtonChecked(Dialog,IDC_CH_SHOWOFFLINE)<>BST_UNCHECKED;
- if qsopt.showoffline then
+ if IsDlgButtonChecked(Dialog,IDC_CH_SHOWOFFLINE)<>BST_UNCHECKED then
+ begin
+ qsopt.flags:=qsopt.flags or QSO_SHOWOFFLINE;
AdvFilter:=AdvFilter or flt_show_offline
+ end
else
+ begin
+ qsopt.flags:=qsopt.flags and not QSO_SHOWOFFLINE;
AdvFilter:=AdvFilter and not flt_show_offline;
+ end;
AdvancedFilter;
end;
IDC_CH_COLORIZE: begin
- qsopt.colorize:=IsDlgButtonChecked(Dialog,IDC_CH_COLORIZE)<>BST_UNCHECKED;
+ if IsDlgButtonChecked(Dialog,IDC_CH_COLORIZE)=BST_UNCHECKED then
+ qsopt.flags:=qsopt.flags and not QSO_COLORIZE
+ else
+ qsopt.flags:=qsopt.flags or QSO_COLORIZE;
RedrawWindow(grid,nil,0,RDW_INVALIDATE);
end;
@@ -2593,47 +2235,20 @@ begin
end;
end;
+//----- base QS window functions -----
+
function CloseSrWindow:boolean;
begin
- result:=true;
- if opened and (mainwnd<>0) then
+ if mainwnd<>0 then
begin
+ result:=true;
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);
+ FreeProtoList;
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;
+ result:=false;
end;
function BringToFront:integer;
@@ -2648,294 +2263,49 @@ begin
SetForegroundWindow(mainwnd);
end;
-procedure ChangeStatusPicture(row:integer; hContact:THANDLE;Pic:integer);
+function OpenSRWindow(apattern:PWideChar;flags:LPARAM):boolean;
var
- li:LV_ITEM;
+ i,j:integer;
begin
- row:=FindItem(row);
- if row>=0 then
+ result:=true;
+ if mainwnd<>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));
+ BringToFront;
+ exit;
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
+ j:=0;
+ for i:=0 to qsopt.numcolumns-1 do
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;
+ if (qsopt.columns[i].flags and COL_ON)<>0 then
+ inc(j);
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;
+ // no even one visible column
+ if j=0 then
+ exit;
-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
+ TTInstalled := ServiceExists(MS_TIPPER_SHOWTIP)<>0;
+ // too lazy to move pattern and flags to thread
+ if apattern<>nil then
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
+ if flags=0 then
+ StrDupW(pattern,apattern)
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;
+ AnsiToWide(PAnsiChar(apattern),pattern);
+ CharLowerW(pattern);
+ end
+ else if (qsopt.flags and QSO_SAVEPATTERN)<>0 then
+ pattern:=DBReadUnicode(0,qs_module,'pattern',nil)
+ else
+ pattern:=nil;
-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<qsopt.numcolumns))) then
+ CreateProtoList;
+ if PrepareToFill then
begin
- SendMessage(grid,WM_SETREDRAW,0,0);
- case code of
- wcUp,wcDown: begin
- // changing buffer data
- if code=wcUp then
- incr:=-1
- else
- incr:=1;
-
- // memory
- for i:=0 to HIGH(MainBuf) do
- begin
- coldata :=MainBuf[i,column];
- MainBuf[i,column ]:=MainBuf[i,column+incr];
- MainBuf[i,column+incr]:=coldata;
- end;
-
- // index
- col :=colorder[column];
- colorder[column ]:=colorder[column+incr];
- colorder[column+incr]:=col;
-
- // check needs for screen resort (columns are AFTER resort)
- if ((qsopt.columns[column ].flags and COL_ON)=COL_ON) and
- ((qsopt.columns[column+incr].flags and COL_ON)=COL_ON) then // both visible
- begin // need resort on screen
- SetColumnOrder;
- end;
- SendMessage(grid,WM_SETREDRAW,1,0);
- exit;
- end;
-
- wcHide: begin // hide column
- // screen
- SendMessage(grid,LVM_DELETECOLUMN,colorder[column],0);
- dec(tablecolumns);
- // index
- ShiftIndex(column,colorder);
- colorder[column]:=-1;
- end;
-
- wcDelete: begin // delete column
- // screen
- SendMessage(grid,LVM_DELETECOLUMN,colorder[column],0);
- dec(tablecolumns);
- // memory
- for i:=0 to HIGH(MainBuf) do
- begin
- mFreeMem(MainBuf[i,column].text);
- if column<qsopt.numcolumns then
- move(MainBuf[i,column+1],MainBuf[i,column],SizeOf(tQSRec));
- end;
- SetLength(MainBuf,Length(MainBuf),qsopt.numcolumns); //!!!!
- // index
- if column<qsopt.numcolumns then
- move(colorder[column+1],colorder[column],SizeOf(integer));
- SetLength(colorder,qsopt.numcolumns);
- end;
-
- wcShow: begin // show column
- // memory
- if (qsopt.columns[column].flags and COL_INIT)=0 then
- begin
- for i:=0 to HIGH(MainBuf) do // contacts
- begin
- LoadOneItem(FlagBuf[i].contact,column,FlagBuf[i].proto,MainBuf[i,column]);
- end;
- qsopt.columns[column].flags:=qsopt.columns[column].flags or COL_INIT;
- end;
- // screen
- with qsopt.columns[column] do // atm - to the end only
- addcolumn(grid,tablecolumns,width,TranslateW(title));
-
- // fill new column
- FillLVColumn(column,tablecolumns);
- // index
- colorder[column]:=tablecolumns;
- inc(tablecolumns);
-
- SetColumnOrder;
-{
- SetLength(lcol,tablecolumns);
- 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,tablecolumns,tlparam(@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);
+ ColorReload(0,0);
+ loadopt_wnd;
+ CreateDialogW(hInstance,PWideChar(IDD_MAIN),0,@QSMainWndProc);
end;
end;
-begin
end.