/* Miranda IM: the free IM client for Microsoft* Windows* Copyright 2000-2003 Miranda ICQ/IM project, all portions of this codebase are copyrighted to the people listed in contributors.txt. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "commonheaders.h" #include "m_clc.h" #include "clc.h" //loads of stuff that didn't really fit anywhere else int HitTest(HWND hwnd,struct ClcData *dat,int testx,int testy,struct ClcContact **contact,struct ClcGroup **group,DWORD *flags) { struct ClcContact *hitcontact; struct ClcGroup *hitgroup; int hit,indent,width,i,cxSmIcon; int checkboxWidth, subident,ic=0; SIZE textSize; HDC hdc; HFONT oldfont; RECT clRect; DWORD style=GetWindowLong(hwnd,GWL_STYLE); if(flags) *flags=0; GetClientRect(hwnd,&clRect); if(testx<0 || testy<0 || testy>=clRect.bottom || testx>=clRect.right) { if(flags) { if(testx<0) *flags|=CLCHT_TOLEFT; else if(testx>=clRect.right) *flags|=CLCHT_TORIGHT; if(testy<0) *flags|=CLCHT_ABOVE; else if(testy>=clRect.bottom) *flags|=CLCHT_BELOW; } return -1; } if(testxleftMargin) { if(flags) *flags|=CLCHT_INLEFTMARGIN|CLCHT_NOWHERE; return -1; } hit=GetRowByIndex(dat ,(testy+dat->yScroll)/dat->rowHeight,&hitcontact,&hitgroup); if(hit==-1) { if(flags) *flags|=CLCHT_NOWHERE|CLCHT_BELOWITEMS; return -1; } if(contact) *contact=hitcontact; if(group) *group=hitgroup; ///////// if (hitcontact->type==CLCIT_CONTACT && hitcontact->isSubcontact) subident=dat->rowHeight/2; else subident=0; for(indent=0;hitgroup->parent;indent++,hitgroup=hitgroup->parent); if(testxleftMargin+indent*dat->groupIndent+subident) { if(flags) *flags|=CLCHT_ONITEMINDENT; return hit; } checkboxWidth=0; if(style&CLS_CHECKBOXES && hitcontact->type==CLCIT_CONTACT) checkboxWidth=dat->checkboxSize+2; if(style&CLS_GROUPCHECKBOXES && hitcontact->type==CLCIT_GROUP) checkboxWidth=dat->checkboxSize+2; if(hitcontact->type==CLCIT_INFO && hitcontact->flags&CLCIIF_CHECKBOX) checkboxWidth=dat->checkboxSize+2; if(testxleftMargin+indent*dat->groupIndent+checkboxWidth+subident) { if(flags) *flags|=CLCHT_ONITEMCHECK; return hit; } if(testxleftMargin+indent*dat->groupIndent+checkboxWidth+dat->iconXSpace+subident) { if(flags) *flags|=CLCHT_ONITEMICON; return hit; } hdc=GetDC(hwnd); GetTextExtentPoint32(hdc,hitcontact->szText,lstrlen(hitcontact->szText),&textSize); width=textSize.cx; cxSmIcon=GetSystemMetrics(SM_CXSMICON); for(i=0;iextraColumnsCount;i++) { int x; if(hitcontact->iExtraImage[i]==0xFF) continue; if ((style&CLS_EX_MULTICOLUMNALIGNLEFT)) { x=(dat->leftMargin+indent*dat->groupIndent+checkboxWidth+dat->iconXSpace-2+width); x+=16; x=x+dat->extraColumnSpacing*(ic); if (i==dat->extraColumnsCount-1) {x=clRect.right-18;} }else { int ir; if (dat->MetaIgnoreEmptyExtra) { int j; ir = 0; for(j=i;jextraColumnsCount;j++) if(hitcontact->iExtraImage[j]!=0xFF) ir++; }else ir = dat->extraColumnsCount-i; x=clRect.right-dat->extraColumnSpacing*ir; } ic++; if(testx>=x && testxtype==CLCIT_GROUP) oldfont=SelectObject(hdc,dat->fontInfo[FONTID_GROUPS].hFont); else oldfont=SelectObject(hdc,dat->fontInfo[FONTID_CONTACTS].hFont); if (DBGetContactSettingByte(NULL,"CLC","HiLightMode",0)==1) { if(flags) *flags|=CLCHT_ONITEMLABEL; SelectObject(hdc,oldfont); ReleaseDC(hwnd,hdc); return hit; } GetTextExtentPoint32(hdc,hitcontact->szText,lstrlen(hitcontact->szText),&textSize); width=textSize.cx; if(hitcontact->type==CLCIT_GROUP) { char *szCounts; szCounts = pcli->pfnGetGroupCountsText(dat,hitcontact); if(szCounts[0]) { GetTextExtentPoint32A(hdc," ",1,&textSize); width+=textSize.cx; SelectObject(hdc,dat->fontInfo[FONTID_GROUPCOUNTS].hFont); GetTextExtentPoint32A(hdc,szCounts,lstrlenA(szCounts),&textSize); width+=textSize.cx; } } SelectObject(hdc,oldfont); ReleaseDC(hwnd,hdc); if(testxleftMargin+indent*dat->groupIndent+checkboxWidth+dat->iconXSpace+width+4+subident) { if(flags) *flags|=CLCHT_ONITEMLABEL; return hit; } if(flags) *flags|=CLCHT_NOWHERE; return -1; } void ScrollTo(HWND hwnd,struct ClcData *dat,int desty,int noSmooth) { DWORD startTick,nowTick; int oldy=dat->yScroll; RECT clRect,rcInvalidate; int maxy,previousy; if(dat->iHotTrack!=-1 && dat->yScroll != desty) { pcli->pfnInvalidateItem(hwnd,dat,dat->iHotTrack); dat->iHotTrack=-1; ReleaseCapture(); } GetClientRect(hwnd,&clRect); rcInvalidate=clRect; maxy=dat->rowHeight*GetGroupContentsCount(&dat->list,2)-clRect.bottom; if(desty>maxy) desty=maxy; if(desty<0) desty=0; if(abs(desty-dat->yScroll)<4) noSmooth=1; if (!noSmooth && dat->exStyle&CLS_EX_NOSMOOTHSCROLLING) noSmooth=1; previousy=dat->yScroll; if (!noSmooth) { startTick=GetTickCount(); for (;;) { nowTick=GetTickCount(); if(nowTick>=startTick+dat->scrollTime) break; dat->yScroll=oldy+(desty-oldy)*(int)(nowTick-startTick)/dat->scrollTime; if(dat->backgroundBmpUse&CLBF_SCROLL || dat->hBmpBackground==NULL) ScrollWindowEx(hwnd,0,previousy-dat->yScroll,NULL,NULL,NULL,NULL,SW_INVALIDATE); else InvalidateRect(hwnd,NULL,FALSE); previousy=dat->yScroll; SetScrollPos(hwnd,SB_VERT,dat->yScroll,TRUE); UpdateWindow(hwnd); } } dat->yScroll=desty; if(dat->backgroundBmpUse&CLBF_SCROLL || dat->hBmpBackground==NULL) ScrollWindowEx(hwnd,0,previousy-dat->yScroll,NULL,NULL,NULL,NULL,SW_INVALIDATE); else InvalidateRect(hwnd,NULL,FALSE); SetScrollPos(hwnd,SB_VERT,dat->yScroll,TRUE); } void RecalcScrollBar(HWND hwnd,struct ClcData *dat) { SCROLLINFO si={0}; RECT clRect; NMCLISTCONTROL nm; boolean sbar=FALSE; GetClientRect(hwnd,&clRect); si.cbSize=sizeof(si); si.fMask=SIF_ALL; si.nMin=0; si.nMax=dat->rowHeight*GetGroupContentsCount(&dat->list,2)-1; si.nPage=clRect.bottom; si.nPos=dat->yScroll; nm.hdr.code=CLN_LISTSIZECHANGE; nm.hdr.hwndFrom=hwnd; nm.hdr.idFrom=GetDlgCtrlID(hwnd); nm.pt.y=si.nMax; SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm); GetClientRect(hwnd,&clRect); si.cbSize=sizeof(si); si.fMask=SIF_ALL; si.nMin=0; si.nMax=dat->rowHeight*GetGroupContentsCount(&dat->list,2)-1; si.nPage=clRect.bottom; si.nPos=dat->yScroll; sbar=(dat->noVScrollbar==1||(int)si.nPage>si.nMax); ShowScrollBar(hwnd,SB_VERT,sbar? FALSE : TRUE); if (!sbar) { if ( GetWindowLong(hwnd,GWL_STYLE)&CLS_CONTACTLIST ) { if ( dat->noVScrollbar==0 ) SetScrollInfo(hwnd,SB_VERT,&si,TRUE); else SetScrollInfo(hwnd,SB_VERT,&si,FALSE); } else SetScrollInfo(hwnd,SB_VERT,&si,TRUE); } ScrollTo(hwnd,dat,dat->yScroll,1); } void CalcEipPosition( struct ClcData *dat, struct ClcContact *contact, struct ClcGroup *group, POINT *result) { int indent; for (indent = 0; group->parent; indent++, group = group->parent); result->x = indent * dat->groupIndent + dat->iconXSpace - 2; result->y = dat->selection * dat->rowHeight - dat->yScroll; if (contact->type == CLCIT_CONTACT && contact->isSubcontact) result->x += dat->rowHeight/2; } void GetDefaultFontSetting(int i,LOGFONT *lf,COLORREF *colour) { SystemParametersInfo(SPI_GETICONTITLELOGFONT,sizeof(LOGFONT),lf,FALSE); *colour=GetSysColor(COLOR_WINDOWTEXT); switch(i) { case FONTID_GROUPS: lf->lfWeight=FW_BOLD; break; case FONTID_GROUPCOUNTS: lf->lfHeight=(int)(lf->lfHeight*.75); *colour=GetSysColor(COLOR_3DSHADOW); break; case FONTID_OFFINVIS: case FONTID_INVIS: lf->lfItalic=!lf->lfItalic; break; case FONTID_DIVIDERS: lf->lfHeight=(int)(lf->lfHeight*.75); break; case FONTID_NOTONLIST: *colour=GetSysColor(COLOR_3DSHADOW); break; } } extern void ( *saveLoadClcOptions )(HWND hwnd,struct ClcData *dat); void LoadClcOptions(HWND hwnd,struct ClcData *dat) { int i; dat->style=GetWindowLong(hwnd,GWL_STYLE); dat->MetaIgnoreEmptyExtra=DBGetContactSettingByte(NULL,"CLC","MetaIgnoreEmptyExtra",1); saveLoadClcOptions( hwnd, dat ); for (i = 0; i <= FONTID_MAX; i++) if (dat->fontInfo[i].fontHeight > dat->rowHeight) dat->rowHeight = dat->fontInfo[i].fontHeight; }