From a5a3db4393d85407ff4c5668d88860e06158abd0 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Wed, 4 Jul 2012 13:17:29 +0000 Subject: History++ sources upload (all files, no project) git-svn-id: http://svn.miranda-ng.org/main/trunk@756 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/HistoryPlusPlus/hpp_itemprocess.pas | 558 ++++++++++++++++++++++++++++ 1 file changed, 558 insertions(+) create mode 100644 plugins/HistoryPlusPlus/hpp_itemprocess.pas (limited to 'plugins/HistoryPlusPlus/hpp_itemprocess.pas') 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:''; minRE: 10), + (prefix:(ansi:'[/b]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}'; html:'')), + ((prefix:(ansi:'[i]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'{\i '; html:''; minRE: 10), + (prefix:(ansi:'[/i]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}'; html:'')), + ((prefix:(ansi:'[u]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'{\ul '; html:''; minRE: 10), + (prefix:(ansi:'[/u]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}'; html:'')), + ((prefix:(ansi:'[s]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'{\strike '; html:''; minRE: 10), + (prefix:(ansi:'[/s]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}'; html:'')), + ((prefix:(ansi:'[color='); suffix:(ansi:']'); bbtype:bbColor; rtf:'{\cf%u '; html:''; minRE: 10), + (prefix:(ansi:'[/color]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}'; html:'')), + {$IFDEF USE_URL_BBCODE} + ((prefix:(ansi:'[url='); suffix:(ansi:']'); bbtype:bbUrl; rtf:'{\field{\*\fldinst{HYPERLINK ":%s"}}{\fldrslt{\ul\cf%u'; html:''; minRE: 41), + (prefix:(ansi:'[/url]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}}}'; html:'')), + {$ENDIF} + ((prefix:(ansi:'[size='); suffix:(ansi:']'); bbtype:bbSize; rtf:'{\fs%u '; html:''; minRE: 10), + (prefix:(ansi:'[/size]'); suffix:(ansi:nil); bbtype:bbSimple; rtf:'}'; html:'')), + ((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 (urlStartbufPos+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. -- cgit v1.2.3