├── .gitignore ├── Demo ├── Demo01_Minimal_Console_App.dpr ├── Demo01_Minimal_Console_App.dproj ├── Demo01_Minimal_Console_App.res ├── Demo02_Fontface_Fontsize.dpr ├── Demo02_Fontface_Fontsize.dproj ├── Demo02_Fontface_Fontsize.res ├── Demo03_Move_Window.dpr ├── Demo03_Move_Window.dproj ├── Demo03_Move_Window.res ├── Demo04_Input_Keyboard.dpr ├── Demo04_Input_Keyboard.dproj ├── Demo04_Input_Keyboard.res ├── Demo05_ConsoleMode.dpr ├── Demo05_ConsoleMode.dproj ├── Demo05_ConsoleMode.res ├── Demo06_Colors.dpr ├── Demo06_Colors.dproj ├── Demo06_Colors.res ├── Demo07_ScreenSave.dpr ├── Demo07_ScreenSave.dproj ├── Demo07_ScreenSave.res ├── Demo08_ASCII_Charachters.dpr ├── Demo08_ASCII_Charachters.dproj ├── Demo08_ASCII_Charachters.res ├── Demo09_BuiltIn_Features.dpr ├── Demo09_BuiltIn_Features.dproj ├── Demo09_BuiltIn_Features.res ├── Demo10_Debug_VCL_App.dpr ├── Demo10_Debug_VCL_App.dproj ├── Demo10_Debug_VCL_App.res ├── Demo10_Debug_VCL_App_Form.dfm ├── Demo10_Debug_VCL_App_Form.pas ├── Demo11_Scrolltext.dpr ├── Demo11_Scrolltext.dproj ├── Demo11_Scrolltext.res └── Demos_Crt_Console.groupproj ├── License.md ├── Pictures ├── Demo01_Minimal_Console_App.jpg ├── Demo02_Fontface_Fontsize.jpg ├── Demo03_Move_Window.jpg ├── Demo04_Input_Keyboard.jpg ├── Demo05_Console_Mode.jpg ├── Demo06_Colors.jpg ├── Demo07_ScreenSave.jpg ├── Demo08_ASCII_Characters.jpg └── Demo09_BuiltIn_Features.jpg ├── Ply.Console.Debug.pas ├── Ply.Console.Extended.pas ├── Ply.Console.pas ├── Ply.DateTime.pas ├── Ply.Defines.inc ├── Ply.Files.pas ├── Ply.Math.pas ├── Ply.Patches.pas ├── Ply.StrUtils.pas ├── Ply.SysUtils.pas ├── Ply.Types.pas ├── Readme.md ├── crt.inc └── crt.pas /.gitignore: -------------------------------------------------------------------------------- 1 | # Uncomment these types if you want even more clean repository. But be careful. 2 | # It can make harm to an existing project source. Read explanations below. 3 | # 4 | # Resource files are binaries containing manifest, project icon and version info. 5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. 6 | #*.res 7 | # 8 | # Type library file (binary). In old Delphi versions it should be stored. 9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. 10 | *.tlb 11 | # 12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 13 | # Uncomment this if you are not using diagrams or use newer Delphi version. 14 | *.ddp 15 | # 16 | # Visual LiveBindings file. Added in Delphi XE2. 17 | # Uncomment this if you are not using LiveBindings Designer. 18 | *.vlb 19 | # 20 | # Deployment Manager configuration file for your project. Added in Delphi XE2. 21 | # Uncomment this if it is not mobile development and you do not use remote debug feature. 22 | *.deployproj 23 | # 24 | # C++ object files produced when C/C++ Output file generation is configured. 25 | # Uncomment this if you are not using external objects (zlib library for example). 26 | *.obj 27 | 28 | # Delphi compiler-generated binaries (safe to delete) 29 | *.exe 30 | *.dll 31 | *.bpl 32 | *.bpi 33 | *.dcp 34 | *.so 35 | *.apk 36 | *.drc 37 | *.map 38 | *.dres 39 | *.rsm 40 | *.tds 41 | *.dcu 42 | *.lib 43 | *.a 44 | *.o 45 | *.ocx 46 | 47 | # Delphi autogenerated files (duplicated info) 48 | *.cfg 49 | *.hpp 50 | *Resource.rc 51 | 52 | # Delphi local files (user-specific info) 53 | *.local 54 | *.identcache 55 | *.projdata 56 | *.tvsconfig 57 | *.dsk 58 | 59 | # Delphi history and backups 60 | __history/ 61 | __recovery/ 62 | *.~* 63 | *.bak 64 | 65 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 66 | *.stat 67 | 68 | # Delphi history and backups 69 | __history/ 70 | __recovery/ 71 | *.~* 72 | *.bak 73 | 74 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 75 | *.stat 76 | -------------------------------------------------------------------------------- /Demo/Demo01_Minimal_Console_App.dpr: -------------------------------------------------------------------------------- 1 | program Demo01_Minimal_Console_App; 2 | 3 | {$APPTYPE CONSOLE} 4 | 5 | {$R *.res} 6 | 7 | {$I Ply.Defines.inc} 8 | 9 | Uses Crt; 10 | 11 | begin 12 | Console.Window(80,25); 13 | TextBackground(White); 14 | Textcolor(Red); 15 | ClrScr; 16 | Writeln('Hello World!'); 17 | Readkey; 18 | 19 | Window(3,3,78,23); 20 | TextBackground(Blue); 21 | Textcolor(Yellow); 22 | ClrScr; 23 | Writeln('Goodbye World!'); 24 | // wait 2 seconds and quit program 25 | Delay(2000); 26 | end. 27 | -------------------------------------------------------------------------------- /Demo/Demo01_Minimal_Console_App.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Demo/Demo01_Minimal_Console_App.res -------------------------------------------------------------------------------- /Demo/Demo02_Fontface_Fontsize.dpr: -------------------------------------------------------------------------------- 1 | program Demo02_Fontface_Fontsize; 2 | 3 | {$APPTYPE CONSOLE} 4 | 5 | {$R *.res} 6 | 7 | {$I Ply.Defines.inc} 8 | 9 | uses 10 | Crt, 11 | Ply.Console, 12 | Ply.Types, 13 | Ply.StrUtils, 14 | System.SysUtils; 15 | 16 | Var 17 | Key : Word; 18 | CurWinSize : TConsoleWindowPoint; 19 | begin 20 | try 21 | Textcolor(Yellow); 22 | TextBackground(Blue); 23 | CurWinSize.Create(70,10); 24 | Console.Font.SetDefault; 25 | Repeat 26 | Console.Window(CurWinSize); 27 | Console.AutofitPosition; 28 | ClrScr; 29 | GotoXY(1,1); 30 | Writeln('(1..5|TAB) Fontface : '+Console.Font.FontNumberText); 31 | Writeln('(+|-) Fontsize : '+Console.Font.FontSizeText); 32 | Writeln('(Ctrl)&(←|→|↑|↓) Window-Size : '+Console.WindowSize.ToStringSize); 33 | Writeln('(ESC) Exit'); 34 | WriteXY(1,8,'Desktop.Position : '+Console.Desktop.Area.ToStringPos); 35 | WriteXY(1,9,'Desktop.Size : '+Console.Desktop.Area.ToStringSize); 36 | Readkey(Key); 37 | if (Key=_CTRL_RIGHT) then CurWinSize.x := CurWinSize.x + 1 else 38 | if (Key=_CTRL_LEFT) and (CurWinSize.x>51) then CurWinSize.x := CurWinSize.x - 1 else 39 | if (Key=_CTRL_DOWN) then CurWinSize.y := CurWinSize.y + 1 else 40 | if (Key=_CTRL_Up) and (CurWinSize.y>5) then CurWinSize.y := CurWinSize.y - 1 else 41 | if (Key=_Plus) then Console.Font.IncFontSize else 42 | if (Key=_Minus) then Console.Font.DecFontSize else 43 | if (Key=_Tab) then 44 | begin 45 | Console.Font.IncFontNumber; 46 | end else 47 | if (Key=_Shift_Tab) then 48 | begin 49 | Console.Font.DecFontNumber; 50 | end else 51 | if (Key>=_1) and (Key<=_5) then 52 | begin 53 | Console.Font.FontNumber := (LastKey-_0); 54 | end; 55 | Until (Key=_Esc); 56 | except 57 | on E: Exception do 58 | Writeln(E.ClassName, ': ', E.Message); 59 | end; 60 | end. 61 | -------------------------------------------------------------------------------- /Demo/Demo02_Fontface_Fontsize.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Demo/Demo02_Fontface_Fontsize.res -------------------------------------------------------------------------------- /Demo/Demo03_Move_Window.dpr: -------------------------------------------------------------------------------- 1 | program Demo03_Move_Window; 2 | 3 | {$APPTYPE CONSOLE} 4 | 5 | {$R *.res} 6 | 7 | {$I Ply.Defines.inc} 8 | 9 | uses 10 | Crt, 11 | Ply.Console, 12 | Ply.Types, 13 | System.SysUtils; 14 | 15 | Var corner : Byte; 16 | WorkAreas : tWorkAreas; 17 | CurWorkArea : TConsoleDesktopRect; 18 | CurDeskPos : TConsoleDesktopPoint; 19 | Key : Word; 20 | begin 21 | try 22 | Corner := 0; 23 | WorkAreas.GetWorkAreas; 24 | Console.Window(100,30); 25 | Console.Font.SetDefault; 26 | Repeat 27 | CurWorkArea := WorkAreas.GetWorkArea(Console.Desktop.Position).Rect; 28 | ClrScr; 29 | Writeln(' │ Size │ Rectangle │'); 30 | Writeln('Screen │ '+CurWorkArea.ToStringSize +' │ '+CurWorkArea.ToStringRect +'│'); 31 | Writeln('Console.Desktop │ '+Console.Desktop.Area.ToStringSize +' │ '+Console.Desktop.Area.ToStringRect +'│'); 32 | Writeln('Console.Window │ '+Console.WindowRect.ToStringSize +' │ '+Console.WindowRect.ToStringRect +'│'); 33 | Writeln('Crt.WinSize │ '+Crt.WindSize.ToStringSize +' │ '+Crt.WindSize.ToStringRect +'│'); 34 | Writeln; 35 | Writeln('(Ctrl+Alt +|-) Console-Font : '+Console.Font.FontText); 36 | Writeln('(+|-) alter Console.Window.Size (lines & coloums)'); 37 | Textcolor(Yellow); 38 | Writeln(' Observe what happens when the console-window becomes larger than the screen.'); 39 | Writeln(' Observe what happens when the console-window is in the bottom right corner.'); 40 | Textcolor(LightGray); 41 | Writeln('(1|2) alter Crt.Window.Size'); 42 | Writeln('(←|→|↑|↓) move console-window'); 43 | Writeln('(Enter) move console-window to corner'); 44 | Writeln('(ESC) Exit'); 45 | 46 | Readkey(Key); 47 | if (Key=_Plus) then 48 | begin 49 | Console.Window(Console.WindowSize.X+5,Console.WindowSize.Y+2); 50 | end else 51 | if (Key=_Minus) then 52 | begin 53 | Console.Window(Console.WindowSize.X-5,Console.WindowSize.Y-2) 54 | end else 55 | if (Key=_1) then 56 | begin 57 | if (WindSize.Width>10) and (WindSize.Height>10) then 58 | begin 59 | ClrScr; 60 | Window(WindSize.Left+3,WindSize.Top+3,WindSize.Right-1,WindSize.Bottom-1); 61 | if (TextBackground=Black) 62 | then TextBackground(Blue) 63 | else TextBackground(Black); 64 | end; 65 | end else 66 | if (Key=_2) then 67 | begin 68 | if (WindSize.Width4) then 90 | begin 91 | Corner := 1; 92 | CurWorkArea := WorkAreas.GetWorkAreaNext(Console.Desktop.Position).Rect; 93 | end; 94 | if (corner=1) then 95 | begin 96 | CurDeskPos.Init(CurWorkArea.Left,0); 97 | Console.Desktop.Position := CurDeskPos; 98 | end else 99 | if (corner=2) then 100 | begin 101 | CurDeskPos.Init(CurWorkArea.Right-Console.Desktop.Area.Width,0); 102 | Console.Desktop.Position := CurDeskPos; 103 | end else 104 | if (corner=3) then 105 | begin 106 | CurDeskPos.Init(CurWorkArea.Right-Console.Desktop.Area.Width 107 | ,CurWorkArea.Bottom - Console.Desktop.Area.Height); 108 | Console.Desktop.Position := CurDeskPos; 109 | end else 110 | if (corner=4) then 111 | begin 112 | CurDeskPos.Init(CurWorkArea.Left 113 | ,CurWorkArea.Bottom-Console.Desktop.Area.Height); 114 | Console.Desktop.Position := CurDeskPos; 115 | end; 116 | end; 117 | Until (Key=_ESC); 118 | except 119 | on E: Exception do 120 | Writeln(E.ClassName, ': ', E.Message); 121 | end; 122 | end. 123 | -------------------------------------------------------------------------------- /Demo/Demo03_Move_Window.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Demo/Demo03_Move_Window.res -------------------------------------------------------------------------------- /Demo/Demo04_Input_Keyboard.dpr: -------------------------------------------------------------------------------- 1 | program Demo04_Input_Keyboard; 2 | 3 | {$APPTYPE CONSOLE} 4 | 5 | {$R *.res} 6 | 7 | {$I Ply.Defines.inc} 8 | 9 | uses 10 | Crt, 11 | Ply.Console, 12 | Ply.Console.Extended, 13 | Ply.Types, 14 | Ply.StrUtils, 15 | System.SysUtils; 16 | 17 | Var UStr : UnicodeString; 18 | Str850 : CP850String; 19 | Str437 : CP437String; 20 | AStr : AnsiString; 21 | SStr : ShortString; 22 | aString : String; 23 | aLongString : String; 24 | aInteger : Integer; 25 | aDouble : Double; 26 | wch : WideChar; 27 | Key : Word; 28 | FieldNumber : Integer; 29 | begin 30 | uStr := ''; 31 | aString := '€äöüß ¹²³⁴⁵⁶ - Length restricted to input-field 0123456789 0123456789'; 32 | aLongString := 'This text is longer than the input-field, with which this text can ' 33 | + 'be edited. In addition, it is possible to display the complete text ' 34 | + 'at a different position during input. With (Ctrl + ←|→) you are able ' 35 | + 'to move the cursor to the beginning of the next word. Using (Crtl ' 36 | + '+ ^) you can insert an Ascii-Char [000..255] from current input-' 37 | + 'codepage or an Unicode-Char [0000..FFFF]. To use this feature you ' 38 | + 'have to set first "Console.Flags.AsciiCodeInput := True" in your ' 39 | + 'code. E.g. 277A brings you the character "❺" or 260E the telefon' 40 | + '-character "☎ ". You can also get chinese or japanese characters ' 41 | + 'or something like that "╠" (2560).' ; 42 | aInteger := 1234567; 43 | aDouble := 12345.67; 44 | FieldNumber := 0; 45 | Console.Modes.EnableAsciiCodeInput := True; 46 | try 47 | Console.Window(120,35); 48 | Repeat 49 | Color(LightGray,Black); 50 | ClrScr; 51 | WriteXY(1,1,'Windows-Codepage : '+Console.CodepageWindows.ToString); 52 | WriteXY(1,2,'Keyboard-Layout : $'+Console.KeyboardLayout.ToHexString); 53 | WriteXY(1,3,'Last Input : "'+UStr+'"'); 54 | 55 | Textcolor(LightGreen); 56 | WriteXY(1,10,'(Alt+F1..F3) ConInputCodepage : '+Console.InputCodepage.ToString); 57 | WriteXY(1,11,'(Alt+F4..F6) ConOutputCodepage : '+Console.OutputCodepage.ToString); 58 | WriteXY(1,12,'(Esc) Exit'); 59 | 60 | TextAttr.Create(Yellow,Blue,_ExtTextAttrOutline); 61 | WriteXY( 1,17,'LastInput:'); 62 | WriteXY(90,17,'ASCII-Value first 5 Chars'); 63 | TextAttr.Create(LightGray,Black); 64 | 65 | WriteXY(1,18,'Unicode-String : '); 66 | WriteXY(16,18,StringCodePage(UStr).ToString); 67 | WriteXY(24,18,UStr); 68 | GotoXY(89,18); ClrEol; Textcolor(LightCyan); 69 | if (Length(UStr)>0) then WriteXY( 90,18,'$'+Ord(UStr[1]).ToHexString(4)); 70 | if (Length(UStr)>1) then WriteXY( 96,18,'$'+Ord(UStr[2]).ToHexString(4)); 71 | if (Length(UStr)>2) then WriteXY(102,18,'$'+Ord(UStr[3]).ToHexString(4)); 72 | if (Length(UStr)>3) then WriteXY(108,18,'$'+Ord(UStr[4]).ToHexString(4)); 73 | if (Length(UStr)>4) then WriteXY(114,18,'$'+Ord(UStr[5]).ToHexString(4)); 74 | 75 | TextColor(LightGray); 76 | WriteXY(1,19,'Ansi-String : '); 77 | WriteXY(16,19,StringCodepage(AStr).ToString); 78 | WriteXY(24,19,UnicodeString(AStr)); 79 | GotoXY(89,19); ClrEol; Textcolor(LightCyan); 80 | if (Length(AStr)>0) then WriteXY( 90,19,'$'+Ord(AStr[1]).ToHexString(4)); 81 | if (Length(AStr)>1) then WriteXY( 96,19,'$'+Ord(AStr[2]).ToHexString(4)); 82 | if (Length(AStr)>2) then WriteXY(102,19,'$'+Ord(AStr[3]).ToHexString(4)); 83 | if (Length(AStr)>3) then WriteXY(108,19,'$'+Ord(AStr[4]).ToHexString(4)); 84 | if (Length(AStr)>4) then WriteXY(114,19,'$'+Ord(AStr[5]).ToHexString(4)); 85 | 86 | TextColor(LightGray); 87 | WriteXY(1,20,'CP850-String : '); 88 | WriteXY(16,20,StringCodepage(Str850).ToString); 89 | WriteXY(24,20,Str850); 90 | GotoXY(89,20); ClrEol; Textcolor(LightCyan); 91 | if (Length(Str850)>0) then WriteXY( 90,20,'$'+Ord(Str850[1]).ToHexString(4)); 92 | if (Length(Str850)>1) then WriteXY( 96,20,'$'+Ord(Str850[2]).ToHexString(4)); 93 | if (Length(Str850)>2) then WriteXY(102,20,'$'+Ord(Str850[3]).ToHexString(4)); 94 | if (Length(Str850)>3) then WriteXY(108,20,'$'+Ord(Str850[4]).ToHexString(4)); 95 | if (Length(Str850)>4) then WriteXY(114,20,'$'+Ord(Str850[5]).ToHexString(4)); 96 | 97 | TextColor(LightGray); 98 | WriteXY(1,21,'CP437-String : '); 99 | WriteXY(16,21,StringCodepage(Str437).ToString); 100 | WriteXY(24,21,UnicodeString(Str437)); 101 | GotoXY(89,21); ClrEol; Textcolor(LightCyan); 102 | if (Length(Str437)>0) then WriteXY( 90,21,'$'+Ord(Str437[1]).ToHexString(4)); 103 | if (Length(Str437)>1) then WriteXY( 96,21,'$'+Ord(Str437[2]).ToHexString(4)); 104 | if (Length(Str437)>2) then WriteXY(102,21,'$'+Ord(Str437[3]).ToHexString(4)); 105 | if (Length(Str437)>3) then WriteXY(108,21,'$'+Ord(Str437[4]).ToHexString(4)); 106 | if (Length(Str437)>4) then WriteXY(114,21,'$'+Ord(Str437[5]).ToHexString(4)); 107 | 108 | TextColor(LightGray); 109 | WriteXY(1,22,'Short-String : '); 110 | WriteXY(24,22,SStr); 111 | GotoXY(89,22); ClrEol; Textcolor(LightCyan); 112 | if (Length(SStr)>0) then WriteXY( 90,22,'$'+Ord(SStr[1]).ToHexString(4)); 113 | if (Length(SStr)>1) then WriteXY( 96,22,'$'+Ord(SStr[2]).ToHexString(4)); 114 | if (Length(SStr)>2) then WriteXY(102,22,'$'+Ord(SStr[3]).ToHexString(4)); 115 | if (Length(SStr)>3) then WriteXY(108,22,'$'+Ord(SStr[4]).ToHexString(4)); 116 | if (Length(SStr)>4) then WriteXY(114,22,'$'+Ord(SStr[5]).ToHexString(4)); 117 | 118 | TextColor(LightGray); 119 | WriteXY(1,5,'Input String : '+Copy(aString,1,50)); 120 | WriteXY(1,6,'Input Long String : '+Copy(aLongString,1,70)); 121 | WriteXY(1,7,'Input Integer : '+aInteger.ToString); 122 | WriteXY(1,8,'Input Double : '+DoubleToString(aDouble,0,4,',','.')); 123 | 124 | GotoXY(21,5+FieldNumber); 125 | if (FieldNumber=0) then 126 | begin 127 | aString := InputString(aString,50,Key,[inpCursorPos1]); 128 | UStr := aString; 129 | end else 130 | if (FieldNumber=1) then 131 | begin 132 | aLongString := InputString(aLongString,70,1000,Black,LightGray,Key 133 | ,[inpCursorPos1, inpInsertMode],1,24); 134 | UStr := aLongString; 135 | end else 136 | if (FieldNumber=2) then 137 | begin 138 | aInteger := InputInteger(aInteger,40,Key); 139 | UStr := aInteger.ToString; 140 | end else 141 | if (FieldNumber=3) then 142 | begin 143 | aDouble := InputDouble(aDouble,40,Key,[],4,',','.'); 144 | UStr := DoubleToString(aDouble,0,4,',','.'); 145 | end; 146 | 147 | CursorMoveField(FieldNumber,0,3); 148 | 149 | AStr := AnsiString(UStr); 150 | Str850 := Str_Unicode_CP850(UStr); 151 | Str437 := CP437String(UStr); 152 | SStr := Str850; 153 | 154 | if (LastKey=_ALT_F1) then Console.InputCodepage := _Codepage_437 else 155 | if (LastKey=_ALT_F2) then Console.InputCodepage := _Codepage_850 else 156 | if (LastKey=_ALT_F3) then Console.InputCodepage := _Codepage_1252 else 157 | if (LastKey=_ALT_F4) then Console.OutputCodepage := _Codepage_437 else 158 | if (LastKey=_ALT_F5) then Console.OutputCodepage := _Codepage_850 else 159 | if (LastKey=_ALT_F6) then Console.OutputCodepage := _Codepage_1252; 160 | 161 | Until (LastKey=_ALT_X) or (LastKey=_ESC); 162 | except 163 | on E: Exception do 164 | Writeln(E.ClassName, ': ', E.Message); 165 | end; 166 | end. 167 | -------------------------------------------------------------------------------- /Demo/Demo04_Input_Keyboard.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Demo/Demo04_Input_Keyboard.res -------------------------------------------------------------------------------- /Demo/Demo05_ConsoleMode.dpr: -------------------------------------------------------------------------------- 1 | program Demo05_ConsoleMode; 2 | 3 | {$APPTYPE CONSOLE} 4 | 5 | {$R *.res} 6 | 7 | {$I Ply.Defines.inc} 8 | 9 | uses 10 | Crt, 11 | Ply.Console, 12 | Ply.Console.Extended, 13 | Ply.StrUtils, 14 | Ply.Types, 15 | System.Math, 16 | System.SysUtils, 17 | Vcl.Clipbrd; 18 | 19 | Procedure TestInputBehavior; 20 | Var 21 | FieldNumber : Integer; 22 | Key : Word; 23 | S1, S2, S3 : String; 24 | begin 25 | Window(1,25,35,31,'Test Input Behavior','(Esc) Exit'); 26 | FieldNumber := 0; 27 | Repeat 28 | WriteXY(1,1,'Field 1 : '+S1); ClrEol; 29 | WriteXY(1,2,'Field 2 : '+S2); ClrEol; 30 | WriteXY(1,3,'Field 3 : '+S3); ClrEol; 31 | if (FieldNumber=0) then s1 := InputString(11,1,s1,20,Key) else 32 | if (FieldNumber=1) then s2 := InputString(11,2,s2,20,Key) else 33 | if (FieldNumber=2) then s3 := InputString(11,3,s3,20,Key); 34 | CursorMoveField(FieldNumber,0,3); 35 | if (FieldNumber>2) then FieldNumber := 0; 36 | Until (Key=_ESC); 37 | Crt.Window; 38 | end; 39 | 40 | Procedure Show_Modes; 41 | Var ClipboardText : String; 42 | TextAttrHead : TTextAttr; 43 | TextAttrNote : TTextAttr; 44 | begin 45 | ClrScr; 46 | TextAttrHead.Color(Yellow,Black); 47 | TextAttrHead.Outline := True; 48 | TextAttrNote.Color(White,Red); 49 | TextAttrNote.Underline := True; 50 | 51 | WriteXY( 1, 1,TextAttrHead,'Appearance properties'); 52 | WriteXY( 1, 2,'(1) Cursor-Visible : '+BoolToStringYesNo(Console.CursorVisible)); 53 | WriteXY( 1, 3,'(2) Cursor-Size : '+IntToString(Console.CursorSize)); ClrEol; 54 | {$IFDEF CONSOLEOPACITY} 55 | WriteXY( 1, 4,'(3) Opacity in % : '+IntToString(Console.Modes.Opacity)); 56 | WriteXY( 1, 5,'(4) AutoOpacity on focus : '+BoolToStringYesNo(Console.Modes.AutoOpacityOnFocus)); 57 | {$ENDIF CONSOLEOPACITY} 58 | WriteXY(40, 1,TextAttrHead,'Crt extended features'); 59 | WriteXY(40, 2,'(5) AlternateWriteProc : '+Console.Modes.AlternateWriteProcText); 60 | WriteXY(40, 3,'(6) EnableAsciiCodeInput : '+BoolToStringYesNo(Console.Modes.EnableAsciiCodeInput)); 61 | WriteXY(40, 4,'(7) WrapWord : '+BoolToStringYesNo(Console.Modes.WrapWord)); 62 | WriteXY(40, 5,'(8) ReplaceControlChracter : '+BoolToStringYesNo(Console.Modes.ReplaceCtrlChar)); 63 | 64 | WriteXY( 1, 7,TextAttrHead,'V2 console features'); 65 | WriteXY(23, 7,TextAttrNote,'Note: Some of this V2-features needs restart of application'); 66 | WriteXY( 1, 8,'(F2) ForceV2 : '+BoolToStringYesNo(Console.Modes.ForceV2)); 67 | WriteXY( 1, 9,'(F3) LineSelection : '+BoolToStringYesNo(Console.Modes.LineSelection)); 68 | WriteXY( 1,10,'(F4) FilterOnPaste : '+BoolToStringYesNo(Console.Modes.FilterOnPaste)); 69 | WriteXY( 1,11,'(F5) LineWrap : '+BoolToStringYesNo(Console.Modes.LineWrap)); 70 | WriteXY(40, 8,'(F6) CtrlKeyShortcutsDisabled : '+BoolToStringYesNo(Console.Modes.CtrlKeyShortcutsDisabled)); 71 | WriteXY(40, 9,'(F7) ExtendedEditKey : '+BoolToStringYesNo(Console.Modes.ExtendedEditKey)); 72 | WriteXY(40,10,'(F8) TrimLeadingZeros : '+BoolToStringYesNo(Console.Modes.TrimLeadingZeros)); 73 | 74 | Console.Modes.GetCurrentMode; 75 | WriteXY( 1,13,TextAttrHead,'Standard-Input-Flags:'+IntToString(Console.Modes.Input,4)); 76 | WriteXY( 1,14,'(A) ProcessedInput : '+BoolToStringYesNo(Console.Modes.ProcessedInput)); 77 | WriteXY( 1,15,'(B) LineInput : '+BoolToStringYesNo(Console.Modes.LineInput)); 78 | WriteXY( 1,16,'(C) EchoInput : '+BoolToStringYesNo(Console.Modes.EchoInput)); 79 | WriteXY( 1,17,'(D) WindowInput : '+BoolToStringYesNo(Console.Modes.WindowInput)); 80 | WriteXY( 1,18,'(E) MouseInput : '+BoolToStringYesNo(Console.Modes.MouseInput)); 81 | WriteXY( 1,19,'(F) ExtendedFlags : '+BoolToStringYesNo(Console.Modes.ExtendedFlags)); 82 | WriteXY( 1,20,' (G) InsertMode : '+BoolToStringYesNo(Console.Modes.InsertMode)); 83 | WriteXY( 1,21,' (H) QuickEditMode : '+BoolToStringYesNo(Console.Modes.QuickEditMode)); 84 | WriteXY( 1,22,' (I) AutoPosition : '+BoolToStringYesNo(Console.Modes.AutoPosition)); 85 | WriteXY( 1,23,'(J) VirtualTerminalInput : '+BoolToStringYesNo(Console.Modes.VirtualTerminalInput)); 86 | 87 | WriteXY(40,13,TextAttrHead,'Standard-Output-Flags:'+IntToString(Console.Modes.Output,4)); 88 | WriteXY(40,14,'(K) ProcessedOutput : '+BoolToStringYesNo(Console.Modes.ProcessedOutput)); 89 | WriteXY(40,15,'(L) WrapOutput : '+BoolToStringYesNo(Console.Modes.WrapOutput)); 90 | WriteXY(40,16,'(M) VirtualTerminal : '+BoolToStringYesNo(Console.Modes.VirtualTerminal)); 91 | WriteXY(40,17,'(N) DisableNewlineAutoReturn : '+BoolToStringYesNo(Console.Modes.DisableNewlineAutoReturn)); 92 | WriteXY(40,18,'(O) LvbGridWorldwide : '+BoolToStringYesNo(Console.Modes.LvbGridWorldwide)); 93 | 94 | WriteXY(1,25,'Console.Font:'); 95 | WriteXY(1,26,Console.Font.FontText); 96 | WriteXY(1,28,'Console.Desktop.Size:'); 97 | WriteXY(1,29,Console.Desktop.Area.ToStringPosSize); 98 | WriteXY(1,31,LightMagenta,'(Alt+I) TestInputBehavior'); 99 | 100 | Window(40,20,90,35,'Test Output Clipboard','(Alt+V) Set Clipboard to Demostring'); 101 | ClipboardText := Clipboard.AsText; 102 | 103 | TextColor(LightGreen); 104 | WriteXY(1,1,'Writeln (System.Writeln):'); 105 | GotoXY(1,2); Writeln(ClipboardText); 106 | 107 | Textcolor(LightMagenta); 108 | WriteXY(1,8,'WriteString (faster):'); 109 | WriteString(1,9,ClipboardText); 110 | 111 | TextColor(LightGray); 112 | Crt.Window; 113 | end; 114 | 115 | Procedure Edit_Flags; 116 | Var 117 | Key : Word; 118 | {$IFDEF CONSOLEOPACITY} 119 | OpacityPercent : Byte; 120 | {$ENDIF CONSOLEOPACITY} 121 | begin 122 | Try 123 | {$IFDEF CONSOLEOPACITY} 124 | OpacityPercent := 100; 125 | {$ENDIF CONSOLEOPACITY} 126 | Repeat 127 | Show_Modes; 128 | Readkey(Key); 129 | if (Key=_1) then Console.CursorVisible := not(Console.CursorVisible) else 130 | if (Key=_2) then 131 | begin 132 | if (Console.CursorSize<100) 133 | then Console.CursorSize := Min(Console.CursorSize+5,100) 134 | else Console.CursorSize := 25; 135 | end else 136 | {$IFDEF CONSOLEOPACITY} 137 | if (Key=_3) then 138 | begin 139 | if (OpacityPercent>0) 140 | then OpacityPercent := Max(0,OpacityPercent-5) 141 | else OpacityPercent := 100; 142 | Console.Modes.Opacity := OpacityPercent; 143 | end else 144 | if (Key=_4) then Console.Modes.AutoOpacityOnFocus := not(Console.Modes.AutoOpacityOnFocus) else 145 | {$ENDIF CONSOLEOPACITY} 146 | if (Key=_5) then 147 | begin 148 | if (Console.Modes.AlternateWriteProc=awOff) 149 | then Console.Modes.AlternateWriteProc := awCrt else 150 | if (Console.Modes.AlternateWriteProc=awCrt) 151 | then Console.Modes.AlternateWriteProc := awConsole 152 | else Console.Modes.AlternateWriteProc := awOff; 153 | end else 154 | if (Key=_6) then Console.Modes.EnableAsciiCodeInput := not(Console.Modes.EnableAsciiCodeInput) else 155 | if (Key=_7) then Console.Modes.WrapWord := not(Console.Modes.WrapWord) else 156 | if (Key=_8) then Console.Modes.ReplaceCtrlChar := not(Console.Modes.ReplaceCtrlChar) else 157 | // Special V2 Features 158 | if (Key=_F2) then Console.Modes.ForceV2 := not(Console.Modes.ForceV2) else 159 | if (Key=_F3) then Console.Modes.LineSelection := not(Console.Modes.LineSelection) else 160 | if (Key=_F4) then Console.Modes.FilterOnPaste := not(Console.Modes.FilterOnPaste) else 161 | if (Key=_F5) then Console.Modes.LineWrap := not(Console.Modes.LineWrap) else 162 | if (Key=_F6) then Console.Modes.CtrlKeyShortcutsDisabled := not(Console.Modes.CtrlKeyShortcutsDisabled) else 163 | if (Key=_F7) then Console.Modes.ExtendedEditKey := not(Console.Modes.ExtendedEditKey) else 164 | if (Key=_F8) then Console.Modes.TrimLeadingZeros := not(Console.Modes.TrimLeadingZeros) else 165 | // Standard Input/Output Flags 166 | if (Key=_a) then Console.Modes.ProcessedInput := not(Console.Modes.ProcessedInput) else 167 | if (Key=_b) then Console.Modes.LineInput := not(Console.Modes.LineInput) else 168 | if (Key=_c) then Console.Modes.EchoInput := not(Console.Modes.EchoInput) else 169 | if (Key=_d) then Console.Modes.WindowInput := not(Console.Modes.WindowInput) else 170 | if (Key=_e) then Console.Modes.MouseInput := not(Console.Modes.MouseInput) else 171 | if (Key=_f) then Console.Modes.ExtendedFlags := not(Console.Modes.ExtendedFlags) else 172 | if (Key=_g) then Console.Modes.InsertMode := not(Console.Modes.InsertMode) else 173 | if (Key=_h) then Console.Modes.QuickEditMode := not(Console.Modes.QuickEditMode) else 174 | if (Key=_i) then Console.Modes.AutoPosition := not(Console.Modes.AutoPosition) else 175 | if (Key=_j) then Console.Modes.VirtualTerminalInput := not(Console.Modes.VirtualTerminalInput) else 176 | if (Key=_k) then Console.Modes.ProcessedOutput := not(Console.Modes.ProcessedOutput) else 177 | if (Key=_l) then Console.Modes.WrapOutput := not(Console.Modes.WrapOutput) else 178 | if (Key=_m) then Console.Modes.VirtualTerminal := not(Console.Modes.VirtualTerminal) else 179 | if (Key=_n) then Console.Modes.DisableNewlineAutoReturn := not(Console.Modes.DisableNewlineAutoReturn) else 180 | if (Key=_o) then Console.Modes.LvbGridWorldwide := not(Console.Modes.LvbGridWorldwide) else 181 | if (Key=_ALT_I) then TestInputBehavior else 182 | if (Key=_ALT_V) then 183 | begin 184 | Clipboard.AsText := 'Line 1.1|Line 1.2|Line 1.3|Line 1.4|Line 1.5|'+sLineBreak 185 | + 'Line 2.1|Line 2.2|Line 2.3|Line 2.4|Line 2.5|Line 2.6|'+sLineBreak 186 | + 'Line 3.1|Line 3.2|Line 3.3|Line 3.4|Line 3.5|Line 3.6|Line 3.7|'; 187 | end; 188 | Until (Key=_ESC); 189 | Except 190 | On E : EConsoleApiError do 191 | begin 192 | ConsoleShowError('EConsoleApiError',E.ClassName,E.Message); 193 | Readkey; 194 | end; 195 | End; 196 | end; 197 | 198 | begin 199 | try 200 | Crt.UseRegistry := False; 201 | Crt.UseScreenSaveFile := False; 202 | 203 | Console.Window(91,36); 204 | Edit_Flags; 205 | except 206 | on E: Exception do 207 | ConsoleShowError('Error',E.ClassName,E.Message); 208 | end; 209 | end. 210 | -------------------------------------------------------------------------------- /Demo/Demo05_ConsoleMode.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Demo/Demo05_ConsoleMode.res -------------------------------------------------------------------------------- /Demo/Demo06_Colors.dpr: -------------------------------------------------------------------------------- 1 | program Demo06_Colors; 2 | 3 | {$APPTYPE CONSOLE} 4 | 5 | {$R *.res} 6 | 7 | {$I Ply.Defines.inc} 8 | 9 | uses 10 | Crt, 11 | Ply.Console, 12 | Ply.Console.Extended, 13 | Ply.StrUtils, 14 | System.SysUtils; 15 | 16 | procedure Show_Colors1; 17 | Var 18 | TB,TC : Byte; 19 | begin 20 | Console.Window(147,17); 21 | Console.Font.SetDefault; 22 | Textbackground(Black); 23 | clrscr; 24 | For TB := 0 to 15 do 25 | begin 26 | Textbackground(TB); 27 | For TC := 0 to 15 do 28 | begin 29 | Textcolor(TC); 30 | WriteXY(1+(TB*9),1+TC,'TB'+IntToString(TB,2)+' TC'+IntToString(TC,2)+' '); 31 | end; 32 | end; 33 | Readkey; 34 | end; 35 | 36 | procedure Show_Colors2; 37 | Var 38 | TB,TC : Byte; 39 | Key : Word; 40 | dy : Byte; 41 | begin 42 | Console.Window(55,22); 43 | Console.Font.SetDefault; 44 | Textbackground(Black); 45 | clrscr; 46 | TB := 0; 47 | dy := 1; 48 | Repeat 49 | Textbackground(TB); 50 | clrscr; 51 | for TC := 0 to 15 do 52 | begin 53 | Textcolor(TC); 54 | Writeln('Background :'+IntToString(TB,3) 55 | +' Textcolor :'+IntToString(TC,3) 56 | +' TextAttr : '+IntToString(TextAttr,5)); 57 | end; 58 | Writeln; 59 | Writeln('(↑|↓) Move Cursor'); 60 | Writeln('(←|→) Change background color'); 61 | Writeln('(Esc) Exit'); 62 | Repeat 63 | InvertString(19,dy,14); 64 | Readkey(Key); 65 | InvertString(19,dy,14); 66 | if (Key=_Down) and (dy<16) then 67 | begin 68 | inc(dy); 69 | end else 70 | if (Key=_Up) and (dy>1) then 71 | begin 72 | dec(dy); 73 | end; 74 | Until (Key=_Escape) or (Key=_Right) or (Key=_Left); 75 | if (Key=_Right) and (TB<15) then inc(TB) else 76 | if (Key=_Left) and (TB>0) then dec(TB); 77 | Until (Key=_ESC); 78 | end; 79 | 80 | Procedure Edit_Colors1; 81 | Var ConsoleInfoEx : tConsoleInfoEx; 82 | Key : Word; 83 | BColor : Byte; 84 | CurY : Integer; 85 | begin 86 | Console.Window(100,34); 87 | Console.Font.SetDefault; 88 | BColor := Black; 89 | CurY := 0; 90 | ConsoleInfoEx := tConsoleInfoEx.Create; 91 | Repeat 92 | if (ConsoleInfoEx.GetInfoEx) then 93 | begin 94 | TextBackground(BColor); 95 | ClrScr; 96 | WriteXY(1,1,Yellow,'TConsoleScreenBufferInfoEx:'); 97 | ConsoleInfoEx.ShowDebug(1,2); 98 | WriteXY(50,1,Yellow,'TConsoleBufferInfo:'); 99 | Console.ShowDebug(50,2); 100 | ConsoleInfoEx.Show_Colors(1,10); 101 | WriteXY(1,29,'(F2) Edit Color'); 102 | WriteXY(1,30,'(F3) Default-ColorTable'); 103 | WriteXY(1,31,'(F4) Windows-ColorTable'); 104 | WriteXY(1,32,'(Alt +|-) Textbackground : '+IntToString(BColor)+' = '+ColorNames[BColor]); 105 | WriteXY(1,33,'(ESC) Exit'); 106 | Key := LineSelectExit(11,11+15,1,68,CurY); 107 | if (Key=_F2) then ConsoleInfoEx.Edit_Color(1,CurY,CurY-11) else 108 | if (Key=_F3) then ConsoleInfoEx.SetColorTableDefault else 109 | if (Key=_F4) then ConsoleInfoEx.SetColorTableWindows else 110 | if (Key=_ALT_Plus) and (BColorBlack) then dec(BColor); 112 | end else Key := _ESC; 113 | Until (Key=_ESC); 114 | ConsoleInfoEx.Free; 115 | end; 116 | 117 | Var Key : Word; 118 | begin 119 | try 120 | Console.Font.SetDefault; 121 | Repeat 122 | Color(LightGray,Black); 123 | Console.Window(80,25); 124 | Window(3,2,78,24); 125 | Color(Yellow,Blue); 126 | ClrScr; 127 | WriteXY(2,2,'(1) Show Colors 1'); 128 | WriteXY(2,3,'(2) Show Colors 2'); 129 | WriteXY(2,4,'(3) Edit Colors 1'); 130 | WriteXY(2,6,'(Esc) Exit'); 131 | Readkey(Key); 132 | if (Key=_1) then Show_Colors1 else 133 | if (Key=_2) then Show_Colors2 else 134 | if (Key=_3) then Edit_Colors1; 135 | Until (Key=_Escape); 136 | except 137 | on E: Exception do 138 | Writeln(E.ClassName, ': ', E.Message); 139 | end; 140 | end. 141 | -------------------------------------------------------------------------------- /Demo/Demo06_Colors.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Demo/Demo06_Colors.res -------------------------------------------------------------------------------- /Demo/Demo07_ScreenSave.dpr: -------------------------------------------------------------------------------- 1 | program Demo07_ScreenSave; 2 | 3 | {$APPTYPE CONSOLE} 4 | 5 | {$R *.res} 6 | 7 | {$I Ply.Defines.inc} 8 | 9 | uses 10 | Crt, 11 | Ply.Console, 12 | Ply.Console.Extended, 13 | Ply.Math, 14 | Ply.StrUtils, 15 | Ply.SysUtils, 16 | Ply.Types, 17 | System.SysUtils; 18 | 19 | Var 20 | Key : Word; 21 | ScreenSave : tScreenSave; 22 | BColor : Byte; 23 | FrameWindow : TFrameWindow; 24 | begin 25 | try 26 | BColor := 0; 27 | Color(LightGray,BColor); 28 | Console.WindowMedium; 29 | Console.Font.SetDefault; 30 | ScreenSave.Save; 31 | 32 | FrameWindow.ClearSettings; 33 | FrameWindow.ClrBackground := True; 34 | FrameWindow.ColorBackground := Magenta; 35 | FrameWindow.FrameTextColor := White; 36 | FrameWindow.FrameTextBackground := Darkgray; 37 | FrameWindow.TextTopLeft := 'Text Top Left'; 38 | FrameWindow.TextTitle := 'Text Top Center'; 39 | FrameWindow.TextTopRight := 'Text Top Right'; 40 | FrameWindow.TextBottomLeft := 'Text Bottom Left'; 41 | FrameWindow.TextBottomRight := 'Text Bottom Right'; 42 | // Print Crt.FrameWindow 43 | FrameWindow.Window(5,5,MaxX-4,MaxY-4); 44 | FrameWindow.ClrBackground := False; 45 | 46 | Repeat 47 | ClrScr; 48 | WriteXY(1, 1,'Program : '+ExeFile_Filename); 49 | WriteXY(1, 3,White,'(1) Edit ProgDataPath : '+PlyProgDataPath); 50 | WriteXY(1, 4,White,'(2) Edit ScreenSave.Filename : '+ScreenSave.Filename); 51 | WriteXY(1, 7,'Current Values :'); 52 | WriteXY(1, 8,'ScreenSave.Filename.Data : '+ScreenSave.Filename); 53 | WriteXY(1, 9,'ScreenSave.Filename.Index : '+ScreenSave.FilenameIndex); 54 | WriteXY(1,10,'ScreenSave.File.Count : '+IntToString(ScreenSave.FileCount,4)); 55 | WriteXY(1,14,'(Alt+1..5) Console.Window.Size : '+Console.WindowSize.ToStringSize); 56 | WriteXY(1,15,'(Tab|Shift+Tab) Crt.Window.Size : '+WindSize.ToStringSize); 57 | WriteXY(1,16,'(Ctrl+Alt+S) Save current Screen to File'); 58 | WriteXY(1,17,'(Ctrl+Alt+L) Load Screen from File'); 59 | 60 | ReadKey(Key); 61 | if (Key=_1) then 62 | begin 63 | GotoXY(32, 3); 64 | PlyProgDataPath := InputString(32,3,PlyProgDataPath,50,250); 65 | end else 66 | if (Key=_2) then 67 | begin 68 | ScreenSave.Filename := InputString(32,4,ScreenSave.Filename,50,250); 69 | end else 70 | if (Key=_ALT_1) then Console.WindowDefault else // 80 * 25 = 2000 Chars 71 | if (Key=_ALT_2) then Console.WindowMedium else // 100 * 35 = 3500 Chars 72 | if (Key=_ALT_3) then Console.WindowLarge else // 120 * 50 = 6000 Chars 73 | if (Key=_ALT_4) then Console.Window(150,60) else // 150 * 60 = 9000 Chars 74 | if (Key=_ALT_5) then Console.Window(200,80) else // 200 * 80 = 16000 Chars 75 | // (TAB) Reduce Crt.Window 76 | if (Key=_Tab) then 77 | begin 78 | inc(BColor); if (BColor>15) then BColor := 0; 79 | FrameWindow.TextColor := LightGray; 80 | FrameWindow.TextBackground := BColor; 81 | FrameWindow.Window(WindSize.Left+2,WindSize.Top+2,WindSize.Right,WindSize.Bottom); 82 | end else 83 | // (Shift+TAB) Enlarge Crt.Window 84 | if (Key=_SHIFT_TAB) then 85 | begin 86 | if (WindSize.Left>0) then 87 | begin 88 | inc(BColor); if (BColor>15) then BColor := 0; 89 | FrameWindow.TextColor := LightGray; 90 | FrameWindow.TextBackground := BColor; 91 | FrameWindow.Window(WindSize.Left-2,WindSize.Top-2,WindSize.Right+4,WindSize.Bottom+4); 92 | end; 93 | end; 94 | Until (Key=_ESC); 95 | except 96 | on E: Exception do 97 | Writeln(E.ClassName, ': ', E.Message); 98 | end; 99 | end. 100 | -------------------------------------------------------------------------------- /Demo/Demo07_ScreenSave.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Demo/Demo07_ScreenSave.res -------------------------------------------------------------------------------- /Demo/Demo08_ASCII_Charachters.dpr: -------------------------------------------------------------------------------- 1 | program Demo08_ASCII_Charachters; 2 | 3 | {$APPTYPE CONSOLE} 4 | 5 | {$R *.res} 6 | 7 | {$I Ply.Defines.inc} 8 | 9 | uses 10 | Crt, 11 | Ply.Console, 12 | Ply.Console.Extended, 13 | Ply.Types, 14 | Ply.SysUtils, 15 | Ply.StrUtils, 16 | System.Classes, 17 | System.SysUtils, 18 | Winapi.Windows; 19 | 20 | Var ConOutputAnsiWide : Boolean = True; 21 | 22 | Function ConOutputAnsiWide_Text : String; 23 | begin 24 | if (ConOutputAnsiWide) 25 | then Result := 'AnsiChar' 26 | else Result := 'WideChar'; 27 | end; 28 | 29 | Procedure Print_ASCII_Table(Page: Integer); 30 | Var i,x,y : Integer; 31 | begin 32 | Color(LightGray,Black); 33 | ClrScr; 34 | 35 | For i := 0 to $F do 36 | begin 37 | x := ((i mod 16) + 1) * 4 + 8; 38 | y := 1; 39 | WriteXY(x+0,y+0,i.ToHexString(1)); 40 | WriteXY(x-1,y+1,IntToString(i,2)); 41 | x := 1; 42 | y := i + 4; 43 | WriteXY(x,y,i.ToHexString(1)+' '+IntToString(i*16,3)); 44 | end; 45 | 46 | for i := (0+(Page*256)) to (255+(Page*256)) do 47 | begin 48 | x := ((i mod 16) + 1) * 4 + 8; 49 | y := ((i mod 256) div 16) + 4; 50 | if (ConOutputAnsiWide) 51 | then WriteChar(x,y,AnsiChar(i)) 52 | else WriteChar(x,y,WideChar(i)); 53 | end; 54 | end; 55 | 56 | Procedure Print_Menue(Page: Integer); 57 | begin 58 | Textcolor(White); 59 | WriteXY(1,21,'(Alt+A) Output : '+ConOutputAnsiWide_Text); 60 | if (ConOutputAnsiWide) then 61 | begin 62 | WriteXY(50,21,Yellow,'Current Codepage : '+IntToString(Console.OutputCodepage,6)); 63 | WriteXY(1,22,'(Alt+C) Codepage Switch'); 64 | WriteXY(1,23,'(Alt+D) Codepage Select'); 65 | end else 66 | begin 67 | WriteXY(30,21,'(Tab) Page : '+IntToStr(Page)); 68 | WriteXY(30,22,'#'+IntToStringLZ(Page*256,4)+'..' 69 | +'#'+IntToStringLZ(255+(Page*256),4)); 70 | WriteXY(30,23,'$'+(Page*256).ToHexString(4)+'..' 71 | +'$'+(255+(Page*256)).ToHexString(4)); 72 | end; 73 | WriteXY(1,25,'(Alt + 1..5) Fontface : '+Console.Font.FontName); 74 | WriteXY(1,26,'(Ctrl+Alt +|-) Fontsize : '+Console.Font.FontSizeText); 75 | end; 76 | 77 | procedure Console_Demo08_ASCII; 78 | Var 79 | Key : Word; 80 | Page : Integer; 81 | CP_Pos : Integer; 82 | ScreenSave : tScreenSave; 83 | 84 | Const CPs : Array [1..12] of tCodepage = (437,720,850,852,855,857,858,860,861,862,949,1252); 85 | 86 | begin 87 | CP_Pos := 3; 88 | Console.Font.GetCurrentFontEx; 89 | Console.CursorVisible := False; 90 | 91 | ScreenSave.Save; 92 | Console.Window(90,30); 93 | Page := 0; 94 | Window('Show ASCII characters','',Console.WindowSize.ToStringSize); 95 | Repeat 96 | Print_ASCII_Table(Page); 97 | Print_Menue(Page); 98 | 99 | Readkey(Key); 100 | if (Key=_Alt_A) then 101 | begin 102 | ConOutputAnsiWide := not(ConOutputAnsiWide); 103 | if (ConOutputAnsiWide) then 104 | begin 105 | Page := 0; 106 | end; 107 | end else 108 | if (Key=_ALT_C) and (ConOutputAnsiWide) then 109 | begin 110 | inc(CP_Pos); 111 | if (CP_Pos>length(CPs)) then CP_Pos := 1; 112 | Console.OutputCodepage := CPs[CP_Pos]; 113 | end else 114 | if (Key=_ALT_D) and (ConOutputAnsiWide) then 115 | begin 116 | Console.OutputCodepage := CodepageSelect(Console.OutputCodepage); 117 | end else 118 | if (Key=_Tab) and not(ConOutputAnsiWide) then 119 | begin 120 | inc(Page,1); 121 | if (Page>255) then Page := 0; 122 | end else 123 | if (Key=_Shift_Tab) and not(ConOutputAnsiWide) then 124 | begin 125 | dec(Page,1); 126 | if (Page<0) then Page := 255; 127 | end else 128 | if (Key>=_ALT_1) and (Key<=_ALT_5) then 129 | begin 130 | Console.Font.FontNumber := (Key-_ALT_0); 131 | end; 132 | until (Key=_ESC); 133 | ScreenSave.Restore; 134 | end; 135 | 136 | begin 137 | try 138 | Console_Demo08_ASCII; 139 | except 140 | on E: Exception do 141 | Writeln(E.ClassName, ': ', E.Message); 142 | end; 143 | end. 144 | -------------------------------------------------------------------------------- /Demo/Demo08_ASCII_Charachters.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Demo/Demo08_ASCII_Charachters.res -------------------------------------------------------------------------------- /Demo/Demo09_BuiltIn_Features.dpr: -------------------------------------------------------------------------------- 1 | program Demo09_BuiltIn_Features; 2 | 3 | {$APPTYPE CONSOLE} 4 | 5 | {$R *.res} 6 | 7 | {$I Ply.Defines.inc} 8 | 9 | uses 10 | Crt, 11 | Ply.Console, 12 | Ply.Console.Extended, 13 | Ply.Types, 14 | System.SysUtils; 15 | 16 | procedure Console_Demo09_BuiltIn; 17 | Var 18 | Key : Word; 19 | FrameAttr : TTextAttr; 20 | begin 21 | // Set Console-Window-Size to whatever size you want 22 | Console.Window(100,36); 23 | 24 | // Move Console.Window to a previous user saved position (see below) 25 | if not(ConsoleLocationMoveUser(0)) then 26 | begin 27 | // Move Console.Window (upper left corner) to a position you want 28 | Console.Desktop.MoveTo(300,10); 29 | end; 30 | 31 | // Set Console Font & Size 32 | // Console.Font: 1..5 = Terminal, Consolas, Lucida Console, Courier New, Fira Code 33 | // Console.Size: 1..9 34 | Console.Font.SetCurrentFont(_ConsoleFontCourierNew,6); 35 | // The folowing 2 lines would do the same as last line 36 | // Console.Font.FontNumber := _ConsoleFontCourierNew; 37 | // Console.Font.FontSize := 6; // [Size: 1..9] 38 | 39 | // Create a Crt.Window within which the output takes place 40 | // The borders should be inside Console.Window 41 | Window(5,5,90,30); 42 | Color(Black,White); // Set Textcolor & Textbackground for this Window 43 | ClrScr; // Init the Crt.Window with this color-settings 44 | WriteXY(10,2,'Some Text on Position (10|2) within Crt.Window'); 45 | // Pause, wait for any key to see effect 46 | Readkey; 47 | 48 | // Create a framed Crt.Window within which the output takes place. There 49 | // are 4 overloaded procedures to create windows with a frame If you 50 | // leave the size-information, the window will fill current Console.Window 51 | FrameAttr.Create(White, Red); 52 | Window('Window-Title', FrameAttr, 'Text-Bottom-Left' 53 | , 'Text-Bottom-Right', 'Text-Top-Left', 'Text-Top-Right'); 54 | Writeln('The workspace (crt.window) is smaller than the console window by 2 ' 55 | + 'rows and 2 columns because of the frame.'+sLineBreak 56 | + 'The default color is Lightgray on Black. You can use Color(' 57 | + 'foreground, background) and ClrScr to change the colors of the workspace.'); 58 | // Pause, wait for any key to see effect 59 | Readkey; 60 | 61 | Console.Font.FontNumber := _ConsoleFontConsolas; 62 | Console.Font.FontSize := 5; 63 | Color(White,Black); 64 | ClrScr; 65 | Repeat 66 | WriteXY(1, 1,Lightgreen,'Available with the use of "crt.pas"'); 67 | WriteXY(1, 2,Lightblue,'The functions are available (BuiltIn) as soon as a ' 68 | + 'keyboard-input is active.'); 69 | WriteXY(1, 3,Lightblue,'The programmer does not have to write any code for ' 70 | + 'this.'); 71 | WriteXY(1, 5,Yellow,'Console.Window: Fontsize:'); 72 | WriteXY(1, 6,'(Ctrl & Alt & +) Enlarge fontsize'); 73 | WriteXY(1, 7,'(Ctrl & Alt & -) Reduce fontsize'); 74 | WriteXY(1, 9,Yellow,'Console.Window: 10 positions & font-settings (save & load)'); 75 | WriteXY(1,10,'(Ctrl & Alt & 0..9) Load from registry - (Left-Ctrl & Left-Alt)'); 76 | WriteXY(1,11,'(Ctrl & AltGr & 0..9) Save to registry - (Right-Ctrl & Right-AltGr)'); 77 | 78 | WriteXY(1,13,Lightgreen,'Available with the use of "Ply.Console.Extended.pas"'); 79 | WriteXY(1,15,Yellow,'Save & Load ConsoleScreen (Text, Size, Cursorposition, ' 80 | +'etc.) to/from file'); 81 | WriteXY(1,16,'(Ctrl & Alt & S) Save current Screen to file'); 82 | WriteXY(1,17,'(Ctrl & Alt & L) Load (select & show) previous saved ' 83 | + 'screen from file'); 84 | WriteXY(1,19,Lightblue,'Loading from and saving to registry are replaced by ' 85 | + 'loading form and saving to file.'); 86 | WriteXY(1,20,'(Ctrl & Alt & 0..9) Load form file'); 87 | WriteXY(1,21,'(Ctrl & AltGr & 0..9) Save to file'); 88 | 89 | GotoXY(1,23); 90 | Writeln('So in this demo program the functions "form/to file" are always used. ' 91 | + 'However, you can always replace them with "from/to registry" by using ' 92 | + 'the following code at the start of your program:'+sLineBreak 93 | + ' Proc_CTRL_ALT_0_9 := ConsoleLocationMoveUserRegistry;'+sLineBreak 94 | + ' Proc_CTRL_ALTGR_0_9 := ConsoleLocationSaveUserRegistry;'+sLineBreak 95 | + 'For example, when starting the program, you can set the position of the ' 96 | + 'console.window to a position specified by the user (see line 24).' 97 | + sLineBreak + sLineBreak 98 | + 'Try any of the Functions above now. Look at the source code, there is ' 99 | + 'no code like '+sLineBreak+'"if (Key=_CTRL_ALT_1) then" necessary.'); 100 | WriteXY(1,33,'User input (Esc for exit): '); 101 | Readkey(Key); 102 | Until (Key=_ESC); 103 | end; 104 | 105 | begin 106 | try 107 | Console_Demo09_BuiltIn; 108 | except 109 | on E: Exception do 110 | Writeln(E.ClassName, ': ', E.Message); 111 | end; 112 | end. 113 | -------------------------------------------------------------------------------- /Demo/Demo09_BuiltIn_Features.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Demo/Demo09_BuiltIn_Features.res -------------------------------------------------------------------------------- /Demo/Demo10_Debug_VCL_App.dpr: -------------------------------------------------------------------------------- 1 | program Demo10_Debug_VCL_App; 2 | 3 | uses 4 | Ply.Console.Debug, 5 | Vcl.Forms, 6 | Demo10_Debug_VCL_App_Form in 'Demo10_Debug_VCL_App_Form.pas' {Form_Demo10}; 7 | 8 | {$R *.res} 9 | 10 | begin 11 | Application.Initialize; 12 | Application.MainFormOnTaskbar := True; 13 | Application.CreateForm(TForm_Demo10, Form_Demo10); 14 | Application.Run; 15 | end. 16 | -------------------------------------------------------------------------------- /Demo/Demo10_Debug_VCL_App.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Demo/Demo10_Debug_VCL_App.res -------------------------------------------------------------------------------- /Demo/Demo10_Debug_VCL_App_Form.dfm: -------------------------------------------------------------------------------- 1 | object Form_Demo10: TForm_Demo10 2 | Left = 0 3 | Top = 0 4 | Caption = 'Form_Demo10' 5 | ClientHeight = 666 6 | ClientWidth = 948 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -18 11 | Font.Name = 'Segoe UI' 12 | Font.Style = [] 13 | OnCreate = FormCreate 14 | PixelsPerInch = 144 15 | TextHeight = 25 16 | object Button1: TButton 17 | Left = 372 18 | Top = 228 19 | Width = 113 20 | Height = 38 21 | Margins.Left = 5 22 | Margins.Top = 5 23 | Margins.Right = 5 24 | Margins.Bottom = 5 25 | Caption = 'Button1' 26 | TabOrder = 0 27 | OnClick = Button1Click 28 | end 29 | object Button2: TButton 30 | Left = 372 31 | Top = 312 32 | Width = 113 33 | Height = 38 34 | Margins.Left = 5 35 | Margins.Top = 5 36 | Margins.Right = 5 37 | Margins.Bottom = 5 38 | Caption = 'Button2' 39 | TabOrder = 1 40 | OnClick = Button2Click 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /Demo/Demo10_Debug_VCL_App_Form.pas: -------------------------------------------------------------------------------- 1 | unit Demo10_Debug_VCL_App_Form; 2 | 3 | interface 4 | 5 | uses 6 | Crt, 7 | Winapi.Windows, 8 | Winapi.Messages, 9 | System.SysUtils, 10 | System.Variants, 11 | System.Classes, 12 | Vcl.Graphics, 13 | Vcl.Controls, 14 | Vcl.Forms, 15 | Vcl.Dialogs, 16 | Vcl.StdCtrls; 17 | 18 | type 19 | TForm_Demo10 = class(TForm) 20 | Button1: TButton; 21 | Button2: TButton; 22 | procedure Button1Click(Sender: TObject); 23 | procedure FormCreate(Sender: TObject); 24 | procedure Button2Click(Sender: TObject); 25 | private 26 | Counter : Integer; 27 | public 28 | end; 29 | 30 | var 31 | Form_Demo10: TForm_Demo10; 32 | 33 | implementation 34 | 35 | {$R *.dfm} 36 | 37 | procedure TForm_Demo10.Button1Click(Sender: TObject); 38 | begin 39 | ClrScr; 40 | inc(Counter); 41 | WriteXY(10, 2,'Clicks : '+Counter.ToString); 42 | WriteXY(10, 5,Lightred,'Button1 pressed'); 43 | end; 44 | 45 | procedure TForm_Demo10.Button2Click(Sender: TObject); 46 | begin 47 | ClrScr; 48 | inc(Counter); 49 | WriteXY(10, 2,'Clicks : '+Counter.ToString); 50 | WriteXY(10, 8,Green,'Button2 pressed'); 51 | end; 52 | 53 | procedure TForm_Demo10.FormCreate(Sender: TObject); 54 | begin 55 | Counter := 0; 56 | // Set position of the VCL window on the desktop 57 | Left := 10; 58 | Top := 10; 59 | end; 60 | 61 | begin 62 | // Set title of the Debug-Console-Window 63 | Console.Title := 'PlyConsole - Debug'; 64 | // Set size of the Debug-Console-Window in Chars (Medium = 100 x 35) 65 | Console.WindowMedium; 66 | // Set position of the Console-Window on Desktop 67 | Console.Desktop.MoveTo(1000,10); 68 | // Print information for the programmer 69 | Crt.Window(5,30,95,34); 70 | Color(White,DarkGray); 71 | ClrScr; 72 | WriteXY(3,2,'The unit Ply.Console.Debug must be placed before crt.pas in uses-clauses'); 73 | WriteXY(3,3,'It is recommended to use the unit as the first in the program.'); 74 | WriteXY(3,4,'See Demo10_Debug_VCL_App.dpr'); 75 | // Reduce workingspace to keep this information on Debug-Screen 76 | Crt.Window(1,1,100,29); 77 | Color(LightGray,Black); 78 | end. 79 | -------------------------------------------------------------------------------- /Demo/Demo11_Scrolltext.dpr: -------------------------------------------------------------------------------- 1 | program Demo11_Scrolltext; 2 | 3 | {$APPTYPE CONSOLE} 4 | 5 | {$R *.res} 6 | 7 | {$I Ply.Defines.inc} 8 | 9 | uses 10 | Crt, 11 | Ply.Console, 12 | Ply.Console.Extended, 13 | Ply.StrUtils, 14 | Ply.SysUtils, 15 | Ply.Types, 16 | System.Classes, 17 | System.SysUtils; 18 | 19 | Procedure EnlargeBufferSize; 20 | Var 21 | i : integer; 22 | Key : Word; 23 | uString : String; 24 | ScreenSave : tScreenSave; 25 | begin 26 | // ScreenSave is used here only to demonstrate its use. With ScreenSave.Save 27 | // and ScreenSave.Restore the programmer does not have to worry about which 28 | // console settings (size, color, CursorPos, etc.) are changed within the 29 | // current function. With ScreenSave.Restore the old settings and the old 30 | // contents of the window are simply restored. In the upstream function, 31 | // the screen then also does not have to be recreated. 32 | ScreenSave.Save; 33 | 34 | Color(Yellow,DarkGray); 35 | // enlarge BufferSize; 36 | Console.Buffer(180,1500); 37 | // Use Crt.WriteConsole instead of System.Write; 38 | Console.Modes.AlternateWriteProc := awConsole; 39 | 40 | uString := 'WritelnConsole '+ExeFile_Filename; 41 | for I := 1 to 300 do 42 | begin 43 | // Enlarge StringLength for Demo 44 | if ((i mod 50)=0) then uString := uString + '├────────┤'; 45 | WritelnConsole('Line['+IntToStringLZ(i,4)+'] : '+uString); 46 | end; 47 | 48 | uString := 'System.Writeln '+ExeFile_Filename; 49 | for I := 301 to 600 do 50 | begin 51 | // Enlarge StringLength for Demo 52 | if ((i mod 50)=0) then uString := uString + '├────────┤'; 53 | Writeln('Line['+IntToStringLZ(i,4)+'] : '+uString); 54 | end; 55 | 56 | Textcolor(LightGreen); 57 | for I := 1 to 600 do 58 | begin 59 | if ((i mod 10)=0) then 60 | begin 61 | WriteConsole(14,i,'GreenText'); 62 | end; 63 | end; 64 | 65 | GotoXYConsole(1,602); 66 | Textcolor(White); 67 | Writeln('Done!'); 68 | Writeln('Use Cursor-Keys and/or PgUp|PgDown to scroll text'); 69 | Writeln('(Esc) Exit function'); 70 | 71 | Console.ReadkeyScroll(Key); 72 | 73 | // Use default Crt.WriteString instead of System.Write 74 | Console.Modes.AlternateWriteProc := awCrt; 75 | 76 | ScreenSave.Restore; 77 | end; 78 | 79 | Procedure UseStringListConsole; 80 | Var 81 | i : integer; 82 | Key : Word; 83 | Strings : TStringListConsole; 84 | uString : String; 85 | ScreenSave : tScreenSave; 86 | begin 87 | // ScreenSave is used here only to demonstrate its use. With ScreenSave.Save 88 | // and ScreenSave.Restore the programmer does not have to worry about which 89 | // console settings (size, color, CursorPos, etc.) are changed within the 90 | // current function. With ScreenSave.Restore the old settings and the old 91 | // contents of the window are simply restored. In the upstream function, 92 | // the screen then also does not have to be recreated. 93 | ScreenSave.Save; 94 | 95 | Strings := TStringListConsole.Create; 96 | uString := 'Some text from '+ExeFile_Filename; 97 | for I := 1 to 600 do 98 | begin 99 | // Enlarge StringLength for Demo 100 | if ((i mod 50)=0) then uString := uString + '├────────┤'; 101 | Strings.Add('Line['+IntToStringLZ(i,4)+'] : '+uString); 102 | end; 103 | Repeat 104 | Key := Strings.Show('Show my Strings','(Alt+F12) Toggle WindowSize │ (Ctrl+S) SaveToFile'); 105 | if (Key=_CTRL_S) then 106 | begin 107 | Try 108 | Strings.SaveToFile(FilenameReplaceExtension(ExeFile_Filename,'txt'),TEncoding.UTF8); 109 | ConsoleShowNote('Save StringList to File', 110 | 'Strings were saved',FilenameReplaceExtension(ExeFile_Filename,'txt')); 111 | except 112 | on E: Exception do 113 | Writeln(E.ClassName, ': ', E.Message); 114 | End; 115 | end; 116 | Until (Key=_Esc); 117 | Strings.Free; 118 | 119 | ScreenSave.Restore; 120 | end; 121 | 122 | Var 123 | Key : Word; 124 | begin 125 | try 126 | Color(LightGray,Black); 127 | Console.Window(80,25); 128 | ClrScr; 129 | WriteXY(5,2,'(1) Enlarge ScreenBufferSize'); 130 | WriteXY(5,3,'(2) Use TStringListConsole'); 131 | WriteXY(5,4,'(Esc) Exit'); 132 | WriteXY(5,6,' =>'); 133 | Repeat 134 | Readkey(Key); 135 | if (Key=_1) then EnlargeBufferSize else 136 | if (Key=_2) then UseStringListConsole; 137 | Until (Key=_ESC); 138 | except 139 | on E: Exception do 140 | Writeln(E.ClassName, ': ', E.Message); 141 | end; 142 | 143 | end. 144 | -------------------------------------------------------------------------------- /Demo/Demo11_Scrolltext.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Demo/Demo11_Scrolltext.res -------------------------------------------------------------------------------- /Demo/Demos_Crt_Console.groupproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {2760090C-6DC5-4C06-A528-3BB44FAF153C} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | Default.Personality.12 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | Copyright © 1999 - 2023 Playcom Software Vertriebs GmbH / Wolfgang Myrth - All rights reserved. 2 | 3 | # Three Licenses Model 4 | 5 | The Library source code is licensed under a disjunctive three-license giving you the choice of one of the three following sets of free software/open source licensing terms: 6 | 7 | Mozilla Public License, version 1.1 or later (MPL) 8 | GNU General Public License, version 2.0 or later (GPL) 9 | GNU Lesser General Public License, version 2.1 or later (LGPL) 10 | 11 | This allows you to use of the Library code in a wide variety of software projects, while still maintaining intellectual rights on library code. 12 | 13 | Licenses: 14 | 15 | For GPL projects, use the GPL - see http://www.gnu.org/licenses/gpl-2.0.html 16 | For LGPL projects, use the LGPL - see http://www.gnu.org/licenses/lgpl-2.1.html 17 | For commercial projects, use the MPL - see http://www.mozilla.org/MPL/MPL-1.1.html 18 | 19 | # Modifications and Credits 20 | 21 | You do not have to pay a fee to use the library. In any case all changes made to this source code should be published, also in case of MPL. 22 | 23 | However, please do not forget to provide a link (https://playcom.de) somewhere in your credit window or documentation if you use any of the units published under this three-license. 24 | 25 | 26 | # Disclaimer 27 | 28 | Most units, functions and procedures has been tested extensively in productive use over many years, but unfortunately I am not in a position to make any guarantees. You use it at your own risk. 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Pictures/Demo01_Minimal_Console_App.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Pictures/Demo01_Minimal_Console_App.jpg -------------------------------------------------------------------------------- /Pictures/Demo02_Fontface_Fontsize.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Pictures/Demo02_Fontface_Fontsize.jpg -------------------------------------------------------------------------------- /Pictures/Demo03_Move_Window.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Pictures/Demo03_Move_Window.jpg -------------------------------------------------------------------------------- /Pictures/Demo04_Input_Keyboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Pictures/Demo04_Input_Keyboard.jpg -------------------------------------------------------------------------------- /Pictures/Demo05_Console_Mode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Pictures/Demo05_Console_Mode.jpg -------------------------------------------------------------------------------- /Pictures/Demo06_Colors.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Pictures/Demo06_Colors.jpg -------------------------------------------------------------------------------- /Pictures/Demo07_ScreenSave.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Pictures/Demo07_ScreenSave.jpg -------------------------------------------------------------------------------- /Pictures/Demo08_ASCII_Characters.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Pictures/Demo08_ASCII_Characters.jpg -------------------------------------------------------------------------------- /Pictures/Demo09_BuiltIn_Features.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Pictures/Demo09_BuiltIn_Features.jpg -------------------------------------------------------------------------------- /Ply.Console.Debug.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Ply.Console.Debug.pas -------------------------------------------------------------------------------- /Ply.DateTime.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Ply.DateTime.pas -------------------------------------------------------------------------------- /Ply.Defines.inc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Ply.Defines.inc -------------------------------------------------------------------------------- /Ply.Files.pas: -------------------------------------------------------------------------------- 1 | (****************************************************************************** 2 | 3 | Name : Ply.Files.pas 4 | Copyright : © 1999 - 2023 Playcom Software Vertriebs GmbH 5 | Last modified : 10.10.2023 6 | License : disjunctive three-license (MPL|GPL|LGPL) see License.md 7 | Description : This file is part of the Open Source "Playcom Console Library" 8 | 9 | ******************************************************************************) 10 | 11 | unit Ply.Files; 12 | 13 | interface 14 | 15 | {$I Ply.Defines.inc} 16 | 17 | Uses 18 | Ply.Types, 19 | System.SysUtils; 20 | 21 | resourcestring 22 | // #3 - ERROR_PATH_NOT_FOUND 23 | SPathNotFound = 'Path not found'; 24 | // #19 - ERROR_WRITE_PROTECT 25 | SFileWriteProtected = 'File is write protected'; 26 | // #32 - ERROR_SHARING_VIOLATION 27 | SSharingViolation = 'Sharing violation'; 28 | // #38 - ERROR_HANDLE_EOF 29 | SEndOfFile = 'Reached end of file'; 30 | // #90 - ERROR_INVALID_RECSIZE 31 | SInvalidRecsize = 'Invalid recordsize'; 32 | // #100 - IOERROR_DISK_READ 33 | SFileReadError = 'File read error'; 34 | // #101 - IOERROR_DISK_WRITE 35 | SFileWriteError = 'File write error'; 36 | // #102 - IOERROR_FILE_NOT_ASSIGNED 37 | SFileNotAssigned = 'File not assigned'; 38 | // #103 - IOERROR_FILE_NOT_OPEN 39 | SFileNotOpen = 'File not open'; 40 | // #104 - IOERROR_FILE_NOT_OPEN_FOR_INPUT 41 | SFileNotOpenForInput = 'File not open for input'; 42 | // #105 - IOERROR_FILE_NOT_OPEN_FOR_OUTPUT 43 | SFileNotOpenForOutput = 'File not open for output'; 44 | // #106 - IOERROR_INVALID_NUMERIC_FORMAT 45 | SInvalidNumericFormat = 'Invalid numeric format'; 46 | 47 | Const 48 | ERROR_INVALID_RECSIZE = 90; 49 | IOERROR_DISK_READ = 100; 50 | IOERROR_DISK_WRITE = 101; 51 | IOERROR_FILE_NOT_ASSIGNED = 102; 52 | IOERROR_FILE_NOT_OPEN = 103; 53 | IOERROR_FILE_NOT_OPEN_FOR_INPUT = 104; 54 | IOERROR_FILE_NOT_OPEN_FOR_OUTPUT = 105; 55 | IOERROR_INVALID_NUMERIC_FORMAT = 106; 56 | 57 | fsOriginFromBeginning = 0; 58 | fsOriginFromCurrent = 1; 59 | fsOriginFromEnd = 2; 60 | 61 | (* $1000000 = 16.777.216 Byte | Read/Write max 16 MByte *) 62 | _BlockRead_MaxByte : Int64 = $1000000; 63 | _BlockWrite_MaxByte : Int64 = $1000000; 64 | 65 | Type tPlyFile = object 66 | f : File; 67 | Private 68 | FErrorCode : Integer; 69 | FErrorMessage : String; 70 | Protected 71 | Procedure Success; 72 | Procedure CreateError(eErrorCode:Integer; eErrorMsg:String; 73 | eFuncName:String; ePath:String=''); 74 | Procedure HandleException(eException: TObject; Const eFuncName:String; 75 | ePath:String=''); 76 | Procedure DebugCheckRecSize(aRecSize:tFileRecSize); 77 | Private 78 | Procedure DebugShowError(Title,aFileName,Msg1:String; Msg2:String=''); 79 | Function GetDebugMode : Boolean; 80 | Procedure SetDebugMode(Const Value:Boolean); 81 | Function GetFileName : String; 82 | // Reset: Open exsisting file, fails if file not exists 83 | Function Reset(Const aFileName:String; aRecSize:tFileRecSize; 84 | aFileModeOpen:TFileModeOpen=fmRW_Share) : Boolean; 85 | // Rewrite: Create or Delete & Create if file exists 86 | Function Rewrite(Const aFileName:String; aRecSize:tFileRecSize; 87 | aFileModeOpen:TFileModeOpen=fmRW_Share) : Boolean; 88 | Public 89 | Property FileName: String Read GetFileName; 90 | Property ErrorCode: Integer Read FErrorCode Write FErrorCode; 91 | Property ErrorMessage: String Read FErrorMessage Write FErrorMessage; 92 | Property GlobalDebugMode: Boolean Read GetDebugMode Write SetDebugMode; 93 | Procedure Init; 94 | // Create: Delete & Create new file 95 | Function Create(aFileName:String; aRecSize:tFileRecSize; 96 | aFileModeOpen:tFileModeOpen=fmRW_Share) : Boolean; 97 | // OpenRead: Open existing file for Read 98 | Function OpenRead(aFilename:String; aRecSize:tFileRecSize; 99 | aFileModeOpen:TFileModeOpen=fmR_Share) : Boolean; 100 | // OpenWrite: Open existing file or Create file 101 | Function OpenWrite(aFilename:String; aRecSize:tFileRecSize; 102 | aFileModeOpen:TFileModeOpen=fmW_Share) : Boolean; 103 | // Open: open existing file or create file for read & write 104 | Function Open(aFileName:String; aRecSize:tFileRecSize; 105 | aFileModeOpen:tFileModeOpen=fmRW_Share) : Boolean; 106 | Function Handle : tHandle; 107 | Function FileModeStatus : TFileModeStatus; 108 | Function FileModeStatusText : String; 109 | Function RecSize : Int64; 110 | Function IsOpen : Boolean; 111 | Function Eof : Boolean; 112 | Function Filepos : Longint; 113 | Function Filesize : Longint; 114 | Function Seek(FPos:Longint) : Boolean; 115 | Procedure Seek_Eof; 116 | Function DosRead(Var Daten) : Boolean; 117 | Function DosWrite(Var Daten) : Boolean; 118 | Function BlockRead(Var Daten; RecCount:tFileRecCount; 119 | Out ReadRec:tFileRecCount) : Boolean; 120 | Function BlockWrite(Var Daten; RecCount:tFileRecCount; 121 | Out WrittenRec:tFileRecCount) : Boolean; 122 | Function Seek_Read(FPos:Longint; Var Daten) : Boolean; 123 | Function Seek_Write(FPos:Longint; Var Daten) : Boolean; 124 | Procedure Truncate; 125 | Function Erase : Boolean; 126 | Function Rename(NewFileName:String) : Boolean; 127 | Function DeleteRecord(FPosRecord:Longint) : Boolean; 128 | Function Close : Boolean; 129 | Function Close_Delete : Boolean; 130 | Function Close_Rename(NewFileName:String) : Boolean; 131 | end; 132 | 133 | Type tPlyTextfile = Object 134 | Private 135 | tf : Text; 136 | FErrorCode : Integer; 137 | FErrorMessage : String; 138 | Procedure Success; 139 | Procedure CreateError(eErrorCode:Integer; eErrorMsg:String; 140 | eFuncName:String; ePath:String=''); 141 | Procedure HandleException(eException: TObject; Const eFuncName:String; 142 | ePath:String=''); 143 | Procedure DebugShowError(Title,aFileName,Msg1:String; Msg2:String=''); 144 | Function GetFilename : String; 145 | Public 146 | Property Filename: String Read GetFilename; 147 | Property ErrorCode: Integer Read FErrorCode; 148 | Property ErrorMessage: String Read FErrorMessage; 149 | Procedure Init; 150 | Function Handle : tHandle; 151 | Function FileModeStatus : TFileModeStatus; 152 | Function FileModeStatusText : String; 153 | Function IsOpen : Boolean; 154 | Function OpenReadFilemode(aFileName:String; 155 | aFileModeOpen:TFileModeOpen) : Boolean; 156 | Function OpenRead(aFileName:String) : Boolean; 157 | Function OpenReadExclusive(aFileName:String) : Boolean; 158 | Function OpenWriteFilemode(aFileName:String; 159 | aFileModeOpen: TFileModeOpen; 160 | UTF8_Bom: Boolean=False) : Boolean; 161 | Function OpenWrite(aFileName:String; 162 | UTF8_BOM: Boolean=False) : Boolean; 163 | Function OpenWriteExclusive(aFileName:String; 164 | UTF8_BOM: Boolean=False) : Boolean; 165 | // Create = Delete and Open_Write 166 | Function Create(aFileName:String; Codepage:Word=_Codepage_850) : Boolean; 167 | Function Eof : Boolean; 168 | Function Readln(Var Help:String) : Boolean; 169 | Function Write(Help:String) : Boolean; 170 | Function Writeln(Help:String) : Boolean; 171 | Function Erase : Boolean; 172 | Function Rename(NewName:String) : Boolean; 173 | Function Close : Boolean; 174 | Function Close_Delete : Boolean; 175 | end; 176 | 177 | implementation 178 | 179 | Uses 180 | {$IFDEF CONSOLE} 181 | Ply.Console.Extended, 182 | {$ELSE} 183 | VCL.Dialogs, 184 | {$ENDIF} 185 | Ply.Math, 186 | Ply.StrUtils, 187 | Ply.SysUtils, 188 | System.SysConst, 189 | System.Math, 190 | System.StrUtils, 191 | Winapi.Windows; 192 | 193 | Var FileDebugMode : Boolean = False; 194 | 195 | (********************) 196 | (***** tPlyFile *****) 197 | (********************) 198 | Procedure tPlyFile.Success; 199 | begin 200 | FErrorCode := 0; 201 | FErrorMessage := ''; 202 | end; 203 | 204 | Procedure tPlyFile.CreateError(eErrorCode:Integer; eErrorMsg:String; 205 | eFuncName:String; ePath:String=''); 206 | begin 207 | if (ePath='') then ePath := FileName; 208 | FErrorCode := eErrorCode; 209 | FErrorMessage := FErrorCode.ToString + '│' 210 | + eErrorMsg + '│' 211 | + eFuncName + '│' 212 | + '[' + ePath + ']'; 213 | DebugShowError(eFuncName,ePath,FErrorMessage); 214 | end; 215 | 216 | Procedure tPlyFile.HandleException(eException: TObject; Const eFuncName:String; 217 | ePath:String=''); 218 | begin 219 | if (ePath='') then ePath := FileName; 220 | if (Exception(eException).ClassNameIs('EInOutError')) then 221 | begin 222 | FErrorCode := EInOutError(eException).ErrorCode; 223 | FErrorMessage := EInOutError(eException).ErrorCode.ToString + '│'; 224 | case FErrorCode of 225 | ERROR_PATH_NOT_FOUND : FErrorMessage := FErrorMessage + SPathNotFound + '│'; 226 | ERROR_SHARING_VIOLATION : FErrorMessage := FErrorMessage + SSharingViolation + '│'; 227 | else 228 | FErrorMessage := FErrorMessage + EInOutError(eException).Message + '│'; 229 | end; 230 | FErrorMessage := FErrorMessage + eFuncName; 231 | {$IFDEF DELPHI10UP} 232 | if (EInOutError(eException).Path<>'') 233 | then FErrorMessage := FErrorMessage + '│' + EInOutError(eException).Path else 234 | {$ENDIF DELPHI10UP} 235 | if (ePath<>'') 236 | then FErrorMessage := FErrorMessage + '│' + ePath; 237 | end else 238 | begin 239 | FErrorCode := 0; 240 | FErrorMessage := Exception(eException).Message + '│' 241 | + eFuncName; 242 | if (ePath<>'') 243 | then FErrorMessage := FErrorMessage + '│' + ePath; 244 | end; 245 | DebugShowError(eFuncName,ePath,FErrorMessage); 246 | end; 247 | 248 | Procedure tPlyFile.DebugCheckRecSize(aRecSize:tFileRecSize); 249 | Var lFileSizeByte : Int64; 250 | begin 251 | (* When Debug-Mode is activated *) 252 | if (FileDebugMode) then 253 | begin 254 | (* Check whether the size of the file fit to aRecSize *) 255 | if (aRecSize>1) then 256 | begin 257 | lFileSizeByte := PlyFileSizeByte(FileName); 258 | if (lFileSizeByte>0) then 259 | begin 260 | if ((lFileSizeByte mod aRecSize)<>0) then 261 | begin 262 | CreateError(ERROR_INVALID_RECSIZE 263 | ,SInvalidRecsize+': FileSizeByte='+IntToStr(lFileSizeByte) 264 | +', RecSize='+IntToStr(aRecSize) 265 | ,'tPlyFile.DebugCheckRecSize'); 266 | end; 267 | end; 268 | end; 269 | end; 270 | end; 271 | 272 | Procedure tPlyFile.DebugShowError(Title,aFileName,Msg1:String; Msg2:String=''); 273 | begin 274 | if (FileDebugMode) then 275 | begin 276 | {$IFDEF CONSOLE} 277 | ConsoleShowError('Error['+IntToStr(ErrorCode)+']: '+Title 278 | ,'FileName: '+aFileName,Msg1,Msg2); 279 | {$ELSE} 280 | ShowMessage(Title+sLineBreak 281 | +'Error('+IntToStr(ErrorCode)+')'+sLineBreak 282 | +'FileName: '+FileName+sLineBreak 283 | +Msg1+sLineBreak 284 | +Msg2+sLineBreak); 285 | {$ENDIF} 286 | end; 287 | end; 288 | 289 | Function tPlyFile.GetDebugMode : Boolean; 290 | begin 291 | Result := FileDebugMode; 292 | end; 293 | 294 | Procedure tPlyFile.SetDebugMode(Const Value:Boolean); 295 | begin 296 | FileDebugMode := Value; 297 | end; 298 | 299 | Function tPlyFile.GetFileName: string; 300 | begin 301 | Result := tFilerec(f).Name; 302 | end; 303 | 304 | Function tPlyFile.Reset(Const aFileName:String; aRecSize:tFileRecSize; 305 | aFileModeOpen:TFileModeOpen=fmRW_Share) : Boolean; 306 | begin 307 | Result := False; 308 | try 309 | System.AssignFile(f, aFileName); 310 | System.FileMode := aFileModeOpen; 311 | System.Reset(f,aRecSize); 312 | Success; 313 | Result := True; 314 | except 315 | On E : Exception do 316 | HandleException(e,'tPlyFile.Reset',aFilename); 317 | end; 318 | end; 319 | 320 | Function tPlyFile.Rewrite(Const aFileName:String; aRecSize:tFileRecSize; 321 | aFileModeOpen:TFileModeOpen=fmRW_Share) : Boolean; 322 | begin 323 | Result := False; 324 | try 325 | System.AssignFile(f, aFileName); 326 | System.FileMode := aFileModeOpen; 327 | System.Rewrite(f,aRecSize); 328 | Success; 329 | Result := True; 330 | except 331 | On E : Exception do 332 | HandleException(e,'tPlyFile.Rewrite',aFilename); 333 | end; 334 | end; 335 | 336 | Procedure tPlyFile.Init; 337 | begin 338 | FillChar(tFilerec(f),sizeof(tFilerec),#0); 339 | FErrorCode := 0; 340 | FErrorMessage := ''; 341 | end; 342 | 343 | Function tPlyFile.Create(aFileName:String; aRecSize:tFileRecSize; 344 | aFileModeOpen:tFileModeOpen=fmRW_Share) : Boolean; 345 | begin 346 | Init; 347 | Result := False; 348 | if (PlyFileDelete(aFileName)) then 349 | begin 350 | if (Rewrite(aFileName,aRecSize,aFileModeOpen)) then 351 | begin 352 | Result := True; 353 | end; 354 | end; 355 | end; 356 | 357 | Function tPlyFile.OpenRead(aFilename:String; aRecSize:tFileRecSize; 358 | aFileModeOpen:TFileModeOpen=fmR_Share) : Boolean; 359 | Var sRec : tSearchrec; 360 | begin 361 | Init; 362 | Result := False; 363 | if (PlyFileExists(aFilename,sRec)) then 364 | begin 365 | // if file is write-protected 366 | if ((sRec.Attr and faReadOnly)<>0) then 367 | begin 368 | // downgrade filemode to read only 369 | aFileModeOpen := aFileModeOpen and not(FM_W) and not(FM_RW); 370 | end; 371 | if (Reset(aFilename,aRecSize,aFileModeOpen)) then 372 | begin 373 | Result := True; 374 | DebugCheckRecSize(aRecSize); 375 | end; 376 | end else 377 | begin 378 | CreateError(ERROR_FILE_NOT_FOUND,SFileNotFound 379 | ,'tPlyFile.OpenRead',aFilename); 380 | end; 381 | end; 382 | 383 | Function tPlyFile.OpenWrite(aFilename:String; aRecSize:tFileRecSize; 384 | aFileModeOpen:TFileModeOpen=fmW_Share) : Boolean; 385 | Var sRec : tSearchrec; 386 | begin 387 | Init; 388 | Result := False; 389 | if (PlyFileExists(aFilename,sRec)) then 390 | begin 391 | // if file is write-protected 392 | if ((sRec.Attr and faReadOnly)<>0) then 393 | begin 394 | CreateError(ERROR_WRITE_PROTECT,SFileWriteProtected 395 | ,'tPlyFile.OpenWrite',aFilename); 396 | end else 397 | if (Reset(aFilename,aRecSize,aFileModeOpen)) then 398 | begin 399 | Result := True; 400 | DebugCheckRecSize(aRecSize); 401 | end; 402 | end else 403 | begin 404 | if (Rewrite(aFilename,aRecSize,aFileModeOpen)) then 405 | begin 406 | Result := True; 407 | end; 408 | end; 409 | end; 410 | 411 | Function tPlyFile.Open(aFileName:String; aRecSize:tFileRecSize; 412 | aFileModeOpen:TFileModeOpen=fmRW_Share) : Boolean; 413 | begin 414 | Init; 415 | Result := False; 416 | if (aFileName<>'') then 417 | begin 418 | if (PlyFileExists(aFilename)) then 419 | begin 420 | if (Reset(aFileName,aRecSize,aFileModeOpen)) then 421 | begin 422 | Result := True; 423 | DebugCheckRecSize(aRecSize); 424 | end; 425 | end else 426 | // if File does not exist then create file 427 | begin 428 | Result := Rewrite(aFileName,aRecSize,aFileModeOpen); 429 | end; 430 | (* Error(3) = Path not found *) 431 | if (ErrorCode=ERROR_PATH_NOT_FOUND) then 432 | begin 433 | DebugShowError('FileOpen (Path not found)' 434 | ,aFilename,ErrorMessage); 435 | end else 436 | (* Error(4) : Too many files open *) 437 | if (ErrorCode=ERROR_TOO_MANY_OPEN_FILES) then 438 | begin 439 | DebugShowError(STooManyOpenFiles+'FileOpen (Too many files open)' 440 | ,aFilename,ErrorMessage); 441 | end else 442 | if (ErrorCode<>0) then 443 | begin 444 | DebugShowError('FileOpen ',aFileName,ErrorMessage); 445 | end; 446 | end else 447 | begin 448 | Result := False; 449 | CreateError(ERROR_FILE_NOT_FOUND,SFileNotFound 450 | ,'tPlyFile.Open','no filename'); 451 | end; 452 | (* Set back to Default-FileMode *) 453 | System.Filemode := fmRW_Share; 454 | end; 455 | 456 | Function tPlyFile.Handle : tHandle; 457 | begin 458 | Result := tFilerec(f).Handle; 459 | end; 460 | 461 | Function tPlyFile.FileModeStatus : TFileModeStatus; 462 | begin 463 | Result := tFilerec(f).Mode; 464 | end; 465 | 466 | Function tPlyFile.FileModeStatusText : String; 467 | begin 468 | case FileModeStatus of 469 | fmclosed : Result := 'Closed'; 470 | fmInput : Result := 'Input '; 471 | fmOutput : Result := 'Output'; 472 | fmInOut : Result := 'InOut '; 473 | else 474 | Result := IntToString(FileModeStatus,6); 475 | end; 476 | end; 477 | 478 | Function tPlyFile.RecSize : Int64; 479 | begin 480 | Result := tFilerec(f).RecSize; 481 | end; 482 | 483 | Function tPlyFile.IsOpen : Boolean; 484 | Var CurFileModeStatus : Word; 485 | begin 486 | CurFileModeStatus := FileModeStatus; 487 | Result := (CurFileModeStatus>=fmInput) and (CurFileModeStatus<=fmInOut); 488 | end; 489 | 490 | Function tPlyFile.Eof : Boolean; 491 | begin 492 | if (IsOpen) then 493 | begin 494 | Result := False; 495 | Try 496 | Result := System.Eof(f); 497 | Success; 498 | Except 499 | On E : Exception do 500 | HandleException(e,'tPlyFile.Eof'); 501 | End; 502 | end else 503 | begin 504 | CreateError(IOERROR_FILE_NOT_OPEN,SFileNotOpen 505 | ,'tPlyFile.Eof'); 506 | Result := True; 507 | end; 508 | end; 509 | 510 | Function tPlyFile.Filepos : Longint; 511 | begin 512 | Result := -1; 513 | Try 514 | Result := System.Filepos(f); 515 | Except 516 | On E : Exception do 517 | HandleException(e,'tPlyFile.Filepos'); 518 | End; 519 | end; 520 | 521 | Function tPlyFile.Filesize : Longint; 522 | begin 523 | Result := -1; 524 | Try 525 | Result := System.Filesize(f); 526 | Except 527 | On E : Exception do 528 | HandleException(e,'tPlyFile.Filesize'); 529 | End; 530 | end; 531 | 532 | Function tPlyFile.Seek(FPos:Longint) : Boolean; 533 | begin 534 | Result := False; 535 | FPos := ValueMinMax(FPos,0,Filesize); 536 | Try 537 | System.Seek(f,FPos); 538 | Result := True; 539 | Except 540 | On E : Exception do 541 | HandleException(e,'tPlyFile.Seek'); 542 | End; 543 | end; 544 | 545 | Procedure tPlyFile.Seek_Eof; 546 | begin 547 | Try 548 | System.Seek(f,Filesize); 549 | Except 550 | On E : Exception do 551 | HandleException(e,'tPlyFile.Seek_Eof'); 552 | End; 553 | end; 554 | 555 | Function tPlyFile.DosRead(Var Daten) : Boolean; 556 | Var NumRead : integer; 557 | begin 558 | Result := False; 559 | if not(Eof) then 560 | begin 561 | Try 562 | System.BlockRead(f,Daten,1,NumRead); (* 1 = Read 1 record *) 563 | Success; 564 | Result := True; 565 | Except 566 | On E : Exception do 567 | HandleException(e,'tPlyFile.Seek'); 568 | End; 569 | end; 570 | end; 571 | 572 | Function tPlyFile.DosWrite(Var Daten) : Boolean; 573 | Var NumWritten : tFileRecCount; 574 | begin 575 | Result := False; 576 | Try 577 | System.BlockWrite(f,Daten,1,NumWritten); 578 | Success; 579 | Result := True; 580 | Except 581 | On E : Exception do 582 | HandleException(e,'tPlyFile.Seek'); 583 | End; 584 | end; 585 | 586 | Function tPlyFile.BlockRead(Var Daten; RecCount:tFileRecCount; 587 | Out ReadRec:tFileRecCount) : Boolean; 588 | Var CountByte : Int64; 589 | Steps : Int64; 590 | RecCountStep : Int64; 591 | ReadRec_Total : tFileRecCount; 592 | Count_Steps : Longint; 593 | DatenPtr : PAnsiChar; 594 | begin 595 | Result := False; 596 | ReadRec := 0; 597 | if not(Eof) then 598 | begin 599 | CountByte := RecCount * RecSize; 600 | // if less then 16 MByte to read 601 | if (CountByte<=_BlockRead_MaxByte) then 602 | begin 603 | Try 604 | System.BlockRead(f,Daten,RecCount,ReadRec); 605 | if (ReadRec>0) then 606 | begin 607 | Success; 608 | Result := True; 609 | end; 610 | Except 611 | On E : Exception do 612 | HandleException(e,'tPlyFile.BlockRead'); 613 | End; 614 | end else 615 | // if more then 16 MByte to read 616 | begin 617 | FillChar(Daten,CountByte,#0); 618 | DatenPtr := @Daten; 619 | // Calculate steps of 16 MByte to read 620 | Steps := (CountByte Div _BlockRead_MaxByte) + 1; 621 | // Calculate number of records per step 622 | RecCountStep := (RecCount Div Steps) + 1; 623 | ReadRec_Total := 0; 624 | Count_Steps := 0; 625 | Repeat 626 | inc(Count_Steps); 627 | RecCountStep := Min(RecCountStep,RecCount-ReadRec_Total); 628 | Try 629 | System.BlockRead(f,DatenPtr[ReadRec_Total*RecSize],RecCountStep,ReadRec); 630 | ReadRec_Total := ReadRec_Total + ReadRec; 631 | Except 632 | On E : Exception do 633 | HandleException(e,'tPlyFile.BlockRead.Steps'); 634 | End; 635 | until (Count_Steps>=Steps) or (ReadRec_Total>=RecCount) or (ErrorCode<>0); 636 | // Return how many records are read in total 637 | ReadRec := ReadRec_Total; 638 | if (ReadRec>0) and (ErrorCode=0) then 639 | begin 640 | Success; 641 | Result := True; 642 | end; 643 | end; 644 | end else 645 | begin 646 | // 38 : End of File 647 | // CreateError(ERROR_HANDLE_EOF,SEndOfFile,'tPlyFile.BlockRead'); 648 | end; 649 | end; 650 | 651 | Function tPlyFile.BlockWrite(Var Daten; RecCount:tFileRecCount; 652 | Out WrittenRec:tFileRecCount) : Boolean; 653 | Var CountByte : Int64; 654 | Steps : Int64; 655 | AnzRec_Step : Int64; 656 | WriteRec_Total : tFileRecCount; 657 | Count_Steps : Longint; 658 | DatenPtr : PAnsiChar; 659 | begin 660 | Result := False; 661 | WrittenRec := 0; 662 | CountByte := RecCount * RecSize; 663 | (* if less then 16 MByte to write *) 664 | if (CountByte<=_BlockWrite_MaxByte) then 665 | begin 666 | Try 667 | System.BlockWrite(f,Daten,RecCount,WrittenRec); 668 | if (RecCount=WrittenRec) then 669 | begin 670 | Success; 671 | Result := True; 672 | end; 673 | Except 674 | On E : Exception do 675 | HandleException(e,'tPlyFile.BlockWrite'); 676 | End; 677 | end else 678 | (* if more then 16 MByte to write *) 679 | begin 680 | DatenPtr := @Daten; 681 | (* Calculate steps of 16 MByte to write data *) 682 | Steps := (CountByte Div _BlockWrite_MaxByte) + 1; 683 | (* Calculate number of records per step to write *) 684 | AnzRec_Step := (RecCount Div Steps) + 1; 685 | WriteRec_Total := 0; 686 | Count_Steps := 0; 687 | Repeat 688 | inc(Count_Steps); 689 | AnzRec_Step := Min(AnzRec_Step,RecCount-WriteRec_Total); 690 | Try 691 | System.BlockWrite(f,DatenPtr[WriteRec_Total*RecSize],AnzRec_Step,WrittenRec); 692 | WriteRec_Total := WriteRec_Total + WrittenRec; 693 | Except 694 | On E : Exception do 695 | HandleException(e,'tPlyFile.BlockWrite.Steps'); 696 | End; 697 | until (Count_Steps>=Steps) or (WriteRec_Total>=RecCount) or (ErrorCode<>0); 698 | (* Set Out-Parameter *) 699 | WrittenRec := WriteRec_Total; 700 | if (WrittenRec=RecCount) then 701 | begin 702 | Success; 703 | Result := True; 704 | end; 705 | end; 706 | end; 707 | 708 | Function tPlyFile.Seek_Read(FPos:Longint; Var Daten) : Boolean; 709 | begin 710 | if (FPos>=0) and (FPos<=Filesize) then 711 | begin 712 | Seek(FPos); 713 | Result := DosRead(Daten); 714 | end else 715 | begin 716 | CreateError(IOERROR_DISK_READ,SFileReadError,'tPlyFile.Seek_Read'); 717 | Result := False; 718 | end; 719 | end; 720 | 721 | Function tPlyFile.Seek_Write(FPos:Longint; Var Daten) : Boolean; 722 | begin 723 | if (FPos>=0) and (FPos<=Filesize) then 724 | begin 725 | Seek(FPos); 726 | Result := DosWrite(Daten); 727 | end else 728 | begin 729 | CreateError(IOERROR_DISK_WRITE,SFileWriteError,'tPlyFile.Seek_Write'); 730 | Result := False; 731 | end; 732 | end; 733 | 734 | Procedure tPlyFile.Truncate; 735 | begin 736 | Try 737 | System.Truncate(f); 738 | Except 739 | On E : Exception do 740 | HandleException(e,'tPlyFile.Truncate'); 741 | End; 742 | end; 743 | 744 | Function tPlyFile.Erase : Boolean; 745 | begin 746 | Result := False; 747 | Try 748 | System.Erase(f); 749 | Success; 750 | Result := True; 751 | Except 752 | // ErrorCode=5: File is still opened by another task/user 753 | On E : Exception do 754 | HandleException(e,'tPlyFile.Erase'); 755 | End; 756 | end; 757 | 758 | Function tPlyFile.Rename(NewFileName:String) : Boolean; 759 | begin 760 | Result := False; 761 | Try 762 | System.Rename(f,NewFileName); 763 | Success; 764 | Result := True; 765 | Except 766 | On E : Exception do 767 | HandleException(e,'tPlyFile.Rename'); 768 | End; 769 | end; 770 | 771 | Function tPlyFile.DeleteRecord(FPosRecord:Longint) : Boolean; 772 | Var RecordData : pByte; 773 | FPos : Longint; 774 | Error : Boolean; 775 | begin 776 | Result := False; 777 | if (IsOpen) then 778 | begin 779 | if (FPosRecord'') and 841 | (NewFileName<>OldFileName) then 842 | begin 843 | Result := Rename(NewFileName); 844 | end; 845 | end; 846 | end; 847 | 848 | (************************) 849 | (***** tPlyTextfile *****) 850 | (************************) 851 | Procedure tPlyTextfile.Success; 852 | begin 853 | FErrorCode := 0; 854 | FErrorMessage := ''; 855 | end; 856 | 857 | Procedure tPlyTextfile.CreateError(eErrorCode:Integer; eErrorMsg:String; 858 | eFuncName:String; ePath:String=''); 859 | begin 860 | if (ePath='') then ePath := FileName; 861 | FErrorCode := eErrorCode; 862 | FErrorMessage := FErrorCode.ToString + '│' 863 | + eErrorMsg + '│' 864 | + eFuncName + '│' 865 | + '[' + ePath + ']'; 866 | DebugShowError(eFuncName,ePath,FErrorMessage); 867 | end; 868 | 869 | Procedure tPlyTextfile.HandleException(eException: TObject; Const eFuncName:String; 870 | ePath:String=''); 871 | begin 872 | if (ePath='') then ePath := FileName; 873 | if (Exception(eException).ClassNameIs('EInOutError')) then 874 | begin 875 | FErrorCode := EInOutError(eException).ErrorCode; 876 | FErrorMessage := EInOutError(eException).ErrorCode.ToString + '│'; 877 | case FErrorCode of 878 | ERROR_PATH_NOT_FOUND : FErrorMessage := FErrorMessage + SPathNotFound + '│'; 879 | ERROR_SHARING_VIOLATION : FErrorMessage := FErrorMessage + SSharingViolation + '│'; 880 | else 881 | FErrorMessage := FErrorMessage + EInOutError(eException).Message + '│'; 882 | end; 883 | FErrorMessage := FErrorMessage + eFuncName; 884 | {$IFDEF DELPHI10UP} 885 | if (EInOutError(eException).Path<>'') 886 | then FErrorMessage := FErrorMessage + '│' + EInOutError(eException).Path else 887 | {$ENDIF DELPHI10UP} 888 | if (ePath<>'') 889 | then FErrorMessage := FErrorMessage + '│' + ePath; 890 | end else 891 | begin 892 | FErrorCode := 0; 893 | FErrorMessage := Exception(eException).Message + '│' 894 | + eFuncName; 895 | if (ePath<>'') 896 | then FErrorMessage := FErrorMessage + '│' + ePath; 897 | end; 898 | DebugShowError(eFuncName,ePath,FErrorMessage); 899 | end; 900 | 901 | Procedure tPlyTextfile.DebugShowError(Title,aFileName,Msg1:String; Msg2:String=''); 902 | begin 903 | if (FileDebugMode) then 904 | begin 905 | {$IFDEF CONSOLE} 906 | ConsoleShowError('Error['+IntToStr(ErrorCode)+']: '+Title 907 | ,'FileName: '+aFileName,Msg1,Msg2); 908 | {$ELSE} 909 | ShowMessage(Title+sLineBreak 910 | +'Error('+IntToStr(ErrorCode)+')'+sLineBreak 911 | +'FileName: '+FileName+sLineBreak 912 | +Msg1+sLineBreak 913 | +Msg2+sLineBreak); 914 | {$ENDIF} 915 | end; 916 | end; 917 | 918 | Function tPlyTextfile.GetFilename : String; 919 | begin 920 | Result := StrPas(tTextRec(tf).Name); 921 | end; 922 | 923 | Procedure tPlyTextfile.Init; 924 | begin 925 | FillChar(tTextrec(tf),sizeof(tTextrec),#0); 926 | FErrorCode := 0; 927 | FErrorMessage := ''; 928 | end; 929 | 930 | Function tPlyTextfile.Handle : tHandle; 931 | begin 932 | Result := tTextRec(tf).Handle; 933 | end; 934 | 935 | Function tPlyTextfile.FileModeStatus : TFileModeStatus; 936 | begin 937 | Result := tTextRec(tf).Mode; 938 | end; 939 | 940 | Function tPlyTextfile.FileModeStatusText : String; 941 | begin 942 | case FileModeStatus of 943 | fmclosed : Result := 'Closed'; 944 | fmInput : Result := 'Input '; 945 | fmOutput : Result := 'Output'; 946 | fmInOut : Result := 'InOut '; 947 | else 948 | Result := IntToString(FileModeStatus,6); 949 | end; 950 | end; 951 | 952 | Function tPlyTextfile.IsOpen : Boolean; 953 | Var CurFileModeStatus : Word; 954 | begin 955 | CurFileModeStatus := FileModeStatus; 956 | Result := (CurFileModeStatus>=fmInput) and (CurFileModeStatus<=fmInOut); 957 | end; 958 | 959 | Function tPlyTextfile.OpenReadFilemode(aFileName:String; 960 | aFileModeOpen:TFileModeOpen) : Boolean; 961 | begin 962 | Result := False; 963 | if (aFileName<>'') then 964 | begin 965 | Try 966 | System.AssignFile(tf,aFileName); 967 | System.Filemode := aFileModeOpen; 968 | System.Reset(tf); 969 | Success; 970 | Result := True; 971 | Except 972 | On E : Exception do 973 | HandleException(e,'tPlyTextfile.OpenReadFilemode'); 974 | End; 975 | end else 976 | begin 977 | CreateError(ERROR_FILE_NOT_FOUND,SFileNotFound 978 | ,'tPlyTextfile.OpenReadFilemode','no filename'); 979 | end; 980 | System.FileMode := fmRW_Share; 981 | end; 982 | 983 | Function tPlyTextfile.OpenRead(aFileName:String) : Boolean; 984 | begin 985 | Result := OpenReadFilemode(aFileName,fmR_Share); 986 | end; 987 | 988 | Function tPlyTextfile.OpenReadExclusive(aFileName: string): Boolean; 989 | begin 990 | Result := OpenReadFilemode(aFileName,fmR_DenyRW); 991 | end; 992 | 993 | Function tPlyTextfile.OpenWriteFilemode(aFileName:String; 994 | aFileModeOpen: TFileModeOpen; 995 | UTF8_Bom: Boolean=False) : Boolean; 996 | begin 997 | Result := False; 998 | if (aFileName<>'') then 999 | begin 1000 | Try 1001 | System.AssignFile(tf,aFileName); 1002 | System.Filemode := aFileModeOpen; 1003 | if (FileExists(aFileName)) then 1004 | begin 1005 | System.Append(tf); 1006 | end else 1007 | begin 1008 | System.Rewrite(tf); 1009 | // If the file is to be created in UFT8, then write Byte Order Mark (BOM) to the file 1010 | if (UTF8_Bom) then 1011 | begin 1012 | System.Write(tf,#$ef + #$bb + #$bf); 1013 | end; 1014 | end; 1015 | Success; 1016 | Result := True; 1017 | Except 1018 | On E : Exception do 1019 | HandleException(e,'tPlyTextfile.OpenWriteFilemode'); 1020 | End; 1021 | end else 1022 | begin 1023 | CreateError(ERROR_FILE_NOT_FOUND,SFileNotFound 1024 | ,'tPlyTextfile.OpenWriteFilemode','no filename'); 1025 | end; 1026 | end; 1027 | 1028 | Function tPlyTextfile.OpenWrite(aFileName:String; 1029 | UTF8_BOM:Boolean=False) : Boolean; 1030 | begin 1031 | Result := OpenWriteFilemode(aFileName,fmW_Share,UTF8_BOM); 1032 | end; 1033 | 1034 | Function tPlyTextfile.OpenWriteExclusive(aFileName: string; 1035 | UTF8_BOM: Boolean = False): Boolean; 1036 | begin 1037 | Result := OpenWriteFilemode(aFileName,fmW_DenyRW); 1038 | end; 1039 | 1040 | Function tPlyTextfile.Create(aFileName:String; Codepage:Word=_Codepage_850) : Boolean; 1041 | begin 1042 | if (aFileName<>'') then 1043 | begin 1044 | if (FileExists(aFileName)) then 1045 | begin 1046 | if (System.SysUtils.DeleteFile(aFileName)) then 1047 | begin 1048 | Result := OpenWrite(aFileName,Codepage=_Codepage_UTF8); 1049 | end else Result := False; 1050 | end else 1051 | begin 1052 | Result := OpenWrite(aFileName,Codepage=_Codepage_UTF8); 1053 | end; 1054 | end else Result := False; 1055 | end; 1056 | 1057 | Function tPlyTextfile.Eof : Boolean; 1058 | begin 1059 | if (IsOpen) then 1060 | begin 1061 | Result := False; 1062 | Try 1063 | Result := System.Eof(tf); 1064 | Success; 1065 | Except 1066 | On E : Exception do 1067 | HandleException(e,'tPlyTextfile.Eof'); 1068 | end; 1069 | end else 1070 | begin 1071 | CreateError(IOERROR_FILE_NOT_OPEN,SFileNotOpen 1072 | ,'tPlyTextFile.Eof'); 1073 | Result := True; 1074 | end; 1075 | end; 1076 | 1077 | Function tPlyTextfile.Readln(Var Help:String) : Boolean; 1078 | begin 1079 | Result := False; 1080 | if not(Eof) then 1081 | begin 1082 | Try 1083 | System.Readln(tf,Help); 1084 | Success; 1085 | Result := True; 1086 | Except 1087 | On E : Exception do 1088 | HandleException(e,'tPlyTextfile.Readln'); 1089 | End; 1090 | end; 1091 | end; 1092 | 1093 | Function tPlyTextfile.Write(Help:String) : Boolean; 1094 | begin 1095 | Result := False; 1096 | Try 1097 | System.Write(tf,Help); 1098 | Success; 1099 | Result := True; 1100 | Except 1101 | On E : Exception do 1102 | HandleException(e,'tPlyTextfile.Write'); 1103 | End; 1104 | end; 1105 | 1106 | Function tPlyTextfile.Writeln(Help:String) : Boolean; 1107 | begin 1108 | Result := False; 1109 | Try 1110 | System.Writeln(tf,Help); 1111 | Success; 1112 | Result := True; 1113 | Except 1114 | On E : Exception do 1115 | HandleException(e,'tPlyTextfile.Writeln'); 1116 | End; 1117 | end; 1118 | 1119 | Function tPlyTextfile.Erase : Boolean; 1120 | begin 1121 | Result := False; 1122 | Try 1123 | System.Erase(tf); 1124 | Success; 1125 | Result := True; 1126 | Except 1127 | // ErrorCode=5: File is still opened by another task/user 1128 | On E : Exception do 1129 | HandleException(e,'tPlyTextfile.Erase'); 1130 | End; 1131 | end; 1132 | 1133 | Function tPlyTextfile.Rename(NewName:String) : Boolean; 1134 | begin 1135 | Result := False; 1136 | Try 1137 | System.Rename(tf,NewName); 1138 | Success; 1139 | Result := True; 1140 | Except 1141 | On E : Exception do 1142 | HandleException(e,'tPlyTextFile.Rename'); 1143 | End; 1144 | end; 1145 | 1146 | Function tPlyTextfile.Close : Boolean; 1147 | begin 1148 | if (IsOpen) then 1149 | begin 1150 | Result := False; 1151 | Try 1152 | System.CloseFile(tf); 1153 | Success; 1154 | Result := True; 1155 | Except 1156 | On E : Exception do 1157 | HandleException(e,'tPlyTextFile.Close'); 1158 | End; 1159 | end else Result := True; 1160 | end; 1161 | 1162 | Function tPlyTextfile.Close_Delete : Boolean; 1163 | begin 1164 | if (Close) then 1165 | begin 1166 | Result := Erase; 1167 | end else Result := False; 1168 | end; 1169 | 1170 | end. 1171 | 1172 | -------------------------------------------------------------------------------- /Ply.Math.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playcom-de/Console/d08d687dbb3a3c003c8b5bd0a020e077d122a759/Ply.Math.pas -------------------------------------------------------------------------------- /Ply.Patches.pas: -------------------------------------------------------------------------------- 1 | (****************************************************************************** 2 | 3 | Name : Ply.Patches.pas 4 | Copyright : © 1999 - 2023 Playcom Software Vertriebs GmbH 5 | Last modified : 10.10.2023 6 | License : disjunctive three-license (MPL|GPL|LGPL) see License.md 7 | Description : This file is part of the Open Source "Playcom Console Library" 8 | 9 | ******************************************************************************) 10 | 11 | unit Ply.Patches; 12 | 13 | interface 14 | 15 | {$I Ply.Defines.inc} 16 | 17 | implementation 18 | 19 | uses 20 | Crt, 21 | System.SysUtils, 22 | Winapi.Windows; 23 | 24 | // From which version the error is present I can not say, but until at least 25 | // version 11.3 is the following error in the System.pas. 26 | // Example: 27 | // aInt64 : Int64 = 1234; 28 | // Write(aInt64:10); 29 | // Results in the output "1234" not " 1234" as expected. 30 | // In the functions _WriteLong, _WriteInt64 and _WriteUInt64 not width 31 | // but 0 is specified when converting the integer value, which leads to 32 | // the fact that in the function _WriteUString to the procedure 33 | // AlternateWriteUnicodeStringProc the string is passed without the 34 | // leading spaces. The error only occurs if AlternateWriteUnicodeStringProc 35 | // is assigned, which is mandatory in the case of the "Playcom Console Library". 36 | // 37 | // To fix the error I redirect the function System._WriteUString here to my own 38 | // function WriteUStringFixed to make sure that the correct string with leading 39 | // spaces is passed. 40 | // 41 | // To disable this patch, for whatever reason, it is sufficient to comment 42 | // out "ApplyPatch" in the initialization section at the end of this file. 43 | 44 | function GetWriteUStringAddress: Pointer; 45 | asm 46 | {$ifdef CPUX64} 47 | mov rax,offset System.@WriteUString 48 | {$else} 49 | mov eax,offset System.@WriteUString 50 | {$endif} 51 | end; 52 | 53 | // Fixed Function _WriteUString from System.pas 54 | Function WriteUStringFixed(var t: TTextRec; const s: UnicodeString; width: Integer) : Pointer; 55 | Var uString : UnicodeString; 56 | begin 57 | if assigned(AlternateWriteUnicodeStringProc) then 58 | begin 59 | uString := s; 60 | while length(uString) Null 97 | // #1 Start of Heading 98 | // #2 Start of Text 99 | // #3 End of Text 100 | // #4 End of Transmission 101 | // #5 Enquiry 102 | // #6 Acknowledge 103 | // #7 Bell 104 | // #8 Backspace 105 | // #9 Horizontal Tab 106 | // #10 Line Feed 107 | // #11 Vertical Tab 108 | // #12 Form Feed 109 | // #13 Carriage Return 110 | ControlCharacter : Set of AnsiChar = [#0..#13]; 111 | WrapCharacter : Set of AnsiChar = [#32, '|', '/', '\', '-', '(', ')', '[', ']']; 112 | 113 | // WideChar - Unicode-Char - ASCII-Signs 114 | Const _0_low = $2080; (* #8320 ₀ *) 115 | _1_low = $2081; (* #8321 ₁ *) 116 | _2_low = $2082; (* #8322 ₂ *) 117 | _3_low = $2083; (* #8323 ₃ *) 118 | _4_low = $2084; (* #8324 ₄ *) 119 | _5_low = $2085; (* #8325 ₅ *) 120 | _6_low = $2086; (* #8326 ₆ *) 121 | _7_low = $2087; (* #8327 ₇ *) 122 | _8_low = $2088; (* #8328 ₈ *) 123 | _9_low = $2089; (* #8329 ₉ *) 124 | _0_high = $2070; (* #8304 ⁰ *) 125 | _1_high = $00B9; (* #185 ¹ *) 126 | _2_high = $00B2; (* #178 ² *) 127 | _3_high = $00B3; (* #179 ³ *) 128 | _4_high = $2074; (* #8308 ⁴ *) 129 | _5_high = $2075; (* #8309 ⁵ *) 130 | _6_high = $2076; (* #8310 ⁶ *) 131 | _7_high = $2077; (* #8311 ⁷ *) 132 | _8_high = $2078; (* #8312 ⁸ *) 133 | _9_high = $2079; (* #8313 ⁹ *) 134 | _i_high = $2071; (* #8305 ⁱ *) 135 | _n_high = $207F; (* #8319 ⁿ *) 136 | _TripplePoint = $2026; (* #8230 … *) 137 | _Promill = $2030; (* #8240 ‰ *) 138 | _Pound_Sign = $20A4; (* #8356 £ Britisch Pound *) 139 | _Euro_Sign = $20AC; (* #8364 € Euro Sign *) 140 | _Arrow_Left = $2190; (* #8592 ← *) 141 | _Arrow_Up = $2191; (* #8592 ↑ *) 142 | _Arrow_Right = $2192; (* #8592 → *) 143 | _Arrow_Down = $2193; (* #8592 ↓ *) 144 | _NBSP = $00A0; (* #160 Non-breaking space *) 145 | 146 | _Frame_single_hori = $2500; (* #9472 ─ *) 147 | _Frame_single_vert = $2502; (* #9474 │ *) 148 | _Frame_single_corner_tl = $250C; (* #9484 ┌ *) 149 | _Frane_single_conrer_tr = $2510; (* #9488 ┐ *) 150 | _Frame_single_corner_bl = $2514; (* #9492 └ *) 151 | _Frame_single_corner_br = $2518; (* #9496 ┘ *) 152 | _Frame_single_vert_right = $251C; (* #9500 ├ *) 153 | _Frame_single_vert_left = $2524; (* #9508 ┤ *) 154 | _Frame_single_hori_down = $252C; (* #9516 ┬ *) 155 | _Frame_single_hori_up = $2534; (* #9524 ┴ *) 156 | _Frame_single_cross = $253C; (* #9532 ┼ *) 157 | 158 | _Frame_double_hori = $2550; (* #9552 ═ *) 159 | _Frame_double_vert = $2551; (* #9553 ║ *) 160 | _Frame_double_corner_tl = $2554; (* #9556 ╔ *) 161 | _Frame_double_corner_tr = $2557; (* #9559 ╗ *) 162 | _Frame_double_corner_bl = $255A; (* #9562 ╚ *) 163 | _Frame_double_corner_br = $255D; (* #9565 ╝ *) 164 | _Frame_double_vert_right = $2560; (* #9568 ╠ *) 165 | _Frame_double_vert_left = $2563; (* #9571 ╣ *) 166 | _Frame_double_hori_down = $2566; (* #9574 ╦ *) 167 | _Frame_double_hori_up = $2569; (* #9577 ╩ *) 168 | _Frame_double_cross = $256C; (* #9580 ╬ *) 169 | 170 | _Full_Block = $2588; (* #9608 █ *) 171 | 172 | _Black_Telefon = $260E; (* #9742 ☎ *) 173 | _Female_Sign = $2640; (* #9792 ♀ *) 174 | _Male_Sign = $2642; (* #9794 ♂ *) 175 | 176 | _Dingbat_Negative_1 = $2776; (* #10102 ❶ *) 177 | _Dingbat_Negative_2 = $2777; (* #10102 ❷ *) 178 | _Dingbat_Negative_3 = $2778; (* #10102 ❸ *) 179 | _Dingbat_Negative_4 = $2779; (* #10102 ❹ *) 180 | _Dingbat_Negative_5 = $277A; (* #10102 ❺ *) 181 | _Dingbat_Negative_6 = $277B; (* #10102 ❻ *) 182 | _Dingbat_Negative_7 = $277C; (* #10102 ❼ *) 183 | _Dingbat_Negative_8 = $277D; (* #10102 ❽ *) 184 | _Dingbat_Negative_9 = $277E; (* #10102 ❾ *) 185 | _Dingbat_Negative_10 = $277F; (* #10102 ❿ *) 186 | 187 | _Fullwidth_A = $FF21; (* #65313 A *) 188 | _Fullwidth_B = $FF22; (* #65314 B *) 189 | _Fullwidth_C = $FF23; (* #65315 C *) 190 | _Fullwidth_D = $FF24; (* #65316 D *) 191 | _Fullwidth_E = $FF25; (* #65317 E *) 192 | _Fullwidth_F = $FF26; (* #65318 F *) 193 | 194 | Type 195 | // inpCursorPos1 = Place the cursor on the first letter 196 | // inpExitOnKey = Exit Function "Input" after every key 197 | // inpClrIfKey = Clear InputString on first keypressed 198 | // inpInsertMode = Insert characters on cursorpos 199 | // inpPassword = Input is Password -> Do not show text 200 | // inpDate = (+|-) inc/dec date 201 | // inpTime = t.b.c. 202 | tInputOption = (inpCursorPos1, inpExitOnKey, inpClrIfKey, inpInsertMode, 203 | inpPassword, inpDate, inpTime); 204 | tInputOptions = Set of tInputOption; 205 | 206 | AStr3 = String[3]; 207 | AStr4 = String[4]; 208 | AChar3 = Array [0..2] of AnsiChar; 209 | AChar4 = Array [0..3] of AnsiChar; 210 | WStr20 = Array [0..19] of WideChar; 211 | WStr30 = Array [0..29] of WideChar; 212 | TDynStr = TArray; 213 | TDynWord = TArray; 214 | TDynLongword = Array of Longword; 215 | 216 | UTF8String = Type AnsiString(_Codepage_UTF8); 217 | CP437String = Type AnsiString(_Codepage_437); 218 | CP850String = Type AnsiString(_Codepage_850); 219 | CP1252String = Type AnsiString(_Codepage_1252); 220 | 221 | TSortValue = Int64; 222 | TPlyBoolean = Boolean; 223 | // TCodepage : ConsoleCodepage (Input / Output) 224 | TCodepage = Longword; 225 | // TKeyboardLayout 226 | TKeyboardLayout = Longword; 227 | // TConHandle : Standard-Con-Handles 228 | TConHandle = Winapi.Windows.THandle; 229 | // TFileSize 230 | TFileSize = Int64; 231 | // TFileMode 232 | TFileModeOpen = Byte; 233 | TFileModeStatus = Word; 234 | // TFileRecSize 235 | TFileRecSize = Integer; 236 | // TFileRecCount 237 | TFileRecCount = Integer; 238 | // TFileAttribute 239 | TPlyFileAttribute = Integer; 240 | // TConsoleScreenPoint : Coord of Smallint (16-Bit) (Char: Size(X,Y) or Point(X,Y)) 241 | TConsoleWindowPoint = TSmallPoint; 242 | // TConsoleScreenRect : Rect of Smallint (16-Bit) (Char: columns & lines) 243 | TConsoleWindowRect = TSmallRect; 244 | // TConsoleDesktopPoint : Coord of Integer (32-Bit) (Pixel: Pos(X,Y)) 245 | TConsoleDesktopPoint = TPoint; 246 | // TConsoleDesktopRect : Rect of Integer (32-Bit) (Pixel on Desktop) 247 | TConsoleDesktopRect = TRect; 248 | // TConsoleScreenBuffer 249 | TConsoleScreenBuffer = Array of TCharInfo; 250 | // TFilesort 251 | TFilesort = (NameUp, NameDown, ExtensionUp, ExtensionDown, 252 | SizeUp, SizeDown, DateTimeUp, DateTimeDown); 253 | 254 | Function GetCharset(aCodepage:tCodepage) : String; 255 | Procedure FillWord(Var Dest; Count:Integer; Value:Word); 256 | Procedure FillLongword(Var Dest; Count:Integer; Value:Longword); 257 | 258 | Type 259 | TFileSizeHelper = Record Helper for TFileSize 260 | public 261 | Function ToStringSize(Width:Integer=0) : String; 262 | Function ToStringReadable(ShowByte:Boolean=True) : String; 263 | End; 264 | 265 | TPlyBooleanHelper = record helper for TPlyBoolean 266 | public 267 | Function ZeroOne: Byte; 268 | Function ZeroOneChar : WideChar; 269 | Function YesNo: String; 270 | Function JaNein: String; 271 | end; 272 | 273 | TCoordHelper = record helper for TCoord 274 | public 275 | Procedure Clr; 276 | Function ToString: String; // "X x Y" e.g. "80 x 25" 277 | constructor Create(Const X,Y: Smallint); overload; 278 | constructor Create(Const Value:TCoord); overload; 279 | procedure Normalize(MinX:Smallint=1; MinY:Smallint=1); 280 | {$IFDEF DELPHI10UP} 281 | class operator Equal(Lhs, Rhs: TCoord) : Boolean; 282 | class operator notEqual(Lhs, Rhs: TCoord) : Boolean; 283 | {$ENDIF DELPHI10UP} 284 | end; 285 | 286 | TSmallPointHelper = record helper for TSmallPoint 287 | public 288 | procedure Clear; 289 | Function IsClear : Boolean; 290 | Function ToStringSize: String; // "X x Y" e.g. "80 x 25" 291 | Function ToStringPos: String; // "X | Y" e.g. "10 | 5" 292 | Procedure Normalize(Const MinX:Smallint=1; MinY:Smallint=1); Overload; 293 | Procedure Normalize(Const MinSize:TSmallPoint); Overload; 294 | end; 295 | 296 | TSmallRectHelper = record helper for TSmallRect 297 | private 298 | Function GetWidth : Smallint; 299 | Procedure SetWidth(Const Value: Smallint); 300 | Function GetHeight : Smallint; 301 | Procedure SetHeight(Const Value: Smallint); 302 | Function GetSize : TSmallPoint; 303 | Function GetTopLeft : TSmallPoint; 304 | Procedure SetTopLeft(Value: TSmallPoint); 305 | Function GetBottomRight : TSmallPoint; 306 | Procedure SetBottomRight(Value: TSmallPoint); 307 | public 308 | Function ToStringRect: String; 309 | Function ToStringPos: String; // Top | Left 310 | Function ToStringSize: String; // Width x Height 311 | constructor Create(const Left, Top, Right, Bottom: SmallInt); overload; 312 | constructor Create(Const Width,Height: Smallint); overload; // rect with Top=0 and Left=0 313 | constructor Create(Const Size:TSmallPoint); overload; // rect with Top=0 and Left=0 314 | constructor Create(Const Rect:TSmallRect; Normalize: Boolean = False); overload; // copy rect 315 | constructor Create(const Origin: TCoord; Width, Height: Smallint); overload; // at TPoint of origin with width and height 316 | constructor Create(const P1, P2: TCoord; Normalize: Boolean = False); overload; // with corners specified by p1 and p2 317 | {$IFDEF DELPHI10UP} 318 | class operator Equal(Lhs, Rhs: TSmallRect) : Boolean; 319 | class operator NotEqual(Lhs, Rhs: TSmallRect) : Boolean; 320 | {$ENDIF DELPHI10UP} 321 | procedure NormalizeRect; 322 | Property Width : Smallint Read GetWidth Write SetWidth; 323 | Property Height : Smallint Read GetHeight Write SetHeight; 324 | Property Size : TSmallPoint Read GetSize; 325 | Property TopLeft : TSmallPoint Read GetTopLeft Write SetTopLeft; 326 | Property BottomRight : TSmallPoint Read GetBottomRight Write SetBottomRight; 327 | end; 328 | 329 | {$IFDEF DELPHIXE8DOWN} 330 | Function TSmallRectEqual(Lhs, Rhs: TSmallRect) : Boolean; 331 | {$ENDIF DELPHIXE8DOWN} 332 | 333 | Type 334 | TPointHelper = record helper for TPoint 335 | public 336 | Procedure Clear; 337 | procedure MaximizeToZero; 338 | procedure Init(ValueX,ValueY: Longint); 339 | function ToStringSize: String; 340 | end; 341 | 342 | TRectHelper = record helper for TRect 343 | private 344 | public 345 | Procedure Clear; 346 | // Moves the window if it extends beyond the limits of the screen 347 | // Returns true if the window was moved 348 | Function FitScreen(Const WorkArea:TRect) : Boolean; 349 | // TextPositionSize (Left|Top|Width|Height in Pixel) 350 | // e.g. " 10 | 10, Size : 800 x 400" 351 | Function ToStringPosSize : String; 352 | // ToStringRect (Left|Top|Right|Bottom in Pixel) 353 | // e.g. " 100 | 100 x 900 | 500" 354 | function ToStringRect: String; 355 | // ToStringPos: e.g. " 800 | 400" 356 | function ToStringPos: String; 357 | // ToStringSize (Width|Height in Pixel): e.g. " 800 x 400" 358 | function ToStringSize: String; 359 | end; 360 | 361 | // Coordinates from current Window on Screen within the Consol-Window 362 | // Zero-Base-Values : (0,0,79,24) for Standardsize 363 | TPlyConWinSize = record 364 | private 365 | Function GetWidth : Smallint; 366 | Procedure SetWidth(Const Value:SmallInt); 367 | Function GetHeight : Smallint; 368 | Procedure SetHeight(Const Value:SmallInt); 369 | Function GetWindMin : Word; 370 | Procedure SetWindMin(Const Value:Word); 371 | Function GetWindMax : Word; 372 | Procedure SetWindMax(Const Value:Word); 373 | public 374 | Procedure Clear; 375 | Function ToStringRect : String; 376 | Function ToStringSize : String; 377 | Property Width : Smallint Read GetWidth Write SetWidth; 378 | Property Height : Smallint Read GetHeight Write SetHeight; 379 | Property WindMin : Word Read GetWindMin Write SetWindMin; 380 | Property WindMax : Word Read GetWindMax Write SetWindMax; 381 | case Integer of 382 | 0: (Left, Top, Right, Bottom: Smallint); 383 | 1: (MinX, MinY, MaxX, MaxY : Smallint); 384 | 2: (TopLeft, BottomRight: TConsoleWindowPoint); 385 | 3: (SmallRect:TConsoleWindowRect); 386 | end; 387 | 388 | TBooleanList = TList; 389 | TIntegerList = TList; 390 | 391 | TData64 = Record 392 | Private 393 | Procedure Clear; 394 | Function GetBinary : String; 395 | Function GetBinaryBytes : String; 396 | Function GetHex : String; 397 | Procedure PlusEpsilon; 398 | Procedure MinusEpsilon; 399 | Public 400 | class operator Implicit(Value: Word): TData64; 401 | class operator Implicit(Value: TData64): Word; 402 | class operator Implicit(Value: Longword): TData64; 403 | class operator Implicit(Value: TData64): Longword; 404 | class operator Implicit(Value: Integer): TData64; 405 | class operator Implicit(Value: TData64): Integer; 406 | Property ToBin : String Read GetBinary; 407 | Property ToBinBytes : String Read GetBinaryBytes; 408 | Property ToHex : String Read GetHex; 409 | Function DoubleDigits(Digits: Integer) : Integer; 410 | Procedure DoubleRound; 411 | case Integer of 412 | 0: (AsInt64: Int64); 413 | 1: (AsUInt64: UInt64); 414 | 2: (AsDouble: Double); 415 | 3: (AsComp: Comp); 416 | 4: (AsCurrency: Currency); 417 | 5: (LoLong, HiLong: Longword); 418 | 6: (Words : Array [0..3] of Word); 419 | 7: (Bytes : Array [0..7] of Byte); 420 | end; 421 | 422 | {$IFDEF DELPHI10UP} 423 | Type TBooleanListHelper = Class Helper for TBooleanList 424 | public 425 | Function ToString : String; 426 | end; 427 | {$ENDIF} 428 | 429 | Type TIntegerListHelper = Class Helper for TIntegerList 430 | public 431 | Procedure AddIfnotExists(Const Value:Integer); 432 | {$IFDEF DELPHI10UP} 433 | Function ToString : String; 434 | {$ENDIF DELPHI10UP} 435 | end; 436 | 437 | Const BitValue08 : Array [0..7] of Byte = (1,2,4,8,16,32,64,128); 438 | Const BitValue32 : Array [0..31] of Cardinal = 439 | ( $1, $2, $4, $8, 440 | $10, $20, $40, $80, 441 | $100, $200, $400, $800, 442 | $1000, $2000, $4000, $8000, 443 | $10000, $20000, $40000, $80000, 444 | $100000, $200000, $400000, $800000, 445 | $1000000, $2000000, $4000000, $8000000, 446 | $10000000,$20000000,$40000000,$80000000); 447 | 448 | Type TBoolean32 = Record 449 | private 450 | Procedure SetBool32(Index:Byte; Value:Boolean); 451 | Function GetBool32(Index:Byte) : Boolean; 452 | public 453 | Procedure Clear; 454 | property Bools[Index: Byte]: Boolean Read GetBool32 Write SetBool32; default; 455 | case Cardinal of 456 | 0: (FValue: Cardinal); 457 | 1: (FByte: Array [0..3] of Byte); 458 | end; 459 | 460 | Const PlyBoolSize : Cardinal = 32; 461 | 462 | Type TPlyBoolList = Class(TObject) 463 | Private 464 | FItems : Array of TBoolean32; //UInt32 465 | FCount : Int64; 466 | Procedure SetItem(Index:Int64; Value:Boolean); 467 | Function GetItem(Index:Int64) : Boolean; 468 | Procedure SetCount(Index:Int64); 469 | Function GetCountTrue : Int64; 470 | Public 471 | property Items[Index: Int64]: Boolean read GetItem write SetItem; default; 472 | property Count: Int64 read FCount write SetCount; 473 | property CountTrue: Int64 read GetCountTrue; 474 | constructor Create; overload; 475 | constructor Create(const CountBools:Cardinal; DefaultValue:Boolean=False); overload; 476 | destructor Destroy; override; 477 | Procedure Add(Const Value:Boolean); overload; 478 | Procedure Add(CountBools:Cardinal; Const Value:Boolean); overload; 479 | Function MemorySizeByte : Cardinal; 480 | Function ToStringNumberTrue : String; 481 | Function ToStringNumberFalse : String; 482 | Function ToStringBooleans : String; 483 | End; 484 | 485 | type TAppender = class 486 | class procedure Append(var Arr: TArray; Value: T); 487 | end; 488 | 489 | Var PlyCompanyName : String = 'Playcom'; 490 | PlyAppName : String = ''; 491 | 492 | implementation 493 | 494 | Uses 495 | Ply.Math, 496 | Ply.StrUtils, 497 | System.Math, 498 | System.SysUtils; 499 | 500 | Function GetCharset(aCodepage:tCodepage) : String; 501 | begin 502 | Case aCodepage of 503 | _Codepage_437 : Result := 'IBM437'; 504 | _Codepage_850 : Result := 'IBM850'; 505 | _Codepage_1252 : Result := 'ANSI'; 506 | _Codepage_UTF16_LE : Result := 'UTF-16'; 507 | _Codepage_UTF16_BE : Result := 'UTF-16BE'; 508 | _Codepage_ISO8859_1 : Result := 'ISO-8859-1'; 509 | _Codepage_ISO8859_2 : Result := 'ISO-8859-2'; 510 | _Codepage_ISO8859_3 : Result := 'ISO-8859-3'; 511 | _Codepage_ISO8859_4 : Result := 'ISO-8859-4'; 512 | _Codepage_ISO8859_5 : Result := 'ISO-8859-5'; 513 | _Codepage_ISO8859_6 : Result := 'ISO-8859-6'; 514 | _Codepage_ISO8859_7 : Result := 'ISO-8859-7'; 515 | _Codepage_ISO8859_8 : Result := 'ISO-8859-8'; 516 | _Codepage_ISO8859_9 : Result := 'ISO-8859-9'; 517 | _Codepage_ISO8859_15 : Result := 'ISO-8859-15'; 518 | _Codepage_UTF8 : Result := 'UTF-8'; 519 | else 520 | Result := 'ASCII'; 521 | end; 522 | end; 523 | 524 | Procedure FillWord(Var Dest; Count:Integer; Value:Word); 525 | Var DynWord : TDynWord; 526 | i : Integer; 527 | begin 528 | SetLength(DynWord,Count); 529 | for I := 0 to Count-1 do 530 | begin 531 | DynWord[i] := Value; 532 | end; 533 | Move(DynWord[0],Dest,2*Count); 534 | end; 535 | 536 | Procedure FillLongword(Var Dest; Count:Integer; Value:Longword); 537 | Var DynLongword : TDynLongword; 538 | i : Integer; 539 | begin 540 | SetLength(DynLongword,count); 541 | for i := 0 to Count-1 do 542 | begin 543 | DynLongword[i] := Value; 544 | end; 545 | Move(DynLongword[0],Dest,4*Count); 546 | end; 547 | 548 | (***************************) 549 | (***** TFileSizeHelper *****) 550 | (***************************) 551 | Function TFileSizeHelper.ToStringSize(Width:Integer=0) : String; 552 | var 553 | FSize: Int64; 554 | aString: String; 555 | UnitSize: String; 556 | begin 557 | FSize := Self; 558 | UnitSize := ''; 559 | aString := IntToString(FSize)+UnitSize; 560 | Repeat 561 | if (Length(aString)<=Width) then 562 | begin 563 | Break; 564 | end else 565 | begin 566 | FSize := Round(FSize / 1024); 567 | if (UnitSize='' ) then UnitSize := ' KB' else 568 | if (UnitSize=' KB') then UnitSize := ' MB' else 569 | if (UnitSize=' MB') then UnitSize := ' GB' 570 | else UnitSize := ' TB'; 571 | aString := IntToString(FSize)+UnitSize; 572 | end; 573 | until (UnitSize=' TB'); 574 | Result := StringAlignRight(width,aString); 575 | end; 576 | 577 | Function TFileSizeHelper.ToStringReadable(ShowByte:Boolean=True) : String; 578 | var 579 | FSize: Int64; 580 | UnitSize : Integer; 581 | 582 | Const UnitSizeText : Array [1..5] of String = ('Byte','KByte','MByte','GByte','TByte'); 583 | 584 | begin 585 | FSize := Self; 586 | UnitSize := 1; 587 | while (FSize>100000) and (UnitSize<5) do 588 | begin 589 | FSize := Round(FSize / 1024); 590 | inc(UnitSize); 591 | end; 592 | if not(ShowByte) and (UnitSize=1) 593 | then Result := '' 594 | else Result := IntToString(FSize,0,'.')+' '+UnitSizeText[UnitSize]; 595 | end; 596 | 597 | (**************************) 598 | (***** TBooleanHelper *****) 599 | (**************************) 600 | function TPlyBooleanHelper.JaNein: String; 601 | begin 602 | if (Self=True) then Result := 'Ja' else Result := 'Nein'; 603 | end; 604 | 605 | function TPlyBooleanHelper.YesNo: String; 606 | begin 607 | if (Self=True) then Result := 'Yes' else Result := 'No'; 608 | end; 609 | 610 | function TPlyBooleanHelper.ZeroOne: Byte; 611 | begin 612 | if (Self=True) then Result := 1 else Result := 0; 613 | end; 614 | 615 | Function TPlyBooleanHelper.ZeroOneChar : WideChar; 616 | begin 617 | if (Self=True) then Result := '1' else Result := '0'; 618 | end; 619 | 620 | (************************) 621 | (***** TCoordHelper *****) 622 | (************************) 623 | Procedure TCoordHelper.Clr; 624 | begin 625 | X := 0; 626 | Y := 0; 627 | end; 628 | 629 | Function TCoordHelper.ToString: String; // "X x Y" | "80 x 25" 630 | begin 631 | Result := X.ToString + ' x ' + Y.ToString; 632 | end; 633 | 634 | constructor TCoordHelper.Create(Const X,Y: Smallint); 635 | begin 636 | Self.X := X; 637 | Self.Y := Y; 638 | end; 639 | 640 | constructor TCoordHelper.Create(Const Value:TCoord); 641 | begin 642 | Self := Value; 643 | end; 644 | 645 | procedure TCoordHelper.Normalize(MinX:Smallint=1; MinY:Smallint=1); 646 | begin 647 | X := Max(X,MinX); 648 | Y := Max(Y,MinY); 649 | end; 650 | 651 | {$IFDEF DELPHI10UP} 652 | class operator TCoordHelper.equal(Lhs, Rhs: TCoord) : Boolean; 653 | begin 654 | Result := (Lhs.X = Rhs.X) and (Lhs.Y = Rhs.Y); 655 | end; 656 | 657 | class operator TCoordHelper.notEqual(Lhs, Rhs: TCoord) : Boolean; 658 | begin 659 | Result := Not(Lhs = Rhs); 660 | end; 661 | {$ENDIF DELPHI10UP} 662 | 663 | (*****************************) 664 | (***** TSmallPointHelper *****) 665 | (*****************************) 666 | procedure TSmallPointHelper.Clear; 667 | begin 668 | X := 0; 669 | Y := 0; 670 | end; 671 | 672 | Function TSmallPointHelper.IsClear : Boolean; 673 | begin 674 | if (X=0) or (Y=0) then Result := True 675 | else Result := False; 676 | end; 677 | 678 | // "X x Y" e.g. "80 x 25" 679 | Function TSmallPointHelper.ToStringSize: String; 680 | begin 681 | Result := Format('%4d',[x]) +' x ' 682 | + Format('%4d',[y]); 683 | end; 684 | 685 | // "x|y" e.g. "10|5" 686 | Function TSmallPointHelper.ToStringPos: String; 687 | begin 688 | Result := Format('%1d',[x]) +' | ' 689 | + Format('%1d',[y]); 690 | end; 691 | 692 | procedure TSmallPointHelper.Normalize(Const MinX:Smallint=1; MinY:Smallint=1); 693 | begin 694 | X := Max(X,MinX); 695 | Y := Max(Y,MinY); 696 | end; 697 | 698 | Procedure TSmallPointHelper.Normalize(Const MinSize:TSmallPoint); 699 | begin 700 | Normalize(MinSize.x, MinSize.y); 701 | end; 702 | 703 | (****************************) 704 | (***** TSmallRectHelper *****) 705 | (****************************) 706 | Function TSmallRectHelper.GetWidth : Smallint; 707 | begin 708 | Result := Right - Left + 1; 709 | end; 710 | 711 | Procedure TSmallRectHelper.SetWidth(Const Value: Smallint); 712 | begin 713 | if (Value>=1) then Right := Left + Value; 714 | end; 715 | 716 | Function TSmallRectHelper.GetHeight : Smallint; 717 | begin 718 | Result := Bottom - Top + 1; 719 | end; 720 | 721 | Procedure TSmallRectHelper.SetHeight(const Value: SmallInt); 722 | begin 723 | if (Value>=1) then Bottom := Top + Value; 724 | end; 725 | 726 | Function TSmallRectHelper.GetSize : TSmallPoint; 727 | begin 728 | Result.X := Width; 729 | Result.y := Height; 730 | end; 731 | 732 | Function TSmallRectHelper.GetTopLeft : TSmallPoint; 733 | begin 734 | Result.X := Left; 735 | Result.Y := Top; 736 | end; 737 | 738 | Procedure TSmallRectHelper.SetTopLeft(Value: TSmallPoint); 739 | begin 740 | Left := Value.X; 741 | Top := Value.Y; 742 | end; 743 | 744 | Function TSmallRectHelper.GetBottomRight : TSmallPoint; 745 | begin 746 | Result.X := Right; 747 | Result.Y := Bottom; 748 | end; 749 | 750 | Procedure TSmallRectHelper.SetBottomRight(Value: TSmallPoint); 751 | begin 752 | Right := Value.X; 753 | Bottom := Value.Y; 754 | end; 755 | 756 | Function TSmallRectHelper.ToStringRect: String; 757 | begin 758 | Result := Format('%4d',[Left]) +' | ' 759 | + Format('%4d',[Top]) +' x ' 760 | + Format('%4d',[Right]) +' | ' 761 | + Format('%4d',[Bottom]); 762 | end; 763 | 764 | Function TSmallRectHelper.ToStringPos: String; 765 | begin 766 | Result := Format('%4d',[Top]) +' | ' 767 | + Format('%4d',[Left]); 768 | end; 769 | 770 | Function TSmallRectHelper.ToStringSize: String; 771 | begin 772 | Result := Format('%4d',[Width]) +' x ' 773 | + Format('%4d',[Height]); 774 | end; 775 | 776 | constructor TSmallRectHelper.Create(const Left, Top, Right, Bottom: SmallInt); 777 | begin 778 | Self.Left := Left; 779 | Self.Top := Top; 780 | Self.Right := Right; 781 | Self.Bottom:= Bottom; 782 | end; 783 | 784 | constructor TSmallRectHelper.Create(Const Width,Height: Smallint); 785 | begin 786 | Self.Left := 0; 787 | Self.Top := 0; 788 | Self.Right := Max(0,Width-1); 789 | Self.Bottom := Max(0,Height-1); 790 | end; 791 | 792 | constructor TSmallRectHelper.Create(Const Size:TSmallPoint); 793 | begin 794 | Create(Size.X, Size.Y); 795 | end; 796 | 797 | constructor TSmallRectHelper.Create(Const Rect:TSmallRect; Normalize: Boolean); 798 | begin 799 | Self := Rect; 800 | if Normalize then Self.NormalizeRect; 801 | end; 802 | 803 | constructor TSmallRectHelper.Create(const Origin: TCoord; Width, Height: SmallInt); 804 | begin 805 | Create(Origin.X, Origin.Y, Origin.X + Width, Origin.Y + Height); 806 | end; 807 | 808 | constructor TSmallRectHelper.Create(const P1, P2: TCoord; Normalize: Boolean); 809 | begin 810 | Self.Left := P1.X; 811 | Self.Top := P1.Y; 812 | Self.Right := P2.X; 813 | Self.Bottom := P2.Y; 814 | if Normalize then Self.NormalizeRect; 815 | end; 816 | 817 | {$IFDEF DELPHI10UP} 818 | class operator TSmallRectHelper.equal(Lhs, Rhs: TSmallRect) : Boolean; 819 | begin 820 | Result := (Lhs.Left = Rhs.Left) and (Lhs.Top = Rhs.Top) and 821 | (Lhs.Right = Rhs.Right) and (Lhs.Bottom = Rhs.Bottom); 822 | end; 823 | 824 | class operator TSmallRectHelper.notEqual(Lhs, Rhs: TSmallRect) : Boolean; 825 | begin 826 | Result := Not(Lhs = Rhs); 827 | end; 828 | {$ENDIF DELPHI10UP} 829 | 830 | procedure TSmallRectHelper.NormalizeRect; 831 | begin 832 | if Top > Bottom then 833 | begin 834 | Top := Top xor Bottom; 835 | Bottom := Top xor Bottom; 836 | Top := Top xor Bottom; 837 | end; 838 | if Left > Right then 839 | begin 840 | Left := Left xor Right; 841 | Right := Left xor Right; 842 | Left := Left xor Right; 843 | end 844 | end; 845 | 846 | {$IFDEF DELPHIXE8DOWN} 847 | Function TSmallRectEqual(Lhs, Rhs: TSmallRect) : Boolean; 848 | begin 849 | Result := (Lhs.Left = Rhs.Left) and (Lhs.Top = Rhs.Top) and 850 | (Lhs.Right = Rhs.Right) and (Lhs.Bottom = Rhs.Bottom); 851 | end; 852 | {$ENDIF DELPHIXE8DOWN} 853 | 854 | (************************) 855 | (***** TPointHelper *****) 856 | (************************) 857 | Procedure TPointHelper.Clear; 858 | begin 859 | X := 0; 860 | Y := 0; 861 | end; 862 | 863 | procedure TPointHelper.MaximizeToZero; 864 | begin 865 | X := Max(X,0); 866 | Y := Max(Y,0); 867 | end; 868 | 869 | procedure TPointHelper.Init(ValueX,ValueY: Longint); 870 | begin 871 | X := ValueX; 872 | Y := ValueY; 873 | end; 874 | 875 | Function TPointHelper.ToStringSize : String; 876 | begin 877 | Result := Format('%4d',[x]) +' x ' 878 | + Format('%4d',[y]); 879 | end; 880 | 881 | (***********************) 882 | (***** TRectHelper *****) 883 | (***********************) 884 | Procedure TRectHelper.Clear; 885 | begin 886 | FillChar(Self,sizeof(self),#0); 887 | end; 888 | 889 | Function TRectHelper.FitScreen(const WorkArea: TRect) : Boolean; 890 | Var NewRect : TConsoleDesktopRect; 891 | begin 892 | // NewLeft = Min.WorkArea.Left & (Max.WorkArea.Right-Width) 893 | NewRect.Left := ValueMinMax(Left // DefaultValue 894 | ,WorkArea.Left // MinValue 895 | ,(WorkArea.Right-Width)); // MaxValue 896 | // NewTop = Min.Workarea.Top & (Max.Workarea.Bottom - Height) 897 | NewRect.Top := ValueMinMax(Top // DefaultValue 898 | ,WorkArea.Top // MinValue 899 | ,(WorkArea.Bottom-Height)); // MaxValue 900 | // NewSize = OldSize (width & height) 901 | NewRect.Size := Size; 902 | if (Self <> NewRect) then 903 | begin 904 | Result := True; 905 | Self := NewRect; 906 | end else 907 | begin 908 | Result := False; 909 | end; 910 | end; 911 | 912 | // ToStringPosSize: e.g. " 10 | 10, Size : 800 x 400" 913 | function TRectHelper.ToStringPosSize: String; 914 | begin 915 | Result := Format('%4d',[Left]) +' | ' 916 | + Format('%4d',[Top]) +', Size : ' 917 | + Format('%4d',[Width]) +' x ' 918 | + Format('%4d',[Height]); 919 | end; 920 | 921 | // TextRec: e.g. " 100 | 100 x 900 | 500" 922 | function TRectHelper.ToStringRect: String; 923 | begin 924 | Result := Format('%4d',[Left]) +' | ' 925 | + Format('%4d',[Top]) +' x ' 926 | + Format('%4d',[Right]) +' | ' 927 | + Format('%4d',[Bottom]); 928 | end; 929 | 930 | // ToStringPos: e.g. " 800 | 400" 931 | function TRectHelper.ToStringPos: String; 932 | begin 933 | Result := Format('%4d',[Left]) +' | ' 934 | + Format('%4d',[Top]); 935 | end; 936 | 937 | // ToStringSize: e.g. " 800 x 400" 938 | function TRectHelper.ToStringSize: String; 939 | begin 940 | Result := Format('%4d',[Width]) +' x ' 941 | + Format('%4d',[Height]); 942 | end; 943 | 944 | (**************************) 945 | (***** TPlyConWinSize *****) 946 | (**************************) 947 | Function TPlyConWinSize.GetWidth : Smallint; 948 | begin 949 | Result := Right - Left + 1; 950 | end; 951 | 952 | Procedure TPlyConWinSize.SetWidth(Const Value:SmallInt); 953 | begin 954 | Left := Right + Value; 955 | end; 956 | 957 | Function TPlyConWinSize.GetHeight : Smallint; 958 | begin 959 | Result := Bottom - Top + 1; 960 | end; 961 | 962 | Procedure TPlyConWinSize.SetHeight(const Value: SmallInt); 963 | begin 964 | Bottom := Top + Value; 965 | end; 966 | 967 | Function TPlyConWinSize.GetWindMin : Word; 968 | begin 969 | Result := (Top shl 8) + Left; 970 | end; 971 | 972 | Procedure TPlyConWinSize.SetWindMin(Const Value:Word); 973 | begin 974 | Left := Lo(Value); 975 | Top := Hi(Value); 976 | end; 977 | 978 | Function TPlyConWinSize.GetWindMax : Word; 979 | begin 980 | Result := (Bottom Shl 8) + (Right); 981 | end; 982 | 983 | Procedure TPlyConWinSize.SetWindMax(Const Value:Word); 984 | begin 985 | Right := Lo(Value); 986 | Bottom := Hi(Value); 987 | end; 988 | 989 | Procedure TPlyConWinSize.Clear; 990 | begin 991 | FillChar(Self,sizeof(Self),#0); 992 | end; 993 | 994 | Function TPlyConWinSize.ToStringRect : String; 995 | begin 996 | Result := SmallRect.ToStringRect; 997 | end; 998 | 999 | Function TPlyConWinSize.ToStringSize : String; 1000 | begin 1001 | Result := SmallRect.ToStringSize; 1002 | end; 1003 | 1004 | (*******************) 1005 | (***** TData64 *****) 1006 | (*******************) 1007 | Procedure TData64.Clear; 1008 | begin 1009 | AsInt64 := 0; 1010 | end; 1011 | 1012 | Function TData64.GetBinary : String; 1013 | begin 1014 | Result := LongwordToBinaryString(HiLong) + LongwordToBinaryString(LoLong); 1015 | end; 1016 | 1017 | Function TData64.GetBinaryBytes : String; 1018 | Var i : Integer; 1019 | begin 1020 | Result := ByteToBinaryString(Bytes[7]); 1021 | for i := 6 downto 0 do 1022 | begin 1023 | Result := Result + '.' + ByteToBinaryString(Bytes[i]); 1024 | end; 1025 | end; 1026 | 1027 | Function TData64.GetHex : String; 1028 | begin 1029 | Result := IntToHex(AsUInt64,0); 1030 | end; 1031 | 1032 | Function TData64.DoubleDigits(Digits: Integer) : Integer; 1033 | begin 1034 | if IsNan(AsDouble) or IsInfinite(AsDouble) 1035 | then Result := $100 1036 | else Result := Trunc(Frac(AsDouble)*IntPower(10, Digits)); 1037 | end; 1038 | 1039 | Procedure TData64.DoubleRound; 1040 | begin 1041 | if (AsDouble>0) then PlusEpsilon else 1042 | if (AsDouble<0) then MinusEpsilon; 1043 | end; 1044 | 1045 | class operator TData64.Implicit(Value: Word): TData64; 1046 | begin 1047 | Result.Clear; 1048 | Result.Words[0] := Value; 1049 | end; 1050 | 1051 | class operator TData64.Implicit(Value: TData64): Word; 1052 | begin 1053 | Result := Value.Words[0]; 1054 | end; 1055 | 1056 | class operator TData64.Implicit(Value: Longword): TData64; 1057 | begin 1058 | Result.Clear; 1059 | Result.LoLong := Value; 1060 | end; 1061 | 1062 | class operator TData64.Implicit(Value: TData64): Longword; 1063 | begin 1064 | Result := Value.LoLong; 1065 | end; 1066 | 1067 | class operator TData64.Implicit(Value: Integer): TData64; 1068 | begin 1069 | Result.Clear; 1070 | Result.AsInt64 := Value; 1071 | end; 1072 | 1073 | class operator TData64.Implicit(Value: TData64): Integer; 1074 | begin 1075 | if (Value.AsInt64High(Integer)) then Result := High(Integer) 1077 | else Result := Value.AsInt64; 1078 | end; 1079 | 1080 | Procedure TData64.PlusEpsilon; 1081 | begin 1082 | inc(asUInt64); 1083 | end; 1084 | 1085 | Procedure TData64.MinusEpsilon; 1086 | begin 1087 | dec(asUInt64); 1088 | end; 1089 | 1090 | {$IFDEF DELPHI10UP} 1091 | (******************************) 1092 | (***** TBooleanListHelper *****) 1093 | (******************************) 1094 | Function TBooleanListHelper.ToString: string; 1095 | Var Help : String; 1096 | i : Integer; 1097 | begin 1098 | Help := '['; 1099 | for i := 0 to Count-1 do 1100 | begin 1101 | if (Items[i]) then 1102 | begin 1103 | Help := Help + i.ToString + ', '; 1104 | end; 1105 | end; 1106 | if (Help[length(Help)]=' ') then 1107 | begin 1108 | SetLength(Help,length(Help)-2); 1109 | end; 1110 | Help := Help + ']'; 1111 | Result := Help; 1112 | end; 1113 | {$ENDIF DELPHI10UP} 1114 | 1115 | (******************************) 1116 | (***** TIntegerListHelper *****) 1117 | (******************************) 1118 | Procedure TIntegerListHelper.AddIfNotExists(Const Value:Integer); 1119 | begin 1120 | if (IndexOf(Value)=-1) then Add(Value); 1121 | end; 1122 | 1123 | {$IFDEF DELPHI10UP} 1124 | Function TIntegerListHelper.ToString : String; 1125 | Var 1126 | i : Integer; 1127 | begin 1128 | Result := '['; 1129 | for i := 0 to Count-1 do 1130 | begin 1131 | Result := Result + Items[i].ToString; 1132 | if (i FCount) then 1220 | begin 1221 | Add(Index-FCount,False); 1222 | end else 1223 | if (Index < FCount) then 1224 | begin 1225 | SetLength(FItems, (Index div PlyBoolSize)+1); 1226 | FCount := Index; 1227 | end; 1228 | end; 1229 | 1230 | Function TPlyBoolList.GetCountTrue : Int64; 1231 | Var 1232 | iCount: Int64; 1233 | {$IFDEF DELPHI10UP} 1234 | i: Int64; 1235 | {$ELSE} 1236 | i : Longint; 1237 | {$ENDIF DELPHI10UP} 1238 | begin 1239 | iCount := 0; 1240 | for I := 0 to FCount-1 do 1241 | begin 1242 | if (Items[i]) then inc(iCount); 1243 | end; 1244 | Result := iCount; 1245 | end; 1246 | 1247 | Procedure TPlyBoolList.Add(Const Value:Boolean); 1248 | begin 1249 | if ((FCount div PlyBoolSize)>=length(FItems)) then 1250 | begin 1251 | // Add 32 new Booleans 1252 | SetLength(FItems,length(FItems)+1); 1253 | // Set 32 new Booleans to False 1254 | FItems[length(FItems)-1].FValue := $0; 1255 | end; 1256 | FItems[FCount div PlyBoolSize].Bools[FCount mod PlyBoolSize] := Value; 1257 | inc(FCount); 1258 | end; 1259 | 1260 | Procedure TPlyBoolList.Add(CountBools:Cardinal; Const Value:Boolean); 1261 | Var NewCount : Cardinal; 1262 | begin 1263 | NewCount := FCount + CountBools; 1264 | // Fill existing Booleans with Value 1265 | while (FCount < NewCount) and 1266 | (FCount div PlyBoolsize <= length(FItems)-1) do 1267 | begin 1268 | FItems[FCount div PlyBoolSize].Bools[FCount mod PlyBoolSize] := Value; 1269 | inc(FCount); 1270 | end; 1271 | while (FCount < NewCount) do 1272 | begin 1273 | // Add 32 new Booleans 1274 | SetLength(FItems,length(FItems)+1); 1275 | // Fill 32 new Bolleans with Value 1276 | if (Value) 1277 | then FItems[length(FItems)-1].FValue := $FFFFFFFF 1278 | else FItems[length(FItems)-1].FValue := $0; 1279 | // Set new FCount 1280 | FCount := Min(FCount+32,NewCount); 1281 | end; 1282 | end; 1283 | 1284 | Function TPlyBoolList.MemorySizeByte : Cardinal; 1285 | begin 1286 | Result := Length(FItems) * 4; 1287 | end; 1288 | 1289 | Function TPlyBoolList.ToStringNumberTrue : String; 1290 | Var 1291 | Help: String; 1292 | I: Integer; 1293 | First: Boolean; 1294 | begin 1295 | First := True; 1296 | Help := '['; 1297 | for I := 0 to Count-1 do 1298 | begin 1299 | if (Items[i]) then 1300 | begin 1301 | if (First) then 1302 | begin 1303 | Help := Help + i.ToString; 1304 | First := False; 1305 | end else Help := Help + ', ' + i.ToString; 1306 | end; 1307 | end; 1308 | Help := Help + ']'; 1309 | Result := Help; 1310 | end; 1311 | 1312 | Function TPlyBoolList.ToStringNumberFalse : String; 1313 | Var 1314 | Help: String; 1315 | I: Integer; 1316 | First: Boolean; 1317 | begin 1318 | First := True; 1319 | Help := '['; 1320 | for I := 0 to Count-1 do 1321 | begin 1322 | if not(Items[i]) then 1323 | begin 1324 | if (First) then 1325 | begin 1326 | Help := Help + i.ToString; 1327 | First := False; 1328 | end else Help := Help + ', ' + i.ToString; 1329 | end; 1330 | end; 1331 | Help := Help + ']'; 1332 | Result := Help; 1333 | end; 1334 | 1335 | Function TPlyBoolList.ToStringBooleans : String; 1336 | Var 1337 | Help: String; 1338 | I: Integer; 1339 | First: Boolean; 1340 | begin 1341 | First := True; 1342 | Help := '['; 1343 | for I := 0 to Count-1 do 1344 | begin 1345 | if (First) then 1346 | begin 1347 | Help := Help + Items[i].ZeroOne.ToString; 1348 | First := False; 1349 | end else Help := Help + ', ' + Items[i].ZeroOne.ToString; 1350 | end; 1351 | Help := Help + ']'; 1352 | Result := Help; 1353 | end; 1354 | 1355 | (*********************) 1356 | (***** TAppender *****) 1357 | (*********************) 1358 | class procedure TAppender.Append(var Arr: TArray; Value: T); 1359 | begin 1360 | SetLength(Arr, Length(Arr)+1); 1361 | Arr[High(Arr)] := Value; 1362 | end; 1363 | 1364 | end. 1365 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Playcom Console Library 2 | 3 | **Purpose:** 4 | 5 | Library for Delphi-Console-Applications | Supports Windows 11 (and earlier) 6 | 7 | - Can be used to write modern and appealing console applications. 8 | - Should allow older (legacy) source code (Borland Pascal 7.0) to run under Windows. 9 | 10 | **Usage:** 11 | 12 | Include the location of the unit "crt.pas" to the searchpath in your project settings and add the unit to the uses-clauses of your project. For the use of extended functions of the library it could be necessary to add further units (e.g. "ply.console.pas", or "ply.console.extended.pas") to the uses-clauses. To demonstrate the use of the library, I have added [Demo-Applications](Demo). 13 | 14 | **Feature-List:** 15 | - Largely compatible with legacy code (Borland Pascal 7.0) 16 | - Different fonts and font sizes 17 | - Any size of the console window 18 | - Enhanced Input- and Output-Functions 19 | - FrameWindow & LineSelect 20 | - Extended color-support (16 background colors, colorcodes freely selectable) 21 | - Underline & Outline Text 22 | - Full keyboard support 23 | - AnsiString and UnicodeString support (including e.g. chinese characters) 24 | - ScreenSave & ScreenRestore (save to memory or disk) 25 | - Move console-window on any position on the desktop (includes multi-monitor-support) 26 | - Change all console-modes (LineWarp, Opacity, QuickEditMode, etc.) directly from the software 27 | - and many more 28 | 29 | **Minimal Console-App:** 30 | 31 | ```pascal 32 | program Demo01_Minimal_Console_App; 33 | uses crt; 34 | begin 35 | TextBackground(White); 36 | Textcolor(Red); 37 | ClrScr; 38 | Writeln('Hello World!'); 39 | Readkey; 40 | end. 41 | ``` 42 | 43 | **Contributions:** 44 | 45 | Contributions are welcome, either as Pull Requests or bug reports. If you want to report a bug or you are missing a feature, contact me by email (wolfgang[at]playcom.de). 46 | 47 | **Screenshots:** 48 | 49 | ![Demo01](Pictures/Demo01_Minimal_Console_App.jpg) 50 | 51 | ![Demo02](Pictures/Demo02_Fontface_Fontsize.jpg) 52 | 53 | ![Demo03](Pictures/Demo03_Move_Window.jpg) 54 | 55 | ![Demo04](Pictures/Demo04_Input_Keyboard.jpg) 56 | 57 | ![Demo05](Pictures/Demo05_Console_Mode.jpg) 58 | 59 | ![Demo06](Pictures/Demo06_Colors.jpg) 60 | 61 | ![Demo07](Pictures/Demo07_ScreenSave.jpg) 62 | 63 | ![Demo08](Pictures/Demo08_ASCII_Characters.jpg) 64 | 65 | ![Demo08](Pictures/Demo09_BuiltIn_Features.jpg) 66 | -------------------------------------------------------------------------------- /crt.inc: -------------------------------------------------------------------------------- 1 | (****************************************************************************** 2 | 3 | Name : crt.inc 4 | Copyright : © 1999 - 2023 Playcom Software Vertriebs GmbH 5 | Last modified : 31.07.2023 6 | License : disjunctive three-license (MPL|GPL|LGPL) see License.md 7 | Description : This file is part of the Open Source "Playcom Console Library" 8 | 9 | ******************************************************************************) 10 | 11 | Const 12 | {$IFDEF DELPHIXE8DOWN} 13 | // Console-Attribute Hi-Byte from Word 14 | COMMON_LVB_LEADING_BYTE = $0100; 15 | COMMON_LVB_TRAILING_BYTE = $0200; 16 | COMMON_LVB_GRID_HORIZONTAL = $0400; 17 | COMMON_LVB_GRID_LVERTICAL = $0800; 18 | COMMON_LVB_GRID_RVERTICAL = $1000; 19 | COMMON_LVB_UNKNOWN = $2000; 20 | COMMON_LVB_REVERSE_VIDEO = $4000; 21 | COMMON_LVB_UNDERSCORE = $8000; 22 | {$ENDIF DELPHIXE8DOWN} 23 | 24 | // Values for dwControllKeyState 25 | _CKS_NONE = $0000; 26 | _CKS_RIGHT_ALT_PRESSED = $0001; 27 | _CKS_LEFT_ALT_PRESSED = $0002; 28 | _CKS_RIGHT_CTRL_PRESSED = $0004; 29 | _CKS_LEFT_CTRL_PRESSED = $0008; 30 | _CKS_SHIFT_PRESSED = $0010; 31 | _CKS_NUMLOCK_ON = $0020; 32 | _CKS_SCROLLLOCK_ON = $0040; 33 | _CKS_CAPSLOCK_ON = $0080; 34 | _CKS_ENHANCED_KEY = $0100; 35 | 36 | // Values for wVirtualKeyCode 37 | _VKC_BACK = $0008; (* #8 = Backspace *) 38 | _VKC_TAB = $0009; (* #9 = Tabulator *) 39 | _VKC_RETURN = $000D; (* #13 *) 40 | _VKC_ESCAPE = $001B; (* #27 *) 41 | _VKC_SPACE = $0020; (* #32 *) 42 | _VKC_PgUp = $0021; (* #33 *) 43 | _VKC_PgDown = $0022; (* #34 *) 44 | _VKC_END = $0023; (* #35 *) 45 | _VKC_POS1 = $0024; (* #36 *) 46 | _VKC_HOME = $0024; (* #36 = Alias POS1 *) 47 | _VKC_LEFT = $0025; (* #37 *) 48 | _VKC_UP = $0026; (* #38 *) 49 | _VKC_RIGHT = $0027; (* #39 *) 50 | _VKC_DOWN = $0028; (* #40 *) 51 | _VKC_INSERT = $002D; (* #45 *) 52 | _VKC_DELETE = $002E; (* #46 *) 53 | _VKC_0 = $0030; (* #48 *) 54 | _VKC_1 = $0031; (* #49 *) 55 | _VKC_2 = $0032; (* #50 *) 56 | _VKC_3 = $0033; (* #51 *) 57 | _VKC_4 = $0034; (* #52 *) 58 | _VKC_5 = $0035; (* #53 *) 59 | _VKC_6 = $0036; (* #54 *) 60 | _VKC_7 = $0037; (* #55 *) 61 | _VKC_8 = $0038; (* #56 *) 62 | _VKC_9 = $0039; (* #57 *) 63 | _VKC_A = $0041; (* #65 *) 64 | _VKC_F = $0046; (* #70 *) 65 | _VKC_L = $004C; (* #76 *) 66 | _VKC_N = $004E; (* #78 *) 67 | _VKC_P = $0050; (* #80 *) 68 | _VKC_R = $0052; (* #82 *) 69 | _VKC_Z = $005A; (* #90 *) 70 | _VKC_LWin = $005B; (* #91 = Left Windows Key *) 71 | _VKC_RWin = $005C; (* #92 = Right Windows Key *) 72 | _VKC_0_NumPad = $0060; (* #96 *) 73 | _VKC_1_NumPad = $0061; (* #97 *) 74 | _VKC_2_NumPad = $0062; (* #98 *) 75 | _VKC_3_NumPad = $0063; (* #99 *) 76 | _VKC_4_NumPad = $0064; (* #100 *) 77 | _VKC_5_NumPad = $0065; (* #101 *) 78 | _VKC_6_NumPad = $0066; (* #102 *) 79 | _VKC_7_NumPad = $0067; (* #103 *) 80 | _VKC_8_NumPad = $0068; (* #104 *) 81 | _VKC_9_NumPad = $0069; (* #105 *) 82 | _VKC_MULTIPLY_NumPad = $006A; (* #106 = * (NumPad) *) 83 | _VKC_PLUS_NumPad = $006B; (* #107 *) 84 | _VKC_SEPERATOR = $006C; (* #108 *) 85 | _VKC_MINUS_NumPad = $006D; (* #109 *) 86 | _VKC_DECIMAL_NumPad = $006E; (* #110 = , (NumPad) *) 87 | _VKC_DIVIDE_NumPad = $006F; (* #111 = / (NumPad) *) 88 | _VKC_F1 = $0070; (* #112 *) 89 | _VKC_F24 = $0087; (* #135 *) 90 | _VKC_PLUS = $00BB; (* #187 *) 91 | _VKC_MINUS = $00BD; (* #189 *) 92 | _VKC_OEM1 = $00BA; (* #186 = German Umlaut ü (U+00FC) *) 93 | _VKC_OEM2 = $00BF; (* #191 = Apostrophe ' (U+0027) *) 94 | _VKC_OEM3 = $00C0; (* #192 = German Umlaut ö (U+00F6) *) 95 | _VKC_OEM4 = $00DB; (* #219 = German Umlaut ß (U+00DF) *) 96 | _VKC_OEM5 = $00DC; (* #220 = CP437 = \ *) 97 | _VKC_OEM6 = $00DD; (* #221 = Acute Accent ´ (U+00B4) *) 98 | _VKC_OEM7 = $00DE; (* #222 = German Umlaut ä (U+00E4) *) 99 | 100 | // Key-Values to enable queries like "if (Key>=_F1) and (Key<=_F12) then" 101 | _BackSpace = $0008; (* #8 = Backspace *) 102 | _TAB = $0009; (* #9 = Tabulator *) 103 | _Return = $000D; (* #13 = Return *) 104 | _Escape = $001B; (* #27 = Escape *) 105 | _ESC = $001B; (* #27 = Alias Escape *) 106 | _SPACE = $0020; (* #32 *) 107 | _PgUp = $0021; (* #33 *) 108 | _PgDown = $0022; (* #34 *) 109 | _END = $0023; (* #35 *) 110 | _POS1 = $0024; (* #36 *) 111 | _LEFT = $0025; (* #37 *) 112 | _UP = $0026; (* #38 *) 113 | _RIGHT = $0027; (* #39 *) 114 | _DOWN = $0028; (* #40 *) 115 | _INSERT = $002D; (* #45 *) 116 | // There is a overlap with Winapi.Windows "_Delete" so you have use 117 | // _DELETE_CRT instead of _DELETE to be save 118 | _DELETE_CRT = $002E; (* #46 *) 119 | 120 | _Break = $4500; (* #17664 *) 121 | 122 | _0 = $0030; (* #48 *) 123 | _1 = $0031; (* #49 *) 124 | _2 = $0032; (* #50 *) 125 | _3 = $0033; (* #51 *) 126 | _4 = $0034; (* #52 *) 127 | _5 = $0035; (* #53 *) 128 | _6 = $0036; (* #54 *) 129 | _7 = $0037; (* #55 *) 130 | _8 = $0038; (* #56 *) 131 | _9 = $0039; (* #57 *) 132 | _QUESTIONMARK = $003F; (* #63 = Questionmark ? (U+003F) *) 133 | _A = $0041; (* #65 *) 134 | _B = $0042; (* #66 *) 135 | _C = $0043; (* #67 *) 136 | _D = $0044; (* #68 *) 137 | _E = $0045; (* #69 *) 138 | _F = $0046; (* #70 *) 139 | _G = $0047; (* #71 *) 140 | _H = $0048; (* #72 *) 141 | _I = $0049; (* #73 *) 142 | _J = $004A; (* #74 *) 143 | _K = $004B; (* #75 *) 144 | _L = $004C; (* #76 *) 145 | _M = $004D; (* #77 *) 146 | _N = $004E; (* #78 *) 147 | _O = $004F; (* #79 *) 148 | _P = $0050; (* #80 *) 149 | _Q = $0051; (* #81 *) 150 | _R = $0052; (* #82 *) 151 | _S = $0053; (* #83 *) 152 | _T = $0054; (* #84 *) 153 | _U = $0055; (* #85 *) 154 | _V = $0056; (* #86 *) 155 | _W = $0057; (* #87 *) 156 | _X = $0058; (* #88 *) 157 | _Y = $0059; (* #89 *) 158 | _Z = $005A; (* #90 *) 159 | 160 | _0_NumPad = $0060; (* #96 *) 161 | _1_NumPad = $0061; (* #97 *) 162 | _2_NumPad = $0062; (* #98 *) 163 | _3_NumPad = $0063; (* #99 *) 164 | _4_NumPad = $0064; (* #100 *) 165 | _5_NumPad = $0065; (* #101 *) 166 | _6_NumPad = $0066; (* #102 *) 167 | _7_NumPad = $0067; (* #103 *) 168 | _8_NumPad = $0068; (* #104 *) 169 | _9_NumPad = $0069; (* #105 *) 170 | _MULTIPLY_NumPad = $006A; (* #106 = * (NumPad) *) 171 | _PLUS_NumPad = $006B; (* #107 = + (NumPad) *) 172 | _MINUS_NumPad = $006D; (* #109 = - (NumPad) *) 173 | _DIVIDE_NumPad = $006F; (* #111 = / (NumPad) *) 174 | _F1 = $0070; (* #112 *) 175 | _F2 = $0071; (* #113 *) 176 | _F3 = $0072; (* #114 *) 177 | _F4 = $0073; (* #115 *) 178 | _F5 = $0074; (* #116 *) 179 | _F6 = $0075; (* #117 *) 180 | _F7 = $0076; (* #118 *) 181 | _F8 = $0077; (* #119 *) 182 | _F9 = $0078; (* #120 *) 183 | _F10 = $0079; (* #121 *) 184 | _F11 = $007A; (* #122 *) 185 | _F12 = $007B; (* #123 *) 186 | _F24 = $0087; (* #135 *) 187 | _Return_NumPad = $008F; (* #143 *) 188 | _PLUS = $00BB; (* #187 = + *) 189 | _MINUS = $00BD; (* #189 = - *) 190 | _UE = $00BA; (* #186 = German Umlaut ü *) 191 | _OE = $00C0; (* #192 = German Umlaut ö *) 192 | _SS = $00DB; (* #219 = German Umlaut ß *) 193 | _Akut_Akzent = $00DD; (* #221 = Acute Accent ´ (U+00B4) *) 194 | _AE = $00DE; (* #222 = German Umlaut ä *) 195 | 196 | _Yes = $03EE; (* #1006 = Yes *) 197 | _No = $03EF; (* #1007 = No *) 198 | 199 | // Shift = $4Cxx 200 | _SHIFT_TAB = $4C09; (* #19465 *) 201 | _SHIFT_RETURN = $4C0D; (* #19469 *) 202 | _SHIFT_INSERT = $4C2D; (* #19501 *) 203 | _SHIFT_DELETE = $4C2E; (* #19502 *) 204 | _SHIFT_A = $4C41; (* #19521 *) 205 | _SHIFT_Z = $4C5A; (* #19546 *) 206 | _SHIFT_UE = $4CBA; (* #19642 = German Umlaut Ü *) 207 | _SHIFT_OE = $4CC0; (* #19648 = German Umlaut Ö *) 208 | _SHIFT_AE = $4CDE; (* #19678 = German Umlaut Ü *) 209 | _SHIFT_F1 = $4C70; (* #19568 *) 210 | _SHIFT_F2 = $4C71; (* #19569 *) 211 | _SHIFT_F3 = $4C72; (* #19570 *) 212 | _SHIFT_F4 = $4C73; (* #19571 *) 213 | _SHIFT_F5 = $4C74; (* #19572 *) 214 | _SHIFT_F6 = $4C75; (* #19573 *) 215 | _SHIFT_F7 = $4C76; (* #19574 *) 216 | _SHIFT_F8 = $4C77; (* #19575 *) 217 | _SHIFT_F9 = $4C78; (* #19576 *) 218 | _SHIFT_F10 = $4C79; (* #19568 *) 219 | _SHIFT_F11 = $4C7A; (* #19578 *) 220 | _SHIFT_F12 = $4C7B; (* #19579 *) 221 | _Gravis_Akzent = $4CDD; (* #19677 = Grave Accent ' (U+0060) *) 222 | 223 | // Ctrl (left or right) = $4Exx 224 | _CTRL_TAB = $4E09; (* #19977 *) 225 | _CTRL_Return = $4E0D; (* #19981 *) 226 | _CTRL_PgUp = $4E21; (* #20001 *) 227 | _CTRL_PgDown = $4E22; (* #20002 *) 228 | _CTRL_END = $4E23; (* #20003 *) 229 | _CTRL_POS1 = $4E24; (* #20004 *) 230 | _CTRL_LEFT = $4E25; (* #20005 *) 231 | _CTRL_UP = $4E26; (* #20006 *) 232 | _CTRL_RIGHT = $4E27; (* #20007 *) 233 | _CTRL_DOWN = $4E28; (* #20008 *) 234 | _CTRL_INSERT = $4E2D; (* #20013 *) 235 | _CTRL_DELETE = $4E2E; (* #20014 *) 236 | _CTRL_0 = $4E30; (* #20016 *) 237 | _CTRL_1 = $4E31; (* #20017 *) 238 | _CTRL_2 = $4E32; (* #20018 *) 239 | _CTRL_3 = $4E33; (* #20019 *) 240 | _CTRL_4 = $4E34; (* #20020 *) 241 | _CTRL_5 = $4E35; (* #20021 *) 242 | _CTRL_6 = $4E36; (* #20022 *) 243 | _CTRL_7 = $4E37; (* #20023 *) 244 | _CTRL_8 = $4E38; (* #20024 *) 245 | _CTRL_9 = $4E39; (* #20025 *) 246 | _CTRL_A = $4E41; (* #20033 *) 247 | _CTRL_B = $4E42; (* #20034 *) 248 | _CTRL_C = $4E43; (* #20035 *) 249 | _CTRL_D = $4E44; (* #20036 *) 250 | _CTRL_E = $4E45; (* #20037 *) 251 | _CTRL_F = $4E46; (* #20038 *) 252 | _CTRL_G = $4E47; (* #20039 *) 253 | _CTRL_H = $4E48; (* #20040 *) 254 | _CTRL_I = $4E49; (* #20041 *) 255 | _CTRL_J = $4E4A; (* #20042 *) 256 | _CTRL_K = $4E4B; (* #20043 *) 257 | _CTRL_L = $4E4C; (* #20044 *) 258 | _CTRL_M = $4E4D; (* #20045 *) 259 | _CTRL_N = $4E4E; (* #20046 *) 260 | _CTRL_O = $4E4F; (* #20047 *) 261 | _CTRL_P = $4E50; (* #20048 *) 262 | _CTRL_Q = $4E51; (* #20049 *) 263 | _CTRL_R = $4E52; (* #20050 *) 264 | _CTRL_S = $4E53; (* #20051 *) 265 | _CTRL_T = $4E54; (* #20052 *) 266 | _CTRL_U = $4E55; (* #20053 *) 267 | _CTRL_V = $4E56; (* #20054 *) 268 | _CTRL_W = $4E57; (* #20055 *) 269 | _CTRL_X = $4E58; (* #20056 *) 270 | _CTRL_Y = $4E59; (* #20057 *) 271 | _CTRL_Z = $4E5A; (* #20058 *) 272 | _CTRL_0_NumPad = $4E60; (* #20064 *) 273 | _CTRL_1_NumPad = $4E61; (* #20065 *) 274 | _CTRL_2_NumPad = $4E62; (* #20066 *) 275 | _CTRL_3_NumPad = $4E63; (* #20067 *) 276 | _CTRL_4_NumPad = $4E64; (* #20068 *) 277 | _CTRL_5_NumPad = $4E65; (* #20069 *) 278 | _CTRL_6_NumPad = $4E66; (* #20070 *) 279 | _CTRL_7_NumPad = $4E67; (* #20071 *) 280 | _CTRL_8_NumPad = $4E68; (* #20072 *) 281 | _CTRL_9_NumPad = $4E69; (* #20073 *) 282 | _CTRL_PLUS_NumPad = $4E6B; (* #20075 *) 283 | _CTRL_MINUS_NumPad = $4E6D; (* #20077 *) 284 | _CTRL_F1 = $4E70; (* #20080 *) 285 | _CTRL_F2 = $4E71; (* #20081 *) 286 | _CTRL_F3 = $4E72; (* #20082 *) 287 | _CTRL_F4 = $4E73; (* #20083 *) 288 | _CTRL_F5 = $4E74; (* #20084 *) 289 | _CTRL_F6 = $4E75; (* #20085 *) 290 | _CTRL_F7 = $4E76; (* #20086 *) 291 | _CTRL_F8 = $4E77; (* #20087 *) 292 | _CTRL_F9 = $4E78; (* #20088 *) 293 | _CTRL_F10 = $4E79; (* #20089 *) 294 | _CTRL_F11 = $4E7A; (* #20090 *) 295 | _CTRL_F12 = $4E7B; (* #20091 *) 296 | _CTRL_PLUS = $4EBB; (* #20155 *) 297 | _CTRL_MINUS = $4EBD; (* #20157 *) 298 | 299 | // Ctrl (l or r) & Shift = $4Fxx 300 | _CTRL_SHIFT_0 = $4F30; (* #20272 *) 301 | _CTRL_SHIFT_1 = $4F31; (* #20273 *) 302 | _CTRL_SHIFT_2 = $4F32; (* #20274 *) 303 | _CTRL_SHIFT_3 = $4F33; (* #20275 *) 304 | _CTRL_SHIFT_4 = $4F34; (* #20276 *) 305 | _CTRL_SHIFT_5 = $4F35; (* #20277 *) 306 | _CTRL_SHIFT_6 = $4F36; (* #20278 *) 307 | _CTRL_SHIFT_7 = $4F37; (* #20279 *) 308 | _CTRL_SHIFT_8 = $4F38; (* #20280 *) 309 | _CTRL_SHIFT_9 = $4F39; (* #20281 *) 310 | _CTRL_SHIFT_A = $4F41; (* #20289 *) 311 | _CTRL_SHIFT_B = $4F42; (* #20290 *) 312 | _CTRL_SHIFT_C = $4F43; (* #20291 *) 313 | _CTRL_SHIFT_D = $4F44; (* #20292 *) 314 | _CTRL_SHIFT_E = $4f45; (* #20293 *) 315 | _CTRL_SHIFT_F = $4F46; (* #20294 *) 316 | 317 | // Alt (left) = $50xx 318 | _ALT_Insert = $502D; (* #20525 *) 319 | _ALT_Delete = $502E; (* #20526 *) 320 | _ALT_0 = $5030; (* #20528 *) 321 | _ALT_1 = $5031; (* #20529 *) 322 | _ALT_2 = $5032; (* #20530 *) 323 | _ALT_3 = $5033; (* #20531 *) 324 | _ALT_4 = $5034; (* #20532 *) 325 | _ALT_5 = $5035; (* #20533 *) 326 | _ALT_6 = $5036; (* #20534 *) 327 | _ALT_7 = $5037; (* #20535 *) 328 | _ALT_8 = $5038; (* #20536 *) 329 | _ALT_9 = $5039; (* #20537 *) 330 | _ALT_A = $5041; (* #20545 *) 331 | _ALT_B = $5042; (* #20546 *) 332 | _ALT_C = $5043; (* #20547 *) 333 | _ALT_D = $5044; (* #20548 *) 334 | _ALT_E = $5045; (* #20549 *) 335 | _ALT_F = $5046; (* #20550 *) 336 | _ALT_G = $5047; (* #20551 *) 337 | _ALT_H = $5048; (* #20552 *) 338 | _ALT_I = $5049; (* #20553 *) 339 | _ALT_J = $504A; (* #20554 *) 340 | _ALT_K = $504B; (* #20555 *) 341 | _ALT_L = $504C; (* #20556 *) 342 | _ALT_M = $504D; (* #20557 *) 343 | _ALT_N = $504E; (* #20558 *) 344 | _ALT_O = $504F; (* #20559 *) 345 | _ALT_P = $5050; (* #20560 *) 346 | _ALT_Q = $5051; (* #20561 *) 347 | _ALT_R = $5052; (* #20562 *) 348 | _ALT_S = $5053; (* #20563 *) 349 | _ALT_T = $5054; (* #20564 *) 350 | _ALT_U = $5055; (* #20565 *) 351 | _ALT_V = $5056; (* #20566 *) 352 | _ALT_W = $5057; (* #20567 *) 353 | _ALT_X = $5058; (* #20568 *) 354 | _ALT_Y = $5059; (* #20569 *) 355 | _ALT_Z = $505A; (* #20570 *) 356 | _ALT_0_NumPad = $5060; (* #20576 *) 357 | _ALT_9_NumPad = $5069; (* #20585 *) 358 | _ALT_Plus_NumPad = $506B; (* #20587 *) 359 | _ALT_Minus_NumPad = $506D; (* #20589 *) 360 | _ALT_F1 = $5070; (* #20592 *) 361 | _ALT_F2 = $5071; (* #20593 *) 362 | _ALT_F3 = $5072; (* #20594 *) 363 | _ALT_F4 = $5073; (* #20595 *) 364 | _ALT_F5 = $5074; (* #20596 *) 365 | _ALT_F6 = $5075; (* #20597 *) 366 | _ALT_F7 = $5076; (* #20598 *) 367 | _ALT_F8 = $5077; (* #20599 *) 368 | _ALT_F9 = $5078; (* #20600 *) 369 | _ALT_F10 = $5079; (* #20601 *) 370 | _ALT_F11 = $507A; (* #20602 *) 371 | _ALT_F12 = $507B; (* #20603 *) 372 | _ALT_F24 = $5087; (* #20615 *) 373 | _ALT_Plus = $50BB; (* #20667 *) 374 | _ALT_Minus = $50BD; (* #20669 *) 375 | 376 | // Alt (left) & Shift = $51xx 377 | _ALT_SHIFT_0 = $5130; (* #20784 *) 378 | _ALT_SHIFT_1 = $5131; (* #20785 *) 379 | _ALT_SHIFT_2 = $5132; (* #20786 *) 380 | _ALT_SHIFT_3 = $5133; (* #20787 *) 381 | _ALT_SHIFT_4 = $5134; (* #20788 *) 382 | _ALT_SHIFT_5 = $5135; (* #20789 *) 383 | _ALT_SHIFT_6 = $5136; (* #20790 *) 384 | _ALT_SHIFT_7 = $5137; (* #20791 *) 385 | _ALT_SHIFT_8 = $5138; (* #20792 *) 386 | _ALT_SHIFT_9 = $5139; (* #20793 *) 387 | _ALT_SHIFT_A = $5141; (* #20801 *) 388 | _ALT_SHIFT_B = $5142; (* #20802 *) 389 | _ALT_SHIFT_C = $5143; (* #20803 *) 390 | _ALT_SHIFT_D = $5144; (* #20804 *) 391 | _ALT_SHIFT_E = $5145; (* #20805 *) 392 | _ALT_SHIFT_F = $5146; (* #20806 *) 393 | 394 | // AltGr (right) = $52xx 395 | _ALTGR_INSERT = $522D; (* #21037 *) 396 | _ALTGR_0 = $5230; (* #21040 *) 397 | _ALTGR_1 = $5231; (* #21041 = Superscript 1 ¹ (U+00B9) *) 398 | _ALTGR_2 = $5232; (* #21042 = Superscript 2 ² (U+00B2) *) 399 | _ALTGR_3 = $5233; (* #21043 = Superscript 3 ³ (U+00B3) *) 400 | _ALTGR_4 = $5234; (* #21044 = Superscript 4 ⁴ (U+2074) *) 401 | _ALTGR_5 = $5235; (* #21045 = Superscript 5 ⁵ (U+2075) *) 402 | _ALTGR_6 = $5236; (* #21046 = Superscript 6 ⁶ (U+2076) *) 403 | _ALTGR_7 = $5237; (* #21047 *) 404 | _ALTGR_8 = $5238; (* #21048 *) 405 | _ALTGR_9 = $5239; (* #21049 *) 406 | _ALTGR_C = $5243; (* #21059 = Copyright Sign © (U+00A9) *) 407 | _ALTGR_E = $5245; (* #21061 = Euro-Sign € (U+20AC) *) 408 | _ALTGR_M = $524D; (* #21069 = Greek Small Mu µ (U+03BC) *) 409 | _ALTGR_N = $524E; (* #21070 = Superscript n ⁿ (U+207F) *) 410 | _ALTGR_P = $5250; (* #21072 = Sound Copyright ℗ (U+2117) *) 411 | _ALTGR_R = $5252; (* #21074 = Registered Sign ® (U+00AE) *) 412 | _ALTGR_T = $5254; (* #21076 *) 413 | _ALTGR_0_NumPad = $5260; (* #21088 *) 414 | _ALTGR_1_NumPad = $5261; (* #21089 *) 415 | _ALTGR_2_NumPad = $5262; (* #21090 *) 416 | _ALTGR_3_NumPad = $5263; (* #21091 *) 417 | _ALTGR_4_NumPad = $5264; (* #21092 *) 418 | _ALTGR_5_NumPad = $5265; (* #21093 *) 419 | _ALTGR_6_NumPad = $5266; (* #21094 *) 420 | _ALTGR_7_NumPad = $5267; (* #21095 *) 421 | _ALTGR_8_NumPad = $5268; (* #21096 *) 422 | _ALTGR_9_NumPad = $5269; (* #21097 *) 423 | _ALTGR_PLUS_NumPad = $526B; (* #21099 *) 424 | _ALTGR_MINUS_NumPad = $526D; (* #21101 *) 425 | _ALTGR_Plus = $52BB; (* #21179 *) 426 | _ALTGR_Minus = $52BD; (* #21181 *) 427 | _Backslash = $52DB; (* #21211 = Reverse Solidus \ (U+005C) *) 428 | 429 | // Left-Ctrl + Left-Alt = $CDxx 430 | _CTRL_ALT_TAB = $CD09; (* #52489 *) 431 | _CTRL_ALT_Return = $CD0D; (* #52493 *) 432 | _CTRL_ALT_0 = $CD30; (* #52528 *) 433 | _CTRL_ALT_1 = $CD31; (* #52529 *) 434 | _CTRL_ALT_2 = $CD32; (* #52530 *) 435 | _CTRL_ALT_3 = $CD33; (* #52531 *) 436 | _CTRL_ALT_4 = $CD34; (* #52532 *) 437 | _CTRL_ALT_5 = $CD35; (* #52533 *) 438 | _CTRL_ALT_6 = $CD36; (* #52534 *) 439 | _CTRL_ALT_7 = $CD37; (* #52535 *) 440 | _CTRL_ALT_8 = $CD38; (* #52536 *) 441 | _CTRL_ALT_9 = $CD39; (* #52537 *) 442 | _CTRL_ALT_A = $CD41; (* #52545 *) 443 | _CTRL_ALT_B = $CD42; (* #52546 *) 444 | _CTRL_ALT_C = $CD43; (* #52547 *) 445 | _CTRL_ALT_D = $CD44; (* #52548 *) 446 | _CTRL_ALT_E = $CD45; (* #52549 *) 447 | _CTRL_ALT_F = $CD46; (* #52550 *) 448 | _CTRL_ALT_G = $CD47; (* #52551 *) 449 | _CTRL_ALT_H = $CD48; (* #52552 *) 450 | _CTRL_ALT_I = $CD49; (* #52553 *) 451 | _CTRL_ALT_J = $CD4A; (* #52554 *) 452 | _CTRL_ALT_K = $CD4B; (* #52555 *) 453 | _CTRL_ALT_L = $CD4C; (* #52556 *) 454 | _CTRL_ALT_M = $CD4D; (* #52557 *) 455 | _CTRL_ALT_N = $CD4E; (* #52558 *) 456 | _CTRL_ALT_O = $CD4F; (* #52559 *) 457 | _CTRL_ALT_P = $CD50; (* #52560 *) 458 | _CTRL_ALT_Q = $CD51; (* #52561 *) 459 | _CTRL_ALT_R = $CD52; (* #52562 *) 460 | _CTRL_ALT_S = $CD53; (* #52563 *) 461 | _CTRL_ALT_T = $CD54; (* #52564 *) 462 | _CTRL_ALT_U = $CD55; (* #52565 *) 463 | _CTRL_ALT_V = $CD56; (* #52566 *) 464 | _CTRL_ALT_W = $CD57; (* #52567 *) 465 | _CTRL_ALT_X = $CD58; (* #52568 *) 466 | _CTRL_ALT_Y = $CD59; (* #52569 *) 467 | _CTRL_ALT_Z = $CD5A; (* #52570 *) 468 | _CTRL_ALT_0_NumPad = $CD60; (* #52576 *) 469 | _CTRL_ALT_1_NumPad = $CD61; (* #52577 *) 470 | _CTRL_ALT_2_NumPad = $CD62; (* #52578 *) 471 | _CTRL_ALT_3_NumPad = $CD63; (* #52579 *) 472 | _CTRL_ALT_4_NumPad = $CD64; (* #52580 *) 473 | _CTRL_ALT_5_NumPad = $CD65; (* #52581 *) 474 | _CTRL_ALT_6_NumPad = $CD66; (* #52582 *) 475 | _CTRL_ALT_7_NumPad = $CD67; (* #52583 *) 476 | _CTRL_ALT_8_NumPad = $CD68; (* #52584 *) 477 | _CTRL_ALT_9_NumPad = $CD69; (* #52585 *) 478 | _CTRL_ALT_Plus_NumPad = $CD6B; (* #52587 *) 479 | _CTRL_ALT_Minus_NumPad = $CD6D; (* #52589 *) 480 | _CTRL_ALT_Plus = $CDBB; (* #52667 *) 481 | _CTRL_ALT_Minus = $CDBD; (* #52669 *) 482 | 483 | // Ctrl (right) + AltGr = $CExx 484 | _CTRL_ALTGR_0 = $CE30; (* #52784 *) 485 | _CTRL_ALTGR_1 = $CE31; (* #52785 *) 486 | _CTRL_ALTGR_2 = $CE32; (* #52786 *) 487 | _CTRL_ALTGR_3 = $CE33; (* #52787 *) 488 | _CTRL_ALTGR_4 = $CE34; (* #52788 *) 489 | _CTRL_ALTGR_5 = $CE35; (* #52789 *) 490 | _CTRL_ALTGR_6 = $CE36; (* #52790 *) 491 | _CTRL_ALTGR_7 = $CE37; (* #52791 *) 492 | _CTRL_ALTGR_8 = $CE38; (* #52792 *) 493 | _CTRL_ALTGR_9 = $CE39; (* #52793 *) 494 | _CTRL_ALTGR_0_NumPad = $CE60; (* #52832 *) 495 | _CTRL_ALTGR_1_NumPad = $CE61; (* #52833 *) 496 | _CTRL_ALTGR_2_NumPad = $CE62; (* #52834 *) 497 | _CTRL_ALTGR_3_NumPad = $CE63; (* #52835 *) 498 | _CTRL_ALTGR_4_NumPad = $CE64; (* #52835 *) 499 | _CTRL_ALTGR_5_NumPad = $CE65; (* #52837 *) 500 | _CTRL_ALTGR_6_NumPad = $CE66; (* #52838 *) 501 | _CTRL_ALTGR_7_NumPad = $CE67; (* #52839 *) 502 | _CTRL_ALTGR_8_NumPad = $CE68; (* #52840 *) 503 | _CTRL_ALTGR_9_NumPad = $CE69; (* #52841 *) 504 | _CTRL_ALTGR_Plus_NumPad = $CE6B; (* #52843 *) 505 | _CTRL_ALTGR_Minus_NumPad = $CE6D; (* #52845 *) 506 | _CTRL_ALTGR_Plus = $CEBB; (* #52923 *) 507 | _CTRL_ALTGR_Minus = $CEBD; (* #52925 *) 508 | 509 | _Unkown = $FFFF; 510 | 511 | 512 | --------------------------------------------------------------------------------