summaryrefslogtreecommitdiffstats
path: root/src/vt52_curses.hh
blob: 88c3cb36a57d9becc833a06768aa7a14440154aa (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/**
 * Copyright (c) 2007-2012, Timothy Stack
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * * Neither the name of Timothy Stack nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @file vt52_curses.hh
 */

#ifndef vt52_curses_hh
#define vt52_curses_hh

#include <list>
#include <string>

#include "view_curses.hh"

/**
 * VT52 emulator for curses, useful for mediating between curses and readline,
 * which don't play well together.  It is expected that a subclass of this
 * class will fork off a child process that sends and receives VT52 keycodes(?)
 * which is translated by this class into curses calls.
 *
 * VT52 seems to be the simplest terminal to emulate since we do not need to
 * maintain the state of the screen, beyond past lines.  For example, when
 * inserting a character, VT52 moves the cursor to the insertion point, clears
 * the rest of the line and then rewrites the rest of the line with the new
 * character.  This is in contrast to VT100 which moves the cursor to the
 * insertion point and then sends a code to insert the character and relying
 * on the terminal to shift the rest of the line to the right a character.
 */
class vt52_curses : public view_curses {
public:
    /** @param win The curses window this view is attached to. */
    void set_window(WINDOW* win) { this->vc_window = win; }

    /** @return The curses window this view is attached to. */
    WINDOW* get_window() { return this->vc_window; }

    void set_left(int left) { this->vc_left = left; }

    int get_left() const { return this->vc_left; }

    /**
     * Set the Y position of this view on the display.  A value greater than
     * zero is considered to be an absolute size.  A value less than zero makes
     * the position relative to the bottom of the enclosing window.
     *
     * @param y The Y position of the cursor on the curses display.
     */
    void set_y(int y) { this->vc_y = y; }

    /** @return The abs/rel Y position of the cursor on the curses display. */
    int get_y() const { return this->vc_y; }

    /** @param x The X position of the cursor on the curses display. */
    void set_x(int x) { this->vc_x = x; }

    /** @return The X position of the cursor on the curses display. */
    int get_x() const { return this->vc_x; }

    /**
     * @return The height of this view, which consists of a single line for
     * input, plus any past lines of output, which will appear ABOVE the Y
     * position for this view.
     * @todo Kinda hardwired to the way readline works.
     */
    int get_height() { return 1; }

    void set_max_height(int mh) { this->vc_max_height = mh; }
    int get_max_height() const { return this->vc_max_height; }

    /**
     * Map an ncurses input keycode to a vt52 sequence.
     *
     * @param ch The input character.
     * @param len_out The length of the returned sequence.
     * @return The vt52 sequence to send to the child.
     */
    const char* map_input(int ch, int& len_out);

    /**
     * Map VT52 output to ncurses calls.
     *
     * @param output VT52 encoded output from the child process.
     * @param len The length of the output array.
     */
    void map_output(const char* output, int len);

    /**
     * Paints any past lines and moves the cursor to the current X position.
     */
    void do_update();

    const static char ESCAPE = 27; /*< VT52 Escape key value. */
    const static char BACKSPACE = 8; /*< VT52 Backspace key value. */
    const static char BELL = 7; /*< VT52 Bell value. */
    const static char STX = 2; /*< VT52 Start-of-text value. */

protected:
    /** @return The absolute Y position of this view. */
    int get_actual_y()
    {
        unsigned long width, height;
        int retval;

        getmaxyx(this->vc_window, height, width);
        if (this->vc_y < 0) {
            retval = height + this->vc_y;
        } else {
            retval = this->vc_y;
        }

        return retval;
    }

    WINDOW* vc_window{nullptr}; /*< The window that contains this view. */
    int vc_left{0};
    int vc_x{0}; /*< The X position of the cursor. */
    int vc_y{0}; /*< The Y position of the cursor. */
    int vc_max_height{0};
    char vc_escape[16]; /*< Storage for escape sequences. */
    int vc_escape_len{0}; /*< The number of chars in vc_escape. */
    int vc_expected_escape_len{-1};
    char vc_map_buffer{0}; /*<
                            * Buffer returned by map_input for trivial
                            * translations (one-to-one).
                            */
    attr_line_t vc_line;
};

#endif