unit StringIO; interface type characters = Set of Char; function Capitalize(str: String): String; function Upper(str: String): String; function Lower(str: String): String; function iCASE(str: String): String; function RotStrL(str1,str2: String; shift: Byte): String; function RotStrR(str1,str2: String; shift: Byte): String; function ExpStrL(str: String; size: Byte; chr: Char): String; function ExpStrR(str: String; size: Byte; chr: Char): String; function DietStr(str: String; size: Byte): String; function CutStr(str: String): String; function FlipStr(str: String): String; function FilterStr(str: String; chr0,chr1: Char): String; function FilterStr2(str: String; chr0: characters; chr1: Char): String; function Num2str(num: Longint; base: Byte): String; function Str2num(str: String; base: Byte): Longint; type tINPUT_STR_SETTING = Record insert_mode, replace_enabled, append_enabled: Boolean; character_set, valid_chars, word_characters: characters; terminate_keys: array[1..50] of Word end; type tINPUT_STR_ENVIRONMENT = Record keystroke: Word; locate_pos: Byte; end; const is_setting: tINPUT_STR_SETTING = (insert_mode: TRUE; replace_enabled: TRUE; append_enabled: TRUE; character_set: [#$20..#$0ff]; valid_chars: [#$20..#$0ff]; word_characters: ['A'..'Z','a'..'z','0'..'9','_']; terminate_keys: ($011b,$1c0d,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000)); var is_environment: tINPUT_STR_ENVIRONMENT; function InputStr(s: String; x,y,ln,ln1: Byte; atr1,atr2: Byte): String; function SameName(str1,str2: String): Boolean; function PathOnly(path: String): String; function NameOnly(path: String): String; function BaseNameOnly(path: String): String; function ExtOnly(path: String): String; implementation uses DOS,TxtScrIO; function Capitalize(str: String): String; assembler; asm mov esi,[str] mov edi,@result mov al,[esi] inc esi mov [edi],al inc edi xor ecx,ecx mov cl,al jecxz @@4 mov al,[esi] inc esi cmp al,'a' jb @@0 cmp al,'z' ja @@0 sub al,20h @@0: mov [edi],al inc edi @@1: mov ah,al mov al,[esi] inc esi cmp ah,' ' jnz @@2 cmp al,'a' jb @@2 cmp al,'z' ja @@2 sub al,20h jmp @@3 @@2: cmp al,'A' jb @@3 cmp al,'Z' ja @@3 add al,20h @@3: mov [edi],al inc edi loop @@1 @@4: end; function Upper(str: String): String; assembler; asm mov esi,[str] mov edi,@result mov al,[esi] inc esi mov [edi],al inc edi xor ecx,ecx mov cl,al jecxz @@3 @@1: mov al,[esi] inc esi cmp al,'a' jb @@2 cmp al,'z' ja @@2 sub al,20h @@2: mov [edi],al inc edi loop @@1 @@3: end; function Lower(str: String): String; assembler; asm mov esi,[str] mov edi,@result mov al,[esi] inc esi mov [edi],al inc edi xor ecx,ecx mov cl,al jecxz @@3 @@1: mov al,[esi] inc esi cmp al,'A' jb @@2 cmp al,'Z' ja @@2 add al,20h @@2: mov [edi],al inc edi loop @@1 @@3: end; function iCase(str: String): String; assembler; asm mov esi,[str] mov edi,@result mov al,[esi] inc esi mov [edi],al inc edi xor ecx,ecx mov cl,al jecxz @@5 push edi push ecx @@1: mov al,[esi] inc esi cmp al,'a' jb @@2 cmp al,'z' ja @@2 sub al,20h @@2: mov [edi],al inc edi loop @@1 pop ecx pop edi @@3: mov al,[edi] cmp al,'i'-20h jnz @@4 add al,20h @@4: mov [edi],al inc edi loop @@3 @@5: end; function RotStrL(str1,str2: String; shift: Byte): String; begin RotStrL := Copy(str1,shift+1,Length(str1)-shift)+ Copy(str2,1,shift); end; function RotStrR(str1,str2: String; shift: Byte): String; begin RotStrR := Copy(str2,Length(str2)-shift+1,shift)+ Copy(str1,1,Length(str1)-shift); end; function ExpStrL(str: String; size: Byte; chr: Char): String; assembler; asm mov esi,[str] mov edi,@result cld xor ecx,ecx lodsb cmp al,size jge @@1 mov ah,al mov al,size stosb mov al,ah mov cl,size sub cl,al mov al,chr rep stosb mov cl,ah rep movsb jmp @@2 @@1: stosb mov cl,al rep movsb @@2: end; function ExpStrR(str: String; size: Byte; chr: Char): String; assembler; asm mov esi,[str] mov edi,@result cld xor ecx,ecx lodsb cmp al,size jge @@1 mov ah,al mov al,size stosb mov cl,ah rep movsb mov al,ah mov cl,size sub cl,al mov al,chr rep stosb jmp @@2 @@1: stosb mov cl,al rep movsb @@2: end; function DietStr(str: String; size: Byte): String; begin If (Length(str) <= size) then begin DietStr := str; EXIT; end; Repeat Delete(str,size DIV 2,1) until (Length(str)+3 = size); Insert('...',str,size DIV 2); DietStr := str end; function CutStr(str: String): String; begin While (str[0] <> #0) and (str[1] in [#00,#32]) do Delete(str,1,1); While (str[0] <> #0) and (str[Length(str)] in [#00,#32]) do Delete(str,Length(str),1); CutStr := str; end; function FlipStr(str: String): String; assembler; asm mov esi,[str] mov edi,@result mov al,[esi] inc esi mov [edi],al inc edi dec edi xor ecx,ecx mov cl,al jecxz @@2 add edi,ecx @@1: mov al,[esi] inc esi mov [edi],al dec edi loop @@1 @@2: end; function FilterStr(str: String; chr0,chr1: Char): String; assembler; asm mov esi,[str] mov edi,@result mov al,[esi] inc esi mov [edi],al inc edi xor ecx,ecx mov cl,al jecxz @@3 @@1: mov al,[esi] inc esi cmp al,chr0 jnz @@2 mov al,chr1 @@2: mov [edi],al inc edi loop @@1 @@3: end; const _treat_char: array[$80..$a5] of Char = 'CueaaaaceeeiiiAAE_AooouuyOU_____aiounN'; function FilterStr2(str: String; chr0: characters; chr1: Char): String; var temp: Byte; begin For temp := 1 to Length(str) do If NOT (str[temp] in chr0) then If (str[temp] >= #$80) and (str[temp] <= #$a5) then str[temp] := _treat_char[BYTE(str[temp])] else If (str[temp] = #0) then str[temp] := ' ' else str[temp] := chr1; FilterStr2 := str; end; function Num2str(num: Longint; base: Byte): String; assembler; const hexa: array[0..PRED(16)+32] of Char = '0123456789ABCDEF'+ #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0; asm xor eax,eax xor edx,edx xor edi,edi xor esi,esi mov eax,num xor ebx,ebx mov bl,base cmp bl,2 jb @@3 cmp bl,16 ja @@3 mov edi,32 @@1: dec edi xor edx,edx div ebx mov esi,edx mov dl,byte ptr [hexa+esi] mov byte ptr [hexa+edi+16],dl and eax,eax jnz @@1 mov esi,edi mov ecx,32 sub ecx,edi mov edi,@result mov al,cl stosb @@2: mov al,byte ptr [hexa+esi+16] stosb inc esi loop @@2 jmp @@4 @@3: mov edi,@result xor al,al stosb @@4: end; const digits: array[0..35] of Char = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; function Digit2index(digit: Char): Byte; var index: Byte; begin digit := UpCase(digit); index := 15; While (index > 0) and (digit <> digits[index]) do Dec(index); Digit2index := Index; end; function position_value(position,base: Byte): Longint; var value: Longint; index: Byte; begin value := 1; For index := 2 to position do value := value*base; position_value := value; end; function Str2num(str: String; base: Byte): Longint; var value: Longint; index: Byte; begin value := 0; For index := 1 to Length(str) do Inc(value,Digit2index(str[index])* position_value(Length(str)-index+1,base)); Str2num := value; end; function InputStr(s: String; x,y,ln,ln1: Byte; atr1,atr2: Byte): String; var appn,for1st,qflg,ins: Boolean; cloc,xloc,xint,mx,attr: Byte; key: Word; cur: Longint; s1,s2: String; function LookupKey(key: Word; var table; size: Byte): Boolean; assembler; asm mov esi,[table] xor ecx,ecx mov cl,size mov al,1 jecxz @@3 @@1: lodsw cmp ax,key jz @@2 loop @@1 @@2: xor al,al jecxz @@3 mov al,1 @@3: end; function more(value1,value2: Byte): Byte; assembler; asm mov al,value1 cmp al,value2 jnb @@1 mov al,value2 @@1: end; begin s := Copy(s,1,ln); If (is_environment.locate_pos > ln1) then is_environment.locate_pos := ln1; If (is_environment.locate_pos > Length(s)+1) then is_environment.locate_pos := Length(s); cloc := is_environment.locate_pos; xloc := is_environment.locate_pos; xint := x; qflg := FALSE; ins := is_setting.insert_mode; appn := NOT is_setting.append_enabled; Dec(x); cur := GetCursor; If ins then ThinCursor else WideCursor; s1 := s; If (BYTE(s1[0]) > ln1) then s1[0] := CHR(ln1); ShowStr(Ptr(v_seg,v_ofs)^,xint,y,ExpStrR('',ln1,' '),atr1); ShowStr(Ptr(v_seg,v_ofs)^,xint,y,s1,atr2); for1st := TRUE; Repeat s2 := s1; If (xloc = 1) then s1 := Copy(s,cloc,ln1) else s1 := Copy(s,cloc-xloc+1,ln1); If NOT appn then attr := atr2 else attr := atr1; If appn and for1st then begin ShowStr(Ptr(v_seg,v_ofs)^,xint,y,ExpStrR(s1,ln1,' '),atr1); for1st := FALSE; end; If (s2 <> s1) then ShowStr(Ptr(v_seg,v_ofs)^,xint,y,ExpStrR(s1,ln1,' '),atr1); If (ln1 < ln) then If (cloc-xloc > 0) and (Length(s) > 0) then ShowStr(Ptr(v_seg,v_ofs)^,xint,y,'',(attr AND $0f0)+$0f) else If (cloc-xloc = 0) and (Length(s) <> 0) then ShowStr(Ptr(v_seg,v_ofs)^,xint,y,s[1],attr) else ShowStr(Ptr(v_seg,v_ofs)^,xint,y,' ',atr1); If (ln1 < ln) then If (cloc-xloc+ln1 < Length(s)) then ShowStr(Ptr(v_seg,v_ofs)^,xint+ln1-1,y,'',(attr AND $0f0)+$0f) else If (cloc-xloc+ln1 = Length(s)) then ShowStr(Ptr(v_seg,v_ofs)^,xint+ln1-1,y,s[Length(s)],attr) else ShowStr(Ptr(v_seg,v_ofs)^,xint+ln1-1,y,' ',atr1); GotoXY(x+xloc,y); asm xor ah,ah; int 16h; mov key,ax end; If LookupKey(key,is_setting.terminate_keys,50) then qflg := TRUE; If NOT qflg then Case LO(key) of $09: appn := TRUE; $19: begin appn := TRUE; s := ''; cloc := 1; xloc := 1; end; $14: begin appn := TRUE; While (s[cloc] in is_setting.word_characters) and (cloc <= Length(s)) do Delete(s,cloc,1); While NOT (s[cloc] in is_setting.word_characters) and (cloc <= Length(s)) do Delete(s,cloc,1); end; $7f: begin appn := TRUE; While (s[cloc-1] in is_setting.word_characters) and (cloc > 1) do begin Dec(cloc); Delete(s,cloc,1); If (xloc > 1) then Dec(xloc); end; While NOT (s[cloc-1] in is_setting.word_characters) and (cloc > 1) do begin Dec(cloc); Delete(s,cloc,1); If (xloc > 1) then Dec(xloc); end; end; $11: begin appn := TRUE; Delete(s,cloc,Length(s)); end; $08: begin appn := TRUE; If (cloc > 1) then begin If (xloc > 1) then Dec(xloc); Dec(cloc); Delete(s,cloc,1); end; end; $00: begin If (HI(key) in [$73,$74,$4b,$4d,$52,$47,$4f]) then appn := TRUE; Case (HI(key)) of $73: begin While (s[cloc] in is_setting.word_characters) and (cloc > 1) do begin Dec(cloc); If (xloc > 1) then Dec(xloc); end; While NOT (s[cloc] in is_setting.word_characters) and (cloc > 1) do begin Dec(cloc); If (xloc > 1) then Dec(xloc); end; end; $74: begin While (s[cloc] in is_setting.word_characters) and (cloc < Length(s)) do begin Inc(cloc); If (xloc < ln1) then Inc(xloc); end; While NOT (s[cloc] in is_setting.word_characters) and (cloc < Length(s)) do begin Inc(cloc); If (xloc < ln1) then Inc(xloc); end; end; $4b: begin If (cloc > 1) then Dec(cloc); If (xloc > 1) then Dec(xloc); end; $4d: begin If (cloc < Length(s)) or ((cloc = Length(s)) and ((Length(s) < more(ln,ln1)))) then Inc(cloc); If (xloc < ln1) and (xloc <= Length(s)) then Inc(xloc); end; $53: begin appn := TRUE; If (cloc <= Length(s)) then Delete(s,cloc,1); end; $52: If is_setting.replace_enabled then begin ins := NOT ins; If ins then ThinCursor else WideCursor; end; $47: begin cloc := 1; xloc := 1; end; $4f: begin If (Length(s) < more(ln,ln1)) then cloc := Succ(Length(s)) else cloc := Length(s); If (cloc < ln1) then xloc := cloc else xloc := ln1; end; end; end; else If NOT (LO(key) in [$09,$19,$0d,$14,$0b,$7f]) and (CHR(LO(key)) in characters(is_setting.character_set)) then begin If NOT appn then begin s := ''; cloc := 1; xloc := 1; end; appn := TRUE; If ins and (Length(s) < ln) then begin Insert(CHR(LO(key)),s,cloc); s := FilterStr2(s,is_setting.valid_chars,'_'); If (cloc < ln) then Inc(cloc); If (xloc < ln) and (xloc < ln1) then Inc(xloc) end else If (Length(s) < ln) or NOT ins then begin If (cloc > Length(s)) and (Length(s) < ln) then Inc(BYTE(s[0])); s[cloc] := CHR(LO(key)); s := FilterStr2(s,is_setting.valid_chars,'_'); If (cloc < ln) then Inc(cloc); If (xloc < ln) and (xloc < ln1) then Inc(xloc); end; end; end; until qflg; // SetCursor(cur); If (cloc = 0) then is_environment.locate_pos := 1 else is_environment.locate_pos := cloc; is_environment.keystroke := key; InputStr := s; end; function SameName(str1,str2: String): Boolean; assembler; var LastW: Word; asm xor eax,eax xor ecx,ecx mov esi,[str1] mov edi,[str2] xor ah,ah mov al,[esi] inc esi mov cx,ax mov al,[edi] inc edi mov bx,ax or cx,cx jnz @@1 or bx,bx jz @@13 jmp @@14 xor dh,dh @@1: mov al,[esi] inc esi cmp al,'*' jne @@2 dec cx jz @@13 mov dh,1 mov LastW,cx jmp @@1 @@2: cmp al,'?' jnz @@3 inc edi or bx,bx je @@12 dec bx jmp @@12 @@3: or bx,bx je @@14 cmp al,'[' jne @@11 cmp word ptr [esi],']?' je @@9 mov ah,byte ptr [edi] xor dl,dl cmp byte ptr [esi],'!' jnz @@4 inc esi dec cx jz @@14 inc dx @@4: mov al,[esi] inc esi dec cx jz @@14 cmp al,']' je @@7 cmp ah,al je @@6 cmp byte ptr [esi],'-' jne @@4 inc esi dec cx jz @@14 cmp ah,al jae @@5 inc esi dec cx jz @@14 jmp @@4 @@5: mov al,[esi] inc esi dec cx jz @@14 cmp ah,al ja @@4 @@6: or dl,dl jnz @@14 inc dx @@7: or dl,dl jz @@14 @@8: cmp al,']' je @@10 @@9: mov al,[esi] inc esi cmp al,']' loopne @@9 jne @@14 @@10: dec bx inc edi jmp @@12 @@11: cmp [edi],al jne @@14 inc edi dec bx @@12: xor dh,dh dec cx jnz @@1 or bx,bx jnz @@14 @@13: mov al,1 jmp @@16 @@14: or dh,dh jz @@15 jecxz @@15 or bx,bx jz @@15 inc edi dec bx jz @@15 mov ax,LastW sub ax,cx add cx,ax sub esi,eax dec esi jmp @@1 @@15: mov al,0 @@16: end; var dir: DirStr; name: NameStr; ext: ExtStr; function PathOnly(path: String): String; begin FSplit(path,dir,name,ext); PathOnly := dir; end; function NameOnly(path: String): String; begin FSplit(path,dir,name,ext); NameOnly := name+ext; end; function BaseNameOnly(path: String): String; begin FSplit(path,dir,name,ext); BaseNameOnly := name; end; function ExtOnly(path: String): String; begin FSplit(path,dir,name,ext); Delete(ext,1,1); ExtOnly := ext; end; begin is_environment.locate_pos := 1; end.