]> git.saurik.com Git - cycript.git/blame - Display.cpp
Work around missing column_address with left/right.
[cycript.git] / Display.cpp
CommitLineData
74296173
JF
1/* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2012 Jay Freeman (saurik)
3*/
4
5/* GNU Lesser General Public License, Version 3 {{{ */
6/*
7 * Cycript is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU Lesser General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * Cycript is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with Cycript. If not, see <http://www.gnu.org/licenses/>.
19**/
20/* }}} */
21
22#include <complex>
23#include <sstream>
24
25#ifdef HAVE_READLINE_H
26#include <readline.h>
27#else
28#include <readline/readline.h>
29#endif
30
31#include <sys/ioctl.h>
32
33#include "Highlight.hpp"
34
35#include <term.h>
36
37typedef std::complex<int> CYCursor;
38
39CYCursor current_;
40int width_;
41size_t point_;
42
74296173
JF
43unsigned CYDisplayWidth() {
44 struct winsize info;
45 if (ioctl(1, TIOCGWINSZ, &info) != -1)
46 return info.ws_col;
47 return tgetnum(const_cast<char *>("co"));
48}
49
50void CYDisplayOutput_(int (*put)(int), const char *&data) {
51 for (;; ++data) {
52 char next(*data);
53 if (next == '\0' || next == CYIgnoreEnd)
54 return;
55 if (put != NULL)
56 put(next);
57 }
58}
59
60CYCursor CYDisplayOutput(int (*put)(int), int width, const char *data, ssize_t offset = 0) {
61 CYCursor point(current_);
62
63 for (;;) {
64 if (offset-- == 0)
65 point = current_;
66
67 char next(*data++);
68 switch (next) {
69 case '\0':
70 return point;
71 break;
72
73 case CYIgnoreStart:
74 CYDisplayOutput_(put, data);
75 ++offset;
76 break;
77
78 case CYIgnoreEnd:
79 ++offset;
80 break;
81
82 default:
74296173
JF
83 current_ += CYCursor(0, 1);
84 if (current_.imag() == width)
dd059029 85 case '\n':
74296173 86 current_ = CYCursor(current_.real() + 1, 0);
dd059029
JF
87 if (put != NULL)
88 put(next);
74296173 89 break;
dd059029 90
74296173
JF
91 }
92 }
93
94 return point;
95}
96
66abbf4d 97void CYDisplayMove_(char *negative, char *positive, int offset) {
74296173 98 if (offset < 0)
66abbf4d 99 putp(tparm(negative, -offset));
74296173 100 else if (offset > 0)
66abbf4d
JF
101 putp(tparm(positive, offset));
102}
103
104void CYDisplayMove(CYCursor target) {
105 CYCursor offset(target - current_);
106
107 CYDisplayMove_(parm_up_cursor, parm_down_cursor, offset.real());
108
109 if (char *parm = tparm(column_address, target.imag()))
110 putp(parm);
111 else
112 CYDisplayMove_(parm_left_cursor, parm_right_cursor, offset.imag());
74296173 113
74296173
JF
114 current_ = target;
115}
116
117void CYDisplayStart(int meta) {
118 rl_prep_terminal(meta);
119 current_ = CYCursor();
120}
121
122void CYDisplayUpdate() {
7128e55c
JF
123#if RL_READLINE_VERSION >= 0x0600
124 const char *prompt(rl_display_prompt);
125#else
126 const char *prompt(rl_prompt);
127#endif
128
74296173
JF
129 std::ostringstream stream;
130 CYLexerHighlight(rl_line_buffer, rl_end, stream, true);
131 std::string string(stream.str());
132 const char *buffer(string.c_str());
133
134 int width(CYDisplayWidth());
135 if (width_ != width) {
136 current_ = CYCursor();
7128e55c 137 CYDisplayOutput(NULL, width, prompt);
c584b893 138 current_ = CYDisplayOutput(NULL, width, buffer, point_);
74296173
JF
139 }
140
141 CYDisplayMove(CYCursor());
7128e55c 142 CYDisplayOutput(putchar, width, prompt);
74296173
JF
143
144 CYCursor target(CYDisplayOutput(putchar, width, stream.str().c_str(), rl_point));
145 if (target.imag() == 0)
146 putp(cursor_down);
147
148 putp(clr_eos);
149 CYDisplayMove(target);
150
151 fflush(stdout);
152
153 width_ = width;
154 point_ = rl_point;
155}
156
157void CYDisplayFinish() {
158 rl_deprep_terminal();
159}