1// This file is part of SmallBASIC
2//
3// Copyright(C) 2001-2014 Chris Warren-Smith.
4//
5// This program is distributed under the terms of the GPL v2.0 or later
6// Download the GNU Public License (GPL) from www.gnu.org
7//
8
9#ifndef SCREEN_H
10#define SCREEN_H
11
12#include <config.h>
13
14#include "lib/maapi.h"
15#include "ui/strlib.h"
16#include "ui/utils.h"
17#include "ui/shape.h"
18#include "ui/image.h"
19#include "ui/inputs.h"
20
21using namespace strlib;
22
23#define LINE_SPACING 0
24#define INITXY 2
25#define NO_COLOR -1
26
27struct Screen : public Shape {
28 Screen(int x, int y, int width, int height, int fontSize);
29 virtual ~Screen();
30
31 virtual void calcTab() = 0;
32 virtual bool construct() = 0;
33 virtual void clear();
34 virtual void drawArc(int xc, int yc, double r, double start, double end, double aspect) = 0;
35 virtual void drawBase(bool vscroll, bool update=true) = 0;
36 virtual void drawEllipse(int xc, int yc, int rx, int ry, int fill) = 0;
37 virtual void drawImage(ImageDisplay &image) = 0;
38 virtual void drawInto(bool background=false);
39 virtual void drawLine(int x1, int y1, int x2, int y2) = 0;
40 virtual void drawRect(int x1, int y1, int x2, int y2) = 0;
41 virtual void drawRectFilled(int x1, int y1, int x2, int y2) = 0;
42 virtual void newLine(int lineHeight) = 0;
43 virtual int getPixel(int x, int y) = 0;
44 virtual int print(const char *p, int lineHeight, bool allChars=false);
45 virtual bool setGraphicsRendition(const char c, int escValue, int lineHeight) = 0;
46 virtual void setPixel(int x, int y, int c) = 0;
47 virtual void reset(int fontSize);
48 virtual void resize(int newWidth, int newHeight, int oldWidth,
49 int oldHeight, int lineHeight) = 0;
50 virtual void updateFont(int size=-1) = 0;
51 virtual int getMaxHScroll() = 0;
52
53 void add(Shape *button);
54 void addImage(ImageDisplay &image);
55 int ansiToMosync(long c);
56 void drawLabel();
57 void drawMenu();
58 void drawShape(Shape *button);
59 void drawOverlay(bool vscroll);
60 int getIndex(FormInput *input) const;
61 FormInput *getMenu(FormInput *prev, int px, int py);
62 FormInput *getNextMenu(FormInput *prev, bool up);
63 FormInput *getNextField(FormInput *field);
64 void getScroll(int &x, int &y) { x = _scrollX; y = _scrollY; }
65 void layoutInputs(int newWidth, int newHeight);
66 bool overLabel(int px, int py);
67 bool overMenu(int px, int py);
68 bool overlaps(int px, int py);
69 void remove(Shape *button);
70 void removeImage(unsigned imageId);
71 bool removeInput(FormInput *input);
72 void removeInputs() { _inputs.removeAll(); }
73 void replaceFont(int type = FONT_TYPE_MONOSPACE);
74 void resetScroll() { _scrollX = 0; _scrollY = 0; }
75 void setColor(long color);
76 void setDirty() { if (!_dirty) { _dirty = maGetMilliSecondCount(); } }
77 void setFont(bool bold, bool italic, int size);
78 void selectFont() { if (_font != -1) maFontSetCurrent(_font); }
79 void setScroll(int x, int y) { _scrollX = x; _scrollY = y; }
80 void setTextColor(long fg, long bg);
81 void updateInputs(var_p_t form, bool setVars);
82
83 MAHandle _font;
84 int _fontSize;
85 int _fontStyle;
86 int _charWidth;
87 int _charHeight;
88 int _scrollX;
89 int _scrollY;
90 int _bg, _fg;
91 int _curX;
92 int _curY;
93 int _dirty;
94 int _linePadding;
95 String _label;
96 strlib::List<Shape *> _shapes;
97 strlib::List<FormInput *> _inputs;
98 strlib::List<ImageDisplay *> _images;
99};
100
101struct GraphicScreen : public Screen {
102 GraphicScreen(int width, int height, int fontSize);
103 virtual ~GraphicScreen();
104
105 void calcTab();
106 bool construct();
107 void clear();
108 void drawArc(int xc, int yc, double r, double start, double end, double aspect);
109 void drawBase(bool vscroll, bool update=true);
110 void drawEllipse(int xc, int yc, int rx, int ry, int fill);
111 void drawImage(ImageDisplay &image);
112 void drawInto(bool background=false);
113 void drawLine(int x1, int y1, int x2, int y2);
114 void drawRect(int x1, int y1, int x2, int y2);
115 void drawRectFilled(int x1, int y1, int x2, int y2);
116 int getPixel(int x, int y);
117 void imageScroll();
118 void imageAppend(MAHandle newImage);
119 void newLine(int lineHeight);
120 int print(const char *p, int lineHeight, bool allChars=false);
121 void reset(int fontSize);
122 bool setGraphicsRendition(const char c, int escValue, int lineHeight);
123 void setPixel(int x, int y, int c);
124 void resize(int newWidth, int newHeight, int oldWidth,
125 int oldHeight, int lineHeight);
126 void updateFont(int size);
127 int getMaxHScroll() { return 0; }
128
129 MAHandle _image;
130 bool _underline;
131 bool _invert;
132 bool _bold;
133 bool _italic;
134 int _imageWidth;
135 int _imageHeight;
136 int _curYSaved;
137 int _curXSaved;
138 int _tabSize;
139};
140
141struct TextSeg {
142 enum {
143 BOLD = 0x00000001,
144 ITALIC = 0x00000002,
145 UNDERLINE = 0x00000004,
146 INVERT = 0x00000008,
147 RESET = 0x00000010,
148 };
149
150 // create a new segment
151 TextSeg() :
152 _str(0),
153 _flags(0),
154 _color(NO_COLOR),
155 _next(0) {}
156
157 ~TextSeg() {
158 if (_str) {
159 delete[]_str;
160 }
161 }
162
163 // sets the reset flag
164 void reset() {
165 set(RESET, true);
166 }
167
168 // returns whether the reset flag is set
169 bool isReset() const {
170 return set(RESET);
171 }
172
173 void setText(const char *str, int n) {
174 if ((!str || !n)) {
175 this->_str = 0;
176 } else {
177 this->_str = new char[n + 1];
178 strncpy(this->_str, str, n);
179 this->_str[n] = 0;
180 }
181 }
182
183 // create a string of n spaces
184 void tab(int n) {
185 this->_str = new char[n + 1];
186 memset(this->_str, ' ', n);
187 this->_str[n] = 0;
188 }
189
190 // set the flag value
191 void set(int f, bool value) {
192 if (value) {
193 _flags |= f;
194 } else {
195 _flags &= ~f;
196 }
197 _flags |= (f << 16);
198 }
199
200 // return whether the flag was set (to true or false)
201 bool set(int f) const {
202 return (_flags & (f << 16));
203 }
204
205 // return the flag value if set, otherwise return value
206 bool get(int f, bool *value) const {
207 bool result = *value;
208 if (_flags & (f << 16)) {
209 result = (_flags & f);
210 }
211 return result;
212 }
213
214 // width of this segment in pixels
215 int width() const {
216 MAExtent textSize = maGetTextSize(_str);
217 return EXTENT_X(textSize);
218 }
219
220 // number of chars in this segment
221 int numChars() const {
222 return !_str ? 0 : strlen(_str);
223 }
224
225 // update font and state variables when set in this segment
226 bool escape(bool *bold, bool *italic, bool *underline, bool *invert) {
227 *bold = get(BOLD, bold);
228 *italic = get(ITALIC, italic);
229 *underline = get(UNDERLINE, underline);
230 *invert = get(INVERT, invert);
231 return set(BOLD) || set(ITALIC);
232 }
233
234 char *_str;
235 int _flags;
236 int _color;
237 TextSeg *_next;
238};
239
240struct Row {
241 Row() : _head(0) {}
242 ~Row() {
243 clear();
244 }
245
246 // append a segment to this row
247 void append(TextSeg *node) {
248 if (!_head) {
249 _head = node;
250 } else {
251 tail(_head)->_next = node;
252 }
253 node->_next = 0;
254 }
255
256 // clear the contents of this row
257 void clear() {
258 remove(_head);
259 _head = 0;
260 }
261
262 TextSeg *next() {
263 TextSeg *result = _head;
264 if (!result) {
265 result = new TextSeg();
266 append(result);
267 }
268 return result;
269 }
270
271 // number of characters in this row
272 int numChars() const {
273 return numChars(this->_head);
274 }
275
276 int numChars(TextSeg *next) const {
277 int n = 0;
278 if (next) {
279 n = next->numChars() + numChars(next->_next);
280 }
281 return n;
282 }
283
284 void remove(TextSeg *next) {
285 if (next) {
286 remove(next->_next);
287 delete next;
288 }
289 }
290
291 // move to the tab position
292 void tab() {
293 int tabSize = 6;
294 int num = numChars(this->_head);
295 int pos = tabSize - (num % tabSize);
296 if (pos) {
297 TextSeg *next = new TextSeg();
298 next->tab(pos);
299 append(next);
300 }
301 }
302
303 TextSeg *tail(TextSeg *next) {
304 return !next->_next ? next : tail(next->_next);
305 }
306
307 int width() const {
308 return width(this->_head);
309 }
310
311 int width(TextSeg *next) const {
312 int n = 0;
313 if (next) {
314 n = next->width() + width(next->_next);
315 }
316 return n;
317 }
318
319 TextSeg *_head;
320};
321
322struct TextScreen : public Screen {
323 TextScreen(int width, int height, int fontSize);
324 virtual ~TextScreen();
325
326 void calcTab();
327 bool construct();
328 void clear();
329 void drawArc(int xc, int yc, double r, double start, double end, double aspect) {}
330 void drawBase(bool vscroll, bool update=true);
331 void drawImage(ImageDisplay &image) {}
332 void drawEllipse(int xc, int yc, int rx, int ry, int fill) {}
333 void drawLine(int x1, int y1, int x2, int y2);
334 void drawText(const char *text, int len, int x, int lineHeight);
335 void drawRect(int x1, int y1, int x2, int y2);
336 void drawRectFilled(int x1, int y1, int x2, int y2);
337 int getPixel(int x, int y) { return 0; }
338 void inset(int x, int y, int w, int h, Screen *over);
339 void newLine(int lineHeight);
340 int print(const char *p, int lineHeight, bool allChars=false);
341 void resize(int newWidth, int newHeight, int oldWidth,
342 int oldHeight, int lineHeight);
343 bool setGraphicsRendition(const char c, int escValue, int lineHeight);
344 void setOver(Screen *over) { _over = over; }
345 void setPixel(int x, int y, int c) {}
346 void updateFont(int size) {}
347 int getMaxHScroll() { return (_cols * _charWidth) - w(); }
348
349private:
350 Row *getLine(int ndx);
351
352 // returns the number of display text rows held in the buffer
353 int getTextRows() {
354 return 1 + ((_head >= _tail) ? (_head - _tail) : _head + (_rows - _tail));
355 }
356
357 // returns the number of rows available for display
358 int getPageRows() {
359 return (_height - 1) / _charHeight;
360 }
361
362 Screen *_over; // inset over screen
363 Shape _inset; // relative screen size
364 Row *_buffer; // buffer management
365 int _head; // current head of buffer
366 int _tail; // buffer last line
367 int _rows; // total number of rows - size of buffer
368 int _cols; // maximum number of characters in a row
369};
370
371#endif
372