summaryrefslogtreecommitdiff
path: root/plugins/HistoryPlusPlus/hpp_itemprocess.pas
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/HistoryPlusPlus/hpp_itemprocess.pas')
-rw-r--r--plugins/HistoryPlusPlus/hpp_itemprocess.pas558
1 files changed, 558 insertions, 0 deletions
diff --git a/plugins/HistoryPlusPlus/hpp_itemprocess.pas b/plugins/HistoryPlusPlus/hpp_itemprocess.pas
new file mode 100644
index 0000000000..392aa195b5
--- /dev/null
+++ b/plugins/HistoryPlusPlus/hpp_itemprocess.pas
@@ -0,0 +1,558 @@
+(*
+ History++ plugin for Miranda IM: the free IM client for Microsoft* Windows*
+
+ Copyright (C) 2006-2009 theMIROn, 2003-2006 Art Fedorov.
+ History+ parts (C) 2001 Christian Kastner
+
+ 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
+*)
+
+{-----------------------------------------------------------------------------
+ hpp_itemprocess (historypp project)
+
+ Version: 1.5
+ Created: 05.08.2004
+ Author: Oxygen
+
+ [ Description ]
+
+ Module for people to help get aquanted with ME_HPP_RICHEDIT_ITEMPROCESS
+ Has samples for SmileyAdd, TextFormat, Math Module and new procedure
+ called SeparateDialogs. It makes message black if previous was hour ago,
+ kinda of conversation separation
+
+ [ History ]
+
+ 1.5 (05.08.2004)
+ First version
+
+ [ Modifications ]
+ none
+
+ [ Known Issues ]
+ none
+
+ Contributors: theMIROn, Art Fedorov
+-----------------------------------------------------------------------------}
+
+{.$DEFINE USE_URL_BBCODE}
+
+unit hpp_itemprocess;
+
+interface
+
+uses
+ Windows;
+
+var
+ rtf_ctable_text: AnsiString;
+
+function DoSupportBBCodesHTML(S: AnsiString): AnsiString;
+function DoSupportBBCodesRTF(S: AnsiString; StartColor: integer; doColorBBCodes: boolean): AnsiString;
+function DoStripBBCodes(S: String): String;
+
+function DoSupportSmileys(awParam:WPARAM; alParam: LPARAM): Integer;
+function DoSupportMathModule(awParam:WPARAM; alParam: LPARAM): Integer;
+function DoSupportAvatarHistory(awParam:WPARAM; alParam: LPARAM): Integer;
+
+implementation
+
+uses
+ Messages,
+ SysUtils, StrUtils,
+ m_api,
+ hpp_global, hpp_richedit, hpp_events{, RichEdit -- used for CHARRANGE and EM_EXTSETSEL};
+
+{$include inc\m_mathmodule.inc}
+
+const
+ EM_EXSETSEL = WM_USER + 55; // from RichEdit
+
+type
+
+ TRTFColorTable = record
+ sz: PAnsiChar;
+ col: COLORREF;
+ end;
+
+ TBBCodeClass = (bbStart,bbEnd);
+ TBBCodeType = (bbSimple, bbColor, bbSize, bbUrl, bbImage);
+
+ TBBCodeString = record
+ ansi: PAnsiChar;
+ wide: String;
+ end;
+
+ TBBCodeInfo = record
+ prefix: TBBCodeString;
+ suffix: TBBCodeString;
+ bbtype: TBBCodeType;
+ rtf: PAnsiChar;
+ html: PAnsiChar;
+ minRE: Integer;
+ end;
+
+const
+ rtf_ctable: array[0..7] of TRTFColorTable = (
+ // BBGGRR
+ (sz:'black'; col:$000000),
+ (sz:'blue'; col:$FF0000),
+ (sz:'green'; col:$00FF00),
+ (sz:'red'; col:$0000FF),
+ (sz:'magenta';col:$FF00FF),
+ (sz:'cyan'; col:$FFFF00),
+ (sz:'yellow'; col:$00FFFF),
+ (sz:'white'; col:$FFFFFF));
+
+const
+ bbCodesCount = {$IFDEF USE_URL_BBCODE}7{$ELSE}6{$ENDIF};
+
+var
+ bbCodes: array[0..bbCodesCount,bbStart..bbEnd] of TBBCodeInfo = (
+ ((prefix:(ansi:'[b]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'{\b '; html:'<b>'; minRE: 10),
+ (prefix:(ansi:'[/b]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}'; html:'</b>')),
+ ((prefix:(ansi:'[i]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'{\i '; html:'<i>'; minRE: 10),
+ (prefix:(ansi:'[/i]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}'; html:'</i>')),
+ ((prefix:(ansi:'[u]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'{\ul '; html:'<u>'; minRE: 10),
+ (prefix:(ansi:'[/u]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}'; html:'</u>')),
+ ((prefix:(ansi:'[s]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'{\strike '; html:'<s>'; minRE: 10),
+ (prefix:(ansi:'[/s]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}'; html:'</s>')),
+ ((prefix:(ansi:'[color='); suffix:(ansi:']'); bbtype:bbColor; rtf:'{\cf%u '; html:'<font style="color:%s">'; minRE: 10),
+ (prefix:(ansi:'[/color]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}'; html:'</font>')),
+ {$IFDEF USE_URL_BBCODE}
+ ((prefix:(ansi:'[url='); suffix:(ansi:']'); bbtype:bbUrl; rtf:'{\field{\*\fldinst{HYPERLINK ":%s"}}{\fldrslt{\ul\cf%u'; html:'<a href="%s">'; minRE: 41),
+ (prefix:(ansi:'[/url]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}}}'; html:'</a>')),
+ {$ENDIF}
+ ((prefix:(ansi:'[size='); suffix:(ansi:']'); bbtype:bbSize; rtf:'{\fs%u '; html:'<font style="font-size:%spt">'; minRE: 10),
+ (prefix:(ansi:'[/size]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}'; html:'</font>')),
+ ((prefix:(ansi:'[img]'); suffix:(ansi:nil); bbtype:bbImage; rtf:'[{\revised\ul\cf%u '; html:'['; minRE: 20),
+ (prefix:(ansi:'[/img]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}]'; html:']'))
+ );
+
+const
+ MAX_FMTBUF = 4095;
+
+var
+ i: integer;
+ TextBuffer: THppBuffer;
+
+function GetColorRTF(code: AnsiString; colcount: integer): integer;
+var
+ i: integer;
+begin
+ Result := 0;
+ if colcount >= 0 then
+ for i := 0 to High(rtf_ctable) do
+ if rtf_ctable[i].sz = code then
+ begin
+ Result := colcount + i;
+ break;
+ end;
+end;
+
+function StrReplace(strStart, str, strEnd: PAnsiChar; var strTrail: PAnsiChar): PAnsiChar;
+var
+ len,delta: integer;
+ tmpStartPos,tmpEndPos,tmpTrailPos: Integer;
+ tmpStart,tmpEnd,tmpTrail: PAnsiChar;
+begin
+ if str = nil then
+ len := 0
+ else
+ len := StrLen(str);
+ delta := len - (strTrail - strStart);
+ tmpStartPos := strStart - TextBuffer.Buffer;
+ tmpTrailPos := strTrail - TextBuffer.Buffer;
+ tmpEndPos := strEnd - TextBuffer.Buffer;
+ TextBuffer.Reallocate(tmpEndPos + delta + 1);
+ tmpStart := PAnsiChar(TextBuffer.Buffer) + tmpStartPos;
+ tmpTrail := PAnsiChar(TextBuffer.Buffer) + tmpTrailPos;
+ tmpEnd := PAnsiChar(TextBuffer.Buffer) + tmpEndPos;
+ strTrail := tmpTrail + delta;
+ StrMove(strTrail, tmpTrail, tmpEnd - tmpTrail + 1);
+ if len > 0 then
+ StrMove(tmpStart, str, len);
+ Result := tmpEnd + delta;
+end;
+
+function StrAppend(str, strEnd: PAnsiChar): PAnsiChar;
+var
+ len: integer;
+ tmpEndPos: integer;
+ tmpEnd: PAnsiChar;
+begin
+ if str = nil then
+ begin
+ Result := strEnd;
+ exit;
+ end;
+ len := StrLen(str);
+ tmpEndPos := strEnd - TextBuffer.Buffer;
+ TextBuffer.Reallocate(tmpEndPos + len + 1);
+ tmpEnd := PAnsiChar(TextBuffer.Buffer) + tmpEndPos;
+ StrMove(tmpEnd, str, len + 1);
+ Result := tmpEnd + len;
+end;
+
+function StrSearch(str,prefix,suffix: PAnsiChar; var strStart,strEnd,strCode: PAnsiChar; var lenCode: integer): Boolean;
+begin
+ Result := false;
+ strStart := StrPos(str, prefix);
+ if strStart = nil then
+ exit;
+ strCode := strStart + StrLen(prefix);
+ if suffix = nil then
+ begin
+ lenCode := 0;
+ strEnd := strCode
+ end
+ else
+ begin
+ strEnd := StrPos(strCode, suffix);
+ if strEnd = nil then
+ exit;
+ lenCode := strEnd - strCode;
+ strEnd := strEnd + StrLen(suffix);
+ end;
+ Result := true;
+end;
+
+(* commented out fo future use
+function ParseLinksInRTF(S: AnsiString): AnsiString;
+const
+ urlStopChars = [' ','{','}','\','[',']'];
+ url41fmt = '{\field{\*\fldinst{HYPERLINK "%s"}}{\fldrslt{{\v #}\ul\cf1 %0:s}}}';
+var
+ bufPos,bufEnd: PAnsiChar;
+ urlStart,urlEnd: PAnsiChar;
+ newCode: PAnsiChar;
+ fmt_buffer: array[0..MAX_FMTBUF] of AnsiChar;
+ code: AnsiString;
+begin
+ ShrinkTextBuffer;
+ AllocateTextBuffer(Length(S)+1);
+ bufEnd := StrECopy(buffer,PAnsiChar(S));
+ bufPos := StrPos(buffer,'://');
+ while Assigned(bufPos) do begin
+ urlStart := bufPos;
+ urlEnd := bufPos+3;
+ while urlStart > buffer do begin
+ Dec(urlStart);
+ if urlStart[0] in urlStopChars then begin
+ Inc(urlStart);
+ break;
+ end;
+ end;
+ while urlEnd < bufEnd do begin
+ Inc(UrlEnd);
+ if urlEnd[0] in urlStopChars then break;
+ end;
+ if (urlStart<bufPos) and (urlEnd>bufPos+3) then begin
+ SetString(code,urlStart,urlEnd-urlStart);
+ newCode := StrLFmt(fmt_buffer,MAX_FMTBUF,url41fmt,[code]);
+ bufEnd := StrReplace(urlStart,newCode,bufEnd,urlEnd);
+ bufPos := urlEnd;
+ end;
+ bufPos := StrPos(bufPos,'://');
+ end;
+ SetString(Result,buffer,bufEnd-buffer);
+end;
+*)
+
+function DoSupportBBCodesRTF(S: AnsiString; StartColor: integer; doColorBBCodes: boolean): AnsiString;
+var
+ bufPos,bufEnd: PAnsiChar;
+ strStart,strTrail: PAnsiChar;
+ strCode,newCode: PAnsiChar;
+ i,n,lenCode: Integer;
+ sfound,efound: Boolean;
+ fmt_buffer: array[0..MAX_FMTBUF] of AnsiChar;
+ code: AnsiString;
+begin
+ TextBuffer.Lock;
+ TextBuffer.Allocate(Length(S)+1);
+ bufEnd := StrECopy(TextBuffer.Buffer,PAnsiChar(S));
+ for i := 0 to High(bbCodes) do
+ begin
+ if hppRichEditVersion < bbCodes[i, bbStart].minRE then
+ continue;
+ bufPos := TextBuffer.Buffer;
+ repeat
+ newCode := nil;
+ sfound := StrSearch(TextBuffer.Buffer, bbCodes[i, bbStart].prefix.ansi,
+ bbCodes[i, bbStart].suffix.ansi, strStart, strTrail, strCode, lenCode);
+ if sfound then
+ begin
+ case bbCodes[i, bbStart].bbtype of
+ bbSimple:
+ newCode := bbCodes[i, bbStart].rtf;
+ bbColor:
+ begin
+ if doColorBBCodes then
+ begin
+ SetString(code, strCode, lenCode);
+ n := GetColorRTF(code, StartColor);
+ newCode := StrLFmt(fmt_buffer, MAX_FMTBUF, bbCodes[i, bbStart].rtf, [n]);
+ end;
+ end;
+ bbSize:
+ begin
+ SetString(code, strCode, lenCode);
+ if TryStrToInt(String(code), n) then
+ newCode := StrLFmt(fmt_buffer, MAX_FMTBUF, bbCodes[i, bbStart].rtf, [n shl 1]);
+ end;
+{$IFDEF USE_URL_BBCODE}
+ bbUrl:
+ begin
+ SetString(code, strCode, lenCode);
+ if doColorBBCodes then
+ n := 2
+ else // link color
+ n := 0;
+ newCode := StrLFmt(fmt_buffer, MAX_FMTBUF, bbCodes[i, bbStart].rtf, [PAnsiChar(code), n]);
+ end;
+{$ENDIF}
+ bbImage:
+ begin
+ if doColorBBCodes then
+ n := 2
+ else // link color
+ n := 0;
+ newCode := StrLFmt(fmt_buffer, MAX_FMTBUF, bbCodes[i, bbStart].rtf, [n]);
+ end;
+ end;
+ bufEnd := StrReplace(strStart, newCode, bufEnd, strTrail);
+ bufPos := strTrail;
+ end;
+ repeat
+ efound := StrSearch(bufPos, bbCodes[i, bbEnd].prefix.ansi,
+ bbCodes[i, bbEnd].suffix.ansi, strStart, strTrail, strCode, lenCode);
+ if sfound and (newCode <> nil) then
+ strCode := bbCodes[i, bbEnd].rtf
+ else
+ strCode := nil;
+ if efound then
+ begin
+ bufEnd := StrReplace(strStart, strCode, bufEnd, strTrail);
+ bufPos := strTrail;
+ end
+ else
+ bufEnd := StrAppend(strCode, bufEnd);
+ until sfound or not efound;
+ until not sfound;
+ end;
+ SetString(Result, PAnsiChar(TextBuffer.Buffer), bufEnd - TextBuffer.Buffer);
+ TextBuffer.Unlock;
+end;
+
+function DoSupportBBCodesHTML(S: AnsiString): AnsiString;
+var
+ bufPos,bufEnd: PAnsiChar;
+ strStart,strTrail,strCode: PAnsiChar;
+ i,lenCode: Integer;
+ sfound,efound: Boolean;
+ fmt_buffer: array[0..MAX_FMTBUF] of AnsiChar;
+ code: AnsiString;
+begin
+ TextBuffer.Lock;
+ TextBuffer.Allocate(Length(S) + 1);
+ bufEnd := StrECopy(TextBuffer.Buffer, PAnsiChar(S));
+ for i := 0 to High(bbCodes) do
+ begin
+ bufPos := TextBuffer.Buffer;
+ repeat
+ sfound := StrSearch(TextBuffer.Buffer, bbCodes[i, bbStart].prefix.ansi,
+ bbCodes[i, bbStart].suffix.ansi, strStart, strTrail, strCode, lenCode);
+ if sfound then
+ begin
+ if bbCodes[i, bbStart].bbtype = bbSimple then
+ strCode := bbCodes[i, bbStart].html
+ else
+ begin
+ SetString(code, strCode, lenCode);
+ strCode := StrLFmt(fmt_buffer, MAX_FMTBUF, bbCodes[i, bbStart].html,
+ [PAnsiChar(code)]);
+ end;
+ bufEnd := StrReplace(strStart, strCode, bufEnd, strTrail);
+ bufPos := strTrail;
+ end;
+ repeat
+ efound := StrSearch(bufPos, bbCodes[i, bbEnd].prefix.ansi,
+ bbCodes[i, bbEnd].suffix.ansi, strStart, strTrail, strCode, lenCode);
+ if sfound then
+ strCode := bbCodes[i, bbEnd].html
+ else
+ strCode := nil;
+ if efound then
+ begin
+ bufEnd := StrReplace(strStart, strCode, bufEnd, strTrail);
+ bufPos := strTrail;
+ end
+ else
+ bufEnd := StrAppend(strCode, bufEnd);
+ until sfound or not efound;
+ until not sfound;
+ end;
+ SetString(Result,PAnsiChar(TextBuffer.Buffer),bufEnd-TextBuffer.Buffer);
+ TextBuffer.Unlock;
+end;
+
+function DoStripBBCodes(S: String): String;
+var
+ WideStream: String;
+ i,spos,epos,cpos,slen: integer;
+ trail: String;
+ bbClass: TBBCodeClass;
+begin
+ WideStream := S;
+ for i := 0 to High(bbCodes) do
+ for bbClass := bbStart to bbEnd do
+ begin
+ if bbCodes[i, bbClass].bbtype = bbSimple then
+ WideStream := StringReplace(WideStream, bbCodes[i, bbClass].prefix.wide, '', [rfReplaceAll])
+ else
+ repeat
+ spos := Pos(bbCodes[i, bbClass].prefix.wide, WideStream);
+ epos := 0;
+ if spos > 0 then
+ begin
+ cpos := spos + Length(bbCodes[i, bbClass].prefix.wide);
+ slen := Length(bbCodes[i, bbClass].suffix.wide);
+ if slen = 0 then
+ epos := cpos
+ else
+ epos := PosEx(bbCodes[i, bbClass].suffix.wide, WideStream, cpos);
+ if epos > 0 then
+ begin
+ cpos := epos + slen;
+ trail := Copy(WideStream, cpos, Length(WideStream) - cpos + 1);
+ SetLength(WideStream, spos - 1);
+ WideStream := WideStream + trail;
+ end;
+ end;
+ until (spos = 0) or (epos = 0);
+ end;
+ Result := WideStream;
+end;
+
+function DoSupportSmileys(awParam{hRichEdit}:WPARAM; alParam{PItemRenderDetails}: LPARAM): Integer;
+const
+ mesSent: Array[False..True] of Integer = (0,SAFLRE_OUTGOING);
+var
+ sare: TSMADD_RICHEDIT3;
+ ird: PItemRenderDetails;
+begin
+ ird := Pointer(alParam);
+ sare.cbSize := SizeOf(sare);
+ sare.hwndRichEditControl := awParam;
+ sare.rangeToReplace := nil;
+ sare.ProtocolName := ird^.pProto;
+ //sare.flags := SAFLRE_INSERTEMF + mesSent[ird^.IsEventSent];
+ sare.flags := mesSent[ird^.IsEventSent];
+ sare.disableRedraw := True;
+ sare.hContact := ird^.hContact;
+ CallService(MS_SMILEYADD_REPLACESMILEYS,0,LPARAM(@sare));
+ Result := 0;
+end;
+
+function DoSupportMathModule(awParam{hRichEdit}:WPARAM; alParam{PItemRenderDetails}: LPARAM): Integer;
+var
+ mrei: TMathRicheditInfo;
+begin
+ mrei.hwndRichEditControl := awParam;
+ mrei.sel := nil;
+ mrei.disableredraw := integer(false);
+ Result := CallService(MATH_RTF_REPLACE_FORMULAE,0,LPARAM(@mrei));
+end;
+
+(*
+function DoSupportAvatars(wParam:WPARAM; lParam: LPARAM): Integer;
+const
+ crlf: AnsiString = '{\line }';
+var
+ ird: PItemRenderDetails;
+ ave: PAvatarCacheEntry;
+ msglen: integer;
+begin
+ ird := Pointer(lParam);
+ ave := Pointer(CallService(MS_AV_GETAVATARBITMAP,ird.hContact,0));
+ if (ave <> nil) and (ave.hbmPic <> 0) then begin
+ msglen := SendMessage(wParam,WM_GETTEXTLENGTH,0,0);
+ SendMessage(wParam,EM_SETSEL,msglen,msglen);
+ SetRichRTF(wParam,crlf,True,False,True);
+ InsertBitmapToRichEdit(wParam,ave.hbmPic);
+ end;
+ Result := 0;
+end;
+*)
+
+function DoSupportAvatarHistory(awParam:WPARAM; alParam: LPARAM): int;
+const
+ crlf: AnsiString = '{\rtf1{\line }}';
+var
+ ird: PItemRenderDetails;
+ Link: AnsiString;
+ hBmp: hBitmap;
+ cr: CHARRANGE;
+begin
+ Result := 0;
+ ird := Pointer(alParam);
+ if ird.wEventType <> EVENTTYPE_AVATARCHANGE then
+ exit;
+ if (ird.pExtended = nil) or (lstrlenA(ird.pExtended) < 4) then
+ exit;
+ if ((ird.pExtended[0] = '\') and (ird.pExtended[1] = '\')) or
+ ((ird.pExtended[0] in ['A' .. 'Z', 'a' .. 'z']) and (ird.pExtended[1] = ':') and
+ (ird.pExtended[2] = '\')) then
+ Link := ird.pExtended
+ else
+ Link := AnsiString(hppProfileDir) + '\' + ird.pExtended; //!!
+ hBmp := CallService(MS_UTILS_LOADBITMAP, 0, LPARAM(@Link[1]));
+ if hBmp <> 0 then
+ begin
+ cr.cpMin := SendMessage(awParam, WM_GETTEXTLENGTH, 0, 0);
+ cr.cpMax := cr.cpMin;
+ SendMessage(awParam, EM_EXSETSEL, 0, LPARAM(@cr));
+ SetRichRTF(awParam, crlf, true, false, true);
+ RichEdit_InsertBitmap(awParam, hBmp, Cardinal(-1));
+ end;
+end;
+
+
+initialization
+ rtf_ctable_text := '';
+
+ for i := 0 to High(rtf_ctable) do
+ begin
+ rtf_ctable_text := rtf_ctable_text + AnsiString(format('\red%d\green%d\blue%d;',
+ [rtf_ctable[i].col and $FF,
+ (rtf_ctable[i].col shr 8) and $FF,
+ (rtf_ctable[i].col shr 16) and $FF]));
+ end;
+
+ for i := 0 to High(bbCodes) do
+ begin
+ bbCodes[i, bbStart].prefix.wide := String(bbCodes[i, bbStart].prefix.ansi);
+ bbCodes[i, bbStart].suffix.wide := String(bbCodes[i, bbStart].suffix.ansi);
+ bbCodes[i, bbEnd ].prefix.wide := String(bbCodes[i, bbEnd ].prefix.ansi);
+ bbCodes[i, bbEnd ].suffix.wide := String(bbCodes[i, bbEnd ].suffix.ansi);
+ end;
+
+ TextBuffer := THppBuffer.Create;
+
+finalization
+ TextBuffer.Destroy;
+
+end.