static char* CreateRTFHeader(SrmmWindowData*) { HDC hdc = GetDC(NULL); logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); ReleaseDC(NULL, hdc); CMStringA buffer; buffer.Append("{\\rtf1\\ansi\\deff0{\\fonttbl"); LOGFONT lf; for (int i = 0; LoadMsgDlgFont(i, &lf, NULL); i++) buffer.AppendFormat(FONT_FORMAT, i, lf.lfCharSet, lf.lfFaceName); buffer.Append("}{\\colortbl "); COLORREF colour; for (int i = 0; LoadMsgDlgFont(i, NULL, &colour); i++) buffer.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); if (GetSysColorBrush(COLOR_HOTLIGHT) == NULL) colour = RGB(0, 0, 255); else colour = GetSysColor(COLOR_HOTLIGHT); buffer.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); buffer.Append("}"); return buffer.Detach(); }
//mir_free() the return value static char* CreateRTFFromDbEvent(SrmmWindowData *dat, MCONTACT hContact, MEVENT hDbEvent, struct LogStreamData *streamData) { int showColon = 0; DBEVENTINFO dbei = { sizeof(dbei) }; dbei.cbBlob = db_event_getBlobSize(hDbEvent); if (dbei.cbBlob == -1) return NULL; dbei.pBlob = (PBYTE)mir_alloc(dbei.cbBlob); db_event_get(hDbEvent, &dbei); if (!DbEventIsShown(&dbei)) { mir_free(dbei.pBlob); return NULL; } if (!(dbei.flags & DBEF_SENT) && (dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei))) { db_event_markRead(hContact, hDbEvent); pcli->pfnRemoveEvent(hContact, hDbEvent); } else if (dbei.eventType == EVENTTYPE_JABBER_CHATSTATES || dbei.eventType == EVENTTYPE_JABBER_PRESENCE) { db_event_markRead(hContact, hDbEvent); } CMStringA buffer; if (!dat->bIsAutoRTL && !streamData->isEmpty) buffer.Append("\\par"); if (dbei.flags & DBEF_RTL) { buffer.Append("\\rtlpar"); dat->bIsAutoRTL = TRUE; } else buffer.Append("\\ltrpar"); streamData->isEmpty = 0; if (dat->bIsAutoRTL) { if (dbei.flags & DBEF_RTL) buffer.Append("\\ltrch\\rtlch"); else buffer.Append("\\rtlch\\ltrch"); } if (g_dat.flags & SMF_SHOWICONS) { int i = ((dbei.eventType == EVENTTYPE_MESSAGE) ? ((dbei.flags & DBEF_SENT) ? LOGICON_MSG_OUT : LOGICON_MSG_IN): LOGICON_MSG_NOTICE); buffer.Append("\\f0\\fs14"); buffer.Append(pLogIconBmpBits[i]); } if (g_dat.flags & SMF_SHOWTIME) { const TCHAR* szFormat; TCHAR str[64]; if (g_dat.flags & SMF_SHOWSECS) szFormat = g_dat.flags & SMF_SHOWDATE ? _T("d s") : _T("s"); else szFormat = g_dat.flags & SMF_SHOWDATE ? _T("d t") : _T("t"); TimeZone_PrintTimeStamp(NULL, dbei.timestamp, szFormat, str, _countof(str), 0); buffer.AppendFormat(" %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYTIME : MSGFONTID_YOURTIME)); AppendToBufferWithRTF(buffer, str); showColon = 1; } if (!(g_dat.flags & SMF_HIDENAMES) && dbei.eventType != EVENTTYPE_JABBER_CHATSTATES && dbei.eventType != EVENTTYPE_JABBER_PRESENCE) { TCHAR *szName; CONTACTINFO ci = { 0 }; if (dbei.flags & DBEF_SENT) { ci.cbSize = sizeof(ci); ci.szProto = dbei.szModule; ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) { // CNF_DISPLAY always returns a string type szName = ci.pszVal; } else // Shouldn't happen? szName = mir_tstrdup(TranslateT("Me")); } else szName = pcli->pfnGetContactDisplayName(hContact, 0); buffer.AppendFormat(" %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYNAME : MSGFONTID_YOURNAME)); AppendToBufferWithRTF(buffer, szName); showColon = 1; if (ci.pszVal) mir_free(ci.pszVal); } if (showColon) buffer.AppendFormat("%s :", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYCOLON : MSGFONTID_YOURCOLON)); TCHAR *msg, *szName; switch (dbei.eventType) { case EVENTTYPE_JABBER_CHATSTATES: case EVENTTYPE_JABBER_PRESENCE: if (dbei.flags & DBEF_SENT) { CONTACTINFO ci = { sizeof(ci) }; ci.hContact = NULL; ci.szProto = dbei.szModule; ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; // CNF_DISPLAY always returns a string type if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)& ci)) szName = NEWTSTR_ALLOCA(ci.pszVal); else szName = _T(""); mir_free(ci.pszVal); } else szName = pcli->pfnGetContactDisplayName(hContact, 0); buffer.AppendFormat(" %s ", SetToStyle(MSGFONTID_NOTICE)); AppendToBufferWithRTF(buffer, szName); AppendToBufferWithRTF(buffer, _T(" ")); msg = DbGetEventTextT(&dbei, CP_ACP); if (msg) { AppendToBufferWithRTF(buffer, msg); mir_free(msg); } break; case EVENTTYPE_FILE: { char* filename = (char*)dbei.pBlob + sizeof(DWORD); char* descr = filename + mir_strlen(filename) + 1; ptrT ptszFileName(DbGetEventStringT(&dbei, filename)); buffer.AppendFormat(" %s ", SetToStyle(MSGFONTID_NOTICE)); AppendToBufferWithRTF(buffer, (dbei.flags & DBEF_SENT) ? TranslateT("File sent") : TranslateT("File received")); buffer.Append(": "); AppendToBufferWithRTF(buffer, ptszFileName); if (*descr != 0) { ptrT ptszDescr(DbGetEventStringT(&dbei, descr)); buffer.Append(" ("); AppendToBufferWithRTF(buffer, ptszDescr); buffer.Append(")"); } } break; case EVENTTYPE_MESSAGE: default: msg = DbGetEventTextT(&dbei, CP_ACP); buffer.AppendFormat(" %s ", SetToStyle((dbei.eventType == EVENTTYPE_MESSAGE) ? ((dbei.flags & DBEF_SENT) ? MSGFONTID_MYMSG : MSGFONTID_YOURMSG) : MSGFONTID_NOTICE)); AppendToBufferWithRTF(buffer, msg); mir_free(msg); } if (dat->bIsAutoRTL) buffer.Append("\\par"); mir_free(dbei.pBlob); return buffer.Detach(); }
static char* Log_CreateRTF(LOGSTREAMDATA *streamData) { LOGINFO *lin = streamData->lin; MODULEINFO *mi = pci->MM_FindModule(streamData->si->pszModule); // ### RTF HEADER if (0 == mi->pszHeader) mi->pszHeader = Log_CreateRtfHeader(mi); char *header = mi->pszHeader; streamData->crCount = mi->nColorCount; CMStringA str; if (header) str.Append(header); // ### RTF BODY (one iteration per event that should be streamed in) while (lin) { // filter if ((streamData->si->iType != GCW_CHATROOM && streamData->si->iType != GCW_PRIVMESS) || !streamData->si->bFilterEnabled || (streamData->si->iLogFilterFlags & lin->iType) != 0) { if (lin->next != NULL) str.Append("\\par "); if (streamData->dat->dwFlags & MWF_DIVIDERWANTED || lin->dwFlags & MWF_DIVIDERWANTED) { static char szStyle_div[128] = "\0"; if (szStyle_div[0] == 0) mir_snprintf(szStyle_div, "\\f%u\\cf%u\\ul0\\b%d\\i%d\\fs%u", 17, 18, 0, 0, 5); lin->dwFlags |= MWF_DIVIDERWANTED; if (lin->prev || !streamData->bRedraw) str.AppendFormat("\\qc\\sl-1\\highlight%d %s ---------------------------------------------------------------------------------------\\par ", 18, szStyle_div); streamData->dat->dwFlags &= ~MWF_DIVIDERWANTED; } // create new line, and set font and color str.AppendFormat("\\ql\\sl0%s ", pci->Log_SetStyle(0)); str.AppendFormat("\\v~-+%d+-~\\v0 ", lin); // Insert icon if (g_Settings.bLogSymbols) // use symbols str.AppendFormat("%s %c", pci->Log_SetStyle(17), EventToSymbol(lin)); else if (g_Settings.dwIconFlags) { int iIndex = lin->bIsHighlighted ? ICON_HIGHLIGHT : EventToIcon(lin); str.Append("\\f0\\fs14"); str.AppendFormat(pci->pLogIconBmpBits[iIndex], (int)pci->logIconBmpSize[iIndex]); } if (g_Settings.bTimeStampEventColour) { // colored timestamps static char szStyle[256]; LOGFONT &F = pci->aFonts[0].lf; int iii; if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) { iii = lin->bIsHighlighted ? 16 : (lin->bIsMe ? 2 : 1); mir_snprintf(szStyle, "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\ul%d\\fs%u", iii + 1, F.lfWeight >= FW_BOLD ? 1 : 0, F.lfItalic, F.lfUnderline, 2 * abs(F.lfHeight) * 74 / pci->logPixelSY); str.Append(szStyle); } else { iii = lin->bIsHighlighted ? 16 : EventToIndex(lin); mir_snprintf(szStyle, "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\ul%d\\fs%u", iii + 1, F.lfWeight >= FW_BOLD ? 1 : 0, F.lfItalic, F.lfUnderline, 2 * abs(F.lfHeight) * 74 / pci->logPixelSY); str.Append(szStyle); } } else str.Append(pci->Log_SetStyle(0)); str.AppendChar(' '); // insert a TAB if necessary to put the timestamp in the right position if (g_Settings.dwIconFlags) str.Append("\\tab "); //insert timestamp if (g_Settings.bShowTime) { TCHAR szTimeStamp[30], szOldTimeStamp[30]; _tcsncpy_s(szTimeStamp, pci->MakeTimeStamp(g_Settings.pszTimeStamp, lin->time), _TRUNCATE); _tcsncpy_s(szOldTimeStamp, pci->MakeTimeStamp(g_Settings.pszTimeStamp, streamData->si->LastTime), _TRUNCATE); if (!g_Settings.bShowTimeIfChanged || streamData->si->LastTime == 0 || mir_tstrcmp(szTimeStamp, szOldTimeStamp)) { streamData->si->LastTime = lin->time; Log_AppendRTF(streamData, TRUE, str, _T("%s"), szTimeStamp); } str.Append("\\tab "); } // Insert the nick if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) { char pszIndicator[3] = "\0\0"; int crNickIndex = 0; if (g_Settings.bLogClassicIndicators || g_Settings.bColorizeNicksInLog) pszIndicator[0] = GetIndicator(streamData->si, lin->ptszNick, &crNickIndex); str.Append(pci->Log_SetStyle(lin->bIsMe ? 2 : 1)); str.AppendChar(' '); if (g_Settings.bLogClassicIndicators) str.Append(pszIndicator); CMString pszTemp(lin->bIsMe ? g_Settings.pszOutgoingNick : g_Settings.pszIncomingNick); pszTemp.Replace(_T("%n"), _T("%s")); if (!lin->bIsMe) { if (g_Settings.bClickableNicks) pszTemp.Replace(_T("%s"), _T("~~++#%s#++~~")); if (g_Settings.bColorizeNicksInLog && pszIndicator[0]) str.AppendFormat("\\cf%u ", OPTIONS_FONTCOUNT + streamData->crCount + crNickIndex); } Log_AppendRTF(streamData, TRUE, str, pszTemp, lin->ptszNick); str.AppendChar(' '); } // Insert the message str.Append(pci->Log_SetStyle(lin->bIsHighlighted ? 16 : EventToIndex(lin))); str.AppendChar(' '); streamData->lin = lin; AddEventToBuffer(str, streamData); } lin = lin->prev; } // ### RTF END if (streamData->bRedraw) str.Append("\\par}"); else str.Append("}"); return str.Detach(); }
INT_PTR CSkypeProto::GetEventText(WPARAM, LPARAM lParam) { DBEVENTGETTEXT *pEvent = (DBEVENTGETTEXT *)lParam; CMStringA szText; BOOL bUseBB = db_get_b(NULL, pEvent->dbei->szModule, "UseBBCodes", 1); switch (pEvent->dbei->eventType) { case SKYPE_DB_EVENT_TYPE_EDITED_MESSAGE: { JSONNode jMsg = JSONNode::parse((char*)pEvent->dbei->pBlob); if (jMsg) { JSONNode &jOriginalMsg = jMsg["original_message"]; szText.AppendFormat(bUseBB ? Translate("[b]Original message:[/b]\n%s\n") : Translate("Original message:\n%s\n"), mir_utf8decodeA(jOriginalMsg["text"].as_string().c_str())); JSONNode &jEdits = jMsg["edits"]; for (auto it = jEdits.begin(); it != jEdits.end(); ++it) { const JSONNode &jEdit = *it; time_t time = jEdit["time"].as_int(); char szTime[MAX_PATH]; strftime(szTime, sizeof(szTime), "%X %x", localtime(&time)); szText.AppendFormat(bUseBB ? Translate("[b]Edited at %s:[/b]\n%s\n") : Translate("Edited at %s:\n%s\n"), szTime, mir_utf8decodeA(jEdit["text"].as_string().c_str())); } } else { szText = INVALID_DATA; } break; } case SKYPE_DB_EVENT_TYPE_CALL_INFO: { HXML xml = xmlParseString(ptrT(mir_utf8decodeT((char*)pEvent->dbei->pBlob)), 0, _T("partlist")); if (xml != NULL) { ptrA type(mir_t2a(xmlGetAttrValue(xml, _T("type")))); bool bType = (!mir_strcmpi(type, "started")) ? 1 : 0; time_t callDuration = 0; for (int i = 0; i < xmlGetChildCount(xml); i++) { HXML xmlPart = xmlGetNthChild(xml, _T("part"), i); if (xmlPart != NULL) { HXML xmlDuration = xmlGetChildByPath(xmlPart, _T("duration"), 0); if (xmlDuration != NULL) { callDuration = _ttol(xmlGetText(xmlDuration)); xmlDestroyNode(xmlDuration); xmlDestroyNode(xmlPart); break; } xmlDestroyNode(xmlPart); } } if (bType) { szText = Translate("Call"); } else { if (callDuration == 0) { szText = Translate("Call missed"); } else { char szTime[100]; strftime(szTime, sizeof(szTime), "%X", gmtime(&callDuration)); szText.Format(Translate("Call ended (%s)"), szTime); } } xmlDestroyNode(xml); } else { szText = INVALID_DATA; } break; } case SKYPE_DB_EVENT_TYPE_FILETRANSFER_INFO: { HXML xml = xmlParseString(ptrT(mir_utf8decodeT((char*)pEvent->dbei->pBlob)), 0, _T("files")); if (xml != NULL) { for (int i = 0; i < xmlGetChildCount(xml); i++) { LONGLONG fileSize = 0; HXML xmlNode = xmlGetNthChild(xml, _T("file"), i); if (xmlNode != NULL) { fileSize = _ttol(xmlGetAttrValue(xmlNode, _T("size"))); char *fileName = _T2A(xmlGetText(xmlNode)); if (fileName != NULL) { szText.AppendFormat(Translate("File transfer:\n\tFile name: %s \n\tSize: %lld bytes \n"), fileName, fileSize); } xmlDestroyNode(xmlNode); } } xmlDestroyNode(xml); } else { szText = INVALID_DATA; } break; } case SKYPE_DB_EVENT_TYPE_MOJI: case SKYPE_DB_EVENT_TYPE_URIOBJ: { HXML xml = xmlParseString(ptrT(mir_utf8decodeT((char*)pEvent->dbei->pBlob)), 0, _T("URIObject")); if (xml != NULL) { szText.Append(_T2A(xmlGetText(xml))); HXML xmlA = xmlGetChildByPath(xml, _T("a"), 0); if (xmlA != NULL) { szText += _T2A(xmlGetAttrValue(xmlA, _T("href"))); xmlDestroyNode(xmlA); } xmlDestroyNode(xml); } else { szText = INVALID_DATA; } break; } case SKYPE_DB_EVENT_TYPE_INCOMING_CALL: { szText = Translate("Incoming call"); break; } case SKYPE_DB_EVENT_TYPE_UNKNOWN: { szText.Format(Translate("Unknown event, please send this text for developer: \"%s\""), mir_utf8decodeA((char*)pEvent->dbei->pBlob)); break; } default: { szText = ptrA(mir_utf8decodeA((char*)pEvent->dbei->pBlob)); } } switch(pEvent->datatype) { case DBVT_TCHAR: { return (INT_PTR)mir_a2t(szText); } case DBVT_ASCIIZ: { return (INT_PTR)szText.Detach(); } case DBVT_UTF8: { return (INT_PTR)mir_utf8encode(szText); } default: { return NULL; } } }