static int Log_AppendRTF(LOGSTREAMDATA* streamData, BOOL simpleMode, char **buffer, int *cbBufferEnd, int *cbBufferAlloced, const TCHAR *fmt, ...) { va_list va; int lineLen, textCharsCount=0; TCHAR* line = (TCHAR*)alloca(8001 * sizeof(TCHAR)); char* d; va_start(va, fmt); lineLen = _vsntprintf( line, 8000, fmt, va); if (lineLen < 0) lineLen = 8000; line[lineLen] = 0; va_end(va); lineLen = lineLen*20 + 8; if (*cbBufferEnd + lineLen > *cbBufferAlloced) { cbBufferAlloced[0] += (lineLen + 1024 - lineLen % 1024); *buffer = (char *) mir_realloc(*buffer, *cbBufferAlloced); } d = *buffer + *cbBufferEnd; for (; *line; line++, textCharsCount++) { if (*line == '\r' && line[1] == '\n') { CopyMemory(d, "\\par ", 5); line++; d += 5; } else if (*line == '\n') { CopyMemory(d, "\\line ", 6); d += 6; } else if (*line == '%' && !simpleMode ) { char szTemp[200]; szTemp[0] = '\0'; switch ( *++line ) { case '\0': case '%': *d++ = '%'; break; case 'c': case 'f': if (g_Settings.StripFormat || streamData->bStripFormat) line += 2; else if ( line[1] != '\0' && line[2] != '\0') { TCHAR szTemp3[3], c = *line; int col; szTemp3[0] = line[1]; szTemp3[1] = line[2]; szTemp3[2] = '\0'; line += 2; col = _ttoi(szTemp3); col += (OPTIONS_FONTCOUNT + 1); mir_snprintf(szTemp, SIZEOF(szTemp), ( c == 'c' ) ? "\\cf%u " : "\\highlight%u ", col); } break; case 'C': case 'F': if ( !g_Settings.StripFormat && !streamData->bStripFormat) { int j = streamData->lin->bIsHighlighted ? 16 : EventToIndex(streamData->lin); if ( *line == 'C' ) mir_snprintf(szTemp, SIZEOF(szTemp), "\\cf%u ", j+1); else mir_snprintf(szTemp, SIZEOF(szTemp), "\\highlight0 "); } break; case 'b': case 'u': case 'i': if ( !streamData->bStripFormat ) mir_snprintf(szTemp, SIZEOF(szTemp), (*line == 'u') ? "\\%cl " : "\\%c ", *line ); break; case 'B': case 'U': case 'I': if ( !streamData->bStripFormat ) { mir_snprintf( szTemp, SIZEOF(szTemp), (*line == 'U') ? "\\%cl0 " : "\\%c0 ", *line ); CharLowerA( szTemp ); } break; case 'r': if ( !streamData->bStripFormat ) { int index = EventToIndex(streamData->lin); mir_snprintf(szTemp, SIZEOF(szTemp), "%s ", Log_SetStyle(index, index)); } break; } if ( szTemp[0] ) { int iLen = lstrlenA(szTemp); memcpy( d, szTemp, iLen ); d += iLen; } } else if (*line == '\t' && !streamData->bStripFormat) { CopyMemory(d, "\\tab ", 5); d += 5; } else if ((*line == '\\' || *line == '{' || *line == '}') && !streamData->bStripFormat) { *d++ = '\\'; *d++ = (char) *line; } else if (*line > 0 && *line < 128) { *d++ = (char) *line; } #if defined( _UNICODE ) else d += sprintf(d, "\\u%u ?", (WORD)*line); #else else d += sprintf(d, "\\'%02x", (BYTE)*line); #endif }
char* Log_CreateRTF(LOGSTREAMDATA *streamData) { MODULEINFO *mi = ci.MM_FindModule(streamData->si->pszModule); // guesstimate amount of memory for the RTF size_t bufferEnd = 0, bufferAlloced = streamData->bRedraw ? 1024 * (streamData->si->iEventCount + 2) : 2048; char *buffer = (char *)mir_alloc(bufferAlloced); buffer[0] = '\0'; // ### RTF HEADER char *header = mi->pszHeader; if (header) Log_Append(buffer, bufferEnd, bufferAlloced, header); // ### RTF BODY (one iteration per event that should be streamed in) for (LOGINFO *lin = streamData->lin; lin; lin = lin->prev) { // filter if (streamData->si->iType == GCW_CHATROOM || streamData->si->iType == GCW_PRIVMESS) if (streamData->si->bFilterEnabled && (streamData->si->iLogFilterFlags & lin->iType) == 0) continue; // create new line, and set font and color if (lin->next != NULL) Log_Append(buffer, bufferEnd, bufferAlloced, "\\par "); Log_Append(buffer, bufferEnd, bufferAlloced, "%s ", Log_SetStyle(0)); // Insert icon if ((lin->iType & g_Settings->dwIconFlags) || lin->bIsHighlighted && (g_Settings->dwIconFlags & GC_EVENT_HIGHLIGHT)) { int iIndex = (lin->bIsHighlighted && g_Settings->dwIconFlags & GC_EVENT_HIGHLIGHT) ? ICON_HIGHLIGHT : EventToIcon(lin); Log_Append(buffer, bufferEnd, bufferAlloced, "\\f0\\fs14"); while (bufferAlloced - bufferEnd < logIconBmpSize[0]) bufferAlloced += 4096; buffer = (char *)mir_realloc(buffer, bufferAlloced); memcpy(buffer + bufferEnd, pLogIconBmpBits[iIndex], logIconBmpSize[iIndex]); bufferEnd += logIconBmpSize[iIndex]; } if (g_Settings->bTimeStampEventColour) { LOGFONT &lf = ci.aFonts[0].lf; // colored timestamps static char szStyle[256]; if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) { int iii = lin->bIsHighlighted ? 16 : (lin->bIsMe ? 2 : 1); mir_snprintf(szStyle, _countof(szStyle), "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\fs%u", iii + 1, lf.lfWeight >= FW_BOLD ? 1 : 0, lf.lfItalic, 2 * abs(lf.lfHeight) * 74 / ci.logPixelSY); Log_Append(buffer, bufferEnd, bufferAlloced, "%s ", szStyle); } else { int iii = lin->bIsHighlighted ? 16 : EventToIndex(lin); mir_snprintf(szStyle, _countof(szStyle), "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\fs%u", iii + 1, lf.lfWeight >= FW_BOLD ? 1 : 0, lf.lfItalic, 2 * abs(lf.lfHeight) * 74 / ci.logPixelSY); Log_Append(buffer, bufferEnd, bufferAlloced, "%s ", szStyle); } } else Log_Append(buffer, bufferEnd, bufferAlloced, "%s ", Log_SetStyle(0)); if (g_Settings->dwIconFlags) Log_Append(buffer, bufferEnd, bufferAlloced, "\\tab "); //insert timestamp if (g_Settings->bShowTime) { TCHAR szTimeStamp[30], szOldTimeStamp[30]; mir_tstrncpy(szTimeStamp, MakeTimeStamp(g_Settings->pszTimeStamp, lin->time), 30); mir_tstrncpy(szOldTimeStamp, MakeTimeStamp(g_Settings->pszTimeStamp, streamData->si->LastTime), 30); if (!g_Settings->bShowTimeIfChanged || streamData->si->LastTime == 0 || mir_tstrcmp(szTimeStamp, szOldTimeStamp)) { streamData->si->LastTime = lin->time; Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, _T("%s"), szTimeStamp); } Log_Append(buffer, bufferEnd, bufferAlloced, "\\tab "); } // Insert the nick if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) { TCHAR pszTemp[300], *p1; Log_Append(buffer, bufferEnd, bufferAlloced, "%s ", Log_SetStyle(lin->bIsMe ? 2 : 1)); mir_tstrncpy(pszTemp, lin->bIsMe ? g_Settings->pszOutgoingNick : g_Settings->pszIncomingNick, 299); p1 = _tcsstr(pszTemp, _T("%n")); if (p1) p1[1] = 's'; Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, pszTemp, lin->ptszNick); Log_Append(buffer, bufferEnd, bufferAlloced, " "); } // Insert the message Log_Append(buffer, bufferEnd, bufferAlloced, "%s ", Log_SetStyle(lin->bIsHighlighted ? 16 : EventToIndex(lin))); streamData->lin = lin; AddEventToBuffer(buffer, bufferEnd, bufferAlloced, streamData); } // ### RTF END if (streamData->bRedraw) Log_Append(buffer, bufferEnd, bufferAlloced, "\\par}"); else Log_Append(buffer, bufferEnd, bufferAlloced, "}"); return buffer; }