/* Miranda IM: the free IM client for Microsoft* Windows* Copyright 2000-2009 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 "..\..\core\commonheaders.h" #include "FontService.h" #define FontID_OLDSIZE (offsetof(FontID, backgroundGroup)) #define FontIDW_OLDSIZE (offsetof(FontIDW, backgroundGroup)) COLORREF GetColorFromDefault(COLORREF cl); void ConvertFontSettings(FontSettings* fs, FontSettingsW* fsw) { fsw->colour = fs->colour; fsw->size = fs->size; fsw->style = fs->style; fsw->charset = fs->charset; MultiByteToWideChar(code_page, 0, fs->szFace, -1, fsw->szFace, LF_FACESIZE); } bool ConvertFontID(FontID *fid, FontIDW* fidw) { if (fid->cbSize != sizeof(FontID) && fid->cbSize != FontID_OLDSIZE) return false; memset(fidw, 0, sizeof(FontIDW)); fidw->cbSize = sizeof(FontIDW); strcpy(fidw->dbSettingsGroup, fid->dbSettingsGroup); strcpy(fidw->prefix, fid->prefix); fidw->flags = fid->flags; fidw->order = fid->order; ConvertFontSettings(&fid->deffontsettings, &fidw->deffontsettings); MultiByteToWideChar(code_page, 0, fid->group, -1, fidw->group, 64); MultiByteToWideChar(code_page, 0, fid->name, -1, fidw->name, 64); if (fid->cbSize > FontID_OLDSIZE) { MultiByteToWideChar(code_page, 0, fid->backgroundGroup, -1, fidw->backgroundGroup, 64); MultiByteToWideChar(code_page, 0, fid->backgroundName, -1, fidw->backgroundName, 64); } return true; } bool ConvertColourID(ColourID *cid, ColourIDW* cidw) { if (cid->cbSize != sizeof(ColourID)) return false; cidw->cbSize = sizeof(ColourIDW); strcpy(cidw->dbSettingsGroup, cid->dbSettingsGroup); strcpy(cidw->setting, cid->setting); cidw->flags = cid->flags; cidw->defcolour = cid->defcolour; cidw->order = cid->order; MultiByteToWideChar(code_page, 0, cid->group, -1, cidw->group, 64); MultiByteToWideChar(code_page, 0, cid->name, -1, cidw->name, 64); return true; } bool ConvertEffectID(EffectID *eid, EffectIDW* eidw) { if (eid->cbSize != sizeof(EffectID)) return false; eidw->cbSize = sizeof(EffectIDW); strcpy(eidw->dbSettingsGroup, eid->dbSettingsGroup); strcpy(eidw->setting, eid->setting); eidw->flags = eid->flags; eidw->defeffect.effectIndex = eid->defeffect.effectIndex; eidw->defeffect.baseColour = eid->defeffect.baseColour; eidw->defeffect.secondaryColour = eid->defeffect.secondaryColour; eidw->order = eid->order; MultiByteToWideChar(code_page, 0, eid->group, -1, eidw->group, 64); MultiByteToWideChar(code_page, 0, eid->name, -1, eidw->name, 64); return true; } void ConvertLOGFONT(LOGFONTW *lfw, LOGFONTA *lfa) { lfa->lfHeight = lfw->lfHeight; lfa->lfWidth = lfw->lfWidth; lfa->lfEscapement = lfw->lfEscapement; lfa->lfOrientation = lfw->lfOrientation; lfa->lfWeight = lfw->lfWeight; lfa->lfItalic = lfw->lfItalic; lfa->lfUnderline = lfw->lfUnderline; lfa->lfStrikeOut = lfw->lfStrikeOut; lfa->lfCharSet = lfw->lfCharSet; lfa->lfOutPrecision = lfw->lfOutPrecision; lfa->lfClipPrecision = lfw->lfClipPrecision; lfa->lfQuality = lfw->lfQuality; lfa->lfPitchAndFamily = lfw->lfPitchAndFamily; WideCharToMultiByte(code_page, 0, lfw->lfFaceName, -1, lfa->lfFaceName, LF_FACESIZE, 0, 0); } static void GetDefaultFontSetting(LOGFONT* lf, COLORREF* colour) { SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), lf, FALSE); if (colour) *colour = GetSysColor(COLOR_WINDOWTEXT); lf->lfHeight = 10; HDC hdc = GetDC(0); lf->lfHeight = -MulDiv(lf->lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72); ReleaseDC(0, hdc); } int GetFontSettingFromDB(char *settings_group, char *prefix, LOGFONT* lf, COLORREF * colour, DWORD flags) { DBVARIANT dbv; char idstr[256]; BYTE style; int retval = 0; GetDefaultFontSetting(lf, colour); if (flags & FIDF_APPENDNAME) mir_snprintf(idstr, SIZEOF(idstr), "%sName", prefix); else mir_snprintf(idstr, SIZEOF(idstr), "%s", prefix); if ( !DBGetContactSettingTString(NULL, settings_group, idstr, &dbv)) { _tcscpy(lf->lfFaceName, dbv.ptszVal); DBFreeVariant(&dbv); } else retval = 1; if (colour) { mir_snprintf(idstr, SIZEOF(idstr), "%sCol", prefix); *colour = DBGetContactSettingDword(NULL, settings_group, idstr, *colour); } mir_snprintf(idstr, SIZEOF(idstr), "%sSize", prefix); lf->lfHeight = (char)DBGetContactSettingByte(NULL, settings_group, idstr, lf->lfHeight); //wsprintf(idstr, "%sFlags", prefix); //if (DBGetContactSettingDword(NULL, settings_group, idstr, 0) & FIDF_SAVEACTUALHEIGHT) { // HDC hdc = GetDC(0); // lf->lfHeight = -lf->lfHeight; // ReleaseDC(0, hdc); //} mir_snprintf(idstr, SIZEOF(idstr), "%sSty", prefix); style = (BYTE) DBGetContactSettingByte(NULL, settings_group, idstr, (lf->lfWeight == FW_NORMAL ? 0 : DBFONTF_BOLD) | (lf->lfItalic ? DBFONTF_ITALIC : 0) | (lf->lfUnderline ? DBFONTF_UNDERLINE : 0) | lf->lfStrikeOut ? DBFONTF_STRIKEOUT : 0); lf->lfWidth = lf->lfEscapement = lf->lfOrientation = 0; lf->lfWeight = style & DBFONTF_BOLD ? FW_BOLD : FW_NORMAL; lf->lfItalic = (style & DBFONTF_ITALIC) != 0; lf->lfUnderline = (style & DBFONTF_UNDERLINE) != 0; lf->lfStrikeOut = (style & DBFONTF_STRIKEOUT) != 0; mir_snprintf(idstr, SIZEOF(idstr), "%sSet", prefix); lf->lfCharSet = DBGetContactSettingByte(NULL, settings_group, idstr, lf->lfCharSet); lf->lfOutPrecision = OUT_DEFAULT_PRECIS; lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; lf->lfQuality = DEFAULT_QUALITY; lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; if (lf->lfHeight > 0) { HDC hdc = GetDC(0); if (flags & FIDF_SAVEPOINTSIZE) { lf->lfHeight = -MulDiv(lf->lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72); } else { // assume SAVEACTUALHEIGHT TEXTMETRIC tm; HFONT hFont = CreateFontIndirect(lf); HFONT hOldFont = (HFONT)SelectObject(hdc, hFont); GetTextMetrics(hdc, &tm); lf->lfHeight = -(lf->lfHeight - tm.tmInternalLeading); SelectObject(hdc, hOldFont); DeleteObject(hFont); } //lf->lfHeight = -MulDiv(lf->lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72); ReleaseDC(0, hdc); } return retval; } int CreateFromFontSettings(FontSettingsT* fs, LOGFONT* lf) { GetDefaultFontSetting(lf, 0); _tcscpy(lf->lfFaceName, fs->szFace); lf->lfWidth = lf->lfEscapement = lf->lfOrientation = 0; lf->lfWeight = fs->style & DBFONTF_BOLD ? FW_BOLD : FW_NORMAL; lf->lfItalic = (fs->style & DBFONTF_ITALIC) != 0; lf->lfUnderline = (fs->style & DBFONTF_UNDERLINE) != 0; lf->lfStrikeOut = (fs->style & DBFONTF_STRIKEOUT) != 0;; lf->lfCharSet = fs->charset; lf->lfOutPrecision = OUT_DEFAULT_PRECIS; lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; lf->lfQuality = DEFAULT_QUALITY; lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; lf->lfHeight = fs->size; return 0; } void UpdateFontSettings(FontIDW* font_id, FontSettingsT* fontsettings) { LOGFONT lf; COLORREF colour; if (GetFontSettingFromDB(font_id->dbSettingsGroup, font_id->prefix, &lf, &colour, font_id->flags) && (font_id->flags & FIDF_DEFAULTVALID)) { CreateFromFontSettings(&font_id->deffontsettings, &lf); colour = GetColorFromDefault(font_id->deffontsettings.colour); } fontsettings->style = (lf.lfWeight == FW_NORMAL ? 0 : DBFONTF_BOLD) | (lf.lfItalic ? DBFONTF_ITALIC : 0) | (lf.lfUnderline ? DBFONTF_UNDERLINE : 0) | (lf.lfStrikeOut ? DBFONTF_STRIKEOUT : 0); fontsettings->size = (char)lf.lfHeight; fontsettings->charset = lf.lfCharSet; fontsettings->colour = colour; _tcscpy(fontsettings->szFace, lf.lfFaceName); } static COLORREF sttMixColor(COLORREF cl1, COLORREF cl2, int q) { return RGB( (GetRValue(cl1) * q + GetRValue(cl2) * (255 - q)) / 255, (GetGValue(cl1) * q + GetGValue(cl2) * (255 - q)) / 255, (GetBValue(cl1) * q + GetBValue(cl2) * (255 - q)) / 255 ); } COLORREF GetColorFromDefault(COLORREF cl) { /* if (cl & 0x80000000) return GetSysColor(cl & 0x7fffffff); if (cl & 0x40000000) { switch (cl) { case MIRCOLOR_BTNHALF: return sttMixColor(GetSysColor(COLOR_BTNFACE), GetSysColor(COLOR_BTNTEXT), 128); case MIRCOLOR_WNDHALF: return sttMixColor(GetSysColor(COLOR_WINDOW), GetSysColor(COLOR_WINDOWTEXT), 128); case MIRCOLOR_SELHALF: return sttMixColor(GetSysColor(COLOR_HIGHLIGHT), GetSysColor(COLOR_HIGHLIGHTTEXT), 128); case MIRCOLOR_INBACK: return sttMixColor(GetSysColor(COLOR_WINDOW), RGB(0, 0, 255), 245); case MIRCOLOR_INTEXT: return GetSysColor(COLOR_WINDOWTEXT); case MIRCOLOR_INHALF: return sttMixColor(GetColorFromDefault(MIRCOLOR_INBACK), GetColorFromDefault(MIRCOLOR_INTEXT), 128); case MIRCOLOR_OUTBACK: return sttMixColor(GetSysColor(COLOR_WINDOW), RGB(0, 255, 0), 245); case MIRCOLOR_OUTTEXT: return GetSysColor(COLOR_WINDOWTEXT); case MIRCOLOR_OUTHALF: return sttMixColor(GetColorFromDefault(MIRCOLOR_OUTBACK), GetColorFromDefault(MIRCOLOR_OUTTEXT), 128); } } */ return cl; } ///////////////////////////////////////////////////////////////////////////////////////// // RegisterFont service static int sttRegisterFontWorker(FontIDW* font_id, int hLangpack) { if (font_id->cbSize != sizeof(FontIDW) && font_id->cbSize != FontIDW_OLDSIZE) return -1; for (int i = 0; i < font_id_list.getCount(); i++) { FontInternal& F = font_id_list[i]; if ( !lstrcmp(F.group, font_id->group) && !lstrcmp(F.name, font_id->name) && !(F.flags & FIDF_ALLOWREREGISTER)) return 1; } char idstr[256]; mir_snprintf(idstr, SIZEOF(idstr), "%sFlags", font_id->prefix); DBWriteContactSettingDword(0, font_id->dbSettingsGroup, idstr, font_id->flags); FontInternal* newItem = new FontInternal; memset(newItem, 0, sizeof(FontIDW)); memcpy(newItem, font_id, font_id->cbSize); if ( !lstrcmp(newItem->deffontsettings.szFace, _T("MS Shell Dlg"))) { LOGFONT lf; SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, FALSE); lstrcpyn(newItem->deffontsettings.szFace, lf.lfFaceName, SIZEOF(newItem->deffontsettings.szFace)); if ( !newItem->deffontsettings.size) newItem->deffontsettings.size = lf.lfHeight; } UpdateFontSettings(font_id, &newItem->value); font_id_list.insert(newItem); return 0; } INT_PTR RegisterFontW(WPARAM wParam, LPARAM lParam) { return sttRegisterFontWorker((FontIDW*)wParam, (int)lParam); } INT_PTR RegisterFont(WPARAM wParam, LPARAM lParam) { FontIDW temp; if ( !ConvertFontID((FontID*)wParam, &temp)) return -1; return sttRegisterFontWorker(&temp, (int)lParam); } ///////////////////////////////////////////////////////////////////////////////////////// // GetFont service static INT_PTR sttGetFontWorker(FontIDW* font_id, LOGFONT* lf) { COLORREF colour; for (int i = 0; i < font_id_list.getCount(); i++) { FontInternal& F = font_id_list[i]; if ( !_tcsncmp(F.name, font_id->name, SIZEOF(F.name)) && !_tcsncmp(F.group, font_id->group, SIZEOF(F.group))) { if (GetFontSettingFromDB(F.dbSettingsGroup, F.prefix, lf, &colour, F.flags) && (F.flags & FIDF_DEFAULTVALID)) { CreateFromFontSettings(&F.deffontsettings, lf); colour = GetColorFromDefault(F.deffontsettings.colour); } return colour; } } GetDefaultFontSetting(lf, &colour); return colour; } INT_PTR GetFontW(WPARAM wParam, LPARAM lParam) { return sttGetFontWorker((FontIDW*)wParam, (LOGFONT*)lParam); } INT_PTR GetFont(WPARAM wParam, LPARAM lParam) { FontIDW temp; if ( !ConvertFontID((FontID*)wParam, &temp)) return -1; LOGFONT lftemp; int ret = sttGetFontWorker(&temp, &lftemp); ConvertLOGFONT(&lftemp, (LOGFONTA*)lParam); return ret; } ///////////////////////////////////////////////////////////////////////////////////////// // RegisterColour service void UpdateColourSettings(ColourIDW* colour_id, COLORREF *colour) { *colour = (COLORREF)DBGetContactSettingDword(NULL, colour_id->dbSettingsGroup, colour_id->setting, GetColorFromDefault(colour_id->defcolour)); } static INT_PTR sttRegisterColourWorker(ColourIDW* colour_id, int hLangpack) { if (colour_id->cbSize != sizeof(ColourIDW)) return -1; for (int i = 0; i < colour_id_list.getCount(); i++) { ColourInternal& C = colour_id_list[i]; if ( !_tcscmp(C.group, colour_id->group) && !_tcscmp(C.name, colour_id->name)) return 1; } ColourInternal* newItem = new ColourInternal; memcpy(newItem, colour_id, sizeof(ColourIDW)); UpdateColourSettings(colour_id, &newItem->value); colour_id_list.insert(newItem); return 0; } INT_PTR RegisterColourW(WPARAM wParam, LPARAM lParam) { return sttRegisterColourWorker((ColourIDW*)wParam, (int)lParam); } INT_PTR RegisterColour(WPARAM wParam, LPARAM lParam) { ColourIDW temp; if ( !ConvertColourID((ColourID*)wParam, &temp)) return -1; return sttRegisterColourWorker(&temp, (int)lParam); } ///////////////////////////////////////////////////////////////////////////////////////// // GetColour service static INT_PTR sttGetColourWorker(ColourIDW* colour_id) { for (int i = 0; i < colour_id_list.getCount(); i++) { ColourInternal& C = colour_id_list[i]; if ( !_tcscmp(C.group, colour_id->group) && !_tcscmp(C.name, colour_id->name)) return DBGetContactSettingDword(NULL, C.dbSettingsGroup, C.setting, GetColorFromDefault(C.defcolour)); } return -1; } INT_PTR GetColourW(WPARAM wParam, LPARAM) { return sttGetColourWorker((ColourIDW*)wParam); } INT_PTR GetColour(WPARAM wParam, LPARAM) { ColourIDW temp; if ( !ConvertColourID((ColourID*)wParam, &temp)) return -1; return sttGetColourWorker(&temp); } ////////////////////////////////////////////////////////////////////////// // Effects void UpdateEffectSettings(EffectIDW* effect_id, FONTEFFECT* effectsettings) { char str[256]; mir_snprintf(str, SIZEOF(str), "%sEffect", effect_id->setting); effectsettings->effectIndex = DBGetContactSettingByte(NULL, effect_id->dbSettingsGroup, str, effect_id->defeffect.effectIndex); mir_snprintf(str, SIZEOF(str), "%sEffectCol1", effect_id->setting); effectsettings->baseColour = DBGetContactSettingDword(NULL, effect_id->dbSettingsGroup, str, effect_id->defeffect.baseColour); mir_snprintf(str, SIZEOF(str), "%sEffectCol2", effect_id->setting); effectsettings->secondaryColour = DBGetContactSettingDword(NULL, effect_id->dbSettingsGroup, str, effect_id->defeffect.secondaryColour); } ///////////////////////////////////////////////////////////////////////////////////////// // RegisterFont service static INT_PTR sttRegisterEffectWorker(EffectIDW* effect_id, int hLangpack) { if (effect_id->cbSize != sizeof(EffectIDW)) return -1; for (int i = 0; i < effect_id_list.getCount(); i++) { EffectInternal& E = effect_id_list[i]; if ( !_tcscmp(E.group, effect_id->group) && !_tcscmp(E.name, effect_id->name)) return 1; } EffectInternal* newItem = new EffectInternal; memcpy(newItem, effect_id, sizeof(EffectIDW)); UpdateEffectSettings(effect_id, &newItem->value); effect_id_list.insert(newItem); return 0; } INT_PTR RegisterEffectW(WPARAM wParam, LPARAM lParam) { return sttRegisterEffectWorker((EffectIDW*)wParam, (int)lParam); } INT_PTR RegisterEffect(WPARAM wParam, LPARAM lParam) { EffectIDW temp; if ( !ConvertEffectID((EffectID*)wParam, &temp)) return -1; return sttRegisterEffectWorker(&temp, (int)lParam); } ///////////////////////////////////////////////////////////////////////////////////////// // GetEffect service static INT_PTR sttGetEffectWorker(EffectIDW* effect_id, FONTEFFECT* effect) { for (int i = 0; i < effect_id_list.getCount(); i++) { EffectInternal& E = effect_id_list[i]; if ( !_tcsncmp(E.name, effect_id->name, SIZEOF(E.name)) && !_tcsncmp(E.group, effect_id->group, SIZEOF(E.group))) { FONTEFFECT temp; UpdateEffectSettings(effect_id, &temp); effect->effectIndex = temp.effectIndex; effect->baseColour = temp.baseColour; effect->secondaryColour = temp.secondaryColour; return TRUE; } } return FALSE; } INT_PTR GetEffectW(WPARAM wParam, LPARAM lParam) { return sttGetEffectWorker((EffectIDW*)wParam, (FONTEFFECT*)lParam); } INT_PTR GetEffect(WPARAM wParam, LPARAM lParam) { EffectIDW temp; if ( !ConvertEffectID((EffectID*)wParam, &temp)) return -1; return sttGetEffectWorker(&temp, (FONTEFFECT*)lParam); }