source: trunk/tools/neercs/term/term.cpp @ 2587

Last change on this file since 2587 was 2587, checked in by sam, 8 years ago

base: roll our own constants because it’s always a pain in the ass
to get M_PI from the platform headers and cast it to float.

File size: 7.8 KB
Line 
1//
2// Neercs
3//
4
5#if defined HAVE_CONFIG_H
6#   include "config.h"
7#endif
8
9#include "core.h"
10
11using namespace std;
12using namespace lol;
13
14#include "../neercs.h"
15#include "term.h"
16
17extern bool g_setup;
18
19Term::Term(ivec2 size)
20  : m_pty(0),
21    m_caca(caca_create_canvas(size.x, size.y)),
22    m_size(size),
23    m_title(0),
24    m_bell(0),
25    m_init(0),
26    m_report_mouse(0),
27    m_changed(0),
28    m_time(0.f),
29    m_debug(false)
30{
31#if defined HAVE_PTY_H || defined HAVE_UTIL_H || defined HAVE_LIBUTIL_H
32    m_pty = new Pty();
33    char const *shell = getenv("SHELL");
34    if (!shell)
35        shell = "/bin/sh";
36    m_pty->Run(shell, size);
37#endif
38}
39
40void Term::TickGame(float seconds)
41{
42    Entity::TickGame(seconds);
43
44#if defined HAVE_PTY_H || defined HAVE_UTIL_H || defined HAVE_LIBUTIL_H
45    if (!g_setup)
46    {
47        bool have_ctrl = Input::GetStatus(Key::LeftCtrl)
48                          || Input::GetStatus(Key::RightCtrl);
49        bool have_shift = Input::GetStatus(Key::LeftShift)
50                           || Input::GetStatus(Key::RightShift);
51
52        /* Check for standard ASCII keys */
53        for (int i = 0x0; i < 0x7f; ++i)
54        {
55            if (Input::WasPressed((Key::Value)i))
56            {
57                if (have_ctrl && i >= 'a' && i <= 'z')
58                {
59                    char c = i + 1 - 'a';
60                    m_pty->WriteData(&c, 1);
61                }
62                else if (have_shift && i >= 'a' && i <= 'z')
63                {
64                    char c = i + 'A' - 'a';
65                    m_pty->WriteData(&c, 1);
66                }
67                else
68                {
69                    char c = i;
70                    m_pty->WriteData(&c, 1);
71                }
72            }
73        }
74
75        /* Check for special keys */
76        static struct { Key::Value k; char const *str; int len; } const lut[] =
77        {
78            { Key::Up, "\033OA", 3 },
79            { Key::Down, "\033OB", 3 },
80            { Key::Right, "\033OC", 3 },
81            { Key::Left, "\033OD", 3 },
82            { Key::PageUp, "\033[5~", 4 },
83            { Key::PageDown, "\033[6~", 4 },
84            { Key::Home, "\033[1~", 4 },
85            { Key::Insert, "\033[2~", 4 },
86            { Key::Delete, "\033[3~", 4 },
87            { Key::End, "\033[4~", 4 },
88#if 0 /* FIXME: disabled for now (used by the theme system */
89            { Key::F1, "\033[11~", 5 },
90            { Key::F2, "\033[12~", 5 },
91            { Key::F3, "\033[13~", 5 },
92            { Key::F4, "\033[14~", 5 },
93            { Key::F5, "\033[15~", 5 },
94            { Key::F6, "\033[17~", 5 },
95            { Key::F7, "\033[18~", 5 },
96            { Key::F8, "\033[19~", 5 },
97            { Key::F9, "\033[20~", 5 },
98            { Key::F10, "\033[21~", 5 },
99            { Key::F11, "\033[23~", 5 },
100            { Key::F12, "\033[24~", 5 },
101#endif
102        };
103
104        for (size_t i = 0; i < sizeof(lut) / sizeof(*lut); i++)
105        {
106            if (!have_ctrl && !have_shift)
107                if (Input::WasPressed(lut[i].k))
108                    m_pty->WriteData(lut[i].str, lut[i].len);
109        }
110    }
111
112    m_time += seconds;
113
114    if (m_pty->IsEof())
115    {
116        /* FIXME: we could do more interesting things here… */
117        Ticker::Shutdown();
118    }
119
120    m_pty->SetWindowSize(ivec2(caca_get_canvas_width(m_caca),
121                               caca_get_canvas_height(m_caca)));
122
123    /* This is the real terminal code */
124    size_t total = 0;
125    for (;;)
126    {
127        char buf[BUFSIZ];
128        size_t current = m_pty->ReadData(buf, BUFSIZ);
129        if (current <= 0)
130            break;
131        /* FIXME: by the time we're finished decoding the ANSI data, some
132         * new data may be available. We need to avoid reading it because
133         * it's time rendering the canvas isntead. */
134        size_t processed = ReadAnsi(buf, current);
135        if (processed < current)
136            m_pty->UnreadData(buf + processed, current - processed);
137        total += processed;
138        if (processed == 0)
139            break;
140
141        /* FIXME: when do we know when to stop? If we read too much
142         * data, some of our frames will not be rendered because they'll
143         * be overwritten by new data. If we don't read enough, we will
144         * start rendering even if a frame isn't finished. */
145        if (total > 12000)
146            break;
147    }
148
149    /* Some fancy shit if we press F3 */
150    if (Input::WasPressed(Key::F3))
151        m_debug = !m_debug;
152
153    if (m_debug)
154    {
155        DrawFancyShit();
156    }
157#else
158    /* Unsupported platform - draw some fancy shit instead */
159    m_time += seconds;
160    DrawFancyShit();
161#endif
162}
163
164void Term::TickDraw(float seconds)
165{
166    Entity::TickDraw(seconds);
167}
168
169Term::~Term()
170{
171#if defined HAVE_PTY_H || defined HAVE_UTIL_H || defined HAVE_LIBUTIL_H
172    delete m_pty;
173#endif
174    caca_free_canvas(m_caca);
175}
176
177/*
178 * XXX: fancy shit below
179 */
180
181static uint32_t hex_color(float r, float g, float b)
182{
183    return ((uint32_t)(r * 15.99f) << 8) |
184           ((uint32_t)(g * 15.99f) << 4) |
185           (uint32_t)(b * 15.99f);
186}
187
188void Term::DrawFancyShit()
189{
190    /* draw something awesome */
191    int bg_color = 0x000;
192    int w = caca_get_canvas_width(m_caca);
193    int h = caca_get_canvas_height(m_caca);
194
195    caca_set_color_argb(m_caca, 0xfff, bg_color);
196    caca_clear_canvas(m_caca);
197
198    caca_set_color_argb(m_caca, 0x0f0, bg_color);
199    for(int i = 0; i < h; i++)
200    {
201        float a = F_PI / 180 * i * 16 + m_time * 4;
202        float b = F_PI / 180 * i * 12;
203        int x = w / 2  - 14 + w / 4 * lol::cos(a) + w / 4 * lol::sin(b);
204        caca_put_str(m_caca, x, i, "LOL WUT! NEERCS SI TEH RULEZ");
205    }
206
207    caca_set_color_argb(m_caca, 0x444, bg_color);
208    for(int i = 0; i < w; i++)
209    {
210        float a = m_time * 1 + F_PI / 180 * i * 8;
211        float b = m_time * -2 + F_PI / 180 * i * 5;
212        int y = h / 2 + h / 4 * lol::cos(a) + h / 4 * lol::sin(b);
213        caca_set_color_argb(m_caca, hex_color(0.25f + 0.5f / w * i - 0.25f / h * y, 0.25f, 0.25f + 0.25f / w * i + 0.25f / h * y), bg_color);
214        caca_draw_line(m_caca, i, y - 1, i, y + 1,'%');
215    }
216
217/* __  _________ ______ ______ ______ ______
218  /  \/  /  __  >  __  >  __  >  ___//  ___/ \x0a9
219 /      /  ____/  ____/  __  <  <____\___  \
220/__/\__/\_______________/  \________________\ */
221
222    int logo_x = (w - 46) / 2;
223    int logo_y = h / 2 - 2;
224
225    caca_set_color_argb(m_caca, 0xbac, bg_color);
226    caca_put_str(m_caca, logo_x + 3, logo_y    ,"__  _________ ______ ______ ______ ______");
227    caca_put_str(m_caca, logo_x + 2, logo_y + 1, "/  \\/  /  __  >  __  >  __  >  ___//  ___/ \x0a9");
228    caca_put_str(m_caca, logo_x + 1, logo_y + 2, "/      /  ____/  ____/  __  <  <____\\___  \\");
229    caca_put_str(m_caca, logo_x    , logo_y + 3, "/__/\\__/\\_______________/  \\________________\\");
230    caca_set_color_argb(m_caca, 0x269, bg_color);
231    caca_put_str(m_caca, logo_x + 5, logo_y + 5, "ALL YOUR TERMINALS ARE BELONG TO US");
232
233    caca_set_color_argb(m_caca, 0x777, bg_color);
234    caca_printf(m_caca, 2, h - 3, "W=%i", w);
235    caca_printf(m_caca, 2, h - 2, "H=%i", h);
236
237    caca_set_color_argb(m_caca, hex_color(0.6f + 0.4f * lol::cos(m_time * 2), 0.2f, 0.2f), bg_color);
238    caca_put_str(m_caca, w - 12, h - 2, "CACA RULEZ");
239
240/*_______
241 /      /|
242/______/ |
243|      | |
244|  :D  | /
245|______|/
246*/
247/*
248    int lolcube_x = w - 12;
249    int lolcube_y = h - 8;
250
251    caca_set_color_argb(m_caca, 0x777, bg_color);
252    caca_put_str(m_caca, lolcube_x + 2, lolcube_y    , "_______");
253    caca_put_str(m_caca, lolcube_x + 1, lolcube_y + 1, "/      /|");
254    caca_put_str(m_caca, lolcube_x    , lolcube_y + 2, "/______/ |");
255    caca_put_str(m_caca, lolcube_x    , lolcube_y + 3, "|      | |");
256    caca_put_str(m_caca, lolcube_x    , lolcube_y + 4, "|  :D  | /");
257    caca_put_str(m_caca, lolcube_x    , lolcube_y + 5, "|______|/");
258*/
259
260    caca_set_color_argb(m_caca, 0x777, bg_color);
261    caca_put_str(m_caca, 0, 0, "rez@lol:~/code/neercs/");
262}
Note: See TracBrowser for help on using the repository browser.