plugy/PlugYLocal/PlugYLocal.dpr

824 lines
28 KiB
ObjectPascal
Raw Normal View History

library PlugYLocal;
//Created by L'Autour
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
2016-04-20 03:23:52 +00:00
KOL; //library from http://www.kolmck.net/
//SysUtils,
//Classes;
{$R *.res}
type
TLocalStr = record
name: AnsiString;
value: WideString;
end;
TStrType = record
k: AnsiString;
s: WideString;
case Byte of
0: (dw: Cardinal);
1: (c: array[0..3] of AnsiChar);
end;
const
NamePlugyLocal = 'Plugy\PlugYLocal.ini';
MaxStr = 52;
MaxLng = 11;
MaxType = 97;
MaxIdxType = 41;
sLng: array[0..MaxLng] of AnsiString =
('ENG','ESP','DEU','FRA','POR','ITA','JPN','KOR','SIN','CHI','POL','RUS');
var
Gender: WideString = '';
StrTypes: array[0..MaxType + 1] of TStrType = (
(k: ''; s: 'Shield (Not Class Specific)'; c: ('s','h','i','e')),
(k: ''; s: 'Body Armor'; c: ('t','o','r','s')),
(k: 'Gold'; s: 'Gold'; c: ('g','o','l','d')),
(k: 'aqv'; s: 'Arrows'; c: ('b','o','w','q')),
(k: 'cqv'; s: 'Bolts'; c: ('x','b','o','q')),
(k: 'ear'; s: 'Ear'; c: ('p','l','a','y')),
(k: 'hrb'; s: 'Herb'; c: ('h','e','r','b')),
(k: ''; s: 'Potion'; c: ('p','o','t','i')),
(k: 'rin'; s: 'Ring'; c: ('r','i','n','g')),
(k: 'elx'; s: 'Elixir'; c: ('e','l','i','x')),
(k: 'amu'; s: 'Amulet'; c: ('a','m','u','l')),
(k: ''; s: 'Charm'; c: ('c','h','a','r')),
(k: 'lbt'; s: 'Boots'; c: ('b','o','o','t')),
(k: ''; s: 'Gloves'; c: ('g','l','o','v')),
(k: ''; s: 'Book'; c: ('b','o','o','k')),
(k: 'mbl'; s: 'Belt'; c: ('b','e','l','t')),
(k: ''; s: 'Gem'; c: ('g','e','m',' ')),
(k: 'tch'; s: 'Torch'; c: ('t','o','r','c')),
(k: ''; s: 'Scroll'; c: ('s','c','r','o')),
(k: 'scp'; s: 'Scepter'; c: ('s','c','e','p')),
(k: 'wnd'; s: 'Wand'; c: ('w','a','n','d')),
(k: ''; s: 'Staff'; c: ('s','t','a','f')),
(k: ''; s: 'Bow'; c: ('b','o','w',' ')),
(k: 'axe'; s: 'Axe'; c: ('a','x','e',' ')),
(k: 'clb'; s: 'Club'; c: ('c','l','u','b')),
(k: ''; s: 'Sword'; c: ('s','w','o','r')),
(k: ''; s: 'Hammer'; c: ('h','a','m','m')),
(k: ''; s: 'Knife'; c: ('k','n','i','f')),
(k: 'spr'; s: 'Spear'; c: ('s','p','e','a')),
(k: ''; s: 'Polearm'; c: ('p','o','l','e')),
(k: 'mxb'; s: 'Crossbow'; c: ('x','b','o','w')),
(k: 'mac'; s: 'Mace'; c: ('m','a','c','e')),
(k: 'hlm'; s: 'Helm'; c: ('h','e','l','m')),
(k: ''; s: 'Missile Potion'; c: ('t','p','o','t')),
(k: ''; s: 'Quest Item'; c: ('q','u','e','s')),
(k: ''; s: 'Body Part'; c: ('b','o','d','y')),
(k: 'key'; s: 'Key'; c: ('k','e','y',' ')),
(k: 'tkf'; s: 'Throwing Knife'; c: ('t','k','n','i')),
(k: 'tax'; s: 'Throwing Axe'; c: ('t','a','x','e')),
(k: 'jav'; s: 'Javelin'; c: ('j','a','v','e')),
(k: ''; s: 'Weapon'; c: ('w','e','a','p')),
(k: ''; s: 'Melee Weapon'; c: ('m','e','l','e')),
(k: ''; s: 'Missile Weapon'; c: ('m','i','s','s')),
(k: ''; s: 'Throwing Weapon'; c: ('t','h','r','o')),
(k: ''; s: 'Combo Weapon'; c: ('c','o','m','b')),
(k: ''; s: 'Armor'; c: ('a','r','m','o')),
(k: ''; s: 'Any Shield'; c: ('s','h','l','d')),
(k: ''; s: 'Miscellaneous'; c: ('m','i','s','c')),
(k: ''; s: 'Socket Filler'; c: ('s','o','c','k')),
(k: ''; s: 'Second Hand Item'; c: ('s','e','c','o')),
(k: ''; s: 'Staves And Rods'; c: ('r','o','d',' ')),
(k: ''; s: 'Missile'; c: ('m','i','s','l')),
(k: ''; s: 'Blunt'; c: ('b','l','u','n')),
(k: 'jew'; s: 'Jewel'; c: ('j','e','w','l')),
(k: ''; s: 'Class Specific'; c: ('c','l','a','s')),
(k: ''; s: 'Amazon Item'; c: ('a','m','a','z')),
(k: ''; s: 'Barbarian Item'; c: ('b','a','r','b')),
(k: ''; s: 'Necromancer Item'; c: ('n','e','c','r')),
(k: ''; s: 'Paladin Item'; c: ('p','a','l','a')),
(k: ''; s: 'Sorceress Item'; c: ('s','o','r','c')),
(k: ''; s: 'Assassin Item'; c: ('a','s','s','n')),
(k: ''; s: 'Druid Item'; c: ('d','r','u','i')),
(k: ''; s: 'Claw'; c: ('h','2','h',' ')),
(k: ''; s: 'Assassin Claw'; c: ('h','2','h','2')),
(k: ''; s: 'Orb'; c: ('o','r','b',' ')),
(k: ''; s: 'Voodoo Heads'; c: ('h','e','a','d')),
(k: ''; s: 'Paladin Shield'; c: ('a','s','h','d')),
(k: ''; s: 'Barbarian Helm'; c: ('p','h','l','m')),
(k: ''; s: 'Druid Helm'; c: ('p','e','l','t')),
(k: 'cloak'; s: 'Cloak'; c: ('c','l','o','a')),
(k: ''; s: 'Rune'; c: ('r','u','n','e')),
(k: 'circlet'; s: 'Circlet'; c: ('c','i','r','c')),
(k: 'hp3'; s: 'Healing Potion'; c: ('h','p','o','t')),
(k: 'mp3'; s: 'Mana Potion'; c: ('m','p','o','t')),
(k: 'rvs'; s: 'Rejuvenation potion'; c: ('r','p','o','t')),
(k: 'vps'; s: 'Stamina Potion'; c: ('s','p','o','t')),
(k: 'yps'; s: 'Antidote Potion'; c: ('a','p','o','t')),
(k: 'wms'; s: 'Thawing Potion'; c: ('w','p','o','t')),
(k: 'cm1'; s: 'Small Charm'; c: ('s','c','h','a')),
(k: 'cm2'; s: 'Large Charm'; c: ('m','c','h','a')),
(k: 'cm3'; s: 'Grand Charm'; c: ('l','c','h','a')),
(k: ''; s: 'Amazon Bow'; c: ('a','b','o','w')),
(k: ''; s: 'Amazon Spear'; c: ('a','s','p','e')),
(k: ''; s: 'Amazon Javelin'; c: ('a','j','a','v')),
(k: ''; s: 'Magic Arrows'; c: ('m','b','o','q')),
(k: ''; s: 'Magic Bolts'; c: ('m','x','b','q')),
(k: ''; s: 'Chipped Gem'; c: ('g','e','m','0')),
(k: ''; s: 'Flawed Gem'; c: ('g','e','m','1')),
(k: ''; s: 'Normal Gem'; c: ('g','e','m','2')),
(k: ''; s: 'Flawless Gem'; c: ('g','e','m','3')),
(k: ''; s: 'Perfect Gem'; c: ('g','e','m','4')),
(k: 'gsv'; s: 'Amethyst'; c: ('g','e','m','a')),
(k: 'gsw'; s: 'Diamond'; c: ('g','e','m','d')),
(k: 'gsg'; s: 'Emerald'; c: ('g','e','m','e')),
(k: 'gsr'; s: 'Ruby'; c: ('g','e','m','r')),
(k: 'gsb'; s: 'Sapphire'; c: ('g','e','m','s')),
(k: 'gsy'; s: 'Topaz'; c: ('g','e','m','t')),
(k: 'sku'; s: 'Skull'; c: ('g','e','m','z')),
(k: ''; s: '???'; dw: 0));
LocalStrings: array[0..MaxStr + 1] of TLocalStr = (
(name: 'STR_STATS_UNASSIGN_WITH_LIMIT'; value: '+Alt: Unassign, +Shift: by %d points'),
(name: 'STR_STATS_UNASSIGN_WITHOUT_LIMIT'; value: '+Alt: Unassign, +Shift: all remaining points'),
(name: 'STR_STATS_BASE_MIN'; value: 'Base: %d (Min: %d)'),
(name: 'STR_SKILLS_UNASSIGN'; value: 'Un-allocate all skills points'),
(name: 'STR_STASH_PREVIOUS_PAGE'; value: 'Previous Page (+shift: First Page)'),
(name: 'STR_STASH_NEXT_PAGE'; value: 'Next Page (+shift: Last not empty Page'),
(name: 'STR_TOGGLE_TO_PERSONAL'; value: 'Toggle to Personal Stash'),
(name: 'STR_TOGGLE_TO_SHARED'; value: 'Toggle to Shared Stash'),
(name: 'STR_STASH_PREVIOUS_INDEX'; value: 'Previous Index : by %d Pages (+Shift: %d)'),
(name: 'STR_STASH_NEXT_INDEX'; value: 'Next Index : by %d Pages (+shift: %d)'),
2016-04-20 03:23:52 +00:00
(name: 'STR_PERSONAL_PAGE_NUMBER'; value: 'Personal Page n°%u'),
(name: 'STR_SHARED_PAGE_NUMBER'; value: 'Shared Page n°%u'),
(name: 'STR_NO_SELECTED_PAGE'; value: 'No selected page'),
(name: 'STR_PUT_GOLD'; value: 'Put Gold'),
(name: 'STR_TAKE_GOLD'; value: 'Take Gold'),
(name: 'STR_SHARED_GOLD_QUANTITY'; value: 'Shared Gold : %u'),
(name: 'STR_PREVIOUS_PAGE'; value: 'Previous Page'),
(name: 'STR_NEXT_PAGE'; value: 'Next Page'),
(name: 'STR_ITEM_LEVEL'; value: 'Item Level: %u'),
(name: 'STR_COW_PORTAL'; value: 'Cow Portal'),
(name: 'STR_PANDEMONIUM_PORTAL'; value: 'Pandemonium Portal'),
(name: 'STR_PANDEMONIUM_FINAL_PORTAL'; value: 'Pandemonium Final Portal'),
(name: 'STR_FULL'; value: 'Fully '),
(name: 'STR_REPAIR'; value: 'Repair '),
(name: 'STR_AND'; value: 'and '),
(name: 'STR_RECHARGE'; value: 'Recharge '),
(name: 'STR_DESTROY_FILLERS'; value: 'Destroys Fillers '),
(name: 'STR_REMOVE_FILLERS'; value: 'Remove Fillers '),
(name: 'STR_REGENERATE'; value: 'Regenerate '),
(name: 'STR_WITH_N_SOCKETS'; value: ' with %u Sockets'),
(name: 'STR_ETHERAL'; value: 'Ethereal '),
(name: 'STR_NOT_ETHERAL'; value: 'Not Ethereal '),
(name: 'STR_NOT_RUNEWORD'; value: 'Not Runeword '),
(name: 'STR_BASIC'; value: 'Basic '),
(name: 'STR_EXCEPTIONAL'; value: 'Exceptional '),
(name: 'STR_ELITE'; value: 'Elite '),
(name: 'STR_CRACKED'; value: 'Cracked '),
(name: 'STR_NORMAL'; value: 'Normal '),
(name: 'STR_SUPERIOR'; value: 'Superior '),
(name: 'STR_MAGIC'; value: 'Magic '),
(name: 'STR_SET'; value: 'Set '),
(name: 'STR_RARE'; value: 'Rare '),
(name: 'STR_UNIQUE'; value: 'Unique '),
(name: 'STR_CRAFTED'; value: 'Crafted '),
(name: 'STR_TEMPERED'; value: 'Tempered '),
(name: 'STR_ITEM'; value: 'Item'),
(name: 'STR_ITEM_SAME_TYPE'; value: 'Item of the same type'),
(name: 'STR_OR_UPGRADED'; value: ' (or upgraded)'),
(name: 'STR_WITHOUT_SOCKET'; value: ' without Sockets'),
(name: 'STR_WITH_SOCKET'; value: ' with Sockets'),
(name: 'STR_ONLY_N_H'; value: ' (Nightmare and Hell only)'),
(name: 'STR_ONLY_HELL'; value: ' (Hell only)'),
(name: 'STR_ONLY_CLASS'; value: ' (%s only)'),
(name: ''; value: '<unknown string>')
);
IniName: AnsiString;
//MS C++__fastcall(ecx,edx) vs Delphi register(eax,edx,ecx) - :(
function InitTranslatedString(_EAX: Integer;_EDX: Integer; iLng: Integer): Boolean; register;
var
IniFile: PIniFile;
CurLng: AnsiString;
S: UTF8String;
i: Integer;
begin
Result := False;
if not FileExists(IniName) then Exit;
if (iLng < 0)or(iLng > MaxLng) then iLng := 0;
CurLng := sLng[iLng];
IniFile := OpenIniFile(IniName);
IniFile.Mode := ifmRead;
for i := 0 to MaxStr do
begin
IniFile.Section := LocalStrings[i].name;
S := IniFile.ValueString(CurLng, '');
if S <> '' then LocalStrings[i].value := UTF8Decode(S);
end;
for i := 0 to MaxType do
begin
IniFile.Section := StrTypes[i].c;
S := IniFile.ValueString(CurLng, '');
if S <> '' then
begin
StrTypes[i].s := UTF8Decode(S);
StrTypes[i].k := '';
end;
end;
Result := True;
end;
//MS C++__fastcall(ecx,edx) vs Delphi register(eax,edx,ecx) - :(
function GetTranslatedString(_EAX: Integer;_EDX: Integer; Idx: Integer): PWideChar; register;
begin
if (Idx < 0)or(Idx > MaxStr) then Idx := MaxStr + 1;
Result := @LocalStrings[Idx].Value[1];
end;
//MS C++__fastcall(ecx,edx) vs Delphi register(eax,edx,ecx) - :(
function GetTypeString(_EAX: Integer;out IdxStr: PAnsiChar; Code: Cardinal): PWideChar; register;
var
i: Integer;
begin
i := 0;
while i <= MaxType do
begin
if Code = StrTypes[i].dw then Break;
Inc(i);
end;
if StrTypes[i].k = '' then
IdxStr := nil
else
IdxStr := PAnsiChar(StrTypes[i].k);
Result := PWideChar(StrTypes[i].s);
end;
function WSprintStringLastGender(buf: PWideChar; lenbuf: Integer; Idx: Integer): Integer; stdcall;
var
i, p, L: Integer;
S: WideString;
begin
S := GetTranslatedString(0,0,Idx);
if Gender <> '' then
begin
p := Pos(Gender, S);
if p <> 0 then
begin
L := Length(S);
p := p + Length(Gender);
for i := p to L do
if S[i] = '[' then Break;
S := Copy(S, p, i - p);
end;
end;
Result := Min(lenbuf - 1, Length(S));
for i := 1 to Result do
buf[i-1] := S[i];
buf[Result + 1] := #$0000;
end;
//MS C++__fastcall(ecx,edx) vs Delphi register(eax,edx,ecx) - :(
function SetMonoString(_EAX: Integer;_EDX: Integer; InStr: PWideChar): PWideChar; register;
var
StrList: PWStrList;
i: Integer;
S: WideString;
begin
Result := InStr;
if Result = nil then Exit;
StrList := NewWStrList;
StrList.Text := InStr;
i := Strlist.Count - 1;
if i = 0 then Exit;
S := StrList.Items[i];
while i > 0 do
begin
Dec(i);
S := S + '. ' + StrList.Items[i];
end;
Move(S[1], InStr[0], Length(S) shl 1);
end;
//MS C++__fastcall(ecx,edx) vs Delphi register(eax,edx,ecx) - :(
function CutStringGender(_EAX: Integer;_EDX: Integer; InStr: PWideChar): PWideChar; register;
var
i, j: Integer;
begin
Result := InStr;
Gender := '';
if (InStr = nil)or(InStr[0] <> '[') then Exit;
i := 1;
while (InStr[i] <> #$0000) do
begin
if InStr[i] = ']' then
begin
if (i < 2)or(InStr[i+1] = #$0000) then Exit;
SetLength(Gender, i + 1);
for j := 0 to i do
Gender[j+1] := InStr[j];
Result := @InStr[i+1];
Exit;
end;
Inc(i);
end;
end;
{
const
NcColor = 14;
LenCode = 9;
type
TTextColor = array[0..LenCode - 1] of AnsiChar;
const
cColor: array[0..NcColor - 1] of TTextColor = (
('\','w','h','i','t','e',';',#00,#00),
('\','g','r','e','y',';',#00,#00,#00),
('\','r','e','d',';',#00,#00,#00,#00),
('\','g','r','e','e','n',';',#00,#00),
('\','b','l','u','e',';',#00,#00,#00),
('\','g','o','l','d',';',#00,#00,#00),
('\','d','g','r','e','y',';',#00,#00),
('\','b','l','a','c','k',';',#00,#00),
('\','t','a','n',';',#00,#00,#00,#00),
('\','o','r','a','n','g','e',';',#00),
('\','y','e','l','l','o','w',';',#00),
('\','d','g','r','e','e','n',';',#00),
('\','p','u','r','p','l','e',';',#00),
('\','c','o','l','o','r',';',#00,#00));
//lengths of strings in cColor table, without '\'
cColLength: array[0..NcColor-1] of Byte = (6,5,4,6,5,5,6,6,4,7,7,7,7,6);
pColor: PAnsiChar = @cColor[NcColor-1][1];
var
SaveToTbl: Byte = 0;
//ANSI convert ColorApi to ColorCode
//optional UCS2 convert '\n' to $0A
function ColorApi2ColorCode(Src: PAnsiChar; Dst: PAnsiChar;
SourceChars: Integer): Integer;
//EAX: Src
//EDX: Dst
//ECX: Length Src
//Result: OutLength -> EAX
asm
//backup
PUSHF
2016-04-20 03:23:52 +00:00
CLD //èíêðåìåíò äëÿ ñòðîêîâûõ êîìàíä
PUSH ESI
PUSH EDI
PUSH EBX
PUSH EBP
2016-04-20 03:23:52 +00:00
PUSH EDX //ñîõðàíÿåì íà÷àëüíûé àäðåñ ïðèåìíèêà
MOV EDI, Dst
2016-04-20 03:23:52 +00:00
TEST Src, Src //ïðîâåðêà íà ïóñòóþ ñòðîêó
JZ @Exit
MOV ESI, Src
2016-04-20 03:23:52 +00:00
// â ECX õðàíèòñÿ êîëè÷åñòâî îñòàâøèõñÿ ñèìâîëîâ èç Src
@NextChar:
2016-04-20 03:23:52 +00:00
//çàãðóçêà î÷åðåäíîãî ñèìâîëà â EAX
XOR EAX, EAX
LODSB //MOV AL, [ESI]+
2016-04-20 03:23:52 +00:00
//ïðîâåðêà íà íóëåâîé ñèìâîë (êîíåö ñòðîêè)
TEST AL, AL
JZ @Exit
2016-04-20 03:23:52 +00:00
//ïðîâåðêà íà ñèìâîë '\'
CMP AL, '\'
JE @Slash
@CopyChar:
//normal chars
STOSB //MOV [EDI]+, AL
2016-04-20 03:23:52 +00:00
//óìåíüøåíèå ñ÷åò÷èêà íåîáðàáîòàííûõ áàéòîâ è ïåðåä â íà÷àëî öèêëà
@Loop:
LOOP @NextChar
@Exit:
2016-04-20 03:23:52 +00:00
MOV BYTE PTR [EDI], $00 //íóëåâîé ñèìâîë â êîíöå âûõîäíîé ñòðîêè
POP EAX //âîññòàíàâëèâàåì íà÷àëüíûé àäðåñ ïðèåìíèêà
XCHG EAX, EDI
//get length of Dst
SUB EAX, EDI
//restore
POP EBP
POP EBX
POP EDI
POP ESI
POPF
RET
@Slash:
2016-04-20 03:23:52 +00:00
//ïðîâåðêà íà íàëè÷èå ñëåäóþùåãî ñèìâîëà
CMP ECX, 1
JB @CopyChar // if ECX < 1
2016-04-20 03:23:52 +00:00
//çàãðóçêà ñëåäóþùåãî ñèìâîëà
LODSB //MOV AL, [ESI]+
2016-04-20 03:23:52 +00:00
//ïðîâåðêà ñèìâîëà íà êîä ïåðåâîäà ñòðîêè
CMP AL, 'n'
JNZ @TestColor
2016-04-20 03:23:52 +00:00
//ïîïðàâêà ECX
DEC ECX
//test Save2Tbl
CMP SaveToTbl, 0
JNZ @UnixReturn
//save '\n'
MOV AL, '\'
STOSB //MOV [EDI]+, AL
MOV AL, 'n'
JMP @CopyChar
@UnixReturn:
//save UnixNewLine
MOV AL, $0A
JMP @CopyChar
2016-04-20 03:23:52 +00:00
//ïðîâåðêà íà ñòðîêè óñòàíîâêè öâåòà øðèôòà:
@TestColor:
2016-04-20 03:23:52 +00:00
//ïðîâåðêà íà èñïîëüçîâàíèå ìàêðî îïðåäåëåíèé öâåòà øðèôòà
//CMP MacroColorView, $00
//JE @StoreSlash
//backup
PUSH ECX
PUSH EDI
2016-04-20 03:23:52 +00:00
//âîññòàíîâëåíèå ESI
DEC ESI
2016-04-20 03:23:52 +00:00
//ñîõðàíåíèå èñòî÷íêà
MOV EBX, ESI
2016-04-20 03:23:52 +00:00
//çàãðóçêà êîëè÷åñòâà ñðàâíèâàåìûõ ñòðîê
MOV EAX, NcColor
2016-04-20 03:23:52 +00:00
//çàãðóçêà àäðåñà ïîñëåäíåé ñòðîêè èç ìàññèâà ñòðîê
//óñòàíîâêè öâåòà øðèôòà (áåç '')
MOV EBP, pColor
2016-04-20 03:23:52 +00:00
//çàãðóçêà àäðåñà ìàññèâà äëèí ñòðîê áåç '\' è
//(-1, ò.ê. áóäåò ïðèáàâëÿòñÿ EAX)
LEA EDX, [cColLength - 1]
@CmpStr:
2016-04-20 03:23:52 +00:00
//çàãðóçêà àäðåñà ñòðîêè ïðèåìíèêà
MOV EDI, EBP
2016-04-20 03:23:52 +00:00
//çàãðóçêà ñ÷åò÷èêà ñèìâîëîâ ñòðîêè
MOVZX ECX, BYTE PTR [EDX + EAX]
2016-04-20 03:23:52 +00:00
//ñðàâíåíèå ñòðîê
//(ïðåðûâàíèå, åñëè íå ðàâíû, ò.å. äëèíó Src ìîæíî íå ïðîâåðÿòü)
REPE CMPSB
2016-04-20 03:23:52 +00:00
//ïðîâåðêà ðåçóëüòàòà ñðàâíåíèÿ ñòðîê
JZ @ColorCode
2016-04-20 03:23:52 +00:00
//âîññòàíîâëåíèå àäðåñà ñòðîêè èñòî÷íèêà
MOV ESI, EBX
2016-04-20 03:23:52 +00:00
//ñäâèã àäðåñà ñòðîêè ïðèåìíèêà íà ñëåäóþùóþ ñòðîêó
SUB EBP, LenCode
2016-04-20 03:23:52 +00:00
//äåêðåìåíò ñ÷åò÷èêà ñòðîê
DEC EAX
2016-04-20 03:23:52 +00:00
//ïðîâåðêà íà ïîâòîð öèêëà ñðàâíåíèÿ ñòðîê
JA @CmpStr //if EAX > 0
2016-04-20 03:23:52 +00:00
//ñèìâîë '\' áûë ïðîñòî ñèìâîëîì
//restore
POP EDI
POP ECX
@StoreSlash:
2016-04-20 03:23:52 +00:00
//çàïèñü êîäà ñèìâîëà '\'
MOV AL, '\'
JMP @CopyChar
2016-04-20 03:23:52 +00:00
//çàïèñü êîäà ñìåíû èçâåñòíîãî öâåòà øðèôòà
//â AL íîìåð ñòðîêè èç cColor
@ColorCode:
//restore
POP EDI
2016-04-20 03:23:52 +00:00
//äîáàâêà êîäà öâåòà ê ColorCode
MOVZX EDX, BYTE PTR [EDX + EAX]//çàãðóçêà ñ÷åò÷èêà ñèìâîëîâ ñòðîêè
ADD AL, $2E //1..14 + $2E = $2F..$3C
//backup EAX
MOV ECX, EAX
//save ColorCode
MOV AX, $63FF
STOSW //MOVD [EDI]+, AX
//restore EAX
MOV EAX, ECX
//test \color;
CMP AL, $3C
JE @FullColorCode
//add number to ColorCode
STOSB //MOVD [EDI]+, AL
@FullColorCode:
//restore ECX
POP ECX
2016-04-20 03:23:52 +00:00
SUB ECX, EDX //êîððåêöèÿ ECX íà äëèíó ñòðîêè
JZ @Exit //êîíåö ñòðîêè èñòî÷íèêà
//ESI ïîñëå ñðàâíåíèÿ óæå óêàçûâàåò íà ñëåäóþùèé ñèìâîë
JMP @NextChar //ECX >= 1
end;
//MS C++__fastcall(ecx,edx) vs Delphi register(eax,edx,ecx) - :(
procedure ReplaceColorCode(_EAX: Integer;_EDX: Integer; Str: PAnsiChar); register;
var
i, L, n: Integer;
begin
L := Length(Str);
n := ColorApi2ColorCode(Str, Str, L);
Dec(L);
for i := n to L do
begin
//Str[i] := ' ';
end;
//MsgOK(Str);
end;
}
//Decode string from UCS2 to UTF8
//WideCharToMultiByte not support CP_UTF8 in Windows 95
function UCS2ToUTF8(Dest: PAnsiChar; MaxDestBytes: Integer;
Source: PWideChar; SourceChars: Integer): Integer;
//EAX: @Dest
//EDX: MaxDestBytes
//ECX: @Source
//(ESP): SourceChars;
//Result: DestChars of @Dest -> EAX
asm
//backup
PUSHF
CLD //set (ESI)+
PUSH EBX
PUSH ESI
PUSH EDI
PUSH Dest //backup @Dst
MOV EDI, Dest
TEST Source, Source //test NULL string
JZ @Exit
MOV ESI, Source
MOV ECX, SourceChars
@NextChar:
//test length of Dst
DEC EDX
JLE @Exit
//get next char to EAX
XOR EAX, EAX
LODSW //MOV AX, [ESI]+
//test NULL char (end of string)
TEST EAX, EAX
JZ @Exit
//decode UCS2 to UTF8
@Ucs2ToUtf8:
//test UCS2-char in $0000..$007F
CMP AX, $007F
JA @11xxxxxx //if AX > $7F
//UTF8-char: 0xxxxxxx
//AH = 00000000; AL = 0xxxxxxx
@0xxxxxxx:
//save UTF8-char
STOSB //MOVB [EDI]+, AL
//end Loop
@Loop:
LOOP @NextChar
JMP @Exit
@11xxxxxx:
//test length of Dst
DEC EDX
JLE @Exit
//test UCS2-char in $0080..$07FF
CMP AX, $07FF
JA @1110xxxx //if AX > $07FF
//UTF8-char: 110xxxxx 10xxxxxx
//AH = 00000xxx; AL = xxxxxxxx
//get first byte UTF8-char to AL
ROR AX, 6 //AH = xxxxxx00; AL = 000xxxxx
//get second byte UTF8-char to AH
SHR AH, 2 //AH = 00xxxxxx
OR AX, $80C0 //AH = 10xxxxxx; AL = 110xxxxx
//save UTF8-char
STOSW //MOVW [EDI]+, AX
JMP @Loop
//UTF8-char: 1110xxxx 10xxxxxx 10xxxxxx
@1110xxxx:
//test length of Dst
DEC EDX
JLE @Exit
//save lobyte of UCS2-char
MOV BL, AL
//AH = xxxxxxxx; AL = xxxxxxxx
//get first byte UTF8-char UTF8 to AL
ROL AX, 4 //AL = ????xxxx; AH = xxxxxx??
AND AL, $0F //AL = 0000xxxx
//get second byte UTF8-char to AH
SHR AH, 2 //AH = 00xxxxxx
OR AX, $80E0 //AH = 10xxxxxx; AL = 1110xxxx
//save first bytes UTF8-char
STOSW //MOVW [EDI]+, AX
//get second byte UTF8-char to AL
XCHG EAX, EBX //??xxxxxx
AND AL, $3F //00xxxxxx
OR AL, $80 //10xxxxxx
//save third byte UTF8-char
JMP @0xxxxxxx
@Exit:
MOV BYTE PTR [EDI], $00 //set end-char of Dst
POP EAX //restore @Dst
XCHG EAX, EDI
//get length of Dst to Result
SUB EAX, EDI
//restore
POP EDI
POP ESI
POP EBX
POPF
end;
function _UCS2ToUTF8(Dest: PAnsiChar; MaxDestBytes: Integer;
Source: PWideChar; SourceChars: Integer): Integer; stdcall;
begin
Result := UCS2ToUTF8(Dest, MaxDestBytes, Source, SourceChars);
end;
//Decode string from UTF8 to UCS2
function UTF8ToUCS2(Dest: PWideChar; MaxDestBytes: Integer;
Source: PAnsiChar; SourceChars: Integer): Integer;
//EAX: @Dest
//EDX: MaxDestBytes
//ECX: @Source
//(ESP): SourceChars;
//Result: DestChars of @Dest -> EAX
//if errors then
//Result: -(DestChars of @Dest) -> EAX
asm
//backup
PUSHF
CLD //set (ESI)+
PUSH EBX
PUSH ESI
PUSH EDI
PUSH Dest //backup @Dst
MOV EDI, Dest
TEST Source, Source //test NULL string
JZ @Exit
MOV ESI, Source
MOV ECX, SourceChars
@NextChar:
//test length of Dst
SUB EDX, 2
JLE @Exit
//get next char to EAX
XOR EAX, EAX
LODSB //MOV AL, [ESI]+
//test NULL char (end of string)
TEST AL, AL
JZ @Exit
//decode UTF8 to UCS2
@Utf8ToUcs2:
//test first byte UTF8 = 0xxxxxxx
TEST AL, $80
JNZ @1xxxxxxx
//UTF8: 0xxxxxxx (AH = 0)
@SaveU16:
STOSW //MOVW [EDI]+, EAX
@Loop:
LOOP @NextChar
JMP @Exit
@1xxxxxxx:
//test first byte UTF8 = 10xxxxxx
TEST AL, $40 //01000000
JZ @Exit //Error UTF8: 10xxxxxx
//test first byte UTF8 = 1111xxxx
CMP AL, $F0 //11110000
JAE @Exit //Error UTF8 to UCS2: 1111xxxx ( if AL >= $F0)
//test exist second byte UTF8
JECXZ @Exit // DEC ECX; if ECX = 0
//backup first byte UTF8
MOV AH, AL //11xxxxxx
//load second byte UTF8
LODSB //MOV AL, [ESI]+
//test second byte UTF8 = 10xxxxxx
TEST AL, $40 //01000000
JNE @Exit //Error UTF8: 10xxxxxx
//test second byte UTF8 = 110xxxxx
TEST AH, $20 //00100000
JNZ @1110xxxx //third byte UTF8
//UTF8: 110xxxxx 10xxxxxx
//backup first byte UTF8
MOV BL, AH //110xxxxx
//get high byte UCS2
SHR AH, 2 //00110xxx
AND AX, $073F //AH: 00000xxx; AL: 00xxxxxx
//get low byte USC2
SHL BL, 6 //xx000000
OR AL, BL //xxxxxxxx
//AX: 00000xxx:xxxxxxxx
JMP @SaveU16
@1110xxxx:
//test exist third byte UTF8
JeCXZ @Exit // DEC ECX; if ECX = 0
//backup second byte UTF8
MOV BL, AL //10xxxxxx
//load third byte UTF8
LODSB //MOV AL, [ESI]+
//test third byte UTF8 = 10xxxxxx
CMP AL, $C0 //11000000
JAE @Exit //Error UTF8: 11xxxxxx ( if AL >= $C0)
//UTF8: 1110xxxx 10xxxxxx 10xxxxxx
2016-04-20 03:23:52 +00:00
//get bytes UCS2 íà: xx00000:0000xxxx
AND BX, $003F //DX := 00000000:00xxxxxx
ROR BX, 2 //BL := 0000xxxx; BH := xx000000
//get low byte UTF8
AND AL, $3F //00xxxxxx
OR AL, BH //xxxxxxxx
//get high byte UCS2
SHL AH, 4 //xxxx0000
OR AH, BL //xxxxxxxx
JMP @SaveU16
@Exit:
XOR EAX, EAX
MOV [EDI],AX //set end-char of Dst
POP EAX //restore @Dst
XCHG EAX, EDI
//get length of Dst to Result
SUB EAX, EDI
SHR EAX, 1
//restore
POP EDI
POP ESI
POP EBX
POPF
end ; //asm
function _UTF8ToUCS2(Dest: PWideChar; MaxDestBytes: Integer;
Source: PAnsiChar; SourceChars: Integer): Integer; stdcall;
begin
Result := UTF8ToUCS2(Dest, MaxDestBytes, Source, SourceChars);
end;
exports
_UCS2ToUTF8 name '__stdcall UCS2toUTF8',
_UTF8ToUCS2 name '__stdcall UTF8toUCS2',
//ReplaceColorCode name 'replaceColorCode',
SetMonoString name '__fastcall setMonoString',
WSprintStringLastGender name '__stdcall wSprintStringLastGender',
CutStringGender name '__fastcall cutStringGender',
GetTypeString name '__fastcall getTypeString',
GetTranslatedString name '__fastcall getTranslatedString',
InitTranslatedString name '__fastcall initTranslatedString';
var
i, j: Integer;
S: UTF8String;
b: Boolean;
begin
IniName := GetStartDir + NamePlugyLocal;
if FileExists(IniName) then Exit;
S := #$EF#$BB#$BF';UTF8';
for i := 0 to MaxStr do
begin
S := S + #$0D#$0A'[' + LocalStrings[i].name + ']'#$0D#$0A + sLng[0] + '="'
+ LocalStrings[i].value + '"'#$0D#$0A;
for j := 1 to MaxLng do
S := S + sLng[j] + '='#$0D#$0A;
end;
for i := 0 to MaxType do
begin
S := S + #$0D#$0A;
b := (StrTypes[i].k <> '');
if b then
S := S + ';';
S := S + '[' + StrTypes[i].c + ']'#$0D#$0A;
if b then
S := S + ';';
S := S + sLng[0] + '="' + StrTypes[i].s + '"'#$0D#$0A;
if not b then
begin
for j := 1 to MaxLng do
S := S + sLng[j] + '='#$0D#$0A;
end;
end;
StrSaveToFile(IniName, S);
end.