-
Notifications
You must be signed in to change notification settings - Fork 1
/
ctext.h
515 lines (457 loc) · 13.6 KB
/
ctext.h
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
#ifndef _WIN32
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <ncurses.h>
#include <stdint.h>
#ifndef __83a9222a_c8b9_4f36_9721_5dfbaccb28d0_CTEXT
#define __83a9222a_c8b9_4f36_9721_5dfbaccb28d0_CTEXT
#define CTEXT_BUFFER_SIZE (4096)
using namespace std;
class ctext;
struct ctext_config_struct
{
//
// This specifies how many lines are kept
// in the ring-buffer.
//
// A value of -1 means to keep it completely
// unregulated.
//
int32_t m_buffer_size;
#define CTEXT_DEFAULT_BUFFER_SIZE 500
//
// The bounding box bool specifies whether
// we are allowed to move outside where the
// content exists. Pretend there's the
// following content and window (signified
// by the + marks)
//
// + +
// xxxx
// xxx
// xxxxx
// + +
//
// If we were to move say, 3 units right and
// had no bounding box (false) you'd see this:
//
// + +
// x
//
// xx
// + +
//
// In other words, we could potentially scroll
// well beyond our content.
//
// A bounding box set to true would prevent this,
// making sure that the viewport doesn't extend
// beyond the existing content.
//
bool m_bounding_box;
#define CTEXT_DEFAULT_BOUNDING_BOX false
//
// Sometimes content can be extremely lengthy
// on one line, overwhelming any other content
// in view, losing the context of what the content
// means.
//
// In these cases, we can truncate long text from
// occupying the next row of text, and instead extend
// beyond the viewport of our window. Under these cases
// the user will have to scroll the viewport in order
// to see the remainder of the text.
//
bool m_do_wrap;
#define CTEXT_DEFAULT_DO_WRAP false
//
// In most user interfaces, new text appears
// underneath previous text on a new line.
//
// However, sometimes it's more natural to see
// new entries come in ON TOP of old ones, pushing
// the old ones downward.
//
// m_append_top deals with this duality
//
bool m_append_top;
#define CTEXT_DEFAULT_APPEND_TOP false
//
// Sometimes seeing new content is of the utmost
// importance and takes precendence over analysis
// of any historical data.
//
// In that case, the scroll_on_append will forcefully
// scroll the text so that the new content is
// visible.
//
bool m_scroll_on_append;
#define CTEXT_DEFAULT_SCROLL_ON_APPEND false
//
// The auto_newline boolean will specify whether
// a newline is appended at the end of every printf
// call automatically for you ... as opposed to
// the more traditional printf where it is not.
//
// Our definition of newline is unixes, that is
// the single character of 0x0A, or \n.
//
bool m_auto_newline;
#define CTEXT_DEFAULT_AUTO_NEWLINE false
};
typedef struct ctext_config_struct ctext_config;
typedef struct ctext_format_struct
{
int32_t offset;
attr_t attrs;
int16_t color_pair;
} ctext_format;
typedef struct ctext_pos_struct
{
int32_t x;
int32_t y;
} ctext_pos;
typedef struct ctext_search_struct
{
// The current position of the
// search. ... you could do
//
// ct.get_offset(&search.pos);
//
// in order to initialize it to
// the current point.
//
ctext_pos pos;
// Should we wrap around when
// we are done.
bool do_wrap;
// True if we are searching forward
// false if we aren't.
bool is_forward;
// Case insensitivity is defined in the
// classic (c >= 'A' ? c | 0x20) manner.
bool is_case_insensitive;
// This is used internally,
// please don't modify.
ctext_pos _start_pos;
ctext_pos _last_match;
uint64_t _last_event;
int16_t _match_count;
// The string to match
string _query;
} ctext_search;
typedef struct ctext_row_struct
{
string data;
vector<ctext_format> format;
} ctext_row;
typedef vector<ctext_row> ctext_buffer;
class ctext
{
public:
ctext(WINDOW *win = 0, ctext_config *config = 0);
//
// A ctext instance has a configuration specified through
// the ctext_config structure above
//
// When this function is called, a copy of the structure
// is made so that further modifications are not reflected
// in a previously instantiated instance.
//
// Returns 0 on success
//
int8_t set_config(ctext_config *config);
//
// get_config allows you to change a parameter in the
// configuration of a ctext instance and to duplicate
// an existing configuration in a new instance.
//
// Returns 0 on success
//
int8_t get_config(ctext_config *config);
//
// At most 1 curses window may be attached at a time.
//
// This function specifies the curses window which
// will be attached given this instance.
//
// If one is already attached, it will be detached and
// potentially orphaned.
//
// Returns 0 on success
//
int8_t attach_curses_window(WINDOW *win);
//
// Under normal circumstances, a user would like to
// remove all the existing content with a clear, starting
// anew.
//
// However, if you'd like to only remove part of the content,
// then you can pass a row_count in and clear will truncate
// row_count units of the oldest content.
//
// The return code is how many rows were cleared from the
// buffer.
//
int32_t clear(int32_t row_count = -1);
//
// Scroll_to when appending to the bottom in the traditional
// default sense, will specify the top x and y coordinate
// of the viewport.
//
// However, if we are appending to the top, then since new
// content goes above the previous one, scroll_to specifies
// the lower left coordinate.
//
// Returns 0 on success
//
int8_t scroll_to(int32_t x, int32_t y);
int8_t scroll_to(ctext_pos *pos);
// get_offset returns the current coordinates of the view port.
// The values from get_offset are complementary to those
// of scroll_to
//
// Returns 0 on success
//
int8_t get_offset(int32_t*x, int32_t*y);
int8_t get_offset(ctext_pos *pos);
//
// get_offset_percent is a courtesy function returning
// a percentage value corresponding to the Y amount of
// scroll within the window.
//
// Returns 0 on success
//
int8_t get_offset_percent(float*percent);
//
// get_buf_size returns the number of rows of content
// for y in the current buffer.
//
// Returns 0 on success
//
int8_t get_buf_size(int32_t*buf_size);
//
// available_rows communicates how many rows
// are left given the buffer size specified
// in the config with respect to the amount
// of content placed in the buffer.
//
// If that sounds overly complex, I assure
// you this function does pretty much exactly
// what you'd expect ... it tells you how
// much space you have left in the buffer
// before its full and starts dropping
// content.
//
// Returns number of aviailable rows
//
int32_t available_rows();
//
// Each of the directional functions,
// up, down, left, and right, can be
// called without an argument to move
// 1 unit in their respective direction.
//
// The return code is how far the movement
// happened.
//
int32_t up(int32_t amount = 1);
int32_t down(int32_t amount = 1);
int32_t left(int32_t amount = 1);
int32_t right(int32_t amount = 1);
//
// Identical to the above functions but this
// time by an entire page of content (that
// is to say, the height of the current curses
// window.)
//
int32_t page_up(int32_t page_count = 1);
int32_t page_down(int32_t page_count = 1);
//
// The jump_to_first_line and jump_to_last_line
// can conveniently be mapped to home/end keys
// and do what they say under the following
// condition:
//
// If the bounding_box is set to true,
// then the "first" and "last" line corresponds
// to an entire screen full of data.
//
// If the bounding box is set to false, then
// the screen will be empty except for 1 line
// corresponding to the first or last line.
//
// That is to say that with a bounding box off,
// you'd see something like
//
// + +
//
//
// xxxxx
// + +
//
// when we are doing jump_to_first_line.
//
// With a bounding_box on you'd see
//
// + +
// xxxxx
// xx
// xxx
// + +
//
// The return code is how many vertical lines
// were scrolled in order to accomplish the
// action.
//
int32_t jump_to_first_line();
int32_t jump_to_last_line();
//
// printf is identical to printf(3) and can be called
// from the function at the end of this file, cprintf,
// with an instance variable. It places text into the
// buffer specified.
//
// You can take the function pointer of printf from
// an existing application and point it to this printf
// inside of an instance in order to migrate an existing
// application to this library seamlessly.
//
int8_t printf(const char*format, ...);
int8_t vprintf(const char*format, va_list ap = 0);
//
// nprintf is identical to the printf above EXCEPT for
// the fact that it doesn't refresh (redraw) the screen.
//
// In order to do that, a redraw (below) must be called
// manually.
//
int8_t nprintf(const char*format, ...);
//
// Under normal (printf) conditions, this does not
// need to be called explicitly and is instead called
// each time a printf is called.
//
int8_t redraw();
//
// A naming convention inspired from php's ob_start,
// this function stops refreshing the screen until
// ob_end is called, upon which a refresh is done.
//
// Internally, a binary flag is flipped. That is
// to say that multiple ob_start calls will only
// set the flag to TRUE, all to be undone by a single
// ob_end call.
//
// Returns 0 if the call was meaningful (that is,
// it toggled state) - otherwise -1.
//
int8_t ob_start();
int8_t ob_end();
//
// This highlights a search context given a mask.
// A few big mask optiosn are A_REVERSE, A_UNDERLINE,
// A_BLINK, and A_BOLD. They can be binary ORed.
//
int8_t highlight(ctext_search *context = 0, int32_t mask = A_REVERSE);
//
// This is how you initialize a search.
//
// You are free to toggle the properties of the object
// at your own pleasure or peril.
//
// Returns you_manage_this_memory back at you or NULL
// on an error.
//
ctext_search *new_search(ctext_search *you_manage_this_memory, string to_search, bool is_case_insensitive = false, bool is_forward = true, bool do_wrap = false);
//
// If you want to modify the query of an existing search then you
// should call this function directly instead of trying to modify
// the parameter yourself.
//
// Returns 0 on success
//
int8_t set_query(ctext_search *p_search, string new_query);
//
// After you've initiated your search you can then go over
// the body of text by re-executing the str_search function.
//
// You don't have to worry about incrementing any silly variables
// to avoid an infinite loop on the previous match or any of those
// annoyances that the base c/c++ libraries decided to make YOUR
// problem every time.
//
// This function will go to the "next" match (based on your parameters)
// and then highlight all the matches in the viewport. You can
// "turn off" this highlighting by running search_off (see below).
//
// Returns 0 every time a valid search is found and something
// "happened". Otherwise you get something non-zero, signifying that
// the search is "done".
//
int8_t str_search(ctext_search *to_search);
// Turn off syntax highlighting from search.
int8_t search_off();
private:
//
// This function answers the question "where on the screen would
// the buffer at line X, character Y appear?" The *win gets populated
// with the answer or a value is returned if there's an overflow.
//
int8_t map_to_win(int32_t buffer_x, int32_t buffer_y, ctext_pos *win);
int8_t y_scroll_calculate(int32_t amount, ctext_pos *pos);
int16_t redraw_partial(int32_t buf_start_x, int32_t buf_start_y, int32_t buf_end_x, int32_t buf_end_y);
int16_t redraw_partial(ctext_pos *pos, size_t len);
// This is just a test function to make sure everything works.
int8_t redraw_partial_test();
ctext_row* add_row();
void add_format_if_needed();
int8_t rebuf();
void get_win_size();
// Highlights the matches in he current vieport without
// doing any scrolling.
int8_t highlight_matches(ctext_search *context = 0);
//
// Directly scroll to an x/y location with respect to
// the buffer without any redraw or other calculation.
//
// This just moves the internal pointers forward with
// respect to the internal configuration.
//
// The return value is 0 iff the value of the scroll
// was changed. Otherwise, if nothing changed in the
// request, -1 is returned.
//
int8_t direct_scroll(int32_t x, int32_t y);
int8_t direct_scroll(ctext_pos *pos);
// A mast to apply to the text being rendered.
attr_t m_attr_mask;
//
// Leave the new_pos_out as null for an idempotent version of this function -
// as in one that doesn't modify the to_search_in variable in returning a value.
//
// It's perfectly acceptable to pass the same variable as both to_search_in and
// new_pos_out if you want to execute it with a side-effect - as much of the
// implementation actually does.
//
int8_t str_search_single(ctext_search *to_search_in, ctext_search *new_pos_out = 0, ctext_pos *limit = 0);
// Whether or not to draw when new text comes in or to skip the step.
bool m_do_draw;
WINDOW *m_win;
ctext_config m_config;
ctext_buffer m_buffer;
ctext_search *m_last_search;
// The start point of the buffer with
// respect to the current viewport
ctext_pos m_pos_start;
int32_t m_max_y;
int32_t m_win_width;
int32_t m_win_height;
uint64_t m_event_counter;
ofstream *m_debug;
};
int cprintf(ctext*win, const char *format, ...);
#endif
#endif // _WIN32