summaryrefslogtreecommitdiff
path: root/src/ansi_terminal.adb
blob: c356c21318dff875078b05af2b92ae03f4e04e77 (plain)
1
2
3
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
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

with

    Ada.Characters.Latin_1,
    Ada.Strings.Fixed,
    Ada.Text_IO;

package body ANSI_Terminal is

    package Latin renames Ada.Characters.Latin_1;
    package IO renames Ada.Text_IO;



    function Clear_Screen
        return String is
    begin
        --  ANSI control sequence Erase in Display
        --  Variant to clear entire screen
        return Latin.ESC & "[2J";
    end Clear_Screen;

    function Reset_Cursor
        return String is
    begin
        --  ANSI control sequence Cursor Position
        --  Parameters to move cursor to top left corner
        return Latin.ESC & "[1;1H";
    end Reset_Cursor;

    procedure Clear_Screen is
    begin
        IO.Put (Clear_Screen);
    end Clear_Screen;

    procedure Reset_Cursor is
    begin
        IO.Put (Reset_Cursor);
    end Reset_Cursor;



    function BG_Color_Code
           (Value : in Natural)
        return String
    is
        use Ada.Strings;
        use Ada.Strings.Fixed;
    begin
        --  ANSI sequence to change text background colour
        --  Total length is always 11 characters
        --  It doesn't have to be, but the consistency is important for rendering
        return Latin.ESC & "[48;5;" & Tail (Trim (Integer'Image (Value), Left), 3, '0') & "m";
    end BG_Color_Code;



    function Lookup
           (Input : in March_Cell_Grid;
            X, Y  : in Integer)
        return String
    is
        Average_Density : Natural := Integer (Quantity'Ceiling (Input (X, Y).Density / 4.0));
        Bit_Index : Positive := Integer (Input (X, Y).Index) + 1;
        Choice : Natural;
    begin
        case Average_Density is
            when  1 ..  2 => Choice := 19; --  dark blue
            when  3 ..  4 => Choice := 20; --  slightly less dark blue
            when  5 ..  6 => Choice := 21; --  slightly dark blue
            when  7 ..  8 => Choice := 12; --  blue
            when  9 .. 10 => Choice := 14; --  cyan
            when 11 .. 12 => Choice := 10; --  green
            when 13 .. 14 => Choice := 11; --  yellow
            when 15 .. 16 => Choice :=  3; --  dark yellow
            when 17 .. 18 => Choice :=  9; --  red
            when 19 .. 20 => Choice :=  1; --  dark red
            when others   => Choice :=  0; --  black
        end case;
        --  Total length should always be 12 characters
        return BG_Color_Code (Choice) & Liquid_Chars (Bit_Index);
    end Lookup;

    function Marching_Squares
           (Input : in Particle_Vector)
        return String
    is
        --  Having the grid be one bigger around the edges simplifies calculations
        Grid : March_Cell_Grid (0 .. 81, 0 .. 26);

        --  80 cols * 25 rows * 12 chars/cell + 24 linefeeds + 4 char color reset = 24028
        --  Oh yeah, baby, big strings
        Output : String (1 .. 24028);

        X, Y, S : Integer;
    begin
        for P of Input loop
            X := Integer (Plane.Re (P.Place) - 0.5);
            Y := Integer (Plane.Im (P.Place) / 2.0 - 0.5);
            if X >= 0 and X <= 80 and Y >= 0 and Y <= 25 then
                for J in Integer range 0 .. 1 loop
                    for I in Integer range 0 .. 1 loop
                        Grid (X + I, Y + J).Index :=
                            Grid (X + I, Y + J).Index or (2 ** (I + 2 * J));
                        Grid (X + I, Y + J).Density :=
                            Grid (X + I, Y + J).Density + P.Density;
                    end loop;
                end loop;
            end if;
        end loop;
        for J in Integer range 1 .. 25 loop
            for I in Integer range 1 .. 80 loop
                S := (J - 1) * 961 + (I - 1) * 12 + 1;
                Output (S .. S + 11) := Lookup (Grid, I, J);
            end loop;
            Output (J * 961) := Latin.LF;
        end loop;
        Output (24025 .. 24028) := Latin.ESC & "[0m";
        return Output;
    end Marching_Squares;

end ANSI_Terminal;