aboutsummaryrefslogtreecommitdiff
path: root/src/ansi_terminal.adb
blob: 8e47d0613a7827b54e51243bfa0a02d0fcf920a7 (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
124
125
126
127
128
129
130
131
132
133
134


--  Programmed by Jedidiah Barber
--  Licensed under the Sunset License v1.0

--  See license.txt for further details


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 : constant Natural :=
            Integer (Quantity'Ceiling (Input (X, Y).Density / 4.0));
        Bit_Index : constant 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;