diff --git a/.gitignore b/.gitignore index 661f1f8..9c1e01d 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ old # DEBUGGING # gmem.out Makefile +github diff --git a/CHANGELOG.md b/CHANGELOG.md index f2e58a2..b1be7d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,18 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [0.0.3] - +## [0.0.3] - 2020-12-06 ### Added -- Added documentation to all parts of the Ansi package. +- Added documentation to all parts of the Ansi package except IO package. - Added Signal and Input handling. +- Finished implementing surfaces, colours and styles. +- Added support for the non-ansi-compliant windows console CMD, to support older versions of Windows. +- Finished some things marked to do. ### Fixed - Fixed the format of this changelog. - Fixed Put(3) procedure in Ansi.Surfaces and added style printing too. - Fixed native support for older Windows consoles. +- Fixed some bugs and errors found while coding. ### Removed - Removed the inlining of many of the functions and procedures throughout the package. +- Removed Ansi.Pools, it will be available in a future. ## [0.0.2] - 2020-11-21 diff --git a/TODO b/TODO index 5fc7864..469e8f3 100644 --- a/TODO +++ b/TODO @@ -13,3 +13,4 @@ * TODO TODO comments. * Update styles in the Put function of Ansi.Surfaces * Recheck implementations. + * Finish Windows part diff --git a/src/ansi-compliance.ads b/src/ansi-compliance.ads index 5cf25d0..5c7edce 100644 --- a/src/ansi-compliance.ads +++ b/src/ansi-compliance.ads @@ -127,6 +127,27 @@ private package Ansi.Compliance is -- STYLE OPERATIONS -- ---------------------- -- This part declares the styling procedures. + + -- + -- This function returns the code to put a style in standard output without + -- the trailing `ESC[' and the `m'. + -- + -- @param Style + -- The style to generate. + -- + -- @param Remove + -- If this parameter is set to true, it will return the code to remove the + -- given style. + -- + -- @return + -- The code to put the given style, in Windows it returns a null string, + -- though. + -- + function Gen_Style (Style : Style_Type; + Remove: Boolean := False) + return Str_Type; + pragma Inline (Gen_Style); + pragma Pure_Function (Gen_Style); -- -- This procedure is used to set an array of styles into standard output. @@ -235,7 +256,7 @@ private package Ansi.Compliance is -- This procedure moves the position of the cursor up. In windows it uses -- the Set_Position function if it's non-ansi-compliant. -- - -- @param Rows + -- @param Cols -- The number of rows to move up. -- procedure Move_Right (Cols: Positive := 1); @@ -245,7 +266,7 @@ private package Ansi.Compliance is -- This procedure moves the position of the cursor up. In windows it uses -- the Set_Position function if it's non-ansi-compliant. -- - -- @param Rows + -- @param Cols -- The number of rows to move up. -- procedure Move_Left (Cols: Positive := 1); diff --git a/src/ansi-pools.ads b/src/ansi-pools.ads deleted file mode 100644 index c2f0955..0000000 --- a/src/ansi-pools.ads +++ /dev/null @@ -1,39 +0,0 @@ -------------------------------------------------------------------------------- --- -- --- A N S I - P O O L S . A D S -- --- -- --- A D A T Y P E R -- --- -- --- S P E C -- --- -- -------------------------------------------------------------------------------- --- Copyright (c) 2020 José Antonio Verde Jiménez All Rights Reserved -- -------------------------------------------------------------------------------- --- This file is part of adatyper. -- --- -- --- This program is free software: you can redistribute it and/or modify it -- --- under the terms of the GNU General License as published by the Free -- --- Software Foundation, either version 3 of the License, or (at your -- --- opinion) any later version. -- --- -- --- This program is distributed in the hope that it will be useful, but -- --- WITHOUT ANY WARRANTY; without even the implied warranty of -- --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -- --- Public License for more details. -- --- -- --- You should have received a copy of the GNU General Public License along -- --- with this program. If not, see . -- --- -- -------------------------------------------------------------------------------- - - --- This package contains pools to work with allocations and deallocations. -package Ansi.Pools is - - -end Ansi.Pools; - - ----=======================-------------------------=========================--- ---=======================-- E N D O F F I L E --=========================-- ----=======================-------------------------=========================--- diff --git a/src/ansi-styles.adb b/src/ansi-styles.adb index 02dc146..46830ee 100644 --- a/src/ansi-styles.adb +++ b/src/ansi-styles.adb @@ -38,6 +38,18 @@ package body Ansi.Styles is -- SURFACE OPERATIONS -- ------------------------ + function Gen_Style (Style : Style_Type; + Remove: Boolean := False) + return Str_Type is + begin + + return Ansi.Compliance.Gen_Style(Style => Style, + Remove => Remove); + + end Gen_Style; + + + procedure Get_Style (Surface: in not null Surface_Type; Styles : out Style_Array; Row : Row_Type; diff --git a/src/ansi-styles.ads b/src/ansi-styles.ads index 1825715..199f67e 100644 --- a/src/ansi-styles.ads +++ b/src/ansi-styles.ads @@ -42,6 +42,26 @@ package Ansi.Styles is -- SURFACE OPERATIONS -- ------------------------ + -- + -- This function returns the code used to put a style in a two byte string, + -- for example to put it bright its: ESC[1m, then it returns "_1" (The + -- underscore is a null byte. In windows it returns a null string. + -- + -- @param Style + -- The style to put. + -- + -- @param Remove + -- If true it returns the code to remove the style. + -- + -- @return + -- The string to put to get such style. + -- + function Gen_Style (Style : Style_Type; + Remove: Boolean := False) + return Str_Type; + pragma Inline (Gen_Style); + pragma Pure_Function (Gen_Style); + -- -- This procedure returns the style in a certain position of the surface. -- diff --git a/src/ansi-surfaces.adb b/src/ansi-surfaces.adb index bf8490b..e4a65ec 100644 --- a/src/ansi-surfaces.adb +++ b/src/ansi-surfaces.adb @@ -31,7 +31,7 @@ with Ansi.Compliance; with Ansi.Colors; with Ansi.Cursors; with Ansi.Exceptions; --- with Ansi.Styles; +with Ansi.Styles; with Ansi.Text_IO; -- with Debug; use Debug; -- DEBUGING @@ -241,8 +241,6 @@ package body Ansi.Surfaces is others => NUL); -- This type is used to store changes. - Fg_Changes: Boolean := False; - Bg_Changes: Boolean := False; Changes : Boolean := False; -- This is the memory chunk. @@ -271,6 +269,7 @@ package body Ansi.Surfaces is procedure Compare_Item is + I: Positive := 10; begin -- We check which parts of the format have changed. -- First the foreground colour; the colour and the brightness come in @@ -291,10 +290,42 @@ package body Ansi.Surfaces is Buffer(5) := ';'; end if; - Fg_Changes := True; Changes := True; end if; - -- TODO: Add styles. elsif ... + + if Item.Fmt.Bg_Color /= Last_Fmt.Bg_Color or else + Item.Fmt.Bg_Bright /= Last_Fmt.Bg_Bright + then + -- We update the new Last_Fmt + Last_Fmt.Bg_Color := Item.Fmt.Bg_Color; + Last_Fmt.Bg_Bright := Item.Fmt.Bg_Bright; + + -- We add it to the buffer if it is Ansi-Compliant. + if Ansi.Compliance.Is_Ansi_Compliant then + Buffer(6 .. 8) := Ansi.Colors.Gen_Background( + Color => Last_Fmt.Bg_Color, + Bright => Last_Fmt.Bg_Bright); + Buffer(9) := ';'; + end if; + + Changes := True; + end if; + + if Item.Fmt.Style /= Last_Fmt.Style then + for S in Style_Type'Range loop + if Item.Fmt.Style(S) /= Last_Fmt.Style(S) then + Last_Fmt.Style(S) := Item.Fmt.Style(S); + if Ansi.Compliance.Is_Ansi_Compliant then + Buffer(I .. I + 1) := Ansi.Styles.Gen_Style + (Style => S, + Remove => not Last_Fmt.Style(S)); + Buffer(I + 2) := ';'; + end if; + end if; + I := I + 3; + end loop; + Changes := True; + end if; end Compare_Item; procedure Update_Changes is @@ -302,18 +333,26 @@ package body Ansi.Surfaces is -- We then check if there has been any changes, if so we print -- the escape sequence and set it back to 0. if Changes and Ansi.Compliance.Is_Ansi_Compliant then - -- We remove the last colomn. - if Bg_Changes then - Buffer(9) := NUL; - elsif Fg_Changes then - Buffer(5) := NUL; - end if; - - Changes := False; - Bg_Changes := False; - Fg_Changes := False; + -- We remove the last colon. + for I in reverse Buffer'Range loop + if Buffer(I) = ';' then + Buffer(I) := NUL; + exit; + end if; + end loop; Push(Buffer & Item.Char); + Changes := False; +-- DEBUG: +-- Debug_Scope_Put: +-- declare +-- Data: String(Buffer'First + 1 .. Buffer'Last); +-- begin +-- for K in Positive range Buffer'First + 1 .. Buffer'Last loop +-- Data(K) := Character'Val(Char_Type'Pos(Buffer(K))); +-- end loop; +-- BREAKPOINT(Data, 3, True); +-- end Debug_Scope_Put; -- We finally default some parts of the buffer, to make it -- easier for the terminal emulator not to have so many @@ -338,8 +377,6 @@ package body Ansi.Surfaces is Next: Operation; begin - -- TODO: Add styles - -- We wait for the Update lock to be lifted. while Lock loop null; @@ -348,6 +385,8 @@ package body Ansi.Surfaces is -- We lock the main surface. Lock := True; + Ansi.Compliance.Clear_Format; + -- We first see two possible scenaries, the first one is a screen that is -- completely when the Update_All attribute is set to true. The second -- one is to check the stack for any possible changes. @@ -383,7 +422,14 @@ package body Ansi.Surfaces is -- We then print the last buffer. Pop; -- And we finally remove log of applied changes to the surface. - -- TODO: Free stack + while Node /= null loop + Next := Node.Next; + Ansi.Cursors.Free(Node.Cursor); + Free(Node); + Node := Next; + end loop; + Surface.Head := null; + Surface.Tail := null; Surface.Update_All := False; else @@ -426,6 +472,9 @@ package body Ansi.Surfaces is -- We unlock the Main_Surface. Lock := False; + -- We clear the format. + Ansi.Compliance.Clear_Format; + end Put; @@ -434,16 +483,23 @@ package body Ansi.Surfaces is Col : Col_Type; Length : Positive) return Str_Type is + Str: Str_Type(1 .. Length); begin - if Positive(Row) = Positive(Col) then - return "TODO"; - elsif Positive(Surface.Width) = Length then - return "TODO"; - else - return "TODO"; + if Row > Surface.Height or + Col > Surface.Width or + Col + Col_Type(Length) - 1 > Surface.Width + then + raise Ansi.Exceptions.Out_Of_Bounds_Issue + with "Couldn't fit the string in the surface!"; end if; + for I in Str'Range loop + Str(I) := Surface.Grid(Row, Col + Col_Type(I) - 1).Char; + end loop; + + return Str; + end Read; @@ -1005,22 +1061,64 @@ package body Ansi.Surfaces is end Get_Visibility; + procedure Move_Layer (Layerer: Layerer_Type; - From : Positive; + Layer : Surface_Type; To : Positive) is + Temp_Layer: Surface_Type; begin - null; -- TODO + if To > Layerer.Size then + raise Ansi.Exceptions.Out_Of_Bounds_Issue + with "The destination position is out of bounds!"; + end if; + + for I in Positive range 1 .. Layerer.Size loop + if Layerer.Layers(I) = Layer then + Temp_Layer := Layerer.Layers(I); + if To > I then + for K in Positive range I .. To - 1 loop + Layerer.Layers(K) := Layerer.Layers(K + 1); + end loop; + elsif To < I then + for K in reverse Positive range To + 1 .. I loop + Layerer.Layers(K) := Layerer.Layers(K - 1); + end loop; + end if; + Layerer.Layers(To) := Temp_Layer; + return; + end if; + end loop; + + raise Ansi.Exceptions.Unknown_Layer_Issue + with "The layer to be hidden isn't in the layerer!"; end Move_Layer; procedure Move_Layer (Layerer: Layerer_Type; - Layer : Surface_Type; + From : Positive; To : Positive) is + Temp_Layer: Surface_Type; begin - null; -- TODO + if To > Layerer.Size or From > Layerer.Size then + raise Ansi.Exceptions.Out_Of_Bounds_Issue + with "Either the `From', the `To' or both Positions are out of the " & + "layerer bounds!"; + end if; + + Temp_Layer := Layerer.Layers(From); + if To > From then + for K in Positive range From .. To - 1 loop + Layerer.Layers(K) := Layerer.Layers(K + 1); + end loop; + elsif To < From then + for K in reverse Positive range To + 1 .. From loop + Layerer.Layers(K) := Layerer.Layers(K - 1); + end loop; + end if; + Layerer.Layers(To) := Temp_Layer; end Move_Layer; diff --git a/src/ansi.adb b/src/ansi.adb index 5799a81..fdca87f 100644 --- a/src/ansi.adb +++ b/src/ansi.adb @@ -130,9 +130,10 @@ package body Ansi is begin Ansi.Os_Utils.Clean_Up; - Main_Cursor.Set_Position(Height - 1, Width - 1); Ansi.Compliance.Clear_Format; + Main_Cursor.Set_Position(Height - 1, Width - 1); -- TODO: Use the language and the Ansi.Text_IO packages in the future. + Ada.Text_IO.New_Line; Ada.Text_IO.Put("Press any key to continue..."); Ada.Text_IO.Get_Immediate(Tmp); diff --git a/src/posix/ansi-compliant/ansi-compliance.adb b/src/posix/ansi-compliant/ansi-compliance.adb index 3d86c5f..7f66ef8 100644 --- a/src/posix/ansi-compliant/ansi-compliance.adb +++ b/src/posix/ansi-compliant/ansi-compliance.adb @@ -45,11 +45,8 @@ package body Ansi.Compliance is return Str_Type is begin - return (if Bright then - '9' - else - '3' - ) & Char_Type'Val(ZERO + Color'Enum_Rep); + return (if Bright then '9' + else '3') & Char_Type'Val(ZERO + Color'Enum_Rep); end Gen_Foreground; @@ -59,10 +56,9 @@ package body Ansi.Compliance is return Str_Type is begin - return (if Bright then - "10" - else - "4") & Char_Type'Val(ZERO + Color'Enum_Rep); + return (if Bright then "10" + else Char_Type'Val(0) &"4") & + Char_Type'Val(ZERO + Color'Enum_Rep); end Gen_Background; @@ -86,10 +82,33 @@ package body Ansi.Compliance is end Put_Background; + ---------------------- -- STYLE OPERATIONS -- ---------------------- + function Gen_Style (Style : Style_Type; + Remove: Boolean := False) + return Str_Type is + begin + + case Remove is + when True => + case Style is + when Bright | Dim => + return "22"; + when others => + return '2' & Char_Type'Val(Style'Enum_Rep + ZERO); + end case; + + when others => + return Char_Type'Val(0) & Char_Type'Val(Style'Enum_Rep + ZERO); + + end case; + + end Gen_Style; + + procedure Put_Style (Styles: Style_Array) is -- The sequence is stored in an array like this one: -- ESC[<>;<>;<>m @@ -106,10 +125,9 @@ package body Ansi.Compliance is Sequence(Size) := 'm'; for S in Styles'Range loop - Sequence(Pointer + 1) := Char_Type'Val(S'Enum_Rep + ZERO); - if not Styles(S) then - Sequence(Pointer) := '2'; - end if; + Sequence(Pointer .. Pointer + 1) := Gen_Style + (Style => S, + Remove => not Styles(S)); Pointer := Pointer + 3; end loop; @@ -144,7 +162,7 @@ package body Ansi.Compliance is procedure Clear_Format is begin - Ansi.Text_IO.Put_Ansi_Sequence(ESC & "[0m"); + Ansi.Text_IO.Put_Ansi_Sequence(ESC & "0m"); end Clear_Format; diff --git a/src/title.adb b/src/title.adb index 621e490..d622373 100644 --- a/src/title.adb +++ b/src/title.adb @@ -98,8 +98,13 @@ begin Ansi.Colors.Set_Foreground(Letter_Small_r, Ansi.Red, True); Ansi.Colors.Set_Foreground(Letter_Cursor , Ansi.White, True); - -- We change some styles. - Ansi.Styles.Set_Style(Letter_Big_A, Ansi.Reversed); + Ansi.Colors.Set_Background(Letter_Small_d, Ansi.Red, False); + Ansi.Styles.Set_Style( Letter_Big_A, Ansi.Bright); + Ansi.Styles.Set_Style(Letter_Small_d, Ansi.Dim); + Ansi.Styles.Set_Style(Letter_Small_a, Ansi.Italics); + Ansi.Styles.Set_Style( Letter_Big_T, Ansi.Underlined); + Ansi.Styles.Set_Style(Letter_Small_y, Ansi.Slow_Blink); + Ansi.Styles.Set_Style(Letter_Small_p, Ansi.Reversed); -- We add them to the letterer. Letterer.Add( Letter_Big_A); diff --git a/src/windows/non-ansi-compliant/ansi-compliance.adb b/src/windows/non-ansi-compliant/ansi-compliance.adb index 9afd9af..cb5346b 100644 --- a/src/windows/non-ansi-compliant/ansi-compliance.adb +++ b/src/windows/non-ansi-compliant/ansi-compliance.adb @@ -151,6 +151,20 @@ package body Ansi.Compliance is -- STYLE OPERATIONS -- ---------------------- + function Gen_Style (Style : Style_Type; + Remove: Boolean := False) + return Str_Type is + begin + + Last_Format.Style(Style) := Remove; + + Set_Windows_Console_Color_With_Attributes; + + return ""; + + end Gen_Style; + + procedure Put_Style (Styles: Style_Array) is begin