]> git.saurik.com Git - cycript.git/blame - Display.cpp
Highlight NULL, YES, and NO identifiers as constants.
[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
43const char *CYDisplayPrompt() {
44#if RL_READLINE_VERSION >= 0x0600
45 return rl_display_prompt;
46#else
47 return rl_prompt;
48#endif
49}
50
51unsigned CYDisplayWidth() {
52 struct winsize info;
53 if (ioctl(1, TIOCGWINSZ, &info) != -1)
54 return info.ws_col;
55 return tgetnum(const_cast<char *>("co"));
56}
57
58void CYDisplayOutput_(int (*put)(int), const char *&data) {
59 for (;; ++data) {
60 char next(*data);
61 if (next == '\0' || next == CYIgnoreEnd)
62 return;
63 if (put != NULL)
64 put(next);
65 }
66}
67
68CYCursor CYDisplayOutput(int (*put)(int), int width, const char *data, ssize_t offset = 0) {
69 CYCursor point(current_);
70
71 for (;;) {
72 if (offset-- == 0)
73 point = current_;
74
75 char next(*data++);
76 switch (next) {
77 case '\0':
78 return point;
79 break;
80
81 case CYIgnoreStart:
82 CYDisplayOutput_(put, data);
83 ++offset;
84 break;
85
86 case CYIgnoreEnd:
87 ++offset;
88 break;
89
90 default:
91 if (put != NULL)
92 put(next);
93
94 current_ += CYCursor(0, 1);
95 if (current_.imag() == width)
96 current_ = CYCursor(current_.real() + 1, 0);
97 break;
98 }
99 }
100
101 return point;
102}
103
104void CYDisplayMove(CYCursor target) {
105 int offset(target.real() - current_.real());
106
107 if (offset < 0)
108 putp(tparm(parm_up_cursor, -offset));
109 else if (offset > 0)
110 putp(tparm(parm_down_cursor, offset));
111
112 putp(tparm(column_address, target.imag()));
113 current_ = target;
114}
115
116void CYDisplayStart(int meta) {
117 rl_prep_terminal(meta);
118 current_ = CYCursor();
119}
120
121void CYDisplayUpdate() {
122 std::ostringstream stream;
123 CYLexerHighlight(rl_line_buffer, rl_end, stream, true);
124 std::string string(stream.str());
125 const char *buffer(string.c_str());
126
127 int width(CYDisplayWidth());
128 if (width_ != width) {
129 current_ = CYCursor();
130 CYDisplayOutput(NULL, width, CYDisplayPrompt());
131 CYDisplayOutput(NULL, width, buffer, point_);
132 }
133
134 CYDisplayMove(CYCursor());
135 CYDisplayOutput(putchar, width, CYDisplayPrompt());
136
137 CYCursor target(CYDisplayOutput(putchar, width, stream.str().c_str(), rl_point));
138 if (target.imag() == 0)
139 putp(cursor_down);
140
141 putp(clr_eos);
142 CYDisplayMove(target);
143
144 fflush(stdout);
145
146 width_ = width;
147 point_ = rl_point;
148}
149
150void CYDisplayFinish() {
151 rl_deprep_terminal();
152}