summaryrefslogtreecommitdiff
path: root/plugins/ImportTXT
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
commit48540940b6c28bb4378abfeb500ec45a625b37b6 (patch)
tree2ef294c0763e802f91d868bdef4229b6868527de /plugins/ImportTXT
parent5c350913f011e119127baeb32a6aedeb4f0d33bc (diff)
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/ImportTXT')
-rw-r--r--plugins/ImportTXT/BICQ5IP.inc112
-rw-r--r--plugins/ImportTXT/BICQ6IP.inc91
-rw-r--r--plugins/ImportTXT/BRMSIP.inc77
-rw-r--r--plugins/ImportTXT/BbayanIP.inc77
-rw-r--r--plugins/ImportTXT/BmContactIP.inc58
-rw-r--r--plugins/ImportTXT/BqhfIP.inc131
-rw-r--r--plugins/ImportTXT/FileDlgs.pas131
-rw-r--r--plugins/ImportTXT/General.pas562
-rw-r--r--plugins/ImportTXT/ImpDlgRes.inc12
-rw-r--r--plugins/ImportTXT/ImpTxtDlg.rc18
-rw-r--r--plugins/ImportTXT/ImpTxtDlg.resbin0 -> 3264 bytes
-rw-r--r--plugins/ImportTXT/ImpTxtWiz.rc64
-rw-r--r--plugins/ImportTXT/ImpTxtWiz.resbin0 -> 2840 bytes
-rw-r--r--plugins/ImportTXT/ImpTxt_Ver.rc28
-rw-r--r--plugins/ImportTXT/ImpTxt_Ver.resbin0 -> 1056 bytes
-rw-r--r--plugins/ImportTXT/ImpWizRes.inc21
-rw-r--r--plugins/ImportTXT/ImportT.pas82
-rw-r--r--plugins/ImportTXT/ImportTU.pas260
-rw-r--r--plugins/ImportTXT/ImportThrd.pas599
-rw-r--r--plugins/ImportTXT/ImportTxtWiz.pas369
-rw-r--r--plugins/ImportTXT/PerlRegEx.pas447
-rw-r--r--plugins/ImportTXT/doc/changelog_ru.txt77
-rw-r--r--plugins/ImportTXT/doc/examples_ru.txt169
-rw-r--r--plugins/ImportTXT/doc/importtxt_translate.txt105
-rw-r--r--plugins/ImportTXT/doc/pattern_cfg_ru.txt77
-rw-r--r--plugins/ImportTXT/doc/readme_ru.txt78
-rw-r--r--plugins/ImportTXT/ico/def_ico.icobin0 -> 2550 bytes
-rw-r--r--plugins/ImportTXT/importtxt.dpr202
-rw-r--r--plugins/ImportTXT/importtxt/ICQ5_p.ini9
-rw-r--r--plugins/ImportTXT/importtxt/ICQ6_p.ini5
-rw-r--r--plugins/ImportTXT/importtxt/MAgent_p.ini23
-rw-r--r--plugins/ImportTXT/importtxt/QHF_p.ini5
-rw-r--r--plugins/ImportTXT/importtxt/SEmidprms_p.ini5
-rw-r--r--plugins/ImportTXT/importtxt/bayanICQ_p.ini9
-rw-r--r--plugins/ImportTXT/importtxt/dichat_p.ini24
-rw-r--r--plugins/ImportTXT/importtxt/historypp_p.ini1
-rw-r--r--plugins/ImportTXT/importtxt/jimm_p.ini24
-rw-r--r--plugins/ImportTXT/importtxt/jimmws2_p.ini22
-rw-r--r--plugins/ImportTXT/importtxt/jimmws_p.ini23
-rw-r--r--plugins/ImportTXT/importtxt/mContact_p.ini9
-rw-r--r--plugins/ImportTXT/importtxt/msgexport_p.ini23
-rw-r--r--plugins/ImportTXT/importtxt/nokmidprms_p.ini9
-rw-r--r--plugins/ImportTXT/importtxt/pigeon_p.ini23
-rw-r--r--plugins/ImportTXT/importtxt/qip_p.ini23
-rw-r--r--plugins/ImportTXT/importtxt/smaper_p.ini23
-rw-r--r--plugins/ImportTXT/importtxt/smapern_p.ini23
-rw-r--r--plugins/ImportTXT/importtxtdlg.pas233
-rw-r--r--plugins/ImportTXT/make.bat10
48 files changed, 4373 insertions, 0 deletions
diff --git a/plugins/ImportTXT/BICQ5IP.inc b/plugins/ImportTXT/BICQ5IP.inc
new file mode 100644
index 0000000000..581085ece6
--- /dev/null
+++ b/plugins/ImportTXT/BICQ5IP.inc
@@ -0,0 +1,112 @@
+{$ifdef BIN_IMPORT_}
+var
+ XI:XML_API_W;
+ rhxml:HXML;
+ curxml:HXML;
+ chldxml:HXML;
+ ptxt:PWideChar;
+ txtlen:int;
+ ic,tm:integer;
+ res:LongBool;
+
+{$else}
+begin
+ If pluginLink^.ServiceExists(MS_SYSTEM_GET_XI)>0 then
+ begin
+ XI.cbSize:=SizeOf(XML_API_W);
+ res:=longbool(pluginLink^.CallService(MS_SYSTEM_GET_XI,0,Int(@XI)));
+ if not res then
+ begin
+ XI.cbSize:=SizeOf(XML_API_W)-4;
+ res:=longbool(pluginLink^.CallService(MS_SYSTEM_GET_XI,0,Int(@XI)));
+ if not res then
+ begin
+ s:=TranslateWideString('Error at initialization XML parser');
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ exit;
+ end;
+ end;
+ end
+ else
+ begin
+ s:=TranslateWideString('Your version of Miranda don''t support XML parsing');
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ exit;
+ end;
+ if (DContact.hContact=0) or (DContact.hContact=INVALID_HANDLE_VALUE) then
+ if (fContact.hContact<>0) and (fContact.hContact<>INVALID_HANDLE_VALUE) then
+ DContact:=fContact;
+ if (DContact.hContact<>0) and (DContact.hContact<>INVALID_HANDLE_VALUE) then
+ begin
+ proto:=GetContactProto(DContact.hContact);
+ DoMessage(ITXT_THREAD_DEST_CONTACT,DContact.hContact,0);
+ DoMessage(ITXT_THREAD_START,0,0);
+ GetMem(ptxt,SizeOf(WideChar)*FileLen+2);
+ try
+ ptxt:=UTF8toWide(pFileText,ptxt,SizeOf(WideChar)*FileLen+2);
+ ptxt[FileLen+1]:=#0000;
+ rhxml:=XI.parseString(ptxt,@txtlen,'root');
+ finally
+ freemem(ptxt);
+ end;
+ if (rhxml=0) then exit;
+ DoMessage(ITXT_THREAD_MAXPROGRESS,0,xi.getChildCount(rhxml));
+ chldxml:=xi.getFirstChild(rhxml);
+ if xi.getName(chldxml)='version' then
+ begin
+ ic:=0;
+ curxml:=xi.getNextChild(rhxml,'event',@ic);
+ while (curxml<>0) do
+ begin
+ fillchar(dbei,sizeof(dbei),0);
+ dbei.cbSize:=sizeof(dbei);
+ dbei.szModule:=PChar(proto);
+ if TryStrToInt(xi.getText(xi.getChildByPath(curxml,'time',false)),tm) then dbei.timestamp:=tm;
+ if xi.getText(xi.getChildByPath(curxml,'incoming',false))='Yes' then dbei.flags:=DBEF_READ
+ else dbei.flags:=DBEF_SENT or DBEF_READ;
+ if isMirandaUnicode then dbei.flags:=dbei.flags or DBEF_UTF;
+
+ if xi.getText(xi.getChildByPath(curxml,'type',false))^='2' then
+ begin
+ s:=xi.getText(xi.getChildByPath(curxml,'text',false))+': '+
+ xi.getText(xi.getChildByPath(curxml,'data',false));
+ dbei.eventType:= EVENTTYPE_URL;
+ end
+ else
+ begin
+ s:=xi.getText(xi.getChildByPath(curxml,'text',false));
+ dbei.eventType:= EVENTTYPE_MESSAGE;
+ end;
+ try
+ if IsMirandaUnicode then tempstr:=WidetoUTF8(PWideChar(s),tempstr)
+ else tempstr:=WideToANSI(PWideChar(s),tempstr,cp);
+ dbei.cbBlob:=lstrlen(tempstr)+1;
+ dbei.pBlob:=PByte(tempstr);
+ if not IsDuplicateEvent(DContact.hContact,dbei) then
+ if pluginLink^.CallService(MS_DB_EVENT_ADD, wParam(DContact.hContact), lParam(@dbei))<>0 then Inc(AddedMessages)
+ else begin
+ s:= 'Error adding message to DB';
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0); break; end
+
+ else Inc(Duplicates);
+
+ finally
+ FreeMem(tempstr);
+ curxml:=xi.getNextChild(rhxml,'event',@ic);
+ DoMessage(ITXT_THREAD_PROGRESS,ic,0);
+ end;
+ end;
+ end
+ else
+ begin
+ s:=WideFormat(TranslateWideString('Its not %s file'),['ICQ5']);
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ end;
+ end
+ else
+ begin
+ s:=TranslateWideString('Can''t determine destination contact');
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ end;
+end;
+{$endif} \ No newline at end of file
diff --git a/plugins/ImportTXT/BICQ6IP.inc b/plugins/ImportTXT/BICQ6IP.inc
new file mode 100644
index 0000000000..af8c197e74
--- /dev/null
+++ b/plugins/ImportTXT/BICQ6IP.inc
@@ -0,0 +1,91 @@
+{$ifdef BIN_IMPORT_}
+var DS: PDataSource;
+ SS: PSession;
+ QR1: PQuery;
+
+var
+ OneContact:boolean;
+ flags:integer;
+ timestamp:LongWord;
+ Msg:string;
+
+function FindUIDinDB(too:string):string;
+var QR2:PQuery;
+begin
+ QR2:= NewQuery( SS );
+ QR2.Text := 'select to, UID from ChatHistory WHERE to='+too;
+ QR2.Open;
+ QR2.First;
+ result:=QR2.FieldByNameAsStr['UID'];
+ QR2.Free;
+end;
+
+{$else}
+begin
+ DoUnMapFile;
+ OneContact:=(DContact.hContact<>0) and (DContact.hContact<>INVALID_HANDLE_VALUE);
+ try
+ DS := NewDataSource( 'Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;' +
+ 'Data Source='+FileName+
+ ';Mode=Share Deny None;' +
+ 'Extended Properties="";' +
+ 'Locale Identifier=1033;' +
+ 'Persist Security Info=False;');
+ SS := NewSession( DS );
+ QR1 := NewQuery( SS );
+ QR1.Text:= 'SELECT Messages.from, date, to, type, subType, subject FROM Messages';
+ QR1.Open;
+ if (QR1.ColCount=7) then
+ begin
+ DoMessage(ITXT_THREAD_START,0,0);
+ QR1.First;
+ DoMessage(ITXT_THREAD_MAXPROGRESS,0,QR1.RowCount);
+ While not QR1.EOF do
+ begin
+ try
+ if (QR1.SFieldByName[ 'type' ]='Text') and
+ (QR1.SFieldByName[ 'subType' ]='IM') then
+ begin
+ UIDStr:=FindUIDinDB(QR1.FieldByNameAsStr[ 'to' ]);
+ if not OneContact then
+ begin
+ DContact.ContactUID:=UIDStr;
+ TryDetermContact(DContact);
+ end;
+ if (DContact.hContact<>0) and (DContact.hContact<>INVALID_HANDLE_VALUE) then
+ begin
+ if QR1.SField[ 1 ]='' then flags:=DBEF_SENT or DBEF_READ
+ else flags:=DBEF_READ;
+ if IsMirandaUnicode then flags:=flags or DBEF_UTF;
+ timestamp:=DateTimeToTimeStamp(QR1.DFieldByName['date']-693594);
+ Msg:=QR1.SFieldByName['subject'];
+ if IsMirandaUnicode then
+ begin
+ tempstr:=ANSIToUTF8(PAnsiChar(Msg),tempstr,cp);
+ Msg:=tempstr;
+ FreeMem(tempstr);
+ end;
+ AddMsgToDB(DContact.hContact,flags,timestamp,Msg,AddedMessages,Duplicates);
+ end;
+ end;
+ except
+ ShowException(ExceptObject,ExceptAddr)
+ end;
+ QR1.Next;
+ DoMessage(ITXT_THREAD_PROGRESS,QR1.CurIndex,0);
+ end; //for
+ end
+ else
+ begin
+ s:=WideFormat(TranslateWideString('Its not %s file'),['ICQ6 mdb']);
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ end;
+ finally
+ DS.Free;
+ DS := nil;
+ SS := nil;
+ QR1 := nil;
+ end;
+end;
+{$endif}
+
diff --git a/plugins/ImportTXT/BRMSIP.inc b/plugins/ImportTXT/BRMSIP.inc
new file mode 100644
index 0000000000..552a98af3b
--- /dev/null
+++ b/plugins/ImportTXT/BRMSIP.inc
@@ -0,0 +1,77 @@
+{$ifdef BIN_IMPORT_}
+var rsz:integer;
+
+{$else}
+begin
+ pt:=integer(pFileText);
+ i:=0;
+ if FileLen>=$30 then
+ if (StrLComp(PChar(pt),'midp-rms',8)=0) then
+ begin
+ if FileLen>=$48 then
+ if (RLInteger(pt+$40)=$48) then
+ begin
+ fsz:=RLInteger(pt+$44);
+ i:=$48;
+ end;
+ if (RLInteger(pt+$28)=$30) then
+ begin
+ fsz:=RLInteger(pt+$2C);
+ i:=$30;
+ end;
+
+ if (DContact.hContact=0) or (DContact.hContact=INVALID_HANDLE_VALUE) then
+ if (fContact.hContact<>0) and (fContact.hContact<>INVALID_HANDLE_VALUE) then
+ DContact:=fContact;
+ if (DContact.hContact<>0) and (DContact.hContact<>INVALID_HANDLE_VALUE) then
+ begin
+ proto:=GetContactProto(DContact.hContact);
+ DoMessage(ITXT_THREAD_DEST_CONTACT,DContact.hContact,0);
+ DoMessage(ITXT_THREAD_START,0,0);
+ DoMessage(ITXT_THREAD_MAXPROGRESS,0,fsz);
+ while i<fsz do
+ begin
+ with dbei do
+ begin
+ fillchar(dbei,sizeof(dbei),0);
+ cbSize:=sizeof(dbei);
+ szModule:=PChar(proto);
+ rsz:= RLInteger(pt+i+$08);
+ if PByte(pt+i+$10)^=$00 then flags:=0
+ else flags:=DBEF_SENT;
+ flags:=flags or DBEF_READ or DBEF_UTF; //в файлах лежат в utf8 и импортируются без изменений
+ eventType:= EVENTTYPE_MESSAGE;
+ cbBlob:=RLWord(pt+i+$13+RLWord(pt+i+$11));
+ pBlob:=Pointer(pt+i+$13+RLWord(pt+i+$11)+$2);
+ timestamp:=StrToTimeStamp(pointer(pt+i+$13+RLWord(pt+i+$11)+$4+cbBlob),RLWord(pt+i+$13+RLWord(pt+i+$11)+$2+cbBlob));
+ inc(cbBlob);
+ end;
+ try
+ if not IsDuplicateEvent(DContact.hContact,dbei) then
+ if pluginLink^.CallService(MS_DB_EVENT_ADD, wParam(DContact.hContact), lParam(@dbei))<>0 then Inc(AddedMessages)
+ else begin
+ s:= 'Error adding message to DB';
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0); break; end
+
+ else Inc(Duplicates);
+ finally
+ inc(i,rsz);
+ end;
+ DoMessage(ITXT_THREAD_PROGRESS,i,0);
+ end;
+ end
+ else
+ begin
+ s:=TranslateWideString('Can''t determine destination contact');
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ end;
+ end
+ else
+ begin
+ s:=WideFormat(TranslateWideString('Its not %s file'),['midp-rms']);
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ end
+ else //file len
+
+end;
+{$endif}
diff --git a/plugins/ImportTXT/BbayanIP.inc b/plugins/ImportTXT/BbayanIP.inc
new file mode 100644
index 0000000000..b37892fbdc
--- /dev/null
+++ b/plugins/ImportTXT/BbayanIP.inc
@@ -0,0 +1,77 @@
+{$ifdef BIN_IMPORT_}
+var j:integer;
+{$else}
+begin
+ pt:=integer(pFileText);
+ if FileLen>=10 then
+ if true {(PWORD(pt)^=$4248) and (PDWORD(pt+2)^=$FFFFFFFF)} then
+ begin
+ //смотрим есть ли у нас контакт назначения
+ if (DContact.hContact=0) or (DContact.hContact=INVALID_HANDLE_VALUE) then
+ if (fContact.hContact<>0) and (fContact.hContact<>INVALID_HANDLE_VALUE) then
+ DContact:=fContact;
+ if (DContact.hContact<>0) and (DContact.hContact<>INVALID_HANDLE_VALUE) then
+ begin
+ proto:=GetContactProto(DContact.hContact);
+ DoMessage(ITXT_THREAD_DEST_CONTACT,DContact.hContact,0);
+ DoMessage(ITXT_THREAD_START,0,0);
+ fsz:=FileLen-2; //размер данных в файле
+ DoMessage(ITXT_THREAD_MAXPROGRESS,0,fsz);
+ inc(pt,2);
+ i:=0;
+ while i<fsz do
+ begin
+ with dbei do
+ begin
+ fillchar(dbei,sizeof(dbei),0);
+ cbSize:=sizeof(dbei);
+ szModule:=PChar(proto);
+ timestamp:=ImportTU.TimeStamp(
+ RLWORD(pt+i+5),
+ PByte(pt+i+4)^,
+ PByte(pt+i+3)^,
+ PByte(pt+i)^,
+ PByte(pt+i+1)^,
+ PByte(pt+i+2)^);
+ if PByte(pt+i+$7)^=$00 then flags:=DBEF_READ
+ else flags:=DBEF_SENT or DBEF_READ;
+ eventType:= EVENTTYPE_MESSAGE;
+ cbBlob:=(RLWORD(pt+i+$8)+1);
+ s:='';
+ for j:=0 to RLWORD(pt+i+$8) do
+ s:=s+WideChar(RLWORD(pt+i+$0A+(j*2)));
+ if IsMirandaUnicode then
+ begin
+ flags:=flags or DBEF_UTF;
+ cbBlob:=cbBlob*SizeOf(WideChar);
+ pBlob:=PByte(WideToUTF8(PWideChar(S),PChar(pBlob)));
+ end
+ else
+ pBlob:=PByte(WideToANSI(PWideChar(S),PChar(pBlob),cp));
+ end;
+ if not IsDuplicateEvent(DContact.hContact,dbei) then
+ if pluginLink^.CallService(MS_DB_EVENT_ADD, wParam(DContact.hContact), lParam(@dbei))<>0 then Inc(AddedMessages)
+ else begin
+ s:= 'Error adding message to DB';
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0); break; end
+
+ else Inc(Duplicates);
+ inc(i,dbei.cbBlob+$0C);
+ FreeMem(dbei.pBlob);
+ DoMessage(ITXT_THREAD_PROGRESS,i,0);
+ end;
+ end
+ else
+ begin
+ s:=TranslateWideString('Can''t determine destination contact');
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ end;
+ end
+ else
+ begin
+ s:=WideFormat(TranslateWideString('Its not %s file'),['bayanICQ']);
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ end
+ else //file len
+end;
+{$endif}
diff --git a/plugins/ImportTXT/BmContactIP.inc b/plugins/ImportTXT/BmContactIP.inc
new file mode 100644
index 0000000000..e4fe59165e
--- /dev/null
+++ b/plugins/ImportTXT/BmContactIP.inc
@@ -0,0 +1,58 @@
+{$ifdef BIN_IMPORT_}
+
+{$else}
+begin
+ pt:=integer(pFileText);
+ if FileLen>=10 then
+ if (PWORD(pt)^=$4248) and (PDWORD(pt+2)^=$FFFFFFFF) then
+ begin
+ //смотрим есть ли у нас контакт назначения
+ if (DContact.hContact=0) or (DContact.hContact=INVALID_HANDLE_VALUE) then
+ if (fContact.hContact<>0) and (fContact.hContact<>INVALID_HANDLE_VALUE) then
+ DContact:=fContact;
+ if (DContact.hContact<>0) and (DContact.hContact<>INVALID_HANDLE_VALUE) then
+ begin
+ proto:=GetContactProto(DContact.hContact);
+ DoMessage(ITXT_THREAD_DEST_CONTACT,DContact.hContact,0);
+ DoMessage(ITXT_THREAD_START,0,0);
+ fsz:=PDWORD(pt+6)^; //размер данных в файле
+ DoMessage(ITXT_THREAD_MAXPROGRESS,0,fsz);
+ inc(pt,10);
+ i:=0;
+ while i<fsz do
+ begin
+ with dbei do
+ begin
+ cbSize:=PInteger(pt+i)^;
+ szModule:=PChar(proto);
+ timestamp:=PDWORD(pt+i+$08)^;
+ flags:=PDWORD(pt+i+$0C)^;
+ eventtype:=PDWORD(pt+i+$10)^;
+ cbBlob:=PDWORD(pt+i+$14)^;
+ pBlob:=PBYTE(pt+i+cbSize);
+ end;
+ if not IsDuplicateEvent(DContact.hContact,dbei) then
+ if pluginLink^.CallService(MS_DB_EVENT_ADD, wParam(DContact.hContact), lParam(@dbei))<>0 then Inc(AddedMessages)
+ else begin
+ s:= 'Error adding message to DB';
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0); break; end
+
+ else Inc(Duplicates);
+ inc(i,dbei.cbSize+dbei.cbBlob);
+ DoMessage(ITXT_THREAD_PROGRESS,i,0);
+ end;
+ end
+ else
+ begin
+ s:=TranslateWideString('Can''t determine destination contact');
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ end;
+ end
+ else
+ begin
+ s:=WideFormat(TranslateWideString('Its not %s file'),['mContact']);
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ end
+ else //file len
+end;
+{$endif}
diff --git a/plugins/ImportTXT/BqhfIP.inc b/plugins/ImportTXT/BqhfIP.inc
new file mode 100644
index 0000000000..236a37de0b
--- /dev/null
+++ b/plugins/ImportTXT/BqhfIP.inc
@@ -0,0 +1,131 @@
+{$ifdef BIN_IMPORT_}
+var
+ qhfver:byte;
+ szMsgHd:word;
+ UIDstr:UTF8String;
+ UIDLen,NickLen:word;
+ NickStr:UTF8String;
+
+function DecodeQHFMsg(ver:byte; adr:integer; cSize:word):string;
+
+function get1(c: char): byte;
+begin
+ if ShortInt(c)>=0 then Result:=Byte(c)
+ else Result := Byte(c)+256;
+end;
+
+function get2(b:byte): char;
+begin
+ if b<128 then result:=Char(b)
+ else result:=Char(b-256);
+end;
+
+var i:integer;
+begin
+ SetLength(Result,cSize);
+ for i:=1 to cSize do
+ begin
+ Result[i]:=PChar(adr+i-1)^;
+ if ver<>$01 then
+ begin
+ inc(Result[i],i);
+ Result[i]:=get2(255-get1(Result[i]));
+ end
+ end;
+end;
+
+{$else}
+begin
+ pt:=integer(pFileText);
+ if FileLen>=$2E then
+ if (PChar(pt)^='Q') and (PChar(pt+1)^='H') and (PChar(pt+2)^='F') then
+ begin
+ qhfver:=PByte(pt+3)^;
+ if qhfver>=$03 then szMsgHd:=$23
+ else szMsgHd:=$21;
+ fsz:=RLInteger(pt+$04);
+ UIDLen:=RLWord(pt+$2C);
+ SetLength(UIDstr,UIDLen);
+ if qhfver<=2 then lstrcpynA(PChar(UIDstr),PChar(pt+$2E),UIDLen)
+ else lstrcpynA(PChar(UIDstr),PChar(pt+$2E),UIDLen+1);
+ NickLen:=RLWord(pt+$2E+UIDLen);
+ SetLength(NickStr,NickLen);
+ if qhfver<=2 then lstrcpynA(PChar(NickStr),PChar(pt+$2E+UIDLen+2),UIDLen)
+ else lstrcpynA(PChar(NickStr),PChar(pt+$2E+UIDLen+2),UIDLen+1);
+ inc(pt,$2E+UIDLen+2+NickLen);
+ if fsz<>FileLen-($2E+UIDLen+2+NickLen) then fsz:= FileLen-($2E+UIDLen+2+NickLen);
+ if (DContact.hContact=0) or (DContact.hContact=INVALID_HANDLE_VALUE) then
+ begin
+ if IsMirandaUnicode then DContact.ContactUID:=UIDstr
+ else
+ begin
+ tempstr:=UTF8ToANSI(PChar(UIDstr),tempstr,cp);
+ DContact.ContactUID:=tempstr;
+ FreeMem(tempstr);
+ end;
+ if IsMirandaUnicode then DContact.ContactNick:=NickStr
+ else
+ begin
+ tempstr:=UTF8ToANSI(PChar(NickStr),tempstr,cp);
+ DContact.ContactNick:=tempstr;
+ FreeMem(tempstr);
+ end;
+ TryDetermContact(DContact);
+ end;
+ if (DContact.hContact=0) or (DContact.hContact=INVALID_HANDLE_VALUE) then
+ if (fContact.hContact<>0) and (fContact.hContact<>INVALID_HANDLE_VALUE) then
+ DContact:=fContact;
+ if (DContact.hContact<>0) and (DContact.hContact<>INVALID_HANDLE_VALUE) then
+ begin
+ proto:=GetContactProto(DContact.hContact);
+ DoMessage(ITXT_THREAD_DEST_CONTACT,DContact.hContact,0);
+ DoMessage(ITXT_THREAD_START,0,0);
+ DoMessage(ITXT_THREAD_MAXPROGRESS,0,fsz);
+ i:=0;
+ while i<fsz do
+ begin
+ with dbei do
+ begin
+ fillchar(dbei,sizeof(dbei),0);
+ cbSize:=sizeof(dbei);
+ szModule:=PChar(proto);
+ timestamp:=RLInteger(pt+i+$12);
+ timestamp:=timestamp-(PluginLink.CallService(MS_DB_TIME_TIMESTAMPTOLOCAL,timestamp,0)-timestamp);//приводим к GMT
+ if PByte(pt+i+$1A)^=$00 then flags:=0
+ else flags:=DBEF_SENT;
+ flags:=flags or DBEF_READ or DBEF_UTF; //в файлах лежат в utf8 и импортируются без изменений
+ eventType:= EVENTTYPE_MESSAGE;
+ cbBlob:=RLWord(pt+i+szMsgHd-2)+1; //размер текста сообщения с #0
+ pBlob:=AllocMem(cbBlob);
+ end;
+ try
+ Move(DecodeQHFMsg(qhfver,pt+i+szMsgHd,dbei.cbBlob-1)[1],dbei.pBlob^,dbei.cbBlob-1);
+ if not IsDuplicateEvent(DContact.hContact,dbei) then
+ if pluginLink^.CallService(MS_DB_EVENT_ADD, wParam(DContact.hContact), lParam(@dbei))<>0 then Inc(AddedMessages)
+ else begin
+ s:= 'Error adding message to DB';
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0); break; end
+
+ else Inc(Duplicates);
+
+ finally
+ inc(i,szMsgHd+dbei.cbBlob-1);
+ FreeMem(dbei.pBlob);
+ end;
+ DoMessage(ITXT_THREAD_PROGRESS,i,0);
+ end;
+ end
+ else
+ begin
+ s:=TranslateWideString('Can''t determine destination contact');
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ end;
+ end
+ else
+ begin
+ s:=WideFormat(TranslateWideString('Its not %s file'),['QHF']);
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ end
+ else //file len
+end;
+{$endif} \ No newline at end of file
diff --git a/plugins/ImportTXT/FileDlgs.pas b/plugins/ImportTXT/FileDlgs.pas
new file mode 100644
index 0000000000..2257a7ab5e
--- /dev/null
+++ b/plugins/ImportTXT/FileDlgs.pas
@@ -0,0 +1,131 @@
+unit FileDlgs;
+
+interface
+
+uses windows,m_api;
+
+function OpenDialogExecute(hDlg:hWnd; flg:cardinal; var nFO:integer; const DefExt:string):WideString; //Диалог открытия файла
+function FolderDialogExecute(hdlg:HWND; var nFO:integer; const DefExt:string):WideString; //Диалог выбора папки
+
+implementation
+
+uses shlobj, activex, SysUtils, CommDlg;
+
+function OpenDialogExecute(hDlg:hWnd; flg:cardinal; var nFO:integer; const DefExt:string):WideString; //Диалог открытия файла
+var OpenFilename:TOpenFilenameW;
+ TempFilename:WideString;
+ Temp1,Temp2:WideString;
+ res:bool;
+begin
+ nFO:=0;
+ FillChar(OpenFileName, SizeOf(OpenFileName), 0);
+ with OpenFilename do
+ begin
+ lStructSize:=SizeOf(OpenFilename);
+ hWndOwner:=hDlg;
+ Temp1:=
+ TranslateWideString('Default extension')+' (*.'+DefExt+')'+#0+'*.'+DefExt+#0+
+ TranslateWideString('All files (*.*)')+#0+'*.*'+#0#0;
+ lpstrFilter:=PWideChar(Temp1);
+ nMaxFile:=MAX_PATH*16;
+ SetLength(TempFilename, nMaxFile + 2);
+ TempFilename[1]:=#0;
+ lpstrFile :=PWideChar(TempFilename);
+ Temp2:=TranslateWideString('Choose a file for import...');
+ lpstrTitle:=PWideChar(Temp2);
+ Flags:=flg or OFN_EXPLORER or OFN_ENABLESIZING or OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST or OFN_NOCHANGEDIR;
+ end;
+ res:=GetOpenFileNameW(OpenFileName);
+ if res then
+ begin
+ Result:=TempFilename;
+ nFO:=OpenFilename.nFileOffset;
+ end
+ else Result:='';
+end;
+
+//***Awkward - author of this procedures************
+
+function StrDupW(var dst:PWideChar;src:PWideChar;len:integer=0):PWideChar;
+begin
+ if (src=nil) or (src^=#0) then
+ dst:=nil
+ else
+ begin
+ if len=0 then
+ len:=lstrlenw(src);
+ GetMem(dst,(len+1)*SizeOf(WideChar));
+ lstrcpynw(dst,src,len+1);
+ end;
+ result:=dst;
+end;
+
+function SelectDirectory(Caption:PWideChar;var Directory:PWideChar;
+ Parent:HWND=0;newstyle:bool=false):Boolean;
+var
+ BrowseInfo:TBrowseInfoW;
+ Buffer:array [0..MAX_PATH-1] of WideChar;
+ ItemIDList:PItemIDList;
+ ShellMalloc:IMalloc;
+begin
+ Result:=False;
+ FillChar(BrowseInfo,SizeOf(BrowseInfo),0);
+ if (ShGetMalloc(ShellMalloc)=S_OK) and (ShellMalloc<>nil) then
+ begin
+ with BrowseInfo do
+ begin
+ hwndOwner :=Parent;
+ pszDisplayName:=Buffer;
+ lpszTitle :=Caption;
+ ulFlags :=BIF_RETURNONLYFSDIRS;
+ end;
+ if newstyle then
+ if CoInitializeEx(nil,COINIT_APARTMENTTHREADED)<>RPC_E_CHANGED_MODE then
+ BrowseInfo.ulFlags:=BrowseInfo.ulFlags or BIF_NEWDIALOGSTYLE;
+ try
+ ItemIDList:=ShBrowseForFolderW(BrowseInfo);
+ Result:=ItemIDList<>nil;
+ if Result then
+ begin
+ ShGetPathFromIDListW(ItemIDList,Buffer);
+ StrDupW(Directory,Buffer);
+ ShellMalloc.Free(ItemIDList);
+ end;
+ finally
+ if newstyle then CoUninitialize;
+ end;
+ end;
+end;
+
+//*******************************************************************
+
+function FolderDialogExecute(hdlg:HWND; var nFO:integer; const DefExt:string):WideString; //Диалог выбора папки
+var
+ SR: _WIN32_FIND_DATAW;
+ hFFF:THandle;
+ tpwc:PWideChar;
+ tws:WideString;
+begin
+ if SelectDirectory(PWideChar(TranslateWideString('Select folder for import...')),tpwc,hdlg,true) then
+ begin
+ result:=tpwc;
+ result:=result+#0;
+ nFO:=length(result);
+ tws:=tpwc;
+ tws:=tws+'\*.'+DefExt;
+ SR.dwFileAttributes:=faAnyFile;
+ hFFF:=FindFirstFileW(PWideChar(tws),SR);
+ if hFFF<>INVALID_HANDLE_VALUE then
+ begin
+ repeat
+ result:=result+SR.cFileName;
+ result:=result+#0;
+ until not FindNextFileW(hFFF,SR);
+ windows.FindClose(hFFF);
+ result:=result+#0;
+ end;
+ end
+ else result:='';
+end;
+
+end.
diff --git a/plugins/ImportTXT/General.pas b/plugins/ImportTXT/General.pas
new file mode 100644
index 0000000000..d263dde816
--- /dev/null
+++ b/plugins/ImportTXT/General.pas
@@ -0,0 +1,562 @@
+unit general;
+
+interface
+
+uses Windows,Messages,SysUtils,IniFiles,
+ m_api,
+ ImportT,
+ ImportTU;
+
+var MirVers:DWORD;
+ IsMirandaUnicode:boolean;
+ cp:cardinal;
+
+var
+ AppPath:array[0..MAX_PATH] of char;
+ TxtPatterns: array of RTxtPattern;
+ PatternNames: array of PChar;
+ PatternsCount:integer;
+ Protocols:array of TDestProto;
+ ProtoCount: integer;
+ CheckForDuplicates:boolean;
+ ShowDuplicates:boolean;
+
+const
+ BIN_PROCEDURE_COUNT=6; //количество реализованых процедур бинарного импорта
+
+const
+ {$EXTERNALSYM PBM_SETRANGE}
+ PBM_SETRANGE = WM_USER+1;
+ {$EXTERNALSYM PBM_SETPOS}
+ PBM_SETPOS = WM_USER+2;
+
+const
+ IMPORT_TXT_MODULE= 'ImportTXT';
+ IMPORT_TXT_SERVICE= IMPORT_TXT_MODULE+'/Import';
+ IMPORT_WIZ_SERVICE= IMPORT_TXT_MODULE+'/Wizard';
+
+ //keys
+ IMPORT_TXT_AS= 'AutoStart';
+ IMPORT_TXT_LP= 'LastPattern';
+
+type TOnAccountListChange = procedure ();
+
+var
+ OnAccountListChange:TOnAccountListChange;
+
+function ReadPattern(FileName: string):boolean;
+procedure ReadPatterns;
+procedure ExtractFilePath(fName:PChar);
+function fIsMirandaUnicode:boolean;
+function GetContactProto(hContact: THandle): String;
+function GetContactByUID(proto:string;id:string):THandle;
+function GetContactByNick(Proto:string;Nick:string):THandle;
+procedure EnumProtocols;
+function GetContactID(hContact: THandle; Proto: String = ''; Contact: boolean = false): String;
+function GetContactNick(hContact: THandle; Proto: String = ''; Contact: boolean = false): String;
+function DBReadByte (hContact:THANDLE;szModule:PChar;szSetting:PChar;default:byte =0):byte;
+function DBWriteByte (hContact:THANDLE;szModule:PChar;szSetting:PChar;val:Byte ):Integer;
+procedure SetLastPattern(lp:byte);
+function GetLastPattern:byte;
+function TimeStampToWStr(ts:dword):WideString;
+function StrToTimeStamp(STime:PChar;len:integer):dword;
+
+function RLWord(adr:integer):word;
+function RLInteger(adr:integer):integer;
+
+implementation
+
+
+procedure ExtractFilePath(fName:PChar);
+var p:PChar;
+begin
+ p:=fName;
+ if p<>nil then
+ begin
+ while p^<>#0 do inc(p);
+ while p^<>'\' do dec(p);
+ inc(p);
+ p^:=#0;
+ end;
+end;
+
+function ReadPattern(FileName: string):boolean;
+var TI: TIniFile;
+ h:integer;
+ Err:boolean;
+ tempstr:string;
+begin
+ err:=false;
+ TI:=TIniFile.Create(FileName);
+ try
+ h:=High(TxtPatterns);
+ if not TI.SectionExists('General') then begin result:=true; exit; end;
+ //if "General" exists
+ if TI.ValueExists('General','Name') then TxtPatterns[h].Name:=TI.ReadString('General','Name','')
+ else err:=true;
+ if TI.ValueExists('General','Type') then TxtPatterns[h].IType:=TI.ReadInteger('General','Type',1)
+ else err:=true;
+ case TxtPatterns[h].IType of
+ 1:
+ begin
+ if TI.ValueExists('General','Charset') then
+ begin
+ tempstr:=TI.ReadString('General','Charset','UTF8');
+ if tempstr='ANSI' then TxtPatterns[h].Charset:=inANSI
+ else
+ if tempstr='UTF8' then TxtPatterns[h].Charset:=inUTF8
+ else
+ if tempstr='UCS2' then TxtPatterns[h].Charset:=inUCS2
+ else err:=true;
+ end
+ else err:=true;
+ if TxtPatterns[h].Charset=inANSI then
+ begin
+ TxtPatterns[h].Codepage:= TI.ReadInteger('General','Codepage',0);
+ if not IsValidCodePage(TxtPatterns[h].Codepage) then TxtPatterns[h].Codepage:=0;
+ end;
+ TxtPatterns[h].UseHeader:=TI.ReadInteger('General','UseHeader',0);
+ TxtPatterns[h].UsePreMsg:=TI.ReadBool('General','UsePreMsg',false);
+ // Read message section
+ if TI.SectionExists('Message') then
+ begin
+ if TI.ValueExists('Message','Pattern') then TxtPatterns[h].Msg.Pattern:=TI.ReadString('Message','Pattern','')
+ else err:=true;
+ TxtPatterns[h].Msg.Incoming:=TI.ReadString('Message','In','');
+ TxtPatterns[h].Msg.Outgoing:=TI.ReadString('Message','Out','');
+ if TI.ValueExists('Message','Direction') then TxtPatterns[h].Msg.Direction:=TI.ReadInteger('Message','Direction',0)
+ else err:=true;
+ if TI.ValueExists('Message','Day') then TxtPatterns[h].Msg.Day:=TI.ReadInteger('Message','Day',0)
+ else err:=true;
+ if TI.ValueExists('Message','Month') then TxtPatterns[h].Msg.Month:=TI.ReadInteger('Message','Month',0)
+ else err:=true;
+ if TI.ValueExists('Message','Year') then TxtPatterns[h].Msg.Year:=TI.ReadInteger('Message','Year',0)
+ else err:=true;
+ if TI.ValueExists('Message','Hours') then TxtPatterns[h].Msg.Hours:=TI.ReadInteger('Message','Hours',0)
+ else err:=true;
+ if TI.ValueExists('Message','Minutes') then TxtPatterns[h].Msg.Minutes:=TI.ReadInteger('Message','Minutes',0)
+ else err:=true;
+ TxtPatterns[h].Msg.Seconds:=TI.ReadInteger('Message','Seconds',0)
+ end
+ else err:=true;
+ // if need read header section
+ if (TxtPatterns[h].UseHeader>0) then
+ if TI.SectionExists('Header') then
+ begin
+ if TI.ValueExists('Header','Pattern') then TxtPatterns[h].Header.Pattern:=TI.ReadString('Header','Pattern','')
+ else err:=true;
+ if (not TI.ValueExists('Header','In')) and ((TxtPatterns[h].UseHeader and 1)=1) then err:=true;
+ TxtPatterns[h].Header.Incoming:=TI.ReadInteger('Header','In',0);
+ TxtPatterns[h].Header.Outgoing:=TI.ReadInteger('Header','Out',0);
+ TxtPatterns[h].Header.InNick:=TI.ReadInteger('Header','InNick',0);
+ TxtPatterns[h].Header.OutNick:=TI.ReadInteger('Header','OutNick',0);
+ TxtPatterns[h].Header.InUID:=TI.ReadInteger('Header','InUID',0);
+ TxtPatterns[h].Header.OutUID:=TI.ReadInteger('Header','OutUID',0);
+ if ((TxtPatterns[h].UseHeader and 2)=2) then
+ if (TxtPatterns[h].Header.InNick=0) and (TxtPatterns[h].Header.InUID=0) then err:=true;
+ end
+ else err:=true;
+ // if nead read PreMessage section
+ if TxtPatterns[h].UsePreMsg then
+ if TI.SectionExists('PreMessage') then
+ begin
+ TxtPatterns[h].PreMsg.PreRN:=TI.ReadInteger('PreMessage','PreRN',-1);
+ TxtPatterns[h].PreMsg.AfterRN:=TI.ReadInteger('PreMessage','AfterRN',-1);
+ TxtPatterns[h].PreMsg.PreSP:=TI.ReadInteger('PreMessage','PreSP',0);
+ TxtPatterns[h].PreMsg.AfterSP:=TI.ReadInteger('PreMessage','AfterSP',0);
+ end
+ else err:=true;
+ end; //1
+ 2:
+ begin
+ TxtPatterns[h].BinProc:= TI.ReadInteger('General','BinProcedure',0);
+ if (TxtPatterns[h].BinProc>BIN_PROCEDURE_COUNT) then err:=true;
+ end;
+ end; //case
+ TxtPatterns[h].DefExtension:=TI.ReadString('General','DefaultExtension','txt');
+ TxtPatterns[h].UseFileName:=TI.ReadBool('General','UseFileName',false);
+ // if nead read FileName section
+ if TxtPatterns[h].UseFileName then
+ if TI.SectionExists('FileName') then
+ begin
+ if TI.ValueExists('FileName','Pattern') then TxtPatterns[h].FName.Pattern:=TI.ReadString('FileName','Pattern','')
+ else err:=true;
+ TxtPatterns[h].FName.InNick:=TI.ReadInteger('FileName','InNick',0);
+ TxtPatterns[h].FName.InUID:=TI.ReadInteger('FileName','InUID',0);
+ if (TxtPatterns[h].FName.InNick=0) and (TxtPatterns[h].FName.InUID=0) then err:=true;
+ TxtPatterns[h].FName.OutNick:=TI.ReadInteger('FileName','OutNick',0);
+ TxtPatterns[h].FName.OutUID:=TI.ReadInteger('FileName','OutUID',0);
+ end
+ else err:=true;
+ finally
+ TI.Free;
+ end;
+ Result:=err;
+end;
+
+procedure ReadPatterns;
+var
+ SR: TSearchRec;
+ FileAttrs: Integer;
+ i:integer;
+begin
+ FileAttrs:=faAnyFile;
+ i:=0;
+ if FindFirst(AppPath+'\importtxt\*.ini',FileAttrs,SR)=0 then
+ begin
+ repeat
+ SetLength(TxtPatterns,i+1);
+ SetLength(PatternNames,i+1);
+ if not ReadPattern(AppPath+'\importtxt\'+SR.Name) then
+ begin
+ PatternNames[i]:= PChar(TxtPatterns[i].Name);
+ inc(i);
+ end;
+ until FindNext(SR) <> 0 ;
+ FindClose(SR);
+ end;
+ PatternsCount:=i;
+end;
+
+
+function GetContactByUID(proto:string;id:string):THandle;
+var
+ contact:THandle;
+ otherproto:string;
+ ci:TCONTACTINFO;
+ idnum:integer;
+ tempwstr:PWideChar;
+ ws:WideString;
+begin
+ if not TryStrToInt(id,idnum) then idnum:=0;
+ if IsMirandaUnicode then
+ begin
+ tempwstr:=UTF8ToWide(PChar(id),tempwstr);
+ ws :=tempwstr;
+ FreeMem(tempwstr);
+ end;
+ result:=INVALID_HANDLE_VALUE;
+ contact:=pluginlink^.CallService(MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ while (contact<>0) do
+ begin
+ otherproto:=PChar(pluginlink^.CallService(MS_PROTO_GETCONTACTBASEPROTO,contact,0));
+ if otherproto=proto then
+ begin
+ ci.cbSize:=SizeOf(ci);
+ ci.dwFlag:=CNF_UNIQUEID;
+ if IsMirandaUnicode then ci.dwFlag:=ci.dwFlag or CNF_UNICODE;
+ ci.hContact:=contact;
+ ci.szProto:=PChar(otherproto);
+ if pluginlink^.CallService(MS_CONTACT_GETCONTACTINFO,0,integer(@ci))=0 then
+ begin
+ case ( ci._type ) of
+ CNFT_BYTE: if ci.retval.bVal = idnum then
+ begin
+ result:=contact;
+ break;
+ end;
+ CNFT_WORD: if ci.retval.wVal = idnum then
+ begin
+ result:=contact;
+ break;
+ end;
+ CNFT_DWORD: if ci.retval.dVal = DWORD(idnum) then
+ begin
+ result:=contact;
+ break;
+ end;
+ CNFT_ASCIIZ:
+ if IsMirandaUnicode then
+ if ws=ci.retval.szVal.w then
+ begin
+ result:=contact;
+ break;
+ end else
+ else
+ if id=ci.retval.szVal.a then
+ begin
+ result:=contact;
+ break;
+ end;
+ end; //case
+ end; //if
+ end; //if
+ contact:= Pluginlink^.CallService(MS_DB_CONTACT_FINDNEXT,contact,0);
+ end; //while
+end;
+
+function GetContactByNick(Proto:string;Nick:string):THandle;
+var
+ contact:THandle;
+ otherproto:string;
+ ci:TCONTACTINFO;
+ tempwstr:PWideChar;
+ ws:WideString;
+begin
+ if IsMirandaUnicode then
+ begin
+ tempwstr:=UTF8ToWide(PChar(Nick),tempwstr);
+ ws :=tempwstr;
+ FreeMem(tempwstr);
+ end;
+ result:=INVALID_HANDLE_VALUE;
+ contact:=pluginlink^.CallService(MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ while (contact<>0) do
+ begin
+ otherproto:=PChar(pluginlink^.CallService(MS_PROTO_GETCONTACTBASEPROTO,contact,0));
+ if otherproto=proto then
+ begin
+ ci.cbSize:=SizeOf(ci);
+ ci.dwFlag:=CNF_NICK;
+ if IsMirandaUnicode then ci.dwFlag:=ci.dwFlag or CNF_UNICODE;
+ ci.hContact:=contact;
+ ci.szProto:=PChar(otherproto);
+ if pluginlink^.CallService(MS_CONTACT_GETCONTACTINFO,0,integer(@ci))=0 then
+ begin
+ if IsMirandaUnicode then
+ begin
+ if ws=ci.retval.szVal.w then
+ begin
+ result:=contact;
+ break;
+ end;
+ end
+ else
+ begin
+ if Nick=ci.retval.szVal.a then
+ begin
+ result:=contact;
+ break;
+ end;
+ end;
+ end; //if
+ end; //if
+ contact:= Pluginlink^.CallService(MS_DB_CONTACT_FINDNEXT,contact,0);
+ end; //while
+end;
+
+procedure EnumProtocols;
+var i,iProtoCount:integer;
+ ppAccounts:^PPROTOACCOUNT;
+ temps:string;
+begin
+ ProtoCount:=0;
+ SetLength(Protocols,30);
+ if MirVers> $080000 then pluginLink^.CallService(MS_PROTO_ENUMACCOUNTS,int(@iProtoCount),int(@ppAccounts))
+ else pluginLink^.CallService(MS_PROTO_ENUMPROTOCOLS,int(@iProtoCount),int(@ppAccounts));
+ for i:=1 to iProtoCount do
+ begin
+ if (ppAccounts^^._type=PROTOTYPE_PROTOCOL) then
+ begin
+ temps:=GetContactID(0,ppAccounts^^.szModuleName,false);
+ if temps<>'' then
+ begin
+ protocols[ProtoCount].ProtoName:=ppAccounts^^.szModuleName;
+ protocols[ProtoCount].ProtoUID:=temps;
+ protocols[ProtoCount].ProtoNick:=GetContactNick(0,ppAccounts^^.szModuleName,false);
+ inc(ProtoCount);
+ end;
+ end;
+ inc(ppAccounts);
+ end;
+ SetLength(Protocols,ProtoCount);
+end;
+
+function fIsMirandaUnicode:boolean;
+var ver:ShortString;
+begin
+ Result:=true;
+ SetLength(ver,255);
+ if PluginLink.CallService(MS_SYSTEM_GETVERSIONTEXT,wParam(255),lParam(@ver[1]))=0 then
+ Result:=Pos('Unicode',ver)>0;
+end;
+
+function GetContactProto(hContact: THandle): String;
+begin
+ Result := PChar(PluginLink.CallService(MS_PROTO_GETCONTACTBASEPROTO,hContact,0));
+end;
+
+function DBFreeVariant(dbv:PDBVARIANT):integer;
+begin
+ Result:=PluginLink^.CallService(MS_DB_CONTACT_FREEVARIANT,0,lParam(dbv));
+end;
+
+function GetContactID(hContact: THandle; Proto: String = ''; Contact: boolean = false): String;
+var
+ uid: PChar;
+ dbv: TDBVARIANT;
+ cgs: TDBCONTACTGETSETTING;
+ tempstr:PChar;
+begin
+ Result := '';
+ if not ((hContact = 0) and Contact) then begin
+ if Proto = '' then Proto := GetContactProto(hContact);
+ uid := PChar(CallProtoService(PChar(Proto),PS_GETCAPS,PFLAG_UNIQUEIDSETTING,0));
+ if (Cardinal(uid) <> CALLSERVICE_NOTFOUND) and (uid <> nil) then begin
+ cgs.szModule := PChar(Proto);
+ cgs.szSetting := uid;
+ cgs.pValue := @dbv;
+ if PluginLink^.CallService(MS_DB_CONTACT_GETSETTING,hContact,LPARAM(@cgs)) = 0 then begin
+ case dbv._type of
+ DBVT_BYTE:
+ Result := intToStr(dbv.bVal);
+ DBVT_WORD:
+ Result := intToStr(dbv.wVal);
+ DBVT_DWORD:
+ Result := intToStr(dbv.dVal);
+ DBVT_ASCIIZ:
+ if IsMirandaUnicode then
+ begin
+ tempstr:=ANSIToUTF8(dbv.szVal.a,tempstr,cp);
+ Result :=tempstr;
+ FreeMem(tempstr);
+ end else Result := dbv.szVal.a;
+ DBVT_UTF8:
+ if IsMirandaUnicode then Result :=dbv.szVal.a
+ else
+ begin
+ tempstr:=UTF8ToANSI(dbv.szVal.a,tempstr,cp);
+ Result :=tempstr;
+ FreeMem(tempstr);
+ end;
+ DBVT_WCHAR:
+ begin
+ if IsMirandaUnicode then tempstr:=WideToUTF8(dbv.szVal.w,tempstr)
+ else tempstr:=WideToAnsi(dbv.szVal.w,tempstr,cp);
+ Result:=tempstr;
+ FreeMem(tempstr);
+ end;
+ end;
+ // free variant
+ DBFreeVariant(@dbv);
+ end;
+ end;
+ end;
+end;
+
+function GetContactNick(hContact: THandle; Proto: String = ''; Contact: boolean = false): String;
+var
+ dbv: TDBVARIANT;
+ cgs: TDBCONTACTGETSETTING;
+ tempstr:PChar;
+begin
+ Result := '';
+ if not ((hContact = 0) and Contact) then begin
+ if Proto = '' then Proto := GetContactProto(hContact);
+ cgs.szModule := PChar(Proto);
+ cgs.szSetting := 'Nick';
+ cgs.pValue := @dbv;
+ if PluginLink^.CallService(MS_DB_CONTACT_GETSETTING,hContact,LPARAM(@cgs)) = 0 then begin
+ case dbv._type of
+ DBVT_BYTE:
+ Result := intToStr(dbv.bVal);
+ DBVT_WORD:
+ Result := intToStr(dbv.wVal);
+ DBVT_DWORD:
+ Result := intToStr(dbv.dVal);
+ DBVT_ASCIIZ:
+ if IsMirandaUnicode then
+ begin
+ tempstr:=ANSIToUTF8(dbv.szVal.a,tempstr,cp);
+ Result :=tempstr;
+ FreeMem(tempstr);
+ end else Result := dbv.szVal.a;
+ DBVT_UTF8:
+ if IsMirandaUnicode then Result :=dbv.szVal.a
+ else
+ begin
+ tempstr:=UTF8ToANSI(dbv.szVal.a,tempstr,cp);
+ Result :=tempstr;
+ FreeMem(tempstr);
+ end;
+ DBVT_WCHAR:
+ begin
+ if IsMirandaUnicode then tempstr:=WideToUTF8(dbv.szVal.w,tempstr)
+ else tempstr:=WideToAnsi(dbv.szVal.w,tempstr,cp);
+ Result:=tempstr;
+ FreeMem(tempstr);
+ end;
+ end;
+ // free variant
+ DBFreeVariant(@dbv);
+ end;
+ end;
+end;
+
+function DBReadByte(hContact:THANDLE;szModule:PChar;szSetting:PChar;default:byte=0):byte;
+var
+ dbv:TDBVARIANT;
+ cgs:TDBCONTACTGETSETTING;
+begin
+ cgs.szModule :=szModule;
+ cgs.szSetting:=szSetting;
+ cgs.pValue :=@dbv;
+ If PluginLink^.CallService(MS_DB_CONTACT_GETSETTING,hContact,lParam(@cgs))<>0 then
+ Result:=default
+ else
+ Result:=dbv.bVal;
+end;
+
+function DBWriteByte(hContact:THANDLE;szModule:PChar;szSetting:PChar;val:Byte):Integer;
+var
+ cws:TDBCONTACTWRITESETTING;
+begin
+ cws.szModule :=szModule;
+ cws.szSetting :=szSetting;
+ cws.value._type:=DBVT_BYTE;
+ cws.value.bVal :=Val;
+ Result:=PluginLink^.CallService(MS_DB_CONTACT_WRITESETTING,hContact,lParam(@cws));
+end;
+
+procedure SetLastPattern(lp:byte);
+begin
+ DBWriteByte(0,IMPORT_TXT_MODULE,IMPORT_TXT_LP,lp);
+end;
+
+function GetLastPattern:byte;
+begin
+ result:=DBReadByte(0,IMPORT_TXT_MODULE,IMPORT_TXT_LP,0);
+ if result>=PatternsCount then result:=0;
+end;
+
+function TimeStampToWStr(ts:dword):WideString;
+var dbtts:TDBTIMETOSTRING;
+ s:WideString;
+begin
+ SetLength(s,20);
+ dbtts.szFormat.w:='d s';
+ dbtts.szDest.w:=PWideChar(s);
+ dbtts.cbDest:=20;
+ pluginlink^.CallService(MS_DB_TIME_TIMESTAMPTOSTRINGT,ts,Int(@dbtts));
+ result:=s;
+end;
+
+function StrToTimeStamp(STime:PChar;len:integer):dword;
+var hour, min, sec, day, month, year: integer;
+begin
+ sec:=0;
+ day:=(ord(stime[0])-$30)*10+(ord(stime[1])-$30);
+ month:=(ord(stime[3])-$30)*10+(ord(stime[4])-$30);
+ year:=(ord(stime[6])-$30)*1000+(ord(stime[7])-$30)*100+(ord(stime[8])-$30)*10+(ord(stime[9])-$30);
+ hour:=(ord(stime[11])-$30)*10+(ord(stime[12])-$30);
+ min:=(ord(stime[14])-$30)*10+(ord(stime[15])-$30);
+ if len>15 then sec:=(ord(stime[17])-$30)*10+(ord(stime[18])-$30);
+ result:=Timestamp(year,month,day,hour,min,sec);
+end;
+
+function RLWord(adr:integer):word;
+begin
+ Result:=PByte(adr+1)^ + (PByte(adr)^ *$100);
+end;
+
+function RLInteger(adr:integer):integer;
+begin
+ Result:=PByte(adr+3)^ + (PByte(adr+2)^*$100) +
+ (PByte(adr+1)^ * $10000) + (PByte(adr)^ *$1000000);
+end;
+
+begin
+ GetModuleFileName(hInstance,@AppPath[0],MAX_PATH);
+ ExtractFilePath(AppPath);
+ ReadPatterns;
+end.
diff --git a/plugins/ImportTXT/ImpDlgRes.inc b/plugins/ImportTXT/ImpDlgRes.inc
new file mode 100644
index 0000000000..b176adb9a5
--- /dev/null
+++ b/plugins/ImportTXT/ImpDlgRes.inc
@@ -0,0 +1,12 @@
+const
+ IDD_IMPDIALOG = 101;
+ IDSTART = 1001;
+ IDC_FILENAME = 1002;
+ IDC_BRWSBTN = 1003;
+ IDC_TYPECOMBO = 1004;
+ IDC_STATUSLIST = 1005;
+ IDC_PROGRESS = 1006;
+ IDC_CHKDUP = 1007;
+ IDC_SHOWDUP = 1008;
+
+ IDI_DEFAULT = 110; \ No newline at end of file
diff --git a/plugins/ImportTXT/ImpTxtDlg.rc b/plugins/ImportTXT/ImpTxtDlg.rc
new file mode 100644
index 0000000000..e1f3b19b74
--- /dev/null
+++ b/plugins/ImportTXT/ImpTxtDlg.rc
@@ -0,0 +1,18 @@
+101 DIALOGEX 0, 0, 264, 220
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Import history to "
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+FONT 8, "MS Shell Dlg"
+BEGIN
+ PUSHBUTTON "Start",1001,2,204,50,14
+ PUSHBUTTON "Close",IDCLOSE,211,204,50,14
+ LTEXT "Choose a file...",1002,3,3,240,11,SS_SUNKEN
+ PUSHBUTTON "...",1003,244,3,17,11
+ COMBOBOX 1004,3,16,258,80,CBS_DROPDOWNLIST | CBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP
+ LISTBOX 1005,3,42,258,150,LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_VSCROLL | WS_TABSTOP
+ CONTROL "",1006,"msctls_progress32",0x1,3,194,258,8
+ CHECKBOX "Check for duplicates", 1007, 3, 29, 105, 12, BS_AUTOCHECKBOX | WS_VISIBLE | WS_TABSTOP
+ CHECKBOX "Show duplicates", 1008, 140, 29, 86, 12, BS_AUTOCHECKBOX | WS_VISIBLE | WS_TABSTOP
+END
+
+110 ICON "ico\def_ico.ico" \ No newline at end of file
diff --git a/plugins/ImportTXT/ImpTxtDlg.res b/plugins/ImportTXT/ImpTxtDlg.res
new file mode 100644
index 0000000000..9feb9a0abe
--- /dev/null
+++ b/plugins/ImportTXT/ImpTxtDlg.res
Binary files differ
diff --git a/plugins/ImportTXT/ImpTxtWiz.rc b/plugins/ImportTXT/ImpTxtWiz.rc
new file mode 100644
index 0000000000..617c23af55
--- /dev/null
+++ b/plugins/ImportTXT/ImpTxtWiz.rc
@@ -0,0 +1,64 @@
+
+102 DIALOGEX 0, 0, 220, 143
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CAPTION | WS_SYSMENU
+CAPTION "Import Text Files Wizard"
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+FONT 8, "MS Shell Dlg"
+BEGIN
+ DEFPUSHBUTTON "&Next >",IDOK,120,124,45,13
+ PUSHBUTTON "Cancel",IDCANCEL,168,124,45,13
+ PUSHBUTTON "< &Back",3,75,124,45,13
+ CONTROL "",1011,"Static",SS_ETCHEDHORZ,5,116,210,1
+END
+
+103 DIALOGEX 0, 0, 220, 114
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "This wizard will help you import message history from some other clients and Miranda plugins, stored in text files.",1010,18,12,182,32
+ LTEXT "Click ""Next"" to choose the information you wish to import, or click ""Cancel"" to exit the wizard and continue using Miranda.",1009,18,42,182,25
+ CTEXT "It is recommended that you create a backup of your current Miranda profile before importing.",1008,18,78,182,21
+END
+
+104 DIALOGEX 0, 0, 220, 114
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Choose type of imported files:",1010,6,76,208,8
+ COMBOBOX 1007,5,90,208,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+END
+
+105 DIALOGEX 0, 0, 220, 114
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Select files or the whole directory for import:",1010,6,86,208,8
+ LISTBOX 1002,5,12,208,55,LBS_SORT | LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Files...",1001,157,96,56,14
+ LTEXT "Path:",1009,6,73,24,8
+ EDITTEXT 1003,31,71,182,12,ES_AUTOHSCROLL | WS_DISABLED
+ LTEXT "Files:",1008,6,3,208,8
+ PUSHBUTTON "Directory...",1005,101,96,56,14
+END
+
+106 DIALOGEX 0, 0, 220, 114
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CHECKBOX "Check messages for duplicates", 1012, 6, 20, 140, 14, BS_AUTOCHECKBOX | WS_VISIBLE | WS_TABSTOP
+ CHECKBOX "Show duplicates", 1013, 6, 32, 86, 14, BS_AUTOCHECKBOX | WS_VISIBLE | WS_TABSTOP
+ LTEXT "All previous chosen files will try to import to this protocol.", 1010, 6, 46, 208, 10
+ COMBOBOX 1007,5,66,208,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Select protocol or account:",1009,6,55,208,8
+ CTEXT "Click ""Next"" to start Import or ""Cancel"" to Abort.",1008,6,96,208,8
+END
+
+107 DIALOGEX 0, 0, 220, 114
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Now importing...",1010,6,11,208,8
+ CONTROL "Progress1",1004,"msctls_progress32",WS_BORDER | 0x1,5,24,208,10
+ LISTBOX 1006,5,38,208,61,NOT LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | LBS_NOSEL | WS_VSCROLL | WS_TABSTOP
+END
+
diff --git a/plugins/ImportTXT/ImpTxtWiz.res b/plugins/ImportTXT/ImpTxtWiz.res
new file mode 100644
index 0000000000..2164f8ebd1
--- /dev/null
+++ b/plugins/ImportTXT/ImpTxtWiz.res
Binary files differ
diff --git a/plugins/ImportTXT/ImpTxt_Ver.rc b/plugins/ImportTXT/ImpTxt_Ver.rc
new file mode 100644
index 0000000000..df41863127
--- /dev/null
+++ b/plugins/ImportTXT/ImpTxt_Ver.rc
@@ -0,0 +1,28 @@
+1 VERSIONINFO
+FILEVERSION 0,0,1,10
+PRODUCTVERSION 0,0,1,10
+FILEOS 0x4
+FILETYPE 0x2
+{
+BLOCK "StringFileInfo"
+{
+ BLOCK "000004b0"
+ {
+ VALUE "CompanyName", "Miranda Open Source Project"
+ VALUE "FileDescription", "ImportTXT plugin for Miranda IM"
+ VALUE "FileVersion", "0.0.1.10"
+ VALUE "InternalName", "importtxt"
+ VALUE "LegalCopyright", "© 2008 Abyss"
+ VALUE "LegalTrademarks", "Gnu General Public License V2"
+ VALUE "OriginalFilename", "importtxt.dll"
+ VALUE "ProductName", "Import TXT Module"
+ VALUE "ProductVersion", "0.0.1.10"
+ VALUE "Comments", "Imports history saved in TXT files from other clients"
+ }
+}
+
+BLOCK "VarFileInfo"
+{
+ VALUE "Translation", 0x0000 0x04B0
+}
+}
diff --git a/plugins/ImportTXT/ImpTxt_Ver.res b/plugins/ImportTXT/ImpTxt_Ver.res
new file mode 100644
index 0000000000..3a97a1125f
--- /dev/null
+++ b/plugins/ImportTXT/ImpTxt_Ver.res
Binary files differ
diff --git a/plugins/ImportTXT/ImpWizRes.inc b/plugins/ImportTXT/ImpWizRes.inc
new file mode 100644
index 0000000000..a60bba6a54
--- /dev/null
+++ b/plugins/ImportTXT/ImpWizRes.inc
@@ -0,0 +1,21 @@
+const
+ IDC_BACK = 3;
+ IDD_IMPWIZARD = 102;
+ IDD_IMPWIZARDINTRO = 103;
+ IDD_IMPTYPE = 104;
+ IDD_IMPFILES = 105;
+ IDD_IMPDEST = 106;
+ IDD_PROGRESS = 107;
+ IDC_FILE = 1001;
+ IDC_LIST = 1002;
+ IDC_PATH = 1003;
+ IDC_PROGRESS = 1004;
+ IDC_DIR = 1005;
+ IDC_STATUS = 1006;
+ IDC_COMBO1 = 1007;
+ IDC_STATIC3 = 1008;
+ IDC_STATIC2 = 1009;
+ IDC_STATIC1 = 1010;
+ IDC_STATIC = 1011;
+ IDC_CHKDUPW = 1012;
+ IDC_SHOWDUPW = 1013;
diff --git a/plugins/ImportTXT/ImportT.pas b/plugins/ImportTXT/ImportT.pas
new file mode 100644
index 0000000000..4976d2cc39
--- /dev/null
+++ b/plugins/ImportTXT/ImportT.pas
@@ -0,0 +1,82 @@
+unit ImportT;
+interface
+
+type
+
+ RHeader = record
+ Pattern:string;
+ Incoming:integer;
+ Outgoing:integer;
+ InNick:integer;
+ OutNick:integer;
+ InUID:integer;
+ OutUID:integer;
+ end;
+
+ RPreMessage = record
+ PreRN:integer;
+ AfterRN:integer;
+ PreSP:integer;
+ AfterSP:integer;
+ end;
+
+ RMessage = record
+ Pattern:string;
+ Incoming:string;
+ Outgoing:string;
+ Direction:integer;
+ Day:integer;
+ Month:integer;
+ Year:integer;
+ Hours:integer;
+ Minutes:integer;
+ Seconds:integer;
+ end;
+
+ RFileName = record
+ Pattern:string;
+ InNick:integer;
+ OutNick:integer;
+ InUID:integer;
+ OutUID:integer;
+ end;
+
+ RTxtPattern = record
+ Name:string;
+ IType:byte; //1 -text,2- binary, 3 - ...
+ Charset:word;
+ Codepage:Cardinal;
+ DefExtension:string;
+ BinProc:word;
+ UseHeader:Byte;
+ UseFileName:ByteBool;
+ UsePreMsg:ByteBool;
+ Msg:RMessage;
+ Header:RHeader;
+ PreMsg:RPreMessage;
+ FName:RFileName;
+ end;
+
+const
+ inANSI = 1;
+ inUTF8 = 2;
+ inUCS2 = 3;
+
+type PDestProto = ^TDestProto;
+ TDestProto = record
+ ProtoName: string;
+ ProtoUID: string;
+ ProtoNick: string;
+ end;
+
+type PDestContact = ^TDestContact;
+ TDestContact = record
+ hContact: THandle;
+ ProtoName: string;
+ ContactUID: string;
+ ContactNick: string;
+ end;
+
+implementation
+
+end.
diff --git a/plugins/ImportTXT/ImportTU.pas b/plugins/ImportTXT/ImportTU.pas
new file mode 100644
index 0000000000..1ef7bdd4c3
--- /dev/null
+++ b/plugins/ImportTXT/ImportTU.pas
@@ -0,0 +1,260 @@
+Unit ImportTU;
+
+interface
+
+Uses windows, StrUtils,
+ m_api;
+
+type
+ PDayTable = ^TDayTable;
+ TDayTable = array[1..12] of Word;
+
+const
+ MonthDays: array [Boolean] of TDayTable =
+ ((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
+ (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));
+
+function Timestamp(Year,Month,Day,Hour,Min,Sec:Word; toGMT:boolean = true):LongWord;
+{function TimestampICQ(Year,Month,Day,Hour,Min,Sec:Word):LongWord;}
+function DateTimeToTimeStamp(const DateTime: TDateTime; toGMT: boolean = true): DWord;
+
+
+
+{***** Authtor of this procedures Alexey Kulakov aka Awkward*****}
+function ChangeUnicode(str:PWideChar):PWideChar;
+function UTF8Len(src:PChar):integer;
+function WideToANSI(src:PWideChar;var dst:PChar ;cp:dword=CP_ACP):PChar;
+function ANSIToWide(src:PChar ;var dst:PWideChar;cp:dword=CP_ACP):PWideChar;
+function ANSIToUTF8(src:PChar ;var dst:pChar ;cp:dword=CP_ACP):PChar;
+function UTF8toANSI(src:PChar ;var dst:PChar ;cp:dword=CP_ACP):PChar;
+function UTF8toWide(src:PChar ;var dst:PWideChar;len:cardinal=dword(-1)):PWideChar;
+function WidetoUTF8(src:PWideChar;var dst:PChar ):PChar;
+{*****}
+
+
+implementation
+
+uses SysUtils;
+
+function IsLeapYear(Year:Word):Boolean;
+begin
+ Result:=(Year mod 4=0) and ((Year mod 100<>0) or (Year mod 400=0));
+end;
+
+function Timestamp(Year,Month,Day,Hour,Min,Sec:Word; toGMT: boolean = true):LongWord;
+var i:Integer;
+ DayTable:PDayTable;
+ DT,D:Longword;
+begin
+ //fix for 2 digit year
+ if year>0 then
+ if year<90 then inc(year,2000)
+ else
+ if year <100 then inc(year,1900);
+ //
+ DayTable:=@MonthDays[IsLeapYear(Year)];
+ for i:=1 to Month-1 do Inc(Day,DayTable^[i]);
+ I := Year - 1;
+ D := I * 365 + I div 4 - I div 100 + I div 400 + Day - (1969*365 + 492 - 19 + 4 +1);
+ DT:= (D*24*60*60) + (Hour*3600+Min*60+Sec);
+ //Приводим к GMT...судя по всему миранда хранит таймштампы в GMT
+ if toGMT then Result := DT -(PluginLink.CallService(MS_DB_TIME_TIMESTAMPTOLOCAL,DT,0)-DT)
+ else Result := DT;
+end;
+
+function DateTimeToTimeStamp(const DateTime: TDateTime; toGMT: boolean = true): DWord;
+begin
+ Result := Round((DateTime-UnixDateDelta) * SecsPerDay);
+ if toGMT then Result := Result -(PluginLink.CallService(MS_DB_TIME_TIMESTAMPTOLOCAL,Result,0)-Result);
+end;
+
+function ChangeUnicode(str:PWideChar):PWideChar;
+var
+ i,len:integer;
+begin
+ result:=str;
+ if str=nil then
+ exit;
+ if (word(str^)=$FFFE) or (word(str^)=$FEFF) then
+ begin
+ len:=lstrlenw(str);
+ if word(str^)=$FFFE then
+ begin
+ i:=len-1;
+ while i>0 do // str^<>#0
+ begin
+ pword(str)^:=swap(pword(str)^);
+ inc(str);
+ dec(i);
+ end;
+// str:=result;
+ end;
+ move((result+1)^,result^,len*SizeOf(WideChar));
+ end;
+end;
+
+function WideToANSI(src:PWideChar;var dst:PChar; cp:dword=CP_ACP):PChar;
+var
+ len,l:integer;
+begin
+ if (src=nil) or (src^=#0) then
+ begin
+ GetMem(dst,1);
+ dst^:=#0;
+ end
+ else
+ begin
+ l:=lstrlenw(src);
+ len:=WideCharToMultiByte(cp,0,src,l,NIL,0,NIL,NIL)+1;
+ GetMem(dst,len);
+ FillChar(dst^,len,0);
+ WideCharToMultiByte(cp,0,src,l,dst,len,NIL,NIL);
+ end;
+ result:=dst;
+end;
+
+function ANSIToWide(src:PChar;var dst:PWideChar; cp:dword=CP_ACP):PWideChar;
+var
+ len,l:integer;
+begin
+ if (src=nil) or (src^=#0) then
+ begin
+ GetMem(dst,SizeOf(WideChar));
+ dst^:=#0;
+ end
+ else
+ begin
+ l:=lstrlen(src);
+ len:=MultiByteToWideChar(cp,0,src,l,NIL,0)+1;
+ GetMem(dst,len*SizeOf(WideChar));
+ FillChar(dst^,len*SizeOf(WideChar),0);
+ MultiByteToWideChar(cp,0,src,l,dst,len);
+ end;
+ result:=dst;
+end;
+
+function ANSIToUTF8(src:PChar;var dst:pChar;cp:dword=CP_ACP):PChar;
+var
+ tmp:PWideChar;
+begin
+ AnsiToWide(src,tmp,cp);
+ result:=WideToUTF8(tmp,dst);
+ FreeMem(tmp);
+end;
+
+function UTF8Len(src:PChar):integer; // w/o zero
+begin
+ result:=0;
+ if src<>nil then
+ begin
+ while src^<>#0 do
+ begin
+ if (ord(src^) and $80)=0 then
+ else if (ord(src^) and $E0)=$E0 then
+ inc(src,2)
+ else
+ inc(src);
+ inc(result);
+ inc(src);
+ end;
+ end;
+end;
+
+function CalcUTF8Len(src:pWideChar):integer;
+begin
+ result:=0;
+ if src<>nil then
+ begin
+ while src^<>#0 do
+ begin
+ if src^<#$0080 then
+ else if src^<#$0800 then
+ inc(result)
+ else
+ inc(result,2);
+ inc(src);
+ inc(result);
+ end;
+ end;
+end;
+
+function UTF8toWide(src:PChar; var dst:PWideChar; len:cardinal=dword(-1)):PWideChar;
+var
+ w:word;
+ p:PWideChar;
+begin
+ GetMem(dst,(UTF8Len(src)+1)*SizeOf(WideChar));
+ p:=dst;
+ if src<>nil then
+ begin
+ while (src^<>#0) and (len>0) do
+ begin
+ if ord(src^)<$80 then
+ w:=ord(src^)
+ else if (ord(src^) and $E0)=$E0 then
+ begin
+ w:=(ord(src^) and $1F) shl 12;
+ inc(src); dec(len);
+ w:=w or (((ord(src^))and $3F) shl 6);
+ inc(src); dec(len);
+ w:=w or (ord(src^) and $3F);
+ end
+ else
+ begin
+ w:=(ord(src^) and $3F) shl 6;
+ inc(src); dec(len);
+ w:=w or (ord(src^) and $3F);
+ end;
+ p^:=WideChar(w);
+ inc(p);
+ inc(src); dec(len);
+ end;
+ end;
+ p^:=#0;
+ result:=dst;
+end;
+
+function UTF8toANSI(src:PChar;var dst:PChar;cp:dword=CP_ACP):PChar;
+var
+ tmp:pWideChar;
+begin
+ UTF8ToWide(src,tmp);
+ result:=WideToAnsi(tmp,dst,cp);
+ FreeMem(tmp);
+end;
+
+function WidetoUTF8(src:PWideChar; var dst:PChar):PChar;
+var
+ p:PChar;
+begin
+ GetMem(dst,CalcUTF8Len(src)+1);
+ p:=dst;
+ if src<>nil then
+ begin
+ while src^<>#0 do
+ begin
+ if src^<#$0080 then
+ p^:=Char(src^)
+ else if src^<#$0800 then
+ begin
+ p^:=chr($C0 or (ord(src^) shr 6));
+ inc(p);
+ p^:=chr($80 or (ord(src^) and $3F));
+ end
+ else
+ begin
+ p^:=chr($E0 or (ord(src^) shr 12));
+ inc(p);
+ p^:=chr($80 or ((ord(src^) shr 6) and $3F));
+ inc(p);
+ p^:=chr($80 or (ord(src^) and $3F));
+ end;
+ inc(p);
+ inc(src);
+ end;
+ end;
+ p^:=#0;
+ result:=dst;
+end;
+
+end.
diff --git a/plugins/ImportTXT/ImportThrd.pas b/plugins/ImportTXT/ImportThrd.pas
new file mode 100644
index 0000000000..4da1eae5b0
--- /dev/null
+++ b/plugins/ImportTXT/ImportThrd.pas
@@ -0,0 +1,599 @@
+unit ImportThrd;
+
+interface
+
+uses
+ Classes,
+ Windows,
+ SysUtils,
+ StrUtils,
+ PerlRegEx,
+ m_api,
+ general,
+ ImportT,
+ ImportTU,
+ KOLEdb
+ ;
+
+
+
+const ITXT_THREAD_BASE = $8000+$2000;//WM_APP + $2000
+ ITXT_THREAD_START = ITXT_THREAD_BASE+1; //Поток запустился (0,0)
+ ITXT_THREAD_MAXPROGRESS = ITXT_THREAD_BASE+2; // Мах прогресс (0, MaxProgress)
+ ITXT_THREAD_PROGRESS = ITXT_THREAD_BASE+3; //Прогресс (Current, 0)
+ ITXT_THREAD_ERROR = ITXT_THREAD_BASE+4; //Возникла ошибка (PWideChar(ErrorString),0)
+ ITXT_THREAD_FINISH = ITXT_THREAD_BASE+5; //Завершение файла, подведение результатов (Added, Duplicates)
+ ITXT_THREAD_START_FILE = ITXT_THREAD_BASE+6; //Начали работать с файлом(PWideChar(FileName),0);
+ ITXT_THREAD_DEST_CONTACT = ITXT_THREAD_BASE+7; //Определили контакт (hContact,0)
+ ITXT_THREAD_ALLSTARTED = ITXT_THREAD_BASE+8; //Началось
+ ITXT_THREAD_ALLFINISHED = ITXT_THREAD_BASE+9; //Всё закончено :)
+
+type
+ TSendMethod = (smSend,smPost);
+
+type
+ TImportThrd = class(TThread)
+ private
+ { Private declarations }
+ RegExpr:TPerlRegEx;
+ hMapedFile:THandle;
+ hFile:THandle;
+ pFileText:Pointer;
+ FolderName:WideString;
+ FileName:WideString;
+ FileLen:Cardinal;
+ fContact:TDestContact; //Contact recognised by filename
+ AddedMessages: integer;
+ Duplicates: integer;
+ function DoMessage(Message: Longword; wParam: WPARAM; lParam: LPARAM; Method: TSendMethod = smSend): Boolean;
+ function DoMapFile:boolean;
+ procedure DoUnMapFile;
+ Procedure PreMessageSP(var src:string; CSP:integer);
+ procedure AddMsgToDB(hContact:Thandle; Direction:integer; MsgTimeStamp:LongWord; const Text: string;
+ var AddMsg,Dupy:integer);
+ procedure TextImportProcedure;
+ procedure BinImportProcedure;
+ protected
+ procedure Execute; override;
+ public
+ FileNames:WideString; //File Names
+ OffsetFileName:integer; //offset name of file in FileNames
+ WorkPattern:RTxtPattern; // Pattern for work
+ DContact:TDestContact; //Recognised or defined contact
+ Destination:TDestProto; // destination protocol
+ ParentHWND:LongWord; //HWND of parent window
+ end;
+
+
+function IsDuplicateEvent(hContact:THandle; dbei:TDBEVENTINFO):boolean;
+
+function PassMessage(Handle: THandle; Message: LongWord; wParam: WPARAM; lParam: LPARAM; Method: TSendMethod = smSend): Boolean;
+
+
+implementation
+
+
+// Returns TRUE if event already is in base
+function IsDuplicateEvent(hContact:THandle; dbei:TDBEVENTINFO):boolean;
+var
+ hExistingDbEvent:THandle;
+ dbeiExisting:TDBEVENTINFO;
+ dwFirstEventTimeStamp:LongWord;
+ dwLastEventTimeStamp:LongWord;
+ dwPreviousTimeStamp:LongWord;
+begin
+ result:=FALSE;
+ if not CheckForDuplicates then exit;
+ hExistingDbEvent:=pluginLink^.CallService(MS_DB_EVENT_FINDFIRST, hContact, 0);
+ if hExistingDbEvent=0 then begin Result:=False; exit; end;
+
+ FillChar(dbeiExisting, SizeOf(dbeiExisting), Byte(0));
+ dbeiExisting.cbSize:= sizeof(dbeiExisting);
+ dbeiExisting.cbBlob:= 0;
+ pluginLink^.CallService(MS_DB_EVENT_GET, wParam(hExistingDbEvent), lParam(@dbeiExisting));
+ dwFirstEventTimeStamp:=dbeiExisting.timestamp;
+
+ hExistingDbEvent:=pluginLink^.CallService(MS_DB_EVENT_FINDLAST, wParam(hContact), lParam(0));
+ if hExistingDbEvent=0 then begin Result:=False; exit; end;
+
+ FillChar(dbeiExisting, SizeOf(dbeiExisting), Byte(0));
+ dbeiExisting.cbSize:= sizeof(dbeiExisting);
+ dbeiExisting.cbBlob:= 0;
+ pluginLink^.CallService(MS_DB_EVENT_GET, wParam(hExistingDbEvent), lParam(@dbeiExisting));
+ dwLastEventTimeStamp:=dbeiExisting.timestamp;
+
+ // If before the first
+ if (dbei.timestamp < dwFirstEventTimeStamp) then begin Result:=False; exit; end;
+
+ // If after the last
+ if (dbei.timestamp > dwLastEventTimeStamp) then begin Result:=False; exit; end;
+
+ dwPreviousTimeStamp:=dwLastEventTimeStamp;
+
+ if (dbei.timestamp <= dwPreviousTimeStamp) then // search from the end
+ begin
+ while (hExistingDbEvent <> 0) do
+ begin
+ FillChar(dbeiExisting, SizeOf(dbeiExisting), Byte(0));
+ dbeiExisting.cbSize:= sizeof(dbeiExisting);
+ dbeiExisting.cbBlob:= 0;
+ pluginLink^.CallService(MS_DB_EVENT_GET, wParam(hExistingDbEvent), lParam(@dbeiExisting));
+ // compare event
+ if ( dbei.timestamp = dbeiExisting.timestamp ) and
+ ( (dbei.flags) = (dbeiExisting.flags and not DBEF_FIRST)) and //fix for first event
+ (dbei.eventType = dbeiExisting.eventType) and
+ (dbei.cbBlob = dbeiExisting.cbBlob) then begin Result:=true; exit; end;
+
+ if (dbei.timestamp > dbeiExisting.timestamp) then begin Result:=False; exit; end;
+ // get the previous
+ hExistingDbEvent:=pluginLink^.CallService(MS_DB_EVENT_FINDPREV, wParam(hExistingDbEvent), 0);
+ end;
+ end;
+end;
+
+
+Procedure TImportThrd.PreMessageSP(var src:string; CSP:integer);
+var i:integer;
+ ls:integer;
+ PSP,ASP:integer;
+begin
+ ls:=-1;
+ repeat
+ i:=ls+2;
+ PSP:=0;
+ while (src[i+PSP]=' ') do inc(PSP);
+ if PSP>0 then
+ case WorkPattern.PreMsg.PreSP of
+ 0: PSP:=0;
+ -1: ;
+ -2: if PSP>CSP then PSP:=CSP;
+ else if PSP>WorkPattern.PreMsg.PreSP then PSP:=WorkPattern.PreMsg.PreSP;
+ end; //case
+ Delete(src,i,PSP);
+ ls:=PosEx(#$0D#$0A,src,i);
+ ASP:=0;
+ while (ls>1) and (src[ls-ASP-1]=' ') do inc(ASP);
+ if ASP>0 then
+ case WorkPattern.PreMsg.AfterSP of
+ 0: ASP:=0;
+ -1: ;
+ -2: if ASP>CSP then ASP:=CSP;
+ else if ASP>WorkPattern.PreMsg.AfterSP then ASP:=WorkPattern.PreMsg.AfterSP;
+ end; //case
+ Delete(src,ls-ASP-1,ASP);
+ Until ls<=0
+end;
+
+Procedure TImportThrd.AddMsgToDB(hContact:Thandle; Direction:integer;MsgTimeStamp:LongWord; const Text: string;
+ var AddMsg,Dupy:integer);
+var dbei:TDBEVENTINFO;
+ proto:string;
+ s:WideString;
+begin
+ FillChar(dbei, SizeOf(dbei), Byte(0));
+ dbei.cbSize:= sizeof(dbei);
+ dbei.eventType:= EVENTTYPE_MESSAGE;
+ dbei.flags:=direction;
+ proto:=GetContactProto(hContact);
+ dbei.szModule:= PAnsiChar(proto);
+ dbei.timestamp:=MsgTimeStamp;
+ dbei.cbBlob:=Length(Text)+1;
+ dbei.pBlob:=PByte(AllocMem(dbei.cbBlob));
+ try
+ Move(Text[1],dbei.pBlob^,dbei.cbBlob);
+ if not IsDuplicateEvent(hContact,dbei) then
+ if pluginLink^.CallService(MS_DB_EVENT_ADD, wParam(hContact), lParam(@dbei))<>0 then Inc(AddMsg)
+ else begin
+ s:= 'Error adding message to DB';
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0); end
+
+ else
+ begin
+ if ShowDuplicates then
+ begin
+ if (dbei.flags and DBEF_SENT)>0 then s:='>'
+ else s:='<';
+ s:=TranslateWideString('Duplicate:')+' '+s+' '+TimeStampToWStr(dbei.timestamp);
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0,smSend);
+ end;
+ Inc(Dupy);
+ end;
+ finally
+ FreeMem(dbei.pBlob);
+ end;
+end;
+
+function PassMessage(Handle: THandle; Message: LongWord; wParam: WPARAM; lParam: LPARAM; Method: TSendMethod = smSend): Boolean;
+var
+ Tries: integer;
+begin
+ Result := True;
+ case Method of
+ smSend: SendMessage(Handle,Message,wParam,lParam);
+ smPost: begin
+ Tries := 5;
+ while (Tries > 0) and not PostMessage(Handle,Message,wParam,lParam) do begin
+ Dec(Tries);
+ Sleep(5);
+ end;
+ Result := (Tries > 0);
+ end;
+ end;
+end;
+
+function TImportThrd.DoMessage(Message: LongWord; wParam: WPARAM; lParam: LPARAM; Method: TSendMethod = smSend): Boolean;
+begin
+ Result := PassMessage(ParentHWND,Message,wParam,lParam,Method);
+end;
+
+function TImportThrd.DoMapFile:boolean;
+var s:WideString;
+begin
+ result:=true;
+ hFile:=CreateFileW(PWideChar(FileName),GENERIC_READ,0,nil,OPEN_EXISTING,0,0);
+ if hFile=INVALID_HANDLE_VALUE then
+ begin
+ result:=false;
+ s:='Error opening file';
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ exit;
+ end;
+ FileLen:=GetFileSize(hFile,nil);
+ hMapedFile:=CreateFileMapping(hFile,nil,PAGE_READONLY,0,0,'ImportTXTmapfile');
+ if hMapedFile=0 then
+ begin
+ result:=false;
+ s:= 'Error mapping file';
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ exit;
+ end;
+ pFileText:=MapViewOfFile(hMapedFile,FILE_MAP_READ,0,0,0);
+ if pFileText=nil then
+ begin
+ result:=false;
+ s:='Error mapping';
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ exit;
+ end;
+end;
+
+procedure TImportThrd.DoUnMapFile;
+begin
+ UnmapViewOfFile(pFileText);
+ pFileText:=nil;
+ CloseHandle(hMapedFile);
+ CloseHandle(hFile);
+end;
+
+procedure TryDetermContact(var dContact:TDestContact);
+begin
+ if dContact.ProtoName<>'' then
+ begin
+ if dContact.ContactUID<>'' then
+ begin
+ dContact.hContact:=GetContactByUID(dContact.ProtoName,dContact.ContactUID)
+ end
+ else
+ if dContact.ContactNick<>'' then
+ begin
+ dContact.hContact:=GetContactByNick(dContact.ProtoName,dContact.ContactNick);
+ end
+ else
+ dContact.hContact:=INVALID_HANDLE_VALUE;
+ end
+ else
+ dContact.hContact:=INVALID_HANDLE_VALUE;
+end;
+
+procedure TImportThrd.TextImportProcedure;
+var
+ PosCur,LenCur,PosNext:integer;
+ TextLength,
+ h1,h2:integer;
+ PRN,ARN,j:DWORD;
+ msg_flag:integer;
+ DT:LongWord;
+ TxtMsg:string;
+ s:WideString;
+ tempstr:PChar;
+ tempwstr:PWideChar;
+begin
+ AddedMessages:=0;
+ Duplicates:=0;
+ Case WorkPattern.Charset of
+ inANSI:if IsMirandaUnicode then
+ begin
+ if WorkPattern.Codepage<>0 then tempstr:=ANSIToUTF8(PAnsiChar(pFileText),tempstr,WorkPattern.Codepage)
+ else tempstr:=ANSIToUTF8(PAnsiChar(pFileText),tempstr,cp);
+ RegExpr.Subject:=tempstr;
+ FreeMem(tempstr);
+ end
+ else RegExpr.Subject:=PAnsiChar(pFileText);
+ inUTF8:if IsMirandaUnicode then RegExpr.Subject:=PChar(pFileText)+3
+ else
+ begin
+ tempstr:=UTF8ToANSI(PChar(pFileText)+3,tempstr,cp);
+ RegExpr.Subject:=tempstr;
+ FreeMem(tempstr);
+ end;
+ inUCS2:begin
+ GetMem(tempwstr,FileLen+2);
+ lstrcpynW(tempwstr,PWideChar(pFileText),FileLen);
+ tempwstr[FileLen div SizeOf(WideChar)]:=#$0000; //file is not ended dy #0000
+ if IsMirandaUnicode then tempstr:=WidetoUTF8(ChangeUnicode(tempwstr),tempstr)
+ else tempstr:=WideToANSI(ChangeUnicode(tempwstr),tempstr,cp);
+ RegExpr.Subject:=tempstr;
+ FreeMem(tempstr);
+ FreeMem(tempwstr);
+ end;
+ end; //case
+ if (WorkPattern.UseHeader and 1)=0 then //If the information on a direction is not present that we will transform a line
+ begin
+ if IsMirandaUnicode then
+ begin
+ tempstr:=ANSIToUTF8(PAnsiChar(WorkPattern.Msg.Incoming),tempstr,cp);
+ WorkPattern.Msg.Incoming:=tempstr;
+ FreeMem(tempstr);
+ tempstr:=ANSIToUTF8(PAnsiChar(WorkPattern.Msg.Outgoing),tempstr,cp);
+ WorkPattern.Msg.Outgoing:=tempstr;
+ FreeMem(tempstr);
+ end
+ end;
+ if (WorkPattern.UseHeader>0) then
+ begin
+ if IsMirandaUnicode then
+ begin
+ tempstr:=ANSIToUTF8(PAnsiChar(WorkPattern.Header.Pattern),tempstr,cp);
+ RegExpr.RegEx:=tempstr;
+ RegExpr.Options:=[preMultiLine, preUTF8];
+ FreeMem(tempstr);
+ end
+ else
+ begin
+ RegExpr.RegEx:=WorkPattern.Header.Pattern;
+ RegExpr.Options:=[preMultiLine];
+ end;
+ if not RegExpr.Match then
+ begin
+ s:=TranslateWideString('Header not found');
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ exit;
+ end
+ else
+ begin
+ if (WorkPattern.UseHeader and 1)=1 then
+ begin
+ WorkPattern.Msg.Incoming:=RegExpr.SubExpressions[WorkPattern.Header.Incoming];
+ WorkPattern.Msg.Outgoing:=RegExpr.SubExpressions[WorkPattern.Header.Outgoing];
+ end;
+ if (WorkPattern.UseHeader and 2)=2 then
+ if (DContact.hContact=0) or (DContact.hContact=INVALID_HANDLE_VALUE) then
+ begin
+ if WorkPattern.Header.InUID<>0 then DContact.ContactUID:=RegExpr.SubExpressions[WorkPattern.Header.InUID]
+ else DContact.ContactUID:='';
+ if WorkPattern.Header.InNick<>0 then DContact.ContactNick:=RegExpr.SubExpressions[WorkPattern.Header.InNick]
+ else DContact.ContactNick:='';
+ TryDetermContact(DContact);
+ end;
+ end;
+ end;
+ //Whether if it has not turned out to define in header then we look it was defined in a file
+ if (DContact.hContact=0) or (DContact.hContact=INVALID_HANDLE_VALUE) then
+ if (fContact.hContact<>0) and (fContact.hContact<>INVALID_HANDLE_VALUE) then
+ DContact:=fContact;
+ if (DContact.hContact<>0) and (DContact.hContact<>INVALID_HANDLE_VALUE) then
+ begin
+ DoMessage(ITXT_THREAD_DEST_CONTACT,DContact.hContact,0);
+ DoMessage(ITXT_THREAD_START,0,0);
+ if IsMirandaUnicode then
+ begin
+ tempstr:=ANSIToUTF8(PAnsiChar(WorkPattern.Msg.Pattern),tempstr,cp);
+ RegExpr.RegEx:=tempstr;
+ RegExpr.Options:=[preMultiLine, preUTF8];
+ FreeMem(tempstr);
+ end
+ else
+ begin
+ RegExpr.RegEx:=WorkPattern.Msg.Pattern;
+ RegExpr.Options:=[preMultiLine];
+ end;
+
+ TextLength:=Length(RegExpr.Subject)-1; //Position of last symbol
+ DoMessage(ITXT_THREAD_MAXPROGRESS,0,TextLength);
+ RegExpr.State:=[preNotEmpty];
+ //search for regular expression
+ if not RegExpr.Match then
+ begin
+ s:=TranslateWideString('No messages in this file');
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ end
+ else
+ begin
+ PosCur:=RegExpr.MatchedExpressionOffset; //get the position of RegExpression
+ repeat
+ LenCur:=RegExpr.MatchedExpressionLength; //get the length of RegExpression
+ //Further we define a message direction (incoming or outgoing)
+ if RegExpr.SubExpressions[WorkPattern.Msg.Direction]=WorkPattern.Msg.Incoming then msg_flag:=DBEF_READ
+ else msg_flag:=DBEF_READ or DBEF_SENT;
+ if IsMirandaUnicode then msg_flag:=msg_flag or DBEF_UTF;
+ //make timestamp
+ if WorkPattern.Msg.Seconds<>0 then
+ DT:=TimeStamp(
+ StrToInt(RegExpr.SubExpressions[WorkPattern.Msg.Year]),
+ StrToInt(RegExpr.SubExpressions[WorkPattern.Msg.Month]),
+ StrToInt(RegExpr.SubExpressions[WorkPattern.Msg.Day]),
+ StrToInt(RegExpr.SubExpressions[WorkPattern.Msg.Hours]),
+ StrToInt(RegExpr.SubExpressions[WorkPattern.Msg.Minutes]),
+ StrToInt(RegExpr.SubExpressions[WorkPattern.Msg.Seconds])
+ ) else
+ DT:=TimeStamp(
+ StrToInt(RegExpr.SubExpressions[WorkPattern.Msg.Year]),
+ StrToInt(RegExpr.SubExpressions[WorkPattern.Msg.Month]),
+ StrToInt(RegExpr.SubExpressions[WorkPattern.Msg.Day]),
+ StrToInt(RegExpr.SubExpressions[WorkPattern.Msg.Hours]),
+ StrToInt(RegExpr.SubExpressions[WorkPattern.Msg.Minutes]),
+ 0
+ );
+
+ if RegExpr.MatchAgain then PosNext:=RegExpr.MatchedExpressionOffset //search for next regexpr
+ else PosNext:=TextLength; // if not then end of file
+ h1:=PosCur+LenCur; //The message text beginning presumably
+ h2:=PosNext-PosCur-LenCur-2; //its presumably message length
+ //working with message text
+ if WorkPattern.UsePreMsg then PRN:=DWORD(WorkPattern.PreMsg.PreRN)
+ else PRN:=DWORD(-1);
+ if PRN<>0 then
+ begin
+ j:=1;
+ while ((RegExpr.Subject[h1]=Char($0D))and
+ (RegExpr.Subject[h1+1]=Char($0A))) and
+ (j<=PRN)
+ do begin inc(h1,2); dec(h2,2); inc(j); end; //remove carriage return in the beginning
+ end;
+ if WorkPattern.UsePreMsg then ARN:=DWORD(WorkPattern.PreMsg.AfterRN)
+ else ARN:=DWORD(-1);
+ if ARN<>0 then
+ begin
+ j:=1;
+ while ((RegExpr.Subject[h1+h2]=Char($0D))and
+ (RegExpr.Subject[h1+h2+1]=Char($0A))) and
+ (j<=ARN)
+ do begin dec(h2,2); inc(j) end; //remove carriage return in the end
+ end;
+ //get the message text
+ TxtMsg:=Copy(RegExpr.Subject,h1,h2+2);
+ //remove spaces if needs
+ if WorkPattern.UsePreMsg and ((WorkPattern.PreMsg.PreSP<>0) or (WorkPattern.PreMsg.AfterSP<>0)) then
+ if IsMirandaUnicode then PreMessageSP(TxtMsg,UTF8Len(PChar(RegExpr.MatchedExpression)))
+ else PreMessageSP(TxtMsg,LenCur);
+ AddMsgToDB(DContact.hContact,msg_flag,DT,TxtMsg,AddedMessages,Duplicates); //adding in base
+ PosCur:=PosNext;
+ DoMessage(ITXT_THREAD_PROGRESS,PosCur,0);
+ until (PosNext = TextLength) or Terminated ;
+ end; //RegExpr.Exec
+ end
+ else
+ begin
+ s:=TranslateWideString('Can''t determine destination contact');
+ DoMessage(ITXT_THREAD_ERROR,integer(PWideChar(s)),0);
+ end;
+end;
+
+procedure TImportThrd.BinImportProcedure;
+var i:integer;
+ s:WideString;
+ tempstr:PChar;
+var dbei:TDBEVENTINFO;
+ proto:string;
+ pt:integer;
+ fsz:integer;
+
+{$define BIN_IMPORT_}
+{$i BmContactIP.inc}
+{$i BqhfIP.inc}
+{$i BICQ6IP.inc}
+{$i BICQ5IP.inc}
+{$i BRMSIP.inc}
+{$i BbayanIP.inc}
+{$undef BIN_IMPORT_}
+begin
+ AddedMessages:=0;
+ Duplicates:=0;
+ case WorkPattern.BinProc of
+ 1: //mContactImport
+ {$i BmContactIP.inc}
+ 2: //QHF
+ {$i BqhfIP.inc}
+ 3: //ICQ6
+ {$i BICQ6IP.inc}
+ 4: //ICQ5
+ {$i BICQ5IP.inc}
+ 5: //Nokia midp-rms
+ {$i BRMSIP.inc}
+ 6: //BayanICQ
+ {$i BbayanIP.inc}
+
+ end;
+end;
+
+procedure TImportThrd.Execute;
+var
+ i:integer;
+ s1:WideString;
+ tempstr:PChar;
+begin
+ DoMessage(ITXT_THREAD_ALLSTARTED,0,0);
+ FolderName:=Copy(FileNames,1,OffsetFileName-1);
+ i:=OffsetFileName;
+ while (FileNames[i+1]<>#0)and not Terminated do
+ begin //начало цикла по файлам
+ s1:='';
+ Inc(i);
+ while FileNames[i]<>#0 do
+ begin s1:=s1+FileNames[i]; inc(i); end;
+ if (s1<>'') and (s1<>#0) then
+ begin //Начинаем работать с файлом
+ FileName:=FolderName+'\'+s1;
+ DoMessage(ITXT_THREAD_START_FILE,Integer(PWideChar(FileName)),0,smSend);
+ pFileText:=nil;
+ hFile:=INVALID_HANDLE_VALUE;
+ DContact.ProtoName:=Destination.ProtoName;
+ fContact.hContact:=INVALID_HANDLE_VALUE;
+ RegExpr:=TPerlRegEx.Create; //Создаём объект для работы с рег. выражениями
+ try
+ //Поработаем с именем файла
+ if WorkPattern.UseFileName then
+ if (DContact.hContact=0) or (DContact.hContact=INVALID_HANDLE_VALUE) then
+ begin
+ if IsMirandaUnicode then
+ begin
+ tempstr:=WideToUTF8(PWideChar(FileName),tempstr);
+ RegExpr.Subject:=tempstr;
+ FreeMem(tempstr);
+ tempstr:=ANSIToUTF8(PAnsiChar(WorkPattern.FName.Pattern),tempstr,cp);
+ RegExpr.RegEx:=tempstr;
+ FreeMem(tempstr);
+ RegExpr.Options:=[preUTF8];
+ end
+ else
+ begin
+ RegExpr.Subject:=FileName;
+ RegExpr.RegEx:=WorkPattern.FName.Pattern;
+ RegExpr.Options:=[];
+ end;
+ if RegExpr.Match then
+ begin
+ fContact.ProtoName:=Destination.ProtoName;
+ if WorkPattern.FName.InUID<>0 then fContact.ContactUID:=RegExpr.SubExpressions[WorkPattern.FName.InUID]
+ else fContact.ContactUID:='';
+ if WorkPattern.FName.InNick<>0 then fContact.ContactNick:=RegExpr.SubExpressions[WorkPattern.FName.InNick]
+ else fContact.ContactNick:='';
+ TryDetermContact(fContact);
+ end;
+ end;
+
+ //Загружаем сам файл
+ // [preMultiLine] модификатор для восприятия многострочного текста
+ if DoMapFile then //Загружаем файл
+ begin
+ pluginLink^.CallService(MS_DB_SETSAFETYMODE, wParam(false), 0);
+ case WorkPattern.IType of
+ 1:TextImportProcedure;
+ 2:BinImportProcedure;
+ end; //case
+ end; //DoMapFile
+ finally
+ pluginLink^.CallService(MS_DB_SETSAFETYMODE, wParam(true), 0);
+ DoMessage(ITXT_THREAD_FINISH,AddedMessages,Duplicates);
+ DoUnMapFile;
+ RegExpr.Free;
+ end;
+ DContact.hContact:=INVALID_HANDLE_VALUE;
+ Sleep(10); //чтобы все сообщения дошли до окна
+ end; //закончили работать с файлом
+ end; //цикла по файлам
+ DoMessage(ITXT_THREAD_ALLFINISHED,0,0);
+end;
+
+end.
+ \ No newline at end of file
diff --git a/plugins/ImportTXT/ImportTxtWiz.pas b/plugins/ImportTXT/ImportTxtWiz.pas
new file mode 100644
index 0000000000..72c74b2386
--- /dev/null
+++ b/plugins/ImportTXT/ImportTxtWiz.pas
@@ -0,0 +1,369 @@
+unit ImportTxtWiz;
+
+interface
+
+uses Windows,Messages,SysUtils,
+ m_api,
+ general, ImportTU, FileDlgs,
+ ImportThrd
+ ;
+
+{$R ImpTxtWiz.res}
+{$I ImpWizRes.inc}
+
+const
+ WIZM_GOTOPAGE = (WM_USER+10); //wParam=resource id, lParam=dlgproc
+ WIZM_DISABLEBUTTON = (WM_USER+11); //wParam=0:back, 1:next, 2:cancel
+ WIZM_SETCANCELTEXT = (WM_USER+12); //lParam=(char*)newText
+ WIZM_SETNEXTTEXT = (WM_USER+13); //lParam=(char*)newText
+ WIZM_ENABLEBUTTON = (WM_USER+14); //wParam=0:back, 1:next, 2:cancel
+
+ WIZM_ACCLISTCHANGED = (WM_USER+15); //OnAccountListChanged
+
+var hwndPage:HWND;
+ IndexOfPattern:integer;
+ FileNames:array of WideString;
+ FileName:string;
+ nFO:integer;
+ FilePath:WideString;
+ ProtoSelect: integer;
+ ImportThrd:TImportThrd;
+ StartTime,FinishTime:TDateTime;
+
+function WizardIntroPageProc(hdlg:HWND; hMessage,wParam,lParam:DWORD):LongBool; stdcall;
+function ImportTypePageProc(hdlg:HWND; hMessage,wParam,lParam:DWORD):LongBool; stdcall;
+function WizardDlgProc(hdlg:HWND; hMessage,wParam,lParam:DWORD):LongBool; stdcall;
+function ImportFilesPageProc(hdlg:HWND; hMessage,wParam,lParam:DWORD):LongBool; stdcall;
+function ImportDestinationPageProc(hdlg:HWND; hMessage,wParam,lParam:DWORD):LongBool; stdcall;
+function ImportProgressPageProc(hdlg:HWND; hMessage,wParam,lParam:DWORD):LongBool; stdcall;
+
+implementation
+
+
+function MakeFileList(hdlg:HWND; param:WORD):boolean;
+var i:integer;
+ s1:WideString;
+begin
+ result:=false;
+ case param of
+ IDC_FILE: FileName:=OpenDialogExecute(hdlg, $0200, nFO,TxtPatterns[IndexOfPattern].DefExtension); //OFN_ALLOWMULTISELECT = $00000200;
+ IDC_DIR: FileName:=FolderDialogExecute(hdlg, nFO,TxtPatterns[IndexOfPattern].DefExtension);
+ end;
+ if FileName<>'' then
+ begin
+ SendDlgItemMessageW(hDlg,IDC_LIST,LB_RESETCONTENT,0,0);
+ SendDlgItemMessageW(hdlg, IDC_PATH,WM_SETTEXT,0,0);
+ SetLength(FileNames,0);
+ FilePath:=Copy(FileName,1,nFO-1);
+ SendDlgItemMessageW(hdlg, IDC_PATH,WM_SETTEXT,0,dword(PWideChar(FilePath)));
+ i:=nFO;
+ while FileName[i+1]<>#0 do
+ begin
+ s1:='';
+ Inc(i);
+ while FileName[i]<>#0 do
+ begin s1:=s1+FileName[i]; inc(i); end;
+ if (s1<>'') and (s1<>#0) then
+ begin
+ SetLength(FileNames,Length(FileNames)+1);
+ FileNames[High(FileNames)]:=s1;
+ SendDlgItemMessageW(hDlg,IDC_LIST,LB_ADDSTRING,0,Integer(PWideChar(s1)));
+ end;
+ end;
+ end;
+ if High(FileNames)>-1 then result:=true;
+end;
+
+procedure AddStatusMessage(hDLG:HWND; msg:WideString);
+begin
+ SendDlgItemMessageW(hDLG,IDC_STATUS,LB_SETCURSEL,SendDlgItemMessageW(hDLG,IDC_STATUS,LB_ADDSTRING,0,dword(PWideChar(msg))),0);
+end;
+
+procedure AccLstChngd;
+begin
+ SendMessageW(hwndPage,WIZM_ACCLISTCHANGED,0,0);
+end;
+
+function WizardIntroPageProc(hdlg:HWND; hMessage,wParam,lParam:DWORD):LongBool; stdcall;
+begin
+ result:=false;
+ case hMessage of
+ WM_INITDIALOG:
+ begin
+ TranslateDialogDefault(hdlg);
+ SendMessage(GetParent(hdlg), WIZM_DISABLEBUTTON, 0, 0);
+ IndexOfPattern:=0;
+ ProtoSelect:=0;
+ SetLength(FileNames,0);
+ result:=true;
+ end;
+ WM_COMMAND:
+ case LOWORD(wParam) of
+ IDOK:
+ PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_IMPTYPE, integer(@ImportTypePageProc));
+ IDCANCEL:
+ PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0);
+ end; //Case wParam
+ end; //Case hMassege
+end;
+
+function ImportTypePageProc(hdlg:HWND; hMessage,wParam,lParam:DWORD):LongBool; stdcall;
+var i:integer;
+begin
+ result:=false;
+ case hMessage of
+ WM_INITDIALOG:
+ begin
+ TranslateDialogDefault(hdlg);
+ ReadPatterns;
+ if PatternsCount>0 then
+ begin
+ For i:=0 to PatternsCount-1 do
+ SendDlgItemMessage(hDlg,IDC_COMBO1,CB_ADDSTRING,0,Integer(PatternNames[i]));
+ SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, GetLastPattern, 0);
+ IndexOfPattern:=GetLastPattern;
+ end
+ else
+ SendMessage(GetParent(hdlg), WIZM_DISABLEBUTTON, 1, 0);
+ result:=true;
+ end;
+ WM_COMMAND:
+ begin
+ if (HiWord(wParam)=CBN_SELCHANGE) and (LoWord(wParam)=IDC_COMBO1) then
+ IndexOfPattern:=SendDlgItemMessage(hdlg, IDC_COMBO1, CB_GETCURSEL, 0, 0);
+ Case LOWORD(wParam) of
+ IDC_BACK:
+ PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_IMPWIZARDINTRO, integer(@WizardIntroPageProc));
+ IDOK:
+ PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_IMPFILES, integer(@ImportFilesPageProc));
+ IDCANCEL:
+ PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0);
+ end; //Case wParam
+ end; //WM_COMMAND
+ end; //Case hMassage
+end;
+
+function ImportFilesPageProc(hdlg:HWND; hMessage,wParam,lParam:DWORD):LongBool; stdcall;
+var i:integer;
+begin
+ result:=false;
+ case hMessage of
+ WM_INITDIALOG:
+ begin
+ TranslateDialogDefault(hdlg);
+ if High(FileNames)<0 then SendMessage(GetParent(hdlg), WIZM_DISABLEBUTTON, 1, 0)
+ else
+ begin
+ SendDlgItemMessageW(hdlg, IDC_PATH,WM_SETTEXT,0,dword(PWideChar(FilePath)));
+ for i:=0 to High(FileNames) do
+ SendDlgItemMessageW(hDlg,IDC_LIST,LB_ADDSTRING,0,Integer(PWideChar(FileNames[i])));
+ end;
+ result:=true;
+ end;
+ WM_COMMAND:
+ Case LOWORD(wParam) of
+ IDC_FILE,
+ IDC_DIR: if MakeFileList(hdlg,LOWORD(wParam)) then SendMessage(GetParent(hdlg), WIZM_ENABLEBUTTON, 1, 0)
+ else SendMessage(GetParent(hdlg), WIZM_DISABLEBUTTON, 1, 0);
+ IDC_BACK:
+ PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_IMPTYPE, integer(@ImportTypePageProc));
+ IDOK:
+ PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_IMPDEST, integer(@ImportDestinationPageProc));
+ IDCANCEL:
+ PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0);
+ end; //Case wParam
+ end; //Case hMassage
+end;
+
+function ImportDestinationPageProc(hdlg:HWND; hMessage,wParam,lParam:DWORD):LongBool; stdcall;
+var i:integer;
+ tempws:WideString;
+begin
+ result:=false;
+ case hMessage of
+ WM_INITDIALOG:
+ begin
+ TranslateDialogDefault(hdlg);
+ EnumProtocols;
+ for i:=0 to ProtoCount-1 do
+ begin
+ tempws:=Protocols[i].ProtoName+' | ';
+ if IsMirandaUnicode then tempws:=tempws+UTF8Decode(Protocols[i].ProtoUID)+' | '+UTF8Decode(Protocols[i].ProtoNick)
+ else tempws:=tempws+Protocols[i].ProtoUID+' | '+Protocols[i].ProtoNick;
+ SendDlgItemMessageW(hDlg,IDC_COMBO1,CB_ADDSTRING,0,Integer(PWideChar(tempws)));
+ end;
+ SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, 0, 0);
+ OnAccountListChange:=AccLstChngd;
+ CheckDlgButton(hdlg,IDC_CHKDUPW,BST_CHECKED);
+ CheckForDuplicates:=true;
+ CheckDlgButton(hdlg,IDC_SHOWDUPW,BST_UNCHECKED);
+ CheckForDuplicates:=false;
+ result:=true;
+ end;
+ WM_COMMAND: begin
+ if (HiWord(wParam)=CBN_SELCHANGE) and (LoWord(wParam)=IDC_COMBO1) then
+ ProtoSelect:=SendDlgItemMessage(hdlg, IDC_COMBO1, CB_GETCURSEL, 0, 0);
+ if (HiWord(wParam)=BN_CLICKED) and (LoWord(wParam)=IDC_CHKDUPW) then
+ if LongBool(IsDlgButtonChecked(hdlg,IDC_CHKDUPW)) then EnableWindow(GetDlgItem(hdlg, IDC_SHOWDUPW), TRUE)
+ else EnableWindow(GetDlgItem(hdlg, IDC_SHOWDUPW), FALSE);
+ Case LOWORD(wParam) of
+ IDC_BACK:
+ PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_IMPFILES, integer(@ImportFilesPageProc));
+ IDOK:begin
+ CheckForDuplicates:=LongBool(IsDlgButtonChecked(hdlg,IDC_CHKDUPW));
+ ShowDuplicates:=LongBool(IsDlgButtonChecked(hdlg,IDC_SHOWDUPW));
+ PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_PROGRESS, integer(@ImportProgressPageProc));end;
+ IDCANCEL:
+ PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0);
+ end; //Case wParam
+ end; //WM_COMMAND
+ WIZM_ACCLISTCHANGED:begin
+ ProtoSelect:=SendDlgItemMessage(hdlg, IDC_COMBO1, CB_GETCURSEL, 0, 0);
+ SendDlgItemMessageW(hDlg,IDC_COMBO1,CB_RESETCONTENT,0,0);
+ for i:=0 to ProtoCount-1 do
+ begin
+ tempws:=Protocols[i].ProtoName+' | ';
+ if IsMirandaUnicode then tempws:=tempws+UTF8Decode(Protocols[i].ProtoUID)+' | '+UTF8Decode(Protocols[i].ProtoNick)
+ else tempws:=tempws+Protocols[i].ProtoUID+' | '+Protocols[i].ProtoNick;
+ SendDlgItemMessageW(hDlg,IDC_COMBO1,CB_ADDSTRING,0,Integer(PWideChar(tempws)));
+ end;
+ if ProtoSelect<ProtoCount-1 then SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, ProtoSelect, 0)
+ else SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, ProtoCount-1, 0);
+ end; //WIZM_...
+ end; //Case hMassage
+end;
+
+function ImportProgressPageProc(hdlg:HWND; hMessage,wParam,lParam:DWORD):LongBool; stdcall;
+var H,Mi,sec,ms:word;
+ s:WideString;
+ tempwstr:PWideChar;
+begin
+ result:=false;
+ case hMessage of
+ WM_INITDIALOG:
+ begin
+ TranslateDialogDefault(hdlg);
+ SendMessage(GetParent(hdlg), WIZM_DISABLEBUTTON, 0, 0);
+ SendMessage(GetParent(hdlg), WIZM_DISABLEBUTTON, 1, 0);
+ SendMessage(GetParent(hdlg), WIZM_DISABLEBUTTON, 2, 0);
+ SendMessage(GetParent(hdlg), WIZM_SETCANCELTEXT, 0, Integer(PWideChar(TranslateWideString('Finish'))));
+ //START THREAD
+ ImportThrd:=TImportThrd.Create(TRUE);
+ ImportThrd.FreeOnTerminate:=true;
+ ImportThrd.DContact.hContact:=0;
+ ImportThrd.Destination:=Protocols[ProtoSelect];
+ ImportThrd.FileNames:=FileName+#0+#0;
+ ImportThrd.OffsetFileName:=nFO;
+ ImportThrd.WorkPattern:=TxtPatterns[IndexOfPattern];
+ ImportThrd.ParentHWND:=hdlg;
+ ImportThrd.Resume;
+ result:=true;
+ end;
+ WM_COMMAND:
+ Case LOWORD(wParam) of
+ IDCANCEL:
+ PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0);
+ end; //Case wParam
+ //Далее оброботка сообщений от потока импорта
+ //Начали
+ ITXT_THREAD_ALLSTARTED:StartTime:=Time;
+ ITXT_THREAD_START:begin
+ AddStatusMessage(hdlg,TranslateWideString('Import started...'));
+ end;
+ //Известна длинна файла выставляем диапазон прогрессбара
+ ITXT_THREAD_MAXPROGRESS:
+ SendDlgItemMessage(hdlg,IDC_PROGRESS,PBM_SETRANGE,0,MakeLParam(0,lParam));
+ //Идет прогресс ...
+ ITXT_THREAD_PROGRESS:
+ SendDlgItemMessage(hdlg,IDC_PROGRESS,PBM_SETPOS,wParam,0);
+ //Возникла ошибка
+ ITXT_THREAD_ERROR:
+ AddStatusMessage(hdlg,TranslateWideString(PWideChar(wParam)));
+ //Закончили
+ ITXT_THREAD_FINISH:begin
+ AddStatusMessage(hdlg,WideFormat(TranslateWideString('Added: %d messages'),[wParam]));
+ AddStatusMessage(hdlg,WideFormat(TranslateWideString('Duplicates: %d messages'),[lParam]));
+ end;
+ //начали новый файл
+ ITXT_THREAD_START_FILE:
+ AddStatusMessage(hdlg,WideFormat(TranslateWideString('File: %s'),[PWideChar(wParam)]));
+ //определили контакт
+ ITXT_THREAD_DEST_CONTACT:begin
+ if IsMirandaUnicode then
+ begin
+ tempwstr:=UTF8toWide(PChar(GetContactID(wParam,'',true)),tempwstr);
+ s:= tempwstr;
+ tempwstr:=UTF8toWide(PChar(GetContactNick(wParam,'',true)),tempwstr);
+ s:=s + ' | ' + tempwstr;
+ end
+ else
+ s:=GetContactID(wParam,'',true)+' | '+GetContactNick(wParam,'',true);
+ AddStatusMessage(hdlg,WideFormat(TranslateWideString('To: %s'),[s]));
+ end;
+ ITXT_THREAD_ALLFINISHED:begin
+ FinishTime:=Time;
+ DecodeTime(FinishTime-StartTime,h,mi,sec,ms);
+ AddStatusMessage(hdlg,WideFormat(TranslateWideString('In: %d:%d:%d'),[h,mi,sec]));
+ SendMessage(GetParent(hdlg), WIZM_ENABLEBUTTON, 2, 0);
+ end;
+ end; //Case hMessage
+end;
+
+function WizardDlgProc(hdlg:HWND; hMessage,wParam,lParam:DWORD):LongBool; stdcall;
+begin
+ result:=false;
+ case hMessage of
+ WM_DESTROY:
+ SetLastPattern(IndexOfPattern);
+ WM_INITDIALOG:
+ begin
+ TranslateDialogDefault(hdlg);
+ hwndPage:=CreateDialog(hInstance, MAKEINTRESOURCE(IDD_IMPWIZARDINTRO), hdlg, @WizardIntroPageProc);
+ SetWindowPos(hwndPage, 0, 0, 0, 0, 0, SWP_NOZORDER or SWP_NOSIZE);
+ ShowWindow(hwndPage, SW_SHOW);
+ ShowWindow(hdlg, SW_SHOW);
+ SendMessage(hdlg, WM_SETICON, ICON_BIG, LoadIcon(hInstance,MAKEINTRESOURCE(110)));
+ result:=true;
+ end;
+ WIZM_GOTOPAGE:
+ begin
+ DestroyWindow(hwndPage);
+ EnableWindow(GetDlgItem(hdlg, IDC_BACK), TRUE);
+ EnableWindow(GetDlgItem(hdlg, IDOK), TRUE);
+ EnableWindow(GetDlgItem(hdlg, IDCANCEL), TRUE);
+ SetDlgItemTextW(hdlg, IDCANCEL, PWideChar(TranslateWideString('Cancel')));
+ hwndPage:=CreateDialog(hInstance, MAKEINTRESOURCE(wParam), hdlg, Pointer(lParam));
+ SetWindowPos(hwndPage, 0, 0, 0, 0, 0, SWP_NOZORDER or SWP_NOSIZE);
+ ShowWindow(hwndPage, SW_SHOW);
+ end;
+ WIZM_DISABLEBUTTON:
+ begin
+ case wParam of
+ 0: EnableWindow(GetDlgItem(hdlg, IDC_BACK), FALSE);
+ 1: EnableWindow(GetDlgItem(hdlg, IDOK), FALSE);
+ 2: EnableWindow(GetDlgItem(hdlg, IDCANCEL), FALSE);
+ end; //Case wParam
+ end;
+ WIZM_ENABLEBUTTON:
+ begin
+ case wParam of
+ 0: EnableWindow(GetDlgItem(hdlg, IDC_BACK), TRUE);
+ 1: EnableWindow(GetDlgItem(hdlg, IDOK), TRUE);
+ 2: EnableWindow(GetDlgItem(hdlg, IDCANCEL), TRUE);
+ end; //Case wParam
+ end;
+ WIZM_SETCANCELTEXT:
+ SetDlgItemTextW(hdlg, IDCANCEL, PWideChar(lParam));
+ WIZM_SETNEXTTEXT:
+ SetDlgItemTextW(hdlg, IDOK, PWideChar(lParam));
+ WM_COMMAND:
+ SendMessage(hwndPage, WM_COMMAND, wParam, lParam);
+ WM_CLOSE:
+ begin
+ OnAccountListChange:=nil;
+ DestroyWindow(hwndPage);
+ DestroyWindow(hdlg);
+ end;
+ end;// Case hMessage
+end;
+end.
diff --git a/plugins/ImportTXT/PerlRegEx.pas b/plugins/ImportTXT/PerlRegEx.pas
new file mode 100644
index 0000000000..617479fa91
--- /dev/null
+++ b/plugins/ImportTXT/PerlRegEx.pas
@@ -0,0 +1,447 @@
+(**********************************************************
+* *
+* Perl Regular Expressions *
+* *
+* Delphi wrapper around PCRE - http://www.pcre.org *
+* *
+* Copyright (C) 1999-2006 Jan Goyvaerts *
+* *
+* Design & implementation Jan Goyvaerts 1999-2006 *
+* *
+* *
+* Shorted and added partial ability for PCRE 7.0 *
+* by Abyss *
+**********************************************************)
+
+unit PerlRegEx;
+
+interface
+
+
+
+uses SysUtils;
+
+type
+ TPerlRegExOptions = set of (
+ preCaseLess, // /i -> Case insensitive
+ preMultiLine, // /m -> ^ and $ also match before/after a newline, not just at the beginning and the end of the string
+ preSingleLine, // /s -> Dot matches any character, including \n (newline). Otherwise, it matches anything except \n
+ preExtended, // /x -> Allow regex to contain extra whitespace, newlines and Perl-style comments, all of which will be filtered out
+ preAnchored, // /A -> Successful match can only occur at the start of the subject or right after the previous match
+ preDollarEndOnly, // /E
+ preExtra, // /X
+ preUnGreedy, // Repeat operators (+, *, ?) are not greedy by default
+ // (i.e. they try to match the minimum number of characters instead of the maximum)
+ preUTF8 // UTF8
+ );
+type
+ TPerlRegExState = set of (
+ preNotBOL, // Not Beginning Of Line: ^ does not match at the start of Subject
+ preNotEOL, // Not End Of Line: $ does not match at the end of Subject
+ preNotEmpty // Empty matches not allowed
+ );
+
+const
+ // Maximum number of subexpressions (backreferences)
+ // Subexpressions are created by placing round brackets in the regex, and are referenced by \1, \2, ...
+ // In Perl, they are available as $1, $2, ... after the regex matched; with TPerlRegEx, use the Subexpressions property
+ // You can also insert \1, \2, ... in the Replacement string; \0 is the complete matched expression
+ MAX_SUBEXPRESSIONS = 99;
+
+
+type
+ TPerlRegEx = class
+ private // *** Property storage, getters and setters
+ FCompiled, FStudied: Boolean;
+ FOptions: TPerlRegExOptions;
+ FState: TPerlRegExState;
+ FRegEx, FSubject: string;
+ FStart, FStop: Integer;
+ function GetMatchedExpression: string;
+ function GetMatchedExpressionLength: Integer;
+ function GetMatchedExpressionOffset: Integer;
+ procedure SetOptions(Value: TPerlRegExOptions);
+ procedure SetRegEx(const Value: string);
+ function GetSubExpressionCount: Integer;
+ function GetSubExpressions(Index: Integer): string;
+ function GetSubExpressionLengths(Index: Integer): Integer;
+ function GetSubExpressionOffsets(Index: Integer): Integer;
+ procedure SetSubject(const Value: string);
+ procedure SetStart(const Value: Integer);
+ procedure SetStop(const Value: Integer);
+ function GetFoundMatch: Boolean;
+ private // *** Variables used by pcrelib.dll
+ Offsets: array[0..(MAX_SUBEXPRESSIONS+1)*3] of Integer;
+ OffsetCount: Integer;
+ pcreOptions: Integer;
+ pattern, hints, chartable: Pointer;
+ FSubjectPChar: PChar;
+ protected
+ procedure CleanUp;
+ // Dispose off whatever we created, so we can start over. Called automatically when needed, so it is not made public
+ public
+ constructor Create;
+ // Come to life
+ destructor Destroy; override;
+ // Clean up after ourselves
+ class function EscapeRegExChars(const S: string): string;
+ // Escapes regex characters in S so that the regex engine can be used to match S as plain text
+ procedure Compile;
+ // Compile the regex. Called automatically by Match
+ procedure Study;
+ // Study the regex. Studying takes time, but will make the execution of the regex a lot faster.
+ // Call study if you will be using the same regex many times
+ function Match: Boolean;
+ // Attempt to match the regex
+ function MatchAgain: Boolean;
+ // Attempt to match the regex to the remainder of the string after the previous match
+ // To avoid problems (when using ^ in the regex), call MatchAgain only after a succesful Match()
+ function NamedSubExpression(const SEName: string): Integer;
+ // Returns the index of the named group SEName
+ function Config (What: integer): Integer;
+ //This function makes it possible for a client program
+ // to find out which optional features are available in the
+ //version of the PCRE library it is using.
+ property Compiled: Boolean read FCompiled;
+ // True if the RegEx has already been compiled.
+ property FoundMatch: Boolean read GetFoundMatch;
+ // Returns True when MatchedExpression* and SubExpression* indicate a match
+ property Studied: Boolean read FStudied;
+ // True if the RegEx has already been studied
+ property MatchedExpression: string read GetMatchedExpression;
+ // The matched string
+ property MatchedExpressionLength: Integer read GetMatchedExpressionLength;
+ // Length of the matched string
+ property MatchedExpressionOffset: Integer read GetMatchedExpressionOffset;
+ // Character offset in the Subject string at which the matched substring starts
+ property Start: Integer read FStart write SetStart;
+ // Starting position in Subject from which MatchAgain begins
+ property Stop: Integer read FStop write SetStop;
+ // Last character in Subject that Match and MatchAgain search through
+ property State: TPerlRegExState read FState write FState;
+ // State of Subject
+ property SubExpressionCount: Integer read GetSubExpressionCount;
+ // Number of matched subexpressions
+ property SubExpressions[Index: Integer]: string read GetSubExpressions;
+ // Matched subexpressions after a regex has been matched
+ property SubExpressionLengths[Index: Integer]: Integer read GetSubExpressionLengths;
+ // Lengths of the subexpressions
+ property SubExpressionOffsets[Index: Integer]: Integer read GetSubExpressionOffsets;
+ // Character offsets in the Subject string of the subexpressions
+ property Subject: string read FSubject write SetSubject;
+ // The string on which Match() will try to match RegEx
+ published
+ property Options: TPerlRegExOptions read FOptions write SetOptions;
+ // Options
+ property RegEx: string read FRegEx write SetRegEx;
+ // The regular expression to be matched
+ end;
+
+
+
+implementation
+
+ { ********* pcrelib.dll imports ********* }
+
+const
+ PCRE_CASELESS = $00000001;
+ PCRE_MULTILINE = $00000002;
+ PCRE_SINGLELINE = $00000004;
+ PCRE_EXTENDED = $00000008;
+ PCRE_ANCHORED = $00000010;
+ PCRE_DOLLAR_ENDONLY = $00000020;
+ PCRE_EXTRA = $00000040;
+ PCRE_NOTBOL = $00000080;
+ PCRE_NOTEOL = $00000100;
+ PCRE_UNGREEDY = $00000200;
+ PCRE_NOTEMPTY = $00000400;
+ PCRE_UTF8 = $00000800;
+ PCRE_NO_AUTO_CAPTURE = $00001000;
+ PCRE_NO_UTF8_CHECK = $00002000;
+ PCRE_AUTO_CALLOUT = $00004000;
+ PCRE_PARTIAL = $00008000;
+ PCRE_DFA_SHORTEST = $00010000;
+ PCRE_DFA_RESTART = $00020000;
+ PCRE_FIRSTLINE = $00040000;
+ PCRE_DUPNAMES = $00080000;
+ PCRE_NEWLINE_CR = $00100000;
+ PCRE_NEWLINE_LF = $00200000;
+ PCRE_NEWLINE_CRLF = $00300000;
+ PCRE_NEWLINE_ANY = $00400000;
+
+ // Exec error codes
+ PCRE_ERROR_NOMATCH = -1;
+ PCRE_ERROR_NULL = -2;
+ PCRE_ERROR_BADOPTION = -3;
+ PCRE_ERROR_BADMAGIC = -4;
+ PCRE_ERROR_UNKNOWN_OPCODE = -5;
+ PCRE_ERROR_UNKNOWN_NODE = -5; // For backward compatibility
+ PCRE_ERROR_NOMEMORY = -6;
+ PCRE_ERROR_NOSUBSTRING = -7;
+ PCRE_ERROR_MATCHLIMIT = -8;
+ PCRE_ERROR_CALLOUT = -9; // Never used by PCRE itself
+ PCRE_ERROR_BADUTF8 =-10;
+ PCRE_ERROR_BADUTF8_OFFSET =-11;
+ PCRE_ERROR_PARTIAL =-12;
+ PCRE_ERROR_BADPARTIAL =-13;
+ PCRE_ERROR_INTERNAL =-14;
+ PCRE_ERROR_BADCOUNT =-15;
+ PCRE_ERROR_DFA_UITEM =-16;
+ PCRE_ERROR_DFA_UCOND =-17;
+ PCRE_ERROR_DFA_UMLIMIT =-18;
+ PCRE_ERROR_DFA_WSSIZE =-19;
+ PCRE_ERROR_DFA_RECURSE =-20;
+ PCRE_ERROR_RECURSIONLIMIT =-21;
+ PCRE_ERROR_NULLWSLIMIT =-22;
+ PCRE_ERROR_BADNEWLINE =-23;
+
+(* Request types for pcre_config(). Do not re-arrange, in order to remain compatible. *)
+
+ PCRE_CONFIG_UTF8 = 0;
+ PCRE_CONFIG_NEWLINE = 1;
+ PCRE_CONFIG_LINK_SIZE = 2;
+ PCRE_CONFIG_POSIX_MALLOC_THRESHOLD = 3;
+ PCRE_CONFIG_MATCH_LIMIT = 4;
+ PCRE_CONFIG_STACKRECURSE = 5;
+ PCRE_CONFIG_UNICODE_PROPERTIES = 6;
+ PCRE_CONFIG_MATCH_LIMIT_RECURSION = 7;
+type
+ PPChar = ^PChar;
+ PInt = ^Integer;
+
+
+
+// Functions we import from the PCRE library DLL
+// Leading underscores gratuitously added by Borland C++Builder 6.0
+function pcre_maketables: PAnsiChar; cdecl; external 'pcre3.dll';
+function pcre_compile(const pattern: PChar; options: Integer; errorptr: PPChar; erroroffset: PInt;
+ const tables: PChar): Pointer; cdecl; external 'pcre3.dll';
+function pcre_exec(const pattern: Pointer; const hints: Pointer; const subject: PChar; length, startoffset: Integer;
+ options: Integer; offsets: PInt; offsetcount: Integer): Integer; cdecl; external 'pcre3.dll';
+function pcre_get_stringnumber(const pattern: Pointer; const Name: PChar): Integer; cdecl; external 'pcre3.dll';
+function pcre_study(const pattern: Pointer; options: Integer; errorptr: PPChar): Pointer; cdecl; external 'pcre3.dll';
+function pcre_fullinfo(const pattern: Pointer; const hints: Pointer; what: Integer; where: Pointer): Integer; cdecl; external 'pcre3.dll';
+function pcre_version: pchar; cdecl; external 'pcre3.dll';
+function pcre_config (what:integer; where:pointer):integer; cdecl; external 'pcre3.dll';
+//procedure pcre_free(ptr: Pointer); cdecl; external 'pcre3.dll';
+
+
+
+
+ { ********* TPerlRegEx component ********* }
+
+procedure TPerlRegEx.CleanUp;
+begin
+ FCompiled := False; FStudied := False;
+ pattern := nil; hints := nil;
+ OffsetCount := 0;
+end;
+
+procedure TPerlRegEx.Compile;
+var
+ Error: PChar;
+ ErrorOffset: Integer;
+begin
+ if FRegEx = '' then raise Exception.Create('TPerlRegEx.Compile() - Please specify a regular expression in RegEx first');
+ CleanUp;
+ Pattern := pcre_compile(PChar(FRegEx), pcreOptions, @Error, @ErrorOffset, chartable);
+ if Pattern = nil then
+ raise Exception.Create(Format('TPerlRegEx.Compile() - Error in regex at offset %d: %s', [ErrorOffset, AnsiString(Error)]));
+ FCompiled := True
+end;
+
+
+constructor TPerlRegEx.Create;
+begin
+ inherited Create;
+ FState := [preNotEmpty];
+ chartable := pcre_maketables;
+end;
+
+destructor TPerlRegEx.Destroy;
+begin
+ CleanUp;
+ inherited Destroy;
+end;
+
+class function TPerlRegEx.EscapeRegExChars(const S: string): string;
+var
+ I: Integer;
+begin
+ Result := S;
+ I := Length(Result);
+ while I > 0 do begin
+ if Result[I] in ['.', '[', ']', '(', ')', '?', '*', '+', '{', '}', '^', '$', '|', '\'] then
+ Insert('\', Result, I)
+ else if Result[I] = #0 then begin
+ Result[I] := '0';
+ Insert('\', Result, I);
+ end;
+ Dec(I);
+ end;
+end;
+
+function TPerlRegEx.GetFoundMatch: Boolean;
+begin
+ Result := OffsetCount > 0;
+end;
+
+function TPerlRegEx.GetMatchedExpression: string;
+begin
+ Assert(FoundMatch, 'REQUIRE: There must be a successful match first');
+ Result := GetSubExpressions(0);
+end;
+
+function TPerlRegEx.GetMatchedExpressionLength: Integer;
+begin
+ Assert(FoundMatch, 'REQUIRE: There must be a successful match first');
+ Result := GetSubExpressionLengths(0)
+end;
+
+function TPerlRegEx.GetMatchedExpressionOffset: Integer;
+begin
+ Assert(FoundMatch, 'REQUIRE: There must be a successful match first');
+ Result := GetSubExpressionOffsets(0)
+end;
+
+function TPerlRegEx.GetSubExpressionCount: Integer;
+begin
+ Assert(FoundMatch, 'REQUIRE: There must be a successful match first');
+ Result := OffsetCount-1
+end;
+
+function TPerlRegEx.GetSubExpressionLengths(Index: Integer): Integer;
+begin
+ Assert(FoundMatch, 'REQUIRE: There must be a successful match first');
+ Assert((Index >= 0) and (Index <= SubExpressionCount), 'REQUIRE: Index <= SubExpressionCount');
+ Result := Offsets[Index*2+1]-Offsets[Index*2]
+end;
+
+function TPerlRegEx.GetSubExpressionOffsets(Index: Integer): Integer;
+begin
+ Assert(FoundMatch, 'REQUIRE: There must be a successful match first');
+ Assert((Index >= 0) and (Index <= SubExpressionCount), 'REQUIRE: Index <= SubExpressionCount');
+ Result := Offsets[Index*2]
+end;
+
+function TPerlRegEx.GetSubExpressions(Index: Integer): string;
+begin
+ Assert(FoundMatch, 'REQUIRE: There must be a successful match first');
+ if Index > SubExpressionCount then Result := ''
+ else Result := Copy(FSubject, Offsets[Index*2], Offsets[Index*2+1]-Offsets[Index*2]);
+end;
+
+function TPerlRegEx.Match: Boolean;
+var
+ I, Opts: Integer;
+begin
+ if not Compiled then Compile;
+ if preNotBOL in State then Opts := PCRE_NOTBOL else Opts := 0;
+ if preNotEOL in State then Opts := Opts or PCRE_NOTEOL;
+ if preNotEmpty in State then Opts := Opts or PCRE_NOTEMPTY;
+ if FStart > FStop then OffsetCount := -1
+ else OffsetCount := pcre_exec(Pattern, Hints, FSubjectPChar, FStop, 0, Opts, @Offsets[0], High(Offsets));
+ Result := OffsetCount > 0;
+ // Convert offsets into string indices
+ if Result then begin
+ for I := 0 to OffsetCount*2-1 do
+ Inc(Offsets[I]);
+ FStart := Offsets[1];
+ if Offsets[0] = Offsets[1] then Inc(FStart); // Make sure we don't get stuck at the same position
+ end;
+end;
+
+function TPerlRegEx.MatchAgain: Boolean;
+var
+ I, Opts: Integer;
+begin
+ if not Compiled then Compile;
+ if preNotBOL in State then Opts := PCRE_NOTBOL else Opts := 0;
+ if preNotEOL in State then Opts := Opts or PCRE_NOTEOL;
+ if preNotEmpty in State then Opts := Opts or PCRE_NOTEMPTY;
+ if FStart > FStop then OffsetCount := -1
+ else OffsetCount := pcre_exec(Pattern, Hints, FSubjectPChar, FStop, FStart-1, Opts, @Offsets[0], High(Offsets));
+ Result := OffsetCount > 0;
+ // Convert offsets into string indices
+ if Result then begin
+ for I := 0 to OffsetCount*2-1 do
+ Inc(Offsets[I]);
+ FStart := Offsets[1];
+ if Offsets[0] = Offsets[1] then Inc(FStart); // Make sure we don't get stuck at the same position
+ end;
+end;
+
+function TPerlRegEx.NamedSubExpression(const SEName: string): Integer;
+begin
+ Result := pcre_get_stringnumber(Pattern, PChar(SEName));
+end;
+
+function TPerlRegEx.Config(What: integer):integer;
+begin
+ result:=-1;
+ pcre_config(what, @result);
+end;
+
+
+procedure TPerlRegEx.SetOptions(Value: TPerlRegExOptions);
+begin
+ if (FOptions <> Value) then begin
+ FOptions := Value;
+ pcreOptions := 0;
+ if (preCaseLess in Value) then pcreOptions := pcreOptions or PCRE_CASELESS;
+ if (preMultiLine in Value) then pcreOptions := pcreOptions or PCRE_MULTILINE;
+ if (preSingleLine in Value) then pcreOptions := pcreOptions or PCRE_SINGLELINE;
+ if (preExtended in Value) then pcreOptions := pcreOptions or PCRE_EXTENDED;
+ if (preAnchored in Value) then pcreOptions := pcreOptions or PCRE_ANCHORED;
+ if (preDollarEndOnly in Value) then pcreOptions := pcreOptions or PCRE_DOLLAR_ENDONLY;
+ if (preExtra in Value) then pcreOptions := pcreOptions or PCRE_EXTRA;
+ if (preUnGreedy in Value) then pcreOptions := pcreOptions or PCRE_UNGREEDY;
+ if (preUTF8 in Value) then pcreOptions := pcreOptions or PCRE_UTF8;
+ CleanUp
+ end
+end;
+
+procedure TPerlRegEx.SetRegEx(const Value: string);
+begin
+ if FRegEx <> Value then begin
+ FRegEx := Value;
+ CleanUp
+ end
+end;
+
+procedure TPerlRegEx.SetStart(const Value: Integer);
+begin
+ if Value < 1 then FStart := 1
+ else FStart := Value;
+ // If FStart > Length(Subject), MatchAgain() will simply return False
+end;
+
+procedure TPerlRegEx.SetStop(const Value: Integer);
+begin
+ if Value > Length(Subject) then FStop := Length(Subject)
+ else FStop := Value;
+end;
+
+procedure TPerlRegEx.SetSubject(const Value: string);
+begin
+ FSubject := Value;
+ FSubjectPChar := PChar(Value);
+ FStart := 1;
+ FStop := Length(Subject);
+ OffsetCount := 0;
+end;
+
+
+
+procedure TPerlRegEx.Study;
+var
+ Error: PChar;
+begin
+ if not FCompiled then Compile;
+ Hints := pcre_study(Pattern, 0, @Error);
+ if Error <> nil then raise Exception.Create('TPerlRegEx.Study() - Error studying the regex: ' + AnsiString(Error));
+ FStudied := True
+end;
+
+
+end. \ No newline at end of file
diff --git a/plugins/ImportTXT/doc/changelog_ru.txt b/plugins/ImportTXT/doc/changelog_ru.txt
new file mode 100644
index 0000000000..9ce2fe5298
--- /dev/null
+++ b/plugins/ImportTXT/doc/changelog_ru.txt
@@ -0,0 +1,77 @@
+v. 0.0.1.9
+* исправлено дублирование сообщения, если оно совпадает с первым в базе
+* поддержка исправленного xml_api и поддержка плагина XML Driver (для седьмой ветки)
+
+v. 0.0.1.8
+* !важный фикс проверки дубликатов
++ добавлена возможность показывать дубликаты
++ автоскролл в окне сообщений
++ добавлена возможность отключить проверку на дубликаты
+* баг с кривым выводом статусных сообщений
++ добавлен параметр Codepage в шаблон
+- убрана возможность одновременного импорта
++ иконка в окне импорта
++ перечитывание шаблонов, при открытии окна и в Мастере
++ запоминание последнего шаблона
++ полностью переделан импорт из ICQ6
+
+v. 0.0.1.7
++ добавлен шаблон D[i]chat
++ добавлен импорт из ICQ6
++ добавлен импорт из XML файлов ICQ5
+
+v. 0.0.1.6
+* исправлена блокировка папки с импортируемыми файлами
++ добавлен шаблон Pigeon
+
+v. 0.0.1.5
+* исправлено расширение по умолчанию при выборе папки
+
+v. 0.0.1.4
++ добавлена поддержка Updater
+* когда не найден заголовок, не загоралась кнопка "завершить"
+* исправлен шаблон mContacts
+
+v. 0.0.1.3
++ добавлена поддержка бинарных файлов qhf
+
+v. 0.0.1.2
++ добавлен параметр DefaultExtension в шаблон
++ добавлена поддержка бинарных файлов, пока только mContact
+
+v. 0.0.1.1
++ добавлена возможность автостарта
+* обновление списка аккаунтов при его изменении :)
+
+v. 0.0.1.0
+* пункт меню добавляется всем контактам
+* добавлен мастер массового импорта
+
+v. 0.0.0.6
+* переработан формат файлов шаблона, теперь это ini файлы
+* выделен обработчик сообщений перед импортом (удаление переводов строк и пробелов)
++ добавлена поддержка Message Export
+* мелкие исправления
+
+v. 0.0.0.5
+* добавлена поддержка файлов с заголовком, с ником в заголовке сообщениия, но без направления
+ (History++)
+
+v. 0.0.0.4
+* добавлена поддержка мультиаккаунтности для 0.8+
+* пункт меню теперь добавляется для всех ICQ протоколов (если несколько копий DLL)
+
+v. 0.0.0.3
+* изменены процедуры преобразования кодировок
+* убраны утечки памяти
++ добавлена собственная иконка
+
+v. 0.0.0.2
+* изменен способ работы с рег. выражениями (pcre3.dll)
++ сообщения импортируются в базу в UTF8 или ANSI в зависимости от версии Миранды
++ разные кодировки входных файлов
++ фикс перевода
+
+
+v. 0.0.0.1
++ первый релиз \ No newline at end of file
diff --git a/plugins/ImportTXT/doc/examples_ru.txt b/plugins/ImportTXT/doc/examples_ru.txt
new file mode 100644
index 0000000000..2120fd2b72
--- /dev/null
+++ b/plugins/ImportTXT/doc/examples_ru.txt
@@ -0,0 +1,169 @@
+
+Пример файла:
+************
+
+ История сообщений с Неизвестный (000000000)
+ Сохранено из Jimm 07.06.2008 11:49:17
+
+
+------------------------------------>>>-
+ Abyss (06.09.2007 17:52:51):
+Привет!
+
+------------------------------------<<<-
+ Неизвестный (06.09.2007 18:03:09):
+Хай
+
+************
+
+Шаблон такой:
+
+[General]
+Name=Jimm import pattern
+Charset=ANSI
+UseHeader=2
+UsePreMsg=1
+[Message]
+Pattern=^------------------------------------(<<<|>>>)-\r\n\s([^\r\n]+?)\s\((\d\d?)\.(\d\d?)\.(\d\d\d?\d?)\s(\d\d?):(\d\d?):(\d\d?)\):$
+In=<<<
+Out=>>>
+Direction=1
+Day=3
+Month=4
+Year=5
+Hours=6
+Minutes=7
+Seconds=8
+[PreMessage]
+PreRN=1
+AfterRN=2
+[Header]
+Pattern=^\r\n\tИстория сообщений с ([^\r\n]+?)\s\((\d{5,})\)\r\n\tСохранено из Jimm\s[^\r\n]+?\r\n
+InNick=1
+InUID=2
+
+Коментарии: основные моменты содержаться в pattern_cfg,
+Такие значения RN потому что:
+считаем...
+
+Привет!{\r\n} Раз
+{\r\n} два после
+------------------------------------<<<-
+ Неизвестный (06.09.2007 18:03:09):{\r\n} Один до
+Хай
+
+UseHeader=2 используем заголовок только для определения контакта назначения
+
+
+====================================================================================================================================
+Для History++
+=============
+
+Пример файла
+************
+
+###
+### Полная история
+### Abyss (ICQ: 0000000) - Неизвестный (ICQ: 00000000)
+### (создана модулем history++)
+###
+
+[06.09.2007 17:52:51] Abyss:
+Привет!
+
+[06.09.2007 18:03:09] Неизвестный:
+Хай
+
+************
+Файл шаблона выглядит так:
+**************************
+[General]
+Name=History++ pattern
+Charset=UCS2
+UseHeader=3
+UsePreMsg=1
+[Message]
+Pattern=^\[(\d\d?)\.(\d\d?)\.(\d\d\d?\d?)\s(\d\d?):(\d\d?):(\d\d?)\]\s([^\r\n]+?):$
+Direction=7
+Day=1
+Month=2
+Year=3
+Hours=4
+Minutes=5
+Seconds=6
+[Header]
+Pattern=^###\r\n###\s[^\r\n]+?\r\n###\s([^\r\n]+?)\s\([^\r\n]+?:\s([^\r\n]+?)\)\s-\s([^\r\n]+?)\s\([^\r\n]+?:\s([^\r\n]+?)\)\r\n###\s[^\r\n]+?\r\n###\r\n
+In=3
+Out=1
+InNick=3
+OutNick=1
+InUID=4
+OutUID=2
+[PreMessage]
+PreRN=1
+AfterRN=2
+**************************
+
+Все аналогично только добавляется обработка заголовка, получаем ник для того чтобы потом его использовать в качестве маркера направления
+
+========================================================================================================================================
+
+Для Message Export
+==================
+Файл:
+*****
+------------------------------------------------
+ History for
+User : Неизвестный
+Protocol : ICQ
+UIN : 00000000
+FirstName : Mister
+LastName : X
+Age : 0
+Gender : M
+e-mail :
+Nick : Неизвестный
+City :
+State : 66
+Phone :
+Homepage :
+- About -
+
+------------------------------------------------
+Abyss 06.09.2007 17:52:51 Привет
+ Как дела?
+Неизвестный 06.09.2007 18:03:09 Хай, нормально
+
+*******************
+
+[General]
+Name=Message export import pattern
+Charset=UTF8
+UseHeader=3
+UsePreMsg=1
+[Message]
+Pattern=^([^\r\n]+?)[\s]+?(\d\d?)\.(\d\d?)\.(\d\d\d?\d?)\s(\d\d?):(\d\d?):(\d\d?)\s
+Direction=1
+Day=2
+Month=3
+Year=4
+Hours=5
+Minutes=6
+Seconds=7
+[Header]
+Pattern=^------------------------------------------------\r\n[\s]+?History for\r\nUser[\s]+?:\s([^\r\n]+?)\r\n(.*\r\n)+?Nick[\s]+?:\s([^\r\n]+?)\s\r\n(.*\r\n)+?^------------------------------------------------$
+In=1
+InNick=3
+[PreMessage]
+PreRN=0
+AfterRN=1
+PreSP=-2
+*********************
+
+
+Добавлено удаление пробелов в многострочных сообщениях PreSP=-2
+
+С этим форматом сообщений бардак: 1) если протокол НЕ ICQ то UID мы не увидим, тоесть ни JID ни что-то там еще не сохраняются
+ приходится использовать Ник, что не есть гуд
+ 2) Ник! Зачем писать в файлы пробел после ника????
+ Все строчки (Potocol, User, email) нормальные, а после ника пробел. \ No newline at end of file
diff --git a/plugins/ImportTXT/doc/importtxt_translate.txt b/plugins/ImportTXT/doc/importtxt_translate.txt
new file mode 100644
index 0000000000..4220d2e02d
--- /dev/null
+++ b/plugins/ImportTXT/doc/importtxt_translate.txt
@@ -0,0 +1,105 @@
+;============================================================
+; Module: importtxt.dll
+; Plugin: Imports history saved in TXT files from other clients
+; Versions: 0.0.0.1 - 0.0.1.2
+; Translators: Abyss
+; Dates: 6.09.08
+; Template:
+; URL:
+;============================================================
+[Imports history saved in TXT files from other clients]
+Импортирует историю из текстовых файлов
+[Import history to ]
+Импортировать историю в
+[Import history]
+Импорт истории
+[Choose a file...]
+Выберите файл...
+[Choose a pattern...]
+Выберите шаблон...
+[Choose a file for import...]
+Выберите файл для импорта...
+[Text files (*.txt)]
+Текстовые файлы (*.txt)
+[All files (*.*)]
+Все файлы (*.*)
+[Start]
+Старт
+;[Close]
+[Error in cfg file: ]
+Ошибка в cfg файле:
+[No Files Patterns Found]
+Не найдены файлы шаблонов
+[No messages in this file]
+В этом файле нет сообщений
+[Import started...]
+Импорт запущен...
+[Added: %d messages]
+Добавлено: %d сообщений
+[Duplicates: %d messages]
+Дубликатов: %d сообщений
+[In: %d:%d:%d]
+За: %d:%d:%d
+[Import not finished. Do you realy want close?]
+Импорт не закончен. Вы действительно хотите закрыть?
+
+[Error adding message to DB]
+Ошибка добавления сообщения в Базу
+
+[Error opening file]
+Ошибка открытия файла
+[Error mapping file]
+Ошибка отображения файла
+[Error mapping]
+Ошибка отображения
+
+[Header not found]
+Заголовок не найден
+
+[Import Text Files Wizard]
+Мастер Импорта Текстовых Файлов
+
+[This wizard will help you import message history from some other clients and Miranda plugins, stored in text files.]
+Этот мастер поможет вам импортировать сообщения из некоторых других клиентов и плагинов Миранды, хранящуюся в текстовых файлах.
+[Click ""Next"" to choose the information you wish to import, or click ""Cancel"" to exit the wizard and continue using Miranda.]
+Нажмите "Далее" чтобы выбрать информацию для импортирования, или "Отмена" чтобы выйти из этого мастера.
+[It is recommended that you create a backup of your current Miranda profile before importing.]
+Рекомендуется создать резервную копию текущего профиля перед импортированием.
+
+[Choose type of imported files:]
+Выберите тип импортируемых файлов:
+
+[Select files or the whole directory for import:]
+Выберите файлы или целую директорию для импорта:
+[Files...]
+Файлы...
+[Path:]
+Путь:
+[Files:]
+Файлы:
+[Directory...]
+Директория...
+
+[All previous chosen files will try to import to this protocol.]
+Все ранее выбраные файлы будут импортированы в этот протокол.
+[Select protocol or account:]
+Выберите протокол или аккаунт:
+[Click "Next" to start Import or "Cancel" to Abort.]
+Нажмите "Далее" для начала Импорта или "Отмена" для выхода.
+[Now importing...]
+Импортируется...
+
+
+[Select folder for import...]
+Выберите папку для импорта...
+[File: %s]
+Файл: %s
+[To: %s]
+В: %s
+[Can''t determine destination contact]
+Не могу определить контакт назначения
+
+[Default extension]
+Расширение по умолчанию
+[Its not %s file]
+Это не файл %s
diff --git a/plugins/ImportTXT/doc/pattern_cfg_ru.txt b/plugins/ImportTXT/doc/pattern_cfg_ru.txt
new file mode 100644
index 0000000000..e27cf4bb1d
--- /dev/null
+++ b/plugins/ImportTXT/doc/pattern_cfg_ru.txt
@@ -0,0 +1,77 @@
+Структура файла шаблона плагина importtxt начиная с версии 0.0.1.2
+Расширение файла .ini
+
+[General]* Общие параметры
+Name=* Имя шаблона, выводится в списке
+Type=* Тип импорта возможные значения
+ 1 - импорт из текстовых файлов
+ 2 - импорт из бинарных файлов
+*******параметры для импорта текста*********
+Charset=* кодировка ANSI, UTF8, UCS2
+Codepage= кодовая страница для ANSI
+UseHeader= 0..3 - использовать заголовок
+ первый бит использовать заголовок для распознавания направления
+ второй бит использовать заголовок для распознования контакта назначения
+UsePreMsg= 0 - не использовать предварительную обработку сообщений,
+ даже если не используется, то всё равно будут удаляться все переводы строки в конце и в начале
+ 1 - использовать предварительную обработку
+*******параметры для бинарного импорта*********
+BinProcedure= Используется для установки процедуры бинарного импорта (обязательна при Type=2)
+ Возможные значения:
+ 1 - mContacts
+ 2 - QHF
+ 3 - ICQ6
+ 4 - ICQ5
+*******общие параметры*********
+UseFileName= использовать имя файла для определения UID
+DefaultExtension= Расширение файлов по умолчанию (если нет то txt)
+*******параметры для импорта текста*********
+[Message]* Сообщение
+Pattern=* рег. выражение для разбора заголовка сообщения
+In= варианты направления, если нет или пустые то используется из заголовка
+Out= если UseHeader=0 и In пустой, то ошибка
+Direction=* номер подвыражения определяющее направление сообщения (либо жестко заданное либо ник или уин)
+Day=* номер подваражения дня
+Month=* номер подваражения месяца
+Year=* номер подваражения года
+Hours=* номер подваражения часов
+Minutes=* номер подваражения минут
+Seconds= номер подваражения секунд (может быть 0, тогда при импорте принимается за 00)
+
+[Header] Заголовок файла
+Pattern=* рег. выражение заголовка
+In=* подвыражение определяющее то что сообщение входящее (Ник, Уин)
+Out= подвыражение определяющее то что сообщение исходящее (Ник, Уин)
+ может быть 0 или отсутствовать, если при импорте Direction<>In тогда оно исходящее, такая случайная фишка, но очень помогающая
+InNick=* Ник собеседника
+OutNick= Ваш Ник //не используется
+InUID=* UID собеседника
+OutUID= ваш UID //не используется
+
+[PreMessage] Обработка сообщения перед импортом в базу
+PreRN= удалить переводы строк в начале сообщения (целое число или -1 тогда все)
+AfterRN= удалить переводы строк в конце сообщения (целое число или -1 тогда все)
+PreSP= удалить пробелы в начале каждой строки сообщения
+AfterSP= удалить пробелы в конце каждой строки сообщения
+ возможные значения:
+ целое число
+ -1 все
+ -2 кол-во равно длине распознаного шаблона заголовка сообщения (актуально для Message Export)
+ любой параметр может отсутствовать или быть равен нулю, тогда не используется
+ SP использовать только в случае крайней необходимости, потому что замедляется работа
+*******общие параметры*********
+[FileName] Имя файла
+Pattern=* шаблон для распознования
+InNick=* Ник собеседника
+OutNick= Ваш Ник //не используется
+InUID=* UID собеседника
+OutUID= Ваш UID //не используется
+
+
+ * обязательная секция, если указаны UseHeader=1, а секции [Header] нет, то ошибка, аналогично с [PreMessage] и [FileName]
+ * обязательный параметр в секции, если параметр не обязателен то по умолчанию используется либо 0 для PS, либо -1 для RN , либо пустая строка
+ * если в UseHeader включен второй бит, то обязателен либо InUID, либо InNick, приоритетом распознавания является UID
+ * в Имени файла аналогично
+
+ UID означает Уникальный ИДентификатор :) это может быть UIN, JID и т.д.
+ \ No newline at end of file
diff --git a/plugins/ImportTXT/doc/readme_ru.txt b/plugins/ImportTXT/doc/readme_ru.txt
new file mode 100644
index 0000000000..2c7e4c3ebb
--- /dev/null
+++ b/plugins/ImportTXT/doc/readme_ru.txt
@@ -0,0 +1,78 @@
+Import TXT plugin for Miranda IM
+================================
+Плагин предоставляет возможность импортировать историю контактов
+из других клиентов, хранящуюся в текстовых файлах.
+
+Copyright and License
+===============================
+
+Copyright (C) 2008 Andrey Kunitsyn (Abyss) All Rights Reserved
+Some procedures are used written by Alexey Kulakov
+
+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, see <http://www.gnu.org/licenses/>.
+
+
+Установка:
+==========
+1. Сделайте бэкап Базы Миранды
+2. Скопируйте importtxt.dll, папку importtxt и всё её содержимое в папку Plugins каталога Миранды.
+3. Скопируйте файл pcre3.dll в корень миранды или system32
+4. Содержимое файла importtxt_translate.txt добавьте в конец Лангпака
+5. Запустите миранду
+В меню контактов появится пункт "Import history..." ("Импортировать историю")
+В главном меню появиться такой же пункт - это мастер импорта.
+
+Для автостарта мастера нужно прописать в базе ImportTXT/AutoStart значение 1 типа byte
+
+ВАЖНО:
+======
+Обязательно сделайте бэкап базы!
+Файлы шаблонов должны быть в кодировке ANSI.
+
+
+Описание:
+=========
+Плагин написан с нацеленностью на универсальность, вы можете написать
+свои правила разбора файлов и положить в папку importtxt.
+НО есть некоторые ограничения:
+1. Входные файлы могут быть в любой кодировке (ANSI, UTF8, UCS2)
+ (перекодирование происходит с кодовой страницей лангпака, если его нет то с системной)
+2. Каждое сообщение в файле должно содержать заголовок с полной информацией о нем:
+ - направление (входящее или исходящее)
+ - таймштамп (полная дата, полное время (можно без секунд, но это должно быть обозначено в шаблоне)
+ - текст сообщения :)
+3. Начиная с версии 0.0.0.5 поддерживаются входные файлы следующего вида:
+ в файле есть заголовок с никами переписывающихся , в заголовке каждого сообщения есть Ник, но нет направления сообщения
+ (под этот тип подходят файлы экспортируемые History++)
+4. Для массового импорта необходима информация о контакте назначения (UID или Ник), в заголовке файла или имени файла.
+
+Начиная с версии 0.0.1.2 реализована поддержка некоторых бинарных файлов.
+(каких именно смотрите pattern_cfg)
+Начиная с версии 0.0.1.7 добавлен импорт из XML файлов ICQ5 (для импорта нужно ядро не ниже 0.8.0.21)
+
+Примерный алгоритм работы:
+==========================
+В файле ищется регулярное выражение описанное в шаблоне, при помощи подвыражений выделяется дата, время и тд.
+Всё что находится после него и до следующего считается текстом сообщения.
+
+Дубликаты
+=========
+При импорте происходит простая проверка на дубликаты (направление, таймштамп, размер сообщения) как в import.dll
+
+Написание шаблона:
+==================
+Формат файлов шаблона описан в pattern_cfg
+Примеры написания с комментариями в examples
+
+Подробнее о регулярных выражениях вы можете почитать в интернете ;).
diff --git a/plugins/ImportTXT/ico/def_ico.ico b/plugins/ImportTXT/ico/def_ico.ico
new file mode 100644
index 0000000000..eba0fce356
--- /dev/null
+++ b/plugins/ImportTXT/ico/def_ico.ico
Binary files differ
diff --git a/plugins/ImportTXT/importtxt.dpr b/plugins/ImportTXT/importtxt.dpr
new file mode 100644
index 0000000000..c7a1ab303b
--- /dev/null
+++ b/plugins/ImportTXT/importtxt.dpr
@@ -0,0 +1,202 @@
+(*
+ ImportTXT plugin for Miranda IM: the free IM client for Microsoft* Windows*
+
+ Copyright (С) 2008 Abyss
+
+ 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
+*)
+
+{$IMAGEBASE $2080000}
+library importtxt;
+
+uses
+ m_api,
+ Windows,
+ General,
+ ImportTxtDlg,
+ ImportTxtWiz;
+
+{$R imptxt_ver.res}
+{$include m_helpers.inc}
+
+
+const
+ PluginInfo:TPLUGININFOEX=(
+ cbSize :sizeof(TPLUGININFOEX);
+ shortName :'Import TXT';
+ version :$0000010A;
+ description:'Imports history saved in TXT files from other clients.';
+ author :'Abyss';
+ authorEmail:'abyss.andrey@gmail.com';
+ copyright :'(C)2008 Abyss';
+ homepage :'none';
+ flags :UNICODE_AWARE;
+ replacesDefaultModule:0;
+ uuid:'{6F376B33-D3F4-4c4f-A96B-77DA08043B06}';
+ );
+
+// Updater compatibility data
+const
+ VersionURL = 'http://abyss.web.ur.ru/itxt_ver.htm';
+ VersionPrefix = 'Current version: ';
+ UpdateURL = 'http://abyss.web.ur.ru/importtxt.zip';
+ BetaVersionURL = nil;
+ BetaVersionPrefix = nil;
+ BetaUpdateURL = nil;
+ BetaChangelogURL = nil;
+
+var
+ PluginInterfaces:array [0..1] of MUUID;
+ hwndWizard:HWND;
+ hwndDialog:HWND;
+ //Services
+ SrvITxt,SrvIWiz:Cardinal;
+ //hooks
+ onLoadHook:Cardinal;
+ onAccChangHook:Cardinal;
+
+function MirandaPluginInfo(mirandaVersion:DWORD):PPLUGININFOEX; cdecl;
+begin
+ MirVers:=mirandaVersion;
+ result:=@PluginInfo;
+ //PluginInfo.cbSize:=SizeOf(TPLUGININFO);
+end;
+
+function MirandaPluginInfoEx(mirandaVersion:DWORD):PPLUGININFOEX; cdecl;
+begin
+ MirVers:=mirandaVersion;
+ result:=@PluginInfo;
+ //PluginInfo.cbSize:=SizeOf(TPLUGININFOEX);
+end;
+
+function ContactMenuCommand(wParam: WPARAM; lParam: LPARAM): Integer; cdecl;
+begin
+ Result := 0;
+ if IsWindow(hwndDialog) then
+ begin
+ SetForegroundWindow(hwndDialog);
+ BringWindowToTop(hwndDialog);
+ end
+ else
+ hwndDialog:=CreateDialogParamW(hInstance,MAKEINTRESOURCEW(IDD_IMPDIALOG),0,@IDMainWndProc, wParam);
+end;
+
+function MainMenuCommand(wParam: WPARAM; lParam: LPARAM): Integer; cdecl;
+begin
+ Result:=0;
+ if (IsWindow(hwndWizard)) then
+ begin
+ SetForegroundWindow(hwndWizard);
+ BringWindowToTop(hwndWizard);
+ end
+ else
+ hwndWizard:=CreateDialogW(hInstance, MAKEINTRESOURCEW(IDD_IMPWIZARD), 0, @WizardDlgProc);
+end;
+
+function OnAccountChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl;
+begin
+ Result:=0;
+ EnumProtocols;
+ if Assigned(OnAccountListChange) then OnAccountListChange;
+end;
+
+function OnModulesLoaded(wParam:WPARAM;lParam:LPARAM):int;cdecl;
+var upd: TUpdate;
+ buf:array [0..63] of char;
+begin
+ PluginLink^.UnhookEvent(onloadhook);
+ Result:=0;
+ EnumProtocols;
+ // Register in updater
+ if Boolean(PluginLink.ServiceExists(MS_UPDATE_REGISTER)) then
+ begin
+ ZeroMemory(@upd,SizeOf(upd));
+ upd.cpbVersion := SizeOf(upd);
+ upd.szComponentName := PluginInfo.ShortName;;
+ upd.pbVersion := CreateVersionStringPlugin(@pluginInfo,buf);
+ upd.cpbVersion := lstrlen(upd.pbVersion);
+ upd.szUpdateURL := UpdateURL;
+ upd.szVersionURL := VersionURL;
+ upd.pbVersionPrefix := VersionPrefix;
+ upd.cpbVersionPrefix := Length(VersionPrefix);
+ upd.szBetaUpdateURL := BetaUpdateURL;
+ upd.szBetaVersionURL := BetaVersionURL;
+ upd.pbBetaVersionPrefix := BetaVersionPrefix;
+ upd.cpbBetaVersionPrefix := length(upd.pbBetaVersionPrefix);
+ upd.szBetaChangelogURL := BetaChangelogURL;
+ PluginLink.CallService(MS_UPDATE_REGISTER, 0, DWORD(@upd));
+ end;
+ //check for AutoStart
+ if (DBReadByte(0,IMPORT_TXT_MODULE,IMPORT_TXT_AS)=1) and
+ (ProtoCount>0) then
+ begin
+ pluginLink^.CallService(IMPORT_WIZ_SERVICE,0,0);
+ DBWriteByte(0,IMPORT_TXT_MODULE,IMPORT_TXT_AS,0);
+ end;
+end;
+
+
+function Load(link: PPLUGINLINK): int; cdecl;
+var
+ mi: TCListMenuItem;
+begin
+ PLUGINLINK := Pointer(link);
+ IsMirandaUnicode:=fIsMirandaUnicode;
+ cp:=pluginLink^.CallService(MS_LANGPACK_GETCODEPAGE, 0, 0);
+ SrvITxt:=pluginLink^.CreateServiceFunction(IMPORT_TXT_SERVICE, @ContactMenuCommand);
+ SrvIWiz:=pluginLink^.CreateServiceFunction(IMPORT_WIZ_SERVICE, @MainMenuCommand);
+ FillChar(mi, sizeof(mi), 0);
+ mi.cbSize := sizeof(mi);
+ mi.flags := 0;
+ mi.position := 1000090050;
+ mi.hIcon := LoadIcon(hInstance,MAKEINTRESOURCE(IDI_DEFAULT));
+ mi.szName.a := 'Import history';
+ mi.pszService := IMPORT_TXT_SERVICE;
+ mi.pszContactOwner:=nil; //All contacts
+ pluginLink^.CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, int(@mi));
+ mi.position := 500050010;
+ mi.pszService := IMPORT_WIZ_SERVICE;
+ mi.pszContactOwner:=nil;
+ pluginLink^.CallService(MS_CLIST_ADDMAINMENUITEM, 0, int(@mi));
+ onloadhook:=PluginLink^.HookEvent(ME_SYSTEM_MODULESLOADED,@OnModulesLoaded);
+ if MirVers>080000 then onAccChangHook:=pluginLink^.HookEvent(ME_PROTO_ACCLISTCHANGED,@OnAccountChanged);
+ Result := 0;
+end;
+
+function Unload: int; cdecl;
+begin
+ if MirVers>080000 then pluginLink^.UnhookEvent(onAccChangHook);
+ pluginlink^.DestroyServiceFunction(SrvITxt);
+ pluginlink^.DestroyServiceFunction(SrvIWiz);
+ Result := 0;
+end;
+
+function MirandaPluginInterfaces:PMUUID; cdecl;
+begin
+ PluginInterfaces[0]:=PluginInfo.uuid;
+ PluginInterfaces[1]:=MIID_LAST;
+ result:=@PluginInterfaces;
+end;
+
+
+exports
+
+ Load, Unload,
+ MirandaPluginInfo,
+ MirandaPluginInfoEx,
+ MirandaPluginInterfaces;
+
+begin
+end.
diff --git a/plugins/ImportTXT/importtxt/ICQ5_p.ini b/plugins/ImportTXT/importtxt/ICQ5_p.ini
new file mode 100644
index 0000000000..d2f468af7d
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/ICQ5_p.ini
@@ -0,0 +1,9 @@
+[General]
+Name=ICQ5 xml files import
+Type=2
+BinProcedure=4
+DefaultExtension=xml
+UseFileName=1
+[FileName]
+Pattern=^[^\r\n]+?\\(\d{5,})-(\d{4,})\.xml$
+InUID=1 \ No newline at end of file
diff --git a/plugins/ImportTXT/importtxt/ICQ6_p.ini b/plugins/ImportTXT/importtxt/ICQ6_p.ini
new file mode 100644
index 0000000000..1d9984962a
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/ICQ6_p.ini
@@ -0,0 +1,5 @@
+[General]
+Name=ICQ6 database
+Type=2
+BinProcedure=3
+DefaultExtension=mdb \ No newline at end of file
diff --git a/plugins/ImportTXT/importtxt/MAgent_p.ini b/plugins/ImportTXT/importtxt/MAgent_p.ini
new file mode 100644
index 0000000000..6b54883d78
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/MAgent_p.ini
@@ -0,0 +1,23 @@
+[General]
+Name=MobileAgent import pattern
+Type=1
+Charset=UCS2
+UsePreMsg=1
+UseFileName=1
+[Message]
+Pattern=^---------------------------([<>])--\r\n([^\r\n]+?)\s\((\d\d?).(\d\d?).(\d\d\d?\d?)\s(\d\d?).(\d\d?).(\d\d?)\)$
+In=>
+Out=<
+Direction=1
+Day=3
+Month=4
+Year=5
+Hours=6
+Minutes=7
+Seconds=8
+[PreMessage]
+PreRN=1
+AfterRN=2
+[FileName]
+Pattern=^[^\r\n]+?\\(\d{5,})\.txt$
+InUID=1
diff --git a/plugins/ImportTXT/importtxt/QHF_p.ini b/plugins/ImportTXT/importtxt/QHF_p.ini
new file mode 100644
index 0000000000..b6eb687502
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/QHF_p.ini
@@ -0,0 +1,5 @@
+[General]
+Name=QHF files import pattern (QIP PDA and Infinum)
+Type=2
+BinProcedure=2
+DefaultExtension=qhf \ No newline at end of file
diff --git a/plugins/ImportTXT/importtxt/SEmidprms_p.ini b/plugins/ImportTXT/importtxt/SEmidprms_p.ini
new file mode 100644
index 0000000000..ca0637d8f6
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/SEmidprms_p.ini
@@ -0,0 +1,5 @@
+[General]
+Name=Jimm midp-rms SonyEricsson
+Type=2
+BinProcedure=5
+DefaultExtension=d \ No newline at end of file
diff --git a/plugins/ImportTXT/importtxt/bayanICQ_p.ini b/plugins/ImportTXT/importtxt/bayanICQ_p.ini
new file mode 100644
index 0000000000..f85bb397e5
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/bayanICQ_p.ini
@@ -0,0 +1,9 @@
+[General]
+Name=bayanICQ import pattern
+Type=2
+BinProcedure=6
+DefaultExtension=hf
+UseFileName=1
+[FileName]
+Pattern=^[^\r\n]+?\\hist(\d{5,})\.hf$
+InUID=1 \ No newline at end of file
diff --git a/plugins/ImportTXT/importtxt/dichat_p.ini b/plugins/ImportTXT/importtxt/dichat_p.ini
new file mode 100644
index 0000000000..3fd5c6a25e
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/dichat_p.ini
@@ -0,0 +1,24 @@
+[General]
+Name=D[i]Chat import pattern
+Type=1
+Charset=ANSI
+UseHeader=2
+UsePreMsg=1
+[Message]
+Pattern=^---(<<<|>>>)---\r\n\s([^\r\n]+?)\s\((\d\d?)\.(\d\d?)\.(\d\d\d?\d?)\s(\d\d?):(\d\d?):(\d\d?)\):$
+In=<<<
+Out=>>>
+Direction=1
+Day=3
+Month=4
+Year=5
+Hours=6
+Minutes=7
+Seconds=8
+[PreMessage]
+PreRN=1
+AfterRN=2
+[Header]
+Pattern=^\tИстория сообщений с ([^\r\n]+?)\s\((\d{5,})\)\r\n\tСохранено из D\[i\]Chat\s[^\r\n]+?\r\n
+InNick=1
+InUID=2 \ No newline at end of file
diff --git a/plugins/ImportTXT/importtxt/historypp_p.ini b/plugins/ImportTXT/importtxt/historypp_p.ini
new file mode 100644
index 0000000000..7d5e353e48
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/historypp_p.ini
@@ -0,0 +1 @@
+[General] Name=History++ pattern Type=1 Charset=UCS2 UseHeader=3 UsePreMsg=1 [Message] Pattern=^\[(\d\d?)\.(\d\d?)\.(\d\d\d?\d?)\s(\d\d?):(\d\d?):(\d\d?)\]\s([^\r\n]+?):$ Direction=7 Day=1 Month=2 Year=3 Hours=4 Minutes=5 Seconds=6 [Header] Pattern=^###\r\n###\s[^\r\n]+?\r\n###\s([^\r\n]+?)\s\([^\r\n]+?:\s([^\r\n]+?)\)\s-\s([^\r\n]+?)\s\([^\r\n]+?:\s([^\r\n]+?)\)\r\n###\s[^\r\n]+?\r\n###\r\n In=3 Out=1 InNick=3 OutNick=1 InUID=4 OutUID=2 [PreMessage] PreRN=1 AfterRN=2 \ No newline at end of file
diff --git a/plugins/ImportTXT/importtxt/jimm_p.ini b/plugins/ImportTXT/importtxt/jimm_p.ini
new file mode 100644
index 0000000000..10d9ab2100
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/jimm_p.ini
@@ -0,0 +1,24 @@
+[General]
+Name=Jimm import pattern
+Type=1
+Charset=ANSI
+UseHeader=2
+UsePreMsg=1
+[Message]
+Pattern=^------------------------------------(<<<|>>>)-\r\n\s([^\r\n]+?)\s\((\d\d?)\.(\d\d?)\.(\d\d\d?\d?)\s(\d\d?):(\d\d?):(\d\d?)\):$
+In=<<<
+Out=>>>
+Direction=1
+Day=3
+Month=4
+Year=5
+Hours=6
+Minutes=7
+Seconds=8
+[PreMessage]
+PreRN=1
+AfterRN=2
+[Header]
+Pattern=^\r\n\tИстория сообщений с ([^\r\n]+?)\s\((\d{5,})\)\r\n\tСохранено из Jimm\s[^\r\n]+?\r\n
+InNick=1
+InUID=2
diff --git a/plugins/ImportTXT/importtxt/jimmws2_p.ini b/plugins/ImportTXT/importtxt/jimmws2_p.ini
new file mode 100644
index 0000000000..8f0baa9b1f
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/jimmws2_p.ini
@@ -0,0 +1,22 @@
+[General]
+Name=Jimm import pattern(without seconds) modified
+Type=1
+Charset=ANSI
+UseHeader=3
+UsePreMsg=1
+[Message]
+Pattern=([^\r\n]+?)\s\((\d\d?)\.(\d\d?)\.(\d\d\d?\d?)\s(\d\d?):(\d\d?)\):\r\n
+Direction=1
+Day=2
+Month=3
+Year=4
+Hours=5
+Minutes=6
+[PreMessage]
+PreRN=1
+AfterRN=2
+[Header]
+Pattern=^\r\n\tИстория сообщений с ([^\r\n]+?)\s\((\d{5,})\)\r\n\tСохранено из Jimm\s[^\r\n]+?\r\n
+In=1
+InNick=1
+InUID=2
diff --git a/plugins/ImportTXT/importtxt/jimmws_p.ini b/plugins/ImportTXT/importtxt/jimmws_p.ini
new file mode 100644
index 0000000000..59c609fd50
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/jimmws_p.ini
@@ -0,0 +1,23 @@
+[General]
+Name=Jimm import pattern(without seconds)
+Type=1
+Charset=ANSI
+UseHeader=2
+UsePreMsg=1
+[Message]
+Pattern=^------------------------------------(<<<|>>>)-\r\n\s([^\r\n]+?)\s\((\d\d?)\.(\d\d?)\.(\d\d\d?\d?)\s(\d\d?):(\d\d?)\):$
+In=<<<
+Out=>>>
+Direction=1
+Day=3
+Month=4
+Year=5
+Hours=6
+Minutes=7
+[PreMessage]
+PreRN=1
+AfterRN=2
+[Header]
+Pattern=^\r\n\tИстория сообщений с ([^\r\n]+?)\s\((\d{5,})\)\r\n\tСохранено из Jimm\s[^\r\n]+?\r\n
+InNick=1
+InUID=2
diff --git a/plugins/ImportTXT/importtxt/mContact_p.ini b/plugins/ImportTXT/importtxt/mContact_p.ini
new file mode 100644
index 0000000000..925c712330
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/mContact_p.ini
@@ -0,0 +1,9 @@
+[General]
+Name=mContact import pattern
+Type=2
+BinProcedure=1
+UseFileName=1
+DefaultExtension=dat
+[FileName]
+Pattern=^[^\r\n]+?\\([^\r\n\\]+?)\.dat$
+InNick=1 \ No newline at end of file
diff --git a/plugins/ImportTXT/importtxt/msgexport_p.ini b/plugins/ImportTXT/importtxt/msgexport_p.ini
new file mode 100644
index 0000000000..933df10808
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/msgexport_p.ini
@@ -0,0 +1,23 @@
+[General]
+Name=Message export import pattern
+Type=1
+Charset=UTF8
+UseHeader=3
+UsePreMsg=1
+[Message]
+Pattern=^([^\r\n]+?)[\s]+?(\d\d?)\.(\d\d?)\.(\d\d\d?\d?)\s(\d\d?):(\d\d?):(\d\d?)\s
+Direction=1
+Day=2
+Month=3
+Year=4
+Hours=5
+Minutes=6
+Seconds=7
+[Header]
+Pattern=^------------------------------------------------\r\n[\s]+?History for\r\nUser[\s]+?:\s([^\r\n]+?)\r\n(.*\r\n)+?Nick[\s]+?:\s([^\r\n]+?)\s\r\n(.*\r\n)+?^------------------------------------------------$
+In=1
+InNick=3
+[PreMessage]
+PreRN=0
+AfterRN=1
+PreSP=-2 \ No newline at end of file
diff --git a/plugins/ImportTXT/importtxt/nokmidprms_p.ini b/plugins/ImportTXT/importtxt/nokmidprms_p.ini
new file mode 100644
index 0000000000..d743b1a9df
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/nokmidprms_p.ini
@@ -0,0 +1,9 @@
+[General]
+Name=Jimm midp-rms Nokia
+Type=2
+BinProcedure=5
+DefaultExtension=rms
+UseFileName=1
+[FileName]
+Pattern=^[^\r\n]+?\\Jimm_m_hist(\d{5,})\.rms$
+InUID=1 \ No newline at end of file
diff --git a/plugins/ImportTXT/importtxt/pigeon_p.ini b/plugins/ImportTXT/importtxt/pigeon_p.ini
new file mode 100644
index 0000000000..7487075089
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/pigeon_p.ini
@@ -0,0 +1,23 @@
+[General]
+Name=Pigeon import pattern
+Type=1
+Charset=ANSI
+UsePreMsg=1
+UseFileName=1
+[Message]
+Pattern=^\[(I|O)\s(\d\d?)\.(\d\d?)\.(\d\d\d?\d?)\s(\d\d?):(\d\d?):(\d\d?)\]$
+In=I
+Out=O
+Direction=1
+Day=2
+Month=3
+Year=4
+Hours=5
+Minutes=6
+Seconds=7
+[PreMessage]
+PreRN=1
+AfterRN=2
+[FileName]
+Pattern=^[^\r\n]+?\\msg_(\d{5,})\.txt$
+InUID=1 \ No newline at end of file
diff --git a/plugins/ImportTXT/importtxt/qip_p.ini b/plugins/ImportTXT/importtxt/qip_p.ini
new file mode 100644
index 0000000000..ddb112f8f5
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/qip_p.ini
@@ -0,0 +1,23 @@
+[General]
+Name=QIP import pattern
+Type=1
+Charset=ANSI
+UsePreMsg=1
+UseFileName=1
+[Message]
+Pattern=^--------------------------------------([<>])-\r\n([^\r\n]+?)\s\((\d\d?):(\d\d?):(\d\d?)\s(\d\d?)/(\d\d?)/(\d\d\d?\d?)\)$
+In=<
+Out=>
+Direction=1
+Day=6
+Month=7
+Year=8
+Hours=3
+Minutes=4
+Seconds=5
+[PreMessage]
+PreRN=1
+AfterRN=2
+[FileName]
+Pattern=^[^\r\n]+?\\(\d{5,})\.txt$
+InUID=1
diff --git a/plugins/ImportTXT/importtxt/smaper_p.ini b/plugins/ImportTXT/importtxt/smaper_p.ini
new file mode 100644
index 0000000000..d02eedae78
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/smaper_p.ini
@@ -0,0 +1,23 @@
+[General]
+Name=Smaper(vmICQ) import pattern
+Type=1
+Charset=UCS2
+UsePreMsg=1
+UseFileName=1
+[Message]
+Pattern=^(<-|->)\s\((\d\d?)\.(\d\d?)\.(\d\d\d?\d?)\s(\d\d?)\.(\d\d?)\.(\d\d?)\)$
+In=<-
+Out=->
+Direction=1
+Day=2
+Month=3
+Year=4
+Hours=5
+Minutes=6
+Seconds=7
+[PreMessage]
+PreRN=1
+AfterRN=2
+[FileName]
+Pattern=^[^\r\n]+?\\(\d{5,})\.txt$
+InUID=1 \ No newline at end of file
diff --git a/plugins/ImportTXT/importtxt/smapern_p.ini b/plugins/ImportTXT/importtxt/smapern_p.ini
new file mode 100644
index 0000000000..cce53f048c
--- /dev/null
+++ b/plugins/ImportTXT/importtxt/smapern_p.ini
@@ -0,0 +1,23 @@
+[General]
+Name=Smaper (with Nick) import pattern
+Type=1
+Charset=UCS2
+UsePreMsg=1
+UseFileName=1
+[Message]
+Pattern=^(<-|->)\s[^\r\n]+?\s\((\d\d?)\.(\d\d?)\.(\d\d\d?\d?)\s(\d\d?)\.(\d\d?)\.(\d\d?)\)$
+In=<-
+Out=->
+Direction=1
+Day=2
+Month=3
+Year=4
+Hours=5
+Minutes=6
+Seconds=7
+[PreMessage]
+PreRN=1
+AfterRN=2
+[FileName]
+Pattern=^[^\r\n]+?\\(\d{5,})\.txt$
+InUID=1 \ No newline at end of file
diff --git a/plugins/ImportTXT/importtxtdlg.pas b/plugins/ImportTXT/importtxtdlg.pas
new file mode 100644
index 0000000000..84f1c3a6cf
--- /dev/null
+++ b/plugins/ImportTXT/importtxtdlg.pas
@@ -0,0 +1,233 @@
+unit ImportTxtDlg;
+
+interface
+
+uses
+ m_api,
+ Windows, Messages, SysUtils, CommDlg, IniFiles,
+ ImportThrd, general, ImportTU, FileDlgs;
+
+
+{$I ImpDlgRes.inc}
+
+
+function IDMainWndProc(Dialog:HWnd; hMessage,wParam,lParam:DWord):integer; stdcall;
+function GetContactDisplayName(hContact:THandle):string;
+
+implementation
+
+{$R ImpTxtDlg.res}
+
+type TImpTxtDlgData = record
+ cbSize:integer;
+ CanStart:boolean;
+ ChoFile:boolean;
+ ChoPatt:boolean;
+ PattFError:boolean;
+ ITStarted:boolean;
+ ITFinished:boolean;
+ StartTime:TDateTime;
+ FinishTime:TDateTime;
+ IndexOfPattern:integer;
+ oFN:integer;
+ hContact:THandle;
+ ImportThrd:TImportThrd;
+ end;
+
+type PImpTxtDlgData = ^TImpTxtDlgData;
+
+var ITDD:TImpTxtDlgData;
+
+function GetContactDisplayName(hContact:THandle):string;
+begin
+ Result := PChar(pluginLink^.CallService(MS_CLIST_GETCONTACTDISPLAYNAME,hContact,0));
+end;
+
+procedure AddStatusMessage(hDLG:HWND; msg:WideString);
+begin
+ SendDlgItemMessageW(hDLG,IDC_STATUSLIST,LB_SETCURSEL,SendDlgItemMessageW(hDLG,IDC_STATUSLIST,LB_ADDSTRING,0,dword(PWideChar(msg))),0);
+end;
+
+procedure FillComboBox(hDlg:hWnd); //Заполняем список именами шаблонов
+var
+ i:integer;
+begin
+ ITDD.PattFError:=true;
+ ReadPatterns;
+ SendDlgItemMessage(hDlg,IDC_TYPECOMBO,CB_RESETCONTENT,0,0);
+ if PatternsCount>0 then
+ begin
+ For i:=0 to PatternsCount-1 do
+ SendDlgItemMessage(hDlg,IDC_TYPECOMBO,CB_ADDSTRING,0,Integer(PatternNames[i]));
+ ITDD.PattFError:=false;
+ end
+ else
+ begin
+ AddStatusMessage(hDlg,TranslateWideString('No Files Patterns Found'));
+ EnableWindow(GetDlgItem(hDlg, IDC_TYPECOMBO), FALSE);
+ ITDD.ChoPatt:=false;
+ end;
+end;
+
+procedure MStart(hDlg:hWnd); //проверяем всё ли сделано чтоб начать импорт
+begin
+with ITDD do
+begin
+if ChoFile and ChoPatt and (not PattFError) then
+ begin
+ CanStart:=true;
+ EnableWindow(GetDlgItem(hDlg, IDSTART), TRUE);
+ end
+ else
+ begin
+ CanStart:=false;
+ EnableWindow(GetDlgItem(hDlg, IDSTART), FALSE);
+ end;
+end;
+end;
+
+
+function IDMainWndProc(Dialog:HWnd; hMessage,wParam,lParam:DWord):integer; stdcall;
+//Процедура окна диалога
+var
+ s:WideString;
+ tempwstr:PWideChar;
+
+var H,Mi,sec,ms:word;
+
+begin
+ result:=0;
+ case hMessage of
+ WM_DESTROY: begin
+ if ITDD.ImportThrd<>Nil then ITDD.ImportThrd.Terminate;
+ SetLastPattern(SendDlgItemMessage(Dialog, IDC_TYPECOMBO, CB_GETCURSEL, 0, 0));
+ end;
+ WM_INITDIALOG: begin
+ TranslateDialogDefault(Dialog);
+ tempwstr:=ANSIToWide(PChar(GetContactDisplayName(lParam)),tempwstr,cp);
+ s:=WideFormat(TranslateWideString('Import history to %s (%s)'),[tempwstr,GetContactID(lParam)]);
+ SetWindowTextW(Dialog,PWideChar(s));
+ SendMessage(Dialog,WM_SETICON,ICON_SMALL,LoadIcon(hInstance,MAKEINTRESOURCE(IDI_DEFAULT)));
+ FillChar(ITDD,SizeOf(TImpTxtDlgData),0);
+ with ITDD do begin
+ cbSize:=SizeOf(TImpTxtDlgData);
+ hContact:=lParam;
+ CanStart:=false;
+ ChoFile:=false;
+ ChoPatt:=true;
+ PattFError:=false;
+ ITStarted:=false;
+ ITFinished:=false;
+ end;
+
+ FillComboBox(Dialog);
+ SendDlgItemMessage(Dialog, IDC_TYPECOMBO, CB_SETCURSEL, GetLastPattern, 0);
+ ITDD.IndexOfPattern:=GetLastPattern;
+ MStart(Dialog);
+ CheckDlgButton(Dialog,IDC_CHKDUP,BST_CHECKED);
+ CheckForDuplicates:=true;
+ CheckDlgButton(Dialog,IDC_SHOWDUP,BST_UNCHECKED);
+ CheckForDuplicates:=false;
+ ShowWindow(Dialog,SW_NORMAL);
+ end;
+ WM_COMMAND: begin
+ if (HiWord(wParam)=CBN_SELCHANGE) and (LoWord(wParam)=IDC_TYPECOMBO) then //Сделали выбор шаблона
+ begin
+ ITDD.ChoPatt:=true;
+ ITDD.IndexOfPattern:=SendDlgItemMessage(Dialog, IDC_TYPECOMBO, CB_GETCURSEL, 0, 0);
+ MStart(Dialog);
+ end;
+ if (HiWord(wParam)=BN_CLICKED) and (LoWord(wParam)=IDC_CHKDUP) then
+ if LongBool(IsDlgButtonChecked(Dialog,IDC_CHKDUP)) then EnableWindow(GetDlgItem(Dialog, IDC_SHOWDUP), TRUE)
+ else EnableWindow(GetDlgItem(Dialog, IDC_SHOWDUP), FALSE);
+ case loword(wParam) of
+ IDCLOSE: DestroyWindow(Dialog);
+ IDC_BRWSBTN: begin //Нажали кнопку "..."
+ s:=OpenDialogExecute(Dialog,0,ITDD.oFN,TxtPatterns[ITDD.IndexOfPattern].DefExtension);
+ if s<>'' then ITDD.ChoFile:=true
+ else ITDD.ChoFile:=false;
+ SendDlgItemMessageW(Dialog, IDC_FILENAME,WM_SETTEXT,0,dword(PWideChar(s)));
+ MStart(Dialog);
+ end;
+ IDSTART: begin //Старт
+ with ITDD do
+ if CanStart then
+ begin
+ EnableWindow(GetDlgItem(Dialog, IDSTART), FALSE);
+ EnableWindow(GetDlgItem(Dialog, IDCLOSE), FALSE);
+ EnableWindow(GetDlgItem(Dialog, IDC_TYPECOMBO), FALSE);
+ EnableWindow(GetDlgItem(Dialog, IDC_BRWSBTN), FALSE);
+ ImportThrd:=TImportThrd.Create(TRUE);
+ ImportThrd.FreeOnTerminate:=true;
+ ImportThrd.DContact.hContact:=hContact;
+ CheckForDuplicates:=LongBool(IsDlgButtonChecked(Dialog,IDC_CHKDUP));
+ ShowDuplicates:=LongBool(IsDlgButtonChecked(Dialog,IDC_SHOWDUP));
+ h:=SendDlgItemMessageW(Dialog, IDC_FILENAME,WM_GETTEXTLENGTH,0,0)+1;
+ SetLength(s,h);
+ SendDlgItemMessageW(Dialog, IDC_FILENAME,WM_GETTEXT,h,dword(PWideChar(s)));
+ ImportThrd.FileNames:=s+#0+#0;
+ ImportThrd.OffsetFileName:=oFN;
+ ImportThrd.WorkPattern:=TxtPatterns[IndexOfPattern];
+ ImportThrd.ParentHWND:=Dialog;
+ ImportThrd.Resume;
+ end;
+ end;
+ end;
+ end;
+ WM_CLOSE: begin
+ DestroyWindow(Dialog);
+ end;
+ //Далее оброботка сообщений от потока импорта
+ //Начали
+ ITXT_THREAD_ALLSTARTED:begin
+ ITDD.ITStarted:=true;
+ ITDD.StartTime:=Time;
+ end;
+ ITXT_THREAD_START:begin
+ AddStatusMessage(Dialog,TranslateWideString('Import started...'));
+ end;
+ //Известна длинна файла выставляем диапазон прогрессбара
+ ITXT_THREAD_MAXPROGRESS:
+ SendDlgItemMessage(Dialog,IDC_PROGRESS,PBM_SETRANGE,0,MakeLParam(0,lParam));
+ //Идет прогресс ...
+ ITXT_THREAD_PROGRESS:
+ SendDlgItemMessage(Dialog,IDC_PROGRESS,PBM_SETPOS,wParam,0);
+ //Возникла ошибка
+ ITXT_THREAD_ERROR:
+ AddStatusMessage(Dialog,TranslateWideString(PWideChar(wParam)));
+ //Закончили
+ ITXT_THREAD_FINISH:begin
+ ITDD.ITFinished:=true;
+ ITDD.FinishTime:=Time;
+ DecodeTime(ITDD.FinishTime-ITDD.StartTime,h,mi,sec,ms);
+ AddStatusMessage(Dialog,WideFormat(TranslateWideString('Added: %d messages'),[wParam]));
+ AddStatusMessage(Dialog,WideFormat(TranslateWideString('Duplicates: %d messages'),[lParam]));
+ AddStatusMessage(Dialog,WideFormat(TranslateWideString('In: %d:%d:%d'),[h,mi,sec]));
+ AddStatusMessage(Dialog,'');
+ SendDlgItemMessageW(Dialog, IDC_FILENAME,WM_SETTEXT,0,0);
+ ITDD.ChoFile:=false;
+ EnableWindow(GetDlgItem(Dialog, IDC_TYPECOMBO), TRUE);
+ EnableWindow(GetDlgItem(Dialog, IDC_BRWSBTN), TRUE);
+ EnableWindow(GetDlgItem(Dialog, IDCLOSE), TRUE);
+ end;
+ //начали новый файл
+ ITXT_THREAD_START_FILE:
+ AddStatusMessage(Dialog,WideFormat(TranslateWideString('File: %s'),[PWideChar(wParam)]));
+ //определили контакт
+ ITXT_THREAD_DEST_CONTACT:begin
+ if IsMirandaUnicode then
+ begin
+ tempwstr:=UTF8toWide(PChar(GetContactID(wParam,'',true)),tempwstr);
+ s:= tempwstr;
+ tempwstr:=UTF8toWide(PChar(GetContactNick(wParam,'',true)),tempwstr);
+ s:=s + ' | ' + tempwstr;
+ end
+ else
+ s:=GetContactID(wParam,'',true)+' | '+GetContactNick(wParam,'',true);
+
+ AddStatusMessage(Dialog,WideFormat(TranslateWideString('To: %s'),[s]));
+ end;
+ end;
+end;
+
+end. \ No newline at end of file
diff --git a/plugins/ImportTXT/make.bat b/plugins/ImportTXT/make.bat
new file mode 100644
index 0000000000..fc878f2509
--- /dev/null
+++ b/plugins/ImportTXT/make.bat
@@ -0,0 +1,10 @@
+set COMPDIR=-$A8 -$D- -$J+ -$L- -$O+ -$Q- -$R- -$Y- -$C-
+set INCDIR="c:\program files\borland\delphi7\lib\kol;..\..\include;"
+set OUTDIR="..\plugins"
+set DCUDIR="tmp"
+md %DCUDIR% 2>nul
+brcc32 -foImpTxt_Ver.res ImpTxt_Ver.rc
+brcc32 -foImpTxtDlg.res ImpTxtDlg.rc
+brcc32 -foImpTxtWiz.res ImpTxtWiz.rc
+dcc32 -B -CG -U%INCDIR% -R%INCDIR% -I%INCDIR% -E%OUTDIR% -LE%DCUDIR% -LN%DCUDIR% -N%DCUDIR% %COMPDIR% importtxt.dpr
+rd /q /s %DCUDIR% \ No newline at end of file